From 56aff33bff7df9842a136364389fccf54692500e Mon Sep 17 00:00:00 2001 From: petaded Date: Sun, 18 Jun 2023 10:45:44 +0100 Subject: [PATCH 1/5] Changes from PR #3673 --- .../ft-list-lazy-wrapper/ft-list-lazy-wrapper.js | 14 ++++++-------- src/renderer/views/Subscriptions/Subscriptions.js | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/renderer/components/ft-list-lazy-wrapper/ft-list-lazy-wrapper.js b/src/renderer/components/ft-list-lazy-wrapper/ft-list-lazy-wrapper.js index fae88932f3217..ebc5aabba9ab3 100644 --- a/src/renderer/components/ft-list-lazy-wrapper/ft-list-lazy-wrapper.js +++ b/src/renderer/components/ft-list-lazy-wrapper/ft-list-lazy-wrapper.js @@ -48,13 +48,7 @@ export default defineComponent({ }, hideUpcomingPremieres: function () { return this.$store.getters.getHideUpcomingPremieres - } - }, - methods: { - onVisibilityChanged: function (visible) { - this.visible = visible }, - /** * Show or Hide results in the list * @@ -70,10 +64,9 @@ export default defineComponent({ // hide livestreams return false } - if (this.hideUpcomingPremieres && // Observed for premieres in Local API Channels. - (data.durationText === 'PREMIERE' || + (data.premiereDate != null || // viewCount is our only method of detecting premieres in RSS // data without sending an additional request. // If we ever get a better flag, use it here instead. @@ -98,6 +91,11 @@ export default defineComponent({ } return true } + }, + methods: { + onVisibilityChanged: function (visible) { + this.visible = visible + } } }) diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 5a441948d1139..5805d62441531 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -206,7 +206,7 @@ export default defineComponent({ return item.viewCount !== '0' } // Observed for premieres in Local API Subscriptions. - return item.durationText !== 'PREMIERE' + return item.premiereDate == null }) } const profileSubscriptions = { From 82d3345fc0f7928b9dd28c9d009f423610517bd4 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Wed, 14 Jun 2023 14:00:00 +0800 Subject: [PATCH 2/5] * Update subscription view to be able to load videos from video cache again --- .../privacy-settings/privacy-settings.js | 10 +- src/renderer/store/modules/subscriptions.js | 74 +++++--- .../views/Subscriptions/Subscriptions.js | 159 ++++++++++-------- .../views/Subscriptions/Subscriptions.vue | 2 +- 4 files changed, 143 insertions(+), 102 deletions(-) diff --git a/src/renderer/components/privacy-settings/privacy-settings.js b/src/renderer/components/privacy-settings/privacy-settings.js index 7b2a406dc4863..03d65a5f88d6f 100644 --- a/src/renderer/components/privacy-settings/privacy-settings.js +++ b/src/renderer/components/privacy-settings/privacy-settings.js @@ -110,12 +110,7 @@ export default defineComponent({ } }) - this.updateAllSubscriptionsList([]) - this.updateProfileSubscriptions({ - activeProfile: MAIN_PROFILE_ID, - videoList: [], - errorChannels: [] - }) + this.clearSubscriptionsCache() } }, @@ -129,8 +124,7 @@ export default defineComponent({ 'updateProfile', 'removeProfile', 'updateActiveProfile', - 'updateAllSubscriptionsList', - 'updateProfileSubscriptions' + 'clearSubscriptionsCache', ]) } }) diff --git a/src/renderer/store/modules/subscriptions.js b/src/renderer/store/modules/subscriptions.js index 37be7815cbcab..4ed626ca340d9 100644 --- a/src/renderer/store/modules/subscriptions.js +++ b/src/renderer/store/modules/subscriptions.js @@ -1,39 +1,71 @@ import { MAIN_PROFILE_ID } from '../../../constants' -const state = { - allSubscriptionsList: [], - profileSubscriptions: { - activeProfile: MAIN_PROFILE_ID, +const defaultState = { + subscriptionsCacheForAllSubscriptionsProfile: { + videoList: [], + }, + subscriptionsCacheForActiveProfile: { videoList: [], - errorChannels: [] - } + profileID: '', + errorChannels: [], + }, +} + +function deepCopy(obj) { + return JSON.parse(JSON.stringify(obj)) +} + +const state = { + subscriptionsCacheForAllSubscriptionsProfile: deepCopy(defaultState.subscriptionsCacheForAllSubscriptionsProfile), + subscriptionsCacheForActiveProfile: deepCopy(defaultState.subscriptionsCacheForActiveProfile), } const getters = { - getAllSubscriptionsList: () => { - return state.allSubscriptionsList + getSubscriptionsCacheForAllSubscriptionsProfile: () => { + return state.subscriptionsCacheForAllSubscriptionsProfile + }, + getSubscriptionsCacheForProfile: (state) => (profileId) => { + if (state.subscriptionsCacheForActiveProfile.profileID !== profileId) { return null } + + return state.subscriptionsCacheForActiveProfile }, - getProfileSubscriptions: () => { - return state.profileSubscriptions - } } const actions = { - updateAllSubscriptionsList ({ commit }, subscriptions) { - commit('setAllSubscriptionsList', subscriptions) + updateSubscriptionsCacheForActiveProfile: ({ commit }, payload) => { + if (payload.profileID === MAIN_PROFILE_ID) { + commit('updateSubscriptionsCacheForAllSubscriptionsProfile', { + videoList: payload.videoList, + }) + } else { + // When cache for a non default profile (the one for all subscriptions) updated + // The cache for all subscriptions could be stale at that point + commit('clearSubscriptionsCacheForAllSubscriptionsProfile') + } + + commit('updateSubscriptionsCacheForActiveProfile', payload) + }, + clearSubscriptionsCache: ({ commit }) => { + commit('clearSubscriptionsCacheForAllSubscriptionsProfile') + commit('clearSubscriptionsCacheForActiveProfile') }, - updateProfileSubscriptions ({ commit }, subscriptions) { - commit('setProfileSubscriptions', subscriptions) - } } const mutations = { - setAllSubscriptionsList (state, allSubscriptionsList) { - state.allSubscriptionsList = allSubscriptionsList + updateSubscriptionsCacheForAllSubscriptionsProfile (state, { videoList }) { + state.subscriptionsCacheForAllSubscriptionsProfile.videoList = videoList + }, + updateSubscriptionsCacheForActiveProfile (state, { profileID, videoList, errorChannels }) { + state.subscriptionsCacheForActiveProfile.profileID = profileID + state.subscriptionsCacheForActiveProfile.videoList = videoList + state.subscriptionsCacheForActiveProfile.errorChannels = errorChannels + }, + clearSubscriptionsCacheForAllSubscriptionsProfile (state) { + state.subscriptionsCacheForAllSubscriptionsProfile = deepCopy(defaultState.subscriptionsCacheForAllSubscriptionsProfile) + }, + clearSubscriptionsCacheForActiveProfile (state) { + state.subscriptionsCacheForActiveProfile = deepCopy(defaultState.subscriptionsCacheForActiveProfile) }, - setProfileSubscriptions (state, profileSubscriptions) { - state.profileSubscriptions = profileSubscriptions - } } export default { diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 5805d62441531..298e2d16875c9 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -30,7 +30,7 @@ export default defineComponent({ dataLimit: 100, videoList: [], errorChannels: [], - attemptedFetch: false + attemptedFetch: false, } }, computed: { @@ -65,13 +65,24 @@ export default defineComponent({ activeProfile: function () { return this.$store.getters.getActiveProfile }, + activeProfileId: function () { + return this.activeProfile._id + }, + + subscriptionsCacheForAllSubscriptionsProfile: function () { + return this.$store.getters.getSubscriptionsCacheForAllSubscriptionsProfile + }, + videoCacheForAllSubscriptionsProfilePresent: function () { + return this.subscriptionsCacheForAllSubscriptionsProfile.videoList.length > 0 + }, - profileSubscriptions: function () { - return this.$store.getters.getProfileSubscriptions + subscriptionsCacheForActiveProfile: function () { + return this.$store.getters.getSubscriptionsCacheForProfile(this.activeProfile._id) }, + videoCacheForActiveProfilePresent: function () { + if (this.subscriptionsCacheForActiveProfile == null) { return false } - allSubscriptionsList: function () { - return this.$store.getters.getAllSubscriptionsList + return this.subscriptionsCacheForActiveProfile.videoList.length > 0 }, historyCache: function () { @@ -92,12 +103,13 @@ export default defineComponent({ fetchSubscriptionsAutomatically: function() { return this.$store.getters.getFetchSubscriptionsAutomatically - } + }, }, watch: { activeProfile: async function (_) { - this.getProfileSubscriptions() - } + this.isLoading = true + this.loadVideosFromCacheSometimes() + }, }, mounted: async function () { document.addEventListener('keydown', this.keyboardShortcutHandler) @@ -108,43 +120,70 @@ export default defineComponent({ this.dataLimit = dataLimit } - if (this.profileSubscriptions.videoList.length !== 0) { - 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() - } - - this.isLoading = false - } else if (this.fetchSubscriptionsAutomatically) { - setTimeout(async () => { - this.getSubscriptions() - }, 300) - } else { - this.isLoading = false - } + this.loadVideosFromCacheSometimes() }, beforeDestroy: function () { document.removeEventListener('keydown', this.keyboardShortcutHandler) }, methods: { + loadVideosFromCacheSometimes() { + // Called on view visible (initial view rendering, tab switching, etc.) + if (this.videoCacheForActiveProfilePresent) { + this.loadVideosFromCacheForActiveProfile() + return + } + + if (this.videoCacheForAllSubscriptionsProfilePresent) { + this.loadVideosFromCacheForAllSubscriptionsProfile() + return + } + + this.maybeLoadVideosForSubscriptionsFromRemote() + }, + + async loadVideosFromCacheForActiveProfile() { + const subscriptionList = JSON.parse(JSON.stringify(this.subscriptionsCacheForActiveProfile)) + this.errorChannels = subscriptionList.errorChannels + 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.isLoading = false + }, + + async loadVideosFromCacheForAllSubscriptionsProfile() { + const cachedVideosFromAllSubscriptions = this.subscriptionsCacheForAllSubscriptionsProfile.videoList + // Load videos from cached videos for all subscriptions + this.videoList = await Promise.all(cachedVideosFromAllSubscriptions.filter((video) => { + const channelIndex = this.activeSubscriptionList.findIndex((subscribedChannel) => { + return subscribedChannel.id === video.authorId + }) + + if (this.hideWatchedSubs) { + const historyIndex = this.historyCache.findIndex((x) => { + return x.videoId === video.videoId + }) + + return channelIndex !== -1 && historyIndex === -1 + } else { + return channelIndex !== -1 + } + })) + this.isLoading = false + }, + goToChannel: function (id) { this.$router.push({ path: `/channel/${id}` }) }, - getSubscriptions: function () { + loadVideosForSubscriptionsFromRemote: function () { if (this.activeSubscriptionList.length === 0) { this.isLoading = false this.videoList = [] @@ -209,11 +248,6 @@ export default defineComponent({ return item.premiereDate == null }) } - const profileSubscriptions = { - activeProfile: this.activeProfile._id, - videoList: videoList, - errorChannels: this.errorChannels - } this.videoList = await Promise.all(videoList.filter((video) => { if (this.hideWatchedSubs) { @@ -226,43 +260,25 @@ export default defineComponent({ return true } })) - this.updateProfileSubscriptions(profileSubscriptions) + this.updateSubscriptionsCacheForActiveProfile({ + profileID: this.activeProfileId, + videoList: videoList, + errorChannels: this.errorChannels, + }) this.isLoading = false this.updateShowProgressBar(false) - - 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 - }) - - if (this.hideWatchedSubs) { - const historyIndex = this.historyCache.findIndex((x) => { - return x.videoId === video.videoId - }) - - return channelIndex !== -1 && historyIndex === -1 - } else { - return channelIndex !== -1 - } - })) - this.isLoading = false - } else if (this.fetchSubscriptionsAutomatically) { - this.getSubscriptions() - } else if (this.activeProfile._id === this.profileSubscriptions.activeProfile) { - this.videoList = this.profileSubscriptions.videoList + maybeLoadVideosForSubscriptionsFromRemote: async function () { + if (this.fetchSubscriptionsAutomatically) { + // `this.isLoading = false` is called inside `loadVideosForSubscriptionsFromRemote` when needed + this.loadVideosForSubscriptionsFromRemote() } else { this.videoList = [] this.attemptedFetch = false + this.isLoading = false } }, @@ -483,7 +499,7 @@ export default defineComponent({ case 'r': case 'R': if (!this.isLoading) { - this.getSubscriptions() + this.loadVideosForSubscriptionsFromRemote() } break } @@ -491,8 +507,7 @@ export default defineComponent({ ...mapActions([ 'updateShowProgressBar', - 'updateProfileSubscriptions', - 'updateAllSubscriptionsList' + 'updateSubscriptionsCacheForActiveProfile', ]), ...mapMutations([ diff --git a/src/renderer/views/Subscriptions/Subscriptions.vue b/src/renderer/views/Subscriptions/Subscriptions.vue index 23529adeb37fd..9fd269fc94383 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.vue +++ b/src/renderer/views/Subscriptions/Subscriptions.vue @@ -68,7 +68,7 @@ :title="$t('Subscriptions.Refresh Subscriptions')" :size="12" theme="primary" - @click="getSubscriptions" + @click="loadVideosForSubscriptionsFromRemote" /> From 51da2f69cf9dd241833267830907c59d338fffa4 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Thu, 15 Jun 2023 14:34:13 +0800 Subject: [PATCH 3/5] * Update subscription view to be able to load videos from video cache per channel --- src/renderer/store/modules/subscriptions.js | 66 ++---- .../views/Subscriptions/Subscriptions.js | 193 +++++++++--------- 2 files changed, 111 insertions(+), 148 deletions(-) diff --git a/src/renderer/store/modules/subscriptions.js b/src/renderer/store/modules/subscriptions.js index 4ed626ca340d9..ef2a8bd42ead3 100644 --- a/src/renderer/store/modules/subscriptions.js +++ b/src/renderer/store/modules/subscriptions.js @@ -1,14 +1,5 @@ -import { MAIN_PROFILE_ID } from '../../../constants' - -const defaultState = { - subscriptionsCacheForAllSubscriptionsProfile: { - videoList: [], - }, - subscriptionsCacheForActiveProfile: { - videoList: [], - profileID: '', - errorChannels: [], - }, +const defaultCacheEntryValueForForOneChannel = { + videos: null, } function deepCopy(obj) { @@ -16,55 +7,34 @@ function deepCopy(obj) { } const state = { - subscriptionsCacheForAllSubscriptionsProfile: deepCopy(defaultState.subscriptionsCacheForAllSubscriptionsProfile), - subscriptionsCacheForActiveProfile: deepCopy(defaultState.subscriptionsCacheForActiveProfile), + subscriptionsCachePerChannel: {}, } const getters = { - getSubscriptionsCacheForAllSubscriptionsProfile: () => { - return state.subscriptionsCacheForAllSubscriptionsProfile - }, - getSubscriptionsCacheForProfile: (state) => (profileId) => { - if (state.subscriptionsCacheForActiveProfile.profileID !== profileId) { return null } - - return state.subscriptionsCacheForActiveProfile + getSubscriptionsCacheEntriesForOneChannel: (state) => (channelId) => { + return state.subscriptionsCachePerChannel[channelId] }, } const actions = { - updateSubscriptionsCacheForActiveProfile: ({ commit }, payload) => { - if (payload.profileID === MAIN_PROFILE_ID) { - commit('updateSubscriptionsCacheForAllSubscriptionsProfile', { - videoList: payload.videoList, - }) - } else { - // When cache for a non default profile (the one for all subscriptions) updated - // The cache for all subscriptions could be stale at that point - commit('clearSubscriptionsCacheForAllSubscriptionsProfile') - } - - commit('updateSubscriptionsCacheForActiveProfile', payload) - }, clearSubscriptionsCache: ({ commit }) => { - commit('clearSubscriptionsCacheForAllSubscriptionsProfile') - commit('clearSubscriptionsCacheForActiveProfile') + commit('clearSubscriptionsCachePerChannel') + }, + + updateSubscriptionsCacheForOneChannel: ({ commit }, payload) => { + commit('updateSubscriptionsCacheForOneChannel', payload) }, } const mutations = { - updateSubscriptionsCacheForAllSubscriptionsProfile (state, { videoList }) { - state.subscriptionsCacheForAllSubscriptionsProfile.videoList = videoList - }, - updateSubscriptionsCacheForActiveProfile (state, { profileID, videoList, errorChannels }) { - state.subscriptionsCacheForActiveProfile.profileID = profileID - state.subscriptionsCacheForActiveProfile.videoList = videoList - state.subscriptionsCacheForActiveProfile.errorChannels = errorChannels - }, - clearSubscriptionsCacheForAllSubscriptionsProfile (state) { - state.subscriptionsCacheForAllSubscriptionsProfile = deepCopy(defaultState.subscriptionsCacheForAllSubscriptionsProfile) - }, - clearSubscriptionsCacheForActiveProfile (state) { - state.subscriptionsCacheForActiveProfile = deepCopy(defaultState.subscriptionsCacheForActiveProfile) + updateSubscriptionsCacheForOneChannel(state, { channelId, videos }) { + const existingObject = state.subscriptionsCachePerChannel[channelId] + const newObject = existingObject != null ? existingObject : deepCopy(defaultCacheEntryValueForForOneChannel) + if (videos != null) { newObject.videos = videos } + state.subscriptionsCachePerChannel[channelId] = newObject + }, + clearSubscriptionsCachePerChannel(state) { + state.subscriptionsCachePerChannel = {} }, } diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 298e2d16875c9..6d8a861e72d6d 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -69,20 +69,23 @@ export default defineComponent({ return this.activeProfile._id }, - subscriptionsCacheForAllSubscriptionsProfile: function () { - return this.$store.getters.getSubscriptionsCacheForAllSubscriptionsProfile - }, - videoCacheForAllSubscriptionsProfilePresent: function () { - return this.subscriptionsCacheForAllSubscriptionsProfile.videoList.length > 0 - }, + cacheEntriesForAllActiveProfileChannels() { + const entries = [] + this.activeSubscriptionList.forEach((channel) => { + const cacheEntry = this.$store.getters.getSubscriptionsCacheEntriesForOneChannel(channel.id) + if (cacheEntry == null) { return } - subscriptionsCacheForActiveProfile: function () { - return this.$store.getters.getSubscriptionsCacheForProfile(this.activeProfile._id) + entries.push(cacheEntry) + }) + return entries }, - videoCacheForActiveProfilePresent: function () { - if (this.subscriptionsCacheForActiveProfile == null) { return false } + videoCacheForAllActiveProfileChannelsPresent() { + if (this.cacheEntriesForAllActiveProfileChannels.length === 0) { return false } + if (this.cacheEntriesForAllActiveProfileChannels.length < this.activeSubscriptionList.length) { return false } - return this.subscriptionsCacheForActiveProfile.videoList.length > 0 + return this.cacheEntriesForAllActiveProfileChannels.every((cacheEntry) => { + return cacheEntry.videos != null + }) }, historyCache: function () { @@ -127,55 +130,23 @@ export default defineComponent({ }, methods: { loadVideosFromCacheSometimes() { - // Called on view visible (initial view rendering, tab switching, etc.) - if (this.videoCacheForActiveProfilePresent) { - this.loadVideosFromCacheForActiveProfile() - return - } - - if (this.videoCacheForAllSubscriptionsProfilePresent) { - this.loadVideosFromCacheForAllSubscriptionsProfile() + // This method is called on view visible + if (this.videoCacheForAllActiveProfileChannelsPresent) { + this.loadVideosFromCacheForAllActiveProfileChannels() return } this.maybeLoadVideosForSubscriptionsFromRemote() }, - async loadVideosFromCacheForActiveProfile() { - const subscriptionList = JSON.parse(JSON.stringify(this.subscriptionsCacheForActiveProfile)) - this.errorChannels = subscriptionList.errorChannels - if (this.hideWatchedSubs) { - this.videoList = await Promise.all(subscriptionList.videoList.filter((video) => { - const historyIndex = this.historyCache.findIndex((x) => { - return x.videoId === video.videoId - }) + async loadVideosFromCacheForAllActiveProfileChannels() { + const videoList = [] + this.activeSubscriptionList.forEach((channel) => { + const channelCacheEntry = this.$store.getters.getSubscriptionsCacheEntriesForOneChannel(channel.id) - return historyIndex === -1 - })) - } else { - this.videoList = subscriptionList.videoList - } - this.isLoading = false - }, - - async loadVideosFromCacheForAllSubscriptionsProfile() { - const cachedVideosFromAllSubscriptions = this.subscriptionsCacheForAllSubscriptionsProfile.videoList - // Load videos from cached videos for all subscriptions - this.videoList = await Promise.all(cachedVideosFromAllSubscriptions.filter((video) => { - const channelIndex = this.activeSubscriptionList.findIndex((subscribedChannel) => { - return subscribedChannel.id === video.authorId - }) - - if (this.hideWatchedSubs) { - const historyIndex = this.historyCache.findIndex((x) => { - return x.videoId === video.videoId - }) - - return channelIndex !== -1 && historyIndex === -1 - } else { - return channelIndex !== -1 - } - })) + videoList.push(...channelCacheEntry.videos) + }) + this.updateVideoListAfterProcessing(videoList) this.isLoading = false }, @@ -183,30 +154,48 @@ export default defineComponent({ this.$router.push({ path: `/channel/${id}` }) }, - loadVideosForSubscriptionsFromRemote: function () { + loadVideosForSubscriptionsFromRemote: async function (allowUseOfChannelCache = false) { if (this.activeSubscriptionList.length === 0) { this.isLoading = false this.videoList = [] return } + let channelsToLoadFromRemote = [...this.activeSubscriptionList] + const videoList = [] + let channelCount = 0 + this.isLoading = true + + if (allowUseOfChannelCache) { + const channelIdsLoadedFromCache = [] + channelsToLoadFromRemote.forEach((channel) => { + const channelCacheEntry = this.$store.getters.getSubscriptionsCacheEntriesForOneChannel(channel.id) + if (channelCacheEntry == null) { return } + if (channelCacheEntry.videos == null) { return } + + videoList.push(...channelCacheEntry.videos) + channelCount++ + + channelIdsLoadedFromCache.push(channel.id) + }) + // Remove all channels already loaded from cache + channelsToLoadFromRemote = channelsToLoadFromRemote.filter((c) => !channelIdsLoadedFromCache.includes(c.id)) + } + let useRss = this.useRssFeeds - if (this.activeSubscriptionList.length >= 125 && !useRss) { + if (channelsToLoadFromRemote.length >= 125 && !useRss) { showToast( this.$t('Subscriptions["This profile has a large number of subscriptions. Forcing RSS to avoid rate limiting"]'), 10000 ) useRss = true } - this.isLoading = true this.updateShowProgressBar(true) this.setProgressBarPercentage(0) this.attemptedFetch = true - let videoList = [] - let channelCount = 0 this.errorChannels = [] - this.activeSubscriptionList.forEach(async (channel) => { + const videoListFromRemote = (await Promise.all(channelsToLoadFromRemote.map(async (channel) => { let videos = [] if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') { if (useRss) { @@ -222,51 +211,54 @@ export default defineComponent({ } } - videoList = videoList.concat(videos) channelCount++ - const percentageComplete = (channelCount / this.activeSubscriptionList.length) * 100 + const percentageComplete = (channelCount / channelsToLoadFromRemote.length) * 100 this.setProgressBarPercentage(percentageComplete) + this.updateSubscriptionsCacheForOneChannel({ + channelId: channel.id, + videos: videos, + }) + return videos + }))).flatMap((o) => o) + videoList.push(...videoListFromRemote) - 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) - }) - } - if (this.hideUpcomingPremieres) { - videoList = videoList.filter(item => { - if (item.isRSS) { - // viewCount is our only method of detecting premieres in RSS - // data without sending an additional request. - // If we ever get a better flag, use it here instead. - return item.viewCount !== '0' - } - // Observed for premieres in Local API Subscriptions. - return item.premiereDate == null - }) - } + this.updateVideoListAfterProcessing(videoList) + this.isLoading = false + this.updateShowProgressBar(false) + }, - this.videoList = await Promise.all(videoList.filter((video) => { - if (this.hideWatchedSubs) { - const historyIndex = this.historyCache.findIndex((x) => { - return x.videoId === video.videoId - }) + updateVideoListAfterProcessing(videoList) { + // Filtering and sorting based in preference + videoList.sort((a, b) => { + return b.publishedDate - a.publishedDate + }) + if (this.hideLiveStreams) { + videoList = videoList.filter(item => { + return (!item.liveNow && !item.isUpcoming) + }) + } + if (this.hideUpcomingPremieres) { + videoList = videoList.filter(item => { + if (item.isRSS) { + // viewCount is our only method of detecting premieres in RSS + // data without sending an additional request. + // If we ever get a better flag, use it here instead. + return item.viewCount !== '0' + } + // Observed for premieres in Local API Subscriptions. + return item.premiereDate == null + }) + } - return historyIndex === -1 - } else { - return true - } - })) - this.updateSubscriptionsCacheForActiveProfile({ - profileID: this.activeProfileId, - videoList: videoList, - errorChannels: this.errorChannels, + this.videoList = videoList.filter((video) => { + if (this.hideWatchedSubs) { + const historyIndex = this.historyCache.findIndex((x) => { + return x.videoId === video.videoId }) - this.isLoading = false - this.updateShowProgressBar(false) + + return historyIndex === -1 + } else { + return true } }) }, @@ -274,7 +266,8 @@ export default defineComponent({ maybeLoadVideosForSubscriptionsFromRemote: async function () { if (this.fetchSubscriptionsAutomatically) { // `this.isLoading = false` is called inside `loadVideosForSubscriptionsFromRemote` when needed - this.loadVideosForSubscriptionsFromRemote() + // Also we disallow the use of local cache to avoid users expecting fresh data but getting potentially stale results + await this.loadVideosForSubscriptionsFromRemote(false) } else { this.videoList = [] this.attemptedFetch = false @@ -507,7 +500,7 @@ export default defineComponent({ ...mapActions([ 'updateShowProgressBar', - 'updateSubscriptionsCacheForActiveProfile', + 'updateSubscriptionsCacheForOneChannel', ]), ...mapMutations([ From dc85b012c14978fd662814fec416f857edbc6669 Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Fri, 16 Jun 2023 15:17:57 +0800 Subject: [PATCH 4/5] * Remove meaningless argument `allowUseOfChannelCache` --- .../views/Subscriptions/Subscriptions.js | 23 +++---------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 6d8a861e72d6d..406d36b5a28b5 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -154,34 +154,18 @@ export default defineComponent({ this.$router.push({ path: `/channel/${id}` }) }, - loadVideosForSubscriptionsFromRemote: async function (allowUseOfChannelCache = false) { + loadVideosForSubscriptionsFromRemote: async function () { if (this.activeSubscriptionList.length === 0) { this.isLoading = false this.videoList = [] return } - let channelsToLoadFromRemote = [...this.activeSubscriptionList] + const channelsToLoadFromRemote = this.activeSubscriptionList const videoList = [] let channelCount = 0 this.isLoading = true - if (allowUseOfChannelCache) { - const channelIdsLoadedFromCache = [] - channelsToLoadFromRemote.forEach((channel) => { - const channelCacheEntry = this.$store.getters.getSubscriptionsCacheEntriesForOneChannel(channel.id) - if (channelCacheEntry == null) { return } - if (channelCacheEntry.videos == null) { return } - - videoList.push(...channelCacheEntry.videos) - channelCount++ - - channelIdsLoadedFromCache.push(channel.id) - }) - // Remove all channels already loaded from cache - channelsToLoadFromRemote = channelsToLoadFromRemote.filter((c) => !channelIdsLoadedFromCache.includes(c.id)) - } - let useRss = this.useRssFeeds if (channelsToLoadFromRemote.length >= 125 && !useRss) { showToast( @@ -266,8 +250,7 @@ export default defineComponent({ maybeLoadVideosForSubscriptionsFromRemote: async function () { if (this.fetchSubscriptionsAutomatically) { // `this.isLoading = false` is called inside `loadVideosForSubscriptionsFromRemote` when needed - // Also we disallow the use of local cache to avoid users expecting fresh data but getting potentially stale results - await this.loadVideosForSubscriptionsFromRemote(false) + await this.loadVideosForSubscriptionsFromRemote() } else { this.videoList = [] this.attemptedFetch = false From ca8a8a71138c6c4b82a720e6f4509c679ec612ff Mon Sep 17 00:00:00 2001 From: PikachuEXE Date: Wed, 28 Jun 2023 09:17:42 +0800 Subject: [PATCH 5/5] $ Remove unused imports --- src/renderer/views/Subscriptions/Subscriptions.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 406d36b5a28b5..a728901ebddaa 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -8,7 +8,6 @@ import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' import FtElementList from '../../components/ft-element-list/ft-element-list.vue' import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubble.vue' -import { MAIN_PROFILE_ID } from '../../../constants' import { calculatePublishedDate, copyToClipboard, showToast } from '../../helpers/utils' import { invidiousAPICall } from '../../helpers/api/invidious' import { getLocalChannelVideos } from '../../helpers/api/local'