<template> <div class="mk-post-detail"> <button class="read-more" v-if="p.reply && p.reply.reply_id && context == null" @click="loadContext" disabled={ loadingContext }> <template v-if="!contextFetching">%fa:ellipsis-v%</template> <template v-if="contextFetching">%fa:spinner .pulse%</template> </button> <div class="context"> <template each={ post in context }> <mk-post-detail-sub post={ post }/> </template> </div> <div class="reply-to" v-if="p.reply"> <mk-post-detail-sub post={ p.reply }/> </div> <div class="repost" v-if="isRepost"> <p> <a class="avatar-anchor" href={ '/' + post.user.username }> <img class="avatar" src={ post.user.avatar_url + '?thumbnail&size=32' } alt="avatar"/></a> %fa:retweet%<a class="name" href={ '/' + post.user.username }> { post.user.name } </a> ćRepost </p> </div> <article> <header> <a class="avatar-anchor" href={ '/' + p.user.username }> <img class="avatar" src={ p.user.avatar_url + '?thumbnail&size=64' } alt="avatar"/> </a> <div> <a class="name" href={ '/' + p.user.username }>{ p.user.name }</a> <span class="username">@{ p.user.username }</span> </div> </header> <div class="body"> <mk-post-html v-if="p.ast" :ast="p.ast" :i="$root.$data.os.i"/> <mk-url-preview v-for="url in urls" :url="url" :key="url"/> <div class="media" v-if="p.media"> <mk-images images={ p.media }/> </div> <mk-poll v-if="p.poll" post={ p }/> </div> <a class="time" href={ '/' + p.user.username + '/' + p.id }> <mk-time time={ p.created_at } mode="detail"/> </a> <footer> <mk-reactions-viewer post={ p }/> <button @click="reply" title="%i18n:mobile.tags.mk-post-detail.reply%"> %fa:reply%<p class="count" v-if="p.replies_count > 0">{ p.replies_count }</p> </button> <button @click="repost" title="Repost"> %fa:retweet%<p class="count" v-if="p.repost_count > 0">{ p.repost_count }</p> </button> <button :class="{ reacted: p.my_reaction != null }" @click="react" ref="reactButton" title="%i18n:mobile.tags.mk-post-detail.reaction%"> %fa:plus%<p class="count" v-if="p.reactions_count > 0">{ p.reactions_count }</p> </button> <button @click="menu" ref="menuButton"> %fa:ellipsis-h% </button> </footer> </article> <div class="replies" v-if="!compact"> <template each={ post in replies }> <mk-post-detail-sub post={ post }/> </template> </div> </div> </template> <script lang="ts"> import Vue from 'vue'; import getPostSummary from '../../../../common/get-post-summary.ts'; import openPostForm from '../scripts/open-post-form'; export default Vue.extend({ props: { post: { type: Object, required: true }, compact: { default: false } }, data() { return { context: [], contextFetching: false, replies: [], }; }, computed: { isRepost(): boolean { return this.post.repost != null; }, p(): any { return this.isRepost ? this.post.repost : this.post; }, reactionsCount(): number { return this.p.reaction_counts ? Object.keys(this.p.reaction_counts) .map(key => this.p.reaction_counts[key]) .reduce((a, b) => a + b) : 0; }, urls(): string[] { if (this.p.ast) { return this.p.ast .filter(t => (t.type == 'url' || t.type == 'link') && !t.silent) .map(t => t.url); } else { return null; } } }, mounted() { // Get replies if (!this.compact) { this.$root.$data.os.api('posts/replies', { post_id: this.p.id, limit: 8 }).then(replies => { this.replies = replies; }); } }, methods: { fetchContext() { this.contextFetching = true; // Fetch context this.$root.$data.os.api('posts/context', { post_id: this.p.reply_id }).then(context => { this.contextFetching = false; this.context = context.reverse(); }); } } }); </script> <style lang="stylus" scoped> .mk-post-detail overflow hidden margin 0 auto padding 0 width 100% text-align left background #fff border-radius 8px box-shadow 0 0 0 1px rgba(0, 0, 0, 0.2) > .fetching padding 64px 0 > .read-more display block margin 0 padding 10px 0 width 100% font-size 1em text-align center color #999 cursor pointer background #fafafa outline none border none border-bottom solid 1px #eef0f2 border-radius 6px 6px 0 0 box-shadow none &:hover background #f6f6f6 &:active background #f0f0f0 &:disabled color #ccc > .context > * border-bottom 1px solid #eef0f2 > .repost color #9dbb00 background linear-gradient(to bottom, #edfde2 0%, #fff 100%) > p margin 0 padding 16px 32px .avatar-anchor display inline-block .avatar vertical-align bottom min-width 28px min-height 28px max-width 28px max-height 28px margin 0 8px 0 0 border-radius 6px [data-fa] margin-right 4px .name font-weight bold & + article padding-top 8px > .reply-to border-bottom 1px solid #eef0f2 > article padding 14px 16px 9px 16px @media (min-width 500px) padding 28px 32px 18px 32px &:after content "" display block clear both &:hover > .main > footer > button color #888 > header display flex line-height 1.1 > .avatar-anchor display block padding 0 .5em 0 0 > .avatar display block width 54px height 54px margin 0 border-radius 8px vertical-align bottom @media (min-width 500px) width 60px height 60px > div > .name display inline-block margin .4em 0 color #777 font-size 16px font-weight bold text-align left text-decoration none &:hover text-decoration underline > .username display block text-align left margin 0 color #ccc > .body padding 8px 0 > .text cursor default display block margin 0 padding 0 overflow-wrap break-word font-size 16px color #717171 @media (min-width 500px) font-size 24px > mk-url-preview margin-top 8px > .media > img display block max-width 100% > .time font-size 16px color #c0c0c0 > footer font-size 1.2em > button margin 0 padding 8px background transparent border none box-shadow none font-size 1em color #ddd cursor pointer &:not(:last-child) margin-right 28px &:hover color #666 > .count display inline margin 0 0 0 8px color #999 &.reacted color $theme-color > .replies > * border-top 1px solid #eef0f2 </style>