2019-05-28 11:03:14 +00:00
|
|
|
<template>
|
2019-05-29 14:54:00 +00:00
|
|
|
<div class="entry-content">
|
|
|
|
<div v-if="item.actor_info" class="post-avatar">
|
|
|
|
<avatar v-if="item.local" :size="32" :user="item.actor_info.preferredUsername"
|
|
|
|
:display-name="item.actor_info.account" :disable-tooltip="true" />
|
|
|
|
<avatar v-else :size="32" :url="avatarUrl"
|
|
|
|
:disable-tooltip="true" />
|
|
|
|
</div>
|
|
|
|
<div class="post-content">
|
|
|
|
<div class="post-author-wrapper">
|
|
|
|
<router-link v-if="item.actor_info" :to="{ name: 'profile', params: { account: item.local ? item.actor_info.preferredUsername : item.actor_info.account }}">
|
|
|
|
<span class="post-author">
|
|
|
|
{{ userDisplayName(item.actor_info) }}
|
|
|
|
</span>
|
|
|
|
<span class="post-author-id">
|
|
|
|
@{{ item.actor_info.account }}
|
|
|
|
</span>
|
|
|
|
</router-link>
|
|
|
|
<a v-else :href="item.attributedTo">
|
|
|
|
<span class="post-author-id">
|
|
|
|
{{ item.attributedTo }}
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
|
|
<div class="post-message" v-html="formatedMessage" />
|
|
|
|
<div v-click-outside="hidePopoverMenu" class="post-actions">
|
|
|
|
<a v-tooltip.bottom="t('social', 'Reply')" class="icon-reply" @click.prevent="reply" />
|
|
|
|
<a v-if="item.actor_info.account !== cloudId" v-tooltip.bottom="t('social', 'Boost')"
|
|
|
|
:class="(isBoosted) ? 'icon-boosted' : 'icon-boost'"
|
|
|
|
@click.prevent="boost" />
|
2019-07-10 15:39:49 +00:00
|
|
|
<a v-tooltip.bottom="t('social', 'Like')" :class="(isLiked) ? 'icon-starred' : 'icon-favorite'" @click.prevent="like" />
|
2019-07-10 15:41:59 +00:00
|
|
|
<div v-if="popoverMenu.length > 0" v-tooltip.bottom="menuOpened ? '' : t('social', 'More actions')" class="post-actions-more">
|
2019-05-29 14:54:00 +00:00
|
|
|
<a class="icon-more" @click.prevent="togglePopoverMenu" />
|
|
|
|
<div :class="{open: menuOpened}" class="popovermenu menu-center">
|
|
|
|
<popover-menu :menu="popoverMenu" />
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<div :data-timestamp="timestamp" class="post-timestamp live-relative-timestamp">
|
|
|
|
{{ relativeTimestamp }}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2019-05-28 11:03:14 +00:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import Avatar from 'nextcloud-vue/dist/Components/Avatar'
|
|
|
|
import * as linkify from 'linkifyjs'
|
|
|
|
import pluginTag from 'linkifyjs/plugins/hashtag'
|
|
|
|
import pluginMention from 'linkifyjs/plugins/mention'
|
|
|
|
import 'linkifyjs/string'
|
|
|
|
import popoverMenu from './../mixins/popoverMenu'
|
|
|
|
import currentUser from './../mixins/currentUserMixin'
|
|
|
|
|
|
|
|
pluginTag(linkify)
|
|
|
|
pluginMention(linkify)
|
|
|
|
|
|
|
|
export default {
|
2019-06-27 16:25:51 +00:00
|
|
|
name: 'TimelinePost',
|
2019-05-28 11:03:14 +00:00
|
|
|
components: {
|
|
|
|
Avatar
|
|
|
|
},
|
|
|
|
mixins: [popoverMenu, currentUser],
|
|
|
|
props: {
|
2019-05-28 14:08:09 +00:00
|
|
|
item: { type: Object, default: () => {} },
|
2019-05-29 14:54:00 +00:00
|
|
|
parentAnnounce: { type: Object, default: () => {} }
|
2019-05-28 11:03:14 +00:00
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
popoverMenu() {
|
|
|
|
var actions = [
|
|
|
|
]
|
|
|
|
if (this.item.actor_info.account === this.cloudId) {
|
|
|
|
actions.push(
|
|
|
|
{
|
|
|
|
action: () => {
|
|
|
|
this.$store.dispatch('postDelete', this.item)
|
|
|
|
this.hidePopoverMenu()
|
|
|
|
},
|
|
|
|
icon: 'icon-delete',
|
|
|
|
text: t('social', 'Delete post')
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
return actions
|
|
|
|
},
|
|
|
|
relativeTimestamp() {
|
|
|
|
return OC.Util.relativeModifiedDate(this.item.published)
|
|
|
|
},
|
|
|
|
timestamp() {
|
|
|
|
return Date.parse(this.item.published)
|
|
|
|
},
|
|
|
|
formatedMessage() {
|
|
|
|
let message = this.item.content
|
|
|
|
if (typeof message === 'undefined') {
|
|
|
|
return ''
|
|
|
|
}
|
|
|
|
message = message.replace(/(?:\r\n|\r|\n)/g, '<br />')
|
|
|
|
message = message.linkify({
|
|
|
|
formatHref: {
|
|
|
|
hashtag: function(href) {
|
|
|
|
return OC.generateUrl('/apps/social/timeline/tags/' + href.substring(1))
|
|
|
|
},
|
|
|
|
mention: function(href) {
|
|
|
|
return OC.generateUrl('/apps/social/@' + href.substring(1))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
message = this.$twemoji.parse(message)
|
|
|
|
return message
|
|
|
|
},
|
|
|
|
avatarUrl() {
|
|
|
|
return OC.generateUrl('/apps/social/api/v1/global/actor/avatar?id=' + this.item.attributedTo)
|
|
|
|
},
|
|
|
|
isBoosted() {
|
|
|
|
if (typeof this.item.action === 'undefined') {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return !!this.item.action.values.boosted
|
2019-07-10 15:39:49 +00:00
|
|
|
},
|
|
|
|
isLiked() {
|
|
|
|
if (typeof this.item.action === 'undefined') {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return !!this.item.action.values.liked
|
2019-05-28 11:03:14 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
userDisplayName(actorInfo) {
|
|
|
|
return actorInfo.name !== '' ? actorInfo.name : actorInfo.preferredUsername
|
|
|
|
},
|
|
|
|
reply() {
|
|
|
|
this.$root.$emit('composer-reply', this.item)
|
|
|
|
},
|
|
|
|
boost() {
|
2019-05-29 14:54:00 +00:00
|
|
|
let params = {
|
|
|
|
post: this.item,
|
|
|
|
parentAnnounce: this.parentAnnounce
|
|
|
|
}
|
2019-05-28 11:03:14 +00:00
|
|
|
if (this.isBoosted) {
|
2019-05-28 14:08:09 +00:00
|
|
|
this.$store.dispatch('postUnBoost', params)
|
2019-05-28 11:03:14 +00:00
|
|
|
} else {
|
2019-05-28 14:08:09 +00:00
|
|
|
this.$store.dispatch('postBoost', params)
|
2019-05-28 11:03:14 +00:00
|
|
|
}
|
2019-07-10 15:39:49 +00:00
|
|
|
},
|
|
|
|
like() {
|
|
|
|
let params = {
|
|
|
|
post: this.item,
|
|
|
|
parentAnnounce: this.parentAnnounce
|
|
|
|
}
|
2019-07-10 15:40:12 +00:00
|
|
|
if (this.isLiked) {
|
2019-07-10 15:39:49 +00:00
|
|
|
this.$store.dispatch('postUnlike', params)
|
|
|
|
} else {
|
|
|
|
this.$store.dispatch('postLike', params)
|
|
|
|
}
|
2019-05-28 11:03:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
|
|
.post-author {
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
|
|
|
|
.post-author-id {
|
|
|
|
opacity: .7;
|
|
|
|
}
|
|
|
|
|
|
|
|
.post-avatar {
|
|
|
|
margin: 5px;
|
|
|
|
margin-right: 10px;
|
|
|
|
border-radius: 50%;
|
|
|
|
overflow: hidden;
|
|
|
|
width: 32px;
|
|
|
|
height: 32px;
|
|
|
|
min-width: 32px;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.post-timestamp {
|
|
|
|
width: 120px;
|
|
|
|
text-align: right;
|
|
|
|
flex-shrink: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.post-actions {
|
|
|
|
margin-left: -13px;
|
|
|
|
height: 44px;
|
|
|
|
|
|
|
|
.post-actions-more {
|
|
|
|
position: relative;
|
|
|
|
width: 44px;
|
|
|
|
height: 34px;
|
|
|
|
display: inline-block;
|
|
|
|
}
|
|
|
|
.icon-reply,
|
|
|
|
.icon-boost,
|
|
|
|
.icon-boosted,
|
2019-07-10 15:39:49 +00:00
|
|
|
.icon-starred,
|
|
|
|
.icon-favorite,
|
2019-05-28 11:03:14 +00:00
|
|
|
.icon-more {
|
|
|
|
display: inline-block;
|
|
|
|
width: 44px;
|
|
|
|
height: 34px;
|
|
|
|
opacity: .5;
|
|
|
|
&:hover, &:focus {
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.icon-boosted {
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
span {
|
|
|
|
/* opacity: 0.5; */
|
|
|
|
}
|
|
|
|
.entry-content {
|
|
|
|
display: flex;
|
|
|
|
}
|
|
|
|
|
|
|
|
.post-content {
|
|
|
|
flex-grow: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
.post-timestamp {
|
|
|
|
opacity: .7;
|
|
|
|
}
|
|
|
|
</style>
|
|
|
|
<style>
|
|
|
|
.post-message a {
|
|
|
|
text-decoration: underline;
|
|
|
|
}
|
|
|
|
</style>
|