From 296ab5430147f01107131046dcd428085bef9020 Mon Sep 17 00:00:00 2001
From: scarlett <nia@netbsd.org>
Date: Fri, 24 Aug 2018 20:04:26 +0100
Subject: [PATCH] Add settings for changing the visibility of replies in the
 timeline.

---
 src/components/settings/settings.js  |  4 +++
 src/components/settings/settings.vue | 10 +++++++
 src/components/status/status.js      | 42 ++++++++++++++++++++++++++++
 src/components/status/status.vue     |  2 +-
 src/i18n/messages.js                 |  3 ++
 src/main.js                          |  1 +
 src/modules/config.js                |  1 +
 7 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/src/components/settings/settings.js b/src/components/settings/settings.js
index c85ef59f..d5ca33cc 100644
--- a/src/components/settings/settings.js
+++ b/src/components/settings/settings.js
@@ -8,6 +8,7 @@ const settings = {
       hideAttachmentsLocal: this.$store.state.config.hideAttachments,
       hideAttachmentsInConvLocal: this.$store.state.config.hideAttachmentsInConv,
       hideNsfwLocal: this.$store.state.config.hideNsfw,
+      replyVisibilityLocal: this.$store.state.config.replyVisibility,
       loopVideoLocal: this.$store.state.config.loopVideo,
       loopVideoSilentOnlyLocal: this.$store.state.config.loopVideoSilentOnly,
       muteWordsString: this.$store.state.config.muteWords.join('\n'),
@@ -44,6 +45,9 @@ const settings = {
     hideNsfwLocal (value) {
       this.$store.dispatch('setOption', { name: 'hideNsfw', value })
     },
+    replyVisibilityLocal (value) {
+      this.$store.dispatch('setOption', { name: 'replyVisibility', value })
+    },
     loopVideoLocal (value) {
       this.$store.dispatch('setOption', { name: 'loopVideo', value })
     },
diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue
index 415317f0..9612876e 100644
--- a/src/components/settings/settings.vue
+++ b/src/components/settings/settings.vue
@@ -38,6 +38,16 @@
           <input type="checkbox" id="hoverPreview" v-model="hoverPreviewLocal">
           <label for="hoverPreview">{{$t('settings.reply_link_preview')}}</label>
         </li>
+        <li>
+          <label for="replyVisibility" class="select">
+            <select id="replyVisibility" v-model="replyVisibilityLocal">
+              <option value="all" selected>{{$t('settings.reply_visibility_all')}}</option>
+              <option value="following">{{$t('settings.reply_visibility_following')}}</option>
+              <option value="self">{{$t('settings.reply_visibility_self')}}</option>
+            </select>
+            <i class="icon-down-open"/>
+          </label>
+        </li>
       </ul>
     </div>
     <div class="setting-item">
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 9670f69d..a6cb6b6f 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -105,6 +105,48 @@ const Status = {
       const lengthScore = this.status.statusnet_html.split(/<p|<br/).length + this.status.text.length / 80
       return lengthScore > 20
     },
+    isReply () {
+      if (this.status.in_reply_to_status_id) {
+        return true
+      }
+      // For private replies where we can't see the OP, in_reply_to_status_id will be null.
+      // So instead, check that the post starts with a @mention.
+      if (this.status.visibility === 'private') {
+        var textBody = this.status.text
+        if (this.status.summary !== null) {
+            textBody = textBody.substring(this.status.summary.length, textBody.length)
+        }
+        return textBody.startsWith('@')
+      }
+      return false
+    },
+    hideReply () {
+      if (this.$store.state.config.replyVisibility === 'all') {
+        return false
+      }
+      if (this.inlineExpanded || this.expanded || !this.isReply) {
+        return false
+      }
+      if (this.status.user.id === this.$store.state.users.currentUser.id) {
+        return false
+      }
+      if (this.status.activity_type === 'repeat') {
+        return false
+      }
+      var checkFollowing = this.$store.state.config.replyVisibility === 'following'
+      for (var i = 0; i < this.status.attentions.length; ++i) {
+        if (this.status.user.id === this.status.attentions[i].id) {
+          continue
+        }
+        if (checkFollowing && this.status.attentions[i].following) {
+          return false
+        }
+        if (this.status.attentions[i].id === this.$store.state.users.currentUser.id) {
+          return false
+        }
+      }
+      return this.status.attentions.length > 0
+    },
     hideSubjectStatus () {
       if (this.tallStatus && !this.$store.state.config.collapseMessageWithSubject) {
         return false
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index e7d5ed7a..2bc44ee7 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="status-el" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
+  <div class="status-el" v-if="!hideReply" :class="[{ 'status-el_focused': isFocused }, { 'status-conversation': inlineExpanded }]">
     <template v-if="muted && !noReplyLinks">
       <div class="media status container muted">
         <small><router-link :to="{ name: 'user-profile', params: { id: status.user.id } }">{{status.user.screen_name}}</router-link></small>
diff --git a/src/i18n/messages.js b/src/i18n/messages.js
index 04460ecc..a86ac3ea 100644
--- a/src/i18n/messages.js
+++ b/src/i18n/messages.js
@@ -325,6 +325,9 @@ const en = {
     loop_video: 'Loop videos',
     loop_video_silent_only: 'Loop only videos without sound (i.e. Mastodon\'s "gifs")',
     reply_link_preview: 'Enable reply-link preview on mouse hover',
+    reply_visibility_all: 'Show all replies',
+    reply_visibility_following: 'Only show replies directed at me or users I\'m following',
+    reply_visibility_self: 'Only show replies directed at me',
     follow_import: 'Follow import',
     import_followers_from_a_csv_file: 'Import follows from a csv file',
     follows_imported: 'Follows imported! Processing them will take a while.',
diff --git a/src/main.js b/src/main.js
index 4124214d..1648d847 100644
--- a/src/main.js
+++ b/src/main.js
@@ -49,6 +49,7 @@ const persistedStateOptions = {
     'config.hideAttachments',
     'config.hideAttachmentsInConv',
     'config.hideNsfw',
+    'config.replyVisibility',
     'config.autoLoad',
     'config.hoverPreview',
     'config.streaming',
diff --git a/src/modules/config.js b/src/modules/config.js
index 60210a95..45bb1465 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -15,6 +15,7 @@ const defaultState = {
   hoverPreview: true,
   pauseOnUnfocused: true,
   stopGifs: false,
+  replyVisibility: 'all',
   muteWords: [],
   highlight: {}
 }