polish things, enable user popover hover triggers on touch on mobile

This commit is contained in:
Shpuld Shpuldson 2020-07-22 14:26:08 +03:00
parent b64af18eda
commit 0f862e3512
9 changed files with 50 additions and 51 deletions

View file

@ -6,19 +6,11 @@ const BasicUserCard = {
props: [ props: [
'user' 'user'
], ],
data () {
return {
userExpanded: false
}
},
components: { components: {
UserCard, UserCard,
UserAvatar UserAvatar
}, },
methods: { methods: {
toggleUserExpanded () {
this.userExpanded = !this.userExpanded
},
userProfileLink (user) { userProfileLink (user) {
return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames) return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
} }

View file

@ -4,22 +4,10 @@
<UserAvatar <UserAvatar
class="avatar" class="avatar"
:user="user" :user="user"
@click.prevent.native="toggleUserExpanded"
/> />
</router-link> </router-link>
<div <div
v-if="userExpanded" class="basic-user-card-content"
class="basic-user-card-expanded-content"
>
<UserCard
:user-id="user.id"
:rounded="true"
:bordered="true"
/>
</div>
<div
v-else
class="basic-user-card-collapsed-content"
> >
<div <div
:title="user.name" :title="user.name"
@ -59,7 +47,7 @@
margin: 0; margin: 0;
padding: 0.6em 1em; padding: 0.6em 1em;
&-collapsed-content { &-content {
margin-left: 0.7em; margin-left: 0.7em;
text-align: left; text-align: left;
flex: 1; flex: 1;
@ -83,11 +71,5 @@
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
&-expanded-content {
flex: 1;
margin-left: 0.7em;
min-width: 0;
}
} }
</style> </style>

View file

@ -26,16 +26,16 @@
:class="[userClass, { highlighted: userStyle }]" :class="[userClass, { highlighted: userStyle }]"
:style="[ userStyle ]" :style="[ userStyle ]"
> >
<a <router-link
class="avatar-container" class="avatar-container"
:href="notification.from_profile.statusnet_profile_url" :to="userProfileLink"
> >
<UserAvatar <UserAvatar
:compact="true" :compact="true"
:better-shadow="betterShadow" :better-shadow="betterShadow"
:user="notification.from_profile" :user="notification.from_profile"
/> />
</a> </router-link>
<div class="notification-right"> <div class="notification-right">
<span class="notification-details"> <span class="notification-details">
<div class="name-and-action"> <div class="name-and-action">

View file

@ -28,9 +28,14 @@ const Popover = {
data () { data () {
return { return {
hidden: true, hidden: true,
hovered: false,
styles: { opacity: 0 }, styles: { opacity: 0 },
oldSize: { width: 0, height: 0 } oldSize: { width: 0, height: 0 },
timeout: null
}
},
computed: {
isMobileLayout () {
return this.$store.state.interface.mobileLayout
} }
}, },
methods: { methods: {
@ -39,10 +44,8 @@ const Popover = {
return container.getBoundingClientRect() return container.getBoundingClientRect()
}, },
updateStyles () { updateStyles () {
if (this.hidden) { if (this.hidden || !(this.$el && this.$el.offsetParent)) {
this.styles = { this.hidePopover()
opacity: 0
}
return return
} }
@ -124,26 +127,27 @@ const Popover = {
} }
}, },
showPopover () { showPopover () {
if (!this.$el) return
if (this.trigger === 'hover' && !this.hovered) return
if (this.hidden) this.$emit('show') if (this.hidden) this.$emit('show')
this.hidden = false this.hidden = false
this.$nextTick(this.updateStyles) this.$nextTick(this.updateStyles)
}, },
hidePopover () { hidePopover () {
if (!this.hidden) this.$emit('close') if (!this.hidden) this.$emit('close')
if (this.timeout) {
clearTimeout(this.timeout)
this.timeout = null
}
this.hidden = true this.hidden = true
this.styles = { opacity: 0 } this.styles = { opacity: 0 }
}, },
onMouseenter (e) { onMouseenter (e) {
if (this.trigger === 'hover') { if (this.trigger === 'hover') {
this.hovered = true this.$emit('enter')
setTimeout(this.showPopover, this.delay || 100) this.timeout = setTimeout(this.showPopover, this.delay || 100)
} }
}, },
onMouseleave (e) { onMouseleave (e) {
if (this.trigger === 'hover') { if (this.trigger === 'hover') {
this.hovered = false
this.hidePopover() this.hidePopover()
} }
}, },
@ -154,6 +158,18 @@ const Popover = {
} else { } else {
this.hidePopover() this.hidePopover()
} }
} else if (this.trigger === 'hover' && this.isMobileLayout) {
// This is to enable using hover stuff with mobile:
// on first touch it opens the popover, when touching the trigger
// again it will do the click action. Can't use touch events as
// we can't stop/prevent the actual click which will be handled
// first.
if (this.hidden) {
this.$emit('enter')
this.showPopover()
e.preventDefault()
e.stopPropagation()
}
} }
}, },
onClickOutside (e) { onClickOutside (e) {

View file

@ -5,7 +5,7 @@
> >
<div <div
ref="trigger" ref="trigger"
@click="onClick" @click.capture="onClick"
> >
<slot name="trigger" /> <slot name="trigger" />
</div> </div>

View file

@ -177,6 +177,7 @@ const StatusContent = {
} }
} }
window.open(target.href, '_blank') window.open(target.href, '_blank')
event.preventDefault()
} }
}, },
linkHover (event) { linkHover (event) {

View file

@ -51,7 +51,7 @@
v-if="!hideSubjectStatus" v-if="!hideSubjectStatus"
:class="{ 'single-line': singleLine }" :class="{ 'single-line': singleLine }"
class="status-content media-body" class="status-content media-body"
@click.prevent="linkClicked" @click="linkClicked"
@mouseover="linkHover" @mouseover="linkHover"
v-html="postBodyHtml" v-html="postBodyHtml"
/> />

View file

@ -13,6 +13,10 @@ const UserPopover = {
computed: { computed: {
user () { user () {
return this.$store.getters.findUser(this.userId) return this.$store.getters.findUser(this.userId)
},
relationshipAvailable () {
const relationship = this.$store.getters.relationship(this.userId)
return relationship && !relationship.loading
} }
}, },
components: { components: {
@ -21,14 +25,17 @@ const UserPopover = {
}, },
methods: { methods: {
enter () { enter () {
if (!this.userId) return
if (!this.user) { if (!this.user) {
if (!this.userId) {
return
}
this.$store.dispatch('fetchUser', this.userId) this.$store.dispatch('fetchUser', this.userId)
.then(data => (this.error = false)) .then(data => (this.error = false))
.catch(e => (this.error = true)) .catch(e => (this.error = true))
} }
if (!this.relationship) {
this.$store.dispatch('fetchUserRelationship', this.userId)
.then(data => (this.error = false))
.catch(e => (this.error = true))
}
} }
} }
} }

View file

@ -5,18 +5,19 @@
trigger="hover" trigger="hover"
popover-class="user-popover" popover-class="user-popover"
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
:margin="{ left: 5, right: 5 }"
:delay="200" :delay="200"
:anchor-offset="anchorOffset" :anchor-offset="anchorOffset"
@show="enter" @enter="enter"
> >
<template slot="trigger"> <template slot="trigger">
<slot /> <slot />
</template> </template>
<div <div
slot="content" slot="content"
@click.stop.prevent="" @click.prevent=""
> >
<span v-if="user"> <span v-if="user && relationshipAvailable">
<UserCard <UserCard
:user-id="userId" :user-id="userId"
hide-bio="true" hide-bio="true"
@ -30,7 +31,7 @@
</div> </div>
<div <div
v-else v-else
class="status-preview-no-content" class="user-preview-no-content"
> >
<i class="icon-spin4 animate-spin" /> <i class="icon-spin4 animate-spin" />
</div> </div>