Ver Fonte

Merge branch 'from/develop/tusooa/1118-enhanced-mention-link' into 'develop'

Enhanced mention link

Closes #1118

See merge request pleroma/pleroma-fe!1424
HJ há 2 anos atrás
pai
commit
8ade11783a

+ 33 - 0
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,
@@ -50,6 +54,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
     },
@@ -85,6 +93,31 @@ const MentionLink = {
         this.highlightType
       ]
     },
+    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
+    },
+    shouldShowAvatar () {
+      return this.mergedConfig.mentionLinkShowAvatar
+    },
+    shouldFadeDomain () {
+      return this.mergedConfig.mentionLinkFadeDomain
+    },
     ...mapGetters(['mergedConfig']),
     ...mapState({
       currentUser: state => state.users.currentUser

+ 24 - 4
src/components/mention_link/mention_link.scss

@@ -1,3 +1,5 @@
+@import '../../_variables.scss';
+
 .MentionLink {
   position: relative;
   white-space: normal;
@@ -10,6 +12,15 @@
     border-radius: 2px;
   }
 
+  .mention-avatar {
+    border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
+    width: 1.5em;
+    height: 1.5em;
+    vertical-align: middle;
+    user-select: none;
+    margin-right: 0.2em;
+  }
+
   .full {
     position: absolute;
     display: inline-block;
@@ -27,7 +38,8 @@
     user-select: all;
   }
 
-  .short {
+  .short.-with-tooltip,
+  .you {
     user-select: none;
   }
 
@@ -56,7 +68,7 @@
     }
 
     &.-striped {
-      & .userName,
+      & .shortName,
       & .full {
         background-image:
           repeating-linear-gradient(
@@ -70,14 +82,14 @@
     }
 
     &.-solid {
-      & .userName,
+      & .shortName,
       & .full {
         background-image: linear-gradient(var(--____highlight-tintColor2), var(--____highlight-tintColor2));
       }
     }
 
     &.-side {
-      & .userName,
+      & .shortName,
       & .userNameFull {
         box-shadow: 0 -5px 3px -4px inset var(--____highlight-solidColor);
       }
@@ -88,4 +100,12 @@
     opacity: 1;
     pointer-events: initial;
   }
+
+  .serverName.-faded {
+    color: var(--faintLink, $fallback--link);
+  }
+
+  .full .-faded {
+    color: var(--faint, $fallback--faint);
+  }
 }

+ 28 - 5
src/components/mention_link/mention_link.vue

@@ -19,17 +19,30 @@
     >
       <a
         class="short button-unstyled"
+        :class="{ '-with-tooltip': shouldShowTooltip }"
         :href="url"
         @click.prevent="onClick"
       >
         <!-- eslint-disable vue/no-v-html -->
-        <FAIcon
+        <UserAvatar
+          v-if="shouldShowAvatar"
+          class="mention-avatar"
+          :user="user"
+        /><span
+          class="shortName"
+        ><FAIcon
+          v-if="useAtIcon"
           size="sm"
           icon="at"
           class="at"
-        /><span class="shortName"><span
+        />{{ !useAtIcon ? '@' : '' }}<span
           class="userName"
           v-html="userName"
+        /><span
+          v-if="shouldShowFullUserName"
+          class="serverName"
+          :class="{ '-faded': shouldFadeDomain }"
+          v-html="'@' + serverName"
         /></span>
         <span
           v-if="isYou"
@@ -38,14 +51,24 @@
         <!-- eslint-enable vue/no-v-html -->
       </a>
       <span
-        v-if="userName !== userNameFull"
+        v-if="shouldShowTooltip"
         class="full popover-default"
         :class="[highlightType]"
       >
         <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>

+ 5 - 0
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') ||

+ 35 - 0
src/components/settings_modal/tabs/general_tab.vue

@@ -147,6 +147,41 @@
             {{ $t('settings.greentext') }}
           </BooleanSetting>
         </li>
+        <li>
+          <ChoiceSetting
+            id="mentionLinkDisplay"
+            path="mentionLinkDisplay"
+            :options="mentionLinkDisplayOptions"
+          >
+            {{ $t('settings.mention_link_display') }}
+          </ChoiceSetting>
+        </li>
+        <ul
+          class="setting-list suboptions"
+        >
+          <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>
       </ul>
     </div>
 

+ 8 - 0
src/i18n/en.json

@@ -485,6 +485,14 @@
       "true": "yes"
     },
     "virtual_scrolling": "Optimize timeline rendering",
+    "use_at_icon": "Display @ symbol as an icon instead of text",
+    "mention_link_display": "Display mention links",
+    "mention_link_display_short": "always as short names (e.g. @foo)",
+    "mention_link_display_full_for_remote": "as full names only for remote users (e.g. @foo@example.org)",
+    "mention_link_display_full": "always as full names (e.g. @foo@example.org)",
+    "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)",
     "fun": "Fun",
     "greentext": "Meme arrows",
     "notifications": "Notifications",

+ 7 - 1
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 = {
@@ -70,6 +71,11 @@ export const defaultState = {
   useOneClickNsfw: false,
   useContainFit: false,
   greentext: undefined, // instance default
+  useAtIcon: undefined, // instance default
+  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

+ 8 - 0
src/modules/instance.js

@@ -20,6 +20,11 @@ const defaultState = {
   background: '/static/aurora_borealis.jpg',
   collapseMessageWithSubject: false,
   greentext: false,
+  useAtIcon: false,
+  mentionLinkDisplay: 'short',
+  mentionLinkShowTooltip: true,
+  mentionLinkShowAvatar: false,
+  mentionLinkFadeDomain: true,
   hideFilteredStatuses: false,
   // bad name: actually hides posts of muted USERS
   hideMutedPosts: false,
@@ -100,6 +105,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: {