From 95b735ff7244a44c61034be1c1e927f2fef3798e Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 2 Feb 2019 14:11:36 -0500
Subject: [PATCH 01/16] Show placeholder image if avatar image url is broken

---
 src/components/status/status.js            |  2 ++
 src/components/status/status.vue           |  2 +-
 src/components/still-image/still-image.js  |  3 ++-
 src/components/still-image/still-image.vue |  2 +-
 src/components/user_avatar/user_avatar.js  | 28 ++++++++++++++++++++++
 src/components/user_avatar/user_avatar.vue |  5 ++++
 6 files changed, 39 insertions(+), 3 deletions(-)
 create mode 100644 src/components/user_avatar/user_avatar.js
 create mode 100644 src/components/user_avatar/user_avatar.vue

diff --git a/src/components/status/status.js b/src/components/status/status.js
index aaac5b71..2004b5cc 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -5,6 +5,7 @@ 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 UserAvatar from '../user_avatar/user_avatar.vue'
 import Gallery from '../gallery/gallery.vue'
 import LinkPreview from '../link-preview/link-preview.vue'
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@@ -245,6 +246,7 @@ const Status = {
     PostStatusForm,
     UserCardContent,
     StillImage,
+    UserAvatar,
     Gallery,
     LinkPreview
   },
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index c6e73e4e..5611d8d2 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -25,7 +25,7 @@
       <div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status">
         <div v-if="!noHeading" class="media-left">
           <router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
-            <StillImage class='avatar' :class="{'avatar-compact': compact, 'better-shadow': betterShadow}"  :src="status.user.profile_image_url_original"/>
+            <UserAvatar :class="{'avatar-compact': compact, 'better-shadow': betterShadow}" :src="status.user.profile_image_url_original"/>
           </router-link>
         </div>
         <div class="status-body">
diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js
index 5ad06dc2..8f3a7206 100644
--- a/src/components/still-image/still-image.js
+++ b/src/components/still-image/still-image.js
@@ -2,7 +2,8 @@ const StillImage = {
   props: [
     'src',
     'referrerpolicy',
-    'mimetype'
+    'mimetype',
+    'imageLoadError'
   ],
   data () {
     return {
diff --git a/src/components/still-image/still-image.vue b/src/components/still-image/still-image.vue
index 1dcb7ce6..29c59e42 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="onLoad"/>
+    <img ref="src" :src="src" :referrerpolicy="referrerpolicy" v-on:load="onLoad" @error="imageLoadError"/>
   </div>
 </template>
 
diff --git a/src/components/user_avatar/user_avatar.js b/src/components/user_avatar/user_avatar.js
new file mode 100644
index 00000000..bfa2c2b5
--- /dev/null
+++ b/src/components/user_avatar/user_avatar.js
@@ -0,0 +1,28 @@
+import StillImage from '../still-image/still-image.vue'
+import nsfwImage from '../../assets/nsfw.png'
+
+const UserAvatar = {
+  props: [
+    'src'
+  ],
+  data () {
+    return {
+      showPlaceholder: false
+    }
+  },
+  components: {
+    StillImage
+  },
+  computed: {
+    imgSrc () {
+      return this.showPlaceholder ? nsfwImage : this.src
+    }
+  },
+  methods: {
+    imageLoadError () {
+      this.showPlaceholder = true
+    }
+  }
+}
+
+export default UserAvatar
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
new file mode 100644
index 00000000..75a857ac
--- /dev/null
+++ b/src/components/user_avatar/user_avatar.vue
@@ -0,0 +1,5 @@
+<template>
+  <StillImage class="avatar" :src="imgSrc" :imageLoadError="imageLoadError"/>
+</template>
+
+<script src="./user_avatar.js"></script>

From 9c4092dbd5887b4476955076fdcbe621718a8d03 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 2 Feb 2019 14:17:00 -0500
Subject: [PATCH 02/16] Use a correct avatar placeholder image

---
 src/assets/avatar-placeholder.png         | Bin 0 -> 1083 bytes
 src/components/user_avatar/user_avatar.js |   4 ++--
 2 files changed, 2 insertions(+), 2 deletions(-)
 create mode 100644 src/assets/avatar-placeholder.png

diff --git a/src/assets/avatar-placeholder.png b/src/assets/avatar-placeholder.png
new file mode 100644
index 0000000000000000000000000000000000000000..9c8398da6f597e51e74d86125a48c25ee97b4971
GIT binary patch
literal 1083
zcmV-B1jPG^P)<h;3K|Lk000e1NJLTq005Q%005Q<0{{R33*Ujz0000LP)t-s#l^+{
z|Nrmr@B91v$;rvy-rmvC(W|OjRR913;Ymb6RCwC$TiI^oFbs@1BLDxBcNb{0wslex
zDL;r0ZIBqql*jPw=X2!9kt0Wr96562$dMyQjvP6Xiiq%E5sB}C!~nvtfanF-nEpWt
z4<X)(EHY9^ze<x`sOS#lfh+6*#waN2qA`Czr_dI_Sz(gZROU@~HDKr#ikp1>Ew~68
zSOIYhDtvz->s~(kViepQ#TalP3JC*3dzhgq@}?kkb9)YhVr#}*9{dL0PaT0>X5>2{
zBoT-m>eBdoLL+RgEYxuzuRuF>A#~Oa*(c;pOln^gQbR=zwZYbgBRmf~D@sc}Xkccm
zI79_l-mKRLVD4JlSTszG2$N#c2Sq5E-N(6P0u&r!LG4}^0}~E&MubgTWN4T)+a1wo
zi?&+&veH&w3uq85EK5NN)533q1v6Ojo!a{JvOJ0(np8IQt<sTe#|klUnV8t5YC?8Q
z^DMP+dE*v~Mup96C>j;>?Ggh1b<Iy5h;*ifyD^J7%4$5qBV1+Q?pLjdN8Y(aDU63B
zJj3#K6I8jl(v^>{^M_({WVkq>bc&0N4RI%2SUUXEyOhIu(=7{EV-A@b%VkLUP*;|t
z@J!sWA2my5RD(2EJNSFXjOg?<hcyQ2n|_aFR3vTY@!7#valx;0NZg(Zvo_?Cq~E?e
zDmFi^X9tze|30cD-}4da8a2cHs3mp~#g@AfL7h#(8$d-yrfa=7W$q@F?0ppWno-_J
z5Te{yy8w%<?!{nFUOcpjG7ie9uWEj#BILwWuh^`l2832=R)$Orm|1(myL8SMGic5u
zu6@V)h`gXGA4;J~`ipVJ>1Cotvk@_{$v4OK^ed=H{yrC9Xh*7o$u!f+tIN-2xTsdI
zqqQcm;t4L@IUsvq@SMxzGMmG?s+H@lO{fiR>~=q^s9|k>jHHV<C->rDB9pkJl#E;S
zT5P$o;*cI4oLSpf7duJ3(1erGD6oSyG2|sfRO4Q6s;qJHT7n9zPZ*^UeD|GBg&s=h
zdAvbcF!C-59e3S|rehIF(Clqn^U;x3TY`h=gHbnaK;t|%KbRg+7ckS{^!_!k$cC79
zdP+|S5|iLjKtqX1f5a%rxCqLf4>G&X+oMR<>mv&x&RtwQyDwz8ANdo(C;0CtY+E~E
za2BAlVjTPOk(iCE<8Tde@GzHlpXXvA9%(`GfbMTYJq!E~69uEjZU;t>mQYPtGT~b2
zDG)H^eY`jG%)`P&r0M7N^W`!OC<Cer5cP7ZpGCh(u@p3-tm6CCf$G3;(Gbqn<NINe
z4;=0PQ<AH);0H?;lD)8eU8|cR;EXG(>-b%;{s2z#Db~E#gb4ru002ovPDHLkV1n08
B1Tp{s

literal 0
HcmV?d00001

diff --git a/src/components/user_avatar/user_avatar.js b/src/components/user_avatar/user_avatar.js
index bfa2c2b5..407ce1a6 100644
--- a/src/components/user_avatar/user_avatar.js
+++ b/src/components/user_avatar/user_avatar.js
@@ -1,5 +1,5 @@
 import StillImage from '../still-image/still-image.vue'
-import nsfwImage from '../../assets/nsfw.png'
+import avatarPlaceholderImage from '../../assets/avatar-placeholder.png'
 
 const UserAvatar = {
   props: [
@@ -15,7 +15,7 @@ const UserAvatar = {
   },
   computed: {
     imgSrc () {
-      return this.showPlaceholder ? nsfwImage : this.src
+      return this.showPlaceholder ? avatarPlaceholderImage : this.src
     }
   },
   methods: {

From d607e4195a114843029e902e09df323096e0dcd6 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 2 Feb 2019 14:23:16 -0500
Subject: [PATCH 03/16] Migrate StillImage to UserAvatar for avatars

---
 src/components/status/status.js                        | 2 --
 src/components/status/status.vue                       | 2 +-
 src/components/user_card/user_card.js                  | 4 ++--
 src/components/user_card/user_card.vue                 | 2 +-
 src/components/user_card_content/user_card_content.js  | 4 ++--
 src/components/user_card_content/user_card_content.vue | 2 +-
 6 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/src/components/status/status.js b/src/components/status/status.js
index 2004b5cc..25fa205d 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -4,7 +4,6 @@ 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 UserAvatar from '../user_avatar/user_avatar.vue'
 import Gallery from '../gallery/gallery.vue'
 import LinkPreview from '../link-preview/link-preview.vue'
@@ -245,7 +244,6 @@ const Status = {
     DeleteButton,
     PostStatusForm,
     UserCardContent,
-    StillImage,
     UserAvatar,
     Gallery,
     LinkPreview
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 5611d8d2..cf9d1c47 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -13,7 +13,7 @@
     </template>
     <template v-else>
       <div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
-        <StillImage v-if="retweet" class='avatar' :class='{ "better-shadow": betterShadow }' :src="statusoid.user.profile_image_url_original"/>
+        <UserAvatar v-if="retweet" :class='{ "better-shadow": betterShadow }' :src="statusoid.user.profile_image_url_original"/>
         <div class="media-body faint">
           <a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a>
           <a v-else :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 615e6487..ecc36a4d 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -1,5 +1,5 @@
 import UserCardContent from '../user_card_content/user_card_content.vue'
-import StillImage from '../still-image/still-image.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
 
 const UserCard = {
@@ -15,7 +15,7 @@ const UserCard = {
   },
   components: {
     UserCardContent,
-    StillImage
+    UserAvatar
   },
   computed: {
     currentUser () { return this.$store.state.users.currentUser }
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index cf69606d..4f512974 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -1,7 +1,7 @@
 <template>
   <div class="card">
     <a href="#">
-      <StillImage @click.prevent="toggleUserExpanded" class="avatar" :src="user.profile_image_url"/>
+      <UserAvatar @click.prevent="toggleUserExpanded" :src="user.profile_image_url"/>
     </a>
     <div class="usercard" v-if="userExpanded">
       <user-card-content :user="user" :switcher="false"></user-card-content>
diff --git a/src/components/user_card_content/user_card_content.js b/src/components/user_card_content/user_card_content.js
index 541c73b4..6f6d04a7 100644
--- a/src/components/user_card_content/user_card_content.js
+++ b/src/components/user_card_content/user_card_content.js
@@ -1,4 +1,4 @@
-import StillImage from '../still-image/still-image.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
 
@@ -82,7 +82,7 @@ export default {
     }
   },
   components: {
-    StillImage
+    UserAvatar
   },
   methods: {
     followUser () {
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index d1034d68..7f844c19 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -4,7 +4,7 @@
     <div class='user-info'>
       <div class='container'>
         <router-link :to="userProfileLink(user)">
-          <StillImage class="avatar" :class='{ "better-shadow": betterShadow }' :src="user.profile_image_url_original"/>
+          <UserAvatar :class='{ "better-shadow": betterShadow }' :src="user.profile_image_url_original"/>
         </router-link>
         <div class="name-and-screen-name">
           <div class="top-line">

From 89b9aed1344724b6e00fc927570c1a3806aac0ce Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 2 Feb 2019 14:33:13 -0500
Subject: [PATCH 04/16] Move avatar css into a correct place

---
 src/components/status/status.vue           | 27 ----------------------
 src/components/user_avatar/user_avatar.vue | 27 ++++++++++++++++++++++
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index cf9d1c47..5bd5a8e9 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -502,33 +502,6 @@
   }
 }
 
-.avatar.still-image {
-  width: 48px;
-  height: 48px;
-  box-shadow: var(--avatarStatusShadow);
-  border-radius: $fallback--avatarRadius;
-  border-radius: var(--avatarRadius, $fallback--avatarRadius);
-  overflow: hidden;
-  position: relative;
-
-  &.better-shadow {
-    box-shadow: var(--avatarStatusShadowInset);
-    filter: var(--avatarStatusShadowFilter)
-  }
-
-  img {
-    width: 100%;
-    height: 100%;
-  }
-
-  &.animated::before {
-    display: none;
-  }
-
-  &.retweeted {
-  }
-}
-
 .status:hover .animated.avatar {
   canvas {
     display: none;
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
index 75a857ac..bbc99f96 100644
--- a/src/components/user_avatar/user_avatar.vue
+++ b/src/components/user_avatar/user_avatar.vue
@@ -3,3 +3,30 @@
 </template>
 
 <script src="./user_avatar.js"></script>
+<style lang="scss">
+@import '../../_variables.scss';
+
+.avatar.still-image {
+  width: 48px;
+  height: 48px;
+  box-shadow: var(--avatarStatusShadow);
+  border-radius: $fallback--avatarRadius;
+  border-radius: var(--avatarRadius, $fallback--avatarRadius);
+  overflow: hidden;
+  position: relative;
+
+  &.better-shadow {
+    box-shadow: var(--avatarStatusShadowInset);
+    filter: var(--avatarStatusShadowFilter)
+  }
+
+  &.animated::before {
+    display: none;
+  }
+
+  img {
+    width: 100%;
+    height: 100%;
+  }
+}
+</style>

From 0b66a43a83ebe64cf2fbfefac84e66fcd94093d7 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 2 Feb 2019 15:33:02 -0500
Subject: [PATCH 05/16] Improve reusability of UserAvatar component

---
 src/components/notification/notification.js   |  4 +--
 src/components/notification/notification.vue  |  2 +-
 .../notifications/notifications.scss          | 21 +---------------
 src/components/status/status.vue              | 25 +++++--------------
 src/components/user_avatar/user_avatar.js     |  4 ++-
 src/components/user_avatar/user_avatar.vue    | 17 ++++++++-----
 .../user_card_content/user_card_content.vue   | 13 +---------
 7 files changed, 25 insertions(+), 61 deletions(-)

diff --git a/src/components/notification/notification.js b/src/components/notification/notification.js
index f95a329f..7d9807de 100644
--- a/src/components/notification/notification.js
+++ b/src/components/notification/notification.js
@@ -1,5 +1,5 @@
 import Status from '../status/status.vue'
-import StillImage from '../still-image/still-image.vue'
+import UserAvatar from '../user_avatar/user_avatar.vue'
 import UserCardContent from '../user_card_content/user_card_content.vue'
 import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@@ -13,7 +13,7 @@ const Notification = {
   },
   props: [ 'notification' ],
   components: {
-    Status, StillImage, UserCardContent
+    Status, UserAvatar, UserCardContent
   },
   methods: {
     toggleUserExpanded () {
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index f91c90cc..a0a55cba 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -2,7 +2,7 @@
   <status v-if="notification.type === 'mention'" :compact="true" :statusoid="notification.status"></status>
   <div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]"v-else>
     <a class='avatar-container' :href="notification.action.user.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
-      <StillImage class='avatar-compact' :class="{'better-shadow': betterShadow}" :src="notification.action.user.profile_image_url_original"/>
+      <UserAvatar :compact="true" :betterShadow="betterShadow" :src="notification.action.user.profile_image_url_original"/>
     </a>
     <div class='notification-right'>
       <div class="usercard notification-usercard" v-if="userExpanded">
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 5c4ca1b9..bc81d45c 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -36,26 +36,7 @@
   border-color: $fallback--border;
   border-color: var(--border, $fallback--border);
 
-  .avatar-compact {
-    width: 32px;
-    height: 32px;
-    box-shadow: var(--avatarStatusShadow);
-    border-radius: $fallback--avatarAltRadius;
-    border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
-    overflow: hidden;
-    line-height: 0;
-
-    &.better-shadow {
-      box-shadow: var(--avatarStatusShadowInset);
-      filter: var(--avatarStatusShadowFilter)
-    }
-
-    &.animated::before {
-      display: none;
-    }
-  }
-
-  &:hover .animated.avatar-compact {
+  &:hover .animated.avatar {
     canvas {
       display: none;
     }
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 5bd5a8e9..a6586fa0 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -13,7 +13,7 @@
     </template>
     <template v-else>
       <div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
-        <UserAvatar v-if="retweet" :class='{ "better-shadow": betterShadow }' :src="statusoid.user.profile_image_url_original"/>
+        <UserAvatar v-if="retweet" :betterShadow="betterShadow" :src="statusoid.user.profile_image_url_original"/>
         <div class="media-body faint">
           <a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a>
           <a v-else :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
@@ -25,7 +25,7 @@
       <div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet }]" :style="[ userStyle ]" class="media status">
         <div v-if="!noHeading" class="media-left">
           <router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
-            <UserAvatar :class="{'avatar-compact': compact, 'better-shadow': betterShadow}" :src="status.user.profile_image_url_original"/>
+            <UserAvatar :compact="compact" :betterShadow="betterShadow" :src="status.user.profile_image_url_original"/>
           </router-link>
         </div>
         <div class="status-body">
@@ -489,19 +489,6 @@
   color: var(--cBlue, $fallback--cBlue);
 }
 
-.status .avatar-compact {
-  width: 32px;
-  height: 32px;
-  box-shadow: var(--avatarStatusShadow);
-  border-radius: $fallback--avatarAltRadius;
-  border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
-
-  &.better-shadow {
-    box-shadow: var(--avatarStatusShadowInset);
-    filter: var(--avatarStatusShadowFilter)
-  }
-}
-
 .status:hover .animated.avatar {
   canvas {
     display: none;
@@ -571,11 +558,11 @@ a.unmute {
   .status .avatar {
     width: 40px;
     height: 40px;
-  }
 
-  .status .avatar-compact {
-    width: 32px;
-    height: 32px;
+    &.avatar-compact {
+      width: 32px;
+      height: 32px;
+    }
   }
 }
 
diff --git a/src/components/user_avatar/user_avatar.js b/src/components/user_avatar/user_avatar.js
index 407ce1a6..8afb46c2 100644
--- a/src/components/user_avatar/user_avatar.js
+++ b/src/components/user_avatar/user_avatar.js
@@ -3,7 +3,9 @@ import avatarPlaceholderImage from '../../assets/avatar-placeholder.png'
 
 const UserAvatar = {
   props: [
-    'src'
+    'src',
+    'betterShadow',
+    'compact'
   ],
   data () {
     return {
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
index bbc99f96..3ec25b21 100644
--- a/src/components/user_avatar/user_avatar.vue
+++ b/src/components/user_avatar/user_avatar.vue
@@ -1,5 +1,5 @@
 <template>
-  <StillImage class="avatar" :src="imgSrc" :imageLoadError="imageLoadError"/>
+  <StillImage class="avatar" :class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }" :src="imgSrc" :imageLoadError="imageLoadError"/>
 </template>
 
 <script src="./user_avatar.js"></script>
@@ -12,8 +12,11 @@
   box-shadow: var(--avatarStatusShadow);
   border-radius: $fallback--avatarRadius;
   border-radius: var(--avatarRadius, $fallback--avatarRadius);
-  overflow: hidden;
-  position: relative;
+
+  img {
+    width: 100%;
+    height: 100%;
+  }
 
   &.better-shadow {
     box-shadow: var(--avatarStatusShadowInset);
@@ -24,9 +27,11 @@
     display: none;
   }
 
-  img {
-    width: 100%;
-    height: 100%;
+  &.avatar-compact {
+    width: 32px;
+    height: 32px;
+    border-radius: $fallback--avatarAltRadius;
+    border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
   }
 }
 </style>
diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue
index 7f844c19..ce65ec2f 100644
--- a/src/components/user_card_content/user_card_content.vue
+++ b/src/components/user_card_content/user_card_content.vue
@@ -4,7 +4,7 @@
     <div class='user-info'>
       <div class='container'>
         <router-link :to="userProfileLink(user)">
-          <UserAvatar :class='{ "better-shadow": betterShadow }' :src="user.profile_image_url_original"/>
+          <UserAvatar :betterShadow="betterShadow" :src="user.profile_image_url_original"/>
         </router-link>
         <div class="name-and-screen-name">
           <div class="top-line">
@@ -169,23 +169,12 @@
     max-height: 56px;
 
     .avatar {
-      border-radius: $fallback--avatarRadius;
-      border-radius: var(--avatarRadius, $fallback--avatarRadius);
       flex: 1 0 100%;
       width: 56px;
       height: 56px;
       box-shadow: 0px 1px 8px rgba(0,0,0,0.75);
       box-shadow: var(--avatarShadow);
       object-fit: cover;
-
-      &.better-shadow {
-        box-shadow: var(--avatarShadowInset);
-        filter: var(--avatarShadowFilter)
-      }
-
-      &.animated::before {
-        display: none;
-      }
     }
   }
 

From 4833f79cc2f2c43cdd8d185bf0b2cf17dc117b59 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sat, 2 Feb 2019 15:50:25 -0500
Subject: [PATCH 06/16] Fix class ordering issues related to avatar

---
 src/components/status/status.vue       | 6 +++---
 src/components/user_card/user_card.vue | 6 +-----
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index a6586fa0..5f3998a4 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -405,7 +405,7 @@
     padding: 0.4em 0.6em 0 0.6em;
     margin: 0;
 
-    .avatar {
+    .avatar.still-image {
       border-radius: $fallback--avatarAltRadius;
       border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
       margin-left: 28px;
@@ -546,7 +546,7 @@ a.unmute {
 @media all and (max-width: 800px) {
   .status-el {
     .retweet-info {
-      .avatar {
+      .avatar.still-image {
         margin-left: 20px;
       }
     }
@@ -555,7 +555,7 @@ a.unmute {
     max-width: 100%;
   }
 
-  .status .avatar {
+  .status .avatar.still-image {
     width: 40px;
     height: 40px;
 
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 4f512974..57a44dfb 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -1,7 +1,7 @@
 <template>
   <div class="card">
     <a href="#">
-      <UserAvatar @click.prevent="toggleUserExpanded" :src="user.profile_image_url"/>
+      <UserAvatar :compact="true" @click.prevent="toggleUserExpanded" :src="user.profile_image_url"/>
     </a>
     <div class="usercard" v-if="userExpanded">
       <user-card-content :user="user" :switcher="false"></user-card-content>
@@ -70,10 +70,6 @@
 
   .avatar {
     margin-top: 0.2em;
-    width:32px;
-    height: 32px;
-    border-radius: $fallback--avatarAltRadius;
-    border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
   }
 }
 

From 1e40e70efc64071581adff4bce3c8bf78da82acb Mon Sep 17 00:00:00 2001
From: Xiaofeng An <futureweb2020@yandex.com>
Date: Sat, 2 Feb 2019 21:49:07 -0500
Subject: [PATCH 07/16] #306 - fix conversation arrow smushed in notifications
 panel

---
 src/components/status/status.vue | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index c6e73e4e..e8bc8cbc 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -280,6 +280,7 @@
       color: var(--link, $fallback--link);
       max-width: 100%;
       a {
+        min-width: 17px;
         max-width: 100%;
         text-overflow: ellipsis;
         overflow: hidden;

From d4991d01625d27086759220f5d25af5311d5d4ed Mon Sep 17 00:00:00 2001
From: Shpuld Shpludson <shp@cock.li>
Date: Sun, 3 Feb 2019 14:32:23 +0000
Subject: [PATCH 08/16] Revert "Merge branch 'feature/split-hide-network' into
 'develop'"

This reverts merge request !497
---
 src/components/user_settings/user_settings.js            | 9 +++------
 src/components/user_settings/user_settings.vue           | 8 ++------
 src/i18n/de.json                                         | 3 +--
 src/i18n/en.json                                         | 3 +--
 src/i18n/ja.json                                         | 3 +--
 src/i18n/ko.json                                         | 3 +--
 src/i18n/ru.json                                         | 3 +--
 src/services/api/api.service.js                          | 2 +-
 .../entity_normalizer/entity_normalizer.service.js       | 3 +--
 9 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js
index 719a9c0c..9bd8aa00 100644
--- a/src/components/user_settings/user_settings.js
+++ b/src/components/user_settings/user_settings.js
@@ -10,8 +10,7 @@ const UserSettings = {
       newLocked: this.$store.state.users.currentUser.locked,
       newNoRichText: this.$store.state.users.currentUser.no_rich_text,
       newDefaultScope: this.$store.state.users.currentUser.default_scope,
-      hideFollowings: this.$store.state.users.currentUser.hide_followings,
-      hideFollowers: this.$store.state.users.currentUser.hide_followers,
+      newHideNetwork: this.$store.state.users.currentUser.hide_network,
       followList: null,
       followImportError: false,
       followsImported: false,
@@ -67,8 +66,7 @@ const UserSettings = {
       /* eslint-disable camelcase */
       const default_scope = this.newDefaultScope
       const no_rich_text = this.newNoRichText
-      const hide_followings = this.hideFollowings
-      const hide_followers = this.hideFollowers
+      const hide_network = this.newHideNetwork
       /* eslint-enable camelcase */
       this.$store.state.api.backendInteractor
         .updateProfile({
@@ -80,8 +78,7 @@ const UserSettings = {
             /* eslint-disable camelcase */
             default_scope,
             no_rich_text,
-            hide_followings,
-            hide_followers
+            hide_network
             /* eslint-enable camelcase */
           }}).then((user) => {
             if (!user.error) {
diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue
index 82e1e56c..be42cc4a 100644
--- a/src/components/user_settings/user_settings.vue
+++ b/src/components/user_settings/user_settings.vue
@@ -30,12 +30,8 @@
               <label for="account-no-rich-text">{{$t('settings.no_rich_text_description')}}</label>
             </p>
             <p>
-              <input type="checkbox" v-model="hideFollowings" id="account-hide-followings">
-              <label for="account-hide-followings">{{$t('settings.hide_followings_description')}}</label>
-            </p>
-            <p>
-              <input type="checkbox" v-model="hideFollowers" id="account-hide-followers">
-              <label for="account-hide-followers">{{$t('settings.hide_followers_description')}}</label>
+              <input type="checkbox" v-model="newHideNetwork" id="account-hide-network">
+              <label for="account-hide-network">{{$t('settings.hide_network_description')}}</label>
             </p>
             <button :disabled='newName.length <= 0' class="btn btn-default" @click="updateProfile">{{$t('general.submit')}}</button>
           </div>
diff --git a/src/i18n/de.json b/src/i18n/de.json
index 82860e9e..c87371e6 100644
--- a/src/i18n/de.json
+++ b/src/i18n/de.json
@@ -155,8 +155,7 @@
     "notification_visibility_mentions": "Erwähnungen",
     "notification_visibility_repeats": "Wiederholungen",
     "no_rich_text_description": "Rich-Text Formatierungen von allen Beiträgen entfernen",
-    "hide_followings_description": "Zeige nicht, wem ich folge",
-    "hide_followers_description": "Zeige nicht, wer mir folgt",
+    "hide_network_description": "Zeige nicht, wem ich folge und wer mir folgt",
     "nsfw_clickthrough": "Aktiviere ausblendbares Overlay für Anhänge, die als NSFW markiert sind",
     "panelRadius": "Panel",
     "pause_on_unfocused": "Streaming pausieren, wenn das Tab nicht fokussiert ist",
diff --git a/src/i18n/en.json b/src/i18n/en.json
index d3b0e407..29ac2b9a 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -162,8 +162,7 @@
     "notification_visibility_mentions": "Mentions",
     "notification_visibility_repeats": "Repeats",
     "no_rich_text_description": "Strip rich text formatting from all posts",
-    "hide_followings_description": "Don't show who I'm following",
-    "hide_followers_description": "Don't show who's following me",
+    "hide_network_description": "Don't show who I'm following and who's following me",
     "nsfw_clickthrough": "Enable clickthrough NSFW attachment hiding",
     "panelRadius": "Panels",
     "pause_on_unfocused": "Pause streaming when tab is not focused",
diff --git a/src/i18n/ja.json b/src/i18n/ja.json
index 37e96f6c..161856f0 100644
--- a/src/i18n/ja.json
+++ b/src/i18n/ja.json
@@ -157,8 +157,7 @@
     "notification_visibility_mentions": "メンション",
     "notification_visibility_repeats": "リピート",
     "no_rich_text_description": "リッチテキストをつかわない",
-    "hide_followings_description": "フォローしている人を表示しない",
-    "hide_followers_description": "フォローしている人を表示しない",
+    "hide_network_description": "わたしがフォローしているひとと、わたしをフォローしているひとを、みせない",
     "nsfw_clickthrough": "NSFWなファイルをかくす",
     "panelRadius": "パネル",
     "pause_on_unfocused": "タブにフォーカスがないときストリーミングをとめる",
diff --git a/src/i18n/ko.json b/src/i18n/ko.json
index 9f40be51..4b69df07 100644
--- a/src/i18n/ko.json
+++ b/src/i18n/ko.json
@@ -156,8 +156,7 @@
     "notification_visibility_mentions": "멘션",
     "notification_visibility_repeats": "반복",
     "no_rich_text_description": "모든 게시물의 서식을 지우기",
-    "hide_followings_description": "내가 팔로우하는 사람을 표시하지 않음",
-    "hide_followers_description": "나를 따르는 사람을 보여주지 마라.",
+    "hide_network_description": "내 팔로우와 팔로워를 숨기기",
     "nsfw_clickthrough": "NSFW 이미지 \"클릭해서 보이기\"를 활성화",
     "panelRadius": "패널",
     "pause_on_unfocused": "탭이 활성 상태가 아닐 때 스트리밍 멈추기",
diff --git a/src/i18n/ru.json b/src/i18n/ru.json
index bf1e319f..0887bb59 100644
--- a/src/i18n/ru.json
+++ b/src/i18n/ru.json
@@ -127,8 +127,7 @@
     "notification_visibility_mentions": "Упоминания",
     "notification_visibility_repeats": "Повторы",
     "no_rich_text_description": "Убрать форматирование из всех постов",
-    "hide_followings_description": "Не показывать кого я читаю",
-    "hide_followers_description": "Не показывать кто читает меня",
+    "hide_network_description": "Не показывать кого я читаю и кто меня читает",
     "nsfw_clickthrough": "Включить скрытие NSFW вложений",
     "panelRadius": "Панели",
     "pause_on_unfocused": "Приостановить загрузку когда вкладка не в фокусе",
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
index 31b48cb6..5b0d8650 100644
--- a/src/services/api/api.service.js
+++ b/src/services/api/api.service.js
@@ -130,7 +130,7 @@ const updateBanner = ({credentials, params}) => {
 // description
 const updateProfile = ({credentials, params}) => {
   // Always include these fields, because they might be empty or false
-  const fields = ['description', 'locked', 'no_rich_text', 'hide_followings', 'hide_followers']
+  const fields = ['description', 'locked', 'no_rich_text', 'hide_network']
   let url = PROFILE_UPDATE_URL
 
   const form = new FormData()
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index ff4b93ef..74422a49 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -100,8 +100,7 @@ export const parseUser = (data) => {
     output.rights = data.rights
     output.no_rich_text = data.no_rich_text
     output.default_scope = data.default_scope
-    output.hide_followings = data.hide_followings
-    output.hide_followers = data.hide_followers
+    output.hide_network = data.hide_network
     output.background_image = data.background_image
     // on mastoapi this info is contained in a "relationship"
     output.following = data.following

From 965a5785614920df835288c0a249196108d9bd33 Mon Sep 17 00:00:00 2001
From: Xiaofeng An <futureweb2020@yandex.com>
Date: Sun, 3 Feb 2019 09:49:22 -0500
Subject: [PATCH 09/16] Revert "#306 - fix conversation arrow smushed in
 notifications panel"

This reverts commit 1e40e70efc64071581adff4bce3c8bf78da82acb.
---
 src/components/status/status.vue | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index e8bc8cbc..c6e73e4e 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -280,7 +280,6 @@
       color: var(--link, $fallback--link);
       max-width: 100%;
       a {
-        min-width: 17px;
         max-width: 100%;
         text-overflow: ellipsis;
         overflow: hidden;

From 6d3a7809be8502ac06a300447478c12c84f5de01 Mon Sep 17 00:00:00 2001
From: Xiaofeng An <futureweb2020@yandex.com>
Date: Sun, 3 Feb 2019 09:59:32 -0500
Subject: [PATCH 10/16] #306 - fix conversation arrow smushed in notifications
 panel

---
 src/components/status/status.vue | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index c6e73e4e..3e3e82bf 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -285,6 +285,14 @@
         overflow: hidden;
         white-space: nowrap;
       }
+      & > span {
+        text-overflow: ellipsis;
+        overflow: hidden;
+        white-space: nowrap;
+      }
+      & > a:last-child {
+        flex-shrink: 0;
+      }
     }
     .reply-info {
       display: flex;

From e7f43d6bc3c97f5a98df3e3d6defabe896e7cdce Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sun, 3 Feb 2019 13:30:54 -0500
Subject: [PATCH 11/16] Use an existing image served by backend instead

---
 src/assets/avatar-placeholder.png         | Bin 1083 -> 0 bytes
 src/components/user_avatar/user_avatar.js |   3 +--
 2 files changed, 1 insertion(+), 2 deletions(-)
 delete mode 100644 src/assets/avatar-placeholder.png

diff --git a/src/assets/avatar-placeholder.png b/src/assets/avatar-placeholder.png
deleted file mode 100644
index 9c8398da6f597e51e74d86125a48c25ee97b4971..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1083
zcmV-B1jPG^P)<h;3K|Lk000e1NJLTq005Q%005Q<0{{R33*Ujz0000LP)t-s#l^+{
z|Nrmr@B91v$;rvy-rmvC(W|OjRR913;Ymb6RCwC$TiI^oFbs@1BLDxBcNb{0wslex
zDL;r0ZIBqql*jPw=X2!9kt0Wr96562$dMyQjvP6Xiiq%E5sB}C!~nvtfanF-nEpWt
z4<X)(EHY9^ze<x`sOS#lfh+6*#waN2qA`Czr_dI_Sz(gZROU@~HDKr#ikp1>Ew~68
zSOIYhDtvz->s~(kViepQ#TalP3JC*3dzhgq@}?kkb9)YhVr#}*9{dL0PaT0>X5>2{
zBoT-m>eBdoLL+RgEYxuzuRuF>A#~Oa*(c;pOln^gQbR=zwZYbgBRmf~D@sc}Xkccm
zI79_l-mKRLVD4JlSTszG2$N#c2Sq5E-N(6P0u&r!LG4}^0}~E&MubgTWN4T)+a1wo
zi?&+&veH&w3uq85EK5NN)533q1v6Ojo!a{JvOJ0(np8IQt<sTe#|klUnV8t5YC?8Q
z^DMP+dE*v~Mup96C>j;>?Ggh1b<Iy5h;*ifyD^J7%4$5qBV1+Q?pLjdN8Y(aDU63B
zJj3#K6I8jl(v^>{^M_({WVkq>bc&0N4RI%2SUUXEyOhIu(=7{EV-A@b%VkLUP*;|t
z@J!sWA2my5RD(2EJNSFXjOg?<hcyQ2n|_aFR3vTY@!7#valx;0NZg(Zvo_?Cq~E?e
zDmFi^X9tze|30cD-}4da8a2cHs3mp~#g@AfL7h#(8$d-yrfa=7W$q@F?0ppWno-_J
z5Te{yy8w%<?!{nFUOcpjG7ie9uWEj#BILwWuh^`l2832=R)$Orm|1(myL8SMGic5u
zu6@V)h`gXGA4;J~`ipVJ>1Cotvk@_{$v4OK^ed=H{yrC9Xh*7o$u!f+tIN-2xTsdI
zqqQcm;t4L@IUsvq@SMxzGMmG?s+H@lO{fiR>~=q^s9|k>jHHV<C->rDB9pkJl#E;S
zT5P$o;*cI4oLSpf7duJ3(1erGD6oSyG2|sfRO4Q6s;qJHT7n9zPZ*^UeD|GBg&s=h
zdAvbcF!C-59e3S|rehIF(Clqn^U;x3TY`h=gHbnaK;t|%KbRg+7ckS{^!_!k$cC79
zdP+|S5|iLjKtqX1f5a%rxCqLf4>G&X+oMR<>mv&x&RtwQyDwz8ANdo(C;0CtY+E~E
za2BAlVjTPOk(iCE<8Tde@GzHlpXXvA9%(`GfbMTYJq!E~69uEjZU;t>mQYPtGT~b2
zDG)H^eY`jG%)`P&r0M7N^W`!OC<Cer5cP7ZpGCh(u@p3-tm6CCf$G3;(Gbqn<NINe
z4;=0PQ<AH);0H?;lD)8eU8|cR;EXG(>-b%;{s2z#Db~E#gb4ru002ovPDHLkV1n08
B1Tp{s

diff --git a/src/components/user_avatar/user_avatar.js b/src/components/user_avatar/user_avatar.js
index 8afb46c2..e513b993 100644
--- a/src/components/user_avatar/user_avatar.js
+++ b/src/components/user_avatar/user_avatar.js
@@ -1,5 +1,4 @@
 import StillImage from '../still-image/still-image.vue'
-import avatarPlaceholderImage from '../../assets/avatar-placeholder.png'
 
 const UserAvatar = {
   props: [
@@ -17,7 +16,7 @@ const UserAvatar = {
   },
   computed: {
     imgSrc () {
-      return this.showPlaceholder ? avatarPlaceholderImage : this.src
+      return this.showPlaceholder ? '/images/avi.png' : this.src
     }
   },
   methods: {

From abf53838e2d75ba1ef4dd08a53ac5839c8eaa4b4 Mon Sep 17 00:00:00 2001
From: Xiaofeng An <futureweb2020@yandex.com>
Date: Sun, 3 Feb 2019 14:08:04 -0500
Subject: [PATCH 12/16] #307 - replace user links with router links in repeats

---
 src/components/status/status.js  | 1 +
 src/components/status/status.vue | 7 +++++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/components/status/status.js b/src/components/status/status.js
index c718fe9f..c32ba501 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -89,6 +89,7 @@ const Status = {
     retweet () { return !!this.statusoid.retweeted_status },
     retweeter () { return this.statusoid.user.name || this.statusoid.user.screen_name },
     retweeterHtml () { return this.statusoid.user.name_html },
+    retweeterProfileLink () { return this.generateUserProfileLink(this.statusoid.user.id, this.statusoid.user.screen_name) },
     status () {
       if (this.retweet) {
         return this.statusoid.retweeted_status
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 3e3e82bf..a1f79402 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -15,8 +15,11 @@
       <div v-if="retweet && !noHeading" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
         <StillImage v-if="retweet" class='avatar' :class='{ "better-shadow": betterShadow }' :src="statusoid.user.profile_image_url_original"/>
         <div class="media-body faint">
-          <a v-if="retweeterHtml" :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name" v-html="retweeterHtml"></a>
-          <a v-else :href="statusoid.user.statusnet_profile_url" class="user-name" :title="'@'+statusoid.user.screen_name">{{retweeter}}</a>
+          <span class="user-name">
+            <router-link :to="retweeterProfileLink">
+              {{retweeterHtml || retweeter}}
+            </router-link>
+          </span>
           <i class='fa icon-retweet retweeted' :title="$t('tool_tip.repeat')"></i>
           {{$t('timeline.repeated')}}
         </div>

From 06cf8628e54a30c5dd9dff153408f9641b8dad00 Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Sun, 3 Feb 2019 23:47:26 -0500
Subject: [PATCH 13/16] shorten incredibly long content warning or subject

---
 src/components/status/status.js  | 5 +++++
 src/components/status/status.vue | 7 ++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/src/components/status/status.js b/src/components/status/status.js
index c718fe9f..4dd0345c 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -36,6 +36,7 @@ const Status = {
       preview: null,
       showPreview: false,
       showingTall: this.inConversation && this.focused,
+      showingTallSubject: false,
       expandingSubject: typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
         ? !this.$store.state.instance.collapseMessageWithSubject
         : !this.$store.state.config.collapseMessageWithSubject,
@@ -129,6 +130,10 @@ const Status = {
       const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
       return lengthScore > 20
     },
+    tallSubject () {
+      const lengthScore = this.status.summary.length / 80
+      return lengthScore > 10
+    },
     isReply () {
       return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)
     },
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 3e3e82bf..adbaff73 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -85,7 +85,12 @@
             </div>
           </div>
 
-          <div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper">
+          <div class="status-content-wrapper" :class="{ 'tall-status': !showingTallSubject }" v-if="tallSubject">
+            <a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="!showingTallSubject" href="#" @click.prevent="showingTallSubject=true">Show more</a>
+            <div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html"></div>
+            <a v-if="showingTallSubject" href="#" class="status-unhider" @click.prevent="showingTallSubject=false">Show less</a>
+          </div>
+          <div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper" v-else>
             <a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">Show more</a>
             <div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html" v-if="!hideSubjectStatus"></div>
             <div @click.prevent="linkClicked" class="status-content media-body" v-html="status.summary_html" v-else></div>

From 887f1def2e1b8c052ddf2425f192502211c3013e Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Mon, 4 Feb 2019 03:16:55 -0500
Subject: [PATCH 14/16] handle poster attachment with tall subjects

---
 src/components/status/status.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index adbaff73..fdeda42a 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -98,7 +98,7 @@
             <a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">Show less</a>
           </div>
 
-          <div v-if="status.attachments && !hideSubjectStatus" class="attachments media-body">
+          <div v-if="status.attachments && (!hideSubjectStatus || showingTallSubject)" class="attachments media-body">
             <attachment
               class="non-gallery"
               v-for="attachment in nonGalleryAttachments"

From 9d72c7e1bd935b4a308fe2221344edf156288894 Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Mon, 4 Feb 2019 09:28:14 -0500
Subject: [PATCH 15/16] #154 - update long subject determine logic, meaningful
 variable names

---
 src/components/status/status.js  | 7 +++----
 src/components/status/status.vue | 8 ++++----
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/components/status/status.js b/src/components/status/status.js
index 4dd0345c..8b4c50f7 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -36,7 +36,7 @@ const Status = {
       preview: null,
       showPreview: false,
       showingTall: this.inConversation && this.focused,
-      showingTallSubject: false,
+      showingLongSubject: false,
       expandingSubject: typeof this.$store.state.config.collapseMessageWithSubject === 'undefined'
         ? !this.$store.state.instance.collapseMessageWithSubject
         : !this.$store.state.config.collapseMessageWithSubject,
@@ -130,9 +130,8 @@ const Status = {
       const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
       return lengthScore > 20
     },
-    tallSubject () {
-      const lengthScore = this.status.summary.length / 80
-      return lengthScore > 10
+    longSubject () {
+      return this.status.summary.length > 900
     },
     isReply () {
       return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index fdeda42a..a06e6cee 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -85,10 +85,10 @@
             </div>
           </div>
 
-          <div class="status-content-wrapper" :class="{ 'tall-status': !showingTallSubject }" v-if="tallSubject">
-            <a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="!showingTallSubject" href="#" @click.prevent="showingTallSubject=true">Show more</a>
+          <div class="status-content-wrapper" :class="{ 'tall-status': !showingLongSubject }" v-if="longSubject">
+            <a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="!showingLongSubject" href="#" @click.prevent="showingLongSubject=true">Show more</a>
             <div @click.prevent="linkClicked" class="status-content media-body" v-html="status.statusnet_html"></div>
-            <a v-if="showingTallSubject" href="#" class="status-unhider" @click.prevent="showingTallSubject=false">Show less</a>
+            <a v-if="showingLongSubject" href="#" class="status-unhider" @click.prevent="showingLongSubject=false">Show less</a>
           </div>
           <div :class="{'tall-status': hideTallStatus}" class="status-content-wrapper" v-else>
             <a class="tall-status-hider" :class="{ 'tall-status-hider_focused': isFocused }" v-if="hideTallStatus" href="#" @click.prevent="toggleShowMore">Show more</a>
@@ -98,7 +98,7 @@
             <a v-if="showingMore" href="#" class="status-unhider" @click.prevent="toggleShowMore">Show less</a>
           </div>
 
-          <div v-if="status.attachments && (!hideSubjectStatus || showingTallSubject)" class="attachments media-body">
+          <div v-if="status.attachments && (!hideSubjectStatus || showingLongSubject)" class="attachments media-body">
             <attachment
               class="non-gallery"
               v-for="attachment in nonGalleryAttachments"

From 97fbc1d402e611103787abaa0a63b1c7fef47bd0 Mon Sep 17 00:00:00 2001
From: dave <starpumadev@gmail.com>
Date: Mon, 4 Feb 2019 10:45:26 -0500
Subject: [PATCH 16/16] #312 - media uploader not working with same file in
 adjacent order

---
 src/components/media_upload/media_upload.js   | 25 +++++++++++--------
 src/components/media_upload/media_upload.vue  |  2 +-
 .../post_status_form/post_status_form.js      |  1 +
 .../post_status_form/post_status_form.vue     |  2 +-
 4 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/src/components/media_upload/media_upload.js b/src/components/media_upload/media_upload.js
index 42d900d3..1c874faa 100644
--- a/src/components/media_upload/media_upload.js
+++ b/src/components/media_upload/media_upload.js
@@ -3,19 +3,10 @@ import statusPosterService from '../../services/status_poster/status_poster.serv
 import fileSizeFormatService from '../../services/file_size_format/file_size_format.js'
 
 const mediaUpload = {
-  mounted () {
-    const input = this.$el.querySelector('input')
-
-    input.addEventListener('change', ({target}) => {
-      for (var i = 0; i < target.files.length; i++) {
-        let file = target.files[i]
-        this.uploadFile(file)
-      }
-    })
-  },
   data () {
     return {
-      uploading: false
+      uploading: false,
+      uploadReady: true
     }
   },
   methods: {
@@ -56,6 +47,18 @@ const mediaUpload = {
       } else {
         e.dataTransfer.dropEffect = 'none'
       }
+    },
+    clearFile () {
+      this.uploadReady = false
+      this.$nextTick(() => {
+        this.uploadReady = true
+      })
+    },
+    change ({target}) {
+      for (var i = 0; i < target.files.length; i++) {
+        let file = target.files[i]
+        this.uploadFile(file)
+      }
     }
   },
   props: [
diff --git a/src/components/media_upload/media_upload.vue b/src/components/media_upload/media_upload.vue
index 768d3565..fcdc3471 100644
--- a/src/components/media_upload/media_upload.vue
+++ b/src/components/media_upload/media_upload.vue
@@ -3,7 +3,7 @@
     <label class="btn btn-default" :title="$t('tool_tip.media_upload')">
       <i class="icon-spin4 animate-spin" v-if="uploading"></i>
       <i class="icon-upload" v-if="!uploading"></i>
-      <input type="file" style="position: fixed; top: -100em" multiple="true"></input>
+      <input type="file" v-if="uploadReady" @change="change" style="position: fixed; top: -100em" multiple="true"></input>
     </label>
   </div>
 </template>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 88bc736f..5e8c2252 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -250,6 +250,7 @@ const PostStatusForm = {
             visibility: newStatus.visibility,
             contentType: newStatus.contentType
           }
+          this.$refs.mediaUpload.clearFile()
           this.$emit('posted')
           let el = this.$el.querySelector('textarea')
           el.style.height = 'auto'
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 398f1871..e09ad37f 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -64,7 +64,7 @@
         </div>
       </div>
       <div class='form-bottom'>
-        <media-upload @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload>
+        <media-upload ref="mediaUpload" @uploading="disableSubmit" @uploaded="addMediaFile" @upload-failed="uploadFailed" :drop-files="dropFiles"></media-upload>
 
         <p v-if="isOverLengthLimit" class="error">{{ charactersLeft }}</p>
         <p class="faint" v-else-if="hasStatusLengthLimit">{{ charactersLeft }}</p>