From 0582f19e7c2c6f916b427d5ecfbbb571178ce841 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Fri, 6 Aug 2021 20:18:27 -0400
Subject: Add tree-style thread display

---
 src/components/thread_tree/thread_tree.vue | 55 ++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
 create mode 100644 src/components/thread_tree/thread_tree.vue

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
new file mode 100644
index 00000000..8256eee6
--- /dev/null
+++ b/src/components/thread_tree/thread_tree.vue
@@ -0,0 +1,55 @@
+<template>
+  <div class="thread-tree panel-body">
+    <status
+      :key="status.id"
+      ref="statusComponent"
+      :inline-expanded="collapsable && isExpanded"
+      :statusoid="status"
+      :expandable="!isExpanded"
+      :show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
+      :focused="focused(status.id)"
+      :in-conversation="isExpanded"
+      :highlight="getHighlight()"
+      :replies="getReplies(status.id)"
+      :in-profile="inProfile"
+      :profile-user-id="profileUserId"
+      class="conversation-status status-fadein panel-body"
+      @goto="setHighlight"
+      @toggleExpanded="toggleExpanded"
+    />
+    <div
+      v-if="currentReplies.length"
+      class="thread-tree-replies"
+    >
+      <thread-tree
+        v-for="replyStatus in currentReplies"
+        :key="replyStatus.id"
+        ref="childComponent"
+        :status="replyStatus"
+
+        :in-profile="inProfile"
+        :conversation="conversation"
+        :collapsable="collapsable"
+        :is-expanded="isExpanded"
+        :pinned-status-ids-object="pinnedStatusIdsObject"
+        :profile-user-id="profileUserId"
+
+        :focused="focused"
+        :get-replies="getReplies"
+        :get-highlight="getHighlight"
+        :set-highlight="setHighlight"
+        :toggle-expanded="toggleExpanded"
+
+        class="conversation-status status-fadein panel-body"
+      />
+    </div>
+  </div>
+</template>
+
+<script src="./thread_tree.js"></script>
+
+<style lang="scss">
+.thread-tree-replies {
+  margin-left: 1em;
+}
+</style>
-- 
cgit v1.2.3-70-g09d2


From 0f2fd8a3523e9e2cd1ca6fe287eb7304895f2cba Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sat, 7 Aug 2021 00:33:06 -0400
Subject: Implement thread folding/expanding

---
 src/components/conversation/conversation.js  | 105 +++++++++++++++++++++++++--
 src/components/conversation/conversation.vue |   7 ++
 src/components/status/status.js              |  22 +++++-
 src/components/status/status.vue             |  13 ++++
 src/components/thread_tree/thread_tree.js    |  12 ++-
 src/components/thread_tree/thread_tree.vue   |  35 ++++++++-
 6 files changed, 180 insertions(+), 14 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index e663ba15..0abb7abd 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -38,7 +38,8 @@ const conversation = {
   data () {
     return {
       highlight: null,
-      expanded: false
+      expanded: false,
+      threadDisplayStatusObject: {} // id => 'showing' | 'hidden'
     }
   },
   props: [
@@ -56,6 +57,9 @@ const conversation = {
     }
   },
   computed: {
+    maxDepthToShowByDefault () {
+      return 4
+    },
     displayStyle () {
       return this.$store.state.config.conversationDisplay
     },
@@ -112,15 +116,14 @@ const conversation = {
         const id = cur.id
         a.forest[id] = this.getReplies(id)
           .map(s => s.id)
-          .sort((a, b) => reverseLookupTable[a] - reverseLookupTable[b])
 
-        a.topLevel = a.topLevel.filter(k => a.forest[id].contains(k))
         return a
       }, {
         forest: {},
-        topLevel: this.conversation.map(s => s.id)
       })
 
+      debug('threads = ', threads)
+
       const walk = (forest, topLevel, depth = 0, processed = {}) => topLevel.map(id => {
         if (processed[id]) {
           return []
@@ -131,18 +134,63 @@ const conversation = {
           status: this.conversation[reverseLookupTable[id]],
           id,
           depth
-        }, walk(forest, forest[child], depth + 1, processed)].reduce((a, b) => a.concat(b), [])
+        }, walk(forest, forest[id], depth + 1, processed)].reduce((a, b) => a.concat(b), [])
       }).reduce((a, b) => a.concat(b), [])
 
-      const linearized = walk(threads.forest, threads.topLevel)
+      const linearized = walk(threads.forest, this.topLevel.map(k => k.id))
 
       return linearized
     },
