forked from mirror/pixelfed
Timeline refactor
This commit is contained in:
parent
3f8202e29a
commit
5f67a48442
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<div class="container" style="">
|
||||
<div v-if="layout === 'feed'" class="row">
|
||||
<div>
|
||||
<div v-if="currentLayout === 'feed'" class="container">
|
||||
<div class="row">
|
||||
<div v-if="morePostsAvailable == true" class="col-12 mt-5 pt-3 mb-3 fixed-top">
|
||||
<p class="text-center">
|
||||
<button class="btn btn-dark px-4 rounded-pill font-weight-bold shadow" @click="syncNewPosts">Load New Posts</button>
|
||||
|
@ -207,10 +208,10 @@
|
|||
<div class="card-body">
|
||||
<div class="reactions my-1 pb-2">
|
||||
<h3 v-if="status.favourited" class="fas fa-heart text-danger pr-3 m-0 cursor-pointer" title="Like" v-on:click="likeStatus(status, $event);"></h3>
|
||||
<h3 v-else class="far fa-heart pr-3 m-0 like-btn text-lighter cursor-pointer" title="Like" v-on:click="likeStatus(status, $event);"></h3>
|
||||
<h3 v-if="!status.comments_disabled" class="far fa-comment text-lighter pr-3 m-0 cursor-pointer" title="Comment" v-on:click="commentFocus(status, $event)"></h3>
|
||||
<h3 v-if="status.visibility == 'public'" v-bind:class="[status.reblogged ? 'fas fa-retweet pr-3 m-0 text-primary cursor-pointer' : 'fas fa-retweet pr-3 m-0 text-lighter share-btn cursor-pointer']" title="Share" v-on:click="shareStatus(status, $event)"></h3>
|
||||
<h3 class="fas fa-expand pr-3 m-0 cursor-pointer text-lighter" v-on:click="lightbox(status)"></h3>
|
||||
<h3 v-else class="far fa-heart pr-3 m-0 like-btn text-dark cursor-pointer" title="Like" v-on:click="likeStatus(status, $event);"></h3>
|
||||
<h3 v-if="!status.comments_disabled" class="far fa-comment text-dark pr-3 m-0 cursor-pointer" title="Comment" v-on:click="commentFocus(status, $event)"></h3>
|
||||
<!-- <h3 v-if="status.visibility == 'public'" v-bind:class="[status.reblogged ? 'fas fa-retweet pr-3 m-0 text-primary cursor-pointer' : 'fas fa-retweet pr-3 m-0 text-dark share-btn cursor-pointer']" title="Share" v-on:click="shareStatus(status, $event)"></h3> -->
|
||||
<!-- <h3 class="fas fa-expand pr-3 m-0 cursor-pointer text-dark" v-on:click="lightbox(status)"></h3> -->
|
||||
<span v-if="status.taggedPeople.length" class="float-right">
|
||||
<span class="font-weight-light small" style="color:#718096">
|
||||
<i class="far fa-user" data-toggle="tooltip" title="Tagged People"></i>
|
||||
|
@ -234,7 +235,7 @@
|
|||
<span class="status-content" v-html="status.content"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="comments" v-if="status.id == replyId && !status.comments_disabled">
|
||||
<!-- <div class="comments" v-if="status.id == replyId && !status.comments_disabled">
|
||||
<p class="mb-0 d-flex justify-content-between align-items-top read-more mt-2" style="overflow-y: hidden;" v-for="(reply, index) in replies">
|
||||
<span>
|
||||
<a class="text-dark font-weight-bold mr-1" :href="profileUrl(reply)">{{reply.account.username}}</a>
|
||||
|
@ -250,7 +251,7 @@
|
|||
</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="timestamp mt-2">
|
||||
<p class="small text-uppercase mb-0">
|
||||
<a :href="statusUrl(status)" class="text-muted">
|
||||
|
@ -296,7 +297,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-lg-4 my-4 order-1 order-md-2 d-none d-md-block">
|
||||
<div>
|
||||
|
||||
|
@ -401,75 +401,145 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row">
|
||||
<div class="col-12">
|
||||
<!-- <div v-if="loading" class="text-center">
|
||||
</div>
|
||||
|
||||
<div v-if="currentLayout === 'comments'" class="container p-0 overflow-hidden">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<div class="card shadow-none border" style="height:100vh;">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div
|
||||
@click="commentNavigateBack(status.id)"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<i class="fas fa-chevron-left fa-lg px-2"></i>
|
||||
</div>
|
||||
<div>
|
||||
<p class="font-weight-bold mb-0 h5">Comments</p>
|
||||
</div>
|
||||
<div>
|
||||
<i class="fas fa-cog fa-lg text-white"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body" style="overflow-y: auto !important">
|
||||
<div class="media">
|
||||
<img :src="status.account.avatar" class="rounded-circle border mr-3" width="32px" height="32px">
|
||||
<div class="media-body">
|
||||
<p class="d-flex justify-content-between align-items-top mb-0" style="overflow-y: hidden;">
|
||||
<span class="mr-2" style="font-size: 13px;">
|
||||
<a class="text-dark font-weight-bold mr-1 text-break" :href="status.account.url" v-bind:title="status.account.username">{{trimCaption(status.account.username,15)}}</a>
|
||||
<span class="text-break comment-body" style="word-break: break-all;" v-html="status.content"></span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="postCommentsLoader text-center py-2">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="row">
|
||||
<div class="col-12 pl-3 pl-md-0 pt-3 pl-0">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<p class="lead text-muted mb-0"><i :class="[scope == 'home' ? 'fas fa-home':'fas fa-stream']"></i> {{scope == 'local' ? 'Public' : 'Home'}} Timeline</p>
|
||||
<p class="mb-0">
|
||||
<span class="btn-group">
|
||||
<a href="#" :class="[layout=='feed'?'btn btn-sm btn-outline-primary font-weight-bold text-decoration-none':'btn btn-sm btn-outline-lighter font-weight-light text-decoration-none']" @click.prevent="switchFeedLayout('feed')"><i class="fas fa-list"></i></a>
|
||||
<a href="#" :class="[layout!=='feed'?'btn btn-sm btn-outline-primary font-weight-bold text-decoration-none':'btn btn-sm btn-outline-lighter font-weight-light text-decoration-none']" @click.prevent="switchFeedLayout('grid')"><i class="fas fa-th"></i></a>
|
||||
</div>
|
||||
<div class="postCommentsContainer d-none">
|
||||
<p v-if="replies.length" class="mb-1 text-center load-more-link my-4">
|
||||
<a
|
||||
href="#"
|
||||
class="text-dark"
|
||||
title="Load more comments"
|
||||
@click.prevent="loadMoreComments"
|
||||
>
|
||||
<svg class="bi bi-plus-circle" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg" style="font-size:2em;"> <path fill-rule="evenodd" d="M8 3.5a.5.5 0 01.5.5v4a.5.5 0 01-.5.5H4a.5.5 0 010-1h3.5V4a.5.5 0 01.5-.5z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M7.5 8a.5.5 0 01.5-.5h4a.5.5 0 010 1H8.5V12a.5.5 0 01-1 0V8z" clip-rule="evenodd"/> <path fill-rule="evenodd" d="M8 15A7 7 0 108 1a7 7 0 000 14zm0 1A8 8 0 108 0a8 8 0 000 16z" clip-rule="evenodd"/></svg>
|
||||
</a>
|
||||
</p>
|
||||
<div v-for="(reply, index) in replies" class="pb-3 media" :key="'tl' + reply.id + '_' + index">
|
||||
<img :src="reply.account.avatar" class="rounded-circle border mr-3" width="32px" height="32px">
|
||||
<div class="media-body">
|
||||
<div v-if="reply.sensitive == true">
|
||||
<span class="py-3">
|
||||
<a class="text-dark font-weight-bold mr-3" style="font-size: 13px;" :href="reply.account.url" v-bind:title="reply.account.username">{{trimCaption(reply.account.username,15)}}</a>
|
||||
<span class="text-break" style="font-size: 13px;">
|
||||
<span class="font-italic text-muted">This comment may contain sensitive material</span>
|
||||
<span class="text-primary cursor-pointer pl-1" @click="reply.sensitive = false;">Show</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p class="d-flex justify-content-between align-items-top read-more mb-0" style="overflow-y: hidden;">
|
||||
<span class="mr-3" style="font-size: 13px;">
|
||||
<a class="text-dark font-weight-bold mr-1 text-break" :href="reply.account.url" v-bind:title="reply.account.username">{{trimCaption(reply.account.username,15)}}</a>
|
||||
<span class="text-break comment-body" style="word-break: break-all;" v-html="reply.content"></span>
|
||||
</span>
|
||||
<span class="text-right" style="min-width: 30px;">
|
||||
<span v-on:click="likeReply(reply, $event)"><i v-bind:class="[reply.favourited ? 'fas fa-heart fa-sm text-danger':'far fa-heart fa-sm text-lighter']"></i></span>
|
||||
<span class="pl-2 text-lighter cursor-pointer" @click="ctxMenu(reply)">
|
||||
<span class="fas fa-ellipsis-v text-lighter"></span>
|
||||
</span>
|
||||
<!-- <post-menu :status="reply" :profile="user" :size="'sm'" :modal="'true'" class="d-inline-block px-2" v-on:deletePost=""></post-menu> -->
|
||||
</span>
|
||||
</p>
|
||||
<p class="mb-0 d-none d-md-block">
|
||||
<a class="btn btn-block btn-primary btn-sm font-weight-bold" href="/i/compose" data-toggle="modal" data-target="#composeModal">
|
||||
New Post
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 p-1 p-md-3 mb-3" v-for="(s, index) in feed" :key="`${index}-${s.id}`">
|
||||
<a class="card info-overlay card-md-border-0 shadow-sm border border-light" :href="statusUrl(s)">
|
||||
<div :class="[s.sensitive ? 'square' : 'square ' + s.media_attachments[0].filter_class]">
|
||||
<span v-if="s.pf_type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
|
||||
<span v-if="s.pf_type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
|
||||
<span v-if="s.pf_type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
|
||||
<div class="square-content" v-bind:style="previewBackground(s)">
|
||||
</div>
|
||||
<div class="info-overlay-text px-4">
|
||||
<p class="text-white m-auto text-center">
|
||||
{{trimCaption(s.content_text)}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<div class="py-3 media align-items-center">
|
||||
<a class="text-decoration-none" :href="s.account.url"><img :src="s.account.avatar" class="mr-3 rounded-circle shadow-sm" :alt="s.account.username + ' \'s avatar'" width="30px" height="30px" onerror="this.onerror=null;this.src='/storage/avatars/default.png?v=2'"></a>
|
||||
<div class="media-body">
|
||||
<p class="mb-0 font-weight-bold small"><a class="text-dark" :href="s.account.url">{{s.account.username}}</a></p>
|
||||
<p class="mb-0" style="line-height: 0.7;">
|
||||
<a :href="statusUrl(s)" class="small text-lighter">
|
||||
<timeago :datetime="s.created_at" :auto-update="60" :converter-options="{includeSeconds:true}" :title="timestampFormat(s.created_at)" v-b-tooltip.hover.bottom></timeago>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="mb-0">
|
||||
<span v-if="statusOwner(s)" class="font-weight-bold small">{{s.favourites_count == 1 ? '1 like' : s.favourites_count+' likes'}}</span>
|
||||
<span class="px-2"><i v-bind:class="[s.favourited ? 'fas fa-heart text-danger cursor-pointer' : 'far fa-heart like-btn text-lighter cursor-pointer']" v-on:click="likeStatus(s, $event);"></i></span>
|
||||
<span class="mr-2 cursor-pointer"><i class="fas fa-ellipsis-v" @click="ctxMenu(s)"></i></span>
|
||||
<a v-once class="text-muted mr-3 text-decoration-none small" style="width: 20px;" v-text="timeAgo(reply.created_at)" :href="reply.url"></a>
|
||||
<span v-if="reply.favourites_count" class="text-muted comment-reaction font-weight-bold mr-3 small">{{reply.favourites_count == 1 ? '1 like' : reply.favourites_count + ' likes'}}</span>
|
||||
<span class="small text-muted comment-reaction font-weight-bold cursor-pointer" v-on:click="replyFocus(reply, index, true)">Reply</span>
|
||||
</p>
|
||||
<div v-if="reply.reply_count > 0" class="cursor-pointer pb-2" v-on:click="toggleReplies(reply)">
|
||||
<span class="show-reply-bar"></span>
|
||||
<span class="comment-reaction small font-weight-bold">{{reply.thread ? 'Hide' : 'View'}} Replies ({{reply.reply_count}})</span>
|
||||
</div>
|
||||
<div v-if="reply.thread == true" class="comment-thread">
|
||||
<div v-for="(s, sindex) in reply.replies" class="py-1 media" :key="'cr' + s.id + '_' + index">
|
||||
<img :src="s.account.avatar" class="rounded-circle border mr-3" width="25px" height="25px">
|
||||
<div class="media-body">
|
||||
<p class="d-flex justify-content-between align-items-top read-more mb-0" style="overflow-y: hidden;">
|
||||
<span class="mr-2" style="font-size: 13px;">
|
||||
<a class="text-dark font-weight-bold mr-1" :href="s.account.url" :title="s.account.username">{{s.account.username}}</a>
|
||||
<span class="text-break comment-body" style="word-break: break-all;" v-html="s.content"></span>
|
||||
</span>
|
||||
<span>
|
||||
<span v-on:click="likeReply(s, $event)"><i v-bind:class="[s.favourited ? 'fas fa-heart fa-sm text-danger':'far fa-heart fa-sm text-lighter']"></i></span>
|
||||
<!-- <post-menu :status="s" :profile="user" :size="'sm'" :modal="'true'" class="d-inline-block pl-2" v-on:deletePost="deleteCommentReply(s.id, sindex, index) "></post-menu> -->
|
||||
</span>
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<a v-once class="text-muted mr-3 text-decoration-none small" style="width: 20px;" v-text="timeAgo(s.created_at)" :href="s.url"></a>
|
||||
<span v-if="s.favourites_count" class="text-muted comment-reaction font-weight-bold mr-3">{{s.favourites_count == 1 ? '1 like' : s.favourites_count + ' likes'}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && feed.length">
|
||||
<infinite-loading @infinite="infiniteTimeline" :distance="800">
|
||||
<div slot="no-more" class="font-weight-bold">No more posts to load</div>
|
||||
<div slot="no-results" class="font-weight-bold">No more posts to load</div>
|
||||
</infinite-loading>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!replies.length">
|
||||
<p class="text-center text-muted font-weight-bold small">No comments yet</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer mb-3">
|
||||
<div class="align-middle d-flex">
|
||||
<img
|
||||
:src="profile.avatar"
|
||||
width="36"
|
||||
height="36"
|
||||
class="rounded-circle border mr-3">
|
||||
<textarea
|
||||
class="form-control rounded-pill"
|
||||
name="comment"
|
||||
placeholder="Add a comment…"
|
||||
autocomplete="off"
|
||||
autocorrect="off"
|
||||
rows="1"
|
||||
maxlength="0"
|
||||
style="resize: none;overflow-y: hidden"
|
||||
@click="replyFocus(status)">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-stack">
|
||||
<b-modal ref="ctxModal"
|
||||
id="ctx-modal"
|
||||
hide-header
|
||||
|
@ -538,6 +608,7 @@
|
|||
rounded
|
||||
size="sm"
|
||||
body-class="list-group-flush p-0 rounded text-center">
|
||||
<div class="list-group-item rounded cursor-pointer" @click="shareStatus(ctxMenuStatus, $event)">{{ctxMenuStatus.reblogged ? 'Unshare' : 'Share'}} to Followers</div>
|
||||
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</div>
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.local == true && !ctxMenuStatus.in_reply_to_id" class="list-group-item rounded cursor-pointer" @click="ctxMenuEmbed()">Embed</div>
|
||||
<!-- <div class="list-group-item rounded cursor-pointer border-top-0">Email</div>
|
||||
|
@ -669,8 +740,13 @@
|
|||
size="md"
|
||||
body-class="p-2 rounded">
|
||||
<div>
|
||||
<textarea class="form-control" rows="4" style="border: none; font-size: 18px; resize: none; white-space: pre-wrap;outline: none;" placeholder="Reply here ..." v-model="replyText">
|
||||
<vue-tribute :options="tributeSettings">
|
||||
<textarea
|
||||
class="form-control replyModalTextarea"
|
||||
rows="4"
|
||||
v-model="replyText">
|
||||
</textarea>
|
||||
</vue-tribute>
|
||||
|
||||
<div class="border-top border-bottom my-2">
|
||||
<ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;">
|
||||
|
@ -717,80 +793,19 @@
|
|||
</post-component> -->
|
||||
</b-modal>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style type="text/css" scoped>
|
||||
.postPresenterContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
}
|
||||
.word-break {
|
||||
word-break: break-all;
|
||||
}
|
||||
.small .custom-control-label {
|
||||
padding-top: 3px;
|
||||
}
|
||||
.reply-btn {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
right: 20px;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.emoji-reactions .nav-item {
|
||||
font-size: 1.2rem;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.emoji-reactions::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
.reply-btn[disabled] {
|
||||
opacity: .3;
|
||||
color: #3897f0;
|
||||
}
|
||||
.has-story {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
padding: 2px;
|
||||
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
|
||||
}
|
||||
.has-story img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
padding: 3px;
|
||||
background: #fff;
|
||||
}
|
||||
.has-story.has-story-sm {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
padding: 2px;
|
||||
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
|
||||
}
|
||||
.has-story.has-story-sm img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
padding: 3px;
|
||||
background: #fff;
|
||||
}
|
||||
#ctx-reply-modal .form-control:focus {
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
import VueTribute from 'vue-tribute'
|
||||
|
||||
export default {
|
||||
props: ['scope', 'layout'],
|
||||
|
||||
components: {
|
||||
VueTribute
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
ids: [],
|
||||
|
@ -844,7 +859,41 @@
|
|||
mpPoller: null,
|
||||
confirmModalTitle: 'Are you sure?',
|
||||
confirmModalIdentifer: null,
|
||||
confirmModalType: false
|
||||
confirmModalType: false,
|
||||
currentLayout: 'feed',
|
||||
pagination: {},
|
||||
tributeSettings: {
|
||||
collection: [
|
||||
{
|
||||
trigger: '@',
|
||||
menuShowMinLength: 2,
|
||||
values: (function (text, cb) {
|
||||
let url = '/api/compose/v0/search/mention';
|
||||
axios.get(url, { params: { q: text }})
|
||||
.then(res => {
|
||||
cb(res.data);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
})
|
||||
},
|
||||
{
|
||||
trigger: '#',
|
||||
menuShowMinLength: 2,
|
||||
values: (function (text, cb) {
|
||||
let url = '/api/compose/v0/search/hashtag';
|
||||
axios.get(url, { params: { q: text }})
|
||||
.then(res => {
|
||||
cb(res.data);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1057,10 +1106,10 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if(this.status && this.status.id == status.id) {
|
||||
this.$refs.replyModal.show();
|
||||
return;
|
||||
}
|
||||
// if(this.status && this.status.id == status.id) {
|
||||
// this.$refs.replyModal.show();
|
||||
// return;
|
||||
// }
|
||||
|
||||
this.status = status;
|
||||
this.replies = {};
|
||||
|
@ -1068,10 +1117,32 @@
|
|||
this.replyText = '';
|
||||
this.replyId = status.id;
|
||||
this.replyStatus = status;
|
||||
this.$refs.replyModal.show();
|
||||
// this.$refs.replyModal.show();
|
||||
this.fetchStatusComments(status, '');
|
||||
return;
|
||||
|
||||
$('nav').hide();
|
||||
$('footer').hide();
|
||||
$('.mobile-footer-spacer').attr('style', 'display:none !important');
|
||||
$('.mobile-footer').attr('style', 'display:none !important');
|
||||
this.currentLayout = 'comments';
|
||||
window.history.pushState({}, '', status.url);
|
||||
return;
|
||||
},
|
||||
|
||||
commentNavigateBack(id) {
|
||||
$('nav').show();
|
||||
$('footer').show();
|
||||
$('.mobile-footer-spacer').attr('style', 'display:block');
|
||||
$('.mobile-footer').attr('style', 'display:block');
|
||||
this.currentLayout = 'feed';
|
||||
setTimeout(function() {
|
||||
$([document.documentElement, document.body]).animate({
|
||||
scrollTop: $(`div[data-status-id="${id}"]`).offset().top
|
||||
}, 1000);
|
||||
}, 500);
|
||||
|
||||
let path = this.scope == 'home' ? '/' : '/timeline/public';
|
||||
window.history.pushState({}, '', path);
|
||||
},
|
||||
|
||||
likeStatus(status, event) {
|
||||
|
@ -1102,11 +1173,18 @@
|
|||
return;
|
||||
}
|
||||
|
||||
this.closeModals();
|
||||
|
||||
axios.post('/i/share', {
|
||||
item: status.id
|
||||
}).then(res => {
|
||||
status.reblogs_count = res.data.count;
|
||||
status.reblogged = !status.reblogged;
|
||||
if(status.reblogged) {
|
||||
swal('Success', 'You shared this post', 'success');
|
||||
} else {
|
||||
swal('Success', 'You unshared this post', 'success');
|
||||
}
|
||||
}).catch(err => {
|
||||
swal('Error', 'Something went wrong, please try again later.', 'error');
|
||||
});
|
||||
|
@ -1133,19 +1211,67 @@
|
|||
},
|
||||
|
||||
fetchStatusComments(status, card) {
|
||||
axios.get('/api/v2/status/'+status.id+'/replies')
|
||||
.then(res => {
|
||||
let data = res.data.filter(res => {
|
||||
return res.sensitive == false;
|
||||
// axios.get('/api/v2/status/'+status.id+'/replies',
|
||||
// {
|
||||
// params: {
|
||||
// limit: 6
|
||||
// }
|
||||
// })
|
||||
// .then(res => {
|
||||
// let data = res.data.filter(res => {
|
||||
// return res.sensitive == false;
|
||||
// });
|
||||
// this.replies = _.reverse(data);
|
||||
// setTimeout(function() {
|
||||
// document.querySelectorAll('.timeline .card-body .comments .comment-body a').forEach(function(i, e) {
|
||||
// i.href = App.util.format.rewriteLinks(i);
|
||||
// });
|
||||
// }, 500);
|
||||
// }).catch(err => {
|
||||
// })
|
||||
let url = '/api/v2/comments/'+status.account.id+'/status/'+status.id;
|
||||
axios.get(url)
|
||||
.then(response => {
|
||||
let self = this;
|
||||
// this.results = this.layout == 'metro' ?
|
||||
// _.reverse(response.data.data) :
|
||||
// response.data.data;
|
||||
this.replies = _.reverse(response.data.data);
|
||||
this.pagination = response.data.meta.pagination;
|
||||
if(this.replies.length > 0) {
|
||||
$('.load-more-link').removeClass('d-none');
|
||||
}
|
||||
$('.postCommentsLoader').addClass('d-none');
|
||||
$('.postCommentsContainer').removeClass('d-none');
|
||||
// setTimeout(function() {
|
||||
// document.querySelectorAll('.status-comment .postCommentsContainer .comment-body a').forEach(function(i, e) {
|
||||
// i.href = App.util.format.rewriteLinks(i);
|
||||
// });
|
||||
// }, 500);
|
||||
}).catch(error => {
|
||||
if(!error.response) {
|
||||
$('.postCommentsLoader .lds-ring')
|
||||
.attr('style','width:100%')
|
||||
.addClass('pt-4 font-weight-bold text-muted')
|
||||
.text('An error occurred, cannot fetch comments. Please try again later.');
|
||||
} else {
|
||||
switch(error.response.status) {
|
||||
case 401:
|
||||
$('.postCommentsLoader .lds-ring')
|
||||
.attr('style','width:100%')
|
||||
.addClass('pt-4 font-weight-bold text-muted')
|
||||
.text('Please login to view.');
|
||||
break;
|
||||
|
||||
default:
|
||||
$('.postCommentsLoader .lds-ring')
|
||||
.attr('style','width:100%')
|
||||
.addClass('pt-4 font-weight-bold text-muted')
|
||||
.text('An error occurred, cannot fetch comments. Please try again later.');
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
this.replies = _.reverse(data);
|
||||
setTimeout(function() {
|
||||
document.querySelectorAll('.timeline .card-body .comments .comment-body a').forEach(function(i, e) {
|
||||
i.href = App.util.format.rewriteLinks(i);
|
||||
});
|
||||
}, 500);
|
||||
}).catch(err => {
|
||||
})
|
||||
},
|
||||
|
||||
muteProfile(status) {
|
||||
|
@ -1217,7 +1343,7 @@
|
|||
sensitive: this.replyNsfw
|
||||
}).then(res => {
|
||||
this.replyText = '';
|
||||
this.replies.unshift(res.data.entity);
|
||||
this.replies.push(res.data.entity);
|
||||
this.$refs.replyModal.hide();
|
||||
});
|
||||
this.replySending = false;
|
||||
|
@ -1927,6 +2053,92 @@
|
|||
|
||||
confirmModalCancel() {
|
||||
this.closeConfirmModal();
|
||||
},
|
||||
|
||||
timeAgo(ts) {
|
||||
return App.util.format.timeAgo(ts);
|
||||
},
|
||||
|
||||
toggleReplies(reply) {
|
||||
if(reply.thread) {
|
||||
reply.thread = false;
|
||||
} else {
|
||||
if(reply.replies.length > 0) {
|
||||
reply.thread = true;
|
||||
return;
|
||||
}
|
||||
let url = '/api/v2/comments/'+reply.account.id+'/status/'+reply.id;
|
||||
axios.get(url)
|
||||
.then(response => {
|
||||
reply.replies = _.reverse(response.data.data);
|
||||
reply.thread = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
likeReply(status, $event) {
|
||||
if($('body').hasClass('loggedIn') == false) {
|
||||
swal('Login', 'Please login to perform this action.', 'info');
|
||||
return;
|
||||
}
|
||||
|
||||
axios.post('/i/like', {
|
||||
item: status.id
|
||||
}).then(res => {
|
||||
status.favourites_count = res.data.count;
|
||||
if(status.favourited == true) {
|
||||
status.favourited = false;
|
||||
} else {
|
||||
status.favourited = true;
|
||||
}
|
||||
}).catch(err => {
|
||||
swal('Error', 'Something went wrong, please try again later.', 'error');
|
||||
});
|
||||
},
|
||||
|
||||
replyFocus(e, index, prependUsername = false) {
|
||||
if($('body').hasClass('loggedIn') == false) {
|
||||
this.redirect('/login?next=' + encodeURIComponent(window.location.pathname));
|
||||
return;
|
||||
}
|
||||
if(this.status.comments_disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.replyToIndex = index;
|
||||
this.replyingToId = e.id;
|
||||
this.replyingToUsername = e.account.username;
|
||||
this.reply_to_profile_id = e.account.id;
|
||||
let username = e.account.local ? '@' + e.account.username + ' '
|
||||
: '@' + e.account.acct + ' ';
|
||||
if(prependUsername == true) {
|
||||
this.replyText = username;
|
||||
}
|
||||
this.$refs.replyModal.show();
|
||||
setTimeout(function() {
|
||||
$('.replyModalTextarea').focus();
|
||||
}, 500);
|
||||
},
|
||||
|
||||
loadMoreComments() {
|
||||
if(this.pagination.total_pages == 1 || this.pagination.current_page == this.pagination.total_pages) {
|
||||
$('.load-more-link').addClass('d-none');
|
||||
return;
|
||||
}
|
||||
$('.load-more-link').addClass('d-none');
|
||||
$('.postCommentsLoader').removeClass('d-none');
|
||||
let next = this.pagination.links.next;
|
||||
axios.get(next)
|
||||
.then(response => {
|
||||
let self = this;
|
||||
let res = response.data.data;
|
||||
$('.postCommentsLoader').addClass('d-none');
|
||||
for(let i=0; i < res.length; i++) {
|
||||
this.replies.unshift(res[i]);
|
||||
}
|
||||
this.pagination = response.data.meta.pagination;
|
||||
$('.load-more-link').removeClass('d-none');
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1935,3 +2147,129 @@
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="text/css" scoped>
|
||||
.postPresenterContainer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
}
|
||||
.word-break {
|
||||
word-break: break-all;
|
||||
}
|
||||
.small .custom-control-label {
|
||||
padding-top: 3px;
|
||||
}
|
||||
/*.reply-btn {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
right: 20px;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}*/
|
||||
.emoji-reactions .nav-item {
|
||||
font-size: 1.2rem;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.emoji-reactions::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
.reply-btn[disabled] {
|
||||
opacity: .3;
|
||||
color: #3897f0;
|
||||
}
|
||||
.replyModalTextarea {
|
||||
border: none;
|
||||
font-size: 18px;
|
||||
resize: none;
|
||||
white-space: pre-wrap;
|
||||
outline: none;
|
||||
}
|
||||
.has-story {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
padding: 2px;
|
||||
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
|
||||
}
|
||||
.has-story img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
padding: 3px;
|
||||
background: #fff;
|
||||
}
|
||||
.has-story.has-story-sm {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
padding: 2px;
|
||||
background: radial-gradient(ellipse at 70% 70%, #ee583f 8%, #d92d77 42%, #bd3381 58%);
|
||||
}
|
||||
.has-story.has-story-sm img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
padding: 3px;
|
||||
background: #fff;
|
||||
}
|
||||
#ctx-reply-modal .form-control:focus {
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
</style>
|
||||
<style type="text/css">
|
||||
.tribute-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: auto;
|
||||
max-height: 300px;
|
||||
min-width: 120px;
|
||||
max-width: 100vw;
|
||||
overflow: auto;
|
||||
display: block;
|
||||
z-index: 999999;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 1px 4px rgba(#000, 0.13);
|
||||
}
|
||||
.tribute-container ul {
|
||||
margin: 0;
|
||||
margin-top: 2px;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
background: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(#000, 0.13);
|
||||
background-clip: padding-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tribute-container li {
|
||||
color: #000;
|
||||
padding: 5px 15px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
.tribute-container li.highlight,
|
||||
.tribute-container li:hover {
|
||||
background: #2c78bf;
|
||||
color: #fff;
|
||||
}
|
||||
.tribute-container li span {
|
||||
font-weight: bold;
|
||||
}
|
||||
.tribute-container li.no-match {
|
||||
cursor: default;
|
||||
}
|
||||
.tribute-container .menu-highlighted {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue