Skip to content

Commit

Permalink
Add ability to see comment replies of community posts through invidio…
Browse files Browse the repository at this point in the history
…us (#5589)

* Add ability to see comment replies  of community posts through invidious

* Add better styling to comment count link

* Apply suggestions from code review

Co-authored-by: absidue <48293849+absidue@users.noreply.github.com>

* accessibility improvements

* fix showing community comments when local api with fallback

* use authorId and support parsing the youtube link instead of just the invidious one

* remove unneeded isLoading = true

* add no comments message

* add support for auto load comments

* Hide comment count on individual post page

* Apply suggestions from code review

Co-authored-by: absidue <48293849+absidue@users.noreply.github.com>

* Don't nest FtCard in FtCard

Co-Authored-By: absidue <48293849+absidue@users.noreply.github.com>

* watch route for changes

---------

Co-authored-by: absidue <48293849+absidue@users.noreply.github.com>
  • Loading branch information
ChunkyProgrammer and absidue authored Sep 12, 2024
1 parent 1c3a2fe commit 21ff6fe
Show file tree
Hide file tree
Showing 15 changed files with 391 additions and 35 deletions.
11 changes: 11 additions & 0 deletions src/renderer/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,17 @@ export default defineComponent({
break
}

case 'post': {
const { postId, query } = result

openInternalPath({
path: `/post/${postId}`,
query,
doCreateNewWindow
})
break
}

case 'channel': {
const { channelId, subPath, url } = result

Expand Down
26 changes: 22 additions & 4 deletions src/renderer/components/ft-community-post/ft-community-post.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import autolinker from 'autolinker'

import { A11y, Navigation, Pagination } from 'swiper/modules'

import { createWebURL, deepCopy, toLocalePublicationString } from '../../helpers/utils'
import { createWebURL, deepCopy, formatNumber, toLocalePublicationString } from '../../helpers/utils'
import { youtubeImageUrlToInvidious } from '../../helpers/api/invidious'

export default defineComponent({
Expand All @@ -29,17 +29,23 @@ export default defineComponent({
hideForbiddenTitles: {
type: Boolean,
default: true
}
},
singlePost: {
type: Boolean,
default: false
},
},
data: function () {
return {
postText: '',
postId: '',
authorThumbnails: null,
publishedText: '',
voteCount: '',
voteCount: 0,
formattedVoteCount: '',
postContent: '',
commentCount: '',
commentCount: null,
formattedCommentCount: '',
author: '',
authorId: '',
}
Expand All @@ -56,6 +62,16 @@ export default defineComponent({

hideVideo() {
return this.forbiddenTitles.some((text) => this.data.postContent.content.title?.toLowerCase().includes(text.toLowerCase()))
},

backendPreference: function () {
return this.$store.getters.getBackendPreference
},
backendFallback: function () {
return this.$store.getters.getBackendFallback
},
isInvidiousAllowed: function() {
return this.backendPreference === 'invidious' || this.backendFallback
}
},
created: function () {
Expand Down Expand Up @@ -127,7 +143,9 @@ export default defineComponent({
isRSS: this.data.isRSS
})
this.voteCount = this.data.voteCount
this.formattedVoteCount = formatNumber(this.voteCount)
this.commentCount = this.data.commentCount
this.formattedCommentCount = formatNumber(this.commentCount)
this.type = (this.data.postContent !== null && this.data.postContent !== undefined) ? this.data.postContent.type : 'text'
this.author = this.data.author
this.authorId = this.data.authorId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
white-space: pre-wrap;
}

.commentsLink {
color: var(--primary-text-color);
text-decoration: none;
font-weight: bold;
}

.bottomSection {
color: var(--tertiary-text-color);
display: block;
Expand Down
41 changes: 36 additions & 5 deletions src/renderer/components/ft-community-post/ft-community-post.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,42 @@
<div
class="bottomSection"
>
<span class="likeCount"><font-awesome-icon
class="thumbs-up-icon"
:icon="['fas', 'thumbs-up']"
/> {{ voteCount }}</span>
<span class="commentCount">
<span
class="likeCount"
:title="$tc('Global.Counts.Like Count', voteCount, {count: formattedVoteCount})"
:aria-label="$tc('Global.Counts.Like Count', voteCount, {count: formattedVoteCount})"
>
<font-awesome-icon
class="thumbs-up-icon"
:icon="['fas', 'thumbs-up']"
aria-hidden="true"
/> {{ formattedVoteCount }}</span>
<router-link
v-if="isInvidiousAllowed && !singlePost"
:to="{
path: `/post/${postId}`,
query: authorId ? { authorId } : undefined
}"
class="commentsLink"
:aria-label="$t('Channel.Community.View Full Post')"
>
<span
class="commentCount"
:title="$tc('Global.Counts.Comment Count', commentCount, {count: formattedCommentCount})"
:aria-label="$tc('Global.Counts.Comment Count', commentCount, {count: formattedCommentCount})"
>
<font-awesome-icon
class="comment-count-icon"
:icon="['fas', 'comment']"
aria-hidden="true"
/> {{ formattedCommentCount }}</span>
</router-link>
<span
v-else-if="commentCount != null"
class="commentCount"
:title="$tc('Global.Counts.Comment Count', commentCount, {count: formattedCommentCount})"
:aria-label="$tc('Global.Counts.Comment Count', commentCount, {count: formattedCommentCount})"
>
<font-awesome-icon
class="comment-count-icon"
:icon="['fas', 'comment']"
Expand Down
1 change: 1 addition & 0 deletions src/renderer/components/ft-input/ft-input.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ export default defineComponent({
case 'search':
case 'channel':
case 'hashtag':
case 'post':
isYoutubeLink = true
break

Expand Down
12 changes: 12 additions & 0 deletions src/renderer/components/top-nav/top-nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,18 @@ export default defineComponent({
break
}

case 'post': {
const { postId, query } = result

openInternalPath({
path: `/post/${postId}`,
query,
doCreateNewWindow,
searchQueryText: queryText,
})
break
}

case 'channel': {
const { channelId, subPath, url } = result

Expand Down
110 changes: 95 additions & 15 deletions src/renderer/components/watch-video-comments/watch-video-comments.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import FtLoader from '../../components/ft-loader/ft-loader.vue'
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 { getInvidiousCommunityPostCommentReplies, getInvidiousCommunityPostComments, invidiousGetCommentReplies, invidiousGetComments } from '../../helpers/api/invidious'
import { getLocalComments, parseLocalComment } from '../../helpers/api/local'

export default defineComponent({
Expand Down Expand Up @@ -36,6 +36,18 @@ export default defineComponent({
type: String,
default: null,
},
isPostComments: {
type: Boolean,
default: false,
},
postAuthorId: {
type: String,
default: null
},
showSortBy: {
type: Boolean,
default: true,
}
},
emits: ['timestamp-event'],
setup: function () {
Expand Down Expand Up @@ -98,7 +110,7 @@ export default defineComponent({
if (!this.generalAutoLoadMorePaginatedItemsEnabled) {
return false
}
if (!this.videoPlayerReady) { return false }
if (!this.videoPlayerReady && !this.isPostComments) { return false }

return {
callback: (isVisible, _entry) => {
Expand Down Expand Up @@ -162,8 +174,12 @@ export default defineComponent({

getCommentData: function () {
this.isLoading = true
if (!process.env.SUPPORTS_LOCAL_API || this.backendPreference === 'invidious') {
this.getCommentDataInvidious()
if (!process.env.SUPPORTS_LOCAL_API || this.backendPreference === 'invidious' || this.isPostComments) {
if (!this.isPostComments) {
this.getCommentDataInvidious()
} else {
this.getPostCommentsInvidious()
}
} else {
this.getCommentDataLocal()
}
Expand All @@ -173,8 +189,12 @@ export default defineComponent({
if (this.commentData.length === 0 || this.nextPageToken === null || typeof this.nextPageToken === 'undefined') {
showToast(this.$t('Comments.There are no more comments for this video'))
} else {
if (!process.env.SUPPORTS_LOCAL_API || this.backendPreference === 'invidious') {
this.getCommentDataInvidious()
if (!process.env.SUPPORTS_LOCAL_API || this.backendPreference === 'invidious' || this.isPostComments) {
if (!this.isPostComments) {
this.getCommentDataInvidious()
} else {
this.getPostCommentsInvidious()
}
} else {
this.getCommentDataLocal(true)
}
Expand All @@ -190,17 +210,14 @@ export default defineComponent({
},

getCommentReplies: function (index) {
if (process.env.SUPPORTS_LOCAL_API) {
switch (this.commentData[index].dataType) {
case 'local':
this.getCommentRepliesLocal(index)
break
case 'invidious':
this.getCommentRepliesInvidious(index)
break
if (!process.env.SUPPORTS_LOCAL_API || this.commentData[index].dataType === 'invidious' || this.isPostComments) {
if (!this.isPostComments) {
this.getCommentRepliesInvidious(index)
} else {
this.getPostCommentRepliesInvidious(index)
}
} else {
this.getCommentRepliesInvidious(index)
this.getCommentRepliesLocal(index)
}
},

Expand Down Expand Up @@ -375,5 +392,68 @@ export default defineComponent({
this.isLoading = false
})
},

getPostCommentsInvidious: function() {
const nextPageToken = this.nextPageToken

const fetchComments = nextPageToken == null
? getInvidiousCommunityPostComments({ postId: this.id, authorId: this.postAuthorId })
: getInvidiousCommunityPostCommentReplies({ postId: this.id, replyToken: this.nextPageToken, authorId: this.postAuthorId })

fetchComments.then(({ response, commentData, continuation }) => {
commentData = commentData.map(({ replyToken, ...comment }) => {
if (comment.hasReplyToken) {
this.replyTokens.set(comment.id, replyToken)
} else {
this.replyTokens.delete(comment.id)
}

return comment
})

this.commentData = this.commentData.concat(commentData)
this.nextPageToken = response?.continuation ?? continuation
this.isLoading = false
this.showComments = true
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
showToast(`${errorMessage}: ${err}`, 10000, () => {
copyToClipboard(err)
})
this.isLoading = false
})
},

getPostCommentRepliesInvidious: function(index) {
showToast(this.$t('Comments.Getting comment replies, please wait'))

const comment = this.commentData[index]
const replyToken = this.replyTokens.get(comment.id)
const id = this.id

getInvidiousCommunityPostCommentReplies({ postId: id, replyToken: replyToken, authorId: this.postAuthorId })
.then(({ commentData, continuation }) => {
comment.replies = comment.replies.concat(commentData)
comment.showReplies = true

if (continuation) {
this.replyTokens.set(comment.id, continuation)
comment.hasReplyToken = true
} else {
this.replyTokens.delete(comment.id)
comment.hasReplyToken = false
}

this.isLoading = false
}).catch((error) => {
console.error(error)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
showToast(`${errorMessage}: ${error}`, 10000, () => {
copyToClipboard(error)
})
this.isLoading = false
})
}
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
{{ $t("Comments.Click to View Comments") }}
</h4>
<ft-select
v-if="commentData.length > 0 && !isLoading && showComments"
v-if="commentData.length > 0 && !isLoading && showComments && showSortBy"
class="commentSort"
:placeholder="$t('Comments.Sort by')"
:value="currentSortValue"
Expand Down Expand Up @@ -264,7 +264,16 @@
<div
v-else-if="showComments && !isLoading"
>
<h3 class="noCommentMsg">
<h3
v-if="isPostComments"
class="noCommentMsg"
>
{{ $t("Comments.There are no comments available for this post") }}
</h3>
<h3
v-else
class="noCommentMsg"
>
{{ $t("Comments.There are no comments available for this video") }}
</h3>
</div>
Expand Down
Loading

0 comments on commit 21ff6fe

Please sign in to comment.