+    replyIds () {
+      return this.conversation.map(k => k.id)
+        .reduce((res, id) => {
+          res[id] = (this.replies[id] || []).map(k => k.id)
+          return res
+        }, {})
+    },
+    totalReplyCount () {
+      debug('replyIds=', this.replyIds)
+      const sizes = {}
+      const subTreeSizeFor = (id) => {
+        if (sizes[id]) {
+          return sizes[id]
+        }
+        sizes[id] = 1 + this.replyIds[id].map(cid => subTreeSizeFor(cid)).reduce((a, b) => a + b, 0)
+        return sizes[id]
+      }
+      this.conversation.map(k => k.id).map(subTreeSizeFor)
+      debug('totalReplyCount=', sizes)
+      return Object.keys(sizes).reduce((res, id) => {
+        res[id] = sizes[id] - 1 // exclude itself
+        return res
+      }, {})
+    },
+    totalReplyDepth () {
+      const depths = {}
+      const subTreeDepthFor = (id) => {
+        if (depths[id]) {
+          return depths[id]
+        }
+        depths[id] = 1 + this.replyIds[id].map(cid => subTreeDepthFor(cid)).reduce((a, b) => a > b ? a : b, 0)
+        return depths[id]
+      }
+      this.conversation.map(k => k.id).map(subTreeDepthFor)
+      return Object.keys(depths).reduce((res, id) => {
+        res[id] = depths[id] - 1 // exclude itself
+        return res
+      }, {})
+    },
+    depths () {
+      debug('threadTree', this.threadTree)
+      return this.threadTree.reduce((a, k) => {
+        a[k.id] = k.depth
+        return a
+      }, {})
+    },
     topLevel () {
       const topLevel = this.conversation.reduce((tl, cur) =>
         tl.filter(k => this.getReplies(cur.id).map(v => v.id).indexOf(k.id) === -1), this.conversation)
       debug("toplevel =", topLevel)
-      debug("toplevel =", topLevel)
       return topLevel
     },
     replies () {
@@ -169,6 +217,25 @@ const conversation = {
     hiddenStyle () {
       const height = (this.status && this.status.virtualHeight) || '120px'
       return this.virtualHidden ? { height } : {}
+    },
+    threadDisplayStatus () {
+      return this.conversation.reduce((a, k) => {
+        const id = k.id
+        const depth = this.depths[id]
+        const status = (() => {
+          if (this.threadDisplayStatusObject[id]) {
+            return this.threadDisplayStatusObject[id]
+          }
+          if (depth <= this.maxDepthToShowByDefault) {
+            return 'showing'
+          } else {
+            return 'hidden'
+          }
+        })()
+
+        a[id] = status
+        return a
+      }, {})
     }
   },
   components: {
@@ -235,6 +302,30 @@ const conversation = {
     getConversationId (statusId) {
       const status = this.$store.state.statuses.allStatusesObject[statusId]
       return get(status, 'retweeted_status.statusnet_conversation_id', get(status, 'statusnet_conversation_id'))
+    },
+    setThreadDisplay (id, nextStatus) {
+      this.threadDisplayStatusObject = {
+        ...this.threadDisplayStatusObject,
+        [id]: nextStatus
+      }
+    },
+    toggleThreadDisplay (id) {
+      const depth = this.depths[id]
+      debug('depth = ', depth)
+      debug(
+        'threadDisplayStatus = ', this.threadDisplayStatus,
+        'threadDisplayStatusObject = ', this.threadDisplayStatusObject)
+      const curStatus = this.threadDisplayStatus[id]
+      const nextStatus = curStatus === 'showing' ? 'hidden' : 'showing'
+      debug('toggling', id, 'to', nextStatus)
+      this.setThreadDisplay(id, nextStatus)
+    },
+    setThreadDisplayRecursively (id, nextStatus) {
+      this.setThreadDisplay(id, nextStatus)
+      this.getReplies(id).map(k => k.id).map(id => this.setThreadDisplayRecursively(id, nextStatus))
+    },
+    showThreadRecursively (id) {
+      this.setThreadDisplayRecursively(id, 'showing')
     }
   }
 }
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index cea5f88f..783cc894 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -23,6 +23,7 @@
         v-for="status in topLevel"
         :key="status.id"
         ref="statusComponent"
+        :depth="0"
 
         :status="status"
         :in-profile="inProfile"
@@ -37,6 +38,12 @@
         :get-highlight="getHighlight"
         :set-highlight="setHighlight"
         :toggle-expanded="toggleExpanded"
+
+        :toggle-thread-display="toggleThreadDisplay"
+        :thread-display-status="threadDisplayStatus"
+        :show-thread-recursively="showThreadRecursively"
+        :total-reply-count="totalReplyCount"
+        :total-reply-depth="totalReplyDepth"
       />
     </div>
     <div v-if="isLinearView">
diff --git a/src/components/status/status.js b/src/components/status/status.js
index d8f94926..9d423631 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -35,7 +35,9 @@ import {
   faStar,
   faEyeSlash,
   faEye,
-  faThumbtack
+  faThumbtack,
+  faAngleDoubleUp,
+  faAngleDoubleDown
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
@@ -52,7 +54,9 @@ library.add(
   faEllipsisH,
   faEyeSlash,
   faEye,
-  faThumbtack
+  faThumbtack,
+  faAngleDoubleUp,
+  faAngleDoubleDown
 )
 
 const Status = {
@@ -89,7 +93,10 @@ const Status = {
     'inlineExpanded',
     'showPinned',
     'inProfile',
-    'profileUserId'
+    'profileUserId',
+
+    'controlledThreadDisplayStatus',
+    'controlledToggleThreadDisplay'
   ],
   data () {
     return {
@@ -304,6 +311,12 @@ const Status = {
     },
     isSuspendable () {
       return !this.replying && this.mediaPlaying.length === 0
+    },
+    inThreadForest () {
+      return !!this.controlledThreadDisplayStatus
+    },
+    threadShowing () {
+      return this.controlledThreadDisplayStatus === 'showing'
     }
   },
   methods: {
@@ -353,6 +366,9 @@ const Status = {
     },
     setHeadTailLinks (headTailLinks) {
       this.headTailLinks = headTailLinks
+    },
+    toggleThreadDisplay () {
+      this.controlledToggleThreadDisplay()
     }
   },
   watch: {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 3bb29db6..2ebf5638 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -219,6 +219,19 @@
                     class="fa-scale-110"
                   />
                 </button>
+                <button
+                  v-if="inThreadForest && replies && replies.length"
+                  class="button-unstyled"
+                  :title="threadShowing ? $t('status.thread_hide') : $t('status.thread_show')"
+                  :aria-expanded="threadShowing ? 'true' : 'false'"
+                  @click.prevent="toggleThreadDisplay"
+                >
+                  <FAIcon
+                    fixed-width
+                    class="fa-scale-110"
+                    :icon="threadShowing ? 'angle-double-up' : 'angle-double-down'"
+                  />
+                </button>
               </span>
             </div>
             <div
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
index 4f95122a..88b60109 100644
--- a/src/components/thread_tree/thread_tree.js
+++ b/src/components/thread_tree/thread_tree.js
@@ -21,7 +21,14 @@ const ThreadTree = {
     getHighlight: Function,
     getReplies: Function,
     setHighlight: Function,
-    toggleExpanded: Function
+    toggleExpanded: Function,
+
+    // to control display of the whole thread forest
+    toggleThreadDisplay: Function,
+    threadDisplayStatus: Object,
+    showThreadRecursively: Function,
+    totalReplyCount: Object,
+    totalReplyDepth: Object
   },
   computed: {
     reverseLookupTable () {
@@ -35,6 +42,9 @@ const ThreadTree = {
       debug('getReplies:', this.getReplies(this.status.id))
       return this.getReplies(this.status.id).map(({ id }) => this.statusById(id))
     },
+    threadShowing () {
+      return this.threadDisplayStatus[this.status.id] === 'showing'
+    }
   },
   methods: {
     statusById (id) {
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 8256eee6..9f591585 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -13,18 +13,23 @@
       :replies="getReplies(status.id)"
       :in-profile="inProfile"
       :profile-user-id="profileUserId"
-      class="conversation-status status-fadein panel-body"
+      class="conversation-status conversation-status-treeview status-fadein panel-body"
+
+      :controlled-thread-display-status="threadDisplayStatus[status.id]"
+      :controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)"
+
       @goto="setHighlight"
       @toggleExpanded="toggleExpanded"
     />
     <div
-      v-if="currentReplies.length"
+      v-if="currentReplies.length && threadShowing"
       class="thread-tree-replies"
     >
       <thread-tree
         v-for="replyStatus in currentReplies"
         :key="replyStatus.id"
         ref="childComponent"
+        :depth="depth + 1"
         :status="replyStatus"
 
         :in-profile="inProfile"
@@ -40,16 +45,40 @@
         :set-highlight="setHighlight"
         :toggle-expanded="toggleExpanded"
 
-        class="conversation-status status-fadein panel-body"
+        :toggle-thread-display="toggleThreadDisplay"
+        :thread-display-status="threadDisplayStatus"
+        :show-thread-recursively="showThreadRecursively"
+        :total-reply-count="totalReplyCount"
+        :total-reply-depth="totalReplyDepth"
       />
     </div>
+    <div
+      v-if="currentReplies.length && !threadShowing"
+      class="thread-tree-replies thread-tree-replies-hidden"
+    >
+      <button
+        class="button-unstyled -link thread-tree-show-replies-button"
+        @click="showThreadRecursively(status.id)"
+      >
+        {{ $t('status.thread_show_full', { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
+      </button>
+    </div>
   </div>
 </template>
 
 <script src="./thread_tree.js"></script>
 
 <style lang="scss">
+@import '../../_variables.scss';
 .thread-tree-replies {
   margin-left: 1em;
 }
+.thread-tree-replies-hidden {
+  padding: 1em;
+  border-bottom: 1px solid var(--border, #222);
+}
+.conversation-status.conversation-status-treeview:last-child,
+.Conversation.-expanded .conversation-status.conversation-status-treeview:last-child {
+  border-bottom: 1px solid var(--border, #222);
+}
 </style>
-- 
cgit v1.2.3-70-g09d2


From 414ee55957851a30b9455e47e1e6d258743953a3 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sat, 7 Aug 2021 01:05:26 -0400
Subject: Make show full thread message account for numbers

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

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 9f591585..bbdda6fb 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -60,7 +60,7 @@
         class="button-unstyled -link thread-tree-show-replies-button"
         @click="showThreadRecursively(status.id)"
       >
-        {{ $t('status.thread_show_full', { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
+        {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
       </button>
     </div>
   </div>
-- 
cgit v1.2.3-70-g09d2


From ace1f5067c90be2fa0b8da22d39b0e2c88f590fb Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sat, 7 Aug 2021 10:28:45 -0400
Subject: Make status display controlled

---
 src/components/conversation/conversation.js     | 37 +++++++++++++++-
 src/components/conversation/conversation.vue    |  3 ++
 src/components/status/status.js                 |  9 +++-
 src/components/status/status.vue                |  6 +++
 src/components/status_content/status_content.js | 59 ++++++++++++++++++++++++-
 src/components/thread_tree/thread_tree.js       | 11 ++++-
 src/components/thread_tree/thread_tree.vue      | 10 +++++
 7 files changed, 130 insertions(+), 5 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 0abb7abd..6fc86b2c 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -2,7 +2,8 @@ import { reduce, filter, findIndex, clone, get } from 'lodash'
 import Status from '../status/status.vue'
 import ThreadTree from '../thread_tree/thread_tree.vue'
 
-const debug = console.log
+// const debug = console.log
+const debug = () => {}
 
 const sortById = (a, b) => {
   const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id
@@ -39,7 +40,8 @@ const conversation = {
     return {
       highlight: null,
       expanded: false,
-      threadDisplayStatusObject: {} // id => 'showing' | 'hidden'
+      threadDisplayStatusObject: {}, // id => 'showing' | 'hidden'
+      statusContentPropertiesObject: {}
     }
   },
   props: [
@@ -236,6 +238,25 @@ const conversation = {
         a[id] = status
         return a
       }, {})
+    },
+    statusContentProperties () {
+      return this.conversation.reduce((a, k) => {
+        const id = k.id
+        const depth = this.depths[id]
+        const props = (() => {
+          if (this.statusContentPropertiesObject[id]) {
+            return this.statusContentPropertiesObject[id]
+          }
+          return {
+            showingTall: false,
+            expandingSubject: false,
+            showingLongSubject: false,
+          }
+        })()
+
+        a[id] = props
+        return a
+      }, {})
     }
   },
   components: {
@@ -326,6 +347,18 @@ const conversation = {
     },
     showThreadRecursively (id) {
       this.setThreadDisplayRecursively(id, 'showing')
+    },
+    setStatusContentProperty (id, name, value) {
+      this.statusContentPropertiesObject = {
+        ...this.statusContentPropertiesObject,
+        [id]: {
+          ...this.statusContentPropertiesObject[id],
+          [name]: value
+        }
+      }
+    },
+    toggleStatusContentProperty (id, name) {
+      this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
     }
   }
 }
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 783cc894..08cb72d0 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -44,6 +44,9 @@
         :show-thread-recursively="showThreadRecursively"
         :total-reply-count="totalReplyCount"
         :total-reply-depth="totalReplyDepth"
+        :status-content-properties="statusContentProperties"
+        :set-status-content-property="setStatusContentProperty"
+        :toggle-status-content-property="toggleStatusContentProperty"
       />
     </div>
     <div v-if="isLinearView">
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 9d423631..d5ee7d4e 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -96,7 +96,14 @@ const Status = {
     'profileUserId',
 
     'controlledThreadDisplayStatus',
-    'controlledToggleThreadDisplay'
+    'controlledToggleThreadDisplay',
+
+    'controlledShowingTall',
+    'controlledToggleShowingTall',
+    'controlledExpandingSubject',
+    'controlledToggleExpandingSubject',
+    'controlledShowingLongSubject',
+    'controlledToggleShowingLongSubject'
   ],
   data () {
     return {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 2ebf5638..8fdebe44 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -319,6 +319,12 @@
             :no-heading="noHeading"
             :highlight="highlight"
             :focused="isFocused"
+            :controlled-showing-tall="controlledShowingTall"
+            :controlled-expanding-subject="controlledExpandingSubject"
+            :controlled-showing-long-subject="controlledShowingLongSubject"
+            :controlled-toggle-showing-tall="controlledToggleShowingTall"
+            :controlled-toggle-expanding-subject="controlledToggleExpandingSubject"
+            :controlled-toggle-showing-long-subject="controlledToggleShowingLongSubject"
             @mediaplay="addMediaPlaying($event)"
             @mediapause="removeMediaPlaying($event)"
             @parseReady="setHeadTailLinks"
diff --git a/src/components/status_content/status_content.js b/src/components/status_content/status_content.js
index dec8914a..65ec85c4 100644
--- a/src/components/status_content/status_content.js
+++ b/src/components/status_content/status_content.js
@@ -23,6 +23,31 @@ library.add(
   faPollH
 )
 
+const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1)
+
+const controlledOrUncontrolledGetters = list => list.reduce((res, name) => {
+  const camelized = camelCase(name)
+  const toggle = `controlledToggle${camelized}`
+  const controlledName = `controlled${camelized}`
+  const uncontrolledName = `uncontrolled${camelized}`
+  res[name] = function () {
+    return this[toggle] ? this[controlledName] : this[uncontrolledName]
+  }
+  return res
+}, {})
+
+const controlledOrUncontrolledToggle = (obj, name) => {
+  const camelized = camelCase(name)
+  const toggle = `controlledToggle${camelized}`
+  const controlledName = `controlled${camelized}`
+  const uncontrolledName = `uncontrolled${camelized}`
+  if (obj[toggle]) {
+    obj[toggle]()
+  } else {
+    obj[uncontrolledName] = !obj[uncontrolledName]
+  }
+}
+
 const StatusContent = {
   name: 'StatusContent',
   props: [
@@ -31,9 +56,22 @@ const StatusContent = {
     'focused',
     'noHeading',
     'fullContent',
-    'singleLine'
+    'singleLine',
+    'controlledShowingTall',
+    'controlledExpandingSubject',
+    'controlledToggleShowingTall',
+    'controlledToggleExpandingSubject'
   ],
+  data () {
+    return {
+      uncontrolledShowingTall: this.fullContent || (this.inConversation && this.focused),
+      uncontrolledShowingLongSubject: false,
+      // not as computed because it sets the initial state which will be changed later
+      uncontrolledExpandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject
+    }
+  },
   computed: {
+    ...controlledOrUncontrolledGetters(['showingTall', 'expandingSubject', 'showingLongSubject']),
     hideAttachments () {
       return (this.mergedConfig.hideAttachments && !this.inConversation) ||
         (this.mergedConfig.hideAttachmentsInConv && this.inConversation)
@@ -71,6 +109,25 @@ const StatusContent = {
     Gallery,
     LinkPreview,
     StatusBody
+  },
+  methods: {
+    toggleShowingTall () {
+      controlledOrUncontrolledToggle(this, 'showingTall')
+    },
+    toggleExpandingSubject () {
+      controlledOrUncontrolledToggle(this, 'expandingSubject')
+    },
+    toggleShowMore () {
+      if (this.mightHideBecauseTall) {
+        this.toggleShowingTall()
+      } else if (this.mightHideBecauseSubject) {
+        this.toggleExpandingSubject()
+      }
+    },
+    setMedia () {
+      const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments
+      return () => this.$store.dispatch('setMedia', attachments)
+    }
   }
 }
 
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
index 88b60109..46245bdf 100644
--- a/src/components/thread_tree/thread_tree.js
+++ b/src/components/thread_tree/thread_tree.js
@@ -28,7 +28,10 @@ const ThreadTree = {
     threadDisplayStatus: Object,
     showThreadRecursively: Function,
     totalReplyCount: Object,
-    totalReplyDepth: Object
+    totalReplyDepth: Object,
+    statusContentProperties: Object,
+    setStatusContentProperty: Function,
+    toggleStatusContentProperty: Function
   },
   computed: {
     reverseLookupTable () {
@@ -44,6 +47,9 @@ const ThreadTree = {
     },
     threadShowing () {
       return this.threadDisplayStatus[this.status.id] === 'showing'
+    },
+    currentProp () {
+      return this.statusContentProperties[this.status.id]
     }
   },
   methods: {
@@ -55,6 +61,9 @@ const ThreadTree = {
     showThread () {
     },
     showAllSubthreads () {
+    },
+    toggleCurrentProp (name) {
+      this.toggleStatusContentProperty(this.status.id, name)
     }
   }
 }
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index bbdda6fb..d7077bfd 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -18,6 +18,13 @@
       :controlled-thread-display-status="threadDisplayStatus[status.id]"
       :controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)"
 
+      :controlled-showing-tall="currentProp.showingTall"
+      :controlled-expanding-subject="currentProp.expandingSubject"
+      :controlled-showing-long-subject="currentProp.showingLongSubject"
+      :controlled-toggle-showing-tall="() => toggleCurrentProp('ShowingTall')"
+      :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')"
+      :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')"
+
       @goto="setHighlight"
       @toggleExpanded="toggleExpanded"
     />
@@ -50,6 +57,9 @@
         :show-thread-recursively="showThreadRecursively"
         :total-reply-count="totalReplyCount"
         :total-reply-depth="totalReplyDepth"
+        :status-content-properties="statusContentProperties"
+        :set-status-content-property="setStatusContentProperty"
+        :toggle-status-content-property="toggleStatusContentProperty"
       />
     </div>
     <div
-- 
cgit v1.2.3-70-g09d2


From 84a3cd92a3da885fe1a76809c589b8f464eed432 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sat, 7 Aug 2021 11:59:10 -0400
Subject: Support diving into one status in a conversation

---
 src/components/conversation/conversation.js  | 32 +++++++++++++++++++++++++++-
 src/components/conversation/conversation.vue | 30 +++++++++++++++++++++++++-
 src/components/status/status.js              | 13 ++++++-----
 src/components/status/status.vue             | 14 +++++++++++-
 src/components/thread_tree/thread_tree.js    |  3 ++-
 src/components/thread_tree/thread_tree.vue   | 15 +++++++++----
 6 files changed, 94 insertions(+), 13 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 6fc86b2c..584f310c 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -2,6 +2,17 @@ import { reduce, filter, findIndex, clone, get } from 'lodash'
 import Status from '../status/status.vue'
 import ThreadTree from '../thread_tree/thread_tree.vue'
 
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+  faAngleDoubleDown,
+  faAngleDoubleLeft
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faAngleDoubleDown,
+  faAngleDoubleLeft
+)
+
 // const debug = console.log
 const debug = () => {}
 
@@ -41,7 +52,8 @@ const conversation = {
       highlight: null,
       expanded: false,
       threadDisplayStatusObject: {}, // id => 'showing' | 'hidden'
-      statusContentPropertiesObject: {}
+      statusContentPropertiesObject: {},
+      diveRoot: null
     }
   },
   props: [
@@ -195,6 +207,18 @@ const conversation = {
       debug("toplevel =", topLevel)
       return topLevel
     },
+    showingTopLevel () {
+      if (this.diveRoot) {
+        return [this.conversation.filter(k => this.diveRoot === k.id)[0]]
+      }
+      return this.topLevel
+    },
+    diveDepth () {
+      return this.diveRoot ? this.depths[this.diveRoot] : 0
+    },
+    diveMode () {
+      return !!this.diveRoot
+    },
     replies () {
       let i = 1
       // eslint-disable-next-line camelcase
@@ -359,6 +383,12 @@ const conversation = {
     },
     toggleStatusContentProperty (id, name) {
       this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
+    },
+    diveIntoStatus (id) {
+      this.diveRoot = id
+    },
+    undive () {
+      this.diveRoot = null
     }
   }
 }
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 08cb72d0..84e8d8b2 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -18,9 +18,22 @@
         {{ $t('timeline.collapse') }}
       </button>
     </div>
+    <div
+      v-if="diveMode"
+      class="conversation-undive-box"
+    >
+      <i18n
+        path="status.show_all_conversation"
+        tag="button"
+        class="button-unstyled -link"
+        @click.prevent="undive"
+      >
+        <FAIcon icon="angle-double-left" />
+      </i18n>
+    </div>
     <div v-if="isTreeView">
       <thread-tree
-        v-for="status in topLevel"
+        v-for="status in showingTopLevel"
         :key="status.id"
         ref="statusComponent"
         :depth="0"
@@ -47,6 +60,7 @@
         :status-content-properties="statusContentProperties"
         :set-status-content-property="setStatusContentProperty"
         :toggle-status-content-property="toggleStatusContentProperty"
+        :dive="diveIntoStatus"
       />
     </div>
     <div v-if="isLinearView">
@@ -65,6 +79,16 @@
         :in-profile="inProfile"
         :profile-user-id="profileUserId"
         class="conversation-status status-fadein panel-body"
+
+        :toggle-thread-display="toggleThreadDisplay"
+        :thread-display-status="threadDisplayStatus"
+        :show-thread-recursively="showThreadRecursively"
+        :total-reply-count="totalReplyCount"
+        :total-reply-depth="totalReplyDepth"
+        :status-content-properties="statusContentProperties"
+        :set-status-content-property="setStatusContentProperty"
+        :toggle-status-content-property="toggleStatusContentProperty"
+
         @goto="setHighlight"
         @toggleExpanded="toggleExpanded"
       />
@@ -82,6 +106,10 @@
 @import '../../_variables.scss';
 
 .Conversation {
+  .conversation-undive-box {
+    padding: 1em;
+  }
+  .conversation-undive-box,
   .conversation-status {
     border-bottom-width: 1px;
     border-bottom-style: solid;
diff --git a/src/components/status/status.js b/src/components/status/status.js
index d5ee7d4e..f119f42e 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -36,8 +36,9 @@ import {
   faEyeSlash,
   faEye,
   faThumbtack,
-  faAngleDoubleUp,
-  faAngleDoubleDown
+  faChevronUp,
+  faChevronDown,
+  faAngleDoubleRight
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
@@ -55,8 +56,9 @@ library.add(
   faEyeSlash,
   faEye,
   faThumbtack,
-  faAngleDoubleUp,
-  faAngleDoubleDown
+  faChevronUp,
+  faChevronDown,
+  faAngleDoubleRight
 )
 
 const Status = {
@@ -103,7 +105,8 @@ const Status = {
     'controlledExpandingSubject',
     'controlledToggleExpandingSubject',
     'controlledShowingLongSubject',
-    'controlledToggleShowingLongSubject'
+    'controlledToggleShowingLongSubject',
+    'dive'
   ],
   data () {
     return {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 8fdebe44..c2df6021 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -229,7 +229,19 @@
                   <FAIcon
                     fixed-width
                     class="fa-scale-110"
-                    :icon="threadShowing ? 'angle-double-up' : 'angle-double-down'"
+                    :icon="threadShowing ? 'chevron-up' : 'chevron-down'"
+                  />
+                </button>
+                <button
+                  v-if="dive"
+                  class="button-unstyled"
+                  :title="$t('status.show_only_conversation_under_this')"
+                  @click.prevent="dive"
+                >
+                  <FAIcon
+                    fixed-width
+                    class="fa-scale-110"
+                    :icon="'angle-double-right'"
                   />
                 </button>
               </span>
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
index 46245bdf..3e8eedb1 100644
--- a/src/components/thread_tree/thread_tree.js
+++ b/src/components/thread_tree/thread_tree.js
@@ -31,7 +31,8 @@ const ThreadTree = {
     totalReplyDepth: Object,
     statusContentProperties: Object,
     setStatusContentProperty: Function,
-    toggleStatusContentProperty: Function
+    toggleStatusContentProperty: Function,
+    dive: Function
   },
   computed: {
     reverseLookupTable () {
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index d7077bfd..adf7bcdf 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -24,6 +24,7 @@
       :controlled-toggle-showing-tall="() => toggleCurrentProp('ShowingTall')"
       :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')"
       :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')"
+      :dive="dive ? () => dive(status.id) : undefined"
 
       @goto="setHighlight"
       @toggleExpanded="toggleExpanded"
@@ -60,18 +61,24 @@
         :status-content-properties="statusContentProperties"
         :set-status-content-property="setStatusContentProperty"
         :toggle-status-content-property="toggleStatusContentProperty"
+        :dive="dive"
       />
     </div>
     <div
       v-if="currentReplies.length && !threadShowing"
       class="thread-tree-replies thread-tree-replies-hidden"
     >
-      <button
+      <i18n
+        tag="button"
+        path="status.thread_show_full_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
-        @click="showThreadRecursively(status.id)"
+        @click.prevent="showThreadRecursively(status.id)"
       >
-        {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
-      </button>
+        <FAIcon place="icon" icon="angle-double-down" />
+        <span place="text">
+          {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
+        </span>
+      </i18n>
     </div>
   </div>
 </template>
-- 
cgit v1.2.3-70-g09d2


From d15d24c11c57ecfc49705af648b1e8f73caec51e Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sat, 7 Aug 2021 14:11:34 -0400
Subject: Add dive functionality

---
 src/components/conversation/conversation.js  | 69 ++++++++++++++++++++++++----
 src/components/conversation/conversation.vue | 15 +++++-
 src/components/status/status.vue             |  2 +-
 src/components/thread_tree/thread_tree.js    |  3 +-
 src/components/thread_tree/thread_tree.vue   |  5 +-
 5 files changed, 80 insertions(+), 14 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 584f310c..b2af1d6c 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -5,12 +5,14 @@ import ThreadTree from '../thread_tree/thread_tree.vue'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
   faAngleDoubleDown,
-  faAngleDoubleLeft
+  faAngleDoubleLeft,
+  faChevronLeft
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
   faAngleDoubleDown,
-  faAngleDoubleLeft
+  faAngleDoubleLeft,
+  faChevronLeft
 )
 
 // const debug = console.log
@@ -53,7 +55,7 @@ const conversation = {
       expanded: false,
       threadDisplayStatusObject: {}, // id => 'showing' | 'hidden'
       statusContentPropertiesObject: {},
-      diveRoot: null
+      diveHistory: []
     }
   },
   props: [
@@ -120,6 +122,14 @@ const conversation = {
 
       return sortAndFilterConversation(conversation, this.status)
     },
+    conversationDive () {
+    },
+    statusMap () {
+      return this.conversation.reduce((res, s) => {
+        res[s.id] = s
+        return res
+      }, {})
+    },
     threadTree () {
       const reverseLookupTable = this.conversation.reduce((table, status, index) => {
         table[status.id] = index
@@ -208,16 +218,19 @@ const conversation = {
       return topLevel
     },
     showingTopLevel () {
-      if (this.diveRoot) {
-        return [this.conversation.filter(k => this.diveRoot === k.id)[0]]
+      if (this.canDive && this.diveRoot) {
+        return [this.statusMap[this.diveRoot]]
       }
       return this.topLevel
     },
+    diveRoot () {
+      return this.diveHistory[this.diveHistory.length - 1]
+    },
     diveDepth () {
-      return this.diveRoot ? this.depths[this.diveRoot] : 0
+      return this.canDive && this.diveRoot ? this.depths[this.diveRoot] : 0
     },
     diveMode () {
-      return !!this.diveRoot
+      return this.canDive && !!this.diveRoot
     },
     replies () {
       let i = 1
@@ -252,7 +265,7 @@ const conversation = {
           if (this.threadDisplayStatusObject[id]) {
             return this.threadDisplayStatusObject[id]
           }
-          if (depth <= this.maxDepthToShowByDefault) {
+          if ((depth - this.diveDepth) <= this.maxDepthToShowByDefault) {
             return 'showing'
           } else {
             return 'hidden'
@@ -281,6 +294,9 @@ const conversation = {
         a[id] = props
         return a
       }, {})
+    },
+    canDive () {
+      return this.isTreeView && this.isExpanded
     }
   },
   components: {
@@ -310,6 +326,25 @@ const conversation = {
     }
   },
   methods: {
+    conversationFetched () {
+      if (!this.isExpanded) {
+        return
+      }
+
+      if (!this._diven) {
+        if (!this.threadDisplayStatus[this.statusId]) {
+          return
+        }
+        this._diven = true
+        const parentOrSelf = this.parentOrSelf(this.originalStatusId)
+        console.log(
+          'this.threadDisplayStatus ', this.threadDisplayStatus,
+          'this.statusId', this.statusId)
+        if (this.threadDisplayStatus[this.statusId] === 'hidden') {
+          this.diveIntoStatus(parentOrSelf)
+        }
+      }
+    },
     fetchConversation () {
       if (this.status) {
         this.$store.state.api.backendInteractor.fetchConversation({ id: this.statusId })
@@ -318,6 +353,7 @@ const conversation = {
             this.$store.dispatch('addNewStatuses', { statuses: descendants })
             this.setHighlight(this.originalStatusId)
           })
+          .then(this.conversationFetched)
       } else {
         this.$store.state.api.backendInteractor.fetchStatus({ id: this.statusId })
           .then((status) => {
@@ -385,10 +421,23 @@ const conversation = {
       this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
     },
     diveIntoStatus (id) {
-      this.diveRoot = id
+      this.diveHistory = [...this.diveHistory, id]
+    },
+    diveBack () {
+      this.diveHistory = [...this.diveHistory.slice(0, this.diveHistory.length - 1)]
     },
     undive () {
-      this.diveRoot = null
+      this.diveHistory = []
+    },
+    statusById (id) {
+      return this.statusMap[id]
+    },
+    parentOf (id) {
+      const { in_reply_to_status_id: parentId } = this.statusById(id)
+      return parentId
+    },
+    parentOrSelf (id) {
+      return this.parentOf(id) || id
     }
   }
 }
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 84e8d8b2..99bc7bcc 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -31,6 +31,19 @@
         <FAIcon icon="angle-double-left" />
       </i18n>
     </div>
+    <div
+      v-if="diveMode"
+      class="conversation-undive-box"
+    >
+      <i18n
+        path="status.return_to_last_showing"
+        tag="button"
+        class="button-unstyled -link"
+        @click.prevent="diveBack"
+      >
+        <FAIcon icon="chevron-left" />
+      </i18n>
+    </div>
     <div v-if="isTreeView">
       <thread-tree
         v-for="status in showingTopLevel"
@@ -60,7 +73,7 @@
         :status-content-properties="statusContentProperties"
         :set-status-content-property="setStatusContentProperty"
         :toggle-status-content-property="toggleStatusContentProperty"
-        :dive="diveIntoStatus"
+        :dive="canDive ? diveIntoStatus : undefined"
       />
     </div>
     <div v-if="isLinearView">
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index c2df6021..47d35de8 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -220,7 +220,7 @@
                   />
                 </button>
                 <button
-                  v-if="inThreadForest && replies && replies.length"
+                  v-if="inThreadForest && replies && replies.length && toggleThreadDisplay"
                   class="button-unstyled"
                   :title="threadShowing ? $t('status.thread_hide') : $t('status.thread_show')"
                   :aria-expanded="threadShowing ? 'true' : 'false'"
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
index 3e8eedb1..ec7d5884 100644
--- a/src/components/thread_tree/thread_tree.js
+++ b/src/components/thread_tree/thread_tree.js
@@ -1,6 +1,7 @@
 import Status from '../status/status.vue'
 
-const debug = console.log
+// const debug = console.log
+const debug = () => {}
 
 const ThreadTree = {
   components: {
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index adf7bcdf..f0a103d1 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -74,7 +74,10 @@
         class="button-unstyled -link thread-tree-show-replies-button"
         @click.prevent="showThreadRecursively(status.id)"
       >
-        <FAIcon place="icon" icon="angle-double-down" />
+        <FAIcon
+          place="icon"
+          icon="angle-double-down"
+        />
         <span place="text">
           {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
         </span>
-- 
cgit v1.2.3-70-g09d2


From d9a9f97751b2f51f55848652e5126700aea0f3fe Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sat, 7 Aug 2021 18:53:23 -0400
Subject: Add simple tree style navigation

---
 src/components/conversation/conversation.js       | 70 ++++++++++++++++++++---
 src/components/conversation/conversation.vue      |  3 +-
 src/components/settings_modal/tabs/general_tab.js |  2 +-
 src/components/status/status.js                   | 16 ++++--
 src/components/status/status.vue                  |  4 +-
 src/components/thread_tree/thread_tree.js         | 14 ++++-
 src/components/thread_tree/thread_tree.vue        | 22 ++++++-
 src/modules/instance.js                           |  2 +-
 8 files changed, 113 insertions(+), 20 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index b2af1d6c..a1991888 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -80,7 +80,10 @@ const conversation = {
       return this.$store.state.config.conversationDisplay
     },
     isTreeView () {
-      return this.displayStyle === 'tree'
+      return this.displayStyle === 'tree' || this.displayStyle === 'simple_tree'
+    },
+    treeViewIsSimple () {
+      return this.displayStyle === 'simple_tree'
     },
     isLinearView () {
       return this.displayStyle === 'linear'
@@ -297,6 +300,14 @@ const conversation = {
     },
     canDive () {
       return this.isTreeView && this.isExpanded
+    },
+    focused () {
+      return (id) => {
+        return (this.isExpanded) && id === this.highlight
+      }
+    },
+    maybeHighlight () {
+      return this.isExpanded ? this.highlight : null
     }
   },
   components: {
@@ -316,6 +327,9 @@ const conversation = {
     expanded (value) {
       if (value) {
         this.fetchConversation()
+      } else {
+        // if we collapse it, we should reset the dive
+        this._diven = false
       }
     },
     virtualHidden (value) {
@@ -323,6 +337,9 @@ const conversation = {
         'setVirtualHeight',
         { statusId: this.statusId, height: `${this.$el.clientHeight}px` }
       )
+    },
+    highlight (value, old) {
+      console.log('highlight:', old, ' => ', value)
     }
   },
   methods: {
@@ -341,7 +358,8 @@ const conversation = {
           'this.threadDisplayStatus ', this.threadDisplayStatus,
           'this.statusId', this.statusId)
         if (this.threadDisplayStatus[this.statusId] === 'hidden') {
-          this.diveIntoStatus(parentOrSelf)
+          this.diveIntoStatus(parentOrSelf, /* preventScroll */ true)
+          this.tryScrollTo(this.statusId)
         }
       }
     },
@@ -365,18 +383,16 @@ const conversation = {
     getReplies (id) {
       return this.replies[id] || []
     },
-    focused (id) {
-      return (this.isExpanded) && id === this.statusId
+    getHighlight () {
+      return this.isExpanded ? this.highlight : null
     },
     setHighlight (id) {
+      console.log('setHighlight', id)
       if (!id) return
       this.highlight = id
       this.$store.dispatch('fetchFavsAndRepeats', id)
       this.$store.dispatch('fetchEmojiReactionsBy', id)
     },
-    getHighlight () {
-      return this.isExpanded ? this.highlight : null
-    },
     toggleExpanded () {
       this.expanded = !this.expanded
     },
@@ -420,14 +436,52 @@ const conversation = {
     toggleStatusContentProperty (id, name) {
       this.setStatusContentProperty(id, name, !this.statusContentProperties[id][name])
     },
-    diveIntoStatus (id) {
+    leastShowingAncestor (id) {
+      let cur = id
+      let parent = this.parentOf(cur)
+      while (cur) {
+        // if the parent is showing it means cur is visible
+        if (this.threadDisplayStatus[parent] === 'showing') {
+          return cur
+        }
+        parent = this.parentOf(parent)
+        cur = this.parentOf(cur)
+      }
+      // nothing found, fall back to toplevel
+      return topLevel[0].id
+    },
+    diveIntoStatus (id, preventScroll) {
       this.diveHistory = [...this.diveHistory, id]
+      if (!preventScroll) {
+        this.goToCurrent()
+      }
     },
     diveBack () {
+      const oldHighlight = this.highlight
       this.diveHistory = [...this.diveHistory.slice(0, this.diveHistory.length - 1)]
+      if (oldHighlight) {
+        this.tryScrollTo(this.leastShowingAncestor(oldHighlight))
+      }
     },
     undive () {
+      const oldHighlight = this.highlight
       this.diveHistory = []
+      if (oldHighlight) {
+        this.tryScrollTo(this.leastShowingAncestor(oldHighlight))
+      } else {
+        this.goToCurrent()
+      }
+    },
+    tryScrollTo (id) {
+      if (this.isPage) {
+        // set statusId
+        this.$router.push({ name: 'conversation', params: { id } })
+      }
+
+      this.setHighlight(id)
+    },
+    goToCurrent () {
+      this.tryScrollTo(this.diveRoot || this.topLevel[0].id)
     },
     statusById (id) {
       return this.statusMap[id]
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 99bc7bcc..0ffd8c37 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -61,10 +61,11 @@
 
         :focused="focused"
         :get-replies="getReplies"
-        :get-highlight="getHighlight"
+        :highlight="maybeHighlight"
         :set-highlight="setHighlight"
         :toggle-expanded="toggleExpanded"
 
+        :simple="treeViewIsSimple"
         :toggle-thread-display="toggleThreadDisplay"
         :thread-display-status="threadDisplayStatus"
         :show-thread-recursively="showThreadRecursively"
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index abe8f6f7..c43abe8a 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -20,7 +20,7 @@ const GeneralTab = {
         value: mode,
         label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
       })),
-      conversationDisplayOptions: ['tree', 'linear'].map(mode => ({
+      conversationDisplayOptions: ['tree', 'simple_tree', 'linear'].map(mode => ({
         key: mode,
         value: mode,
         label: this.$t(`settings.conversation_display_${mode}`)
diff --git a/src/components/status/status.js b/src/components/status/status.js
index f119f42e..15c2d029 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -97,6 +97,7 @@ const Status = {
     'inProfile',
     'profileUserId',
 
+    'simpleTree',
     'controlledThreadDisplayStatus',
     'controlledToggleThreadDisplay',
 
@@ -379,10 +380,9 @@ const Status = {
     },
     toggleThreadDisplay () {
       this.controlledToggleThreadDisplay()
-    }
-  },
-  watch: {
-    'highlight': function (id) {
+    },
+    scrollIfHighlighted (highlightId) {
+      const id = highlightId
       if (this.status.id === id) {
         let rect = this.$el.getBoundingClientRect()
         if (rect.top < 100) {
@@ -396,6 +396,14 @@ const Status = {
           window.scrollBy(0, rect.bottom - window.innerHeight + 50)
         }
       }
+    }
+  },
+  mounted () {
+    this.scrollIfHighlighted(this.highlight)
+  },
+  watch: {
+    'highlight': function (id) {
+      this.scrollIfHighlighted(id)
     },
     'status.repeat_num': function (num) {
       // refetch repeats when repeat_num is changed in any way
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index 47d35de8..e4812711 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -220,7 +220,7 @@
                   />
                 </button>
                 <button
-                  v-if="inThreadForest && replies && replies.length && toggleThreadDisplay"
+                  v-if="inThreadForest && replies && replies.length && !simpleTree"
                   class="button-unstyled"
                   :title="threadShowing ? $t('status.thread_hide') : $t('status.thread_show')"
                   :aria-expanded="threadShowing ? 'true' : 'false'"
@@ -233,7 +233,7 @@
                   />
                 </button>
                 <button
-                  v-if="dive"
+                  v-if="dive && !simpleTree"
                   class="button-unstyled"
                   :title="$t('status.show_only_conversation_under_this')"
                   @click.prevent="dive"
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
index ec7d5884..cb1d2242 100644
--- a/src/components/thread_tree/thread_tree.js
+++ b/src/components/thread_tree/thread_tree.js
@@ -1,5 +1,16 @@
 import Status from '../status/status.vue'
 
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+  faAngleDoubleDown,
+  faAngleDoubleRight
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faAngleDoubleDown,
+  faAngleDoubleRight
+)
+
 // const debug = console.log
 const debug = () => {}
 
@@ -19,11 +30,12 @@ const ThreadTree = {
     profileUserId: String,
 
     focused: Function,
-    getHighlight: Function,
+    highlight: String,
     getReplies: Function,
     setHighlight: Function,
     toggleExpanded: Function,
 
+    simple: Boolean,
     // to control display of the whole thread forest
     toggleThreadDisplay: Function,
     threadDisplayStatus: Object,
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index f0a103d1..b803f80f 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -9,12 +9,13 @@
       :show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
       :focused="focused(status.id)"
       :in-conversation="isExpanded"
-      :highlight="getHighlight()"
+      :highlight="highlight"
       :replies="getReplies(status.id)"
       :in-profile="inProfile"
       :profile-user-id="profileUserId"
       class="conversation-status conversation-status-treeview status-fadein panel-body"
 
+      :simple-tree="simple"
       :controlled-thread-display-status="threadDisplayStatus[status.id]"
       :controlled-toggle-thread-display="() => toggleThreadDisplay(status.id)"
 
@@ -49,10 +50,11 @@
 
         :focused="focused"
         :get-replies="getReplies"
-        :get-highlight="getHighlight"
+        :highlight="highlight"
         :set-highlight="setHighlight"
         :toggle-expanded="toggleExpanded"
 
+        :simple="simple"
         :toggle-thread-display="toggleThreadDisplay"
         :thread-display-status="threadDisplayStatus"
         :show-thread-recursively="showThreadRecursively"
@@ -69,6 +71,22 @@
       class="thread-tree-replies thread-tree-replies-hidden"
     >
       <i18n
+        v-if="simple"
+        tag="button"
+        path="status.thread_follow_with_icon"
+        class="button-unstyled -link thread-tree-show-replies-button"
+        @click.prevent="dive(status.id)"
+      >
+        <FAIcon
+          place="icon"
+          icon="angle-double-right"
+        />
+        <span place="text">
+          {{ $tc('status.thread_follow', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id] }) }}
+        </span>
+      </i18n>
+      <i18n
+        v-else
         tag="button"
         path="status.thread_show_full_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
diff --git a/src/modules/instance.js b/src/modules/instance.js
index a160a557..8a5bbbd1 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -53,7 +53,7 @@ const defaultState = {
   theme: 'pleroma-dark',
   virtualScrolling: true,
   sensitiveByDefault: false,
-  conversationDisplay: 'tree',
+  conversationDisplay: 'simple_tree',
 
   // Nasty stuff
   customEmoji: [],
-- 
cgit v1.2.3-70-g09d2


From bdf631c2c4d57f855831f8a6c747af7c5ccb6e70 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sun, 8 Aug 2021 09:46:10 -0400
Subject: Fix the bug where toggleShowingTall does not work

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

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index b803f80f..fa1e5f86 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -22,7 +22,7 @@
       :controlled-showing-tall="currentProp.showingTall"
       :controlled-expanding-subject="currentProp.expandingSubject"
       :controlled-showing-long-subject="currentProp.showingLongSubject"
-      :controlled-toggle-showing-tall="() => toggleCurrentProp('ShowingTall')"
+      :controlled-toggle-showing-tall="() => toggleCurrentProp('showingTall')"
       :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')"
       :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')"
       :dive="dive ? () => dive(status.id) : undefined"
-- 
cgit v1.2.3-70-g09d2


From 61bb69c88f6d70431a72bfb649d0f796b976a83b Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sun, 8 Aug 2021 12:40:17 -0400
Subject: Optimize thread display

---
 src/_variables.scss                          |   2 +
 src/components/conversation/conversation.vue | 215 ++++++++++++++++-----------
 src/components/status/status.scss            |   9 --
 src/components/thread_tree/thread_tree.vue   |  16 +-
 4 files changed, 139 insertions(+), 103 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/_variables.scss b/src/_variables.scss
index 9004d551..099d3606 100644
--- a/src/_variables.scss
+++ b/src/_variables.scss
@@ -30,3 +30,5 @@ $fallback--attachmentRadius: 10px;
 $fallback--chatMessageRadius: 10px;
 
 $fallback--buttonShadow: 0px 0px 2px 0px rgba(0, 0, 0, 1), 0px 1px 0px 0px rgba(255, 255, 255, 0.2) inset, 0px -1px 0px 0px rgba(0, 0, 0, 0.2) inset;
+
+$status-margin: 0.75em;
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 0ffd8c37..cd108f69 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -18,94 +18,102 @@
         {{ $t('timeline.collapse') }}
       </button>
     </div>
-    <div
-      v-if="diveMode"
-      class="conversation-undive-box"
-    >
-      <i18n
-        path="status.show_all_conversation"
-        tag="button"
-        class="button-unstyled -link"
-        @click.prevent="undive"
+    <div class="conversation-body panel-body">
+      <div
+        v-if="diveMode"
+        class="conversation-undive-box"
       >
-        <FAIcon icon="angle-double-left" />
-      </i18n>
-    </div>
-    <div
-      v-if="diveMode"
-      class="conversation-undive-box"
-    >
-      <i18n
-        path="status.return_to_last_showing"
-        tag="button"
-        class="button-unstyled -link"
-        @click.prevent="diveBack"
+        <i18n
+          path="status.show_all_conversation"
+          tag="button"
+          class="button-unstyled -link"
+          @click.prevent="undive"
+        >
+          <FAIcon icon="angle-double-left" />
+        </i18n>
+      </div>
+      <div
+        v-if="diveMode"
+        class="conversation-undive-box"
       >
-        <FAIcon icon="chevron-left" />
-      </i18n>
-    </div>
-    <div v-if="isTreeView">
-      <thread-tree
-        v-for="status in showingTopLevel"
-        :key="status.id"
-        ref="statusComponent"
-        :depth="0"
+        <i18n
+          path="status.return_to_last_showing"
+          tag="button"
+          class="button-unstyled -link"
+          @click.prevent="diveBack"
+        >
+          <FAIcon icon="chevron-left" />
+        </i18n>
+      </div>
+      <div
+        v-if="isTreeView"
+        class="thread-body"
+      >
+        <thread-tree
+          v-for="status in showingTopLevel"
+          :key="status.id"
+          ref="statusComponent"
+          :depth="0"
 
-        :status="status"
-        :in-profile="inProfile"
-        :conversation="conversation"
-        :collapsable="collapsable"
-        :is-expanded="isExpanded"
-        :pinned-status-ids-object="pinnedStatusIdsObject"
-        :profile-user-id="profileUserId"
+          :status="status"
+          :in-profile="inProfile"
+          :conversation="conversation"
+          :collapsable="collapsable"
+          :is-expanded="isExpanded"
+          :pinned-status-ids-object="pinnedStatusIdsObject"
+          :profile-user-id="profileUserId"
 
-        :focused="focused"
-        :get-replies="getReplies"
-        :highlight="maybeHighlight"
-        :set-highlight="setHighlight"
-        :toggle-expanded="toggleExpanded"
+          :focused="focused"
+          :get-replies="getReplies"
+          :highlight="maybeHighlight"
+          :set-highlight="setHighlight"
+          :toggle-expanded="toggleExpanded"
 
-        :simple="treeViewIsSimple"
-        :toggle-thread-display="toggleThreadDisplay"
-        :thread-display-status="threadDisplayStatus"
-        :show-thread-recursively="showThreadRecursively"
-        :total-reply-count="totalReplyCount"
-        :total-reply-depth="totalReplyDepth"
-        :status-content-properties="statusContentProperties"
-        :set-status-content-property="setStatusContentProperty"
-        :toggle-status-content-property="toggleStatusContentProperty"
-        :dive="canDive ? diveIntoStatus : undefined"
-      />
-    </div>
-    <div v-if="isLinearView">
-      <status
-        v-for="status in conversation"
-        :key="status.id"
-        ref="statusComponent"
-        :inline-expanded="collapsable && isExpanded"
-        :statusoid="status"
-        :expandable="!isExpanded"
-        :show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
-        :focused="focused(status.id)"
-        :in-conversation="isExpanded"
-        :highlight="getHighlight()"
-        :replies="getReplies(status.id)"
-        :in-profile="inProfile"
-        :profile-user-id="profileUserId"
-        class="conversation-status status-fadein panel-body"
+          :simple="treeViewIsSimple"
+          :toggle-thread-display="toggleThreadDisplay"
+          :thread-display-status="threadDisplayStatus"
+          :show-thread-recursively="showThreadRecursively"
+          :total-reply-count="totalReplyCount"
+          :total-reply-depth="totalReplyDepth"
+          :status-content-properties="statusContentProperties"
+          :set-status-content-property="setStatusContentProperty"
+          :toggle-status-content-property="toggleStatusContentProperty"
+          :dive="canDive ? diveIntoStatus : undefined"
+        />
+      </div>
+      <div
+        v-if="isLinearView"
+        class="thread-body"
+      >
+        <status
+          v-for="status in conversation"
+          :key="status.id"
+          ref="statusComponent"
+          :inline-expanded="collapsable && isExpanded"
+          :statusoid="status"
+          :expandable="!isExpanded"
+          :show-pinned="pinnedStatusIdsObject && pinnedStatusIdsObject[status.id]"
+          :focused="focused(status.id)"
+          :in-conversation="isExpanded"
+          :highlight="getHighlight()"
+          :replies="getReplies(status.id)"
+          :in-profile="inProfile"
+          :profile-user-id="profileUserId"
+          class="conversation-status status-fadein panel-body"
 
-        :toggle-thread-display="toggleThreadDisplay"
-        :thread-display-status="threadDisplayStatus"
-        :show-thread-recursively="showThreadRecursively"
-        :total-reply-count="totalReplyCount"
-        :total-reply-depth="totalReplyDepth"
-        :status-content-properties="statusContentProperties"
-        :set-status-content-property="setStatusContentProperty"
-        :toggle-status-content-property="toggleStatusContentProperty"
+          :toggle-thread-display="toggleThreadDisplay"
+          :thread-display-status="threadDisplayStatus"
+          :show-thread-recursively="showThreadRecursively"
+          :total-reply-count="totalReplyCount"
+          :total-reply-depth="totalReplyDepth"
+          :status-content-properties="statusContentProperties"
+          :set-status-content-property="setStatusContentProperty"
+          :toggle-status-content-property="toggleStatusContentProperty"
 
-        @goto="setHighlight"
-        @toggleExpanded="toggleExpanded"
-      />
+          @goto="setHighlight"
+          @toggleExpanded="toggleExpanded"
+        />
+      </div>
     </div>
   </div>
   <div
@@ -121,21 +129,54 @@
 
 .Conversation {
   .conversation-undive-box {
-    padding: 1em;
+    padding: $status-margin;
   }
+
+  /* HACK: we want the border width to scale with the status *below it* */
   .conversation-undive-box,
   .conversation-status {
-    border-bottom-width: 1px;
-    border-bottom-style: solid;
-    border-bottom-color: var(--border, $fallback--border);
+    border-top-width: 1px;
+    border-top-style: solid;
+    border-top-color: var(--border, $fallback--border);
     border-radius: 0;
   }
 
+  &.-expanded .conversation-body .thread-tree:nth-child(1) > .conversation-status {
+    border-top-left-radius: $fallback--panelRadius;
+    border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
+  }
+
+  /* first element in conversation body */
+  &.-expanded .conversation-body {
+    .conversation-undive-box:nth-child(1),
+    & > .conversation-status:nth-child(1),
+    & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1), {
+      border-top: none;
+    }
+  }
+
+  /* first unexpanded statuses in timeline */
+  &:first-child:not(.-expanded) {
+    .conversation-body {
+      .conversation-status {
+        border-top: none;
+      }
+    }
+  }
+
+  /* expanded conversation in timeline */
+  &.status-fadein.-expanded .thread-body {
+    border-left-width: 4px;
+    border-left-style: solid;
+    border-left-color: $fallback--cRed;
+    border-left-color: var(--cRed, $fallback--cRed);
+    border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
+    border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
+    border-bottom: 1px solid var(--border, $fallback--border);
+  }
   &.-expanded {
     .conversation-status:last-child {
       border-bottom: none;
-      border-radius: 0 0 $fallback--panelRadius $fallback--panelRadius;
-      border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
     }
   }
 }
diff --git a/src/components/status/status.scss b/src/components/status/status.scss
index 2028ade9..80bc392d 100644
--- a/src/components/status/status.scss
+++ b/src/components/status/status.scss
@@ -1,7 +1,5 @@
 @import '../../_variables.scss';
 
-$status-margin: 0.75em;
-
 .Status {
   min-width: 0;
   white-space: normal;
@@ -28,13 +26,6 @@ $status-margin: 0.75em;
     --icon: var(--selectedPostIcon, $fallback--icon);
   }
 
-  &.-conversation {
-    border-left-width: 4px;
-    border-left-style: solid;
-    border-left-color: $fallback--cRed;
-    border-left-color: var(--cRed, $fallback--cRed);
-  }
-
   .gravestone {
     padding: $status-margin;
     color: $fallback--faint;
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index fa1e5f86..aafad66e 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -109,14 +109,16 @@
 <style lang="scss">
 @import '../../_variables.scss';
 .thread-tree-replies {
-  margin-left: 1em;
+  margin-left: $status-margin;
+  border-left: 1px solid var(--border, $fallback--border);
+  border-top-left-radius: $fallback--panelRadius;
+  border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
+  border-bottom-left-radius: $fallback--panelRadius;
+  border-bottom-left-radius: var(--panelRadius, $fallback--panelRadius);
 }
+
 .thread-tree-replies-hidden {
-  padding: 1em;
-  border-bottom: 1px solid var(--border, #222);
-}
-.conversation-status.conversation-status-treeview:last-child,
-.Conversation.-expanded .conversation-status.conversation-status-treeview:last-child {
-  border-bottom: 1px solid var(--border, #222);
+  padding: $status-margin;
+  border-top: 1px solid var(--border, $fallback--border);
 }
 </style>
-- 
cgit v1.2.3-70-g09d2


From 8780246ce5566e60520354f5a3de92eacd059f61 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sun, 8 Aug 2021 12:55:04 -0400
Subject: Optimize thread border radius

---
 src/components/conversation/conversation.vue | 12 +++++++++---
 src/components/thread_tree/thread_tree.vue   |  3 +--
 2 files changed, 10 insertions(+), 5 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index cd108f69..11b5b3d8 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -130,10 +130,13 @@
 .Conversation {
   .conversation-undive-box {
     padding: $status-margin;
+    border-bottom-width: 1px;
+    border-bottom-style: solid;
+    border-bottom-color: var(--border, $fallback--border);
+    border-radius: 0;
   }
 
   /* HACK: we want the border width to scale with the status *below it* */
-  .conversation-undive-box,
   .conversation-status {
     border-top-width: 1px;
     border-top-style: solid;
@@ -146,11 +149,14 @@
     border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
   }
 
-  /* first element in conversation body */
+  /* first element in a reply tree, the border is supplied by reply tree instead
+     for radius to display properly
+   */
   &.-expanded .conversation-body {
     .conversation-undive-box:nth-child(1),
     & > .conversation-status:nth-child(1),
-    & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1), {
+    & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1),
+    .thread-tree:nth-child(1) > .conversation-status:nth-child(1) {
       border-top: none;
     }
   }
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index aafad66e..79ba0cc5 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -111,10 +111,9 @@
 .thread-tree-replies {
   margin-left: $status-margin;
   border-left: 1px solid var(--border, $fallback--border);
+  border-top: 1px solid var(--border, $fallback--border);
   border-top-left-radius: $fallback--panelRadius;
   border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
-  border-bottom-left-radius: $fallback--panelRadius;
-  border-bottom-left-radius: var(--panelRadius, $fallback--panelRadius);
 }
 
 .thread-tree-replies-hidden {
-- 
cgit v1.2.3-70-g09d2


From 0e4a7c3d05333d1e3c86b26b4d6b7cd296ff2582 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Sun, 8 Aug 2021 13:29:49 -0400
Subject: Make dive/undive button clickable along the whole row

---
 src/components/conversation/conversation.vue | 4 ++++
 src/components/thread_tree/thread_tree.vue   | 4 ++++
 2 files changed, 8 insertions(+)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 11b5b3d8..86a227ce 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -134,6 +134,10 @@
     border-bottom-style: solid;
     border-bottom-color: var(--border, $fallback--border);
     border-radius: 0;
+    /* Make the button stretch along the whole row */
+    display: flex;
+    align-items: stretch;
+    flex-direction: column;
   }
 
   /* HACK: we want the border width to scale with the status *below it* */
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 79ba0cc5..46d65101 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -119,5 +119,9 @@
 .thread-tree-replies-hidden {
   padding: $status-margin;
   border-top: 1px solid var(--border, $fallback--border);
+  /* Make the button stretch along the whole row */
+  display: flex;
+  align-items: stretch;
+  flex-direction: column;
 }
 </style>
-- 
cgit v1.2.3-70-g09d2


From 4adffb483579108c0bfe7593157e9bed3571903f Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Tue, 10 Aug 2021 21:28:13 -0400
Subject: Remove horizontal border and thicken vertical border in a thread tree

---
 src/components/conversation/conversation.vue | 32 +++++-----------------------
 src/components/thread_tree/thread_tree.vue   |  7 ++----
 2 files changed, 7 insertions(+), 32 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 86a227ce..c866b983 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -142,36 +142,14 @@
 
   /* HACK: we want the border width to scale with the status *below it* */
   .conversation-status {
-    border-top-width: 1px;
-    border-top-style: solid;
-    border-top-color: var(--border, $fallback--border);
+    border-bottom-width: 1px;
+    border-bottom-style: solid;
+    border-bottom-color: var(--border, $fallback--border);
     border-radius: 0;
   }
 
-  &.-expanded .conversation-body .thread-tree:nth-child(1) > .conversation-status {
-    border-top-left-radius: $fallback--panelRadius;
-    border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
-  }
-
-  /* first element in a reply tree, the border is supplied by reply tree instead
-     for radius to display properly
-   */
-  &.-expanded .conversation-body {
-    .conversation-undive-box:nth-child(1),
-    & > .conversation-status:nth-child(1),
-    & > .thread-body:nth-child(1) > .thread-tree:nth-child(1) > .conversation-status:nth-child(1),
-    .thread-tree:nth-child(1) > .conversation-status:nth-child(1) {
-      border-top: none;
-    }
-  }
-
-  /* first unexpanded statuses in timeline */
-  &:first-child:not(.-expanded) {
-    .conversation-body {
-      .conversation-status {
-        border-top: none;
-      }
-    }
+  &.-expanded .thread-tree .conversation-status {
+    border-bottom: none;
   }
 
   /* expanded conversation in timeline */
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 46d65101..dce03f27 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -110,15 +110,12 @@
 @import '../../_variables.scss';
 .thread-tree-replies {
   margin-left: $status-margin;
-  border-left: 1px solid var(--border, $fallback--border);
-  border-top: 1px solid var(--border, $fallback--border);
-  border-top-left-radius: $fallback--panelRadius;
-  border-top-left-radius: var(--panelRadius, $fallback--panelRadius);
+  border-left: 2px solid var(--border, $fallback--border);
 }
 
 .thread-tree-replies-hidden {
   padding: $status-margin;
-  border-top: 1px solid var(--border, $fallback--border);
+  //border-top: 1px solid var(--border, $fallback--border);
   /* Make the button stretch along the whole row */
   display: flex;
   align-items: stretch;
-- 
cgit v1.2.3-70-g09d2


From 20880cdf0bd33d6c189549441ab0ee26b59abf6d Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Thu, 16 Sep 2021 00:29:14 -0400
Subject: Make replying and mediaPlaying controlled

$refs is not a reliable way to deal with child components under
tree threading as it is not reactive, but the children may change at
any time. The only good way seems to be making these states aggregated on
the conversation component.

Ref: tree-threading
---
 src/components/conversation/conversation.js  | 21 +++++++++---
 src/components/conversation/conversation.vue |  4 +++
 src/components/status/status.js              | 50 +++++++++++++++++++++++++---
 src/components/thread_tree/thread_tree.js    |  3 ++
 src/components/thread_tree/thread_tree.vue   |  4 +++
 5 files changed, 72 insertions(+), 10 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 7f9f24b5..9aa7b183 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -99,6 +99,10 @@ const conversation = {
       return this.otherRepliesButtonPosition === 'inside'
     },
     suspendable () {
+      if (this.isTreeView) {
+        return Object.entries(this.statusContentProperties)
+          .every(([k, prop]) => !prop.replying && prop.mediaPlaying.length === 0)
+      }
       if (this.$refs.statusComponent && this.$refs.statusComponent[0]) {
         return this.$refs.statusComponent.every(s => s.suspendable)
       } else {
@@ -303,14 +307,21 @@ const conversation = {
       return this.conversation.reduce((a, k) => {
         const id = k.id
         const props = (() => {
-          if (this.statusContentPropertiesObject[id]) {
-            return this.statusContentPropertiesObject[id]
-          }
-          return {
+          const def = {
             showingTall: false,
             expandingSubject: false,
-            showingLongSubject: false
+            showingLongSubject: false,
+            isReplying: false,
+            mediaPlaying: []
+          }
+
+          if (this.statusContentPropertiesObject[id]) {
+            return {
+              ...def,
+              ...this.statusContentPropertiesObject[id]
+            }
           }
+          return def
         })()
 
         a[id] = props
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 0cd74539..4d64cf08 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -78,9 +78,13 @@
               :controlled-showing-tall="statusContentProperties[status.id].showingTall"
               :controlled-expanding-subject="statusContentProperties[status.id].expandingSubject"
               :controlled-showing-long-subject="statusContentProperties[status.id].showingLongSubject"
+              :controlled-replying="statusContentProperties[status.id].replying"
+              :controlled-media-playing="statusContentProperties[status.id].mediaPlaying"
               :controlled-toggle-showing-tall="() => toggleStatusContentProperty(status.id, 'showingTall')"
               :controlled-toggle-expanding-subject="() => toggleStatusContentProperty(status.id, 'expandingSubject')"
               :controlled-toggle-showing-long-subject="() => toggleStatusContentProperty(status.id, 'showingLongSubject')"
+              :controlled-toggle-replying="() => toggleStatusContentProperty(status.id, 'replying')"
+              :controlled-set-media-playing="(newVal) => toggleStatusContentProperty(status.id, 'mediaPlaying', newVal)"
 
               @goto="setHighlight"
               @toggleExpanded="toggleExpanded"
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 700b9764..73fad45f 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -61,6 +61,41 @@ library.add(
   faAngleDoubleRight
 )
 
+const camelCase = name => name.charAt(0).toUpperCase() + name.slice(1)
+
+const controlledOrUncontrolledGetters = list => list.reduce((res, name) => {
+  const camelized = camelCase(name)
+  const toggle = `controlledToggle${camelized}`
+  const controlledName = `controlled${camelized}`
+  const uncontrolledName = `uncontrolled${camelized}`
+  res[name] = function () {
+    return this[toggle] ? this[controlledName] : this[uncontrolledName]
+  }
+  return res
+}, {})
+
+const controlledOrUncontrolledToggle = (obj, name) => {
+  const camelized = camelCase(name)
+  const toggle = `controlledToggle${camelized}`
+  const uncontrolledName = `uncontrolled${camelized}`
+  if (obj[toggle]) {
+    obj[toggle]()
+  } else {
+    obj[uncontrolledName] = !obj[uncontrolledName]
+  }
+}
+
+const controlledOrUncontrolledSet = (obj, name, val) => {
+  const camelized = camelCase(name)
+  const set = `controlledSet${camelized}`
+  const uncontrolledName = `uncontrolled${camelized}`
+  if (obj[set]) {
+    obj[set](val)
+  } else {
+    obj[uncontrolledName] = val
+  }
+}
+
 const Status = {
   name: 'Status',
   components: {
@@ -108,20 +143,25 @@ const Status = {
     'controlledToggleExpandingSubject',
     'controlledShowingLongSubject',
     'controlledToggleShowingLongSubject',
+    'controlledReplying',
+    'controlledToggleReplying',
+    'controlledMediaPlaying',
+    'controlledSetMediaPlaying',
     'dive'
   ],
   data () {
     return {
-      replying: false,
+      uncontrolledReplying: false,
       unmuted: false,
       userExpanded: false,
-      mediaPlaying: [],
+      uncontrolledMediaPlaying: [],
       suspendable: true,
       error: null,
       headTailLinks: null
     }
   },
   computed: {
+    ...controlledOrUncontrolledGetters(['replying', 'mediaPlaying']),
     muteWords () {
       return this.mergedConfig.muteWords
     },
@@ -351,7 +391,7 @@ const Status = {
       this.error = undefined
     },
     toggleReplying () {
-      this.replying = !this.replying
+      controlledOrUncontrolledToggle(this, 'replying')
     },
     gotoOriginal (id) {
       if (this.inConversation) {
@@ -371,10 +411,10 @@ const Status = {
       return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)
     },
     addMediaPlaying (id) {
-      this.mediaPlaying.push(id)
+      controlledOrUncontrolledSet(this, 'mediaPlaying', this.mediaPlaying.concat(id))
     },
     removeMediaPlaying (id) {
-      this.mediaPlaying = this.mediaPlaying.filter(mediaId => mediaId !== id)
+      controlledOrUncontrolledSet(this, 'mediaPlaying', this.mediaPlaying.filter(mediaId => mediaId !== id))
     },
     setHeadTailLinks (headTailLinks) {
       this.headTailLinks = headTailLinks
diff --git a/src/components/thread_tree/thread_tree.js b/src/components/thread_tree/thread_tree.js
index 0e499b85..71e63725 100644
--- a/src/components/thread_tree/thread_tree.js
+++ b/src/components/thread_tree/thread_tree.js
@@ -80,6 +80,9 @@ const ThreadTree = {
     },
     toggleCurrentProp (name) {
       this.toggleStatusContentProperty(this.status.id, name)
+    },
+    setCurrentProp (name, newVal) {
+      this.setStatusContentProperty(this.status.id, name)
     }
   }
 }
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index dce03f27..cee223e8 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -22,9 +22,13 @@
       :controlled-showing-tall="currentProp.showingTall"
       :controlled-expanding-subject="currentProp.expandingSubject"
       :controlled-showing-long-subject="currentProp.showingLongSubject"
+      :controlled-replying="currentProp.replying"
+      :controlled-media-playing="currentProp.mediaPlaying"
       :controlled-toggle-showing-tall="() => toggleCurrentProp('showingTall')"
       :controlled-toggle-expanding-subject="() => toggleCurrentProp('expandingSubject')"
       :controlled-toggle-showing-long-subject="() => toggleCurrentProp('showingLongSubject')"
+      :controlled-toggle-replying="() => toggleCurrentProp('replying')"
+      :controlled-set-media-playing="(newVal) => setCurrentProp('mediaPlaying', newVal)"
       :dive="dive ? () => dive(status.id) : undefined"
 
       @goto="setHighlight"
-- 
cgit v1.2.3-70-g09d2


From 415a823af09b61e7ca7adfe295ad3a5eebc5e8b5 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 7 Mar 2022 19:19:12 -0500
Subject: Clean up dead code

---
 src/components/conversation/conversation.js  | 2 --
 src/components/conversation/conversation.vue | 6 ------
 src/components/thread_tree/thread_tree.vue   | 1 -
 3 files changed, 9 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js
index 89ff2f6f..2ef2977a 100644
--- a/src/components/conversation/conversation.js
+++ b/src/components/conversation/conversation.js
@@ -145,8 +145,6 @@ const conversation = {
 
       return sortAndFilterConversation(conversation, this.status)
     },
-    conversationDive () {
-    },
     statusMap () {
       return this.conversation.reduce((res, s) => {
         res[s.id] = s
diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 3e96fba2..20dea4f9 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -230,7 +230,6 @@
   }
   .thread-ancestor-dive-box-inner {
     padding: $status-margin;
-    //border-left: 2px solid var(--border, $fallback--border);
   }
 
   .conversation-status {
@@ -263,10 +262,5 @@
     border-radius: 0 0 var(--panelRadius, $fallback--panelRadius) var(--panelRadius, $fallback--panelRadius);
     border-bottom: 1px solid var(--border, $fallback--border);
   }
-  /* &.-expanded { */
-  /*   .conversation-status:last-child { */
-  /*     border-bottom: none; */
-  /*   } */
-  /* } */
 }
 </style>
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index cee223e8..a29a5bef 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -119,7 +119,6 @@
 
 .thread-tree-replies-hidden {
   padding: $status-margin;
-  //border-top: 1px solid var(--border, $fallback--border);
   /* Make the button stretch along the whole row */
   display: flex;
   align-items: stretch;
-- 
cgit v1.2.3-70-g09d2


From a511250b63b337f4f541a77e57cf6fb7ecbd5d1a Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 7 Mar 2022 19:28:38 -0500
Subject: Make $status-margin fallback only

---
 src/components/conversation/conversation.vue     |  8 ++++----
 src/components/status/status.scss                | 18 +++++++++---------
 src/components/status_content/status_content.vue |  4 ----
 src/components/thread_tree/thread_tree.vue       |  4 ++--
 4 files changed, 15 insertions(+), 19 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 20dea4f9..7628ceaa 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -194,7 +194,7 @@
 
 .Conversation {
   .conversation-dive-to-top-level-box {
-    padding: $status-margin;
+    padding: var(--status-margin, $status-margin);
     border-bottom-width: 1px;
     border-bottom-style: solid;
     border-bottom-color: var(--border, $fallback--border);
@@ -206,7 +206,7 @@
   }
 
   .thread-ancestors {
-    margin-left: $status-margin;
+    margin-left: var(--status-margin, $status-margin);
     border-left: 2px solid var(--border, $fallback--border);
   }
 
@@ -216,7 +216,7 @@
     color: var(--text);
   }
   .thread-ancestor-dive-box {
-    padding-left: $status-margin;
+    padding-left: var(--status-margin, $status-margin);
     border-bottom-width: 1px;
     border-bottom-style: solid;
     border-bottom-color: var(--border, $fallback--border);
@@ -229,7 +229,7 @@
     }
   }
   .thread-ancestor-dive-box-inner {
-    padding: $status-margin;
+    padding: var(--status-margin, $status-margin);
   }
 
   .conversation-status {
diff --git a/src/components/status/status.scss b/src/components/status/status.scss
index 80bc392d..3f647b25 100644
--- a/src/components/status/status.scss
+++ b/src/components/status/status.scss
@@ -27,7 +27,7 @@
   }
 
   .gravestone {
-    padding: $status-margin;
+    padding: var(--status-margin, $status-margin);
     color: $fallback--faint;
     color: var(--faint, $fallback--faint);
     display: flex;
@@ -40,7 +40,7 @@
 
   .status-container {
     display: flex;
-    padding: $status-margin;
+    padding: var(--status-margin, $status-margin);
 
     &.-repeat {
       padding-top: 0;
@@ -48,7 +48,7 @@
   }
 
   .pin {
-    padding: $status-margin $status-margin 0;
+    padding: var(--status-margin, $status-margin) var(--status-margin, $status-margin) 0;
     display: flex;
     align-items: center;
     justify-content: flex-end;
@@ -64,7 +64,7 @@
   }
 
   .left-side {
-    margin-right: $status-margin;
+    margin-right: var(--status-margin, $status-margin);
   }
 
   .right-side {
@@ -73,7 +73,7 @@
   }
 
   .usercard {
-    margin-bottom: $status-margin;
+    margin-bottom: var(--status-margin, $status-margin);
   }
 
   .status-username {
@@ -239,7 +239,7 @@
   }
 
   .repeat-info {
-    padding: 0.4em $status-margin;
+    padding: 0.4em var(--status-margin, $status-margin);
 
     .repeat-icon {
       color: $fallback--cGreen;
@@ -285,7 +285,7 @@
     position: relative;
     width: 100%;
     display: flex;
-    margin-top: $status-margin;
+    margin-top: var(--status-margin, $status-margin);
 
     > * {
       max-width: 4em;
@@ -353,7 +353,7 @@
   }
 
   .favs-repeated-users {
-    margin-top: $status-margin;
+    margin-top: var(--status-margin, $status-margin);
   }
 
   .stats {
@@ -380,7 +380,7 @@
   }
 
   .stat-count {
-    margin-right: $status-margin;
+    margin-right: var(--status-margin, $status-margin);
     user-select: none;
 
     .stat-title {
diff --git a/src/components/status_content/status_content.vue b/src/components/status_content/status_content.vue
index 0a09cda4..9e7d7956 100644
--- a/src/components/status_content/status_content.vue
+++ b/src/components/status_content/status_content.vue
@@ -58,10 +58,6 @@
 
 <script src="./status_content.js" ></script>
 <style lang="scss">
-@import '../../_variables.scss';
-
-$status-margin: 0.75em;
-
 .StatusContent {
   flex: 1;
   min-width: 0;
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index a29a5bef..e64455e0 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -113,12 +113,12 @@
 <style lang="scss">
 @import '../../_variables.scss';
 .thread-tree-replies {
-  margin-left: $status-margin;
+  margin-left: var(--status-margin, $status-margin);
   border-left: 2px solid var(--border, $fallback--border);
 }
 
 .thread-tree-replies-hidden {
-  padding: $status-margin;
+  padding: var(--status-margin, $status-margin);
   /* Make the button stretch along the whole row */
   display: flex;
   align-items: stretch;
-- 
cgit v1.2.3-70-g09d2


From 01d8fa4e543b0a349c95ea7e60a79cf5ecc82157 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Wed, 23 Mar 2022 16:31:34 +0200
Subject: fix i18n at places

---
 src/components/conversation/conversation.vue       | 46 ++++++++++++----------
 .../settings_modal/helpers/boolean_setting.vue     |  1 +
 .../settings_modal/helpers/integer_setting.vue     |  1 +
 .../settings_modal/tabs/theme_tab/theme_tab.vue    | 19 ++++-----
 src/components/shadow_control/shadow_control.vue   |  6 +--
 src/components/thread_tree/thread_tree.vue         | 46 ++++++++++++----------
 6 files changed, 67 insertions(+), 52 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/conversation/conversation.vue b/src/components/conversation/conversation.vue
index 7628ceaa..39c5db33 100644
--- a/src/components/conversation/conversation.vue
+++ b/src/components/conversation/conversation.vue
@@ -27,20 +27,23 @@
           v-if="shouldShowAllConversationButton"
           class="conversation-dive-to-top-level-box"
         >
-          <i18n
-            path="status.show_all_conversation_with_icon"
+          <i18n-t
+            keypath="status.show_all_conversation_with_icon"
             tag="button"
             class="button-unstyled -link"
             @click.prevent="diveToTopLevel"
           >
-            <FAIcon
-              place="icon"
-              icon="angle-double-left"
-            />
-            <span place="text">
-              {{ $tc('status.show_all_conversation', otherTopLevelCount, { numStatus: otherTopLevelCount }) }}
-            </span>
-          </i18n>
+            <template #icon>
+              <FAIcon
+                icon="angle-double-left"
+              />
+            </template>
+            <template #text>
+              <span>
+                {{ $tc('status.show_all_conversation', otherTopLevelCount, { numStatus: otherTopLevelCount }) }}
+              </span>
+            </template>
+          </i18n-t>
         </div>
         <div
           v-if="shouldShowAncestors"
@@ -96,20 +99,23 @@
               <div
                 class="thread-ancestor-dive-box-inner"
               >
-                <i18n
+                <i18n-t
                   tag="button"
-                  path="status.ancestor_follow_with_icon"
+                  keypath="status.ancestor_follow_with_icon"
                   class="button-unstyled -link thread-tree-show-replies-button"
                   @click.prevent="diveIntoStatus(status.id)"
                 >
-                  <FAIcon
-                    place="icon"
-                    icon="angle-double-right"
-                  />
-                  <span place="text">
-                    {{ $tc('status.ancestor_follow', getReplies(status.id).length - 1, { numReplies: getReplies(status.id).length - 1 }) }}
-                  </span>
-                </i18n>
+                  <template #icon>
+                    <FAIcon
+                      icon="angle-double-right"
+                    />
+                  </template>
+                  <template #text>
+                    <span>
+                      {{ $tc('status.ancestor_follow', getReplies(status.id).length - 1, { numReplies: getReplies(status.id).length - 1 }) }}
+                    </span>
+                  </template>
+                </i18n-t>
               </div>
             </div>
           </div>
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index e0d825f2..131377b9 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -14,6 +14,7 @@
       >
         <slot />
       </span>
+      {{ ' ' }}
       <ModifiedIndicator :changed="isChanged" /><ServerSideIndicator :server-side="isServerSide" /> </Checkbox>
   </label>
 </template>
diff --git a/src/components/settings_modal/helpers/integer_setting.vue b/src/components/settings_modal/helpers/integer_setting.vue
index 408b0925..e661a025 100644
--- a/src/components/settings_modal/helpers/integer_setting.vue
+++ b/src/components/settings_modal/helpers/integer_setting.vue
@@ -16,6 +16,7 @@
       :value="state"
       @change="update"
     >
+    {{ ' ' }}
     <ModifiedIndicator :changed="isChanged" />
   </span>
 </template>
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index 177498f8..e86528b8 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -925,6 +925,7 @@
               >
                 {{ $t('settings.style.shadows.override') }}
               </label>
+              {{ ' ' }}
               <input
                 id="override"
                 v-model="currentShadowOverriden"
@@ -950,27 +951,27 @@
             :fallback="currentShadowFallback"
           />
           <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
-            <i18n
-              path="settings.style.shadows.filter_hint.always_drop_shadow"
+            <i18n-t
+              keypath="settings.style.shadows.filter_hint.always_drop_shadow"
               tag="p"
             >
               <code>filter: drop-shadow()</code>
-            </i18n>
+            </i18n-t>
             <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
-            <i18n
-              path="settings.style.shadows.filter_hint.drop_shadow_syntax"
+            <i18n-t
+              keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
               tag="p"
             >
               <code>drop-shadow</code>
               <code>spread-radius</code>
               <code>inset</code>
-            </i18n>
-            <i18n
-              path="settings.style.shadows.filter_hint.inset_classic"
+            </i18n-t>
+            <i18n-t
+              keypath="settings.style.shadows.filter_hint.inset_classic"
               tag="p"
             >
               <code>box-shadow</code>
-            </i18n>
+            </i18n-t>
             <p>{{ $t('settings.style.shadows.filter_hint.spread_zero') }}</p>
           </div>
         </div>
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 511e07f3..b59ac3bc 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -204,12 +204,12 @@
         v-model="selected.alpha"
         :disabled="!present"
       />
-      <i18n
-        path="settings.style.shadows.hintV3"
+      <i18n-t
+        keypath="settings.style.shadows.hintV3"
         tag="p"
       >
         <code>--variable,mod</code>
-      </i18n>
+      </i18n-t>
     </div>
   </div>
 </template>
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index e64455e0..48942005 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -74,36 +74,42 @@
       v-if="currentReplies.length && !threadShowing"
       class="thread-tree-replies thread-tree-replies-hidden"
     >
-      <i18n
+      <i18n-t
         v-if="simple"
         tag="button"
-        path="status.thread_follow_with_icon"
+        keypath="status.thread_follow_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
         @click.prevent="dive(status.id)"
       >
-        <FAIcon
-          place="icon"
-          icon="angle-double-right"
-        />
-        <span place="text">
-          {{ $tc('status.thread_follow', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id] }) }}
-        </span>
-      </i18n>
-      <i18n
+        <template #icon>
+          <FAIcon
+            icon="angle-double-right"
+          />
+        </template>
+        <template #text>
+          <span>
+            {{ $tc('status.thread_follow', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id] }) }}
+          </span>
+        </template>
+      </i18n-t>
+      <i18n-t
         v-else
         tag="button"
-        path="status.thread_show_full_with_icon"
+        keypath="status.thread_show_full_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
         @click.prevent="showThreadRecursively(status.id)"
       >
-        <FAIcon
-          place="icon"
-          icon="angle-double-down"
-        />
-        <span place="text">
-          {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
-        </span>
-      </i18n>
+        <template #icon>
+          <FAIcon
+            icon="angle-double-down"
+          />
+        </template>
+        <template #text>
+          <span>
+            {{ $tc('status.thread_show_full', totalReplyCount[status.id], { numStatus: totalReplyCount[status.id], depth: totalReplyDepth[status.id] }) }}
+          </span>
+        </template>
+      </i18n-t>
     </div>
   </div>
 </template>
-- 
cgit v1.2.3-70-g09d2


From 650e69c33683b34e002f5fdc698ceb384baf059b Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 29 Mar 2022 00:02:02 +0300
Subject: fix misc warnings

---
 src/components/notification/notification.vue               | 2 +-
 src/components/poll/poll.vue                               | 2 +-
 src/components/settings_modal/helpers/integer_setting.js   | 2 +-
 src/components/settings_modal/tabs/theme_tab/theme_tab.vue | 6 +++---
 src/components/shadow_control/shadow_control.vue           | 2 +-
 src/components/thread_tree/thread_tree.vue                 | 4 ++--
 6 files changed, 9 insertions(+), 9 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 23157a51..d77b2f57 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -112,7 +112,7 @@
             </span>
             <span v-if="notification.type === 'pleroma:emoji_reaction'">
               <small>
-                <i18n-t keypath="notifications.reacted_with">
+                <i18n-t scope="global" keypath="notifications.reacted_with">
                   <span class="emoji-reaction-emoji">{{ notification.emoji }}</span>
                 </i18n-t>
               </small>
diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue
index e949c653..c3880096 100644
--- a/src/components/poll/poll.vue
+++ b/src/components/poll/poll.vue
@@ -71,7 +71,7 @@
           {{ $tc("polls.votes_count", poll.votes_count, { count: poll.votes_count }) }}&nbsp;·&nbsp;
         </template>
       </div>
-      <i18n-t :keypath="expired ? 'polls.expired' : 'polls.expires_in'">
+      <i18n-t scope="global" :keypath="expired ? 'polls.expired' : 'polls.expires_in'">
         <Timeago
           :time="expiresAt"
           :auto-update="60"
diff --git a/src/components/settings_modal/helpers/integer_setting.js b/src/components/settings_modal/helpers/integer_setting.js
index 4a19bd7c..17dc0e7b 100644
--- a/src/components/settings_modal/helpers/integer_setting.js
+++ b/src/components/settings_modal/helpers/integer_setting.js
@@ -8,7 +8,7 @@ export default {
     path: String,
     disabled: Boolean,
     min: Number,
-    expert: Number
+    expert: [Number, String]
   },
   computed: {
     pathDefault () {
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index cf049a70..dfa9a735 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -951,14 +951,14 @@
             :fallback="currentShadowFallback"
           />
           <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
-            <i18n-t
+            <i18n-t scope="global"
               keypath="settings.style.shadows.filter_hint.always_drop_shadow"
               tag="p"
             >
               <code>filter: drop-shadow()</code>
             </i18n-t>
             <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
-            <i18n-t
+            <i18n-t scope="global"
               keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
               tag="p"
             >
@@ -966,7 +966,7 @@
               <code>spread-radius</code>
               <code>inset</code>
             </i18n-t>
-            <i18n-t
+            <i18n-t scope="global"
               keypath="settings.style.shadows.filter_hint.inset_classic"
               tag="p"
             >
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index b59ac3bc..d1e5fc22 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -204,7 +204,7 @@
         v-model="selected.alpha"
         :disabled="!present"
       />
-      <i18n-t
+      <i18n-t scope="global"
         keypath="settings.style.shadows.hintV3"
         tag="p"
       >
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 48942005..f81653eb 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -74,7 +74,7 @@
       v-if="currentReplies.length && !threadShowing"
       class="thread-tree-replies thread-tree-replies-hidden"
     >
-      <i18n-t
+      <i18n-t scope="global"
         v-if="simple"
         tag="button"
         keypath="status.thread_follow_with_icon"
@@ -92,7 +92,7 @@
           </span>
         </template>
       </i18n-t>
-      <i18n-t
+      <i18n-t scope="global"
         v-else
         tag="button"
         keypath="status.thread_show_full_with_icon"
-- 
cgit v1.2.3-70-g09d2


From f20ae34400b35c230d3e7824f98d9b3f4e977f82 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 29 Mar 2022 01:04:37 +0300
Subject: lint

---
 src/components/color_input/color_input.vue                   | 2 +-
 src/components/notification/notification.vue                 | 5 ++++-
 src/components/opacity_input/opacity_input.vue               | 2 +-
 src/components/poll/poll.vue                                 | 5 ++++-
 src/components/selectable_list/selectable_list.vue           | 4 ++--
 src/components/settings_modal/helpers/boolean_setting.vue    | 2 +-
 src/components/settings_modal/helpers/choice_setting.vue     | 2 +-
 src/components/settings_modal/settings_modal.vue             | 7 +++++--
 src/components/settings_modal/tabs/profile_tab.vue           | 2 +-
 src/components/settings_modal/tabs/theme_tab/theme_tab.vue   | 9 ++++++---
 src/components/shadow_control/shadow_control.vue             | 3 ++-
 src/components/thread_tree/thread_tree.vue                   | 6 ++++--
 src/components/user_avatar/user_avatar.vue                   | 2 +-
 src/components/user_reporting_modal/user_reporting_modal.vue | 2 +-
 14 files changed, 34 insertions(+), 19 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue
index bb25f5a8..e84603c3 100644
--- a/src/components/color_input/color_input.vue
+++ b/src/components/color_input/color_input.vue
@@ -11,7 +11,7 @@
     </label>
     <Checkbox
       v-if="typeof fallback !== 'undefined' && showOptionalTickbox"
-      :modelValue="present"
+      :model-value="present"
       :disabled="disabled"
       class="opt"
       @update:modelValue="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index d77b2f57..ff7a21f1 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -112,7 +112,10 @@
             </span>
             <span v-if="notification.type === 'pleroma:emoji_reaction'">
               <small>
-                <i18n-t scope="global" keypath="notifications.reacted_with">
+                <i18n-t
+                  scope="global"
+                  keypath="notifications.reacted_with"
+                >
                   <span class="emoji-reaction-emoji">{{ notification.emoji }}</span>
                 </i18n-t>
               </small>
diff --git a/src/components/opacity_input/opacity_input.vue b/src/components/opacity_input/opacity_input.vue
index 83bc917d..15d08e04 100644
--- a/src/components/opacity_input/opacity_input.vue
+++ b/src/components/opacity_input/opacity_input.vue
@@ -11,7 +11,7 @@
     </label>
     <Checkbox
       v-if="typeof fallback !== 'undefined'"
-      :modelValue="present"
+      :model-value="present"
       :disabled="disabled"
       class="opt"
       @update:modelValue="$emit('update:modelValue', !present ? fallback : undefined)"
diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue
index c3880096..9e37a9d7 100644
--- a/src/components/poll/poll.vue
+++ b/src/components/poll/poll.vue
@@ -71,7 +71,10 @@
           {{ $tc("polls.votes_count", poll.votes_count, { count: poll.votes_count }) }}&nbsp;·&nbsp;
         </template>
       </div>
-      <i18n-t scope="global" :keypath="expired ? 'polls.expired' : 'polls.expires_in'">
+      <i18n-t
+        scope="global"
+        :keypath="expired ? 'polls.expired' : 'polls.expires_in'"
+      >
         <Timeago
           :time="expiresAt"
           :auto-update="60"
diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue
index cf7cec27..6d4d0629 100644
--- a/src/components/selectable_list/selectable_list.vue
+++ b/src/components/selectable_list/selectable_list.vue
@@ -6,7 +6,7 @@
     >
       <div class="selectable-list-checkbox-wrapper">
         <Checkbox
-          :modelValue="allSelected"
+          :model-value="allSelected"
           :indeterminate="someSelected"
           @change="toggleAll"
         >
@@ -31,7 +31,7 @@
         >
           <div class="selectable-list-checkbox-wrapper">
             <Checkbox
-              :modelValue="isSelected(item)"
+              :model-value="isSelected(item)"
               @change="checked => toggle(checked, item)"
             />
           </div>
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 3808bc74..69584808 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -4,7 +4,7 @@
     class="BooleanSetting"
   >
     <Checkbox
-      :modelValue="state"
+      :model-value="state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index b6aa853a..258c7422 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -6,7 +6,7 @@
     <slot />
     {{ ' ' }}
     <Select
-      :modelValue="state"
+      :model-value="state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue
index 18dd3d7a..e0e8304d 100644
--- a/src/components/settings_modal/settings_modal.vue
+++ b/src/components/settings_modal/settings_modal.vue
@@ -110,12 +110,15 @@
           </template>
         </Popover>
 
-        <Checkbox :modelValue="!!expertLevel" @update:modelValue="expertLevel = Number($event)">
+        <Checkbox
+          :model-value="!!expertLevel"
+          @update:modelValue="expertLevel = Number($event)"
+        >
           {{ $t("settings.expert_mode") }}
         </Checkbox>
         <span
-          class="extra-content"
           id="unscrolled-content"
+          class="extra-content"
         />
       </div>
     </div>
diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue
index b78581bd..d3f6727f 100644
--- a/src/components/settings_modal/tabs/profile_tab.vue
+++ b/src/components/settings_modal/tabs/profile_tab.vue
@@ -184,8 +184,8 @@
         <button
           v-if="!isDefaultBackground"
           class="button-unstyled"
-          @click="resetBackground"
           :title="$t('settings.reset_profile_background')"
+          @click="resetBackground"
         >
           <FAIcon
             class="reset-button"
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index dfa9a735..ff2fece9 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -951,14 +951,16 @@
             :fallback="currentShadowFallback"
           />
           <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
-            <i18n-t scope="global"
+            <i18n-t
+              scope="global"
               keypath="settings.style.shadows.filter_hint.always_drop_shadow"
               tag="p"
             >
               <code>filter: drop-shadow()</code>
             </i18n-t>
             <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
-            <i18n-t scope="global"
+            <i18n-t
+              scope="global"
               keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
               tag="p"
             >
@@ -966,7 +968,8 @@
               <code>spread-radius</code>
               <code>inset</code>
             </i18n-t>
-            <i18n-t scope="global"
+            <i18n-t
+              scope="global"
               keypath="settings.style.shadows.filter_hint.inset_classic"
               tag="p"
             >
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index d1e5fc22..f2fc7b99 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -204,7 +204,8 @@
         v-model="selected.alpha"
         :disabled="!present"
       />
-      <i18n-t scope="global"
+      <i18n-t
+        scope="global"
         keypath="settings.style.shadows.hintV3"
         tag="p"
       >
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index f81653eb..74577583 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -74,8 +74,9 @@
       v-if="currentReplies.length && !threadShowing"
       class="thread-tree-replies thread-tree-replies-hidden"
     >
-      <i18n-t scope="global"
+      <i18n-t
         v-if="simple"
+        scope="global"
         tag="button"
         keypath="status.thread_follow_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
@@ -92,8 +93,9 @@
           </span>
         </template>
       </i18n-t>
-      <i18n-t scope="global"
+      <i18n-t
         v-else
+        scope="global"
         tag="button"
         keypath="status.thread_show_full_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
index b19ce89b..f4d294df 100644
--- a/src/components/user_avatar/user_avatar.vue
+++ b/src/components/user_avatar/user_avatar.vue
@@ -2,7 +2,7 @@
   <span
     class="Avatar"
     :class="{ '-compact': compact }"
-    >
+  >
     <StillImage
       v-if="user"
       class="avatar"
diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue
index 2993e4ec..cd7b52c4 100644
--- a/src/components/user_reporting_modal/user_reporting_modal.vue
+++ b/src/components/user_reporting_modal/user_reporting_modal.vue
@@ -53,7 +53,7 @@
                   :statusoid="item"
                 />
                 <Checkbox
-                  :modelValue="isChecked(item.id)"
+                  :model-value="isChecked(item.id)"
                   @change="checked => toggleStatus(checked, item.id)"
                 />
               </div>
-- 
cgit v1.2.3-70-g09d2


From d9d4d8954e8dc7a10b5c36840437516f6e56b436 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 29 Mar 2022 11:57:54 +0300
Subject: Revert "lint"

This reverts commit f20ae34400b35c230d3e7824f98d9b3f4e977f82.
---
 src/components/color_input/color_input.vue                   | 2 +-
 src/components/notification/notification.vue                 | 5 +----
 src/components/opacity_input/opacity_input.vue               | 2 +-
 src/components/poll/poll.vue                                 | 5 +----
 src/components/selectable_list/selectable_list.vue           | 4 ++--
 src/components/settings_modal/helpers/boolean_setting.vue    | 2 +-
 src/components/settings_modal/helpers/choice_setting.vue     | 2 +-
 src/components/settings_modal/settings_modal.vue             | 7 ++-----
 src/components/settings_modal/tabs/profile_tab.vue           | 2 +-
 src/components/settings_modal/tabs/theme_tab/theme_tab.vue   | 9 +++------
 src/components/shadow_control/shadow_control.vue             | 3 +--
 src/components/thread_tree/thread_tree.vue                   | 6 ++----
 src/components/user_avatar/user_avatar.vue                   | 2 +-
 src/components/user_reporting_modal/user_reporting_modal.vue | 2 +-
 14 files changed, 19 insertions(+), 34 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue
index e84603c3..bb25f5a8 100644
--- a/src/components/color_input/color_input.vue
+++ b/src/components/color_input/color_input.vue
@@ -11,7 +11,7 @@
     </label>
     <Checkbox
       v-if="typeof fallback !== 'undefined' && showOptionalTickbox"
-      :model-value="present"
+      :modelValue="present"
       :disabled="disabled"
       class="opt"
       @update:modelValue="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index ff7a21f1..d77b2f57 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -112,10 +112,7 @@
             </span>
             <span v-if="notification.type === 'pleroma:emoji_reaction'">
               <small>
-                <i18n-t
-                  scope="global"
-                  keypath="notifications.reacted_with"
-                >
+                <i18n-t scope="global" keypath="notifications.reacted_with">
                   <span class="emoji-reaction-emoji">{{ notification.emoji }}</span>
                 </i18n-t>
               </small>
diff --git a/src/components/opacity_input/opacity_input.vue b/src/components/opacity_input/opacity_input.vue
index 15d08e04..83bc917d 100644
--- a/src/components/opacity_input/opacity_input.vue
+++ b/src/components/opacity_input/opacity_input.vue
@@ -11,7 +11,7 @@
     </label>
     <Checkbox
       v-if="typeof fallback !== 'undefined'"
-      :model-value="present"
+      :modelValue="present"
       :disabled="disabled"
       class="opt"
       @update:modelValue="$emit('update:modelValue', !present ? fallback : undefined)"
diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue
index 9e37a9d7..c3880096 100644
--- a/src/components/poll/poll.vue
+++ b/src/components/poll/poll.vue
@@ -71,10 +71,7 @@
           {{ $tc("polls.votes_count", poll.votes_count, { count: poll.votes_count }) }}&nbsp;·&nbsp;
         </template>
       </div>
-      <i18n-t
-        scope="global"
-        :keypath="expired ? 'polls.expired' : 'polls.expires_in'"
-      >
+      <i18n-t scope="global" :keypath="expired ? 'polls.expired' : 'polls.expires_in'">
         <Timeago
           :time="expiresAt"
           :auto-update="60"
diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue
index 6d4d0629..cf7cec27 100644
--- a/src/components/selectable_list/selectable_list.vue
+++ b/src/components/selectable_list/selectable_list.vue
@@ -6,7 +6,7 @@
     >
       <div class="selectable-list-checkbox-wrapper">
         <Checkbox
-          :model-value="allSelected"
+          :modelValue="allSelected"
           :indeterminate="someSelected"
           @change="toggleAll"
         >
@@ -31,7 +31,7 @@
         >
           <div class="selectable-list-checkbox-wrapper">
             <Checkbox
-              :model-value="isSelected(item)"
+              :modelValue="isSelected(item)"
               @change="checked => toggle(checked, item)"
             />
           </div>
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 69584808..3808bc74 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -4,7 +4,7 @@
     class="BooleanSetting"
   >
     <Checkbox
-      :model-value="state"
+      :modelValue="state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index 258c7422..b6aa853a 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -6,7 +6,7 @@
     <slot />
     {{ ' ' }}
     <Select
-      :model-value="state"
+      :modelValue="state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue
index e0e8304d..18dd3d7a 100644
--- a/src/components/settings_modal/settings_modal.vue
+++ b/src/components/settings_modal/settings_modal.vue
@@ -110,15 +110,12 @@
           </template>
         </Popover>
 
-        <Checkbox
-          :model-value="!!expertLevel"
-          @update:modelValue="expertLevel = Number($event)"
-        >
+        <Checkbox :modelValue="!!expertLevel" @update:modelValue="expertLevel = Number($event)">
           {{ $t("settings.expert_mode") }}
         </Checkbox>
         <span
-          id="unscrolled-content"
           class="extra-content"
+          id="unscrolled-content"
         />
       </div>
     </div>
diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue
index d3f6727f..b78581bd 100644
--- a/src/components/settings_modal/tabs/profile_tab.vue
+++ b/src/components/settings_modal/tabs/profile_tab.vue
@@ -184,8 +184,8 @@
         <button
           v-if="!isDefaultBackground"
           class="button-unstyled"
-          :title="$t('settings.reset_profile_background')"
           @click="resetBackground"
+          :title="$t('settings.reset_profile_background')"
         >
           <FAIcon
             class="reset-button"
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index ff2fece9..dfa9a735 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -951,16 +951,14 @@
             :fallback="currentShadowFallback"
           />
           <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
-            <i18n-t
-              scope="global"
+            <i18n-t scope="global"
               keypath="settings.style.shadows.filter_hint.always_drop_shadow"
               tag="p"
             >
               <code>filter: drop-shadow()</code>
             </i18n-t>
             <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
-            <i18n-t
-              scope="global"
+            <i18n-t scope="global"
               keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
               tag="p"
             >
@@ -968,8 +966,7 @@
               <code>spread-radius</code>
               <code>inset</code>
             </i18n-t>
-            <i18n-t
-              scope="global"
+            <i18n-t scope="global"
               keypath="settings.style.shadows.filter_hint.inset_classic"
               tag="p"
             >
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index f2fc7b99..d1e5fc22 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -204,8 +204,7 @@
         v-model="selected.alpha"
         :disabled="!present"
       />
-      <i18n-t
-        scope="global"
+      <i18n-t scope="global"
         keypath="settings.style.shadows.hintV3"
         tag="p"
       >
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 74577583..f81653eb 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -74,9 +74,8 @@
       v-if="currentReplies.length && !threadShowing"
       class="thread-tree-replies thread-tree-replies-hidden"
     >
-      <i18n-t
+      <i18n-t scope="global"
         v-if="simple"
-        scope="global"
         tag="button"
         keypath="status.thread_follow_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
@@ -93,9 +92,8 @@
           </span>
         </template>
       </i18n-t>
-      <i18n-t
+      <i18n-t scope="global"
         v-else
-        scope="global"
         tag="button"
         keypath="status.thread_show_full_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
index f4d294df..b19ce89b 100644
--- a/src/components/user_avatar/user_avatar.vue
+++ b/src/components/user_avatar/user_avatar.vue
@@ -2,7 +2,7 @@
   <span
     class="Avatar"
     :class="{ '-compact': compact }"
-  >
+    >
     <StillImage
       v-if="user"
       class="avatar"
diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue
index cd7b52c4..2993e4ec 100644
--- a/src/components/user_reporting_modal/user_reporting_modal.vue
+++ b/src/components/user_reporting_modal/user_reporting_modal.vue
@@ -53,7 +53,7 @@
                   :statusoid="item"
                 />
                 <Checkbox
-                  :model-value="isChecked(item.id)"
+                  :modelValue="isChecked(item.id)"
                   @change="checked => toggleStatus(checked, item.id)"
                 />
               </div>
-- 
cgit v1.2.3-70-g09d2


From b93e5437bdfa3f5d3c2e3d9cfec896c399728dfc Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 29 Mar 2022 12:04:09 +0300
Subject: manual lint

---
 src/components/settings_modal/tabs/theme_tab/theme_tab.vue | 9 ++++++---
 src/components/shadow_control/shadow_control.vue           | 3 ++-
 src/components/thread_tree/thread_tree.vue                 | 6 ++++--
 3 files changed, 12 insertions(+), 6 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
index dfa9a735..ff2fece9 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -951,14 +951,16 @@
             :fallback="currentShadowFallback"
           />
           <div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
-            <i18n-t scope="global"
+            <i18n-t
+              scope="global"
               keypath="settings.style.shadows.filter_hint.always_drop_shadow"
               tag="p"
             >
               <code>filter: drop-shadow()</code>
             </i18n-t>
             <p>{{ $t('settings.style.shadows.filter_hint.avatar_inset') }}</p>
-            <i18n-t scope="global"
+            <i18n-t
+              scope="global"
               keypath="settings.style.shadows.filter_hint.drop_shadow_syntax"
               tag="p"
             >
@@ -966,7 +968,8 @@
               <code>spread-radius</code>
               <code>inset</code>
             </i18n-t>
-            <i18n-t scope="global"
+            <i18n-t
+              scope="global"
               keypath="settings.style.shadows.filter_hint.inset_classic"
               tag="p"
             >
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index d1e5fc22..f2fc7b99 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -204,7 +204,8 @@
         v-model="selected.alpha"
         :disabled="!present"
       />
-      <i18n-t scope="global"
+      <i18n-t
+        scope="global"
         keypath="settings.style.shadows.hintV3"
         tag="p"
       >
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index f81653eb..4cae2726 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -74,7 +74,8 @@
       v-if="currentReplies.length && !threadShowing"
       class="thread-tree-replies thread-tree-replies-hidden"
     >
-      <i18n-t scope="global"
+      <i18n-t
+        scope="global"
         v-if="simple"
         tag="button"
         keypath="status.thread_follow_with_icon"
@@ -92,8 +93,9 @@
           </span>
         </template>
       </i18n-t>
-      <i18n-t scope="global"
+      <i18n-t
         v-else
+        scope="global"
         tag="button"
         keypath="status.thread_show_full_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
-- 
cgit v1.2.3-70-g09d2


From 5bbc0e0bb5f4a0c95674e6879975e6b5121b421e Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 29 Mar 2022 15:35:18 +0300
Subject: lint + fixes for registration

---
 src/components/color_input/color_input.vue         |  2 +-
 src/components/notification/notification.vue       |  5 ++-
 src/components/opacity_input/opacity_input.vue     |  2 +-
 src/components/poll/poll.vue                       |  5 ++-
 src/components/registration/registration.js        |  2 +-
 src/components/registration/registration.vue       | 38 +++++++++++-----------
 src/components/selectable_list/selectable_list.vue |  4 +--
 .../settings_modal/helpers/boolean_setting.vue     |  2 +-
 .../settings_modal/helpers/choice_setting.vue      |  2 +-
 src/components/settings_modal/settings_modal.vue   |  7 ++--
 src/components/settings_modal/tabs/profile_tab.vue |  2 +-
 src/components/thread_tree/thread_tree.vue         |  2 +-
 src/components/user_avatar/user_avatar.vue         |  2 +-
 .../user_reporting_modal/user_reporting_modal.vue  |  2 +-
 14 files changed, 43 insertions(+), 34 deletions(-)

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue
index bb25f5a8..e84603c3 100644
--- a/src/components/color_input/color_input.vue
+++ b/src/components/color_input/color_input.vue
@@ -11,7 +11,7 @@
     </label>
     <Checkbox
       v-if="typeof fallback !== 'undefined' && showOptionalTickbox"
-      :modelValue="present"
+      :model-value="present"
       :disabled="disabled"
       class="opt"
       @update:modelValue="$emit('update:modelValue', typeof modelValue === 'undefined' ? fallback : undefined)"
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index d77b2f57..ff7a21f1 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -112,7 +112,10 @@
             </span>
             <span v-if="notification.type === 'pleroma:emoji_reaction'">
               <small>
-                <i18n-t scope="global" keypath="notifications.reacted_with">
+                <i18n-t
+                  scope="global"
+                  keypath="notifications.reacted_with"
+                >
                   <span class="emoji-reaction-emoji">{{ notification.emoji }}</span>
                 </i18n-t>
               </small>
diff --git a/src/components/opacity_input/opacity_input.vue b/src/components/opacity_input/opacity_input.vue
index 83bc917d..15d08e04 100644
--- a/src/components/opacity_input/opacity_input.vue
+++ b/src/components/opacity_input/opacity_input.vue
@@ -11,7 +11,7 @@
     </label>
     <Checkbox
       v-if="typeof fallback !== 'undefined'"
-      :modelValue="present"
+      :model-value="present"
       :disabled="disabled"
       class="opt"
       @update:modelValue="$emit('update:modelValue', !present ? fallback : undefined)"
diff --git a/src/components/poll/poll.vue b/src/components/poll/poll.vue
index c3880096..9e37a9d7 100644
--- a/src/components/poll/poll.vue
+++ b/src/components/poll/poll.vue
@@ -71,7 +71,10 @@
           {{ $tc("polls.votes_count", poll.votes_count, { count: poll.votes_count }) }}&nbsp;·&nbsp;
         </template>
       </div>
-      <i18n-t scope="global" :keypath="expired ? 'polls.expired' : 'polls.expires_in'">
+      <i18n-t
+        scope="global"
+        :keypath="expired ? 'polls.expired' : 'polls.expires_in'"
+      >
         <Timeago
           :time="expiresAt"
           :auto-update="60"
diff --git a/src/components/registration/registration.js b/src/components/registration/registration.js
index 531cc480..a792fb7b 100644
--- a/src/components/registration/registration.js
+++ b/src/components/registration/registration.js
@@ -24,7 +24,7 @@ const registration = {
         password: { required },
         confirm: {
           required,
-          sameAsPassword: sameAs('password')
+          sameAs: sameAs(this.password)
         },
         reason: { required: requiredIf(() => this.accountApprovalRequired) }
       }
diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue
index 65b4bb33..3d409109 100644
--- a/src/components/registration/registration.vue
+++ b/src/components/registration/registration.vue
@@ -12,7 +12,7 @@
           <div class="text-fields">
             <div
               class="form-group"
-              :class="{ 'form-group--error': $v.user.username.$error }"
+              :class="{ 'form-group--error': v$.user.username.$error }"
             >
               <label
                 class="form--label"
@@ -20,18 +20,18 @@
               >{{ $t('login.username') }}</label>
               <input
                 id="sign-up-username"
-                v-model.trim="$v.user.username.$model"
+                v-model.trim="v$.user.username.$model"
                 :disabled="isPending"
                 class="form-control"
                 :placeholder="$t('registration.username_placeholder')"
               >
             </div>
             <div
-              v-if="$v.user.username.$dirty"
+              v-if="v$.user.username.$dirty"
               class="form-error"
             >
               <ul>
-                <li v-if="!$v.user.username.required">
+                <li v-if="!v$.user.username.required">
                   <span>{{ $t('registration.validations.username_required') }}</span>
                 </li>
               </ul>
@@ -39,7 +39,7 @@
 
             <div
               class="form-group"
-              :class="{ 'form-group--error': $v.user.fullname.$error }"
+              :class="{ 'form-group--error': v$.user.fullname.$error }"
             >
               <label
                 class="form--label"
@@ -47,18 +47,18 @@
               >{{ $t('registration.fullname') }}</label>
               <input
                 id="sign-up-fullname"
-                v-model.trim="$v.user.fullname.$model"
+                v-model.trim="v$.user.fullname.$model"
                 :disabled="isPending"
                 class="form-control"
                 :placeholder="$t('registration.fullname_placeholder')"
               >
             </div>
             <div
-              v-if="$v.user.fullname.$dirty"
+              v-if="v$.user.fullname.$dirty"
               class="form-error"
             >
               <ul>
-                <li v-if="!$v.user.fullname.required">
+                <li v-if="!v$.user.fullname.required">
                   <span>{{ $t('registration.validations.fullname_required') }}</span>
                 </li>
               </ul>
@@ -66,7 +66,7 @@
 
             <div
               class="form-group"
-              :class="{ 'form-group--error': $v.user.email.$error }"
+              :class="{ 'form-group--error': v$.user.email.$error }"
             >
               <label
                 class="form--label"
@@ -74,18 +74,18 @@
               >{{ $t('registration.email') }}</label>
               <input
                 id="email"
-                v-model="$v.user.email.$model"
+                v-model="v$.user.email.$model"
                 :disabled="isPending"
                 class="form-control"
                 type="email"
               >
             </div>
             <div
-              v-if="$v.user.email.$dirty"
+              v-if="v$.user.email.$dirty"
               class="form-error"
             >
               <ul>
-                <li v-if="!$v.user.email.required">
+                <li v-if="!v$.user.email.required">
                   <span>{{ $t('registration.validations.email_required') }}</span>
                 </li>
               </ul>
@@ -107,7 +107,7 @@
 
             <div
               class="form-group"
-              :class="{ 'form-group--error': $v.user.password.$error }"
+              :class="{ 'form-group--error': v$.user.password.$error }"
             >
               <label
                 class="form--label"
@@ -122,11 +122,11 @@
               >
             </div>
             <div
-              v-if="$v.user.password.$dirty"
+              v-if="v$.user.password.$dirty"
               class="form-error"
             >
               <ul>
-                <li v-if="!$v.user.password.required">
+                <li v-if="!v$.user.password.required">
                   <span>{{ $t('registration.validations.password_required') }}</span>
                 </li>
               </ul>
@@ -134,7 +134,7 @@
 
             <div
               class="form-group"
-              :class="{ 'form-group--error': $v.user.confirm.$error }"
+              :class="{ 'form-group--error': v$.user.confirm.$error }"
             >
               <label
                 class="form--label"
@@ -149,14 +149,14 @@
               >
             </div>
             <div
-              v-if="$v.user.confirm.$dirty"
+              v-if="v$.user.confirm.$dirty"
               class="form-error"
             >
               <ul>
-                <li v-if="!$v.user.confirm.required">
+                <li v-if="!v$.user.confirm.required">
                   <span>{{ $t('registration.validations.password_confirmation_required') }}</span>
                 </li>
-                <li v-if="!$v.user.confirm.sameAsPassword">
+                <li v-if="!v$.user.confirm.sameAsPassword">
                   <span>{{ $t('registration.validations.password_confirmation_match') }}</span>
                 </li>
               </ul>
diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue
index cf7cec27..6d4d0629 100644
--- a/src/components/selectable_list/selectable_list.vue
+++ b/src/components/selectable_list/selectable_list.vue
@@ -6,7 +6,7 @@
     >
       <div class="selectable-list-checkbox-wrapper">
         <Checkbox
-          :modelValue="allSelected"
+          :model-value="allSelected"
           :indeterminate="someSelected"
           @change="toggleAll"
         >
@@ -31,7 +31,7 @@
         >
           <div class="selectable-list-checkbox-wrapper">
             <Checkbox
-              :modelValue="isSelected(item)"
+              :model-value="isSelected(item)"
               @change="checked => toggle(checked, item)"
             />
           </div>
diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index 3808bc74..69584808 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -4,7 +4,7 @@
     class="BooleanSetting"
   >
     <Checkbox
-      :modelValue="state"
+      :model-value="state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
index b6aa853a..258c7422 100644
--- a/src/components/settings_modal/helpers/choice_setting.vue
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -6,7 +6,7 @@
     <slot />
     {{ ' ' }}
     <Select
-      :modelValue="state"
+      :model-value="state"
       :disabled="disabled"
       @update:modelValue="update"
     >
diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue
index 18dd3d7a..e0e8304d 100644
--- a/src/components/settings_modal/settings_modal.vue
+++ b/src/components/settings_modal/settings_modal.vue
@@ -110,12 +110,15 @@
           </template>
         </Popover>
 
-        <Checkbox :modelValue="!!expertLevel" @update:modelValue="expertLevel = Number($event)">
+        <Checkbox
+          :model-value="!!expertLevel"
+          @update:modelValue="expertLevel = Number($event)"
+        >
           {{ $t("settings.expert_mode") }}
         </Checkbox>
         <span
-          class="extra-content"
           id="unscrolled-content"
+          class="extra-content"
         />
       </div>
     </div>
diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue
index b78581bd..d3f6727f 100644
--- a/src/components/settings_modal/tabs/profile_tab.vue
+++ b/src/components/settings_modal/tabs/profile_tab.vue
@@ -184,8 +184,8 @@
         <button
           v-if="!isDefaultBackground"
           class="button-unstyled"
-          @click="resetBackground"
           :title="$t('settings.reset_profile_background')"
+          @click="resetBackground"
         >
           <FAIcon
             class="reset-button"
diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 4cae2726..74577583 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -75,8 +75,8 @@
       class="thread-tree-replies thread-tree-replies-hidden"
     >
       <i18n-t
-        scope="global"
         v-if="simple"
+        scope="global"
         tag="button"
         keypath="status.thread_follow_with_icon"
         class="button-unstyled -link thread-tree-show-replies-button"
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
index b19ce89b..f4d294df 100644
--- a/src/components/user_avatar/user_avatar.vue
+++ b/src/components/user_avatar/user_avatar.vue
@@ -2,7 +2,7 @@
   <span
     class="Avatar"
     :class="{ '-compact': compact }"
-    >
+  >
     <StillImage
       v-if="user"
       class="avatar"
diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue
index 2993e4ec..cd7b52c4 100644
--- a/src/components/user_reporting_modal/user_reporting_modal.vue
+++ b/src/components/user_reporting_modal/user_reporting_modal.vue
@@ -53,7 +53,7 @@
                   :statusoid="item"
                 />
                 <Checkbox
-                  :modelValue="isChecked(item.id)"
+                  :model-value="isChecked(item.id)"
                   @change="checked => toggleStatus(checked, item.id)"
                 />
               </div>
-- 
cgit v1.2.3-70-g09d2


From 22c70ae22a43bb1b11ace5a480df6587650bb6c3 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Thu, 7 Apr 2022 11:43:59 -0400
Subject: Fix shrug text in muted status

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

(limited to 'src/components/thread_tree/thread_tree.vue')

diff --git a/src/components/thread_tree/thread_tree.vue b/src/components/thread_tree/thread_tree.vue
index 74577583..4eaf597d 100644
--- a/src/components/thread_tree/thread_tree.vue
+++ b/src/components/thread_tree/thread_tree.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="thread-tree panel-body">
+  <div class="thread-tree">
     <status
       :key="status.id"
       ref="statusComponent"
-- 
cgit v1.2.3-70-g09d2

