Skip to content

IV: add support for hashtag pages #3571

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

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
12 changes: 12 additions & 0 deletions src/renderer/helpers/api/invidious.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,15 @@ export function filterInvidiousFormats(formats, allowAv1 = false) {
// }
return [...audioFormats, ...h264Formats]
}

export async function getHashtagInvidious(hashtag, page) {
const payload = {
resource: 'hashtag',
id: hashtag,
params: {
page
}
}
const response = await invidiousAPICall(payload)
return response.results
}
121 changes: 90 additions & 31 deletions src/renderer/views/Hashtag/Hashtag.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
import packageDetails from '../../../../package.json'
import { getHashtagLocal, parseLocalListVideo } from '../../helpers/api/local'
import { isNullOrEmpty } from '../../helpers/utils'
import { copyToClipboard, isNullOrEmpty, showToast } from '../../helpers/utils'
import { getHashtagInvidious } from '../../helpers/api/invidious'

export default defineComponent({
name: 'Hashtag',
Expand All @@ -21,6 +22,7 @@ export default defineComponent({
hashtagContinuationData: null,
videos: [],
apiUsed: 'local',
pageNumber: 1,
isLoading: true
}
},
Expand All @@ -34,66 +36,123 @@ export default defineComponent({
},

showFetchMoreButton() {
return !isNullOrEmpty(this.hashtagContinuationData)
return !isNullOrEmpty(this.hashtagContinuationData) || this.apiUsed === 'invidious'
}
},
watch: {
$route() {
this.isLoading = true
this.hashtag = ''
this.hashtagContinuationData = null
this.videos = []
this.apiUsed = 'local'
this.resetData()
this.getHashtag()
}
},
mounted: function() {
this.isLoading = true
this.resetData()
this.getHashtag()
},
methods: {
resetData: function() {
this.isLoading = true
this.hashtag = ''
this.hashtagContinuationData = null
this.videos = []
this.apiUsed = 'local'
this.pageNumber = 1
},

getHashtag: async function() {
const hashtag = this.$route.params.hashtag
if (this.backendFallback || this.backendPreference === 'local') {
await this.getLocalHashtag(hashtag)
} else {
this.getInvidiousHashtag(hashtag)
await this.getInvidiousHashtag(hashtag)
}
document.title = `${this.hashtag} - ${packageDetails.productName}`
},
getInvidiousHashtag: function(hashtag) {
this.hashtag = '#' + hashtag
this.apiUsed = 'Invidious'
this.isLoading = false

getInvidiousHashtag: async function(hashtag, page) {
try {
const videos = await getHashtagInvidious(hashtag, page)
this.hashtag = '#' + hashtag
this.isLoading = false
this.apiUsed = 'invidious'
this.videos = this.videos.concat(videos)
this.pageNumber += 1
} catch (error) {
console.error(error)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
showToast(`${errorMessage}: ${error}`, 10000, () => {
copyToClipboard(error)
})
if (process.env.IS_ELECTRON && this.backendPreference === 'invidious' && this.backendFallback) {
showToast(this.$t('Falling back to Local API'))
this.resetData()
this.getLocalHashtag(hashtag)
} else {
this.isLoading = false
}
}
},

getLocalHashtag: async function(hashtag) {
const hashtagData = await getHashtagLocal(hashtag)
this.hashtag = hashtagData.header.hashtag
this.videos = hashtagData.contents.contents.filter(item =>
item.type !== 'ContinuationItem'
).map(item =>
parseLocalListVideo(item.content)
)
this.apiUsed = 'local'
this.hashtagContinuationData = hashtagData.has_continuation ? hashtagData : null
this.isLoading = false
try {
const hashtagData = await getHashtagLocal(hashtag)
this.hashtag = hashtagData.header.hashtag
this.videos = hashtagData.contents.contents.filter(item =>
item.type !== 'ContinuationItem'
).map(item =>
parseLocalListVideo(item.content)
)
this.apiUsed = 'local'
this.hashtagContinuationData = hashtagData.has_continuation ? hashtagData : null
this.isLoading = false
} catch (error) {
console.error(error)
const errorMessage = this.$t('Local API Error (Click to copy)')
showToast(`${errorMessage}: ${error}`, 10000, () => {
copyToClipboard(error)
})
if (this.backendPreference === 'local' && this.backendFallback) {
showToast(this.$t('Falling back to Invidious API'))
this.resetData()
this.getInvidiousHashtag(hashtag)
} else {
this.isLoading = false
}
}
},

getLocalHashtagMore: async function() {
const continuation = await this.hashtagContinuationData.getContinuationData()
const newVideos = continuation.on_response_received_actions[0].contents.filter(item =>
item.type !== 'ContinuationItem'
).map(item =>
parseLocalListVideo(item.content)
)
this.hashtagContinuationData = continuation.has_continuation ? continuation : null
this.videos = this.videos.concat(newVideos)
try {
const continuation = await this.hashtagContinuationData.getContinuationData()
const newVideos = continuation.on_response_received_actions[0].contents.filter(item =>
item.type !== 'ContinuationItem'
).map(item =>
parseLocalListVideo(item.content)
)
this.hashtagContinuationData = continuation.has_continuation ? continuation : null
this.videos = this.videos.concat(newVideos)
} catch (error) {
console.error(error)
const errorMessage = this.$t('Local API Error (Click to copy)')
showToast(`${errorMessage}: ${error}`, 10000, () => {
copyToClipboard(error)
})
if (this.backendPreference === 'local' && this.backendFallback) {
showToast(this.$t('Falling back to Invidious API'))
const hashtag = this.hashtag.substring(1)
this.resetData()
this.getLocalHashtag(hashtag)
} else {
this.isLoading = false
}
}
},

handleFetchMore: function() {
if (this.apiUsed === 'local') {
this.getLocalHashtagMore()
} else if (this.apiUsed === 'invidious') {
this.getInvidiousHashtag(this.hashtag.substring(1), this.pageNumber)
}
}
}
Expand Down
13 changes: 2 additions & 11 deletions src/renderer/views/Hashtag/Hashtag.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,18 @@
class="elementList"
>
<ft-element-list
v-if="backendFallback || backendPreference === 'local' && videos.length > 0"
v-if="videos.length > 0"
:data="videos"
/>
<ft-flex-box
v-else-if="backendFallback || backendPreference === 'local' && videos.length === 0"
v-else-if="videos.length === 0"
>
<p
class="message"
>
{{ $t("Hashtag.This hashtag does not currently have any videos") }}
</p>
</ft-flex-box>
<ft-flex-box
v-else
>
<p
class="message"
>
{{ $t("Hashtag.You can only view hashtag pages through the Local API") }}
</p>
</ft-flex-box>
</div>
<div
v-if="showFetchMoreButton"
Expand Down
2 changes: 0 additions & 2 deletions static/locales/ar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -977,5 +977,3 @@ Hashtag:
This hashtag does not currently have any videos: هذا الهاشتاج ليس لديه حاليا أي
مقاطع فيديو
Hashtag: هاشتاج
You can only view hashtag pages through the Local API: يمكنك فقط عرض صفحات الهاشتاج
من خلال واجهة برمجة التطبيقات (API) المحلية
2 changes: 0 additions & 2 deletions static/locales/bg.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1002,5 +1002,3 @@ Ok: Добре
Hashtag:
Hashtag: Хаштаг
This hashtag does not currently have any videos: В момента този хаштаг няма видеа
You can only view hashtag pages through the Local API: Можете да разглеждате страници
с хаштагове само чрез локалния вътрешен интерфейс
2 changes: 0 additions & 2 deletions static/locales/cs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,5 @@ Chapters:
Preferences: Předvolby
Ok: Ok
Hashtag:
You can only view hashtag pages through the Local API: Stránky hashtagů lze momentálně
procházet pouze s lokálním API
Hashtag: Hashtag
This hashtag does not currently have any videos: Tento hashtag nemá žádná videa
1 change: 0 additions & 1 deletion static/locales/en-US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,6 @@ Hashtag:
Hashtag: Hashtag
This hashtag does not currently have any videos: This hashtag does not currently
have any videos
You can only view hashtag pages through the Local API: You can only view hashtag pages through the Local API
Yes: Yes
No: No
Ok: Ok
2 changes: 0 additions & 2 deletions static/locales/es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1010,5 +1010,3 @@ Hashtag:
Hashtag: Hashtag
This hashtag does not currently have any videos: Este hashtag no tiene actualmente
ningún vídeo
You can only view hashtag pages through the Local API: Sólo puedes ver las páginas
de los hashtags a través de la API local
2 changes: 0 additions & 2 deletions static/locales/he.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -960,6 +960,4 @@ Preferences: העדפות
Ok: אישור
Hashtag:
This hashtag does not currently have any videos: לתגית ההקבץ הזו אין סרטונים כרגע
You can only view hashtag pages through the Local API: אפשר לצפות בעמודי תגית הקבץ
דרך ה־API המקומי בלבד
Hashtag: תגית הקבץ
2 changes: 0 additions & 2 deletions static/locales/hr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,4 @@ Preferences: Korisničke postavke
Ok: U redu
Hashtag:
This hashtag does not currently have any videos: Ovaj hashtag trenutačno nema videa
You can only view hashtag pages through the Local API: Stranice s hashtagovima možeš
gledati samo putem lokalnog API-ja
Hashtag: Hashtag
2 changes: 0 additions & 2 deletions static/locales/hu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1002,5 +1002,3 @@ Hashtag:
Hashtag: Kettőskereszt
This hashtag does not currently have any videos: Ez a kettőskereszt jelenleg nem
rendelkezik videókkal
You can only view hashtag pages through the Local API: Kettőskereszt oldalait csak
a helyi API felületen keresztül tudja megtekinteni
2 changes: 0 additions & 2 deletions static/locales/it.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1021,5 +1021,3 @@ Hashtag:
This hashtag does not currently have any videos: Questo hashtag attualmente non
ha alcun video
Hashtag: Hashtag
You can only view hashtag pages through the Local API: Puoi visualizzare le pagine
hashtag solo tramite l'API locale
2 changes: 0 additions & 2 deletions static/locales/pl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1020,8 +1020,6 @@ Chapters:
Preferences: Preferencje
Ok: Ok
Hashtag:
You can only view hashtag pages through the Local API: Strony hashtagów są dostępne
jedynie poprzez lokalne API
Hashtag: Hashtag
This hashtag does not currently have any videos: Nie ma na razie żadnych filmów
z takim hashtagiem
2 changes: 0 additions & 2 deletions static/locales/pt-PT.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,5 @@ Clipboard:
Ok: Ok
Hashtag:
Hashtag: Marcador
You can only view hashtag pages through the Local API: Só é possível ver páginas
de hashtag através da API local
This hashtag does not currently have any videos: Esta hashtag não tem atualmente
quaisquer vídeos
2 changes: 0 additions & 2 deletions static/locales/pt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1001,5 +1001,3 @@ Hashtag:
Hashtag: Marcador
This hashtag does not currently have any videos: Esta hashtag não tem atualmente
quaisquer vídeos
You can only view hashtag pages through the Local API: Só é possível ver páginas
de hashtag através da API local
2 changes: 0 additions & 2 deletions static/locales/ru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1007,5 +1007,3 @@ Hashtag:
Hashtag: Распределительная метка
This hashtag does not currently have any videos: Этой распределительной метки пока
нет ни у одного видео
You can only view hashtag pages through the Local API: Ты можешь видеть страницы
с распределительными метками только через локальный набор функций
2 changes: 0 additions & 2 deletions static/locales/tr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,5 @@ Preferences: Tercihler
Ok: Tamam
Hashtag:
Hashtag: Hashtag
You can only view hashtag pages through the Local API: Hashtag sayfalarını yalnızca
Yerel API aracılığıyla görüntüleyebilirsiniz
This hashtag does not currently have any videos: Bu hashtag'in şu anda herhangi
bir videosu yok
2 changes: 0 additions & 2 deletions static/locales/uk.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,4 @@ Preferences: Налаштування
Ok: Гаразд
Hashtag:
Hashtag: Хештег
You can only view hashtag pages through the Local API: Ви можете переглядати сторінки
з хештегами лише через локальний API
This hashtag does not currently have any videos: За цим хештегом наразі немає відео
1 change: 0 additions & 1 deletion static/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -878,5 +878,4 @@ Preferences: 选项
Ok: 好
Hashtag:
Hashtag: 标签
You can only view hashtag pages through the Local API: 你只能通过本地 API 浏览标签页面
This hashtag does not currently have any videos: 此标签下当前没有任何短视频
1 change: 0 additions & 1 deletion static/locales/zh-TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -890,4 +890,3 @@ Ok: 確定
Hashtag:
Hashtag: 主題標籤
This hashtag does not currently have any videos: 此標籤目前沒有任何影片
You can only view hashtag pages through the Local API: 您僅能透過本機 API 檢視主題標籤頁面