aboutsummaryrefslogtreecommitdiff
path: root/src/components/mention_link
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/mention_link')
-rw-r--r--src/components/mention_link/mention_link.js63
-rw-r--r--src/components/mention_link/mention_link.scss55
-rw-r--r--src/components/mention_link/mention_link.vue93
3 files changed, 157 insertions, 54 deletions
diff --git a/src/components/mention_link/mention_link.js b/src/components/mention_link/mention_link.js
index 65c62baa..6515bd11 100644
--- a/src/components/mention_link/mention_link.js
+++ b/src/components/mention_link/mention_link.js
@@ -1,6 +1,9 @@
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 UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
+import { defineAsyncComponent } from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faAt
@@ -12,6 +15,11 @@ library.add(
const MentionLink = {
name: 'MentionLink',
+ components: {
+ UserAvatar,
+ UnicodeDomainIndicator,
+ UserPopover: defineAsyncComponent(() => import('../user_popover/user_popover.vue'))
+ },
props: {
url: {
required: true,
@@ -30,15 +38,30 @@ const MentionLink = {
type: String
}
},
+ data () {
+ return {
+ hasSelection: false
+ }
+ },
methods: {
onClick () {
+ if (this.shouldShowTooltip) return
const link = generateProfileLink(
this.userId || this.user.id,
this.userScreenName || this.user.screen_name
)
this.$router.push(link)
+ },
+ handleSelection () {
+ this.hasSelection = document.getSelection().containsNode(this.$refs.full, true)
}
},
+ mounted () {
+ document.addEventListener('selectionchange', this.handleSelection)
+ },
+ unmounted () {
+ document.removeEventListener('selectionchange', this.handleSelection)
+ },
computed: {
user () {
return this.url && this.$store && this.$store.getters.findUserByUrl(this.url)
@@ -50,6 +73,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
},
@@ -79,12 +106,44 @@ const MentionLink = {
classnames () {
return [
{
- '-you': this.isYou,
- '-highlighted': this.highlight
+ '-you': this.isYou && this.shouldBoldenYou,
+ '-highlighted': this.highlight,
+ '-has-selection': this.hasSelection
},
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
+ },
+ shouldShowAvatar () {
+ return this.mergedConfig.mentionLinkShowAvatar
+ },
+ shouldShowYous () {
+ return this.mergedConfig.mentionLinkShowYous
+ },
+ shouldBoldenYou () {
+ return this.mergedConfig.mentionLinkBoldenYou
+ },
+ 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 ec2689f8..8b2af926 100644
--- a/src/components/mention_link/mention_link.scss
+++ b/src/components/mention_link/mention_link.scss
@@ -1,15 +1,27 @@
+@import '../../_variables.scss';
+
.MentionLink {
position: relative;
white-space: normal;
- display: inline-block;
+ display: inline;
color: var(--link);
+ word-break: normal;
& .new,
& .original {
- display: inline-block;
+ display: inline;
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 +39,8 @@
user-select: all;
}
- .short {
+ & .short.-with-tooltip,
+ & .you {
user-select: none;
}
@@ -36,19 +49,25 @@
white-space: nowrap;
}
+ .shortName {
+ white-space: normal;
+ }
+
.new {
&.-you {
- & .shortName,
- & .full {
+ .shortName {
font-weight: 600;
}
}
+ &.-has-selection {
+ color: var(--alertNeutralText, $fallback--text);
+ background-color: var(--alertNeutral, $fallback--fg);
+ }
.at {
color: var(--link);
opacity: 0.8;
display: inline-block;
- height: 50%;
line-height: 1;
padding: 0 0.1em;
vertical-align: -25%;
@@ -56,8 +75,7 @@
}
&.-striped {
- & .userName,
- & .full {
+ & .shortName {
background-image:
repeating-linear-gradient(
135deg,
@@ -70,22 +88,29 @@
}
&.-solid {
- & .userName,
- & .full {
+ .shortName {
background-image: linear-gradient(var(--____highlight-tintColor2), var(--____highlight-tintColor2));
}
}
&.-side {
- & .userName,
- & .userNameFull {
+ .shortName {
box-shadow: 0 -5px 3px -4px inset var(--____highlight-solidColor);
}
}
}
- &:hover .new .full {
- opacity: 1;
- pointer-events: initial;
+ .full {
+ pointer-events: none;
}
+
+ .serverName.-faded {
+ color: var(--faintLink, $fallback--link);
+ }
+}
+
+.mention-link-popover {
+ max-width: 70ch;
+ max-height: 20rem;
+ overflow: hidden;
}
diff --git a/src/components/mention_link/mention_link.vue b/src/components/mention_link/mention_link.vue
index a22b486c..869a3257 100644
--- a/src/components/mention_link/mention_link.vue
+++ b/src/components/mention_link/mention_link.vue
@@ -9,48 +9,67 @@
class="original"
target="_blank"
v-html="content"
- />
- <!-- eslint-enable vue/no-v-html -->
- <span
- v-if="user"
- class="new"
- :style="style"
- :class="classnames"
+ /><!-- eslint-enable vue/no-v-html -->
+ <UserPopover
+ v-else
+ :user-id="user.id"
+ :disabled="!shouldShowTooltip"
>
- <a
- class="short button-unstyled"
- :href="url"
- @click.prevent="onClick"
- >
- <!-- eslint-disable vue/no-v-html -->
- <FAIcon
- size="sm"
- icon="at"
- class="at"
- /><span class="shortName"><span
- class="userName"
- v-html="userName"
- /></span>
- <span
- v-if="isYou"
- class="you"
- >{{ $t('status.you') }}</span>
- <!-- eslint-enable vue/no-v-html -->
- </a>
<span
- v-if="userName !== userNameFull"
- class="full popover-default"
- :class="[highlightType]"
+ v-if="user"
+ class="new"
+ :style="style"
+ :class="classnames"
>
- <span
- class="userNameFull"
- v-text="'@' + userNameFull"
- />
+ <a
+ class="short button-unstyled"
+ :class="{ '-with-tooltip': shouldShowTooltip }"
+ :href="url"
+ @click.prevent="onClick"
+ >
+ <!-- eslint-disable vue/no-v-html -->
+ <UserAvatar
+ v-if="shouldShowAvatar"
+ class="mention-avatar"
+ :user="user"
+ /><span
+ class="shortName"
+ ><FAIcon
+ v-if="useAtIcon"
+ size="sm"
+ icon="at"
+ class="at"
+ />{{ !useAtIcon ? '@' : '' }}<span
+ class="userName"
+ v-html="userName"
+ /><span
+ v-if="shouldShowFullUserName"
+ class="serverName"
+ :class="{ '-faded': shouldFadeDomain }"
+ v-html="'@' + serverName"
+ /><UnicodeDomainIndicator
+ v-if="shouldShowFullUserName"
+ :user="user"
+ />
+ </span>
+ <span
+ v-if="isYou && shouldShowYous"
+ :class="{ '-you': shouldBoldenYou }"
+ > {{ ' ' + $t('status.you') }}</span>
+ <!-- eslint-enable vue/no-v-html -->
+ </a><span
+ ref="full"
+ class="full"
+ >
+ <!-- eslint-disable vue/no-v-html -->
+ @<span v-html="userName" /><span v-html="'@' + serverName" />
+ <!-- eslint-enable vue/no-v-html -->
+ </span>
</span>
- </span>
+ </UserPopover>
</span>
</template>
-<script src="./mention_link.js"/>
+<script src="./mention_link.js" />
-<style lang="scss" src="./mention_link.scss"/>
+<style lang="scss" src="./mention_link.scss" />