Skip to content

Add local api support for viewing individual community posts + comments #6491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 23 additions & 9 deletions src/renderer/components/CommentSection/CommentSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ import FtTimestampCatcher from '../FtTimestampCatcher.vue'
import store from '../../store/index'

import { copyToClipboard, showToast } from '../../helpers/utils'
import { getLocalComments, parseLocalComment } from '../../helpers/api/local'
import { getLocalCommunityPostComments, getLocalComments, parseLocalComment } from '../../helpers/api/local'
import {
getInvidiousCommunityPostCommentReplies,
getInvidiousCommunityPostComments,
Expand Down Expand Up @@ -476,7 +476,7 @@ function isSubscribedToChannel(channelId) {
function getCommentData() {
isLoading.value = true

if (!process.env.SUPPORTS_LOCAL_API || backendPreference.value === 'invidious' || props.isPostComments) {
if (!process.env.SUPPORTS_LOCAL_API || backendPreference.value === 'invidious') {
if (!props.isPostComments) {
getCommentDataInvidious()
} else {
Expand All @@ -491,7 +491,7 @@ function getMoreComments() {
if (commentData.value.length === 0 || nextPageToken.value == null) {
showToast(t('Comments.There are no more comments for this video'))
} else {
if (!process.env.SUPPORTS_LOCAL_API || backendPreference.value === 'invidious' || props.isPostComments) {
if (!process.env.SUPPORTS_LOCAL_API || backendPreference.value === 'invidious') {
if (!props.isPostComments) {
getCommentDataInvidious()
} else {
Expand All @@ -518,7 +518,7 @@ function toggleCommentReplies(index) {
* @param {number} index
*/
function getCommentReplies(index) {
if (!process.env.SUPPORTS_LOCAL_API || commentData.value[index].dataType === 'invidious' || props.isPostComments) {
if (!process.env.SUPPORTS_LOCAL_API || commentData.value[index].dataType === 'invidious') {
if (!props.isPostComments) {
getCommentRepliesInvidious(index)
} else {
Expand All @@ -545,9 +545,13 @@ async function getCommentDataLocal(more = false) {
comments = await localCommentsInstance.applySort(sortNewest.value ? 'NEWEST_FIRST' : 'TOP_COMMENTS')
localCommentsInstance = comments
} else {
comments = await getLocalComments(props.id)
sortNewest.value = comments.header?.sort_menu?.sub_menu_items?.[1].selected ?? false
localCommentsInstance = comments
if (props.isPostComments) {
comments = await getLocalCommunityPostComments(props.id, props.postAuthorId, sortNewest.value)
} else {
comments = await getLocalComments(props.id)
sortNewest.value = comments.header?.sort_menu?.sub_menu_items?.[1].selected ?? false
localCommentsInstance = comments
}
}

const parsedComments = comments.contents
Expand Down Expand Up @@ -596,7 +600,11 @@ async function getCommentDataLocal(more = false) {
if (backendFallback.value && backendPreference.value === 'local') {
localCommentsInstance = undefined
showToast(t('Falling back to Invidious API'))
getCommentDataInvidious()
if (props.isPostComments) {
getPostCommentsInvidious()
} else {
getCommentDataInvidious()
}
} else {
isLoading.value = false
}
Expand Down Expand Up @@ -763,7 +771,13 @@ function getPostCommentsInvidious() {
showToast(`${errorMessage}: ${err}`, 10000, () => {
copyToClipboard(err)
})
isLoading.value = false

if (process.env.SUPPORTS_LOCAL_API && backendFallback.value && backendPreference.value === 'invidious') {
showToast(t('Falling back to Local API'))
getCommentDataLocal()
} else {
isLoading.value = false
}
})
}

Expand Down
11 changes: 1 addition & 10 deletions src/renderer/components/FtCommunityPost/FtCommunityPost.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
aria-hidden="true"
/> {{ formattedVoteCount }}</span>
<router-link
v-if="isInvidiousAllowed && !singlePost"
v-if="!singlePost"
:to="{
path: `/post/${postId}`,
query: authorId ? { authorId } : undefined
Expand Down Expand Up @@ -218,15 +218,6 @@ const backendPreference = computed(() => {
return store.getters.getBackendPreference
})

/** @type {import('vue').ComputedRef<boolean>} */
const backendFallback = computed(() => {
return store.getters.getBackendFallback
})

const isInvidiousAllowed = computed(() => {
return backendPreference.value === 'invidious' || backendFallback.value
})

let postType = ''
let postText = ''
let postId = ''
Expand Down
27 changes: 27 additions & 0 deletions src/renderer/helpers/api/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,12 @@ export async function getLocalChannelId(url) {
// handle redirects like https://www.youtube.com/@wanderbots, which resolves to https://www.youtube.com/Wanderbots, which we need to resolve again
url = navigationEndpoint.payload.url
} else {
const channelIdRegex = /\/channel\/(?<channelId>[^/]+)/
const channelIdMatch = navigationEndpoint.metadata.url?.match(channelIdRegex)
if (channelIdMatch) {
return channelIdMatch.groups.channelId
}

return null
}
}
Expand Down Expand Up @@ -1707,3 +1713,24 @@ export async function getHashtagLocal(hashtag) {
const innertube = await createInnertube()
return await innertube.getHashtag(hashtag)
}

export async function getLocalCommunityPost(postId, channelId) {
const innertube = await createInnertube()
if (channelId == null) {
channelId = await getLocalChannelId('https://www.youtube.com/post/' + postId)
}

const postPage = await innertube.getPost(postId, channelId)
return parseLocalCommunityPost(postPage.posts[0])
}

/**
* @param {string} postId
* @param {string} channelId
* @param {boolean} sortByNewest
*/
export async function getLocalCommunityPostComments(postId, channelId, sortByNewest) {
const innertube = await createInnertube()

return await innertube.getPostComments(postId, channelId, sortByNewest ? 'NEWEST_FIRST' : 'TOP_COMMENTS')
}
77 changes: 58 additions & 19 deletions src/renderer/views/Post.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<template>
<div>
<div v-if="!isInvidiousAllowed">
{{ $t('Channel.Community.Viewing Posts Only Supported By Invidious') }}
</div>
<FtLoader v-else-if="isLoading" />
<FtLoader v-if="isLoading" />
<template
v-else
>
Expand All @@ -22,7 +19,7 @@
:force-state="null"
:is-post-comments="true"
:channel-thumbnail="post.authorThumbnails[0].url"
:show-sort-by="false"
:show-sort-by="backendPreference == 'local'"
/>
</template>
</div>
Expand All @@ -32,6 +29,7 @@
import { computed, onMounted, ref, shallowRef, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router/composables'
import packageDetails from '../../../package.json'
import { useI18n } from '../composables/use-i18n-polyfill'

import FtCard from '../components/ft-card/ft-card.vue'
import FtCommunityPost from '../components/FtCommunityPost/FtCommunityPost.vue'
Expand All @@ -41,6 +39,10 @@ import CommentSection from '../components/CommentSection/CommentSection.vue'
import store from '../store/index'

import { getInvidiousCommunityPost } from '../helpers/api/invidious'
import { getLocalCommunityPost } from '../helpers/api/local'
import { copyToClipboard, showToast } from '../helpers/utils'

const { t } = useI18n()

const router = useRouter()
const route = useRoute()
Expand All @@ -60,22 +62,18 @@ const backendFallback = computed(() => {
return store.getters.getBackendFallback
})

const isInvidiousAllowed = computed(() => {
return backendPreference.value === 'invidious' || backendFallback.value
})

onMounted(async () => {
if (isInvidiousAllowed.value) {
id.value = route.params.id
authorId.value = route.query.authorId
id.value = route.params.id
authorId.value = route.query.authorId

if (!process.env.SUPPORTS_LOCAL_API || backendPreference.value === 'invidious') {
await loadDataInvidiousAsync()
} else {
await loadDataLocalAsync()
}
})

async function loadDataInvidiousAsync() {
post.value = await getInvidiousCommunityPost(id.value, authorId.value)
authorId.value = post.value.authorId

function updateTitleAndRoute() {
store.commit('setAppTitle', `${post.value.author} - ${packageDetails.productName}`)
isLoading.value = false

Expand All @@ -92,13 +90,54 @@ async function loadDataInvidiousAsync() {
}
}

async function loadDataLocalAsync() {
try {
post.value = await getLocalCommunityPost(id.value, authorId.value)
authorId.value = post.value.authorId
updateTitleAndRoute()
} catch (error) {
console.error(error)
const errorMessage = t('Local API Error (Click to copy)')
showToast(`${errorMessage}: ${error}`, 10000, () => {
copyToClipboard(error)
})
if (backendPreference.value === 'local' && backendFallback.value) {
showToast(t('Falling back to Invidious API'))
await loadDataInvidiousAsync()
} else {
isLoading.value = false
}
}
}

async function loadDataInvidiousAsync() {
try {
post.value = await getInvidiousCommunityPost(id.value, authorId.value)
authorId.value = post.value.authorId
updateTitleAndRoute()
} catch (error) {
console.error(error)
const errorMessage = t('Invidious API Error (Click to copy)')
showToast(`${errorMessage}: ${error}`, 10000, () => {
copyToClipboard(error)
})

if (process.env.SUPPORTS_LOCAL_API && backendPreference.value === 'invidious' && backendFallback.value) {
showToast(t('Falling back to Local API'))
await loadDataLocalAsync()
} else {
isLoading.value = false
}
}
}

watch(() => route.params.id, async () => {
// react to route changes...
isLoading.value = true
if (isInvidiousAllowed.value) {
id.value = route.params.id
authorId.value = route.query.authorId
if (!process.env.SUPPORTS_LOCAL_API || backendPreference.value === 'invidious') {
await loadDataInvidiousAsync()
} else {
await loadDataLocalAsync()
}
})
</script>
2 changes: 0 additions & 2 deletions static/locales/af.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -829,8 +829,6 @@ Channel:
Hide Answers: 'Versteek antwoorde'
Video hidden by FreeTube: 'Video is deur FreeTube versteek'
View Full Post: Bekyk volle plasing
Viewing Posts Only Supported By Invidious: Bekyk van plasings word slegs vir Invidious
ondersteun. Gaan na ’n kanaal se gemeenskapsblad om inhoud te sien sonder Invidious.
Home:
Home: Tuis
View Playlist: Bekyk afspeellys
Expand Down
2 changes: 0 additions & 2 deletions static/locales/ar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,6 @@ Channel:
votes: '{votes} أصوات'
Reveal Answers: كشف الإجابات
Video hidden by FreeTube: تم إخفاء الفيديو بواسطة FreeTube
Viewing Posts Only Supported By Invidious: عرض المنشورات مدعوم فقط من قبل Invidious.
توجه إلى علامة التبويب مجتمع القناة لعرض المحتوى هناك دون Invidious.
View Full Post: عرض المنشور كاملا
Live:
Live: مباشر
Expand Down
1 change: 0 additions & 1 deletion static/locales/awa.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,6 @@ Channel:
Reveal Answers: ''
Hide Answers: ''
Video hidden by FreeTube: ''
Viewing Posts Only Supported By Invidious: ''
Video:
IP block: ''
MembersOnly: ''
Expand Down
3 changes: 0 additions & 3 deletions static/locales/be.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -822,9 +822,6 @@ Channel:
Hide Answers: 'Схаваць адказы'
Video hidden by FreeTube: Відэа схавана FreeTube'ам
View Full Post: Глядзець поўны пост
Viewing Posts Only Supported By Invidious: Прагляд паведамленняў падтрымліваецца
толькі ў Invidious. Перайдзіце на ўкладку супольнасці канала, каб праглядзець
там змесціва без Invidious.
Home:
Home: Галоўная старонка
View Playlist: Праглядзець плэй-ліст
Expand Down
3 changes: 0 additions & 3 deletions static/locales/bg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -826,9 +826,6 @@ Channel:
Reveal Answers: Разкриване на отговорите
Hide Answers: Скриване на отговорите
Video hidden by FreeTube: Видео, скрито от FreeTube
Viewing Posts Only Supported By Invidious: Преглеждането на публикации се поддържа
само от Invidious. Отидете в раздела на общността на канала, за да видите съдържанието
там без Invidious.
View Full Post: Преглед на цялата публикация
This channel does not exist: Каналът не съществува
This channel does not allow searching: Каналът не позволява търсене
Expand Down
3 changes: 0 additions & 3 deletions static/locales/br.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -844,9 +844,6 @@ Channel:
Reveal Answers: 'Diskouez ar respontoù'
Hide Answers: 'Kuzhat ar respontoù'
Video hidden by FreeTube: 'Video kuzhet gant FreeTube'
Viewing Posts Only Supported By Invidious: 'Posupl eo gwelet ar pennadoù gant
Invidious hepken. Kit war ivinell kumuniezh ur chadenn evit gwelet he fennadoù
hep Invidious.'
Video:
IP block: 'Stanket eo bet ho chomlec''h IP gant YouTube. Klaskit cheñch VPN pe proksi
evit lenn ar videoioù.'
Expand Down
3 changes: 0 additions & 3 deletions static/locales/cs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -820,9 +820,6 @@ Channel:
Reveal Answers: Odhalit odpovědi
Video hidden by FreeTube: Video skryté programem FreeTube
View Full Post: Zobrazit celý příspěvek
Viewing Posts Only Supported By Invidious: Zobrazení příspěvků je podporováno
pouze službou Invidious. Přejděte do karty komunity kanálu pro zobrazení jejího
obsahu bez Invidious.
Live:
Live: Živě
This channel does not currently have any live streams: Tento kanál v současné
Expand Down
2 changes: 0 additions & 2 deletions static/locales/cy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -867,8 +867,6 @@ Channel:
Hide Answers: 'Cuddio Atebion'
Video hidden by FreeTube: Fideo wedi'i guddio gan FreeTube
View Full Post: Gweld Post Llawn
Viewing Posts Only Supported By Invidious: Dim ond Invidious sy'n cefnogi Gweld
Postiadau. Ewch i dab cymunedol sianel i weld cynnwys yno heb Invidious.
Home:
Home: Cartref
View Playlist: Gweld Rhestr Chwarae
Expand Down
3 changes: 0 additions & 3 deletions static/locales/de-DE.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -784,9 +784,6 @@ Channel:
Hide Answers: Antworten verbergen
Video hidden by FreeTube: Video versteckt von FreeTube
View Full Post: Vollständigen Beitrag anzeigen
Viewing Posts Only Supported By Invidious: Die Anzeige von Beiträgen wird nur
von Invidious unterstützt. Gehe zum Tab „Beiträge“ eines Kanals, um dort Inhalte
ohne Invidious anzuzeigen.
Live:
Live: Live
This channel does not currently have any live streams: Dieser Kanal hat derzeit
Expand Down
2 changes: 0 additions & 2 deletions static/locales/en-GB.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -809,8 +809,6 @@ Channel:
votes: '{votes} votes'
Video hidden by FreeTube: Video hidden by FreeTube
View Full Post: View Full Post
Viewing Posts Only Supported By Invidious: Viewing Posts is only supported by
Invidious. Head to a channel's community tab to view content there without Invidious.
Live:
This channel does not currently have any live streams: This channel does not currently
have any live streams
Expand Down
1 change: 0 additions & 1 deletion static/locales/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,6 @@ Channel:
Reveal Answers: Reveal Answers
Hide Answers: Hide Answers
Video hidden by FreeTube: Video hidden by FreeTube
Viewing Posts Only Supported By Invidious: Viewing Posts is only supported by Invidious. Head to a channel's community tab to view content there without Invidious.
Video:
IP block: 'YouTube has blocked your IP address from watching videos. Please try switching to a different VPN or proxy.'
MembersOnly: Members-only videos cannot be watched with FreeTube as they require Google login and paid membership to the uploader's channel.
Expand Down
3 changes: 0 additions & 3 deletions static/locales/es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -797,9 +797,6 @@ Channel:
votes: '{votes} votos'
Video hidden by FreeTube: Vídeo oculto por FreeTube
View Full Post: Ver toda la publicación
Viewing Posts Only Supported By Invidious: La visualización de mensajes solo es
posible con Invidious. Ve a la pestaña de comunidad de un canal para ver el
contenido sin Invidious.
Live:
Live: En directo
This channel does not currently have any live streams: Este canal no tiene actualmente
Expand Down
2 changes: 0 additions & 2 deletions static/locales/et.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -824,8 +824,6 @@ Channel:
votes: '{votes} häält'
Video hidden by FreeTube: FreeTube'i poolt peidetud video
View Full Post: Vaata kogu postitust
Viewing Posts Only Supported By Invidious: Postituste vaatamine toimib vaid Invidiouse
liidestusega. Ilma selleta saad lugeda sisu, mida näed kanali kogukonna vaatest.
This channel does not exist: Sellist kanalit ei leidu
This channel is age-restricted and currently cannot be viewed in FreeTube.: Sellel
kanalil on vanusega seotud piirangud ja teda ei saa hetkel FreeTube'i vahendusel
Expand Down
Loading