FreeTube/src/renderer/views/Subscriptions/Subscriptions.js

477 lines
15 KiB
JavaScript
Raw Normal View History

2020-02-16 19:30:00 +01:00
import Vue from 'vue'
import { mapActions, mapMutations } from 'vuex'
import FtLoader from '../../components/ft-loader/ft-loader.vue'
2020-02-16 19:30:00 +01:00
import FtCard from '../../components/ft-card/ft-card.vue'
import FtButton from '../../components/ft-button/ft-button.vue'
import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue'
import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue'
2020-02-16 19:30:00 +01:00
import FtElementList from '../../components/ft-element-list/ft-element-list.vue'
import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubble.vue'
2020-02-16 19:30:00 +01:00
import ytch from 'yt-channel-info'
import Parser from 'rss-parser'
Store Revamp / Full database synchronization across windows (#1833) * History: Refactor history module * Profiles: Refactor profiles module * IPC: Move channel ids to their own file and make them constants * IPC: Replace single sync channel for one channel per sync type * Everywhere: Replace default profile id magic strings with constant ref * Profiles: Refactor `activeProfile` property from store This commit makes it so that `activeProfile`'s getter returns the entire profile, while the related update function only needs the profile id (instead of the previously used array index) to change the currently active profile. This change was made due to inconsistency regarding the active profile when creating new profiles. If a new profile coincidentally landed in the current active profile's array index after sorting, the app would mistakenly change to it without any action from the user apart from the profile's creation. Turning the profile id into the selector instead solves this issue. * Revert "Store: Implement history synchronization between windows" This reverts commit 99b61e617873412eb393d8f4dfccd8f8c172021f. This is necessary for an upcoming improved implementation of the history synchronization. * History: Remove unused mutation * Everywhere: Create abstract database handlers The project now utilizes abstract handlers to fetch, modify or otherwise manipulate data from the database. This facilitates 3 aspects of the app, in addition of making them future proof: - Switching database libraries is now trivial Since most of the app utilizes the abstract handlers, it's incredibly easily to change to a different DB library. Hypothetically, all that would need to be done is to simply replace the the file containing the base handlers, while the rest of the app would go unchanged. - Syncing logic between Electron and web is now properly separated There are now two distinct DB handling APIs: the Electron one and the web one. The app doesn't need to manually choose the API, because it's detected which platform is being utilized on import. - All Electron windows now share the same database instance This provides a single source of truth, improving consistency regarding data manipulation and windows synchronization. As a sidenote, syncing implementation has been left as is (web unimplemented; Electron only syncs settings, remaining datastore syncing will be implemented in the upcoming commits). * Electron/History: Implement history synchronization * Profiles: Implement suplementary profile creation logic * ft-profile-edit: Small fix on profile name missing display * Electron/Profiles: Implement profile synchronization * Electron/Playlists: Implement playlist synchronization
2021-12-15 19:42:24 +01:00
import { MAIN_PROFILE_ID } from '../../../constants'
2020-02-16 19:30:00 +01:00
export default Vue.extend({
name: 'Subscriptions',
components: {
'ft-loader': FtLoader,
2020-02-16 19:30:00 +01:00
'ft-card': FtCard,
'ft-button': FtButton,
'ft-icon-button': FtIconButton,
'ft-flex-box': FtFlexBox,
'ft-element-list': FtElementList,
'ft-channel-bubble': FtChannelBubble
2020-02-16 19:30:00 +01:00
},
data: function () {
return {
isLoading: false,
dataLimit: 100,
videoList: [],
errorChannels: []
}
},
computed: {
backendPreference: function () {
return this.$store.getters.getBackendPreference
},
backendFallback: function () {
return this.$store.getters.getBackendFallback
},
currentInvidiousInstance: function () {
return this.$store.getters.getCurrentInvidiousInstance
},
hideWatchedSubs: function () {
return this.$store.getters.getHideWatchedSubs
},
useRssFeeds: function () {
return this.$store.getters.getUseRssFeeds
},
profileList: function () {
return this.$store.getters.getProfileList
},
activeVideoList: function () {
if (this.videoList.length < this.dataLimit) {
return this.videoList
} else {
return this.videoList.slice(0, this.dataLimit)
}
},
activeProfile: function () {
return this.$store.getters.getActiveProfile
},
profileSubscriptions: function () {
return this.$store.getters.getProfileSubscriptions
},
allSubscriptionsList: function () {
return this.$store.getters.getAllSubscriptionsList
},
historyCache: function () {
return this.$store.getters.getHistoryCache
},
activeSubscriptionList: function () {
Store Revamp / Full database synchronization across windows (#1833) * History: Refactor history module * Profiles: Refactor profiles module * IPC: Move channel ids to their own file and make them constants * IPC: Replace single sync channel for one channel per sync type * Everywhere: Replace default profile id magic strings with constant ref * Profiles: Refactor `activeProfile` property from store This commit makes it so that `activeProfile`'s getter returns the entire profile, while the related update function only needs the profile id (instead of the previously used array index) to change the currently active profile. This change was made due to inconsistency regarding the active profile when creating new profiles. If a new profile coincidentally landed in the current active profile's array index after sorting, the app would mistakenly change to it without any action from the user apart from the profile's creation. Turning the profile id into the selector instead solves this issue. * Revert "Store: Implement history synchronization between windows" This reverts commit 99b61e617873412eb393d8f4dfccd8f8c172021f. This is necessary for an upcoming improved implementation of the history synchronization. * History: Remove unused mutation * Everywhere: Create abstract database handlers The project now utilizes abstract handlers to fetch, modify or otherwise manipulate data from the database. This facilitates 3 aspects of the app, in addition of making them future proof: - Switching database libraries is now trivial Since most of the app utilizes the abstract handlers, it's incredibly easily to change to a different DB library. Hypothetically, all that would need to be done is to simply replace the the file containing the base handlers, while the rest of the app would go unchanged. - Syncing logic between Electron and web is now properly separated There are now two distinct DB handling APIs: the Electron one and the web one. The app doesn't need to manually choose the API, because it's detected which platform is being utilized on import. - All Electron windows now share the same database instance This provides a single source of truth, improving consistency regarding data manipulation and windows synchronization. As a sidenote, syncing implementation has been left as is (web unimplemented; Electron only syncs settings, remaining datastore syncing will be implemented in the upcoming commits). * Electron/History: Implement history synchronization * Profiles: Implement suplementary profile creation logic * ft-profile-edit: Small fix on profile name missing display * Electron/Profiles: Implement profile synchronization * Electron/Playlists: Implement playlist synchronization
2021-12-15 19:42:24 +01:00
return this.activeProfile.subscriptions
},
hideLiveStreams: function() {
return this.$store.getters.getHideLiveStreams
}
},
watch: {
Store Revamp / Full database synchronization across windows (#1833) * History: Refactor history module * Profiles: Refactor profiles module * IPC: Move channel ids to their own file and make them constants * IPC: Replace single sync channel for one channel per sync type * Everywhere: Replace default profile id magic strings with constant ref * Profiles: Refactor `activeProfile` property from store This commit makes it so that `activeProfile`'s getter returns the entire profile, while the related update function only needs the profile id (instead of the previously used array index) to change the currently active profile. This change was made due to inconsistency regarding the active profile when creating new profiles. If a new profile coincidentally landed in the current active profile's array index after sorting, the app would mistakenly change to it without any action from the user apart from the profile's creation. Turning the profile id into the selector instead solves this issue. * Revert "Store: Implement history synchronization between windows" This reverts commit 99b61e617873412eb393d8f4dfccd8f8c172021f. This is necessary for an upcoming improved implementation of the history synchronization. * History: Remove unused mutation * Everywhere: Create abstract database handlers The project now utilizes abstract handlers to fetch, modify or otherwise manipulate data from the database. This facilitates 3 aspects of the app, in addition of making them future proof: - Switching database libraries is now trivial Since most of the app utilizes the abstract handlers, it's incredibly easily to change to a different DB library. Hypothetically, all that would need to be done is to simply replace the the file containing the base handlers, while the rest of the app would go unchanged. - Syncing logic between Electron and web is now properly separated There are now two distinct DB handling APIs: the Electron one and the web one. The app doesn't need to manually choose the API, because it's detected which platform is being utilized on import. - All Electron windows now share the same database instance This provides a single source of truth, improving consistency regarding data manipulation and windows synchronization. As a sidenote, syncing implementation has been left as is (web unimplemented; Electron only syncs settings, remaining datastore syncing will be implemented in the upcoming commits). * Electron/History: Implement history synchronization * Profiles: Implement suplementary profile creation logic * ft-profile-edit: Small fix on profile name missing display * Electron/Profiles: Implement profile synchronization * Electron/Playlists: Implement playlist synchronization
2021-12-15 19:42:24 +01:00
activeProfile: async function (_) {
this.getProfileSubscriptions()
}
},
mounted: async function () {
this.isLoading = true
const dataLimit = sessionStorage.getItem('subscriptionLimit')
if (dataLimit !== null) {
this.dataLimit = dataLimit
}
2020-09-03 03:04:08 +02:00
if (this.profileSubscriptions.videoList.length !== 0) {
Store Revamp / Full database synchronization across windows (#1833) * History: Refactor history module * Profiles: Refactor profiles module * IPC: Move channel ids to their own file and make them constants * IPC: Replace single sync channel for one channel per sync type * Everywhere: Replace default profile id magic strings with constant ref * Profiles: Refactor `activeProfile` property from store This commit makes it so that `activeProfile`'s getter returns the entire profile, while the related update function only needs the profile id (instead of the previously used array index) to change the currently active profile. This change was made due to inconsistency regarding the active profile when creating new profiles. If a new profile coincidentally landed in the current active profile's array index after sorting, the app would mistakenly change to it without any action from the user apart from the profile's creation. Turning the profile id into the selector instead solves this issue. * Revert "Store: Implement history synchronization between windows" This reverts commit 99b61e617873412eb393d8f4dfccd8f8c172021f. This is necessary for an upcoming improved implementation of the history synchronization. * History: Remove unused mutation * Everywhere: Create abstract database handlers The project now utilizes abstract handlers to fetch, modify or otherwise manipulate data from the database. This facilitates 3 aspects of the app, in addition of making them future proof: - Switching database libraries is now trivial Since most of the app utilizes the abstract handlers, it's incredibly easily to change to a different DB library. Hypothetically, all that would need to be done is to simply replace the the file containing the base handlers, while the rest of the app would go unchanged. - Syncing logic between Electron and web is now properly separated There are now two distinct DB handling APIs: the Electron one and the web one. The app doesn't need to manually choose the API, because it's detected which platform is being utilized on import. - All Electron windows now share the same database instance This provides a single source of truth, improving consistency regarding data manipulation and windows synchronization. As a sidenote, syncing implementation has been left as is (web unimplemented; Electron only syncs settings, remaining datastore syncing will be implemented in the upcoming commits). * Electron/History: Implement history synchronization * Profiles: Implement suplementary profile creation logic * ft-profile-edit: Small fix on profile name missing display * Electron/Profiles: Implement profile synchronization * Electron/Playlists: Implement playlist synchronization
2021-12-15 19:42:24 +01:00
if (this.profileSubscriptions.activeProfile === this.activeProfile._id) {
const subscriptionList = JSON.parse(JSON.stringify(this.profileSubscriptions))
if (this.hideWatchedSubs) {
this.videoList = await Promise.all(subscriptionList.videoList.filter((video) => {
const historyIndex = this.historyCache.findIndex((x) => {
return x.videoId === video.videoId
})
return historyIndex === -1
}))
} else {
this.videoList = subscriptionList.videoList
this.errorChannels = subscriptionList.errorChannels
}
} else {
this.getProfileSubscriptions()
}
2020-09-03 03:04:08 +02:00
this.isLoading = false
} else {
setTimeout(async () => {
this.getSubscriptions()
}, 300)
2020-09-03 03:04:08 +02:00
}
},
methods: {
goToChannel: function (id) {
this.$router.push({ path: `/channel/${id}` })
},
getSubscriptions: function () {
if (this.activeSubscriptionList.length === 0) {
this.isLoading = false
this.videoList = []
return
}
let useRss = this.useRssFeeds
if (this.activeSubscriptionList.length >= 125 && !useRss) {
this.showToast({
message: this.$t('Subscriptions["This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting"]'),
time: 10000
})
useRss = true
}
this.isLoading = true
this.updateShowProgressBar(true)
this.setProgressBarPercentage(0)
let videoList = []
let channelCount = 0
this.errorChannels = []
this.activeSubscriptionList.forEach(async (channel) => {
let videos = []
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
if (useRss) {
2020-09-26 03:40:22 +02:00
videos = await this.getChannelVideosInvidiousRSS(channel)
} else {
2020-09-26 03:40:22 +02:00
videos = await this.getChannelVideosInvidiousScraper(channel)
}
} else {
if (useRss) {
2020-09-26 03:40:22 +02:00
videos = await this.getChannelVideosLocalRSS(channel)
} else {
2020-09-26 03:40:22 +02:00
videos = await this.getChannelVideosLocalScraper(channel)
}
}
videoList = videoList.concat(videos)
channelCount++
const percentageComplete = (channelCount / this.activeSubscriptionList.length) * 100
this.setProgressBarPercentage(percentageComplete)
if (channelCount === this.activeSubscriptionList.length) {
videoList = await Promise.all(videoList.sort((a, b) => {
return b.publishedDate - a.publishedDate
}))
if (this.hideLiveStreams) {
videoList = videoList.filter(item => {
return (!item.liveNow && !item.isUpcoming)
})
}
const profileSubscriptions = {
Store Revamp / Full database synchronization across windows (#1833) * History: Refactor history module * Profiles: Refactor profiles module * IPC: Move channel ids to their own file and make them constants * IPC: Replace single sync channel for one channel per sync type * Everywhere: Replace default profile id magic strings with constant ref * Profiles: Refactor `activeProfile` property from store This commit makes it so that `activeProfile`'s getter returns the entire profile, while the related update function only needs the profile id (instead of the previously used array index) to change the currently active profile. This change was made due to inconsistency regarding the active profile when creating new profiles. If a new profile coincidentally landed in the current active profile's array index after sorting, the app would mistakenly change to it without any action from the user apart from the profile's creation. Turning the profile id into the selector instead solves this issue. * Revert "Store: Implement history synchronization between windows" This reverts commit 99b61e617873412eb393d8f4dfccd8f8c172021f. This is necessary for an upcoming improved implementation of the history synchronization. * History: Remove unused mutation * Everywhere: Create abstract database handlers The project now utilizes abstract handlers to fetch, modify or otherwise manipulate data from the database. This facilitates 3 aspects of the app, in addition of making them future proof: - Switching database libraries is now trivial Since most of the app utilizes the abstract handlers, it's incredibly easily to change to a different DB library. Hypothetically, all that would need to be done is to simply replace the the file containing the base handlers, while the rest of the app would go unchanged. - Syncing logic between Electron and web is now properly separated There are now two distinct DB handling APIs: the Electron one and the web one. The app doesn't need to manually choose the API, because it's detected which platform is being utilized on import. - All Electron windows now share the same database instance This provides a single source of truth, improving consistency regarding data manipulation and windows synchronization. As a sidenote, syncing implementation has been left as is (web unimplemented; Electron only syncs settings, remaining datastore syncing will be implemented in the upcoming commits). * Electron/History: Implement history synchronization * Profiles: Implement suplementary profile creation logic * ft-profile-edit: Small fix on profile name missing display * Electron/Profiles: Implement profile synchronization * Electron/Playlists: Implement playlist synchronization
2021-12-15 19:42:24 +01:00
activeProfile: this.activeProfile._id,
videoList: videoList,
errorChannels: this.errorChannels
}
this.videoList = await Promise.all(videoList.filter((video) => {
if (this.hideWatchedSubs) {
const historyIndex = this.historyCache.findIndex((x) => {
return x.videoId === video.videoId
})
return historyIndex === -1
} else {
return true
}
}))
this.updateProfileSubscriptions(profileSubscriptions)
this.isLoading = false
this.updateShowProgressBar(false)
Store Revamp / Full database synchronization across windows (#1833) * History: Refactor history module * Profiles: Refactor profiles module * IPC: Move channel ids to their own file and make them constants * IPC: Replace single sync channel for one channel per sync type * Everywhere: Replace default profile id magic strings with constant ref * Profiles: Refactor `activeProfile` property from store This commit makes it so that `activeProfile`'s getter returns the entire profile, while the related update function only needs the profile id (instead of the previously used array index) to change the currently active profile. This change was made due to inconsistency regarding the active profile when creating new profiles. If a new profile coincidentally landed in the current active profile's array index after sorting, the app would mistakenly change to it without any action from the user apart from the profile's creation. Turning the profile id into the selector instead solves this issue. * Revert "Store: Implement history synchronization between windows" This reverts commit 99b61e617873412eb393d8f4dfccd8f8c172021f. This is necessary for an upcoming improved implementation of the history synchronization. * History: Remove unused mutation * Everywhere: Create abstract database handlers The project now utilizes abstract handlers to fetch, modify or otherwise manipulate data from the database. This facilitates 3 aspects of the app, in addition of making them future proof: - Switching database libraries is now trivial Since most of the app utilizes the abstract handlers, it's incredibly easily to change to a different DB library. Hypothetically, all that would need to be done is to simply replace the the file containing the base handlers, while the rest of the app would go unchanged. - Syncing logic between Electron and web is now properly separated There are now two distinct DB handling APIs: the Electron one and the web one. The app doesn't need to manually choose the API, because it's detected which platform is being utilized on import. - All Electron windows now share the same database instance This provides a single source of truth, improving consistency regarding data manipulation and windows synchronization. As a sidenote, syncing implementation has been left as is (web unimplemented; Electron only syncs settings, remaining datastore syncing will be implemented in the upcoming commits). * Electron/History: Implement history synchronization * Profiles: Implement suplementary profile creation logic * ft-profile-edit: Small fix on profile name missing display * Electron/Profiles: Implement profile synchronization * Electron/Playlists: Implement playlist synchronization
2021-12-15 19:42:24 +01:00
if (this.activeProfile === MAIN_PROFILE_ID) {
this.updateAllSubscriptionsList(profileSubscriptions.videoList)
}
}
})
},
getProfileSubscriptions: async function () {
if (this.allSubscriptionsList.length !== 0) {
this.isLoading = true
this.videoList = await Promise.all(this.allSubscriptionsList.filter((video) => {
const channelIndex = this.activeSubscriptionList.findIndex((x) => {
return x.id === video.authorId
})
const historyIndex = this.historyCache.findIndex((x) => {
return x.videoId === video.videoId
})
if (this.hideWatchedSubs) {
return channelIndex !== -1 && historyIndex === -1
} else {
return channelIndex !== -1
}
}))
this.isLoading = false
} else {
this.getSubscriptions()
}
},
2020-09-26 03:40:22 +02:00
getChannelVideosLocalScraper: function (channel, failedAttempts = 0) {
return new Promise((resolve, reject) => {
ytch.getChannelVideos({ channelId: channel.id, sortBy: 'latest' }).then(async (response) => {
if (response.alertMessage) {
this.errorChannels.push(channel)
resolve([])
return
}
const videos = await Promise.all(response.items.map(async (video) => {
if (video.liveNow) {
video.publishedDate = new Date().getTime()
} else {
video.publishedDate = await this.calculatePublishedDate(video.publishedText)
}
return video
}))
resolve(videos)
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Local API Error (Click to copy)')
this.showToast({
message: `${errorMessage}: ${err}`,
time: 10000,
action: () => {
this.copyToClipboard({ content: err })
}
})
switch (failedAttempts) {
case 0:
2020-09-26 03:40:22 +02:00
resolve(this.getChannelVideosLocalRSS(channel, failedAttempts + 1))
break
case 1:
if (this.backendFallback) {
this.showToast({
2020-09-26 03:40:22 +02:00
message: this.$t('Falling back to Invidious API')
})
2020-09-26 03:40:22 +02:00
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
} else {
resolve([])
}
break
case 2:
2020-09-26 03:40:22 +02:00
resolve(this.getChannelVideosLocalRSS(channel, failedAttempts + 1))
break
default:
resolve([])
}
})
})
},
2020-09-26 03:40:22 +02:00
getChannelVideosLocalRSS: function (channel, failedAttempts = 0) {
return new Promise((resolve, reject) => {
const parser = new Parser()
2020-09-26 03:40:22 +02:00
const feedUrl = `https://www.youtube.com/feeds/videos.xml?channel_id=${channel.id}`
parser.parseURL(feedUrl).then(async (feed) => {
const items = await Promise.all(feed.items.map((video) => {
2020-09-26 03:40:22 +02:00
video.authorId = channel.id
video.videoId = video.id.replace('yt:video:', '')
video.type = 'video'
video.lengthSeconds = '0:00'
video.isRSS = true
video.publishedDate = new Date(video.pubDate)
if (video.publishedDate.toString() === 'Invalid Date') {
video.publishedDate = new Date(video.isoDate)
}
video.publishedText = video.publishedDate.toLocaleString()
return video
}))
resolve(items)
}).catch((err) => {
console.error(err)
if (err.toString().match(/404/)) {
this.errorChannels.push(channel)
resolve([])
} else {
const errorMessage = this.$t('Local API Error (Click to copy)')
this.showToast({
message: `${errorMessage}: ${err}`,
time: 10000,
action: () => {
this.copyToClipboard({ content: err })
}
})
switch (failedAttempts) {
case 0:
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
break
case 1:
if (this.backendFallback) {
this.showToast({
message: this.$t('Falling back to Invidious API')
})
resolve(this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1))
} else {
resolve([])
}
break
case 2:
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
break
default:
resolve([])
}
}
})
})
},
2020-09-26 03:40:22 +02:00
getChannelVideosInvidiousScraper: function (channel, failedAttempts = 0) {
return new Promise((resolve, reject) => {
const subscriptionsPayload = {
resource: 'channels/latest',
2020-09-26 03:40:22 +02:00
id: channel.id,
params: {}
}
this.invidiousAPICall(subscriptionsPayload).then(async (result) => {
resolve(await Promise.all(result.map((video) => {
video.publishedDate = new Date(video.published * 1000)
return video
})))
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
this.showToast({
message: `${errorMessage}: ${err.responseText}`,
time: 10000,
action: () => {
this.copyToClipboard({ content: err.responseText })
}
})
switch (failedAttempts) {
case 0:
2020-09-26 03:40:22 +02:00
resolve(this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1))
break
case 1:
if (this.backendFallback) {
this.showToast({
message: this.$t('Falling back to the local API')
})
2020-09-26 03:40:22 +02:00
resolve(this.getChannelVideosLocalScraper(channel, failedAttempts + 1))
} else {
resolve([])
}
break
case 2:
2020-09-26 03:40:22 +02:00
resolve(this.getChannelVideosInvidiousRSS(channel, failedAttempts + 1))
break
default:
resolve([])
}
})
})
},
2020-09-26 03:40:22 +02:00
getChannelVideosInvidiousRSS: function (channel, failedAttempts = 0) {
return new Promise((resolve, reject) => {
const parser = new Parser()
const feedUrl = `${this.currentInvidiousInstance}/feed/channel/${channel.id}`
parser.parseURL(feedUrl).then(async (feed) => {
resolve(await Promise.all(feed.items.map((video) => {
2020-09-26 03:40:22 +02:00
video.authorId = channel.id
video.videoId = video.id.replace('yt:video:', '')
video.type = 'video'
video.publishedDate = new Date(video.pubDate)
video.publishedText = video.publishedDate.toLocaleString()
video.lengthSeconds = '0:00'
video.isRSS = true
return video
})))
}).catch((err) => {
console.error(err)
const errorMessage = this.$t('Invidious API Error (Click to copy)')
this.showToast({
2020-10-21 17:15:42 +02:00
message: `${errorMessage}: ${err}`,
time: 10000,
action: () => {
this.copyToClipboard({ content: err })
}
})
if (err.toString().match(/500/)) {
this.errorChannels.push(channel)
resolve([])
} else {
switch (failedAttempts) {
case 0:
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
break
case 1:
if (this.backendFallback) {
this.showToast({
message: this.$t('Falling back to the local API')
})
resolve(this.getChannelVideosLocalRSS(channel, failedAttempts + 1))
} else {
resolve([])
}
break
case 2:
resolve(this.getChannelVideosInvidiousScraper(channel, failedAttempts + 1))
break
default:
resolve([])
}
}
})
})
},
increaseLimit: function () {
this.dataLimit += 100
sessionStorage.setItem('subscriptionLimit', this.dataLimit)
},
...mapActions([
'showToast',
'invidiousAPICall',
'updateShowProgressBar',
'updateProfileSubscriptions',
'updateAllSubscriptionsList',
'calculatePublishedDate',
'copyToClipboard'
]),
...mapMutations([
'setProgressBarPercentage'
])
2020-02-16 19:30:00 +01:00
}
})