1
0
Fork 0

Timeline refactor

This commit is contained in:
Daniel Supernault 2021-03-01 00:24:44 -07:00
parent 3f8202e29a
commit 5f67a48442
No known key found for this signature in database
GPG Key ID: 0DEF1C662C9033F7
1 changed files with 1119 additions and 781 deletions

View File

@ -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>
@ -244,13 +245,13 @@
<span v-on:click="likeStatus(reply, $event);">
<i v-bind:class="[reply.favourited ? 'fas fa-heart fa-sm text-danger cursor-pointer':'far fa-heart fa-sm text-lighter cursor-pointer']"></i>
</span>
<!-- <post-menu :status="reply" :profile="profile" size="sm" :modal="'true'" :feed="feed" class="d-inline-flex pl-2"></post-menu> -->
<!-- <post-menu :status="reply" :profile="profile" size="sm" :modal="'true'" :feed="feed" class="d-inline-flex pl-2"></post-menu> - ->
<span class="text-lighter pl-2 cursor-pointer" @click="ctxMenu(reply)">
<span class="fas fa-ellipsis-v text-lighter"></span>
</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> &nbsp; {{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;">
@ -716,81 +792,20 @@
profile-layout="metro">
</post-component> -->
</b-modal>
</div>
</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>