From a463959a365a5d618a79c96a26f6506e700d6ea3 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 1 Oct 2020 01:43:07 +0300
Subject: Initial work on highlighting changed settings. Some refactoring to
 simplify addition of new settings

---
 src/components/settings_modal/tabs/general_tab.vue | 118 ++++++++++-----------
 1 file changed, 59 insertions(+), 59 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 7f06d0bd..e03e731b 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -7,9 +7,9 @@
           <interface-language-switcher />
         </li>
         <li v-if="instanceSpecificPanelPresent">
-          <Checkbox v-model="hideISP">
+          <BooleanSetting path="hideISP">
             {{ $t('settings.hide_isp') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
@@ -17,46 +17,46 @@
       <h2>{{ $t('nav.timeline') }}</h2>
       <ul class="setting-list">
         <li>
-          <Checkbox v-model="hideMutedPosts">
-            {{ $t('settings.hide_muted_posts') }} {{ $t('settings.instance_default', { value: hideMutedPostsLocalizedValue }) }}
-          </Checkbox>
+          <BooleanSetting path="hideMutedPosts">
+            {{ $t('settings.hide_muted_posts') }}
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="collapseMessageWithSubject">
-            {{ $t('settings.collapse_subject') }} {{ $t('settings.instance_default', { value: collapseMessageWithSubjectLocalizedValue }) }}
-          </Checkbox>
+          <BooleanSetting path="collapseMessageWithSubject">
+            {{ $t('settings.collapse_subject') }}
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="streaming">
+          <BooleanSetting path="streaming">
             {{ $t('settings.streaming') }}
-          </Checkbox>
+          </BooleanSetting>
           <ul
             class="setting-list suboptions"
             :class="[{disabled: !streaming}]"
           >
             <li>
-              <Checkbox
-                v-model="pauseOnUnfocused"
+              <BooleanSetting
+                path="pauseOnUnfocused"
                 :disabled="!streaming"
               >
                 {{ $t('settings.pause_on_unfocused') }}
-              </Checkbox>
+              </BooleanSetting>
             </li>
           </ul>
         </li>
         <li>
-          <Checkbox v-model="useStreamingApi">
+          <BooleanSetting path="useStreamingApi">
             {{ $t('settings.useStreamingApi') }}
             <br>
             <small>
               {{ $t('settings.useStreamingApiWarning') }}
             </small>
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="emojiReactionsOnTimeline">
+          <BooleanSetting path="emojiReactionsOnTimeline">
             {{ $t('settings.emoji_reactions_on_timeline') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
@@ -65,14 +65,14 @@
       <h2>{{ $t('settings.composing') }}</h2>
       <ul class="setting-list">
         <li>
-          <Checkbox v-model="scopeCopy">
-            {{ $t('settings.scope_copy') }} {{ $t('settings.instance_default', { value: scopeCopyLocalizedValue }) }}
-          </Checkbox>
+          <BooleanSetting path="scopeCopy">
+            {{ $t('settings.scope_copy') }}
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="alwaysShowSubjectInput">
-            {{ $t('settings.subject_input_always_show') }} {{ $t('settings.instance_default', { value: alwaysShowSubjectInputLocalizedValue }) }}
-          </Checkbox>
+          <BooleanSetting path="alwaysShowSubjectInput">
+            {{ $t('settings.subject_input_always_show') }}
+          </BooleanSetting>
         </li>
         <li>
           <div>
@@ -127,19 +127,19 @@
           </div>
         </li>
         <li>
-          <Checkbox v-model="minimalScopesMode">
-            {{ $t('settings.minimal_scopes_mode') }} {{ $t('settings.instance_default', { value: minimalScopesModeLocalizedValue }) }}
-          </Checkbox>
+          <BooleanSetting path="minimalScopesMode">
+            {{ $t('settings.minimal_scopes_mode') }} {{ minimalScopesModeDefaultValue }}
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="autohideFloatingPostButton">
+          <BooleanSetting path="autohideFloatingPostButton">
             {{ $t('settings.autohide_floating_post_button') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="padEmoji">
+          <BooleanSetting path="padEmoji">
             {{ $t('settings.pad_emoji') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
@@ -148,14 +148,14 @@
       <h2>{{ $t('settings.attachments') }}</h2>
       <ul class="setting-list">
         <li>
-          <Checkbox v-model="hideAttachments">
+          <BooleanSetting path="hideAttachments">
             {{ $t('settings.hide_attachments_in_tl') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="hideAttachmentsInConv">
+          <BooleanSetting path="hideAttachmentsInConv">
             {{ $t('settings.hide_attachments_in_convo') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <li>
           <label for="maxThumbnails">
@@ -163,7 +163,7 @@
           </label>
           <input
             id="maxThumbnails"
-            v-model.number="maxThumbnails"
+            path.number="maxThumbnails"
             class="number-input"
             type="number"
             min="0"
@@ -171,48 +171,48 @@
           >
         </li>
         <li>
-          <Checkbox v-model="hideNsfw">
+          <BooleanSetting path="hideNsfw">
             {{ $t('settings.nsfw_clickthrough') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <ul class="setting-list suboptions">
           <li>
-            <Checkbox
-              v-model="preloadImage"
+            <BooleanSetting
+              path="preloadImage"
               :disabled="!hideNsfw"
             >
               {{ $t('settings.preload_images') }}
-            </Checkbox>
+            </BooleanSetting>
           </li>
           <li>
-            <Checkbox
-              v-model="useOneClickNsfw"
+            <BooleanSetting
+              path="useOneClickNsfw"
               :disabled="!hideNsfw"
             >
               {{ $t('settings.use_one_click_nsfw') }}
-            </Checkbox>
+            </BooleanSetting>
           </li>
         </ul>
         <li>
-          <Checkbox v-model="stopGifs">
+          <BooleanSetting path="stopGifs">
             {{ $t('settings.stop_gifs') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="loopVideo">
+          <BooleanSetting path="loopVideo">
             {{ $t('settings.loop_video') }}
-          </Checkbox>
+          </BooleanSetting>
           <ul
             class="setting-list suboptions"
             :class="[{disabled: !streaming}]"
           >
             <li>
-              <Checkbox
-                v-model="loopVideoSilentOnly"
+              <BooleanSetting
+                path="loopVideoSilentOnly"
                 :disabled="!loopVideo || !loopSilentAvailable"
               >
                 {{ $t('settings.loop_video_silent_only') }}
-              </Checkbox>
+              </BooleanSetting>
               <div
                 v-if="!loopSilentAvailable"
                 class="unavailable"
@@ -223,14 +223,14 @@
           </ul>
         </li>
         <li>
-          <Checkbox v-model="playVideosInModal">
+          <BooleanSetting path="playVideosInModal">
             {{ $t('settings.play_videos_in_modal') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="useContainFit">
+          <BooleanSetting path="useContainFit">
             {{ $t('settings.use_contain_fit') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
@@ -239,9 +239,9 @@
       <h2>{{ $t('settings.notifications') }}</h2>
       <ul class="setting-list">
         <li>
-          <Checkbox v-model="webPushNotifications">
+          <BooleanSetting path="webPushNotifications">
             {{ $t('settings.enable_web_push_notifications') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
@@ -250,9 +250,9 @@
       <h2>{{ $t('settings.fun') }}</h2>
       <ul class="setting-list">
         <li>
-          <Checkbox v-model="greentext">
-            {{ $t('settings.greentext') }} {{ $t('settings.instance_default', { value: greentextLocalizedValue }) }}
-          </Checkbox>
+          <BooleanSetting path="greentext">
+            {{ $t('settings.greentext') }}
+          </BooleanSetting>
         </li>
       </ul>
     </div>
-- 
cgit v1.2.3-70-g09d2


From 66f3e72b545a7f92d2569baa0fd52275a29d629a Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Mon, 1 Feb 2021 20:08:36 +0200
Subject: update branch with recent develop changes (FA, added settings)

---
 .../settings_modal/helpers/boolean_setting.vue     |  6 +--
 .../settings_modal/helpers/modified_icon.vue       | 46 -------------------
 .../settings_modal/helpers/modified_indicator.vue  | 51 ++++++++++++++++++++++
 .../helpers/shared_computed_object.js              |  1 -
 src/components/settings_modal/tabs/general_tab.vue |  8 ++--
 src/modules/config.js                              |  2 -
 6 files changed, 58 insertions(+), 56 deletions(-)
 delete mode 100644 src/components/settings_modal/helpers/modified_icon.vue
 create mode 100644 src/components/settings_modal/helpers/modified_indicator.vue

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue
index f7c392cd..b600b63b 100644
--- a/src/components/settings_modal/helpers/boolean_setting.vue
+++ b/src/components/settings_modal/helpers/boolean_setting.vue
@@ -13,7 +13,7 @@
         >
         <slot />
       </span>
-      <ModifiedIcon :changed="isChanged" />
+      <ModifiedIndicator :changed="isChanged" />
     </Checkbox>
   </label>
 </template>
@@ -21,7 +21,7 @@
 <script>
 import { get, set } from 'lodash'
 import Checkbox from 'src/components/checkbox/checkbox.vue'
-import ModifiedIcon from './modified_icon.vue'
+import ModifiedIndicator from './modified_indicator.vue'
 export default {
   props: [
     'path',
@@ -29,7 +29,7 @@ export default {
   ],
   components: {
     Checkbox,
-    ModifiedIcon
+    ModifiedIndicator
   },
   computed: {
     pathDefault () {
diff --git a/src/components/settings_modal/helpers/modified_icon.vue b/src/components/settings_modal/helpers/modified_icon.vue
deleted file mode 100644
index 27e0a9c5..00000000
--- a/src/components/settings_modal/helpers/modified_icon.vue
+++ /dev/null
@@ -1,46 +0,0 @@
-<template>
-  <span
-    v-if="changed"
-    class="ModifiedIcon"
-    >
-    <Popover
-      trigger="hover"
-      >
-      <i
-        slot="trigger"
-        class="icon icon-wrench"
-        />
-      <div
-        class="modified-tooltip"
-        slot="content"
-        >
-      {{ $t('settings.setting_changed') }}
-      </div>
-    </Popover>
-  </span>
-</template>
-
-<script>
-import Popover from 'src/components/popover/popover.vue'
-export default {
-  props: ['changed'],
-  components: { Popover }
-}
-</script>
-
-<style lang="scss">
-.ModifiedIcon {
-  display: inline-block;
-  position: relative;
-
-  .icon {
-    display: inline-block;
-  }
-
-  .modified-tooltip {
-    margin: 0.5em 1em;
-    min-width: 10em;
-    text-align: center;
-  }
-}
-</style>
diff --git a/src/components/settings_modal/helpers/modified_indicator.vue b/src/components/settings_modal/helpers/modified_indicator.vue
new file mode 100644
index 00000000..b75a2811
--- /dev/null
+++ b/src/components/settings_modal/helpers/modified_indicator.vue
@@ -0,0 +1,51 @@
+<template>
+  <span
+    v-if="changed"
+    class="ModifiedIndicator"
+    >
+    <Popover
+      trigger="hover"
+      >
+      <span slot="trigger">
+        &nbsp;
+          <FAIcon
+            icon="wrench"
+          />
+      </span>
+      <div
+        class="modified-tooltip"
+        slot="content"
+        >
+      {{ $t('settings.setting_changed') }}
+      </div>
+    </Popover>
+  </span>
+</template>
+
+<script>
+import Popover from 'src/components/popover/popover.vue'
+import { library } from '@fortawesome/fontawesome-svg-core'
+import { faWrench } from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faWrench
+)
+
+export default {
+  props: ['changed'],
+  components: { Popover }
+}
+</script>
+
+<style lang="scss">
+.ModifiedIndicator {
+  display: inline-block;
+  position: relative;
+
+  .modified-tooltip {
+    margin: 0.5em 1em;
+    min-width: 10em;
+    text-align: center;
+  }
+}
+</style>
diff --git a/src/components/settings_modal/helpers/shared_computed_object.js b/src/components/settings_modal/helpers/shared_computed_object.js
index 3cbcd288..2c833c0c 100644
--- a/src/components/settings_modal/helpers/shared_computed_object.js
+++ b/src/components/settings_modal/helpers/shared_computed_object.js
@@ -9,7 +9,6 @@ const SharedComputedObject = () => ({
     .map(key => [
       key + 'DefaultValue',
       function () {
-        console.log(this.$store.getters.defaultConfig)
         return this.$store.getters.defaultConfig[key]
       }
     ])
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 92cd2069..f93f4ea0 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -12,9 +12,9 @@
           </BooleanSetting>
         </li>
         <li v-if="instanceWallpaperUsed">
-          <Checkbox v-model="hideInstanceWallpaper">
+          <BooleanSetting path="hideInstanceWallpaper">
             {{ $t('settings.hide_wallpaper') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
@@ -64,9 +64,9 @@
           </BooleanSetting>
         </li>
         <li>
-          <Checkbox v-model="virtualScrolling">
+          <BooleanSetting path="virtualScrolling">
             {{ $t('settings.virtual_scrolling') }}
-          </Checkbox>
+          </BooleanSetting>
         </li>
       </ul>
     </div>
diff --git a/src/modules/config.js b/src/modules/config.js
index 444808cf..f992519e 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -80,7 +80,6 @@ const config = {
   getters: {
     defaultConfig (state, getters, rootState, rootGetters) {
       const { instance } = rootState
-      console.log('DC', instance.minimalScopesMode)
       return {
         ...defaultState,
         ...Object.fromEntries(
@@ -90,7 +89,6 @@ const config = {
     },
     mergedConfig (state, getters, rootState, rootGetters) {
       const { defaultConfig } = rootGetters
-      console.log('DC2', defaultConfig.hideISP)
       return {
         ...defaultConfig,
         ...state
-- 
cgit v1.2.3-70-g09d2


From 3f23aecd10e570f78b4142687a9a3fa349c13018 Mon Sep 17 00:00:00 2001
From: Shpuld Shpuldson <shp@cock.li>
Date: Tue, 23 Feb 2021 10:00:23 +0200
Subject: add sensitive by default option

---
 src/components/post_status_form/post_status_form.js | 4 ++--
 src/components/settings_modal/tabs/general_tab.vue  | 7 ++++++-
 src/i18n/en.json                                    | 1 +
 src/modules/config.js                               | 3 ++-
 src/modules/instance.js                             | 1 +
 5 files changed, 12 insertions(+), 4 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index 4148381c..e540654b 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -115,7 +115,7 @@ const PostStatusForm = {
       ? this.copyMessageScope
       : this.$store.state.users.currentUser.default_scope
 
-    const { postContentType: contentType } = this.$store.getters.mergedConfig
+    const { postContentType: contentType, sensitiveByDefault } = this.$store.getters.mergedConfig
 
     return {
       dropFiles: [],
@@ -126,7 +126,7 @@ const PostStatusForm = {
       newStatus: {
         spoilerText: this.subject || '',
         status: statusText,
-        nsfw: false,
+        nsfw: !!sensitiveByDefault,
         files: [],
         poll: {},
         mediaDescriptions: {},
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index f93f4ea0..9228c78e 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -144,7 +144,12 @@
         </li>
         <li>
           <BooleanSetting path="minimalScopesMode">
-            {{ $t('settings.minimal_scopes_mode') }} {{ minimalScopesModeDefaultValue }}
+            {{ $t('settings.minimal_scopes_mode') }}
+          </BooleanSetting>
+        </li>
+        <li>
+          <BooleanSetting path="sensitiveByDefault">
+            {{ $t('settings.sensitive_by_default') }}
           </BooleanSetting>
         </li>
         <li>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 0e069785..e6acda9c 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -429,6 +429,7 @@
     "subject_line_mastodon": "Like mastodon: copy as is",
     "subject_line_noop": "Do not copy",
     "post_status_content_type": "Post status content type",
+    "sensitive_by_default": "Mark posts as sensitive by default",
     "stop_gifs": "Play-on-hover GIFs",
     "streaming": "Enable automatic streaming of new posts when scrolled to the top",
     "user_mutes": "Users",
diff --git a/src/modules/config.js b/src/modules/config.js
index f992519e..b08903d1 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -67,7 +67,8 @@ export const defaultState = {
   greentext: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
-  virtualScrolling: undefined // instance default
+  virtualScrolling: undefined, // instance default
+  sensitiveByDefault: undefined
 }
 
 // caching the instance default properties
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 411b1caa..96de73ca 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -43,6 +43,7 @@ const defaultState = {
   subjectLineBehavior: 'email',
   theme: 'pleroma-dark',
   virtualScrolling: true,
+  sensitiveByDefault: false,
 
   // Nasty stuff
   customEmoji: [],
-- 
cgit v1.2.3-70-g09d2


From c6d4c20982261b55b16dda59c3e657eb1feb0041 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 16:11:44 +0200
Subject: Made Select component to make using styled selects easier

---
 src/App.scss                                       | 34 +---------
 src/components/font_control/font_control.js        | 12 ++--
 src/components/font_control/font_control.vue       | 32 ++++------
 .../interface_language_switcher.vue                | 41 +++++-------
 src/components/poll/poll_form.js                   |  6 +-
 src/components/poll/poll_form.vue                  | 51 ++++++---------
 .../post_status_form/post_status_form.js           |  4 +-
 .../post_status_form/post_status_form.vue          | 31 ++++------
 src/components/select/select.vue                   | 67 ++++++++++++++++++++
 .../settings_modal/tabs/filtering_tab.js           | 12 +---
 .../settings_modal/tabs/filtering_tab.vue          | 38 ++++++------
 src/components/settings_modal/tabs/general_tab.js  |  6 +-
 src/components/settings_modal/tabs/general_tab.vue | 72 ++++++++--------------
 .../settings_modal/tabs/theme_tab/theme_tab.js     | 12 +---
 .../settings_modal/tabs/theme_tab/theme_tab.vue    | 70 ++++++++-------------
 src/components/shadow_control/shadow_control.js    |  4 +-
 src/components/shadow_control/shadow_control.vue   | 32 ++++------
 src/components/user_card/user_card.js              |  6 +-
 src/components/user_card/user_card.vue             | 27 +++-----
 19 files changed, 240 insertions(+), 317 deletions(-)
 create mode 100644 src/components/select/select.vue

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/App.scss b/src/App.scss
index 90d083bb..77f2ea79 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -187,7 +187,7 @@ a {
   }
 }
 
-input, textarea, .select, .input {
+input, textarea, .input {
 
   &.unstyled {
     border-radius: 0;
@@ -217,11 +217,7 @@ input, textarea, .select, .input {
   hyphens: none;
   padding: 8px .5em;
 
-  &.select {
-    padding: 0;
-  }
-
-  &:disabled, &[disabled=disabled] {
+  &:disabled, &[disabled=disabled], &.disabled {
     cursor: not-allowed;
     opacity: 0.5;
   }
@@ -239,25 +235,6 @@ input, textarea, .select, .input {
     pointer-events: none;
   }
 
-  select {
-    -webkit-appearance: none;
-    -moz-appearance: none;
-    appearance: none;
-    background: transparent;
-    border: none;
-    color: $fallback--text;
-    color: var(--inputText, --text, $fallback--text);
-    margin: 0;
-    padding: 0 2em 0 .2em;
-    font-family: sans-serif;
-    font-family: var(--inputFont, sans-serif);
-    font-size: 14px;
-    width: 100%;
-    z-index: 1;
-    height: 28px;
-    line-height: 16px;
-  }
-
   &[type=range] {
     background: none;
     border: none;
@@ -809,13 +786,6 @@ nav {
   }
 }
 
-.select-multiple {
-  display: flex;
-  .option-list {
-    margin: 0;
-    padding-left: .5em;
-  }
-}
 .setting-list,
 .option-list{
   list-style-type: none;
diff --git a/src/components/font_control/font_control.js b/src/components/font_control/font_control.js
index 6274780b..137ef9c0 100644
--- a/src/components/font_control/font_control.js
+++ b/src/components/font_control/font_control.js
@@ -1,14 +1,10 @@
 import { set } from 'vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
+import Select from '../select/select.vue'
 
 export default {
+  components: {
+    Select
+  },
   props: [
     'name', 'label', 'value', 'fallback', 'options', 'no-inherit'
   ],
diff --git a/src/components/font_control/font_control.vue b/src/components/font_control/font_control.vue
index dd117ec0..996ff92c 100644
--- a/src/components/font_control/font_control.vue
+++ b/src/components/font_control/font_control.vue
@@ -22,30 +22,20 @@
       class="opt-l"
       :for="name + '-o'"
     />
-    <label
-      :for="name + '-font-switcher'"
-      class="select"
+    <Select
+      :id="name + '-font-switcher'"
+      v-model="preset"
       :disabled="!present"
+      class="font-switcher"
     >
-      <select
-        :id="name + '-font-switcher'"
-        v-model="preset"
-        :disabled="!present"
-        class="font-switcher"
+      <option
+        v-for="option in availableOptions"
+        :key="option"
+        :value="option"
       >
-        <option
-          v-for="option in availableOptions"
-          :key="option"
-          :value="option"
-        >
-          {{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
-        </option>
-      </select>
-      <FAIcon
-        class="select-down-icon"
-        icon="chevron-down"
-      />
-    </label>
+        {{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
+      </option>
+    </Select>
     <input
       v-if="isCustom"
       :id="name"
diff --git a/src/components/interface_language_switcher/interface_language_switcher.vue b/src/components/interface_language_switcher/interface_language_switcher.vue
index dc3bd408..cf307a24 100644
--- a/src/components/interface_language_switcher/interface_language_switcher.vue
+++ b/src/components/interface_language_switcher/interface_language_switcher.vue
@@ -3,27 +3,18 @@
     <label for="interface-language-switcher">
       {{ $t('settings.interfaceLanguage') }}
     </label>
-    <label
-      for="interface-language-switcher"
-      class="select"
+    <Select
+      id="interface-language-switcher"
+      v-model="language"
     >
-      <select
-        id="interface-language-switcher"
-        v-model="language"
+      <option
+        v-for="lang in languages"
+        :key="lang.code"
+        :value="lang.code"
       >
-        <option
-          v-for="lang in languages"
-          :key="lang.code"
-          :value="lang.code"
-        >
-          {{ lang.name }}
-        </option>
-      </select>
-      <FAIcon
-        class="select-down-icon"
-        icon="chevron-down"
-      />
-    </label>
+        {{ lang.name }}
+      </option>
+    </Select>
   </div>
 </template>
 
@@ -32,16 +23,12 @@ import languagesObject from '../../i18n/messages'
 import localeService from '../../services/locale/locale.service.js'
 import ISO6391 from 'iso-639-1'
 import _ from 'lodash'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
+import Select from '../select/select.vue'
 
 export default {
+  components: {
+    Select
+  },
   computed: {
     languages () {
       return _.map(languagesObject.languages, (code) => ({ code: code, name: this.getLanguageName(code) })).sort((a, b) => a.name.localeCompare(b.name))
diff --git a/src/components/poll/poll_form.js b/src/components/poll/poll_form.js
index 1f8df3f9..e30645c3 100644
--- a/src/components/poll/poll_form.js
+++ b/src/components/poll/poll_form.js
@@ -1,19 +1,21 @@
 import * as DateUtils from 'src/services/date_utils/date_utils.js'
 import { uniq } from 'lodash'
 import { library } from '@fortawesome/fontawesome-svg-core'
+import Select from '../select/select.vue'
 import {
   faTimes,
-  faChevronDown,
   faPlus
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
   faTimes,
-  faChevronDown,
   faPlus
 )
 
 export default {
+  components: {
+    Select
+  },
   name: 'PollForm',
   props: ['visible'],
   data: () => ({
diff --git a/src/components/poll/poll_form.vue b/src/components/poll/poll_form.vue
index c4403210..f10d1550 100644
--- a/src/components/poll/poll_form.vue
+++ b/src/components/poll/poll_form.vue
@@ -46,23 +46,13 @@
         class="poll-type"
         :title="$t('polls.type')"
       >
-        <label
-          for="poll-type-selector"
-          class="select"
+        <Select
+          v-model="pollType"
+          @change="updatePollToParent"
         >
-          <select
-            v-model="pollType"
-            class="select"
-            @change="updatePollToParent"
-          >
-            <option value="single">{{ $t('polls.single_choice') }}</option>
-            <option value="multiple">{{ $t('polls.multiple_choices') }}</option>
-          </select>
-          <FAIcon
-            class="select-down-icon"
-            icon="chevron-down"
-          />
-        </label>
+          <option value="single">{{ $t('polls.single_choice') }}</option>
+          <option value="multiple">{{ $t('polls.multiple_choices') }}</option>
+        </Select>
       </div>
       <div
         class="poll-expiry"
@@ -76,24 +66,19 @@
           :max="maxExpirationInCurrentUnit"
           @change="expiryAmountChange"
         >
-        <label class="expiry-unit select">
-          <select
-            v-model="expiryUnit"
-            @change="expiryAmountChange"
+        <Select
+          v-model="expiryUnit"
+          class="expiry-unit"
+          @change="expiryAmountChange"
+        >
+          <option
+            v-for="unit in expiryUnits"
+            :key="unit"
+            :value="unit"
           >
-            <option
-              v-for="unit in expiryUnits"
-              :key="unit"
-              :value="unit"
-            >
-              {{ $t(`time.${unit}_short`, ['']) }}
-            </option>
-          </select>
-          <FAIcon
-            class="select-down-icon"
-            icon="chevron-down"
-          />
-        </label>
+            {{ $t(`time.${unit}_short`, ['']) }}
+          </option>
+        </Select>
       </div>
     </div>
   </div>
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
index e540654b..5342894f 100644
--- a/src/components/post_status_form/post_status_form.js
+++ b/src/components/post_status_form/post_status_form.js
@@ -11,10 +11,10 @@ import { reject, map, uniqBy, debounce } from 'lodash'
 import suggestor from '../emoji_input/suggestor.js'
 import { mapGetters, mapState } from 'vuex'
 import Checkbox from '../checkbox/checkbox.vue'
+import Select from '../select/select.vue'
 
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
-  faChevronDown,
   faSmileBeam,
   faPollH,
   faUpload,
@@ -24,7 +24,6 @@ import {
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
-  faChevronDown,
   faSmileBeam,
   faPollH,
   faUpload,
@@ -84,6 +83,7 @@ const PostStatusForm = {
     PollForm,
     ScopeSelector,
     Checkbox,
+    Select,
     Attachment,
     StatusContent
   },
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
index 73f6a4f1..cc4f6251 100644
--- a/src/components/post_status_form/post_status_form.vue
+++ b/src/components/post_status_form/post_status_form.vue
@@ -189,28 +189,19 @@
             v-if="postFormats.length > 1"
             class="text-format"
           >
-            <label
-              for="post-content-type"
-              class="select"
+            <Select
+              id="post-content-type"
+              v-model="newStatus.contentType"
+              class="form-control"
             >
-              <select
-                id="post-content-type"
-                v-model="newStatus.contentType"
-                class="form-control"
+              <option
+                v-for="postFormat in postFormats"
+                :key="postFormat"
+                :value="postFormat"
               >
-                <option
-                  v-for="postFormat in postFormats"
-                  :key="postFormat"
-                  :value="postFormat"
-                >
-                  {{ $t(`post_status.content_type["${postFormat}"]`) }}
-                </option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+                {{ $t(`post_status.content_type["${postFormat}"]`) }}
+              </option>
+            </Select>
           </div>
           <div
             v-if="postFormats.length === 1 && postFormats[0] !== 'text/plain'"
diff --git a/src/components/select/select.vue b/src/components/select/select.vue
new file mode 100644
index 00000000..a27a2541
--- /dev/null
+++ b/src/components/select/select.vue
@@ -0,0 +1,67 @@
+
+<template>
+  <label
+    class="Select input"
+    :class="{ disabled }"
+  >
+    <select
+      :disabled="disabled"
+      :value="value"
+      @change="$emit('change', $event.target.value)"
+    >
+      <slot />
+    </select>
+    <FAIcon
+      class="select-down-icon"
+      icon="chevron-down"
+    />
+  </label>
+</template>
+
+<script>
+import { library } from '@fortawesome/fontawesome-svg-core'
+import {
+  faChevronDown
+} from '@fortawesome/free-solid-svg-icons'
+
+library.add(
+  faChevronDown
+)
+export default {
+  model: {
+    prop: 'value',
+    event: 'change'
+  },
+  props: [
+    'value',
+    'disabled'
+  ]
+}
+</script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.Select {
+  padding: 0;
+
+  select {
+    -webkit-appearance: none;
+    -moz-appearance: none;
+    appearance: none;
+    background: transparent;
+    border: none;
+    color: $fallback--text;
+    color: var(--inputText, --text, $fallback--text);
+    margin: 0;
+    padding: 0 2em 0 .2em;
+    font-family: sans-serif;
+    font-family: var(--inputFont, sans-serif);
+    font-size: 14px;
+    width: 100%;
+    z-index: 1;
+    height: 28px;
+    line-height: 16px;
+  }
+}
+</style>
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 6e95f7af..89199d85 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -1,15 +1,8 @@
 import { filter, trim } from 'lodash'
 import BooleanSetting from '../helpers/boolean_setting.vue'
+import Select from '../../select/select.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
 
 const FilteringTab = {
   data () {
@@ -18,7 +11,8 @@ const FilteringTab = {
     }
   },
   components: {
-    BooleanSetting
+    BooleanSetting,
+    Select
   },
   computed: {
     ...SharedComputedObject(),
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index 402c2a4a..4023fbe2 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -38,26 +38,17 @@
       </div>
       <div>
         {{ $t('settings.replies_in_timeline') }}
-        <label
-          for="replyVisibility"
-          class="select"
+        <Select
+          id="replyVisibility"
+          v-model="replyVisibility"
         >
-          <select
-            id="replyVisibility"
-            v-model="replyVisibility"
-          >
-            <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>
-          <FAIcon
-            class="select-down-icon"
-            icon="chevron-down"
-          />
-        </label>
+          <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>
       </div>
       <div>
         <BooleanSetting path="hidePostStats">
@@ -88,3 +79,12 @@
   </div>
 </template>
 <script src="./filtering_tab.js"></script>
+<style lang="scss">
+.select-multiple {
+  display: flex;
+  .option-list {
+    margin: 0;
+    padding-left: .5em;
+  }
+}
+</style>
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index 2db523be..03648d0b 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -1,15 +1,14 @@
 import BooleanSetting from '../helpers/boolean_setting.vue'
+import Select from '../../select/select.vue'
 import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
-  faChevronDown,
   faGlobe
 } from '@fortawesome/free-solid-svg-icons'
 
 library.add(
-  faChevronDown,
   faGlobe
 )
 
@@ -27,7 +26,8 @@ const GeneralTab = {
   },
   components: {
     BooleanSetting,
-    InterfaceLanguageSwitcher
+    InterfaceLanguageSwitcher,
+    Select
   },
   computed: {
     postFormats () {
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 9228c78e..a0413cfa 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -87,59 +87,41 @@
         <li>
           <div>
             {{ $t('settings.subject_line_behavior') }}
-            <label
-              for="subjectLineBehavior"
-              class="select"
+            <Select
+              id="subjectLineBehavior"
+              v-model="subjectLineBehavior"
             >
-              <select
-                id="subjectLineBehavior"
-                v-model="subjectLineBehavior"
-              >
-                <option value="email">
-                  {{ $t('settings.subject_line_email') }}
-                  {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
-                </option>
-                <option value="masto">
-                  {{ $t('settings.subject_line_mastodon') }}
-                  {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
-                </option>
-                <option value="noop">
-                  {{ $t('settings.subject_line_noop') }}
-                  {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
-                </option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+              <option value="email">
+                {{ $t('settings.subject_line_email') }}
+                {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
+              </option>
+              <option value="masto">
+                {{ $t('settings.subject_line_mastodon') }}
+                {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
+              </option>
+              <option value="noop">
+                {{ $t('settings.subject_line_noop') }}
+                {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
+              </option>
+            </Select>
           </div>
         </li>
         <li v-if="postFormats.length > 0">
           <div>
             {{ $t('settings.post_status_content_type') }}
-            <label
-              for="postContentType"
-              class="select"
+            <Select
+              id="postContentType"
+              v-model="postContentType"
             >
-              <select
-                id="postContentType"
-                v-model="postContentType"
+              <option
+                v-for="postFormat in postFormats"
+                :key="postFormat"
+                :value="postFormat"
               >
-                <option
-                  v-for="postFormat in postFormats"
-                  :key="postFormat"
-                  :value="postFormat"
-                >
-                  {{ $t(`post_status.content_type["${postFormat}"]`) }}
-                  {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
-                </option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+                {{ $t(`post_status.content_type["${postFormat}"]`) }}
+                {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
+              </option>
+            </Select>
           </div>
         </li>
         <li>
diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
index 6cf75fe7..73068e19 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js
@@ -33,16 +33,9 @@ import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
 import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
 import ExportImport from 'src/components/export_import/export_import.vue'
 import Checkbox from 'src/components/checkbox/checkbox.vue'
+import Select from 'src/components/select/select.vue'
 
 import Preview from './preview.vue'
-import { library } from '@fortawesome/fontawesome-svg-core'
-import {
-  faChevronDown
-} from '@fortawesome/free-solid-svg-icons'
-
-library.add(
-  faChevronDown
-)
 
 // List of color values used in v1
 const v1OnlyNames = [
@@ -384,7 +377,8 @@ export default {
     TabSwitcher,
     Preview,
     ExportImport,
-    Checkbox
+    Checkbox,
+    Select
   },
   methods: {
     loadTheme (
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 b8add42f..2b4b8ba0 100644
--- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
+++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue
@@ -59,32 +59,23 @@
           <template slot="before">
             <div class="presets">
               {{ $t('settings.presets') }}
-              <label
-                for="preset-switcher"
-                class="select"
+              <Select
+                id="preset-switcher"
+                v-model="selected"
+                class="preset-switcher"
               >
-                <select
-                  id="preset-switcher"
-                  v-model="selected"
-                  class="preset-switcher"
+                <option
+                  v-for="style in availableStyles"
+                  :key="style.name"
+                  :value="style"
+                  :style="{
+                    backgroundColor: style[1] || (style.theme || style.source).colors.bg,
+                    color: style[3] || (style.theme || style.source).colors.text
+                  }"
                 >
-                  <option
-                    v-for="style in availableStyles"
-                    :key="style.name"
-                    :value="style"
-                    :style="{
-                      backgroundColor: style[1] || (style.theme || style.source).colors.bg,
-                      color: style[3] || (style.theme || style.source).colors.text
-                    }"
-                  >
-                    {{ style[0] || style.name }}
-                  </option>
-                </select>
-                <FAIcon
-                  class="select-down-icon"
-                  icon="chevron-down"
-                />
-              </label>
+                  {{ style[0] || style.name }}
+                </option>
+              </Select>
             </div>
           </template>
         </ExportImport>
@@ -902,28 +893,19 @@
           <div class="tab-header shadow-selector">
             <div class="select-container">
               {{ $t('settings.style.shadows.component') }}
-              <label
-                for="shadow-switcher"
-                class="select"
+              <Select
+                id="shadow-switcher"
+                v-model="shadowSelected"
+                class="shadow-switcher"
               >
-                <select
-                  id="shadow-switcher"
-                  v-model="shadowSelected"
-                  class="shadow-switcher"
+                <option
+                  v-for="shadow in shadowsAvailable"
+                  :key="shadow"
+                  :value="shadow"
                 >
-                  <option
-                    v-for="shadow in shadowsAvailable"
-                    :key="shadow"
-                    :value="shadow"
-                  >
-                    {{ $t('settings.style.shadows.components.' + shadow) }}
-                  </option>
-                </select>
-                <FAIcon
-                  class="select-down-icon"
-                  icon="chevron-down"
-                />
-              </label>
+                  {{ $t('settings.style.shadows.components.' + shadow) }}
+                </option>
+              </Select>
             </div>
             <div class="override">
               <label
diff --git a/src/components/shadow_control/shadow_control.js b/src/components/shadow_control/shadow_control.js
index 800c39d5..2d5d6eb1 100644
--- a/src/components/shadow_control/shadow_control.js
+++ b/src/components/shadow_control/shadow_control.js
@@ -1,5 +1,6 @@
 import ColorInput from '../color_input/color_input.vue'
 import OpacityInput from '../opacity_input/opacity_input.vue'
+import Select from '../select/select.vue'
 import { getCssShadow } from '../../services/style_setter/style_setter.js'
 import { hex2rgb } from '../../services/color_convert/color_convert.js'
 import { library } from '@fortawesome/fontawesome-svg-core'
@@ -45,7 +46,8 @@ export default {
   },
   components: {
     ColorInput,
-    OpacityInput
+    OpacityInput,
+    Select
   },
   methods: {
     add () {
diff --git a/src/components/shadow_control/shadow_control.vue b/src/components/shadow_control/shadow_control.vue
index 37d491f0..6b5acbdb 100644
--- a/src/components/shadow_control/shadow_control.vue
+++ b/src/components/shadow_control/shadow_control.vue
@@ -59,30 +59,20 @@
         :disabled="usingFallback"
         class="id-control style-control"
       >
-        <label
-          for="shadow-switcher"
-          class="select"
+        <Select
+          id="shadow-switcher"
+          v-model="selectedId"
+          class="shadow-switcher"
           :disabled="!ready || usingFallback"
         >
-          <select
-            id="shadow-switcher"
-            v-model="selectedId"
-            class="shadow-switcher"
-            :disabled="!ready || usingFallback"
+          <option
+            v-for="(shadow, index) in cValue"
+            :key="index"
+            :value="index"
           >
-            <option
-              v-for="(shadow, index) in cValue"
-              :key="index"
-              :value="index"
-            >
-              {{ $t('settings.style.shadows.shadow_id', { value: index }) }}
-            </option>
-          </select>
-          <FAIcon
-            icon="chevron-down"
-            class="select-down-icon"
-          />
-        </label>
+            {{ $t('settings.style.shadows.shadow_id', { value: index }) }}
+          </option>
+        </Select>
         <button
           class="btn button-default"
           :disabled="!ready || !present"
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 3a8efafc..d9fb64d1 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -4,13 +4,13 @@ import ProgressButton from '../progress_button/progress_button.vue'
 import FollowButton from '../follow_button/follow_button.vue'
 import ModerationTools from '../moderation_tools/moderation_tools.vue'
 import AccountActions from '../account_actions/account_actions.vue'
+import Select from '../select/select.vue'
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
 import { mapGetters } from 'vuex'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
   faBell,
   faRss,
-  faChevronDown,
   faSearchPlus,
   faExternalLinkAlt
 } from '@fortawesome/free-solid-svg-icons'
@@ -18,7 +18,6 @@ import {
 library.add(
   faRss,
   faBell,
-  faChevronDown,
   faSearchPlus,
   faExternalLinkAlt
 )
@@ -118,7 +117,8 @@ export default {
     ModerationTools,
     AccountActions,
     ProgressButton,
-    FollowButton
+    FollowButton,
+    Select
   },
   methods: {
     muteUser () {
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 4b7ee7d5..c5b73fde 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -132,25 +132,16 @@
               class="userHighlightCl"
               type="color"
             >
-            <label
-              for="theme_tab"
-              class="userHighlightSel select"
+            <Select
+              :id="'userHighlightSel'+user.id"
+              v-model="userHighlightType"
+              class="userHighlightSel"
             >
-              <select
-                :id="'userHighlightSel'+user.id"
-                v-model="userHighlightType"
-                class="userHighlightSel"
-              >
-                <option value="disabled">{{ $t('user_card.highlight.disabled') }}</option>
-                <option value="solid">{{ $t('user_card.highlight.solid') }}</option>
-                <option value="striped">{{ $t('user_card.highlight.striped') }}</option>
-                <option value="side">{{ $t('user_card.highlight.side') }}</option>
-              </select>
-              <FAIcon
-                class="select-down-icon"
-                icon="chevron-down"
-              />
-            </label>
+              <option value="disabled">{{ $t('user_card.highlight.disabled') }}</option>
+              <option value="solid">{{ $t('user_card.highlight.solid') }}</option>
+              <option value="striped">{{ $t('user_card.highlight.striped') }}</option>
+              <option value="side">{{ $t('user_card.highlight.side') }}</option>
+            </Select>
           </div>
         </div>
         <div
-- 
cgit v1.2.3-70-g09d2


From 1f0ac68fcd3f382eedf69d1f5fdcffdc16c3885e Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 11 Mar 2021 16:55:14 +0200
Subject: implement ChoiceSetting for settings modal similar to BooleanSetting

---
 .../settings_modal/helpers/choice_setting.js       | 34 ++++++++++++++++
 .../settings_modal/helpers/choice_setting.vue      | 29 ++++++++++++++
 .../settings_modal/tabs/filtering_tab.js           | 11 ++++--
 .../settings_modal/tabs/filtering_tab.vue          | 17 +++-----
 src/components/settings_modal/tabs/general_tab.js  | 18 +++++++--
 src/components/settings_modal/tabs/general_tab.vue | 46 ++++++----------------
 6 files changed, 103 insertions(+), 52 deletions(-)
 create mode 100644 src/components/settings_modal/helpers/choice_setting.js
 create mode 100644 src/components/settings_modal/helpers/choice_setting.vue

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js
new file mode 100644
index 00000000..042e8106
--- /dev/null
+++ b/src/components/settings_modal/helpers/choice_setting.js
@@ -0,0 +1,34 @@
+import { get, set } from 'lodash'
+import Select from 'src/components/select/select.vue'
+import ModifiedIndicator from './modified_indicator.vue'
+export default {
+  components: {
+    Select,
+    ModifiedIndicator
+  },
+  props: [
+    'path',
+    'disabled',
+    'options'
+  ],
+  computed: {
+    pathDefault () {
+      const [firstSegment, ...rest] = this.path.split('.')
+      return [firstSegment + 'DefaultValue', ...rest].join('.')
+    },
+    state () {
+      return get(this.$parent, this.path)
+    },
+    defaultState () {
+      return get(this.$parent, this.pathDefault)
+    },
+    isChanged () {
+      return get(this.$parent, this.path) !== get(this.$parent, this.pathDefault)
+    }
+  },
+  methods: {
+    update (e) {
+      set(this.$parent, this.path, e)
+    }
+  }
+}
diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue
new file mode 100644
index 00000000..1a8275b4
--- /dev/null
+++ b/src/components/settings_modal/helpers/choice_setting.vue
@@ -0,0 +1,29 @@
+<template>
+  <label
+    class="ChoiceSetting"
+  >
+    <slot />
+    <Select
+      :value="state"
+      :disabled="disabled"
+      @change="update"
+    >
+      <option
+        v-for="option in options"
+        :key="option.key"
+        :value="option.value"
+      >
+        {{ option.label }}
+        {{ option.value === defaultValue ? $t('settings.instance_default_simple') : '' }}
+      </option>
+    </Select>
+    <ModifiedIndicator :changed="isChanged" />
+  </label>
+</template>
+
+<script src="./choice_setting.js"></script>
+
+<style lang="scss">
+.ChoiceSetting {
+}
+</style>
diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js
index 89199d85..4eaf4217 100644
--- a/src/components/settings_modal/tabs/filtering_tab.js
+++ b/src/components/settings_modal/tabs/filtering_tab.js
@@ -1,18 +1,23 @@
 import { filter, trim } from 'lodash'
 import BooleanSetting from '../helpers/boolean_setting.vue'
-import Select from '../../select/select.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
 
 const FilteringTab = {
   data () {
     return {
-      muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n')
+      muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n'),
+      replyVisibilityOptions: ['all', 'following', 'self'].map(mode => ({
+        key: mode,
+        value: mode,
+        label: this.$t(`settings.reply_visibility_${mode}`)
+      }))
     }
   },
   components: {
     BooleanSetting,
-    Select
+    ChoiceSetting
   },
   computed: {
     ...SharedComputedObject(),
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index 4023fbe2..fb5fc375 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -36,20 +36,13 @@
           </li>
         </ul>
       </div>
-      <div>
-        {{ $t('settings.replies_in_timeline') }}
-        <Select
+      <ChoiceSetting
           id="replyVisibility"
-          v-model="replyVisibility"
+          path="replyVisibility"
+          :options="replyVisibilityOptions"
         >
-          <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>
-      </div>
+        {{ $t('settings.replies_in_timeline') }}
+      </ChoiceSetting>
       <div>
         <BooleanSetting path="hidePostStats">
           {{ $t('settings.hide_post_stats') }}
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index 03648d0b..07fccf57 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -1,5 +1,5 @@
 import BooleanSetting from '../helpers/boolean_setting.vue'
-import Select from '../../select/select.vue'
+import ChoiceSetting from '../helpers/choice_setting.vue'
 import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue'
 
 import SharedComputedObject from '../helpers/shared_computed_object.js'
@@ -15,6 +15,11 @@ library.add(
 const GeneralTab = {
   data () {
     return {
+      subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({
+        key: mode,
+        value: mode,
+        label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
+      })),
       loopSilentAvailable:
       // Firefox
       Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
@@ -26,13 +31,20 @@ const GeneralTab = {
   },
   components: {
     BooleanSetting,
-    InterfaceLanguageSwitcher,
-    Select
+    ChoiceSetting,
+    InterfaceLanguageSwitcher
   },
   computed: {
     postFormats () {
       return this.$store.state.instance.postFormats || []
     },
+    postContentOptions () {
+      return this.postFormats.map(format => ({
+        key: format,
+        value: format,
+        label: this.$t(`post_status.content_type["${format}"]`)
+      }))
+    },
     instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel },
     instanceWallpaperUsed () {
       return this.$store.state.instance.background &&
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index a0413cfa..7fb82c06 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -85,44 +85,22 @@
           </BooleanSetting>
         </li>
         <li>
-          <div>
+          <ChoiceSetting
+            id="subjectLineBehavior"
+            path="subjectLineBehavior"
+            :options="subjectLineOptions"
+          >
             {{ $t('settings.subject_line_behavior') }}
-            <Select
-              id="subjectLineBehavior"
-              v-model="subjectLineBehavior"
-            >
-              <option value="email">
-                {{ $t('settings.subject_line_email') }}
-                {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }}
-              </option>
-              <option value="masto">
-                {{ $t('settings.subject_line_mastodon') }}
-                {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }}
-              </option>
-              <option value="noop">
-                {{ $t('settings.subject_line_noop') }}
-                {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }}
-              </option>
-            </Select>
-          </div>
+          </ChoiceSetting>
         </li>
         <li v-if="postFormats.length > 0">
-          <div>
+          <ChoiceSetting
+            id="postContentType"
+            path="postContentType"
+            :options="postContentOptions"
+          >
             {{ $t('settings.post_status_content_type') }}
-            <Select
-              id="postContentType"
-              v-model="postContentType"
-            >
-              <option
-                v-for="postFormat in postFormats"
-                :key="postFormat"
-                :value="postFormat"
-              >
-                {{ $t(`post_status.content_type["${postFormat}"]`) }}
-                {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }}
-              </option>
-            </Select>
-          </div>
+          </ChoiceSetting>
         </li>
         <li>
           <BooleanSetting path="minimalScopesMode">
-- 
cgit v1.2.3-70-g09d2


From 7341b8a5516621985a76456e1eefc58cd23ff2e2 Mon Sep 17 00:00:00 2001
From: eris <femmediscord@gmail.com>
Date: Wed, 26 May 2021 22:22:55 +0000
Subject: Implement right sidebar option as user option

---
 CHANGELOG.md                                       | 1 +
 src/App.js                                         | 2 +-
 src/components/settings_modal/tabs/general_tab.vue | 5 +++++
 src/i18n/en.json                                   | 1 +
 src/modules/config.js                              | 1 +
 5 files changed, 9 insertions(+), 1 deletion(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cef6d401..905d9f65 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Added a quick settings to timeline header for easier access
 - Added option to mark posts as sensitive by default
 - Added quick filters for notifications
+- Implemented user option to change sidebar position to the right side
 
 
 ## [2.3.0] - 2021-03-01
diff --git a/src/App.js b/src/App.js
index 1ca029b6..231c6ae1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -77,7 +77,7 @@ export default {
     privateMode () { return this.$store.state.instance.private },
     sidebarAlign () {
       return {
-        'order': this.$store.state.instance.sidebarRight ? 99 : 0
+        'order': this.$store.getters.mergedConfig.sidebarRight ? 99 : 0
       }
     },
     ...mapGetters(['mergedConfig'])
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 9228c78e..7bae4a32 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -11,6 +11,11 @@
             {{ $t('settings.hide_isp') }}
           </BooleanSetting>
         </li>
+        <li>
+          <BooleanSetting path="sidebarRight">
+            {{ $t('settings.right_sidebar') }}
+          </BooleanSetting>
+        </li>
         <li v-if="instanceWallpaperUsed">
           <BooleanSetting path="hideInstanceWallpaper">
             {{ $t('settings.hide_wallpaper') }}
diff --git a/src/i18n/en.json b/src/i18n/en.json
index d6138482..1b38e29a 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -345,6 +345,7 @@
     "hide_all_muted_posts": "Hide muted posts",
     "max_thumbnails": "Maximum amount of thumbnails per post",
     "hide_isp": "Hide instance-specific panel",
+    "right_sidebar": "Show sidebar on the right side",
     "hide_wallpaper": "Hide instance wallpaper",
     "preload_images": "Preload images",
     "use_one_click_nsfw": "Open NSFW attachments with just one click",
diff --git a/src/modules/config.js b/src/modules/config.js
index 629588a8..0f596750 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -54,6 +54,7 @@ export const defaultState = {
   interfaceLanguage: browserLocale,
   hideScopeNotice: false,
   useStreamingApi: false,
+  sidebarRight: undefined, // instance default
   scopeCopy: undefined, // instance default
   subjectLineBehavior: undefined, // instance default
   alwaysShowSubjectInput: undefined, // instance default
-- 
cgit v1.2.3-70-g09d2


From b87a9d6675cf7cd8d37d45e62013fab27cbc46e6 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Tue, 8 Jun 2021 16:14:01 +0300
Subject: Rearranged settings, moved more stuff to filtering where apllicable.
 Changed how filering works.

---
 src/components/notification/notification.scss      |   6 +
 src/components/notification/notification.vue       |   1 +
 src/components/notifications/notifications.scss    |   5 -
 .../settings_modal/tabs/filtering_tab.vue          | 195 ++++++++++++++-------
 src/components/settings_modal/tabs/general_tab.vue | 154 ++++++----------
 src/components/status/status.js                    |  44 +++--
 src/components/timeline/timeline_quick_settings.js |   3 +-
 src/i18n/en.json                                   |  14 +-
 src/modules/config.js                              |   2 +
 src/modules/instance.js                            |   3 +
 10 files changed, 242 insertions(+), 185 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/notification/notification.scss b/src/components/notification/notification.scss
index f5905560..e075747b 100644
--- a/src/components/notification/notification.scss
+++ b/src/components/notification/notification.scss
@@ -2,6 +2,12 @@
 
 // TODO Copypaste from Status, should unify it somehow
 .Notification {
+  border-bottom: 1px solid;
+  border-color: $fallback--border;
+  border-color: var(--border, $fallback--border);
+  word-wrap: break-word;
+  word-break: break-word;
+
   &.-muted {
     padding: 0.25em 0.6em;
     height: 1.2em;
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index 0081dee4..fb324cec 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -1,6 +1,7 @@
 <template>
   <Status
     v-if="notification.type === 'mention'"
+    class="Notification"
     :compact="true"
     :statusoid="notification.status"
   />
diff --git a/src/components/notifications/notifications.scss b/src/components/notifications/notifications.scss
index 2bb627a8..b513d8b5 100644
--- a/src/components/notifications/notifications.scss
+++ b/src/components/notifications/notifications.scss
@@ -37,11 +37,6 @@
 
 .notification {
   box-sizing: border-box;
-  border-bottom: 1px solid;
-  border-color: $fallback--border;
-  border-color: var(--border, $fallback--border);
-  word-wrap: break-word;
-  word-break: break-word;
 
   &:hover .animated.Avatar {
     canvas {
diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue
index 6fc9ceaa..5d3c614a 100644
--- a/src/components/settings_modal/tabs/filtering_tab.vue
+++ b/src/components/settings_modal/tabs/filtering_tab.vue
@@ -1,73 +1,138 @@
 <template>
   <div :label="$t('settings.filtering')">
     <div class="setting-item">
-      <div class="select-multiple">
-        <span class="label">{{ $t('settings.notification_visibility') }}</span>
-        <ul class="option-list">
-          <li>
-            <BooleanSetting path="notificationVisibility.likes">
-              {{ $t('settings.notification_visibility_likes') }}
-            </BooleanSetting>
-          </li>
-          <li>
-            <BooleanSetting path="notificationVisibility.repeats">
-              {{ $t('settings.notification_visibility_repeats') }}
-            </BooleanSetting>
-          </li>
-          <li>
-            <BooleanSetting path="notificationVisibility.follows">
-              {{ $t('settings.notification_visibility_follows') }}
-            </BooleanSetting>
-          </li>
-          <li>
-            <BooleanSetting path="notificationVisibility.mentions">
-              {{ $t('settings.notification_visibility_mentions') }}
-            </BooleanSetting>
-          </li>
-          <li>
-            <BooleanSetting path="notificationVisibility.moves">
-              {{ $t('settings.notification_visibility_moves') }}
-            </BooleanSetting>
-          </li>
-          <li>
-            <BooleanSetting path="notificationVisibility.emojiReactions">
-              {{ $t('settings.notification_visibility_emoji_reactions') }}
-            </BooleanSetting>
-          </li>
-        </ul>
-      </div>
-      <ChoiceSetting
-        id="replyVisibility"
-        path="replyVisibility"
-        :options="replyVisibilityOptions"
-      >
-        {{ $t('settings.replies_in_timeline') }}
-      </ChoiceSetting>
-      <div>
-        <BooleanSetting path="hidePostStats">
-          {{ $t('settings.hide_post_stats') }}
-        </BooleanSetting>
-      </div>
-      <div>
-        <BooleanSetting path="hideUserStats">
-          {{ $t('settings.hide_user_stats') }}
-        </BooleanSetting>
-      </div>
+      <h2>{{ $t('settings.posts') }}</h2>
+      <ul class="setting-list">
+        <li>
+          <BooleanSetting path="hideFilteredStatuses">
+            {{ $t('settings.hide_filtered_statuses') }}
+          </BooleanSetting>
+          <ul
+            class="setting-list suboptions"
+            :class="[{disabled: !streaming}]"
+          >
+            <li>
+              <BooleanSetting
+                :disabled="hideFilteredStatuses"
+                path="hideWordFilteredPosts"
+              >
+                {{ $t('settings.hide_wordfiltered_statuses') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting
+                :disabled="hideFilteredStatuses"
+                path="hideMutedThreads"
+              >
+                {{ $t('settings.hide_muted_threads') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting
+                :disabled="hideFilteredStatuses"
+                path="hideMutedPosts"
+                >
+                {{ $t('settings.hide_muted_posts') }}
+              </BooleanSetting>
+            </li>
+          </ul>
+        </li>
+        <li>
+          <BooleanSetting path="hidePostStats">
+            {{ $t('settings.hide_post_stats') }}
+          </BooleanSetting>
+        </li>
+        <ChoiceSetting
+          id="replyVisibility"
+          path="replyVisibility"
+          :options="replyVisibilityOptions"
+        >
+          {{ $t('settings.replies_in_timeline') }}
+        </ChoiceSetting>
+        <li>
+          <h3>{{ $t('settings.wordfilter') }}</h3>
+          <textarea
+            id="muteWords"
+            v-model="muteWordsString"
+            class="resize-height"
+          />
+          <div>{{ $t('settings.filtering_explanation') }}</div>
+        </li>
+        <h3>{{ $t('settings.attachments') }}</h3>
+        <li>
+          <label for="maxThumbnails">
+            {{ $t('settings.max_thumbnails') }}
+          </label>
+          <input
+            id="maxThumbnails"
+            path.number="maxThumbnails"
+            class="number-input"
+            type="number"
+            min="0"
+            step="1"
+          >
+        </li>
+        <li>
+          <BooleanSetting path="hideAttachments">
+            {{ $t('settings.hide_attachments_in_tl') }}
+          </BooleanSetting>
+        </li>
+        <li>
+          <BooleanSetting path="hideAttachmentsInConv">
+            {{ $t('settings.hide_attachments_in_convo') }}
+          </BooleanSetting>
+        </li>
+      </ul>
     </div>
     <div class="setting-item">
-      <div>
-        <p>{{ $t('settings.filtering_explanation') }}</p>
-        <textarea
-          id="muteWords"
-          v-model="muteWordsString"
-          class="resize-height"
-        />
-      </div>
-      <div>
-        <BooleanSetting path="hideFilteredStatuses">
-          {{ $t('settings.hide_filtered_statuses') }}
-        </BooleanSetting>
-      </div>
+      <h2>{{ $t('settings.user_profiles') }}</h2>
+      <ul class="setting-list">
+        <li>
+          <BooleanSetting path="hideUserStats">
+            {{ $t('settings.hide_user_stats') }}
+          </BooleanSetting>
+        </li>
+      </ul>
+    </div>
+    <div class="setting-item">
+      <h2>{{ $t('settings.notifications') }}</h2>
+      <ul class="setting-list">
+        <li class="select-multiple">
+          <span class="label">{{ $t('settings.notification_visibility') }}</span>
+          <ul class="option-list">
+            <li>
+              <BooleanSetting path="notificationVisibility.likes">
+                {{ $t('settings.notification_visibility_likes') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting path="notificationVisibility.repeats">
+                {{ $t('settings.notification_visibility_repeats') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting path="notificationVisibility.follows">
+                {{ $t('settings.notification_visibility_follows') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting path="notificationVisibility.mentions">
+                {{ $t('settings.notification_visibility_mentions') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting path="notificationVisibility.moves">
+                {{ $t('settings.notification_visibility_moves') }}
+              </BooleanSetting>
+            </li>
+            <li>
+              <BooleanSetting path="notificationVisibility.emojiReactions">
+                {{ $t('settings.notification_visibility_emoji_reactions') }}
+              </BooleanSetting>
+            </li>
+          </ul>
+        </li>
+      </ul>
     </div>
   </div>
 </template>
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index bdb29edf..5243d336 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -21,19 +21,9 @@
             {{ $t('settings.hide_wallpaper') }}
           </BooleanSetting>
         </li>
-      </ul>
-    </div>
-    <div class="setting-item">
-      <h2>{{ $t('nav.timeline') }}</h2>
-      <ul class="setting-list">
         <li>
-          <BooleanSetting path="hideMutedPosts">
-            {{ $t('settings.hide_muted_posts') }}
-          </BooleanSetting>
-        </li>
-        <li>
-          <BooleanSetting path="collapseMessageWithSubject">
-            {{ $t('settings.collapse_subject') }}
+          <BooleanSetting path="stopGifs">
+            {{ $t('settings.stop_gifs') }}
           </BooleanSetting>
         </li>
         <li>
@@ -63,98 +53,36 @@
             </small>
           </BooleanSetting>
         </li>
-        <li>
-          <BooleanSetting path="emojiReactionsOnTimeline">
-            {{ $t('settings.emoji_reactions_on_timeline') }}
-          </BooleanSetting>
-        </li>
         <li>
           <BooleanSetting path="virtualScrolling">
             {{ $t('settings.virtual_scrolling') }}
           </BooleanSetting>
         </li>
-      </ul>
-    </div>
-
-    <div class="setting-item">
-      <h2>{{ $t('settings.composing') }}</h2>
-      <ul class="setting-list">
-        <li>
-          <BooleanSetting path="scopeCopy">
-            {{ $t('settings.scope_copy') }}
-          </BooleanSetting>
-        </li>
-        <li>
-          <BooleanSetting path="alwaysShowSubjectInput">
-            {{ $t('settings.subject_input_always_show') }}
-          </BooleanSetting>
-        </li>
-        <li>
-          <ChoiceSetting
-            id="subjectLineBehavior"
-            path="subjectLineBehavior"
-            :options="subjectLineOptions"
-          >
-            {{ $t('settings.subject_line_behavior') }}
-          </ChoiceSetting>
-        </li>
-        <li v-if="postFormats.length > 0">
-          <ChoiceSetting
-            id="postContentType"
-            path="postContentType"
-            :options="postContentOptions"
-          >
-            {{ $t('settings.post_status_content_type') }}
-          </ChoiceSetting>
-        </li>
-        <li>
-          <BooleanSetting path="minimalScopesMode">
-            {{ $t('settings.minimal_scopes_mode') }}
-          </BooleanSetting>
-        </li>
-        <li>
-          <BooleanSetting path="sensitiveByDefault">
-            {{ $t('settings.sensitive_by_default') }}
-          </BooleanSetting>
-        </li>
         <li>
           <BooleanSetting path="autohideFloatingPostButton">
             {{ $t('settings.autohide_floating_post_button') }}
           </BooleanSetting>
         </li>
-        <li>
-          <BooleanSetting path="padEmoji">
-            {{ $t('settings.pad_emoji') }}
-          </BooleanSetting>
-        </li>
       </ul>
     </div>
-
     <div class="setting-item">
-      <h2>{{ $t('settings.attachments') }}</h2>
+      <h2>{{ $t('settings.post_look_feel') }}</h2>
       <ul class="setting-list">
         <li>
-          <BooleanSetting path="hideAttachments">
-            {{ $t('settings.hide_attachments_in_tl') }}
+          <BooleanSetting path="collapseMessageWithSubject">
+            {{ $t('settings.collapse_subject') }}
           </BooleanSetting>
         </li>
         <li>
-          <BooleanSetting path="hideAttachmentsInConv">
-            {{ $t('settings.hide_attachments_in_convo') }}
+          <BooleanSetting path="emojiReactionsOnTimeline">
+            {{ $t('settings.emoji_reactions_on_timeline') }}
           </BooleanSetting>
         </li>
+        <h3>{{ $t('settings.attachments') }}</h3>
         <li>
-          <label for="maxThumbnails">
-            {{ $t('settings.max_thumbnails') }}
-          </label>
-          <input
-            id="maxThumbnails"
-            path.number="maxThumbnails"
-            class="number-input"
-            type="number"
-            min="0"
-            step="1"
-          >
+          <BooleanSetting path="useContainFit">
+            {{ $t('settings.use_contain_fit') }}
+          </BooleanSetting>
         </li>
         <li>
           <BooleanSetting path="hideNsfw">
@@ -179,11 +107,6 @@
             </BooleanSetting>
           </li>
         </ul>
-        <li>
-          <BooleanSetting path="stopGifs">
-            {{ $t('settings.stop_gifs') }}
-          </BooleanSetting>
-        </li>
         <li>
           <BooleanSetting path="loopVideo">
             {{ $t('settings.loop_video') }}
@@ -213,31 +136,70 @@
             {{ $t('settings.play_videos_in_modal') }}
           </BooleanSetting>
         </li>
+        <h3>{{ $t('settings.fun') }}</h3>
         <li>
-          <BooleanSetting path="useContainFit">
-            {{ $t('settings.use_contain_fit') }}
+          <BooleanSetting path="greentext">
+            {{ $t('settings.greentext') }}
           </BooleanSetting>
         </li>
       </ul>
     </div>
 
     <div class="setting-item">
-      <h2>{{ $t('settings.notifications') }}</h2>
+      <h2>{{ $t('settings.composing') }}</h2>
       <ul class="setting-list">
         <li>
-          <BooleanSetting path="webPushNotifications">
-            {{ $t('settings.enable_web_push_notifications') }}
+          <BooleanSetting path="scopeCopy">
+            {{ $t('settings.scope_copy') }}
+          </BooleanSetting>
+        </li>
+        <li>
+          <BooleanSetting path="alwaysShowSubjectInput">
+            {{ $t('settings.subject_input_always_show') }}
+          </BooleanSetting>
+        </li>
+        <li>
+          <ChoiceSetting
+            id="subjectLineBehavior"
+            path="subjectLineBehavior"
+            :options="subjectLineOptions"
+          >
+            {{ $t('settings.subject_line_behavior') }}
+          </ChoiceSetting>
+        </li>
+        <li v-if="postFormats.length > 0">
+          <ChoiceSetting
+            id="postContentType"
+            path="postContentType"
+            :options="postContentOptions"
+          >
+            {{ $t('settings.post_status_content_type') }}
+          </ChoiceSetting>
+        </li>
+        <li>
+          <BooleanSetting path="minimalScopesMode">
+            {{ $t('settings.minimal_scopes_mode') }}
+          </BooleanSetting>
+        </li>
+        <li>
+          <BooleanSetting path="sensitiveByDefault">
+            {{ $t('settings.sensitive_by_default') }}
+          </BooleanSetting>
+        </li>
+        <li>
+          <BooleanSetting path="padEmoji">
+            {{ $t('settings.pad_emoji') }}
           </BooleanSetting>
         </li>
       </ul>
     </div>
 
     <div class="setting-item">
-      <h2>{{ $t('settings.fun') }}</h2>
+      <h2>{{ $t('settings.notifications') }}</h2>
       <ul class="setting-list">
         <li>
-          <BooleanSetting path="greentext">
-            {{ $t('settings.greentext') }}
+          <BooleanSetting path="webPushNotifications">
+            {{ $t('settings.enable_web_push_notifications') }}
           </BooleanSetting>
         </li>
       </ul>
diff --git a/src/components/status/status.js b/src/components/status/status.js
index 470c01f1..5c7caa28 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -157,26 +157,32 @@ const Status = {
       return muteWordHits(this.status, this.muteWords)
     },
     muted () {
+      if (this.statusoid.user.id === this.currentUser.id) return false
+      const reasonsToMute = this.userIsMuted ||
+        // Thread is muted
+        status.thread_muted ||
+        // Wordfiltered
+        this.muteWordHits.length > 0
+      return !this.unmuted && !this.shouldNotMute && reasonsToMute
+    },
+    userIsMuted () {
       if (this.statusoid.user.id === this.currentUser.id) return false
       const { status } = this
       const { reblog } = status
       const relationship = this.$store.getters.relationship(status.user.id)
       const relationshipReblog = reblog && this.$store.getters.relationship(reblog.user.id)
-      const reasonsToMute = (
-        // Post is muted according to BE
-        status.muted ||
+      return status.muted ||
         // Reprööt of a muted post according to BE
         (reblog && reblog.muted) ||
         // Muted user
         relationship.muting ||
         // Muted user of a reprööt
-        (relationshipReblog && relationshipReblog.muting) ||
-        // Thread is muted
-        status.thread_muted ||
-        // Wordfiltered
-        this.muteWordHits.length > 0
-      )
-      const excusesNotToMute = (
+        (relationshipReblog && relationshipReblog.muting)
+    },
+    shouldNotMute () {
+      const { status } = this
+      const { reblog } = status
+      return (
         (
           this.inProfile && (
             // Don't mute user's posts on user timeline (except reblogs)
@@ -189,14 +195,26 @@ const Status = {
         (this.inConversation && status.thread_muted)
         // No excuses if post has muted words
       ) && !this.muteWordHits.length > 0
-
-      return !this.unmuted && !excusesNotToMute && reasonsToMute
+    },
+    hideMutedUsers () {
+      return this.mergedConfig.hideMutedPosts
+    },
+    hideMutedThreads () {
+      return this.mergedConfig.hideMutedThreads
     },
     hideFilteredStatuses () {
       return this.mergedConfig.hideFilteredStatuses
     },
+    hideWordFilteredPosts () {
+      return this.mergedConfig.hideWordFilteredPosts
+    },
     hideStatus () {
-      return (this.muted && this.hideFilteredStatuses) || this.virtualHidden
+      return (this.virtualHidden || !this.shouldNotMute) && (
+        (this.muted && this.hideFilteredStatuses) ||
+        (this.userIsMuted && this.hideMutedUsers) ||
+        (this.status.thread_muted && this.hideMutedThreads) ||
+        (this.muteWordHits.length > 0 && this.hideWordFilteredPosts)
+      )
     },
     isFocused () {
       // retweet or root of an expanded conversation
diff --git a/src/components/timeline/timeline_quick_settings.js b/src/components/timeline/timeline_quick_settings.js
index eae65a55..7b4931ce 100644
--- a/src/components/timeline/timeline_quick_settings.js
+++ b/src/components/timeline/timeline_quick_settings.js
@@ -48,10 +48,9 @@ const TimelineQuickSettings = {
       }
     },
     hideMutedPosts: {
-      get () { return this.mergedConfig.hideMutedPosts || this.mergedConfig.hideFilteredStatuses },
+      get () { return this.mergedConfig.hideFilteredStatuses },
       set () {
         const value = !this.hideMutedPosts
-        this.$store.dispatch('setOption', { name: 'hideMutedPosts', value })
         this.$store.dispatch('setOption', { name: 'hideFilteredStatuses', value })
       }
     }
diff --git a/src/i18n/en.json b/src/i18n/en.json
index aa440ac1..89e808aa 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -259,6 +259,7 @@
     "security": "Security",
     "setting_changed": "Setting is different from default",
     "enter_current_password_to_confirm": "Enter your current password to confirm your identity",
+    "post_look_feel": "Posts Look & Feel",
     "mfa": {
       "otp": "OTP",
       "setup_otp": "Setup OTP",
@@ -331,6 +332,7 @@
     "emoji_reactions_on_timeline": "Show emoji reactions on timeline",
     "export_theme": "Save preset",
     "filtering": "Filtering",
+    "wordfilter": "Wordfilter",
     "filtering_explanation": "All statuses containing these words will be muted, one per line",
     "word_filter": "Word filter",
     "follow_export": "Follow export",
@@ -346,7 +348,7 @@
     "hide_media_previews": "Hide media previews",
     "hide_muted_posts": "Hide posts of muted users",
     "hide_all_muted_posts": "Hide muted posts",
-    "max_thumbnails": "Maximum amount of thumbnails per post",
+    "max_thumbnails": "Maximum amount of thumbnails per post (empty = no limit)",
     "hide_isp": "Hide instance-specific panel",
     "right_sidebar": "Show sidebar on the right side",
     "hide_wallpaper": "Hide instance wallpaper",
@@ -354,7 +356,9 @@
     "use_one_click_nsfw": "Open NSFW attachments with just one click",
     "hide_post_stats": "Hide post statistics (e.g. the number of favorites)",
     "hide_user_stats": "Hide user statistics (e.g. the number of followers)",
-    "hide_filtered_statuses": "Hide filtered statuses",
+    "hide_filtered_statuses": "Hide all filtered posts",
+    "hide_wordfiltered_statuses": "Hide word-filtered statuses",
+    "hide_muted_threads": "Hide muted threads",
     "import_blocks_from_a_csv_file": "Import blocks from a csv file",
     "import_followers_from_a_csv_file": "Import follows from a csv file",
     "import_theme": "Load preset",
@@ -395,6 +399,8 @@
     "name_bio": "Name & bio",
     "new_email": "New email",
     "new_password": "New password",
+    "posts": "Posts",
+    "user_profiles": "User Profiles",
     "notification_visibility": "Types of notifications to show",
     "notification_visibility_follows": "Follows",
     "notification_visibility_likes": "Favorites",
@@ -411,7 +417,7 @@
     "hide_followers_count_description": "Don't show follower count",
     "show_admin_badge": "Show \"Admin\" badge in my profile",
     "show_moderator_badge": "Show \"Moderator\" badge in my profile",
-    "nsfw_clickthrough": "Enable clickthrough attachment and link preview image hiding for NSFW statuses",
+    "nsfw_clickthrough": "Censor NSFW content",
     "oauth_tokens": "OAuth tokens",
     "token": "Token",
     "refresh_token": "Refresh token",
@@ -455,7 +461,7 @@
     "subject_line_noop": "Do not copy",
     "post_status_content_type": "Post status content type",
     "sensitive_by_default": "Mark posts as sensitive by default",
-    "stop_gifs": "Play-on-hover GIFs",
+    "stop_gifs": "Pause animated images until you hover on them",
     "streaming": "Enable automatic streaming of new posts when scrolled to the top",
     "user_mutes": "Users",
     "useStreamingApi": "Receive posts and notifications real-time",
diff --git a/src/modules/config.js b/src/modules/config.js
index 0f596750..df66bfe6 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -23,6 +23,8 @@ export const defaultState = {
   hideInstanceWallpaper: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: undefined, // instance default
+  hideMutedThreads: undefined, // instance default
+  hideWordFilteredPosts: undefined, // instance default
   collapseMessageWithSubject: undefined, // instance default
   padEmoji: true,
   hideAttachments: false,
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 539b9c66..60038f08 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -21,7 +21,10 @@ const defaultState = {
   collapseMessageWithSubject: false,
   greentext: false,
   hideFilteredStatuses: false,
+  // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
+  hideMutedThreads: true,
+  hideWordFilteredPosts: false,
   hidePostStats: false,
   hideSitename: false,
   hideUserStats: false,
-- 
cgit v1.2.3-70-g09d2


From adfe56a3a31b3c4a8c2c206c06bebf9c4af675d1 Mon Sep 17 00:00:00 2001
From: Eris <femmediscord@gmail.com>
Date: Mon, 14 Jun 2021 17:54:40 +0000
Subject: New option: Always show floating New Post button

---
 .gitignore                                                       | 2 ++
 CHANGELOG.md                                                     | 2 +-
 CONTRIBUTORS.md                                                  | 1 +
 src/App.js                                                       | 3 +++
 src/App.vue                                                      | 1 +
 .../mobile_post_status_button/mobile_post_status_button.js       | 3 +++
 .../mobile_post_status_button/mobile_post_status_button.vue      | 4 ++--
 src/components/settings_modal/tabs/general_tab.vue               | 5 +++++
 src/components/shout_panel/shout_panel.vue                       | 9 ++++++++-
 src/i18n/en.json                                                 | 1 +
 src/modules/config.js                                            | 1 +
 11 files changed, 28 insertions(+), 4 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/.gitignore b/.gitignore
index 479d57c4..8b23774f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@ test/e2e/reports
 selenium-debug.log
 .idea/
 config/local.json
+.gitignore
+config/local.example.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 905d9f65..4651c01d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Added option to mark posts as sensitive by default
 - Added quick filters for notifications
 - Implemented user option to change sidebar position to the right side
-
+- Implemented user option to always show floating New Post button (normally mobile-only)
 
 ## [2.3.0] - 2021-03-01
 ### Fixed
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index d7c217ce..f666a4ef 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -3,6 +3,7 @@ Contributors of this project.
 - Constance Variable (lambadalambda@social.heldscal.la): Code
 - Coco Snuss (cocosnuss@social.heldscal.la): Code
 - wakarimasen (wakarimasen@shitposter.club): NSFW hiding image
+- eris (eris@disqordia.space): Code
 - dtluna (dtluna@social.heldscal.la): Code
 - sonyam (sonyam@social.heldscal.la): Background images
 - hakui (hakui@freezepeach.xyz): CSS and styling
diff --git a/src/App.js b/src/App.js
index fe4c30cb..e7ea3851 100644
--- a/src/App.js
+++ b/src/App.js
@@ -73,6 +73,9 @@ export default {
         this.$store.state.instance.instanceSpecificPanelContent
     },
     showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
+    shoutboxPosition () {
+      return this.$store.getters.mergedConfig.showNewPostButton || false
+    },
     isMobileLayout () { return this.$store.state.interface.mobileLayout },
     privateMode () { return this.$store.state.instance.private },
     sidebarAlign () {
diff --git a/src/App.vue b/src/App.vue
index 6c582c03..6b867498 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -53,6 +53,7 @@
       v-if="currentUser && shout"
       :floating="true"
       class="floating-shout mobile-hidden"
+      :class="{ 'left': shoutboxPosition }"
     />
     <MobilePostStatusButton />
     <UserReportingModal />
diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.js b/src/components/mobile_post_status_button/mobile_post_status_button.js
index 366ea89c..d27fb3b8 100644
--- a/src/components/mobile_post_status_button/mobile_post_status_button.js
+++ b/src/components/mobile_post_status_button/mobile_post_status_button.js
@@ -44,6 +44,9 @@ const MobilePostStatusButton = {
 
       return this.autohideFloatingPostButton && (this.hidden || this.inputActive)
     },
+    isPersistent () {
+      return !!this.$store.getters.mergedConfig.showNewPostButton
+    },
     autohideFloatingPostButton () {
       return !!this.$store.getters.mergedConfig.autohideFloatingPostButton
     }
diff --git a/src/components/mobile_post_status_button/mobile_post_status_button.vue b/src/components/mobile_post_status_button/mobile_post_status_button.vue
index 767f8244..37becf4c 100644
--- a/src/components/mobile_post_status_button/mobile_post_status_button.vue
+++ b/src/components/mobile_post_status_button/mobile_post_status_button.vue
@@ -2,7 +2,7 @@
   <div v-if="isLoggedIn">
     <button
       class="button-default new-status-button"
-      :class="{ 'hidden': isHidden }"
+      :class="{ 'hidden': isHidden, 'always-show': isPersistent }"
       @click="openPostForm"
     >
       <FAIcon icon="pen" />
@@ -47,7 +47,7 @@
 }
 
 @media all and (min-width: 801px) {
-  .new-status-button {
+  .new-status-button:not(.always-show) {
     display: none;
   }
 }
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index bdb29edf..4c09d047 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -117,6 +117,11 @@
             {{ $t('settings.sensitive_by_default') }}
           </BooleanSetting>
         </li>
+        <li>
+          <BooleanSetting path="showNewPostButton">
+            {{ $t('settings.showPostButton') }}
+          </BooleanSetting>
+        </li>
         <li>
           <BooleanSetting path="autohideFloatingPostButton">
             {{ $t('settings.autohide_floating_post_button') }}
diff --git a/src/components/shout_panel/shout_panel.vue b/src/components/shout_panel/shout_panel.vue
index f90baf80..c88797d1 100644
--- a/src/components/shout_panel/shout_panel.vue
+++ b/src/components/shout_panel/shout_panel.vue
@@ -79,12 +79,19 @@
 
 .floating-shout {
   position: fixed;
-  right: 0px;
   bottom: 0px;
   z-index: 1000;
   max-width: 25em;
 }
 
+.floating-shout.left {
+  left: 0px;
+}
+
+.floating-shout:not(.left) {
+  right: 0px;
+}
+
 .shout-panel {
   .shout-heading {
     cursor: pointer;
diff --git a/src/i18n/en.json b/src/i18n/en.json
index aa440ac1..26f51cea 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -349,6 +349,7 @@
     "max_thumbnails": "Maximum amount of thumbnails per post",
     "hide_isp": "Hide instance-specific panel",
     "right_sidebar": "Show sidebar on the right side",
+    "showPostButton": "Always show floating New Post button",
     "hide_wallpaper": "Hide instance wallpaper",
     "preload_images": "Preload images",
     "use_one_click_nsfw": "Open NSFW attachments with just one click",
diff --git a/src/modules/config.js b/src/modules/config.js
index 0f596750..30c77a7b 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -34,6 +34,7 @@ export const defaultState = {
   loopVideoSilentOnly: true,
   streaming: false,
   emojiReactionsOnTimeline: true,
+  showNewPostButton: false,
   autohideFloatingPostButton: false,
   pauseOnUnfocused: true,
   stopGifs: false,
-- 
cgit v1.2.3-70-g09d2


From 0c1014524232907925bf5fa59079dd06d0ef0472 Mon Sep 17 00:00:00 2001
From: Eris <femmediscord@gmail.com>
Date: Mon, 14 Jun 2021 19:42:56 +0000
Subject: New option: Hide shoutbox

---
 src/App.js                                         | 3 +++
 src/App.vue                                        | 2 +-
 src/components/settings_modal/tabs/general_tab.js  | 1 +
 src/components/settings_modal/tabs/general_tab.vue | 5 +++++
 src/i18n/en.json                                   | 1 +
 src/modules/config.js                              | 1 +
 6 files changed, 12 insertions(+), 1 deletion(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/App.js b/src/App.js
index fe4c30cb..8d9ec8c7 100644
--- a/src/App.js
+++ b/src/App.js
@@ -73,6 +73,9 @@ export default {
         this.$store.state.instance.instanceSpecificPanelContent
     },
     showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel },
+    hideSB () {
+      return this.$store.getters.mergedConfig.hideShoutbox
+    },
     isMobileLayout () { return this.$store.state.interface.mobileLayout },
     privateMode () { return this.$store.state.instance.private },
     sidebarAlign () {
diff --git a/src/App.vue b/src/App.vue
index 6c582c03..39decde9 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -50,7 +50,7 @@
       <media-modal />
     </div>
     <shout-panel
-      v-if="currentUser && shout"
+      v-if="currentUser && shout && !hideSB"
       :floating="true"
       class="floating-shout mobile-hidden"
     />
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index 07fccf57..0e838e59 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -50,6 +50,7 @@ const GeneralTab = {
       return this.$store.state.instance.background &&
         !this.$store.state.users.currentUser.background_image
     },
+    shout () { return this.$store.state.shout.channel.state === 'joined' }, 
     ...SharedComputedObject()
   }
 }
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index bdb29edf..3a9af1ea 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -21,6 +21,11 @@
             {{ $t('settings.hide_wallpaper') }}
           </BooleanSetting>
         </li>
+        <li v-if="shout">
+          <BooleanSetting path="hideShoutbox">
+            {{ $t('settings.hide_shoutbox') }} {{ $t('shoutbox.title') }}
+          </BooleanSetting>
+        </li>
       </ul>
     </div>
     <div class="setting-item">
diff --git a/src/i18n/en.json b/src/i18n/en.json
index aa440ac1..79dcb919 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -349,6 +349,7 @@
     "max_thumbnails": "Maximum amount of thumbnails per post",
     "hide_isp": "Hide instance-specific panel",
     "right_sidebar": "Show sidebar on the right side",
+    "hide_shoutbox": "Hide ",
     "hide_wallpaper": "Hide instance wallpaper",
     "preload_images": "Preload images",
     "use_one_click_nsfw": "Open NSFW attachments with just one click",
diff --git a/src/modules/config.js b/src/modules/config.js
index 0f596750..bdab3f4d 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -21,6 +21,7 @@ export const defaultState = {
   customThemeSource: undefined,
   hideISP: false,
   hideInstanceWallpaper: false,
+  hideShoutbox: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: undefined, // instance default
   collapseMessageWithSubject: undefined, // instance default
-- 
cgit v1.2.3-70-g09d2


From 4639e30cb8e6086a57acbe35d864e8b453e197ba Mon Sep 17 00:00:00 2001
From: Eris <femmediscord@gmail.com>
Date: Mon, 14 Jun 2021 20:41:34 +0000
Subject: Fix config naming for consistency

---
 src/components/settings_modal/tabs/general_tab.vue | 4 ++--
 src/i18n/en.json                                   | 2 +-
 src/modules/config.js                              | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 4c09d047..44f6fa3e 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -118,8 +118,8 @@
           </BooleanSetting>
         </li>
         <li>
-          <BooleanSetting path="showNewPostButton">
-            {{ $t('settings.showPostButton') }}
+          <BooleanSetting path="alwaysShowNewPostButton">
+            {{ $t('settings.always_show_post_button') }}
           </BooleanSetting>
         </li>
         <li>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 26f51cea..0ee871de 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -349,7 +349,7 @@
     "max_thumbnails": "Maximum amount of thumbnails per post",
     "hide_isp": "Hide instance-specific panel",
     "right_sidebar": "Show sidebar on the right side",
-    "showPostButton": "Always show floating New Post button",
+    "always_show_post_button": "Always show floating New Post button",
     "hide_wallpaper": "Hide instance wallpaper",
     "preload_images": "Preload images",
     "use_one_click_nsfw": "Open NSFW attachments with just one click",
diff --git a/src/modules/config.js b/src/modules/config.js
index 30c77a7b..28ee651b 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -34,7 +34,7 @@ export const defaultState = {
   loopVideoSilentOnly: true,
   streaming: false,
   emojiReactionsOnTimeline: true,
-  showNewPostButton: false,
+  alwaysShowNewPostButton: false,
   autohideFloatingPostButton: false,
   pauseOnUnfocused: true,
   stopGifs: false,
-- 
cgit v1.2.3-70-g09d2


From 5047663c513841ea708f58e672bf193a55a96a82 Mon Sep 17 00:00:00 2001
From: Eris <femmediscord@gmail.com>
Date: Tue, 15 Jun 2021 00:25:09 +0000
Subject: Make locale language cleaner

---
 src/components/settings_modal/tabs/general_tab.vue | 2 +-
 src/i18n/en.json                                   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 3a9af1ea..8c255dd3 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -23,7 +23,7 @@
         </li>
         <li v-if="shout">
           <BooleanSetting path="hideShoutbox">
-            {{ $t('settings.hide_shoutbox') }} {{ $t('shoutbox.title') }}
+            {{ $t('general.hide') }} {{ $t('shoutbox.title') }}
           </BooleanSetting>
         </li>
       </ul>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 79dcb919..247b7167 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -75,6 +75,7 @@
     "confirm": "Confirm",
     "verify": "Verify",
     "close": "Close",
+    "hide": "Hide",
     "peek": "Peek",
     "role": {
       "admin": "Admin",
@@ -349,7 +350,6 @@
     "max_thumbnails": "Maximum amount of thumbnails per post",
     "hide_isp": "Hide instance-specific panel",
     "right_sidebar": "Show sidebar on the right side",
-    "hide_shoutbox": "Hide ",
     "hide_wallpaper": "Hide instance wallpaper",
     "preload_images": "Preload images",
     "use_one_click_nsfw": "Open NSFW attachments with just one click",
-- 
cgit v1.2.3-70-g09d2


From 7e3393b5a2eda7f696781853123de8df965ffbf2 Mon Sep 17 00:00:00 2001
From: Eris <femmediscord@gmail.com>
Date: Tue, 15 Jun 2021 00:59:36 +0000
Subject: Use cleaner instance config check for shoutbox setting

---
 src/components/settings_modal/tabs/general_tab.js  | 2 +-
 src/components/settings_modal/tabs/general_tab.vue | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index be0fc768..eeda61bf 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -50,7 +50,7 @@ const GeneralTab = {
       return this.$store.state.instance.background &&
         !this.$store.state.users.currentUser.background_image
     },
-    shout () { return this.$store.state.shout.channel.state === 'joined' },
+    instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable },
     ...SharedComputedObject()
   }
 }
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 8c255dd3..84f8ef8d 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -21,7 +21,7 @@
             {{ $t('settings.hide_wallpaper') }}
           </BooleanSetting>
         </li>
-        <li v-if="shout">
+        <li v-if="instanceShoutboxPresent">
           <BooleanSetting path="hideShoutbox">
             {{ $t('general.hide') }} {{ $t('shoutbox.title') }}
           </BooleanSetting>
-- 
cgit v1.2.3-70-g09d2


From d7a53aec613c6da7f67906b16f052ec4e7441960 Mon Sep 17 00:00:00 2001
From: Eris <femmediscord@gmail.com>
Date: Tue, 15 Jun 2021 18:09:00 +0000
Subject: Use proper setting name

---
 src/components/settings_modal/tabs/general_tab.vue | 2 +-
 src/i18n/en.json                                   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 84f8ef8d..d3e71b31 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -23,7 +23,7 @@
         </li>
         <li v-if="instanceShoutboxPresent">
           <BooleanSetting path="hideShoutbox">
-            {{ $t('general.hide') }} {{ $t('shoutbox.title') }}
+            {{ $t('settings.hide_shoutbox') }}
           </BooleanSetting>
         </li>
       </ul>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 247b7167..6511019c 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -75,7 +75,6 @@
     "confirm": "Confirm",
     "verify": "Verify",
     "close": "Close",
-    "hide": "Hide",
     "peek": "Peek",
     "role": {
       "admin": "Admin",
@@ -349,6 +348,7 @@
     "hide_all_muted_posts": "Hide muted posts",
     "max_thumbnails": "Maximum amount of thumbnails per post",
     "hide_isp": "Hide instance-specific panel",
+    "hide_shoutbox": "Hide instance shoutbox",
     "right_sidebar": "Show sidebar on the right side",
     "hide_wallpaper": "Hide instance wallpaper",
     "preload_images": "Preload images",
-- 
cgit v1.2.3-70-g09d2


From 76547fe66d1771f5bff732a34b0547f890f4621a Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 10 Jan 2022 00:37:39 -0500
Subject: Add a pref for whether to display mention as icon or text

---
 src/components/mention_link/mention_link.js        | 3 +++
 src/components/mention_link/mention_link.vue       | 9 +++++----
 src/components/settings_modal/tabs/general_tab.vue | 5 +++++
 src/modules/config.js                              | 1 +
 src/modules/instance.js                            | 1 +
 5 files changed, 15 insertions(+), 4 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 65c62baa..637641af 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -85,6 +85,9 @@ const MentionLink = {
         this.highlightType
       ]
     },
+    useAtIcon () {
+      return this.mergedConfig.useAtIcon
+    },
     ...mapGetters(['mergedConfig']),
     ...mapState({
       currentUser: state => state.users.currentUser
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index a22b486c..f633bf50 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -24,13 +24,14 @@
       >
         <!-- eslint-disable vue/no-v-html -->
         <FAIcon
+          v-if="useAtIcon"
           size="sm"
           icon="at"
           class="at"
-        /><span class="shortName"><span
-          class="userName"
-          v-html="userName"
-        /></span>
+        /><span class="shortName">{{ !useAtIcon ? '@' : '' }}<span
+            class="userName"
+            v-html="userName"
+          /></span>
         <span
           v-if="isYou"
           class="you"
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index bd3ee84e..5fec2d89 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -147,6 +147,11 @@
             {{ $t('settings.greentext') }}
           </BooleanSetting>
         </li>
+        <li>
+          <BooleanSetting path="useAtIcon">
+            {{ $t('settings.use_at_icon') }}
+          </BooleanSetting>
+        </li>
       </ul>
     </div>
 
diff --git a/src/modules/config.js b/src/modules/config.js
index c79302b5..43c8b92f 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -70,6 +70,7 @@ export const defaultState = {
   useOneClickNsfw: false,
   useContainFit: false,
   greentext: undefined, // instance default
+  useAtIcon: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
   virtualScrolling: undefined, // instance default
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 60038f08..aaaf7acf 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -20,6 +20,7 @@ const defaultState = {
   background: '/static/aurora_borealis.jpg',
   collapseMessageWithSubject: false,
   greentext: false,
+  useAtIcon: false,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
-- 
cgit v1.2.3-70-g09d2


From 1d4b1b296e8ee37f119f419df49791d99fef4774 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 10 Jan 2022 01:16:33 -0500
Subject: Add pref for whether to display full user names and tooltips

---
 src/components/mention_link/mention_link.js        | 20 ++++++++++++++++++++
 src/components/mention_link/mention_link.vue       | 16 +++++++++++-----
 src/components/settings_modal/tabs/general_tab.js  |  5 +++++
 src/components/settings_modal/tabs/general_tab.vue | 19 +++++++++++++++++++
 src/modules/config.js                              |  5 ++++-
 src/modules/instance.js                            |  5 +++++
 6 files changed, 64 insertions(+), 6 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 637641af..f71c7716 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -50,6 +50,10 @@ const MentionLink = {
     userName () {
       return this.user && this.userNameFullUi.split('@')[0]
     },
+    serverName () {
+      // XXX assumed that domain does not contain @
+      return this.user && (this.userNameFullUi.split('@')[1] || this.$store.getters.instanceDomain)
+    },
     userNameFull () {
       return this.user && this.user.screen_name
     },
@@ -88,6 +92,22 @@ const MentionLink = {
     useAtIcon () {
       return this.mergedConfig.useAtIcon
     },
+    isRemote () {
+      return this.userName !== this.userNameFull
+    },
+    shouldShowFullUserName () {
+      const conf = this.mergedConfig.mentionLinkDisplay
+      if (conf === 'short') {
+        return false
+      } else if (conf === 'full') {
+        return true
+      } else { // full_for_remote
+        return this.isRemote
+      }
+    },
+    shouldShowTooltip () {
+      return this.mergedConfig.mentionLinkShowTooltip && this.mergedConfig.mentionLinkDisplay === 'short' && this.isRemote
+    },
     ...mapGetters(['mergedConfig']),
     ...mapState({
       currentUser: state => state.users.currentUser
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index f633bf50..fe16cbf5 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -28,10 +28,16 @@
           size="sm"
           icon="at"
           class="at"
-        /><span class="shortName">{{ !useAtIcon ? '@' : '' }}<span
-            class="userName"
-            v-html="userName"
-          /></span>
+        /><span
+          class="shortName"
+        >{{ !useAtIcon ? '@' : '' }}<span
+          class="userName"
+          v-html="userName"
+        /><span
+          v-if="shouldShowFullUserName"
+          class="serverName"
+          v-html="'@' + serverName"
+        /></span>
         <span
           v-if="isYou"
           class="you"
@@ -39,7 +45,7 @@
         <!-- eslint-enable vue/no-v-html -->
       </a>
       <span
-        v-if="userName !== userNameFull"
+        v-if="shouldShowTooltip"
         class="full popover-default"
         :class="[highlightType]"
       >
diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js
index eeda61bf..952c328d 100644
--- a/src/components/settings_modal/tabs/general_tab.js
+++ b/src/components/settings_modal/tabs/general_tab.js
@@ -20,6 +20,11 @@ const GeneralTab = {
         value: mode,
         label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`)
       })),
+      mentionLinkDisplayOptions: ['short', 'full_for_remote', 'full'].map(mode => ({
+        key: mode,
+        value: mode,
+        label: this.$t(`settings.mention_link_display_${mode}`)
+      })),
       loopSilentAvailable:
       // Firefox
       Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') ||
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 5fec2d89..8fce1eee 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -152,6 +152,25 @@
             {{ $t('settings.use_at_icon') }}
           </BooleanSetting>
         </li>
+        <li>
+          <ChoiceSetting
+            id="mentionLinkDisplay"
+            path="mentionLinkDisplay"
+            :options="mentionLinkDisplayOptions"
+          >
+            {{ $t('settings.mention_link_display') }}
+          </ChoiceSetting>
+        </li>
+        <ul
+          v-if="mentionLinkDisplay === 'short'"
+          class="setting-list suboptions"
+        >
+          <li>
+            <BooleanSetting path="mentionLinkShowTooltip">
+              {{ $t('settings.mention_link_show_tooltip') }}
+            </BooleanSetting>
+          </li>
+        </ul>
       </ul>
     </div>
 
diff --git a/src/modules/config.js b/src/modules/config.js
index 43c8b92f..e1a49a7d 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -11,7 +11,8 @@ const browserLocale = (window.navigator.language || 'en').split('-')[0]
  */
 export const multiChoiceProperties = [
   'postContentType',
-  'subjectLineBehavior'
+  'subjectLineBehavior',
+  'mentionLinkDisplay' // short | full_for_remote | full
 ]
 
 export const defaultState = {
@@ -71,6 +72,8 @@ export const defaultState = {
   useContainFit: false,
   greentext: undefined, // instance default
   useAtIcon: undefined, // instance default
+  mentionLinkDisplay: undefined, // instance default
+  mentionLinkShowTooltip: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
   virtualScrolling: undefined, // instance default
diff --git a/src/modules/instance.js b/src/modules/instance.js
index aaaf7acf..200a7a6f 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -21,6 +21,8 @@ const defaultState = {
   collapseMessageWithSubject: false,
   greentext: false,
   useAtIcon: false,
+  mentionLinkDisplay: 'short',
+  mentionLinkShowTooltip: true,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
@@ -101,6 +103,9 @@ const instance = {
       return instanceDefaultProperties
         .map(key => [key, state[key]])
         .reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {})
+    },
+    instanceDomain (state) {
+      return new URL(state.server).hostname
     }
   },
   actions: {
-- 
cgit v1.2.3-70-g09d2


From 9fde13c9685e934c8f610c96d481457b3d37c389 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 10 Jan 2022 02:05:41 -0500
Subject: Add option to display user avatar in mention link

---
 src/components/mention_link/mention_link.js        | 7 +++++++
 src/components/mention_link/mention_link.scss      | 9 +++++++++
 src/components/mention_link/mention_link.vue       | 5 +++++
 src/components/settings_modal/tabs/general_tab.vue | 5 +++++
 src/modules/config.js                              | 1 +
 src/modules/instance.js                            | 1 +
 6 files changed, 28 insertions(+)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index f71c7716..426dbe97 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -1,6 +1,7 @@
 import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
 import { mapGetters, mapState } from 'vuex'
 import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
+import UserAvatar from '../user_avatar/user_avatar.vue'
 import { library } from '@fortawesome/fontawesome-svg-core'
 import {
   faAt
@@ -12,6 +13,9 @@ library.add(
 
 const MentionLink = {
   name: 'MentionLink',
+  components: {
+    UserAvatar
+  },
   props: {
     url: {
       required: true,
@@ -108,6 +112,9 @@ const MentionLink = {
     shouldShowTooltip () {
       return this.mergedConfig.mentionLinkShowTooltip && this.mergedConfig.mentionLinkDisplay === 'short' && this.isRemote
     },
+    shouldShowAvatar () {
+      return this.mergedConfig.mentionLinkShowAvatar
+    },
     ...mapGetters(['mergedConfig']),
     ...mapState({
       currentUser: state => state.users.currentUser
diff --git a/src/components/mention_link/mention_link.scss b/src/components/mention_link/mention_link.scss
index 5f467582..be00093a 100644
--- a/src/components/mention_link/mention_link.scss
+++ b/src/components/mention_link/mention_link.scss
@@ -1,3 +1,5 @@
+@import '../../_variables.scss';
+
 .MentionLink {
   position: relative;
   white-space: normal;
@@ -10,6 +12,13 @@
     border-radius: 2px;
   }
 
+  .mention-avatar {
+    border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+    width: 1.5em;
+    height: 1.5em;
+    vertical-align: middle;
+  }
+
   .full {
     position: absolute;
     display: inline-block;
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index c9baee10..8e78243a 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -23,6 +23,11 @@
         :href="url"
         @click.prevent="onClick"
       >
+        <UserAvatar
+          v-if="shouldShowAvatar"
+          class="mention-avatar"
+          :user="user"
+        />
         <!-- eslint-disable vue/no-v-html -->
         <span
           class="shortName"
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 8fce1eee..b4495941 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -171,6 +171,11 @@
             </BooleanSetting>
           </li>
         </ul>
+        <li>
+          <BooleanSetting path="mentionLinkShowAvatar">
+            {{ $t('settings.mention_link_show_avatar') }}
+          </BooleanSetting>
+        </li>
       </ul>
     </div>
 
diff --git a/src/modules/config.js b/src/modules/config.js
index e1a49a7d..cfb753ce 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -74,6 +74,7 @@ export const defaultState = {
   useAtIcon: undefined, // instance default
   mentionLinkDisplay: undefined, // instance default
   mentionLinkShowTooltip: undefined, // instance default
+  mentionLinkShowAvatar: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
   virtualScrolling: undefined, // instance default
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 200a7a6f..6c8823c3 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -23,6 +23,7 @@ const defaultState = {
   useAtIcon: false,
   mentionLinkDisplay: 'short',
   mentionLinkShowTooltip: true,
+  mentionLinkShowAvatar: true,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
-- 
cgit v1.2.3-70-g09d2


From 0c60b31eee3e31810ebd41bc186a9825a39cd821 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 10 Jan 2022 02:31:26 -0500
Subject: Add option to fade domains in mention link

---
 src/components/mention_link/mention_link.js        |  3 +++
 src/components/mention_link/mention_link.scss      |  8 ++++++++
 src/components/mention_link/mention_link.vue       | 15 +++++++++++++--
 src/components/settings_modal/tabs/general_tab.vue |  5 +++++
 src/modules/config.js                              |  1 +
 src/modules/instance.js                            |  1 +
 6 files changed, 31 insertions(+), 2 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 426dbe97..5209907d 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -115,6 +115,9 @@ const MentionLink = {
     shouldShowAvatar () {
       return this.mergedConfig.mentionLinkShowAvatar
     },
+    shouldFadeDomain () {
+      return this.mergedConfig.mentionLinkFadeDomain
+    },
     ...mapGetters(['mergedConfig']),
     ...mapState({
       currentUser: state => state.users.currentUser
diff --git a/src/components/mention_link/mention_link.scss b/src/components/mention_link/mention_link.scss
index 9a285ad8..03306dcc 100644
--- a/src/components/mention_link/mention_link.scss
+++ b/src/components/mention_link/mention_link.scss
@@ -100,4 +100,12 @@
     opacity: 1;
     pointer-events: initial;
   }
+
+  .serverName.-faded {
+    color: var(--faintLink, $fallback--link);
+  }
+
+  .full .-faded {
+    color: var(--faint, $fallback--faint);
+  }
 }
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index c0d71322..ac20eb5a 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -41,6 +41,7 @@
         /><span
           v-if="shouldShowFullUserName"
           class="serverName"
+          :class="{ '-faded': shouldFadeDomain }"
           v-html="'@' + serverName"
         /></span>
         <span
@@ -56,8 +57,18 @@
       >
         <span
           class="userNameFull"
-          v-text="'@' + userNameFull"
-        />
+        >
+          <!-- eslint-disable vue/no-v-html -->
+          @<span
+            class="userName"
+            v-html="userName"
+          /><span
+            class="serverName"
+            :class="{ '-faded': shouldFadeDomain }"
+            v-html="'@' + serverName"
+          />
+          <!-- eslint-enable vue/no-v-html -->
+        </span>
       </span>
     </span>
   </span>
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index b4495941..50599eae 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -176,6 +176,11 @@
             {{ $t('settings.mention_link_show_avatar') }}
           </BooleanSetting>
         </li>
+        <li>
+          <BooleanSetting path="mentionLinkFadeDomain">
+            {{ $t('settings.mention_link_fade_domain') }}
+          </BooleanSetting>
+        </li>
       </ul>
     </div>
 
diff --git a/src/modules/config.js b/src/modules/config.js
index cfb753ce..9f2d4ef3 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -75,6 +75,7 @@ export const defaultState = {
   mentionLinkDisplay: undefined, // instance default
   mentionLinkShowTooltip: undefined, // instance default
   mentionLinkShowAvatar: undefined, // instance default
+  mentionLinkFadeDomain: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
   virtualScrolling: undefined, // instance default
diff --git a/src/modules/instance.js b/src/modules/instance.js
index 6c8823c3..2859b00b 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -24,6 +24,7 @@ const defaultState = {
   mentionLinkDisplay: 'short',
   mentionLinkShowTooltip: true,
   mentionLinkShowAvatar: true,
+  mentionLinkFadeDomain: true,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
-- 
cgit v1.2.3-70-g09d2


From c8983d56063bcb6970c7ba459288049d5d4d2d81 Mon Sep 17 00:00:00 2001
From: Tusooa Zhu <tusooa@kazv.moe>
Date: Mon, 10 Jan 2022 02:53:27 -0500
Subject: Make mention link prefs ui more intuitive

---
 src/components/settings_modal/tabs/general_tab.vue | 35 +++++++++++-----------
 1 file changed, 18 insertions(+), 17 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 50599eae..44b1ac92 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -147,11 +147,6 @@
             {{ $t('settings.greentext') }}
           </BooleanSetting>
         </li>
-        <li>
-          <BooleanSetting path="useAtIcon">
-            {{ $t('settings.use_at_icon') }}
-          </BooleanSetting>
-        </li>
         <li>
           <ChoiceSetting
             id="mentionLinkDisplay"
@@ -162,25 +157,31 @@
           </ChoiceSetting>
         </li>
         <ul
-          v-if="mentionLinkDisplay === 'short'"
           class="setting-list suboptions"
         >
-          <li>
+          <li
+            v-if="mentionLinkDisplay === 'short'"
+          >
             <BooleanSetting path="mentionLinkShowTooltip">
               {{ $t('settings.mention_link_show_tooltip') }}
             </BooleanSetting>
           </li>
+          <li>
+            <BooleanSetting path="useAtIcon">
+              {{ $t('settings.use_at_icon') }}
+            </BooleanSetting>
+          </li>
+          <li>
+            <BooleanSetting path="mentionLinkShowAvatar">
+              {{ $t('settings.mention_link_show_avatar') }}
+            </BooleanSetting>
+          </li>
+          <li>
+            <BooleanSetting path="mentionLinkFadeDomain">
+              {{ $t('settings.mention_link_fade_domain') }}
+            </BooleanSetting>
+          </li>
         </ul>
-        <li>
-          <BooleanSetting path="mentionLinkShowAvatar">
-            {{ $t('settings.mention_link_show_avatar') }}
-          </BooleanSetting>
-        </li>
-        <li>
-          <BooleanSetting path="mentionLinkFadeDomain">
-            {{ $t('settings.mention_link_fade_domain') }}
-          </BooleanSetting>
-        </li>
       </ul>
     </div>
 
-- 
cgit v1.2.3-70-g09d2


From bfb3a4364be3f71f7c46056aeb8972f04a072703 Mon Sep 17 00:00:00 2001
From: Henry Jameson <me@hjkos.com>
Date: Thu, 3 Feb 2022 22:34:57 +0200
Subject: options to disable (You)s and highlighting of yourself

---
 src/components/mention_link/mention_link.js        |  8 +++++++-
 src/components/mention_link/mention_link.vue       |  4 ++--
 src/components/settings_modal/tabs/general_tab.vue | 10 ++++++++++
 src/i18n/en.json                                   |  2 ++
 src/modules/config.js                              |  2 ++
 src/modules/instance.js                            |  2 ++
 6 files changed, 25 insertions(+), 3 deletions(-)

(limited to 'src/components/settings_modal/tabs/general_tab.vue')

diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 5209907d..55eea195 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -87,7 +87,7 @@ const MentionLink = {
     classnames () {
       return [
         {
-          '-you': this.isYou,
+          '-you': this.isYou && this.shouldBoldenYou,
           '-highlighted': this.highlight
         },
         this.highlightType
@@ -115,6 +115,12 @@ const MentionLink = {
     shouldShowAvatar () {
       return this.mergedConfig.mentionLinkShowAvatar
     },
+    shouldShowYous () {
+      return this.mergedConfig.mentionLinkShowYous
+    },
+    shouldBoldenYou () {
+      return this.mergedConfig.mentionLinkBoldenYou
+    },
     shouldFadeDomain () {
       return this.mergedConfig.mentionLinkFadeDomain
     },
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index ac20eb5a..d8ab79fb 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -45,8 +45,8 @@
           v-html="'@' + serverName"
         /></span>
         <span
-          v-if="isYou"
-          class="you"
+          v-if="isYou && shouldShowYous"
+          :class="{ '-you': shouldBoldenYou }"
         >{{ $t('status.you') }}</span>
         <!-- eslint-enable vue/no-v-html -->
       </a>
diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue
index 44b1ac92..eba3b268 100644
--- a/src/components/settings_modal/tabs/general_tab.vue
+++ b/src/components/settings_modal/tabs/general_tab.vue
@@ -147,6 +147,11 @@
             {{ $t('settings.greentext') }}
           </BooleanSetting>
         </li>
+        <li>
+          <BooleanSetting path="mentionLinkShowYous">
+            {{ $t('settings.show_yous') }}
+          </BooleanSetting>
+        </li>
         <li>
           <ChoiceSetting
             id="mentionLinkDisplay"
@@ -181,6 +186,11 @@
               {{ $t('settings.mention_link_fade_domain') }}
             </BooleanSetting>
           </li>
+          <li>
+            <BooleanSetting path="mentionLinkBoldenYou">
+              {{ $t('settings.mention_link_bolden_you') }}
+            </BooleanSetting>
+          </li>
         </ul>
       </ul>
     </div>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index 209fd184..8fd189c6 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -493,8 +493,10 @@
     "mention_link_show_tooltip": "Show full user names as tooltip for remote users",
     "mention_link_show_avatar": "Show user avatar beside the link",
     "mention_link_fade_domain": "Fade domains (e.g. @example.org in @foo@example.org)",
+    "mention_link_bolden_you": "Bolden text of your mention",
     "fun": "Fun",
     "greentext": "Meme arrows",
+    "show_yous": "Show (You)s",
     "notifications": "Notifications",
     "notification_setting_filters": "Filters",
     "notification_setting_block_from_strangers": "Block notifications from users who you do not follow",
diff --git a/src/modules/config.js b/src/modules/config.js
index 9f2d4ef3..20979174 100644
--- a/src/modules/config.js
+++ b/src/modules/config.js
@@ -76,6 +76,8 @@ export const defaultState = {
   mentionLinkShowTooltip: undefined, // instance default
   mentionLinkShowAvatar: undefined, // instance default
   mentionLinkFadeDomain: undefined, // instance default
+  mentionLinkShowYous: undefined, // instance default
+  mentionLinkBoldenYou: undefined, // instance default
   hidePostStats: undefined, // instance default
   hideUserStats: undefined, // instance default
   virtualScrolling: undefined, // instance default
diff --git a/src/modules/instance.js b/src/modules/instance.js
index d686f258..1abd784f 100644
--- a/src/modules/instance.js
+++ b/src/modules/instance.js
@@ -25,6 +25,8 @@ const defaultState = {
   mentionLinkShowTooltip: true,
   mentionLinkShowAvatar: false,
   mentionLinkFadeDomain: true,
+  mentionLinkShowYous: false,
+  mentionLinkBoldenYou: true,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
-- 
cgit v1.2.3-70-g09d2

