mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-14 18:44:31 +00:00
406 lines
9.8 KiB
Vue
406 lines
9.8 KiB
Vue
|
<template>
|
||
|
<div class="comment-post-component">
|
||
|
<div class="media media-status align-items-top mt-3">
|
||
|
<div v-if="commentBorderArrow" class="comment-border-arrow"></div>
|
||
|
<!-- <a
|
||
|
v-if="replyChildId == status.id"
|
||
|
href="#comment-1"
|
||
|
class="comment-border-link"
|
||
|
@click.prevent="replyToChild(status)">
|
||
|
<span class="sr-only">Jump to comment-{{ index }}</span>
|
||
|
</a> -->
|
||
|
|
||
|
<a :href="status.account.url">
|
||
|
<img class="rounded-circle media-avatar border" :src="status.account.avatar" width="32" height="32" onerror="this.onerror=null;this.src='/storage/avatars/default.png?v=2'">
|
||
|
</a>
|
||
|
|
||
|
<div class="media-body">
|
||
|
<div v-if="!status.media_attachments.length" class="media-body-comment">
|
||
|
<p class="media-body-comment-username">
|
||
|
<a :href="status.account.url">
|
||
|
{{status.account.acct}}
|
||
|
</a>
|
||
|
</p>
|
||
|
<read-more :status="status" />
|
||
|
</div>
|
||
|
<div v-else>
|
||
|
<p class="media-body-comment-username">
|
||
|
<a :href="status.account.url">
|
||
|
{{status.account.acct}}
|
||
|
</a>
|
||
|
</p>
|
||
|
<div class="bh-comment" @click="lightbox(status)">
|
||
|
<blur-hash-image
|
||
|
:width="blurhashWidth(status)"
|
||
|
:height="blurhashHeight(status)"
|
||
|
:punch="1"
|
||
|
class="img-fluid rounded-lg border shadow"
|
||
|
:hash="status.media_attachments[0].blurhash"
|
||
|
:src="getMediaSource(status)" />
|
||
|
</div>
|
||
|
</div>
|
||
|
<p class="media-body-reactions">
|
||
|
<a
|
||
|
v-if="profile"
|
||
|
href="#"
|
||
|
class="font-weight-bold"
|
||
|
:class="[ status.favourited ? 'text-primary' : 'text-muted' ]"
|
||
|
@click.prevent="likeComment(status, index, $event)">
|
||
|
{{ status.favourited ? 'Liked' : 'Like' }}
|
||
|
</a>
|
||
|
<!-- <span class="mx-1">·</span> -->
|
||
|
<!-- <a href="#" class="text-muted font-weight-bold" @click.prevent="replyToChild(status, index)">Reply</a> -->
|
||
|
<span v-if="profile" class="mx-1">·</span>
|
||
|
<a
|
||
|
class="font-weight-bold text-muted"
|
||
|
:href="status.url"
|
||
|
v-once>
|
||
|
{{ shortTimestamp(status.created_at) }}
|
||
|
</a>
|
||
|
<span v-if="profile && status.account.id === profile.id">
|
||
|
<span class="mx-1">·</span>
|
||
|
<a
|
||
|
class="font-weight-bold text-lighter"
|
||
|
href="#"
|
||
|
@click.prevent="deleteComment(index)">
|
||
|
Delete
|
||
|
</a>
|
||
|
</span>
|
||
|
</p>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script type="text/javascript">
|
||
|
import ReadMore from './ReadMore.vue';
|
||
|
|
||
|
export default {
|
||
|
props: {
|
||
|
groupId: {
|
||
|
type: String
|
||
|
},
|
||
|
|
||
|
profile: {
|
||
|
type: Object
|
||
|
},
|
||
|
|
||
|
status: {
|
||
|
type: Object,
|
||
|
},
|
||
|
|
||
|
commentBorderArrow: {
|
||
|
type: Boolean,
|
||
|
default: false
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
components: {
|
||
|
"read-more": ReadMore
|
||
|
},
|
||
|
|
||
|
data() {
|
||
|
return {
|
||
|
isLoaded: false,
|
||
|
hide: false,
|
||
|
feed: [],
|
||
|
canLoadMore: false,
|
||
|
isLoadingMore: false,
|
||
|
replyContent: null,
|
||
|
maxReplyId: null,
|
||
|
readMoreCursor: 200,
|
||
|
avatar: '/storage/avatars/default.png',
|
||
|
isUploading: false,
|
||
|
uploadProgress: 0,
|
||
|
lightboxStatus: null,
|
||
|
replyChildId: undefined,
|
||
|
childReplyContent: null,
|
||
|
postingChildComment: false
|
||
|
}
|
||
|
},
|
||
|
|
||
|
mounted() {
|
||
|
console.log(this.status);
|
||
|
// if(this.permalinkMode && this.permalinkStatus) {
|
||
|
// this.feed.push(this.permalinkStatus);
|
||
|
// this.isLoaded = true;
|
||
|
// this.canLoadMore = false;
|
||
|
// } else {
|
||
|
// this.fetchComments();
|
||
|
// }
|
||
|
|
||
|
// if(this.profile && this.profile.hasOwnProperty('avatar')) {
|
||
|
// this.avatar = this.profile.avatar;
|
||
|
// }
|
||
|
},
|
||
|
|
||
|
methods: {
|
||
|
fetchComments() {
|
||
|
axios.get('/api/v0/groups/comments', {
|
||
|
params: {
|
||
|
gid: this.groupId,
|
||
|
sid: this.status.id,
|
||
|
limit: 3
|
||
|
}
|
||
|
}).then(res => {
|
||
|
this.feed = res.data;
|
||
|
this.isLoaded = true;
|
||
|
this.maxReplyId = res.data[(res.data.length - 1)].id;
|
||
|
if(this.feed.length == 3) {
|
||
|
this.canLoadMore = true;
|
||
|
}
|
||
|
}).catch(err => {
|
||
|
this.isLoaded = true;
|
||
|
})
|
||
|
},
|
||
|
|
||
|
loadMoreComments() {
|
||
|
this.isLoadingMore = true;
|
||
|
|
||
|
axios.get('/api/v0/groups/comments', {
|
||
|
params: {
|
||
|
gid: this.groupId,
|
||
|
sid: this.status.id,
|
||
|
limit: 3,
|
||
|
max_id: this.maxReplyId
|
||
|
}
|
||
|
}).then(res => {
|
||
|
if(res.data[res.data.length - 1].id == this.maxReplyId) {
|
||
|
this.isLoadingMore = false;
|
||
|
this.canLoadMore = false;
|
||
|
return;
|
||
|
}
|
||
|
this.feed.push(...res.data);
|
||
|
this.isLoadingMore = false;
|
||
|
this.maxReplyId = res.data[res.data.length - 1].id;
|
||
|
if(res.data.length > 0) {
|
||
|
this.canLoadMore = true;
|
||
|
} else {
|
||
|
this.canLoadMore = false;
|
||
|
}
|
||
|
}).catch(err => {
|
||
|
this.isLoadingMore = false;
|
||
|
this.canLoadMore = false;
|
||
|
})
|
||
|
},
|
||
|
|
||
|
storeComment() {
|
||
|
axios.post('/api/v0/groups/comment', {
|
||
|
gid: this.groupId,
|
||
|
sid: this.status.id,
|
||
|
content: this.replyContent
|
||
|
})
|
||
|
.then(res => {
|
||
|
this.replyContent = null;
|
||
|
this.feed.unshift(res.data);
|
||
|
}).catch(err => {
|
||
|
if(err.response.status == 422) {
|
||
|
this.isUploading = false;
|
||
|
this.uploadProgress = 0;
|
||
|
swal('Oops!', err.response.data.error, 'error');
|
||
|
} else {
|
||
|
this.isUploading = false;
|
||
|
this.uploadProgress = 0;
|
||
|
swal('Oops!', 'An error occured while processing your request, please try again later', 'error');
|
||
|
}
|
||
|
})
|
||
|
},
|
||
|
|
||
|
shortTimestamp(ts) {
|
||
|
return window.App.util.format.timeAgo(ts);
|
||
|
},
|
||
|
|
||
|
readMore() {
|
||
|
this.readMoreCursor = this.readMoreCursor + 200;
|
||
|
},
|
||
|
|
||
|
likeComment(status, index, $event) {
|
||
|
$event.target.blur();
|
||
|
let l = status.favourited ? false : true;
|
||
|
this.feed[index].favourited = l;
|
||
|
status.favourited = l;
|
||
|
axios.post('/api/v0/groups/like', {
|
||
|
sid: status.id,
|
||
|
gid: this.groupId
|
||
|
});
|
||
|
},
|
||
|
|
||
|
deleteComment(index) {
|
||
|
if(window.confirm('Are you sure you want to delete this post?') == false) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
axios.post('/api/v0/groups/status/delete', {
|
||
|
gid: this.groupId,
|
||
|
id: this.feed[index].id
|
||
|
}).then(res => {
|
||
|
this.feed.splice(index, 1);
|
||
|
}).catch(err => {
|
||
|
console.log(err.response);
|
||
|
swal('Error', 'Something went wrong. Please try again later.', 'error');
|
||
|
});
|
||
|
},
|
||
|
|
||
|
uploadImage() {
|
||
|
this.$refs.fileInput.click();
|
||
|
},
|
||
|
|
||
|
handleImageUpload() {
|
||
|
if(!this.$refs.fileInput.files.length) {
|
||
|
return;
|
||
|
}
|
||
|
this.isUploading = true;
|
||
|
let self = this;
|
||
|
let data = new FormData();
|
||
|
data.append('gid', this.groupId);
|
||
|
data.append('sid', this.status.id);
|
||
|
data.append('photo', this.$refs.fileInput.files[0]);
|
||
|
|
||
|
axios.post('/api/v0/groups/comment/photo', data, {
|
||
|
onUploadProgress: function(progressEvent) {
|
||
|
self.uploadProgress = Math.floor(progressEvent.loaded / progressEvent.total * 100);
|
||
|
}
|
||
|
})
|
||
|
.then(res => {
|
||
|
this.isUploading = false;
|
||
|
this.uploadProgress = 0;
|
||
|
this.feed.unshift(res.data);
|
||
|
}).catch(err => {
|
||
|
if(err.response.status == 422) {
|
||
|
this.isUploading = false;
|
||
|
this.uploadProgress = 0;
|
||
|
swal('Oops!', err.response.data.error, 'error');
|
||
|
} else {
|
||
|
this.isUploading = false;
|
||
|
this.uploadProgress = 0;
|
||
|
swal('Oops!', 'An error occured while processing your request, please try again later', 'error');
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
lightbox(status) {
|
||
|
this.lightboxStatus = status.media_attachments[0];
|
||
|
this.$refs.lightboxModal.show();
|
||
|
},
|
||
|
|
||
|
hideLightbox() {
|
||
|
this.lightboxStatus = null;
|
||
|
this.$refs.lightboxModal.hide();
|
||
|
},
|
||
|
|
||
|
blurhashWidth(status) {
|
||
|
if(!status.media_attachments[0].meta) {
|
||
|
return 25;
|
||
|
}
|
||
|
let aspect = status.media_attachments[0].meta.original.aspect;
|
||
|
if(aspect == 1) {
|
||
|
return 25;
|
||
|
} else if(aspect > 1) {
|
||
|
return 30;
|
||
|
} else {
|
||
|
return 20;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
blurhashHeight(status) {
|
||
|
if(!status.media_attachments[0].meta) {
|
||
|
return 25;
|
||
|
}
|
||
|
let aspect = status.media_attachments[0].meta.original.aspect;
|
||
|
if(aspect == 1) {
|
||
|
return 25;
|
||
|
} else if(aspect > 1) {
|
||
|
return 20;
|
||
|
} else {
|
||
|
return 30;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getMediaSource(status) {
|
||
|
let media = status.media_attachments[0];
|
||
|
|
||
|
if(media.preview_url.endsWith('storage/no-preview.png')) {
|
||
|
return media.url;
|
||
|
}
|
||
|
|
||
|
return media.preview_url;
|
||
|
},
|
||
|
|
||
|
replyToChild(status, index) {
|
||
|
if(this.replyChildId == status.id) {
|
||
|
this.replyChildId = null;
|
||
|
return;
|
||
|
} else {
|
||
|
this.childReplyContent = null;
|
||
|
}
|
||
|
|
||
|
this.replyChildId = status.id;
|
||
|
|
||
|
if(!status.hasOwnProperty('replies_loaded') || !status.replies_loaded) {
|
||
|
this.fetchChildReplies(status, index);
|
||
|
} else {
|
||
|
|
||
|
}
|
||
|
},
|
||
|
|
||
|
fetchChildReplies(status, index) {
|
||
|
axios.get('/api/v0/groups/comments', {
|
||
|
params: {
|
||
|
gid: this.groupId,
|
||
|
sid: status.id,
|
||
|
cid: 1,
|
||
|
limit: 3
|
||
|
}
|
||
|
}).then(res => {
|
||
|
if(this.feed[index].hasOwnProperty('children')) {
|
||
|
this.feed[index].children.feed.push(...res.data);
|
||
|
this.feed[index].children.can_load_more = res.data.length == 3;
|
||
|
} else {
|
||
|
this.feed[index].children = {
|
||
|
feed: res.data,
|
||
|
can_load_more: res.data.length == 3
|
||
|
}
|
||
|
}
|
||
|
this.feed[index].replies_loaded = true;
|
||
|
}).catch(err => {
|
||
|
})
|
||
|
},
|
||
|
|
||
|
storeChildComment() {
|
||
|
this.postingChildComment = true;
|
||
|
|
||
|
axios.post('/api/v0/groups/comment', {
|
||
|
gid: this.groupId,
|
||
|
sid: this.status.id,
|
||
|
cid: this.replyChildId,
|
||
|
content: this.childReplyContent
|
||
|
})
|
||
|
.then(res => {
|
||
|
this.childReplyContent = null;
|
||
|
this.postingChildComment = false;
|
||
|
// this.feed.unshift(res.data);
|
||
|
}).catch(err => {
|
||
|
if(err.response.status == 422) {
|
||
|
// this.isUploading = false;
|
||
|
// this.uploadProgress = 0;
|
||
|
swal('Oops!', err.response.data.error, 'error');
|
||
|
} else {
|
||
|
// this.isUploading = false;
|
||
|
// this.uploadProgress = 0;
|
||
|
swal('Oops!', 'An error occured while processing your request, please try again later', 'error');
|
||
|
}
|
||
|
});
|
||
|
|
||
|
console.log(this.replyChildId);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<style lang="scss">
|
||
|
.comment-post-component {
|
||
|
|
||
|
}
|
||
|
</style>
|