mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-12-22 13:03:16 +00:00
Add section components
This commit is contained in:
parent
9817025578
commit
bffd8f0771
2 changed files with 788 additions and 0 deletions
206
resources/assets/components/sections/DiscoverFeed.vue
Normal file
206
resources/assets/components/sections/DiscoverFeed.vue
Normal file
|
@ -0,0 +1,206 @@
|
|||
<template>
|
||||
<div class="discover-feed-component">
|
||||
<section class="mt-3 mb-5 section-explore">
|
||||
<b-breadcrumb class="font-default" :items="breadcrumbItems"></b-breadcrumb>
|
||||
|
||||
<div class="profile-timeline">
|
||||
<div class="row p-0 mt-5">
|
||||
<div class="col-12 mb-4 d-flex justify-content-between align-items-center">
|
||||
<p class="d-block d-md-none h1 font-weight-bold mb-0 font-default">Trending</p>
|
||||
<p class="d-none d-md-block display-4 font-weight-bold mb-0 font-default">Trending</p>
|
||||
|
||||
<div>
|
||||
<div class="btn-group trending-range">
|
||||
<button @click="rangeToggle('daily')" :class="range == 'daily' ? 'btn py-1 font-weight-bold px-3 text-uppercase btn-sm btn-danger':'btn py-1 font-weight-bold px-3 text-uppercase btn-sm btn-outline-danger'">Today</button>
|
||||
<button @click="rangeToggle('monthly')" :class="range == 'monthly' ? 'btn py-1 font-weight-bold px-3 text-uppercase btn-sm btn-danger':'btn py-1 font-weight-bold px-3 text-uppercase btn-sm btn-outline-danger'">This month</button>
|
||||
<button @click="rangeToggle('yearly')" :class="range == 'yearly' ? 'btn py-1 font-weight-bold px-3 text-uppercase btn-sm btn-danger':'btn py-1 font-weight-bold px-3 text-uppercase btn-sm btn-outline-danger'">This year</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading" class="row p-0 px-lg-3">
|
||||
<div v-if="trending.length" v-for="(s, index) in trending" class="col-6 col-lg-4 col-xl-3 p-1">
|
||||
<a class="card info-overlay card-md-border-0" :href="s.url" @click.prevent="goToPost(s)">
|
||||
<div class="square square-next">
|
||||
<div v-if="s.sensitive" class="square-content">
|
||||
<div class="info-overlay-text-label">
|
||||
<h5 class="text-white m-auto font-weight-bold">
|
||||
<span>
|
||||
<span class="far fa-eye-slash fa-lg p-2 d-flex-inline"></span>
|
||||
</span>
|
||||
</h5>
|
||||
</div>
|
||||
<blur-hash-canvas
|
||||
width="32"
|
||||
height="32"
|
||||
:hash="s.media_attachments[0].blurhash"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="square-content">
|
||||
<blur-hash-image
|
||||
width="32"
|
||||
height="32"
|
||||
:hash="s.media_attachments[0].blurhash"
|
||||
:src="s.media_attachments[0].preview_url"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="info-overlay-text">
|
||||
<div class="text-white m-auto">
|
||||
<p class="info-overlay-text-field font-weight-bold">
|
||||
<span class="far fa-heart fa-lg p-2 d-flex-inline"></span>
|
||||
<span class="d-flex-inline">{{formatCount(s.favourites_count)}}</span>
|
||||
</p>
|
||||
|
||||
<p class="info-overlay-text-field font-weight-bold">
|
||||
<span class="far fa-comment fa-lg p-2 d-flex-inline"></span>
|
||||
<span class="d-flex-inline">{{formatCount(s.reply_count)}}</span>
|
||||
</p>
|
||||
|
||||
<p class="mb-0 info-overlay-text-field font-weight-bold">
|
||||
<span class="far fa-sync fa-lg p-2 d-flex-inline"></span>
|
||||
<span class="d-flex-inline">{{formatCount(s.reblogs_count)}}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div v-else class="col-12 d-flex align-items-center justify-content-center bg-light border" style="min-height: 40vh;">
|
||||
<div class="h2">No posts found :(</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="row p-0 px-lg-3">
|
||||
<div class="col-12 d-flex align-items-center justify-content-center" style="min-height: 40vh;">
|
||||
<b-spinner size="lg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: {
|
||||
profile: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
trending: [],
|
||||
range: 'daily',
|
||||
breadcrumbItems: [
|
||||
{
|
||||
text: 'Discover',
|
||||
href: '/i/web/discover'
|
||||
},
|
||||
{
|
||||
text: 'Trending',
|
||||
active: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.loadTrending();
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchData() {
|
||||
axios.get('/api/pixelfed/v2/discover/posts')
|
||||
.then((res) => {
|
||||
this.posts = res.data.posts.filter(r => r != null);
|
||||
this.recommendedLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
loadTrending() {
|
||||
this.loading = true;
|
||||
|
||||
axios.get('/api/pixelfed/v2/discover/posts/trending', {
|
||||
params: {
|
||||
range: this.range
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
let data = res.data.filter(r => {
|
||||
return r !== null;
|
||||
});
|
||||
this.trending = data.filter(t => t.sensitive == false);
|
||||
|
||||
if(this.range == 'daily' && data.length == 0) {
|
||||
this.range = 'yearly';
|
||||
this.loadTrending();
|
||||
}
|
||||
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
formatCount(s) {
|
||||
return App.util.format.count(s);
|
||||
},
|
||||
|
||||
goToPost(status) {
|
||||
this.$router.push({
|
||||
name: 'post',
|
||||
params: {
|
||||
id: status.id,
|
||||
cachedStatus: status,
|
||||
cachedProfile: this.profile
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
rangeToggle(range) {
|
||||
event.currentTarget.blur();
|
||||
this.range = range;
|
||||
this.loadTrending();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.discover-feed-component {
|
||||
.font-default {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
||||
letter-spacing: -0.7px;
|
||||
}
|
||||
|
||||
.info-overlay {
|
||||
border-radius: 15px !important;
|
||||
}
|
||||
|
||||
.square-next {
|
||||
img,
|
||||
.info-overlay-text {
|
||||
border-radius: 15px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.trending-range {
|
||||
.btn {
|
||||
&:hover:not(.btn-danger) {
|
||||
background-color: #fca5a5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.info-overlay-text-field {
|
||||
font-size: 13.5px;
|
||||
margin-bottom: 2px;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
font-size: 20px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
582
resources/assets/components/sections/Timeline.vue
Normal file
582
resources/assets/components/sections/Timeline.vue
Normal file
|
@ -0,0 +1,582 @@
|
|||
<template>
|
||||
<div class="timeline-section-component">
|
||||
<div v-if="!isLoaded">
|
||||
<status-placeholder />
|
||||
<status-placeholder />
|
||||
<status-placeholder />
|
||||
<status-placeholder />
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<status
|
||||
v-for="(status, index) in feed"
|
||||
:key="'pf_feed:' + status.id + ':idx:' + index + ':fui:' + forceUpdateIdx"
|
||||
:status="status"
|
||||
:profile="profile"
|
||||
v-on:like="likeStatus(index)"
|
||||
v-on:unlike="unlikeStatus(index)"
|
||||
v-on:share="shareStatus(index)"
|
||||
v-on:unshare="unshareStatus(index)"
|
||||
v-on:menu="openContextMenu(index)"
|
||||
v-on:counter-change="counterChange(index, $event)"
|
||||
v-on:likes-modal="openLikesModal(index)"
|
||||
v-on:shares-modal="openSharesModal(index)"
|
||||
v-on:follow="follow(index)"
|
||||
v-on:unfollow="unfollow(index)"
|
||||
v-on:comment-likes-modal="openCommentLikesModal"
|
||||
v-on:handle-report="handleReport"
|
||||
v-on:bookmark="handleBookmark(index)"
|
||||
v-on:mod-tools="handleModTools(index)"
|
||||
/>
|
||||
|
||||
<div v-if="showLoadMore" class="text-center">
|
||||
<button
|
||||
class="btn btn-primary rounded-pill font-weight-bold"
|
||||
@click="tryToLoadMore">
|
||||
Load more
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="canLoadMore">
|
||||
<intersect @enter="enterIntersect">
|
||||
<status-placeholder style="margin-bottom: 10rem;"/>
|
||||
</intersect>
|
||||
</div>
|
||||
|
||||
<div v-if="!isLoaded && feed.length && endFeedReached" style="margin-bottom: 50vh">
|
||||
<div class="card card-body shadow-sm mb-3" style="border-radius: 15px;">
|
||||
<p class="display-4 text-center">✨</p>
|
||||
<p class="lead mb-0 text-center">You have reached the end of this feed</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<timeline-onboarding
|
||||
v-if="scope == 'home' && !feed.length"
|
||||
:profile="profile"
|
||||
v-on:update-profile="updateProfile" />
|
||||
|
||||
<empty-timeline v-if="isLoaded && scope !== 'home' && !feed.length" />
|
||||
</div>
|
||||
|
||||
<context-menu
|
||||
v-if="showMenu"
|
||||
ref="contextMenu"
|
||||
:status="feed[postIndex]"
|
||||
:profile="profile"
|
||||
v-on:moderate="commitModeration"
|
||||
v-on:delete="deletePost"
|
||||
v-on:report-modal="handleReport"
|
||||
v-on:edit="handleEdit"
|
||||
/>
|
||||
|
||||
<likes-modal
|
||||
v-if="showLikesModal"
|
||||
ref="likesModal"
|
||||
:status="likesModalPost"
|
||||
:profile="profile"
|
||||
/>
|
||||
|
||||
<shares-modal
|
||||
v-if="showSharesModal"
|
||||
ref="sharesModal"
|
||||
:status="sharesModalPost"
|
||||
:profile="profile"
|
||||
/>
|
||||
|
||||
<report-modal
|
||||
ref="reportModal"
|
||||
:key="reportedStatusId"
|
||||
:status="reportedStatus"
|
||||
/>
|
||||
|
||||
<post-edit-modal
|
||||
ref="editModal"
|
||||
v-on:update="mergeUpdatedPost"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script type="text/javascript">
|
||||
import StatusPlaceholder from './../partials/StatusPlaceholder.vue';
|
||||
import Status from './../partials/TimelineStatus.vue';
|
||||
import Intersect from 'vue-intersect';
|
||||
import ContextMenu from './../partials/post/ContextMenu.vue';
|
||||
import LikesModal from './../partials/post/LikeModal.vue';
|
||||
import SharesModal from './../partials/post/ShareModal.vue';
|
||||
import ReportModal from './../partials/modal/ReportPost.vue';
|
||||
import EmptyTimeline from './../partials/placeholders/EmptyTimeline.vue'
|
||||
import TimelineOnboarding from './../partials/placeholders/TimelineOnboarding.vue'
|
||||
import PostEditModal from './../partials/post/PostEditModal.vue';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
scope: {
|
||||
type: String,
|
||||
default: "home"
|
||||
},
|
||||
|
||||
profile: {
|
||||
type: Object
|
||||
},
|
||||
|
||||
refresh: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
"intersect": Intersect,
|
||||
"status-placeholder": StatusPlaceholder,
|
||||
"status": Status,
|
||||
"context-menu": ContextMenu,
|
||||
"likes-modal": LikesModal,
|
||||
"shares-modal": SharesModal,
|
||||
"report-modal": ReportModal,
|
||||
"empty-timeline": EmptyTimeline,
|
||||
"timeline-onboarding": TimelineOnboarding,
|
||||
"post-edit-modal": PostEditModal
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
isLoaded: false,
|
||||
feed: [],
|
||||
ids: [],
|
||||
max_id: 0,
|
||||
canLoadMore: true,
|
||||
showLoadMore: false,
|
||||
loadMoreTimeout: undefined,
|
||||
loadMoreAttempts: 0,
|
||||
isFetchingMore: false,
|
||||
endFeedReached: false,
|
||||
postIndex: 0,
|
||||
showMenu: false,
|
||||
showLikesModal: false,
|
||||
likesModalPost: {},
|
||||
showReportModal: false,
|
||||
reportedStatus: {},
|
||||
reportedStatusId: 0,
|
||||
showSharesModal: false,
|
||||
sharesModalPost: {},
|
||||
forceUpdateIdx: 0
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if(window.App.config.features.hasOwnProperty('timelines')) {
|
||||
if(this.scope == 'local' && !window.App.config.features.timelines.local) {
|
||||
swal('Error', 'Cannot load this timeline', 'error');
|
||||
return;
|
||||
};
|
||||
if(this.scope == 'network' && !window.App.config.features.timelines.network) {
|
||||
swal('Error', 'Cannot load this timeline', 'error');
|
||||
return;
|
||||
};
|
||||
}
|
||||
this.fetchTimeline();
|
||||
},
|
||||
|
||||
methods: {
|
||||
getScope() {
|
||||
switch(this.scope) {
|
||||
case 'local':
|
||||
return 'public'
|
||||
break;
|
||||
|
||||
case 'global':
|
||||
return 'network'
|
||||
break;
|
||||
|
||||
default:
|
||||
return 'home';
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
fetchTimeline(scrollToTop = false) {
|
||||
let url = `/api/pixelfed/v1/timelines/${this.getScope()}`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
max_id: this.max_id,
|
||||
limit: 6
|
||||
}
|
||||
}).then(res => {
|
||||
let ids = res.data.map(p => {
|
||||
if(p && p.hasOwnProperty('relationship')) {
|
||||
this.$store.commit('updateRelationship', [p.relationship]);
|
||||
}
|
||||
return p.id
|
||||
});
|
||||
this.isLoaded = true;
|
||||
if(res.data.length == 0) {
|
||||
return;
|
||||
}
|
||||
this.ids = ids;
|
||||
this.max_id = Math.min(...ids);
|
||||
this.feed = res.data;
|
||||
|
||||
if(res.data.length !== 6) {
|
||||
this.canLoadMore = false;
|
||||
this.showLoadMore = true;
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if(scrollToTop) {
|
||||
this.$nextTick(() => {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
this.$emit('refreshed');
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
enterIntersect() {
|
||||
if(this.isFetchingMore) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isFetchingMore = true;
|
||||
|
||||
let url = `/api/pixelfed/v1/timelines/${this.getScope()}`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
max_id: this.max_id,
|
||||
limit: 6
|
||||
}
|
||||
}).then(res => {
|
||||
if(!res.data.length) {
|
||||
this.endFeedReached = true;
|
||||
this.canLoadMore = false;
|
||||
this.isFetchingMore = false;
|
||||
}
|
||||
setTimeout(() => {
|
||||
res.data.forEach(p => {
|
||||
if(this.ids.indexOf(p.id) == -1) {
|
||||
if(this.max_id > p.id) {
|
||||
this.max_id = p.id;
|
||||
}
|
||||
this.ids.push(p.id);
|
||||
this.feed.push(p);
|
||||
if(p && p.hasOwnProperty('relationship')) {
|
||||
this.$store.commit('updateRelationship', [p.relationship]);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.isFetchingMore = false;
|
||||
}, 100);
|
||||
});
|
||||
},
|
||||
|
||||
tryToLoadMore() {
|
||||
this.loadMoreAttempts++;
|
||||
if(this.loadMoreAttempts >= 3) {
|
||||
this.showLoadMore = false;
|
||||
}
|
||||
this.showLoadMore = false;
|
||||
this.canLoadMore = true;
|
||||
this.loadMoreTimeout = setTimeout(() => {
|
||||
this.canLoadMore = false;
|
||||
this.showLoadMore = true;
|
||||
}, 5000);
|
||||
},
|
||||
|
||||
likeStatus(index) {
|
||||
let status = this.feed[index];
|
||||
let state = status.favourited;
|
||||
let count = status.favourites_count;
|
||||
this.feed[index].favourites_count = count + 1;
|
||||
this.feed[index].favourited = !status.favourited;
|
||||
|
||||
axios.post('/api/v1/statuses/' + status.id + '/favourite')
|
||||
.then(res => {
|
||||
//
|
||||
}).catch(err => {
|
||||
this.feed[index].favourites_count = count;
|
||||
this.feed[index].favourited = false;
|
||||
|
||||
let el = document.createElement('p');
|
||||
el.classList.add('text-left');
|
||||
el.classList.add('mb-0');
|
||||
el.innerHTML = '<span class="lead">We limit certain interactions to keep our community healthy and it appears that you have reached that limit. <span class="font-weight-bold">Please try again later.</span></span>';
|
||||
let wrapper = document.createElement('div');
|
||||
wrapper.appendChild(el);
|
||||
|
||||
if(err.response.status === 429) {
|
||||
swal({
|
||||
title: 'Too many requests',
|
||||
content: wrapper,
|
||||
icon: 'warning',
|
||||
buttons: {
|
||||
// moreInfo: {
|
||||
// text: "Contact a human",
|
||||
// visible: true,
|
||||
// value: "more",
|
||||
// className: "text-lighter bg-transparent border"
|
||||
// },
|
||||
confirm: {
|
||||
text: "OK",
|
||||
value: false,
|
||||
visible: true,
|
||||
className: "bg-transparent primary",
|
||||
closeModal: true
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((val) => {
|
||||
if(val == 'more') {
|
||||
location.href = '/site/contact'
|
||||
}
|
||||
return;
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
unlikeStatus(index) {
|
||||
let status = this.feed[index];
|
||||
let state = status.favourited;
|
||||
let count = status.favourites_count;
|
||||
this.feed[index].favourites_count = count - 1;
|
||||
this.feed[index].favourited = !status.favourited;
|
||||
|
||||
axios.post('/api/v1/statuses/' + status.id + '/unfavourite')
|
||||
.then(res => {
|
||||
//
|
||||
}).catch(err => {
|
||||
this.feed[index].favourites_count = count;
|
||||
this.feed[index].favourited = false;
|
||||
})
|
||||
},
|
||||
|
||||
openContextMenu(idx) {
|
||||
this.postIndex = idx;
|
||||
this.showMenu = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.contextMenu.open();
|
||||
});
|
||||
},
|
||||
|
||||
handleModTools(idx) {
|
||||
this.postIndex = idx;
|
||||
this.showMenu = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.contextMenu.openModMenu();
|
||||
});
|
||||
},
|
||||
|
||||
openLikesModal(idx) {
|
||||
this.postIndex = idx;
|
||||
this.likesModalPost = this.feed[this.postIndex];
|
||||
this.showLikesModal = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.likesModal.open();
|
||||
});
|
||||
},
|
||||
|
||||
openSharesModal(idx) {
|
||||
this.postIndex = idx;
|
||||
this.sharesModalPost = this.feed[this.postIndex];
|
||||
this.showSharesModal = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.sharesModal.open();
|
||||
});
|
||||
},
|
||||
|
||||
commitModeration(type) {
|
||||
let idx = this.postIndex;
|
||||
|
||||
switch(type) {
|
||||
case 'addcw':
|
||||
this.feed[idx].sensitive = true;
|
||||
break;
|
||||
|
||||
case 'remcw':
|
||||
this.feed[idx].sensitive = false;
|
||||
break;
|
||||
|
||||
case 'unlist':
|
||||
this.feed.splice(idx, 1);
|
||||
break;
|
||||
|
||||
case 'spammer':
|
||||
let id = this.feed[idx].account.id;
|
||||
|
||||
this.feed = this.feed.filter(post => {
|
||||
return post.account.id != id;
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
deletePost() {
|
||||
this.feed.splice(this.postIndex, 1);
|
||||
},
|
||||
|
||||
counterChange(index, type) {
|
||||
switch(type) {
|
||||
case 'comment-increment':
|
||||
this.feed[index].reply_count = this.feed[index].reply_count + 1;
|
||||
break;
|
||||
|
||||
case 'comment-decrement':
|
||||
this.feed[index].reply_count = this.feed[index].reply_count - 1;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
openCommentLikesModal(post) {
|
||||
this.likesModalPost = post;
|
||||
this.showLikesModal = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.likesModal.open();
|
||||
});
|
||||
},
|
||||
|
||||
shareStatus(index) {
|
||||
let status = this.feed[index];
|
||||
let state = status.reblogged;
|
||||
let count = status.reblogs_count;
|
||||
this.feed[index].reblogs_count = count + 1;
|
||||
this.feed[index].reblogged = !status.reblogged;
|
||||
|
||||
axios.post('/api/v1/statuses/' + status.id + '/reblog')
|
||||
.then(res => {
|
||||
//
|
||||
}).catch(err => {
|
||||
this.feed[index].reblogs_count = count;
|
||||
this.feed[index].reblogged = false;
|
||||
})
|
||||
},
|
||||
|
||||
unshareStatus(index) {
|
||||
let status = this.feed[index];
|
||||
let state = status.reblogged;
|
||||
let count = status.reblogs_count;
|
||||
this.feed[index].reblogs_count = count - 1;
|
||||
this.feed[index].reblogged = !status.reblogged;
|
||||
|
||||
axios.post('/api/v1/statuses/' + status.id + '/unreblog')
|
||||
.then(res => {
|
||||
//
|
||||
}).catch(err => {
|
||||
this.feed[index].reblogs_count = count;
|
||||
this.feed[index].reblogged = false;
|
||||
})
|
||||
},
|
||||
|
||||
handleReport(post) {
|
||||
this.reportedStatusId = post.id;
|
||||
this.$nextTick(() => {
|
||||
this.reportedStatus = post;
|
||||
this.$refs.reportModal.open();
|
||||
});
|
||||
},
|
||||
|
||||
handleBookmark(index) {
|
||||
let p = this.feed[index];
|
||||
|
||||
axios.post('/i/bookmark', {
|
||||
item: p.id
|
||||
})
|
||||
.then(res => {
|
||||
this.feed[index].bookmarked = !p.bookmarked;
|
||||
})
|
||||
.catch(err => {
|
||||
// this.feed[index].bookmarked = false;
|
||||
this.$bvToast.toast('Cannot bookmark post at this time.', {
|
||||
title: 'Bookmark Error',
|
||||
variant: 'danger',
|
||||
autoHideDelay: 5000
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
follow(index) {
|
||||
// this.feed[index].relationship.following = true;
|
||||
|
||||
axios.post('/api/v1/accounts/' + this.feed[index].account.id + '/follow')
|
||||
.then(res => {
|
||||
this.$store.commit('updateRelationship', [res.data]);
|
||||
this.updateProfile({ following_count: this.profile.following_count + 1 });
|
||||
this.feed[index].account.followers_count = this.feed[index].account.followers_count + 1;
|
||||
}).catch(err => {
|
||||
swal('Oops!', 'An error occured when attempting to follow this account.', 'error');
|
||||
this.feed[index].relationship.following = false;
|
||||
});
|
||||
},
|
||||
|
||||
unfollow(index) {
|
||||
// this.feed[index].relationship.following = false;
|
||||
|
||||
axios.post('/api/v1/accounts/' + this.feed[index].account.id + '/unfollow')
|
||||
.then(res => {
|
||||
this.$store.commit('updateRelationship', [res.data]);
|
||||
this.updateProfile({ following_count: this.profile.following_count - 1 });
|
||||
this.feed[index].account.followers_count = this.feed[index].account.followers_count - 1;
|
||||
}).catch(err => {
|
||||
swal('Oops!', 'An error occured when attempting to unfollow this account.', 'error');
|
||||
this.feed[index].relationship.following = true;
|
||||
});
|
||||
},
|
||||
|
||||
updateProfile(delta) {
|
||||
this.$emit('update-profile', delta);
|
||||
},
|
||||
|
||||
handleRefresh() {
|
||||
this.isLoaded = false;
|
||||
this.feed = [];
|
||||
this.ids = [];
|
||||
this.max_id = 0;
|
||||
this.canLoadMore = true;
|
||||
this.showLoadMore = false;
|
||||
this.loadMoreTimeout = undefined;
|
||||
this.loadMoreAttempts = 0;
|
||||
this.isFetchingMore = false;
|
||||
this.endFeedReached = false;
|
||||
this.postIndex = 0;
|
||||
this.showMenu = false;
|
||||
this.showLikesModal = false;
|
||||
this.likesModalPost = {};
|
||||
this.showReportModal = false;
|
||||
this.reportedStatus = {};
|
||||
this.reportedStatusId = 0;
|
||||
this.showSharesModal = false;
|
||||
this.sharesModalPost = {};
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.fetchTimeline(true);
|
||||
});
|
||||
},
|
||||
|
||||
handleEdit(status) {
|
||||
this.$refs.editModal.show(status);
|
||||
},
|
||||
|
||||
mergeUpdatedPost(post) {
|
||||
this.feed = this.feed.map(p => {
|
||||
if(p.id == post.id) {
|
||||
p = post;
|
||||
}
|
||||
return p;
|
||||
});
|
||||
this.$nextTick(() => {
|
||||
this.forceUpdateIdx++;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'refresh': 'handleRefresh'
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
clearTimeout(this.loadMoreTimeout);
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in a new issue