From b10787d23ca645932e89383ebb39402d1eb84700 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 29 Jan 2018 10:47:26 +0300
Subject: [PATCH 1/5] first ver

---
 src/components/attachment/attachment.js    |  4 ++
 src/components/attachment/attachment.vue   |  2 +-
 src/components/still-image/still-image.js  | 29 ++++++++++++
 src/components/still-image/still-image.vue | 51 ++++++++++++++++++++++
 4 files changed, 85 insertions(+), 1 deletion(-)
 create mode 100644 src/components/still-image/still-image.js
 create mode 100644 src/components/still-image/still-image.vue

diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js
index 8a2a3826..cd72e571 100644
--- a/src/components/attachment/attachment.js
+++ b/src/components/attachment/attachment.js
@@ -1,3 +1,4 @@
+import StillImage from '../still-image/still-image.vue'
 import nsfwImage from '../../assets/nsfw.png'
 import fileTypeService from '../../services/file_type/file_type.service.js'
 
@@ -16,6 +17,9 @@ const Attachment = {
       img: document.createElement('img')
     }
   },
+  components: {
+    StillImage
+  },
   computed: {
     type () {
       return fileTypeService.fileType(this.attachment.mimetype)
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
index d6a51ffd..2810e205 100644
--- a/src/components/attachment/attachment.vue
+++ b/src/components/attachment/attachment.vue
@@ -8,7 +8,7 @@
     </div>
 
     <a v-if="type === 'image' && !hidden" class="image-attachment" :href="attachment.url" target="_blank">
-      <img class="base03-border" referrerpolicy="no-referrer" :src="attachment.large_thumb_url || attachment.url"/>
+      <StillImage class="base03-border" referrerpolicy="no-referrer" :mimetype="attachment.mimetype" :src="attachment.large_thumb_url || attachment.url"/>
     </a>
 
     <video class="base03" v-if="type === 'video' && !hidden" :src="attachment.url" controls loop></video>
diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
new file mode 100644
index 00000000..fa027bc4
--- /dev/null
+++ b/src/components/still-image/still-image.js
@@ -0,0 +1,29 @@
+import fileTypeService from '../../services/file_type/file_type.service.js'
+
+const StillImage = {
+  props: [
+    'src',
+    'referrerpolicy',
+    'mimetype'
+  ],
+  data () {
+    return {
+      hideNsfwLocal: this.$store.state.config.hideNsfw,
+    }
+  },
+  computed: {
+    animated () {
+      return this.mimetype === 'image/gif'
+    }
+  },
+  methods: {
+    drawCanvas() {
+      const canvas = this.$refs.canvas
+      if (!canvas) return
+      const ctx = canvas.getContext('2d')
+      ctx.drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
+    }
+  }
+}
+
+export default StillImage
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
new file mode 100644
index 00000000..fa086e51
--- /dev/null
+++ b/src/components/still-image/still-image.vue
@@ -0,0 +1,51 @@
+<template>
+  <div class='still-image' :class='{ animated: animated }' >
+    <canvas ref="canvas" v-if="animated"></canvas>
+    <img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="drawCanvas"/>
+  </div>
+</template>
+
+<script src="./still-image.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+.still-image {
+    position: relative;
+    
+    &:hover canvas {
+        display: none;
+    }
+    
+    &.animated {
+        &:hover::before,
+        img {
+            visibility: hidden
+        }
+        
+        &:hover img {
+            visibility: visible
+        }
+
+        &::before {
+            content: 'gif';
+            position: absolute;
+            top: 5px;
+            left: 5px;
+            background: rgba(255,255,255,.5);
+            display: block;
+            padding: 2px;
+            z-index: 2;
+        }
+    }
+
+    canvas {
+        position: absolute;
+        top: 0;
+        bottom: 0;
+        left: 0;
+        right: 0;
+        width: 100%;
+        height: 100%;
+    }
+}
+</style>

From 3257991f4196cb6c2c77b3f81ec9f1850e243211 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sat, 3 Feb 2018 19:55:45 +0300
Subject: [PATCH 2/5] unfinished fetch() version that doesn't work

---
 src/components/attachment/attachment.vue   |  1 -
 src/components/status/status.js            |  4 +++-
 src/components/status/status.vue           | 26 +++++++++++++++++++---
 src/components/still-image/still-image.js  | 21 ++++++++++++-----
 src/components/still-image/still-image.vue |  5 +++--
 5 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
index 2810e205..4ee5153b 100644
--- a/src/components/attachment/attachment.vue
+++ b/src/components/attachment/attachment.vue
@@ -127,7 +127,6 @@
               flex: 1;
 
               img {
-                  object-fit: contain;
                   width: 100%;
                   height: 100%; /* If this isn't here, chrome will stretch the images */
                   max-height: 500px;
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 12f3bb25..7397e80c 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -4,6 +4,7 @@ import RetweetButton from '../retweet_button/retweet_button.vue'
 import DeleteButton from '../delete_button/delete_button.vue'
 import PostStatusForm from '../post_status_form/post_status_form.vue'
 import UserCardContent from '../user_card_content/user_card_content.vue'
+import StillImage from '../still-image/still-image.vue'
 import { filter, find } from 'lodash'
 
 const Status = {
@@ -76,7 +77,8 @@ const Status = {
     RetweetButton,
     DeleteButton,
     PostStatusForm,
-    UserCardContent
+    UserCardContent,
+    StillImage
   },
   methods: {
     linkClicked ({target}) {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 28272b0b..999adb21 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -34,7 +34,7 @@
       <div class="media status container">
         <div class="media-left">
           <a :href="status.user.statusnet_profile_url">
-            <img @click.prevent="toggleUserExpanded" :class="{retweeted: retweet}" class='avatar' :src="status.user.profile_image_url_original">
+            <StillImage @click.native.prevent="toggleUserExpanded" :class="{retweeted: retweet}" class='avatar' :src="status.user.profile_image_url_original"/>
             <img v-if="retweet" class='avatar-retweeter' :src="statusoid.user.profile_image_url_original"></img>
           </a>
         </div>
@@ -84,7 +84,7 @@
             </div>
 
             <div class="status-preview base00-background base03-border" v-if="showPreview && preview">
-              <img class="avatar" :src="preview.user.profile_image_url_original">
+              <StillImage class="avatar" :src="preview.user.profile_image_url_original"/>
               <div class="text">
                 <h4>
                   {{ preview.user.name }}
@@ -146,6 +146,7 @@
     box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
     margin-top: 0.5em;
     margin-left: 1em;
+    z-index: 50;
 
     .avatar {
       flex-shrink: 0;
@@ -266,7 +267,6 @@
         margin: 0.2em 0.3em 0 0;
         img {
           float: right;
-          border-radius: 5px;
         }
      }
 
@@ -330,6 +330,17 @@
  .status .avatar {
    width: 48px;
    height: 48px;
+   border-radius: 5px;
+   overflow: hidden;
+
+   img {
+       width: 100%;
+       height: 100%;
+   }
+
+   &.animated::before {
+       display: none;
+   }
 
    &.retweeted {
      width: 40px;
@@ -339,6 +350,15 @@
    }
  }
 
+ .status:hover .animated.avatar {
+     canvas {
+         display: none;
+     }
+     img {
+         visibility: visible;
+     }
+ }
+
  .status img.avatar-retweeter {
    width: 24px;
    height: 24px;
diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
index fa027bc4..e674b932 100644
--- a/src/components/still-image/still-image.js
+++ b/src/components/still-image/still-image.js
@@ -12,16 +12,27 @@ const StillImage = {
     }
   },
   computed: {
-    animated () {
-      return this.mimetype === 'image/gif'
+    animated: {
+      get () {
+        // If mimetype is gif then it is certainly animated, if it's undefined - we don't know YET
+        return this.mimetype === 'image/gif' ? true : this.mimetype == null ? 'maybe' : false
+      },
+      set (val) {
+        this.mimetype = val
+      }
     }
   },
   methods: {
-    drawCanvas() {
+    onLoad () {
       const canvas = this.$refs.canvas
       if (!canvas) return
-      const ctx = canvas.getContext('2d')
-      ctx.drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
+      canvas.getContext('2d').drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
+      if (this.animated === 'maybe') {
+        fetch(this.src).then((data) => {
+          console.log(data)
+          this.animated = data.type
+        })
+      }
     }
   }
 }
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
index fa086e51..cc426fff 100644
--- a/src/components/still-image/still-image.vue
+++ b/src/components/still-image/still-image.vue
@@ -1,7 +1,7 @@
 <template>
   <div class='still-image' :class='{ animated: animated }' >
     <canvas ref="canvas" v-if="animated"></canvas>
-    <img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="drawCanvas"/>
+    <img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad"/>
   </div>
 </template>
 
@@ -31,9 +31,10 @@
             position: absolute;
             top: 5px;
             left: 5px;
-            background: rgba(255,255,255,.5);
+            background: rgba(127,127,127,.7);
             display: block;
             padding: 2px;
+            border-radius: 3px;
             z-index: 2;
         }
     }

From 55bc1a3414ac15b08554a43c00f7f631ca1d304a Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sat, 3 Feb 2018 20:32:13 +0300
Subject: [PATCH 3/5] fixed stretched spurdo in notifications, misc fixes,
 detect gif by extension for now

---
 src/components/attachment/attachment.vue        |  6 ++++++
 src/components/notifications/notifications.scss |  4 ++++
 src/components/still-image/still-image.js       | 16 ++--------------
 src/components/still-image/still-image.vue      |  1 +
 4 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue
index 4ee5153b..a1b35d91 100644
--- a/src/components/attachment/attachment.vue
+++ b/src/components/attachment/attachment.vue
@@ -126,7 +126,13 @@
               display: flex;
               flex: 1;
 
+              .still-image {
+                  width: 100%;
+                  height: 100%;
+              }
+
               img {
+                  object-fit: contain;
                   width: 100%;
                   height: 100%; /* If this isn't here, chrome will stretch the images */
                   max-height: 500px;
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 241f10b4..4fda255b 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -104,6 +104,10 @@
     max-height: 12em;
     overflow-y: hidden;
     //text-overflow: ellipsis;
+
+    img {
+        object-fit: contain;
+    }
   }
 
   .notification-gradient {
diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
index e674b932..595652f2 100644
--- a/src/components/still-image/still-image.js
+++ b/src/components/still-image/still-image.js
@@ -12,14 +12,8 @@ const StillImage = {
     }
   },
   computed: {
-    animated: {
-      get () {
-        // If mimetype is gif then it is certainly animated, if it's undefined - we don't know YET
-        return this.mimetype === 'image/gif' ? true : this.mimetype == null ? 'maybe' : false
-      },
-      set (val) {
-        this.mimetype = val
-      }
+    animated () {
+      return this.mimetype === 'image/gif' || this.src.endsWith('.gif')
     }
   },
   methods: {
@@ -27,12 +21,6 @@ const StillImage = {
       const canvas = this.$refs.canvas
       if (!canvas) return
       canvas.getContext('2d').drawImage(this.$refs.src, 1, 1, canvas.width, canvas.height)
-      if (this.animated === 'maybe') {
-        fetch(this.src).then((data) => {
-          console.log(data)
-          this.animated = data.type
-        })
-      }
     }
   }
 }
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
index cc426fff..b141cdaf 100644
--- a/src/components/still-image/still-image.vue
+++ b/src/components/still-image/still-image.vue
@@ -11,6 +11,7 @@
 @import '../../_variables.scss';
 .still-image {
     position: relative;
+    line-height: 0;
     
     &:hover canvas {
         display: none;

From 5efd8a4aa6cd4deca287781be24083fc468c563a Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Sat, 3 Feb 2018 20:37:27 +0300
Subject: [PATCH 4/5] fixes

---
 src/components/still-image/still-image.js  | 7 -------
 src/components/still-image/still-image.vue | 7 +++++--
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
index 595652f2..f0b25265 100644
--- a/src/components/still-image/still-image.js
+++ b/src/components/still-image/still-image.js
@@ -1,16 +1,9 @@
-import fileTypeService from '../../services/file_type/file_type.service.js'
-
 const StillImage = {
   props: [
     'src',
     'referrerpolicy',
     'mimetype'
   ],
-  data () {
-    return {
-      hideNsfwLocal: this.$store.state.config.hideNsfw,
-    }
-  },
   computed: {
     animated () {
       return this.mimetype === 'image/gif' || this.src.endsWith('.gif')
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
index b141cdaf..91d7f77a 100644
--- a/src/components/still-image/still-image.vue
+++ b/src/components/still-image/still-image.vue
@@ -30,11 +30,14 @@
         &::before {
             content: 'gif';
             position: absolute;
+            line-height: 10px;
+            font-size: 10px;
             top: 5px;
             left: 5px;
-            background: rgba(127,127,127,.7);
+            background: rgba(127,127,127,.5);
+            color: #FFF;
             display: block;
-            padding: 2px;
+            padding: 2px 4px;
             border-radius: 3px;
             z-index: 2;
         }

From 0c4dc26808c3bb7508bf9005f3c3430f1c7e2039 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 12 Mar 2018 02:31:33 +0300
Subject: [PATCH 5/5] after nine years of development, hopefully, it has been
 worth the weight

---
 src/components/notifications/notifications.js  |  3 ++-
 .../notifications/notifications.scss           | 18 +++++++++++++++++-
 src/components/notifications/notifications.vue |  2 +-
 src/components/settings/settings.js            |  6 +++++-
 src/components/settings/settings.vue           |  8 ++++++--
 src/components/status/status.vue               |  8 ++++----
 src/components/still-image/still-image.js      |  7 ++++++-
 src/components/still-image/still-image.vue     | 14 ++++++++++----
 .../user_card_content/user_card_content.js     |  4 ++++
 .../user_card_content/user_card_content.vue    | 17 +++++++++++++++--
 src/i18n/messages.js                           |  2 ++
 11 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/src/components/notifications/notifications.js b/src/components/notifications/notifications.js
index 5f0d7f26..e9b83bf0 100644
--- a/src/components/notifications/notifications.js
+++ b/src/components/notifications/notifications.js
@@ -1,4 +1,5 @@
 import Status from '../status/status.vue'
+import StillImage from '../still-image/still-image.vue'
 
 import { sortBy, take, filter } from 'lodash'
 
@@ -31,7 +32,7 @@ const Notifications = {
     }
   },
   components: {
-    Status
+    Status, StillImage
   },
   watch: {
     unseenCount (count) {
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 4fda255b..3c500b36 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -88,10 +88,26 @@
     }
 
     .avatar {
-      padding-top: 0.3em;
+      margin-top: 0.3em;
       width: 32px;
       height: 32px;
       border-radius: 50%;
+      overflow: hidden;
+      line-height: 0;
+
+      &.animated::before {
+        display: none;
+      }
+
+    }
+
+    &:hover .animated.avatar {
+      canvas {
+        display: none;
+      }
+      img {
+        visibility: visible;
+      }
     }
 
     &:last-child {
diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue
index b341fcef..8e6f12b2 100644
--- a/src/components/notifications/notifications.vue
+++ b/src/components/notifications/notifications.vue
@@ -10,7 +10,7 @@
         <div v-for="notification in visibleNotifications" :key="notification" class="notification" :class='{"unseen": !notification.seen}'>
           <div>
             <a :href="notification.action.user.statusnet_profile_url" target="_blank">
-              <img class='avatar' :src="notification.action.user.profile_image_url_original">
+              <StillImage class='avatar' :src="notification.action.user.profile_image_url_original"/>
             </a>
           </div>
           <div class='text' style="width: 100%;">
diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index b88937bb..a26111d6 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -10,7 +10,8 @@ const settings = {
       muteWordsString: this.$store.state.config.muteWords.join('\n'),
       autoLoadLocal: this.$store.state.config.autoLoad,
       streamingLocal: this.$store.state.config.streaming,
-      hoverPreviewLocal: this.$store.state.config.hoverPreview
+      hoverPreviewLocal: this.$store.state.config.hoverPreview,
+      stopGifs: this.$store.state.config.stopGifs
     }
   },
   components: {
@@ -43,6 +44,9 @@ const settings = {
     muteWordsString (value) {
       value = filter(value.split('\n'), (word) => trim(word).length > 0)
       this.$store.dispatch('setOption', { name: 'muteWords', value })
+    },
+    stopGifs (value) {
+      this.$store.dispatch('setOption', { name: 'stopGifs', value })
     }
   }
 }
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 8fdd09de..5aa7596a 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -29,8 +29,8 @@
                 <label for="hideNsfw">{{$t('settings.nsfw_clickthrough')}}</label>
             </li>
             <li>
-                <input type="checkbox" id="autoLoad" v-model="autoLoadLocal">
-                <label for="autoLoad">{{$t('settings.autoload')}}</label>
+                <input type="checkbox" id="autoload" v-model="autoloadlocal">
+                <label for="autoload">{{$t('settings.autoload')}}</label>
             </li>
             <li>
                 <input type="checkbox" id="streaming" v-model="streamingLocal">
@@ -40,6 +40,10 @@
                 <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
                 <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
             </li>
+            <li>
+                <input type="checkbox" id="stopGifs" v-model="stopGifs">
+                <label for="stopGifs">{{$t('settings.stop_gifs')}}</label>
+            </li>
         </ul>
       </div>
     </div>
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 999adb21..d451b67c 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -35,7 +35,7 @@
         <div class="media-left">
           <a :href="status.user.statusnet_profile_url">
             <StillImage @click.native.prevent="toggleUserExpanded" :class="{retweeted: retweet}" class='avatar' :src="status.user.profile_image_url_original"/>
-            <img v-if="retweet" class='avatar-retweeter' :src="statusoid.user.profile_image_url_original"></img>
+            <StillImage v-if="retweet" class='avatar avatar-retweeter' :src="statusoid.user.profile_image_url_original"/>
           </a>
         </div>
         <div class="media-body">
@@ -265,7 +265,7 @@
 
      .media-left {
         margin: 0.2em 0.3em 0 0;
-        img {
+        .avatar {
           float: right;
         }
      }
@@ -359,7 +359,7 @@
      }
  }
 
- .status img.avatar-retweeter {
+ .status .avatar-retweeter {
    width: 24px;
    height: 24px;
    position: absolute;
@@ -433,7 +433,7 @@
      }
    }
 
-   .status img.avatar-retweeter {
+   .status .avatar-retweeter {
      width: 22px;
      height: 22px;
      position: absolute;
diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
index f0b25265..0839aca5 100644
--- a/src/components/still-image/still-image.js
+++ b/src/components/still-image/still-image.js
@@ -4,9 +4,14 @@ const StillImage = {
     'referrerpolicy',
     'mimetype'
   ],
+  data () {
+    return {
+      stopGifs: this.$store.state.config.stopGifs
+    }
+  },
   computed: {
     animated () {
-      return this.mimetype === 'image/gif' || this.src.endsWith('.gif')
+      return this.stopGifs && (this.mimetype === 'image/gif' || this.src.endsWith('.gif'))
     }
   },
   methods: {
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
index 91d7f77a..5695c554 100644
--- a/src/components/still-image/still-image.vue
+++ b/src/components/still-image/still-image.vue
@@ -12,17 +12,23 @@
 .still-image {
     position: relative;
     line-height: 0;
-    
+    overflow: hidden;
+
     &:hover canvas {
         display: none;
     }
-    
+
+    img {
+        width: 100%;
+        height: 100%
+    }
+
     &.animated {
         &:hover::before,
         img {
-            visibility: hidden
+            visibility: hidden;
         }
-        
+
         &:hover img {
             visibility: visible
         }
diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js
index 32d62ebb..8c9ccda1 100644
--- a/src/components/user_card_content/user_card_content.js
+++ b/src/components/user_card_content/user_card_content.js
@@ -1,3 +1,4 @@
+import StillImage from '../still-image/still-image.vue'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
 
 export default {
@@ -35,6 +36,9 @@ export default {
       return Math.round(this.user.statuses_count / days)
     }
   },
+  components: {
+    StillImage
+  },
   methods: {
     followUser () {
       const store = this.$store
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index ef000c94..71a879df 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -7,7 +7,7 @@
         </router-link>
         <div class='container'>
           <router-link :to="{ name: 'user-profile', params: { id: user.id } }">
-            <img :src="user.profile_image_url_original">
+            <StillImage class="avatar" :src="user.profile_image_url_original"/>
           </router-link>
           <span class="glyphicon glyphicon-user"></span>
           <div class="name-and-screen-name">
@@ -135,13 +135,26 @@
     overflow: hidden;
   }
 
-  img {
+  .avatar {
     border-radius: 5px;
     flex: 1 0 100%;
     width: 56px;
     height: 56px;
     box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
     object-fit: cover;
+
+    &.animated::before {
+      display: none;
+    }
+  }
+
+  &:hover .animated.avatar {
+    canvas {
+      display: none;
+    }
+    img {
+      visibility: visible;
+    }
   }
 
 	text-shadow: 0px 1px 1.5px rgba(0, 0, 0, 1.0);
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index c4a62128..48708539 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -245,6 +245,7 @@ const en = {
     hide_attachments_in_tl: 'Hide attachments in timeline',
     hide_attachments_in_convo: 'Hide attachments in conversations',
     nsfw_clickthrough: 'Enable clickthrough NSFW attachment hiding',
+    stop_gifs: 'Play-on-hover GIFs',
     autoload: 'Enable automatic loading when scrolled to the bottom',
     streaming: 'Enable automatic streaming of new posts when scrolled to the top',
     reply_link_preview: 'Enable reply-link preview on mouse hover',
@@ -1096,6 +1097,7 @@ const ru = {
     attachments: 'Вложения',
     hide_attachments_in_tl: 'Прятать вложения в ленте',
     hide_attachments_in_convo: 'Прятать вложения в разговорах',
+    stop_gifs: 'Проигрывать GIF анимации только при наведении',
     nsfw_clickthrough: 'Включить скрытие NSFW вложений',
     autoload: 'Включить автоматическую загрузку при прокрутке вниз',
     streaming: 'Включить автоматическую загрузку новых сообщений при прокрутке вверх',