FreeTube/src/renderer/components/watch-video-comments/watch-video-comments.js

245 lines
7.7 KiB
JavaScript
Raw Normal View History

import { defineComponent } from 'vue'
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'
import FtTimestampCatcher from '../../components/ft-timestamp-catcher/ft-timestamp-catcher.vue'
import { copyToClipboard, showToast } from '../../helpers/utils'
import { invidiousGetCommentReplies, invidiousGetComments } from '../../helpers/api/invidious'
import { getLocalComments, parseLocalComment } from '../../helpers/api/local'
2020-10-05 00:15:06 +02:00
export default defineComponent({
2020-02-16 19:30:00 +01:00
name: 'WatchVideoComments',
components: {
'ft-card': FtCard,
'ft-loader': FtLoader,
2020-10-05 00:15:06 +02:00
'ft-select': FtSelect,
'ft-timestamp-catcher': FtTimestampCatcher
2020-02-16 19:30:00 +01:00
},
props: {
id: {
type: String,
required: true
},
channelName: {
type: String,
required: true
},
channelThumbnail: {
type: String,
required: true
2020-02-16 19:30:00 +01:00
}
},
data: function () {
return {
isLoading: false,
showComments: false,
2020-02-16 19:30:00 +01:00
nextPageToken: null,
commentData: [],
sortNewest: false
2020-02-16 19:30:00 +01:00
}
},
computed: {
backendPreference: function () {
return this.$store.getters.getBackendPreference
},
backendFallback: function () {
return this.$store.getters.getBackendFallback
},
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'
]
},
currentSortValue: function () {
return (this.sortNewest) ? 'newest' : 'top'
2020-02-16 19:30:00 +01:00
}
},
2020-02-16 19:30:00 +01:00
methods: {
2020-10-05 00:15:06 +02:00
onTimestamp: function (timestamp) {
this.$emit('timestamp-event', timestamp)
},
handleSortChange: function () {
this.sortNewest = !this.sortNewest
this.commentData = []
// nextPageToken is reset to ensure first page is get
this.nextPageToken = null
this.getCommentData()
2020-10-05 00:15:06 +02:00
},
getCommentData: function () {
2020-02-16 19:30:00 +01:00
this.isLoading = true
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
this.getCommentDataInvidious()
} else {
this.getCommentDataLocal()
2020-02-16 19:30:00 +01: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'))
} else {
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
this.getCommentDataInvidious()
} else {
this.getCommentDataLocal(true)
}
}
},
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) {
if (process.env.IS_ELECTRON) {
switch (this.commentData[index].dataType) {
case 'local':
this.getCommentRepliesLocal(index)
break
case 'invidious':
this.getCommentRepliesInvidious(index)
break
}
} else {
this.getCommentRepliesInvidious(index)
2020-02-16 19:30:00 +01:00
}
},
getCommentDataLocal: async function (more) {
try {
/** @type {import('youtubei.js/dist/src/parser/youtube/Comments').default} */
let comments
if (more) {
comments = await this.nextPageToken.getContinuation()
} else {
comments = await getLocalComments(this.id, this.sortNewest)
}
const parsedComments = comments.contents
.map(commentThread => parseLocalComment(commentThread.comment, commentThread))
if (more) {
this.commentData = this.commentData.concat(parsedComments)
} else {
this.commentData = parsedComments
}
this.nextPageToken = comments.has_continuation ? comments : null
this.isLoading = false
this.showComments = true
} catch (err) {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
2022-10-14 07:59:49 +02:00
showToast(`${errorMessage}: ${err}`, 10000, () => {
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'))
this.getCommentDataInvidious()
} else {
this.isLoading = false
2021-01-20 16:54:44 +01:00
}
}
},
getCommentRepliesLocal: async function (index) {
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
try {
const comment = this.commentData[index]
/** @type {import('youtubei.js/dist/src/parser/classes/comments/CommentThread').default} */
const commentThread = comment.replyToken
if (comment.replies.length > 0) {
await commentThread.getContinuation()
comment.replies = comment.replies.concat(commentThread.replies.map(reply => parseLocalComment(reply)))
} else {
await commentThread.getReplies()
comment.replies = commentThread.replies.map(reply => parseLocalComment(reply))
}
comment.replyToken = commentThread.has_continuation ? commentThread : null
comment.showReplies = true
} catch (err) {
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, () => {
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'))
this.getCommentDataInvidious()
2021-01-20 16:54:44 +01:00
} else {
this.isLoading = false
}
2020-02-16 19:30:00 +01:00
}
},
2020-02-16 19:30:00 +01:00
getCommentDataInvidious: function () {
invidiousGetComments({
id: this.id,
nextPageToken: this.nextPageToken,
sortNewest: this.sortNewest
}).then(({ response, commentData }) => {
2020-02-16 19:30:00 +01:00
this.commentData = this.commentData.concat(commentData)
this.nextPageToken = response.continuation
this.isLoading = false
this.showComments = true
2020-02-16 19:30:00 +01:00
}).catch((xhr) => {
console.error(xhr)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
2022-10-14 07:59:49 +02:00
showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => {
copyToClipboard(xhr.responseText)
})
2023-01-05 04:53:39 +01:00
if (process.env.IS_ELECTRON && this.backendFallback && this.backendPreference === 'invidious') {
2022-10-14 07:59:49 +02:00
showToast(this.$t('Falling back to local API'))
this.getCommentDataLocal()
2020-02-16 19:30:00 +01:00
} else {
this.isLoading = false
}
})
},
getCommentRepliesInvidious: function (index) {
2022-10-14 07:59:49 +02:00
showToast(this.$t('Comments.Getting comment replies, please wait'))
const replyToken = this.commentData[index].replyToken
invidiousGetCommentReplies({ id: this.id, replyToken: replyToken })
.then(({ commentData, continuation }) => {
this.commentData[index].replies = commentData
this.commentData[index].showReplies = true
this.commentData[index].replyToken = continuation
this.isLoading = false
}).catch((xhr) => {
console.error(xhr)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => {
copyToClipboard(xhr.responseText)
})
this.isLoading = false
})
}
2020-02-16 19:30:00 +01:00
}
})