fix animations, replace ugly old mentionlink tooltips with new usercard ones
This commit is contained in:
parent
61d63b0e61
commit
55adcd822e
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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') {
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
@ -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",
|
||||||
|
Loading…
Reference in New Issue
Block a user