mirror of https://github.com/FreeTubeApp/FreeTube
172 lines
5.6 KiB
JavaScript
172 lines
5.6 KiB
JavaScript
import { defineComponent } from 'vue'
|
|
import FtCard from '../../components/ft-card/ft-card.vue'
|
|
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
|
|
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 { copyToClipboard, setPublishedTimestampsInvidious, showToast } from '../../helpers/utils'
|
|
import { isNullOrEmpty } from '../../helpers/strings'
|
|
import { getHashtagInvidious } from '../../helpers/api/invidious'
|
|
|
|
export default defineComponent({
|
|
name: 'Hashtag',
|
|
components: {
|
|
'ft-card': FtCard,
|
|
'ft-element-list': FtElementList,
|
|
'ft-flex-box': FtFlexBox,
|
|
'ft-loader': FtLoader
|
|
},
|
|
data: function() {
|
|
return {
|
|
hashtag: '',
|
|
hashtagContinuationData: null,
|
|
videos: [],
|
|
apiUsed: 'local',
|
|
pageNumber: 1,
|
|
isLoading: true
|
|
}
|
|
},
|
|
computed: {
|
|
backendPreference: function () {
|
|
return this.$store.getters.getBackendPreference
|
|
},
|
|
|
|
backendFallback: function () {
|
|
return this.$store.getters.getBackendFallback
|
|
},
|
|
|
|
showFetchMoreButton() {
|
|
return !isNullOrEmpty(this.hashtagContinuationData) || this.apiUsed === 'invidious'
|
|
}
|
|
},
|
|
watch: {
|
|
$route() {
|
|
this.resetData()
|
|
this.getHashtag()
|
|
}
|
|
},
|
|
mounted: function() {
|
|
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 {
|
|
await this.getInvidiousHashtag(hashtag)
|
|
}
|
|
document.title = `${this.hashtag} - ${packageDetails.productName}`
|
|
},
|
|
|
|
getInvidiousHashtag: async function(hashtag, page) {
|
|
try {
|
|
const videos = await getHashtagInvidious(hashtag, page)
|
|
setPublishedTimestampsInvidious(videos)
|
|
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.SUPPORTS_LOCAL_API && 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) {
|
|
try {
|
|
const hashtagData = await getHashtagLocal(hashtag)
|
|
|
|
const header = hashtagData.header
|
|
if (header) {
|
|
switch (header.type) {
|
|
case 'HashtagHeader':
|
|
this.hashtag = header.hashtag.toString()
|
|
break
|
|
case 'PageHeader':
|
|
this.hashtag = header.content.title.text
|
|
break
|
|
default:
|
|
console.error(`Unknown hashtag header type: ${header.type}, falling back to query parameter.`)
|
|
this.hashtag = `#${hashtag}`
|
|
}
|
|
} else {
|
|
console.error(' Hashtag header missing, probably a layout change, falling back to query parameter.')
|
|
this.hashtag = `#${hashtag}`
|
|
}
|
|
|
|
this.videos = hashtagData.videos.map(parseLocalListVideo)
|
|
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() {
|
|
try {
|
|
const continuation = await this.hashtagContinuationData.getContinuation()
|
|
const newVideos = continuation.videos.map(parseLocalListVideo)
|
|
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)
|
|
}
|
|
}
|
|
}
|
|
})
|