polish things, enable user popover hover triggers on touch on mobile
This commit is contained in:
parent
b64af18eda
commit
0f862e3512
9 changed files with 50 additions and 51 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
ref="trigger"
|
ref="trigger"
|
||||||
@click="onClick"
|
@click.capture="onClick"
|
||||||
>
|
>
|
||||||
<slot name="trigger" />
|
<slot name="trigger" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -177,6 +177,7 @@ const StatusContent = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.open(target.href, '_blank')
|
window.open(target.href, '_blank')
|
||||||
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
linkHover (event) {
|
linkHover (event) {
|
||||||
|
|
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue