commit: 8ade11783aa4740a2cff61f27938f3408c3e0eb0
parent a5e20a4eb25864889dbc7dff1a6a9ad2cb98735b
Author: HJ <30-hj@users.noreply.git.pleroma.social>
Date: Thu, 3 Feb 2022 19:37:13 +0000
Merge branch 'from/develop/tusooa/1118-enhanced-mention-link' into 'develop'
Enhanced mention link
Closes #1118
See merge request pleroma/pleroma-fe!1424
Diffstat:
8 files changed, 148 insertions(+), 10 deletions(-)
diff --git 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,
@@ -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
diff --git 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,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);
+ }
}
diff --git a/src/components/mention_link/mention_link.vue b/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>
diff --git 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
@@ -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>
diff --git a/src/i18n/en.json b/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",
diff --git 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 = {
@@ -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
diff --git a/src/modules/instance.js b/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: {