2020-02-16 19:30:00 +01:00
|
|
|
import Vue from 'vue'
|
2020-08-05 05:44:34 +02:00
|
|
|
import { mapActions } from 'vuex'
|
2020-02-16 19:30:00 +01:00
|
|
|
import FtCard from '../ft-card/ft-card.vue'
|
|
|
|
import FtLoader from '../../components/ft-loader/ft-loader.vue'
|
2020-10-05 00:15:06 +02:00
|
|
|
import FtSelect from '../../components/ft-select/ft-select.vue'
|
2020-09-19 18:19:58 +02:00
|
|
|
import FtTimestampCatcher from '../../components/ft-timestamp-catcher/ft-timestamp-catcher.vue'
|
2020-10-07 17:48:53 +02:00
|
|
|
import autolinker from 'autolinker'
|
2021-07-24 00:17:45 +02:00
|
|
|
import ytcm from '@freetube/yt-comment-scraper'
|
2022-10-20 08:03:31 +02:00
|
|
|
import { copyToClipboard, showToast, toLocalePublicationString } from '../../helpers/utils'
|
2020-10-05 00:15:06 +02:00
|
|
|
|
2020-02-16 19:30:00 +01:00
|
|
|
export default Vue.extend({
|
|
|
|
name: 'WatchVideoComments',
|
|
|
|
components: {
|
|
|
|
'ft-card': FtCard,
|
2020-09-19 18:19:58 +02:00
|
|
|
'ft-loader': FtLoader,
|
2020-10-05 00:15:06 +02:00
|
|
|
'ft-select': FtSelect,
|
2020-09-19 18:19:58 +02:00
|
|
|
'ft-timestamp-catcher': FtTimestampCatcher
|
2020-02-16 19:30:00 +01:00
|
|
|
},
|
|
|
|
props: {
|
|
|
|
id: {
|
|
|
|
type: String,
|
|
|
|
required: true
|
2020-10-19 16:01:24 +02:00
|
|
|
},
|
2021-11-06 03:11:21 +01:00
|
|
|
channelName: {
|
|
|
|
type: String,
|
|
|
|
required: true
|
|
|
|
},
|
2020-10-19 16:01:24 +02:00
|
|
|
channelThumbnail: {
|
|
|
|
type: String,
|
|
|
|
required: true
|
2020-02-16 19:30:00 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
data: function () {
|
|
|
|
return {
|
|
|
|
isLoading: false,
|
2020-02-18 21:59:01 +01:00
|
|
|
showComments: false,
|
2020-09-26 17:43:01 +02:00
|
|
|
commentScraper: null,
|
2020-02-16 19:30:00 +01:00
|
|
|
nextPageToken: null,
|
2020-10-05 19:52:26 +02:00
|
|
|
commentData: [],
|
2020-10-15 11:51:11 +02:00
|
|
|
sortNewest: false,
|
|
|
|
commentProcess: null,
|
|
|
|
sortingChanged: false
|
2020-02-16 19:30:00 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
backendPreference: function () {
|
|
|
|
return this.$store.getters.getBackendPreference
|
|
|
|
},
|
|
|
|
|
|
|
|
backendFallback: function () {
|
|
|
|
return this.$store.getters.getBackendFallback
|
|
|
|
},
|
|
|
|
|
2021-07-03 03:55:56 +02:00
|
|
|
currentInvidiousInstance: function () {
|
|
|
|
return this.$store.getters.getCurrentInvidiousInstance
|
2020-10-05 00:15:06 +02:00
|
|
|
},
|
2020-10-06 04:27:32 +02:00
|
|
|
hideCommentLikes: function () {
|
|
|
|
return this.$store.getters.getHideCommentLikes
|
|
|
|
},
|
2020-10-05 00:15:06 +02:00
|
|
|
|
|
|
|
sortNames: function () {
|
|
|
|
return [
|
|
|
|
this.$t('Comments.Top comments'),
|
|
|
|
this.$t('Comments.Newest first')
|
|
|
|
]
|
|
|
|
},
|
|
|
|
|
|
|
|
sortValues: function () {
|
|
|
|
return [
|
|
|
|
'top',
|
|
|
|
'newest'
|
|
|
|
]
|
2020-10-05 19:52:26 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
currentSortValue: function () {
|
|
|
|
return (this.sortNewest) ? 'newest' : 'top'
|
2020-02-16 19:30:00 +01:00
|
|
|
}
|
|
|
|
},
|
2020-10-15 11:51:11 +02:00
|
|
|
|
|
|
|
beforeDestroy: function () {
|
|
|
|
if (this.commentProcess !== null) {
|
|
|
|
this.commentProcess.send('end')
|
|
|
|
}
|
|
|
|
},
|
2020-02-16 19:30:00 +01:00
|
|
|
methods: {
|
2020-10-05 00:15:06 +02:00
|
|
|
onTimestamp: function (timestamp) {
|
2020-10-04 20:30:54 +02:00
|
|
|
this.$emit('timestamp-event', timestamp)
|
2020-09-19 18:19:58 +02:00
|
|
|
},
|
|
|
|
|
2020-10-05 00:15:06 +02:00
|
|
|
handleSortChange: function (sortType) {
|
2020-10-05 19:52:26 +02:00
|
|
|
this.sortNewest = !this.sortNewest
|
2020-10-08 16:06:06 +02:00
|
|
|
switch (this.backendPreference) {
|
|
|
|
case 'local':
|
2021-01-20 16:54:44 +01:00
|
|
|
this.isLoading = true
|
|
|
|
this.commentData = []
|
|
|
|
this.nextPageToken = undefined
|
2021-02-15 15:59:35 +01:00
|
|
|
this.getCommentDataLocal({
|
|
|
|
videoId: this.id,
|
|
|
|
setCookie: false,
|
|
|
|
sortByNewest: this.sortNewest,
|
|
|
|
continuation: this.nextPageToken ? this.nextPageToken : undefined
|
|
|
|
})
|
2020-10-08 16:06:06 +02:00
|
|
|
break
|
|
|
|
case 'invidious':
|
|
|
|
this.isLoading = true
|
|
|
|
this.commentData = []
|
2022-10-15 06:01:58 +02:00
|
|
|
this.getCommentDataInvidious()
|
2020-10-08 16:06:06 +02:00
|
|
|
break
|
|
|
|
}
|
2020-10-05 00:15:06 +02:00
|
|
|
},
|
|
|
|
|
2020-10-15 11:51:11 +02:00
|
|
|
getCommentData: function () {
|
2020-02-16 19:30:00 +01:00
|
|
|
this.isLoading = true
|
|
|
|
switch (this.backendPreference) {
|
|
|
|
case 'local':
|
2021-02-15 15:59:35 +01:00
|
|
|
this.getCommentDataLocal({
|
|
|
|
videoId: this.id,
|
|
|
|
setCookie: false,
|
|
|
|
sortByNewest: this.sortNewest,
|
|
|
|
continuation: this.nextPageToken ? this.nextPageToken : undefined
|
|
|
|
})
|
2020-02-16 19:30:00 +01:00
|
|
|
break
|
|
|
|
case 'invidious':
|
2022-10-15 06:01:58 +02:00
|
|
|
this.getCommentDataInvidious()
|
2020-02-16 19:30:00 +01:00
|
|
|
break
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-09-23 00:02:20 +02:00
|
|
|
getMoreComments: function () {
|
|
|
|
if (this.commentData.length === 0 || this.nextPageToken === null || typeof this.nextPageToken === 'undefined') {
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(this.$t('Comments.There are no more comments for this video'))
|
2020-09-23 00:02:20 +02:00
|
|
|
} else {
|
|
|
|
this.getCommentData()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2021-02-15 15:59:35 +01:00
|
|
|
toggleCommentReplies: function (index) {
|
|
|
|
if (this.commentData[index].showReplies || this.commentData[index].replies.length > 0) {
|
|
|
|
this.commentData[index].showReplies = !this.commentData[index].showReplies
|
|
|
|
} else {
|
|
|
|
this.getCommentReplies(index)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2020-02-16 19:30:00 +01:00
|
|
|
getCommentReplies: function (index) {
|
|
|
|
switch (this.commentData[index].dataType) {
|
|
|
|
case 'local':
|
2021-02-15 15:59:35 +01:00
|
|
|
this.getCommentRepliesLocal({
|
|
|
|
videoId: this.id,
|
|
|
|
setCookie: false,
|
|
|
|
sortByNewest: this.sortNewest,
|
2021-06-13 22:08:12 +02:00
|
|
|
replyToken: this.commentData[index].replyToken,
|
2021-02-15 15:59:35 +01:00
|
|
|
index: index
|
|
|
|
})
|
2020-02-16 19:30:00 +01:00
|
|
|
break
|
|
|
|
case 'invidious':
|
2021-02-15 15:59:35 +01:00
|
|
|
this.getCommentRepliesInvidious(index)
|
2020-02-16 19:30:00 +01:00
|
|
|
break
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2021-02-15 15:59:35 +01:00
|
|
|
getCommentDataLocal: function (payload) {
|
2021-01-20 16:54:44 +01:00
|
|
|
ytcm.getComments(payload).then((response) => {
|
2021-02-15 15:59:35 +01:00
|
|
|
this.parseLocalCommentData(response, null)
|
|
|
|
}).catch((err) => {
|
2022-09-23 03:04:10 +02:00
|
|
|
console.error(err)
|
2021-02-15 15:59:35 +01:00
|
|
|
const errorMessage = this.$t('Local API Error (Click to copy)')
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(`${errorMessage}: ${err}`, 10000, () => {
|
2022-10-18 10:15:28 +02:00
|
|
|
copyToClipboard(err)
|
2021-01-20 16:54:44 +01:00
|
|
|
})
|
2021-02-15 15:59:35 +01:00
|
|
|
if (this.backendFallback && this.backendPreference === 'local') {
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(this.$t('Falling back to Invidious API'))
|
2022-10-15 06:01:58 +02:00
|
|
|
this.getCommentDataInvidious()
|
2021-02-15 15:59:35 +01:00
|
|
|
} else {
|
|
|
|
this.isLoading = false
|
2021-01-20 16:54:44 +01:00
|
|
|
}
|
2021-02-15 15:59:35 +01:00
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getCommentRepliesLocal: function (payload) {
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(this.$t('Comments.Getting comment replies, please wait'))
|
2021-06-13 22:08:12 +02:00
|
|
|
|
|
|
|
ytcm.getCommentReplies(payload).then((response) => {
|
2021-02-15 15:59:35 +01:00
|
|
|
this.parseLocalCommentData(response, payload.index)
|
2021-01-20 16:54:44 +01:00
|
|
|
}).catch((err) => {
|
2022-09-23 03:04:10 +02:00
|
|
|
console.error(err)
|
2021-01-20 16:54:44 +01:00
|
|
|
const errorMessage = this.$t('Local API Error (Click to copy)')
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(`${errorMessage}: ${err}`, 10000, () => {
|
2022-10-18 10:15:28 +02:00
|
|
|
copyToClipboard(err)
|
2021-01-20 16:54:44 +01:00
|
|
|
})
|
|
|
|
if (this.backendFallback && this.backendPreference === 'local') {
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(this.$t('Falling back to Invidious API'))
|
2022-10-15 06:01:58 +02:00
|
|
|
this.getCommentDataInvidious()
|
2021-01-20 16:54:44 +01:00
|
|
|
} else {
|
|
|
|
this.isLoading = false
|
|
|
|
}
|
|
|
|
})
|
2020-02-16 19:30:00 +01:00
|
|
|
},
|
|
|
|
|
2021-02-15 15:59:35 +01:00
|
|
|
parseLocalCommentData: function (response, index = null) {
|
|
|
|
const commentData = response.comments.map((comment) => {
|
2021-03-18 17:47:28 +01:00
|
|
|
comment.authorLink = comment.authorId
|
2021-02-15 15:59:35 +01:00
|
|
|
comment.showReplies = false
|
|
|
|
comment.authorThumb = comment.authorThumb[0].url
|
|
|
|
comment.replies = []
|
|
|
|
comment.dataType = 'local'
|
2022-10-20 08:03:31 +02:00
|
|
|
comment.time = toLocalePublicationString({
|
|
|
|
publishText: (comment.time + ' ago')
|
2021-02-15 15:59:35 +01:00
|
|
|
})
|
2022-10-20 08:03:31 +02:00
|
|
|
|
2021-02-15 15:59:35 +01:00
|
|
|
if (this.hideCommentLikes) {
|
|
|
|
comment.likes = null
|
|
|
|
}
|
2022-08-16 14:11:29 +02:00
|
|
|
// strip html tags but keep <br>, <b>, </b> <s>, </s>, <i>, </i>
|
|
|
|
comment.text = autolinker.link(comment.text.replace(/(<(?!br|\/?(?:b|s|i)>)([^>]+)>)/ig, ''))
|
2022-05-14 19:33:00 +02:00
|
|
|
if (comment.customEmojis.length > 0) {
|
|
|
|
comment.customEmojis.forEach(emoji => {
|
|
|
|
comment.text = comment.text.replace(emoji.text, `<img width="14" height="14" class="commentCustomEmoji" alt="${emoji.text.substring(2, emoji.text.length - 1)}" src="${emoji.emojiThumbnails[0].url}">`)
|
|
|
|
})
|
|
|
|
}
|
2021-02-15 15:59:35 +01:00
|
|
|
|
|
|
|
return comment
|
|
|
|
})
|
|
|
|
|
|
|
|
if (index !== null) {
|
2022-02-06 20:38:17 +01:00
|
|
|
if (this.commentData[index].replies.length === 0 || this.commentData[index].replies[this.commentData[index].replies.length - 1].commentId !== commentData[commentData.length - 1].commentId) {
|
|
|
|
this.commentData[index].replies = this.commentData[index].replies.concat(commentData)
|
|
|
|
this.commentData[index].replyToken = response.continuation
|
|
|
|
this.commentData[index].showReplies = true
|
|
|
|
}
|
2021-02-15 15:59:35 +01:00
|
|
|
} else {
|
|
|
|
if (this.sortingChanged) {
|
|
|
|
this.commentData = []
|
|
|
|
this.sortingChanged = false
|
2020-02-16 19:30:00 +01:00
|
|
|
}
|
2021-02-15 15:59:35 +01:00
|
|
|
this.commentData = this.commentData.concat(commentData)
|
|
|
|
this.isLoading = false
|
|
|
|
this.showComments = true
|
|
|
|
this.nextPageToken = response.continuation
|
2020-02-16 19:30:00 +01:00
|
|
|
}
|
2021-02-15 15:59:35 +01:00
|
|
|
},
|
2020-02-16 19:30:00 +01:00
|
|
|
|
2022-10-15 06:01:58 +02:00
|
|
|
getCommentDataInvidious: function () {
|
|
|
|
const payload = {
|
|
|
|
resource: 'comments',
|
|
|
|
id: this.id,
|
|
|
|
params: {
|
|
|
|
continuation: this.nextPageToken ?? '',
|
|
|
|
sort_by: this.sortNewest ? 'new' : 'top'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-21 03:59:59 +02:00
|
|
|
this.invidiousAPICall(payload).then((response) => {
|
2020-02-16 19:30:00 +01:00
|
|
|
const commentData = response.comments.map((comment) => {
|
|
|
|
comment.showReplies = false
|
2021-03-18 17:47:28 +01:00
|
|
|
comment.authorLink = comment.authorId
|
2021-07-03 03:55:56 +02:00
|
|
|
comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`)
|
2020-10-06 04:27:32 +02:00
|
|
|
if (this.hideCommentLikes) {
|
|
|
|
comment.likes = null
|
|
|
|
} else {
|
|
|
|
comment.likes = comment.likeCount
|
|
|
|
}
|
2021-09-20 11:25:50 +02:00
|
|
|
comment.text = autolinker.link(comment.content.replace(/(<(?!br>)([^>]+)>)/ig, ''))
|
2020-02-16 19:30:00 +01:00
|
|
|
comment.dataType = 'invidious'
|
2021-11-06 03:11:21 +01:00
|
|
|
comment.isOwner = comment.authorIsChannelOwner
|
2020-02-16 19:30:00 +01:00
|
|
|
|
|
|
|
if (typeof (comment.replies) !== 'undefined' && typeof (comment.replies.replyCount) !== 'undefined') {
|
|
|
|
comment.numReplies = comment.replies.replyCount
|
|
|
|
comment.replyContinuation = comment.replies.continuation
|
|
|
|
} else {
|
|
|
|
comment.numReplies = 0
|
|
|
|
comment.replyContinuation = ''
|
|
|
|
}
|
|
|
|
|
|
|
|
comment.replies = []
|
2022-10-24 17:10:06 +02:00
|
|
|
comment.time = toLocalePublicationString({
|
|
|
|
publishText: comment.publishedText
|
|
|
|
})
|
2020-09-26 17:43:01 +02:00
|
|
|
|
2020-02-16 19:30:00 +01:00
|
|
|
return comment
|
|
|
|
})
|
|
|
|
|
|
|
|
this.commentData = this.commentData.concat(commentData)
|
|
|
|
this.nextPageToken = response.continuation
|
|
|
|
this.isLoading = false
|
2020-02-18 21:59:01 +01:00
|
|
|
this.showComments = true
|
2020-02-16 19:30:00 +01:00
|
|
|
}).catch((xhr) => {
|
2022-09-23 03:04:10 +02:00
|
|
|
console.error(xhr)
|
2020-08-08 04:16:06 +02:00
|
|
|
const errorMessage = this.$t('Invidious API Error (Click to copy)')
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => {
|
2022-10-18 10:15:28 +02:00
|
|
|
copyToClipboard(xhr.responseText)
|
2020-08-08 04:16:06 +02:00
|
|
|
})
|
2020-02-16 19:30:00 +01:00
|
|
|
if (this.backendFallback && this.backendPreference === 'invidious') {
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(this.$t('Falling back to local API'))
|
2020-02-16 19:30:00 +01:00
|
|
|
this.getCommentDataLocal()
|
|
|
|
} else {
|
|
|
|
this.isLoading = false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
getCommentRepliesInvidious: function (index) {
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(this.$t('Comments.Getting comment replies, please wait'))
|
2020-02-16 19:30:00 +01:00
|
|
|
const payload = {
|
|
|
|
resource: 'comments',
|
|
|
|
id: this.id,
|
|
|
|
params: {
|
|
|
|
continuation: this.commentData[index].replyContinuation
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-22 01:56:32 +02:00
|
|
|
this.invidiousAPICall(payload).then((response) => {
|
2020-02-16 19:30:00 +01:00
|
|
|
const commentData = response.comments.map((comment) => {
|
|
|
|
comment.showReplies = false
|
2021-03-18 17:47:28 +01:00
|
|
|
comment.authorLink = comment.authorId
|
2021-07-03 03:55:56 +02:00
|
|
|
comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`)
|
2020-10-06 04:27:32 +02:00
|
|
|
if (this.hideCommentLikes) {
|
|
|
|
comment.likes = null
|
|
|
|
} else {
|
|
|
|
comment.likes = comment.likeCount
|
|
|
|
}
|
2021-09-20 11:25:50 +02:00
|
|
|
comment.text = autolinker.link(comment.content.replace(/(<(?!br>)([^>]+)>)/ig, ''))
|
2020-09-26 17:43:01 +02:00
|
|
|
comment.time = comment.publishedText
|
2020-02-16 19:30:00 +01:00
|
|
|
comment.dataType = 'invidious'
|
|
|
|
comment.numReplies = 0
|
|
|
|
comment.replyContinuation = ''
|
|
|
|
comment.replies = []
|
|
|
|
|
|
|
|
return comment
|
|
|
|
})
|
|
|
|
|
|
|
|
this.commentData[index].replies = commentData
|
|
|
|
this.commentData[index].showReplies = true
|
|
|
|
this.isLoading = false
|
|
|
|
}).catch((xhr) => {
|
2022-09-23 03:04:10 +02:00
|
|
|
console.error(xhr)
|
2020-08-08 04:16:06 +02:00
|
|
|
const errorMessage = this.$t('Invidious API Error (Click to copy)')
|
2022-10-14 07:59:49 +02:00
|
|
|
showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => {
|
2022-10-18 10:15:28 +02:00
|
|
|
copyToClipboard(xhr.responseText)
|
2020-08-08 04:16:06 +02:00
|
|
|
})
|
2020-02-16 19:30:00 +01:00
|
|
|
this.isLoading = false
|
|
|
|
})
|
2020-08-05 05:44:34 +02:00
|
|
|
},
|
|
|
|
|
2021-03-18 17:47:28 +01:00
|
|
|
goToChannel: function (channelId) {
|
|
|
|
this.$router.push({ path: `/channel/${channelId}` })
|
|
|
|
},
|
|
|
|
|
2020-08-05 05:44:34 +02:00
|
|
|
...mapActions([
|
2022-10-18 10:15:28 +02:00
|
|
|
'invidiousAPICall'
|
2020-08-05 05:44:34 +02:00
|
|
|
])
|
2020-02-16 19:30:00 +01:00
|
|
|
}
|
|
|
|
})
|