fix animations, replace ugly old mentionlink tooltips with new usercard ones

This commit is contained in:
Henry Jameson 2022-06-12 16:31:56 +03:00
parent 61d63b0e61
commit 55adcd822e
8 changed files with 140 additions and 90 deletions

View File

@ -829,7 +829,7 @@ option {
// Vue transitions // Vue transitions
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity 0.2s; transition: opacity 0.3s;
} }
.fade-enter-from, .fade-enter-from,

View File

@ -2,6 +2,7 @@ import generateProfileLink from 'src/services/user_profile_link_generator/user_p
import { mapGetters, mapState } from 'vuex' import { mapGetters, mapState } from 'vuex'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import UserAvatar from '../user_avatar/user_avatar.vue' import UserAvatar from '../user_avatar/user_avatar.vue'
import { defineAsyncComponent } from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core' import { library } from '@fortawesome/fontawesome-svg-core'
import { import {
faAt faAt
@ -14,7 +15,9 @@ library.add(
const MentionLink = { const MentionLink = {
name: 'MentionLink', name: 'MentionLink',
components: { components: {
UserAvatar UserAvatar,
Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
UserCard: defineAsyncComponent(() => import('../user_card/user_card.vue'))
}, },
props: { props: {
url: { url: {
@ -36,6 +39,7 @@ const MentionLink = {
}, },
methods: { methods: {
onClick () { onClick () {
if (this.shouldShowTooltip) return
const link = generateProfileLink( const link = generateProfileLink(
this.userId || this.user.id, this.userId || this.user.id,
this.userScreenName || this.user.screen_name this.userScreenName || this.user.screen_name
@ -110,7 +114,7 @@ const MentionLink = {
} }
}, },
shouldShowTooltip () { shouldShowTooltip () {
return this.mergedConfig.mentionLinkShowTooltip && this.mergedConfig.mentionLinkDisplay === 'short' && this.isRemote return this.mergedConfig.mentionLinkShowTooltip
}, },
shouldShowAvatar () { shouldShowAvatar () {
return this.mergedConfig.mentionLinkShowAvatar return this.mergedConfig.mentionLinkShowAvatar

View File

@ -101,7 +101,6 @@
} }
&:hover .new .full { &:hover .new .full {
opacity: 1;
pointer-events: initial; pointer-events: initial;
} }
@ -113,3 +112,9 @@
color: var(--faint, $fallback--faint); color: var(--faint, $fallback--faint);
} }
} }
.mention-link-popover {
max-width: 70ch;
max-height: 20rem;
overflow: hidden;
}

View File

@ -9,66 +9,85 @@
class="original" class="original"
target="_blank" target="_blank"
v-html="content" v-html="content"
/><!-- eslint-enable vue/no-v-html --><span /><!-- eslint-enable vue/no-v-html -->
v-if="user" <Popover
class="new" trigger="click"
:style="style" :bound-to="{ x: 'container'}"
:class="classnames" bound-to-selector=".column"
popover-class="popover-default mention-popover"
:disabled="!shouldShowTooltip"
> >
<a <template v-slot:trigger>
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"
/>
</span>
<span <span
v-if="isYou && shouldShowYous" v-if="user"
:class="{ '-you': shouldBoldenYou }" class="new"
> {{ ' ' + $t('status.you') }}</span> :style="style"
<!-- eslint-enable vue/no-v-html --> :class="classnames"
</a><span
v-if="shouldShowTooltip"
class="full popover-default"
:class="[highlightType]"
>
<span
class="userNameFull"
> >
<!-- eslint-disable vue/no-v-html --> <a
@<span class="short button-unstyled"
class="userName" :class="{ '-with-tooltip': shouldShowTooltip }"
v-html="userName" :href="url"
/><span @click.prevent="onClick"
class="serverName" >
:class="{ '-faded': shouldFadeDomain }" <!-- eslint-disable vue/no-v-html -->
v-html="'@' + serverName" <UserAvatar
/> v-if="shouldShowAvatar"
<!-- eslint-enable vue/no-v-html --> class="mention-avatar"
</span> :user="user"
</span> /><span
</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"
/>
</span>
<span
v-if="isYou && shouldShowYous"
:class="{ '-you': shouldBoldenYou }"
> {{ ' ' + $t('status.you') }}</span>
<!-- eslint-enable vue/no-v-html -->
</a><span
v-if="shouldShowTooltip"
class="full"
>
<span
class="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></template>
<template v-slot:content>
<UserCard
class="mention-link-popover"
:user-id="user.id"
:hide-bio="true"
:bordered="false"
:allow-zooming-avatar="true"
:rounded="true"
/>
</template>
</Popover>
</span> </span>
</template> </template>

View File

@ -31,13 +31,18 @@ const Popover = {
// If true, subtract padding when calculating position for the popover, // If true, subtract padding when calculating position for the popover,
// use it when popover offset looks to be different on top vs bottom. // use it when popover offset looks to be different on top vs bottom.
removePadding: Boolean removePadding: Boolean,
// self-explanatory (i hope)
disabled: Boolean
}, },
data () { data () {
return { return {
hidden: true, hidden: true,
styles: { opacity: 0 }, styles: {},
oldSize: { width: 0, height: 0 } oldSize: { width: 0, height: 0 },
// used to avoid blinking if hovered onto popover
graceTimeout: null
} }
}, },
methods: { methods: {
@ -47,9 +52,7 @@ const Popover = {
}, },
updateStyles () { updateStyles () {
if (this.hidden) { if (this.hidden) {
this.styles = { this.styles = {}
opacity: 0
}
return return
} }
@ -132,7 +135,6 @@ const Popover = {
// Note, separate translateX and translateY avoids blurry text on chromium, // Note, separate translateX and translateY avoids blurry text on chromium,
// single translate or translate3d resulted in blurry text. // single translate or translate3d resulted in blurry text.
this.styles = { this.styles = {
opacity: 1,
left: `${Math.round(translateX)}px`, left: `${Math.round(translateX)}px`,
top: `${Math.round(translateY)}px`, top: `${Math.round(translateY)}px`,
position: 'fixed' position: 'fixed'
@ -143,6 +145,7 @@ const Popover = {
} }
}, },
showPopover () { showPopover () {
if (this.disabled) return
const wasHidden = this.hidden const wasHidden = this.hidden
this.hidden = false this.hidden = false
this.$nextTick(() => { this.$nextTick(() => {
@ -153,13 +156,30 @@ const Popover = {
hidePopover () { hidePopover () {
if (!this.hidden) this.$emit('close') if (!this.hidden) this.$emit('close')
this.hidden = true this.hidden = true
this.styles = { opacity: 0 }
}, },
onMouseenter (e) { onMouseenter (e) {
if (this.trigger === 'hover') this.showPopover() if (this.trigger === 'hover') {
clearTimeout(this.graceTimeout)
this.graceTimeout = null
this.showPopover()
}
}, },
onMouseleave (e) { onMouseleave (e) {
if (this.trigger === 'hover') this.hidePopover() if (this.trigger === 'hover') {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
}
},
onMouseenterContent (e) {
if (this.trigger === 'hover') {
clearTimeout(this.graceTimeout)
this.graceTimeout = null
this.showPopover()
}
},
onMouseleaveContent (e) {
if (this.trigger === 'hover') {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
}
}, },
onClick (e) { onClick (e) {
if (this.trigger === 'click') { if (this.trigger === 'click') {

View File

@ -1,5 +1,5 @@
<template> <template>
<div <span
@mouseenter="onMouseenter" @mouseenter="onMouseenter"
@mouseleave="onMouseleave" @mouseleave="onMouseleave"
> >
@ -12,21 +12,25 @@
<slot name="trigger" /> <slot name="trigger" />
</button> </button>
<teleport to="#popovers"> <teleport to="#popovers">
<div <transition name="fade">
v-if="!hidden" <div
ref="content" v-if="!hidden"
:style="styles" ref="content"
class="popover" :style="styles"
:class="popoverClass || 'popover-default'" class="popover"
> :class="popoverClass || 'popover-default'"
<slot @mouseenter="onMouseenterContent"
name="content" @mouseleave="onMouseleaveContent"
class="popover-inner" >
:close="hidePopover" <slot
/> name="content"
</div> class="popover-inner"
:close="hidePopover"
/>
</div>
</transition>
</teleport> </teleport>
</div> </span>
</template> </template>
<script src="./popover.js" /> <script src="./popover.js" />
@ -47,8 +51,6 @@
} }
.popover-default { .popover-default {
transition: opacity 0.3s;
&:after { &:after {
content: ''; content: '';
position: absolute; position: absolute;

View File

@ -269,7 +269,7 @@
path="mentionLinkShowTooltip" path="mentionLinkShowTooltip"
expert="1" expert="1"
> >
{{ $t('settings.mention_link_show_tooltip') }} {{ $t('settings.mention_link_use_tooltip') }}
</BooleanSetting> </BooleanSetting>
</li> </li>
</ul> </ul>

View File

@ -523,7 +523,7 @@
"mention_link_display_short": "always as short names (e.g. {'@'}foo)", "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_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_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_use_tooltip": "Show user card when clicking mention links",
"mention_link_show_avatar": "Show user avatar beside the link", "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_fade_domain": "Fade domains (e.g. {'@'}example.org in {'@'}foo{'@'}example.org)",
"mention_link_bolden_you": "Highlight mention of you when you are mentioned", "mention_link_bolden_you": "Highlight mention of you when you are mentioned",