From 8f35f95a5b8c24624ae294efcd5f51fa728a86ba Mon Sep 17 00:00:00 2001 From: Preston Date: Tue, 1 Sep 2020 23:20:21 -0400 Subject: [PATCH] Finish Core Subscriptions logic and add more locales to profiles page --- package-lock.json | 52 +++++ package.json | 1 + .../components/ft-list-video/ft-list-video.js | 3 +- .../ft-profile-selector.css | 20 +- .../ft-profile-selector.js | 13 +- .../ft-profile-selector.vue | 4 +- .../subscription-settings.js | 16 +- .../subscription-settings.vue | 13 +- src/renderer/store/modules/settings.js | 36 ++- src/renderer/store/modules/subscriptions.js | 16 +- src/renderer/store/modules/utils.js | 2 + src/renderer/views/ProfileEdit/ProfileEdit.js | 18 +- .../views/ProfileSettings/ProfileSettings.vue | 2 +- src/renderer/views/Settings/Settings.vue | 1 + .../views/Subscriptions/Subscriptions.css | 6 + .../views/Subscriptions/Subscriptions.js | 211 +++++++++++++++--- .../views/Subscriptions/Subscriptions.vue | 17 +- static/locales/en-US.yaml | 12 +- 18 files changed, 373 insertions(+), 70 deletions(-) diff --git a/package-lock.json b/package-lock.json index 344251cc..8fdf9ba5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11136,6 +11136,14 @@ } } }, + "javascript-time-ago": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/javascript-time-ago/-/javascript-time-ago-2.0.13.tgz", + "integrity": "sha512-zH+obXUQ4vlc9UlERFe637rNJQaVYLizwODUfGzYN/cNW/owkk5wzb327gAfEXFpI4yhFcStEaoqoJtMGAmrAg==", + "requires": { + "relative-time-format": "^0.1.3" + } + }, "jest": { "version": "26.4.2", "resolved": "https://registry.npmjs.org/jest/-/jest-26.4.2.tgz", @@ -16240,6 +16248,11 @@ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", "dev": true }, + "relative-time-format": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/relative-time-format/-/relative-time-format-0.1.3.tgz", + "integrity": "sha512-0O6i4fKjsx8qhz57zorG+LrIDnF9pSvP5s7H9R1Nb5nSqih5dvRyKzNKs6MxhL3bv4iwsz4DuDwAyw+c47QFIA==" + }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -16522,6 +16535,31 @@ "sprintf-js": "^1.1.2" } }, + "rss-parser": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.9.0.tgz", + "integrity": "sha512-wlRSfGrotOXuWo19Dtl2KmQt7o9i5zzCExUrxpechE0O54BAx7JD+xhWyGumPPqiJj771ndflV3sE3bTHen0HQ==", + "requires": { + "entities": "^2.0.3", + "xml2js": "^0.4.19" + }, + "dependencies": { + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==" + } + } + }, + "rss-to-json": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rss-to-json/-/rss-to-json-1.1.1.tgz", + "integrity": "sha512-d+TwrFI5wAHbZ/fTd3Pvty14tadBjKHAjfMcUam9FWoWrC9g5rHJN9Slw10OZwk6Mey+hqdXwdmymO7d8ebVmw==", + "requires": { + "axios": "^0.19.2", + "xml2json": "^0.12.0" + } + }, "rsvp": { "version": "4.8.5", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", @@ -20249,6 +20287,15 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, "xml2json": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/xml2json/-/xml2json-0.12.0.tgz", @@ -20259,6 +20306,11 @@ "node-expat": "^2.3.18" } }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xmlchars": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", diff --git a/package.json b/package.json index 752f94ad..24fc7771 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "mediaelement": "^4.2.16", "nedb": "^1.8.0", "opml-to-json": "0.0.3", + "rss-parser": "^3.9.0", "video.js": "7.6.6", "videojs-abloop": "^1.1.2", "videojs-contrib-quality-levels": "^2.0.9", diff --git a/src/renderer/components/ft-list-video/ft-list-video.js b/src/renderer/components/ft-list-video/ft-list-video.js index d1117955..5ab2216d 100644 --- a/src/renderer/components/ft-list-video/ft-list-video.js +++ b/src/renderer/components/ft-list-video/ft-list-video.js @@ -255,7 +255,8 @@ export default Vue.extend({ liveStreamString: this.$t('Video.Watching'), upcomingString: this.$t('Video.Published.Upcoming'), isLive: this.isLive, - isUpcoming: this.data.isUpcoming + isUpcoming: this.data.isUpcoming, + isRSS: this.data.isRSS }).then((data) => { this.uploadedTime = data }).catch((error) => { diff --git a/src/renderer/components/ft-profile-selector/ft-profile-selector.css b/src/renderer/components/ft-profile-selector/ft-profile-selector.css index f630dc0c..1d4559f5 100644 --- a/src/renderer/components/ft-profile-selector/ft-profile-selector.css +++ b/src/renderer/components/ft-profile-selector/ft-profile-selector.css @@ -1,6 +1,6 @@ .colorOption { - width: 50px; - height: 50px; + width: 40px; + height: 40px; margin: 10px; cursor: pointer; border-radius: 200px 200px 200px 200px; @@ -8,10 +8,10 @@ } .initial { - font-size: 25px; + font-size: 20px; text-align: center; position: relative; - bottom: 27px; + bottom: 30px; } #profileList { @@ -39,10 +39,18 @@ .profile { cursor: pointer; + height: 50px; + -webkit-transition: background 0.2s ease-out; + -moz-transition: background 0.2s ease-out; + -o-transition: background 0.2s ease-out; + transition: background 0.2s ease-out; } .profile:hover { background-color: var(--side-nav-hover-color); + -moz-transition: background 0.2s ease-in; + -o-transition: background 0.2s ease-in; + transition: background 0.2s ease-in; } .profile .colorOption { @@ -51,6 +59,10 @@ bottom: 5px; } +.profileName { + line-height: 50px; +} + .profileListTitle { position: absolute; top: -15px; diff --git a/src/renderer/components/ft-profile-selector/ft-profile-selector.js b/src/renderer/components/ft-profile-selector/ft-profile-selector.js index f63d5aa0..218e7434 100644 --- a/src/renderer/components/ft-profile-selector/ft-profile-selector.js +++ b/src/renderer/components/ft-profile-selector/ft-profile-selector.js @@ -36,6 +36,16 @@ export default Vue.extend({ } }, mounted: function () { + setTimeout(() => { + const profileIndex = this.profileList.findIndex((profile) => { + return profile._id === this.defaultProfile + }) + + if (profileIndex !== -1) { + this.updateActiveProfile(profileIndex) + } + }, 100) + $('#profileList').focusout(() => { $('#profileList')[0].style.display = 'none' }) @@ -65,8 +75,9 @@ export default Vue.extend({ return } this.updateActiveProfile(index) + const message = this.$t('Profile.$ is now the active profile').replace('$', profile.name) this.showToast({ - message: `${profile.name} is now the active profile` + message: message }) $('#profileList').focusout() }, diff --git a/src/renderer/components/ft-profile-selector/ft-profile-selector.vue b/src/renderer/components/ft-profile-selector/ft-profile-selector.vue index e8c864d3..8f865446 100644 --- a/src/renderer/components/ft-profile-selector/ft-profile-selector.vue +++ b/src/renderer/components/ft-profile-selector/ft-profile-selector.vue @@ -44,7 +44,9 @@ {{ profileInitials[index] }}

-

+

{{ profile.name }}

diff --git a/src/renderer/components/subscription-settings/subscription-settings.js b/src/renderer/components/subscription-settings/subscription-settings.js index 7d5d2ef7..5c8fe9e0 100644 --- a/src/renderer/components/subscription-settings/subscription-settings.js +++ b/src/renderer/components/subscription-settings/subscription-settings.js @@ -1,4 +1,5 @@ import Vue from 'vue' +import { mapActions } from 'vuex' import FtCard from '../ft-card/ft-card.vue' import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue' import FtButton from '../ft-button/ft-button.vue' @@ -27,9 +28,18 @@ export default Vue.extend({ ] } }, - methods: { - goToChannel: function () { - console.log('TODO: Handle goToChannel') + computed: { + hideWatchedSubs: function () { + return this.$store.getters.getHideWatchedSubs + }, + useRssFeeds: function () { + return this.$store.getters.getUseRssFeeds } + }, + methods: { + ...mapActions([ + 'updateHideWatchedSubs', + 'updateUseRssFeeds' + ]) } }) diff --git a/src/renderer/components/subscription-settings/subscription-settings.vue b/src/renderer/components/subscription-settings/subscription-settings.vue index cdc82dc3..aa1c2e79 100644 --- a/src/renderer/components/subscription-settings/subscription-settings.vue +++ b/src/renderer/components/subscription-settings/subscription-settings.vue @@ -5,16 +5,24 @@

- {{ title }} + {{ $t("Settings.Subscription Settings.Subscription Settings") }}

+
diff --git a/src/renderer/store/modules/settings.js b/src/renderer/store/modules/settings.js index ab3acbc4..f51346f1 100644 --- a/src/renderer/store/modules/settings.js +++ b/src/renderer/store/modules/settings.js @@ -57,6 +57,7 @@ const state = { debugMode: false, disctractionFreeMode: false, hideWatchedSubs: false, + useRssFeeds: false, usingElectron: true } @@ -157,13 +158,21 @@ const getters = { return state.defaultQuality }, + getHideWatchedSubs: () => { + return state.hideWatchedSubs + }, + + getUseRssFeeds: () => { + return state.useRssFeeds + }, + getUsingElectron: () => { return state.usingElectron } } const actions = { - grabUserSettings ({ dispatch, commit }) { + grabUserSettings ({ dispatch, commit, rootState }) { settingsDb.find({}, (err, results) => { if (!err) { console.log(results) @@ -206,6 +215,12 @@ const actions = { case 'barColor': commit('setBarColor', result.value) break + case 'hideWatchedSubs': + commit('setHideWatchedSubs', result.value) + break + case 'useRssFeeds': + commit('setUseRssFeeds', result.value) + break case 'rememberHistory': commit('setRememberHistory', result.value) break @@ -341,6 +356,22 @@ const actions = { }) }, + updateHideWatchedSubs ({ commit }, hideWatchedSubs) { + settingsDb.update({ _id: 'hideWatchedSubs' }, { _id: 'hideWatchedSubs', value: hideWatchedSubs }, { upsert: true }, (err, numReplaced) => { + if (!err) { + commit('setHideWatchedSubs', hideWatchedSubs) + } + }) + }, + + updateUseRssFeeds ({ commit }, useRssFeeds) { + settingsDb.update({ _id: 'useRssFeeds' }, { _id: 'useRssFeeds', value: useRssFeeds }, { upsert: true }, (err, numReplaced) => { + if (!err) { + commit('setUseRssFeeds', useRssFeeds) + } + }) + }, + updateRememberHistory ({ commit }, history) { settingsDb.update({ _id: 'rememberHistory' }, { _id: 'rememberHistory', value: history }, { upsert: true }, (err, numReplaced) => { if (!err) { @@ -546,6 +577,9 @@ const mutations = { setHideWatchedSubs (state, hideWatchedSubs) { state.hideWatchedSubs = hideWatchedSubs }, + setUseRssFeeds (state, useRssFeeds) { + state.useRssFeeds = useRssFeeds + }, setUsingElectron (state, usingElectron) { state.usingElectron = usingElectron }, diff --git a/src/renderer/store/modules/subscriptions.js b/src/renderer/store/modules/subscriptions.js index 84e36201..6bbf944c 100644 --- a/src/renderer/store/modules/subscriptions.js +++ b/src/renderer/store/modules/subscriptions.js @@ -1,7 +1,5 @@ -import ytch from 'yt-channel-info' - const state = { - subscriptions: [], + allSubscriptionsList: [], profileSubscriptions: { activeProfile: 0, videoList: [] @@ -9,8 +7,8 @@ const state = { } const getters = { - getSubscriptions: () => { - return state.subscriptions + getAllSubscriptionsList: () => { + return state.allSubscriptionsList }, getProfileSubscriptions: () => { return state.profileSubscriptions @@ -18,8 +16,8 @@ const getters = { } const actions = { - updateSubscriptions ({ commit }, subscriptions) { - commit('setSubscriptions', subscriptions) + updateAllSubscriptionsList ({ commit }, subscriptions) { + commit('setAllSubscriptionsList', subscriptions) }, updateProfileSubscriptions ({ commit }, subscriptions) { commit('setProfileSubscriptions', subscriptions) @@ -27,8 +25,8 @@ const actions = { } const mutations = { - setSubscriptions (state, subscriptions) { - state.subscriptions = subscriptions + setAllSubscriptionsList (state, allSubscriptionsList) { + state.allSubscriptionsList = allSubscriptionsList }, setProfileSubscriptions (state, profileSubscriptions) { state.profileSubscriptions = profileSubscriptions diff --git a/src/renderer/store/modules/utils.js b/src/renderer/store/modules/utils.js index 2ecd99d4..bfa780fc 100644 --- a/src/renderer/store/modules/utils.js +++ b/src/renderer/store/modules/utils.js @@ -265,6 +265,8 @@ const actions = { } else if (payload.isUpcoming || payload.publishText === null) { // the check for null is currently just an inferring of knowledge, because there is no other possibility left return payload.upcomingString + } else if (payload.isRSS) { + return payload.publishText } const strings = payload.publishText.split(' ') const singular = (strings[0] === '1') diff --git a/src/renderer/views/ProfileEdit/ProfileEdit.js b/src/renderer/views/ProfileEdit/ProfileEdit.js index 28fdbf05..aece2bd6 100644 --- a/src/renderer/views/ProfileEdit/ProfileEdit.js +++ b/src/renderer/views/ProfileEdit/ProfileEdit.js @@ -63,7 +63,7 @@ export default Vue.extend({ this.isLoading = true const profileType = this.$route.name - this.deletePromptLabel = 'Are you sure you want to delete this profile? All subscriptions in this profile will also be deleted.' + this.deletePromptLabel = `${this.$t('Profile.Are you sure you want to delete this profile?')} ${this.$t('Profile["All subscriptions will also be deleted."]')}` if (profileType === 'newProfile') { this.isNew = true @@ -78,7 +78,7 @@ export default Vue.extend({ this.grabProfileInfo(this.profileId).then((profile) => { if (profile === null) { this.showToast({ - message: 'Profile could not be found' + message: this.$t('Profile.Profile could not be found') }) this.$router.push({ path: '/settings/profile/' @@ -108,7 +108,7 @@ export default Vue.extend({ saveProfile: function () { if (this.profileName === '') { this.showToast({ - message: 'Your profile name cannot be empty' + message: this.$t('Profile.Your profile name cannot be empty') }) return } @@ -129,34 +129,36 @@ export default Vue.extend({ if (this.isNew) { this.showToast({ - message: 'Profile has been created' + message: this.$t('Profile.Profile has been created') }) this.$router.push({ path: '/settings/profile/' }) } else { this.showToast({ - message: 'Profile has been updated' + message: this.$t('Profile.Profile has been updated') }) } }, setDefaultProfile: function () { this.updateDefaultProfile(this.profileId) + const message = this.$t('Profile.Your default profile has been set to $').replace('$', this.profileName) this.showToast({ - message: `Your default profile has been set to ${this.profileName}` + message: message }) }, deleteProfile: function () { this.removeProfile(this.profileId) + const message = this.$t('Profile.Removed $ from your profiles').replace('$', this.profileName) this.showToast({ - message: `Removed ${this.profileName} from your profiles` + message: message }) if (this.defaultProfile === this.profileId) { this.updateDefaultProfile('allChannels') this.showToast({ - message: 'Your default profile has been set your Primary profile' + message: this.$t('Profile.Your default profile has been changed to your primary profile') }) } if (this.activeProfile._id === this.profileId) { diff --git a/src/renderer/views/ProfileSettings/ProfileSettings.vue b/src/renderer/views/ProfileSettings/ProfileSettings.vue index b03cd6c4..b1e0b605 100644 --- a/src/renderer/views/ProfileSettings/ProfileSettings.vue +++ b/src/renderer/views/ProfileSettings/ProfileSettings.vue @@ -16,7 +16,7 @@ diff --git a/src/renderer/views/Settings/Settings.vue b/src/renderer/views/Settings/Settings.vue index 665ad161..16f22727 100644 --- a/src/renderer/views/Settings/Settings.vue +++ b/src/renderer/views/Settings/Settings.vue @@ -3,6 +3,7 @@ + diff --git a/src/renderer/views/Subscriptions/Subscriptions.css b/src/renderer/views/Subscriptions/Subscriptions.css index b6db9095..76a3d760 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.css +++ b/src/renderer/views/Subscriptions/Subscriptions.css @@ -8,6 +8,12 @@ color: var(--tertiary-text-color); } +.floatingTopButton { + position: absolute; + top: 70px; + right: 10px; +} + @media only screen and (max-width: 680px) { .card { width: 90%; diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index 278a1d10..fc187453 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -2,16 +2,21 @@ import Vue from 'vue' import { mapActions, mapMutations } from 'vuex' import FtLoader from '../../components/ft-loader/ft-loader.vue' 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' import FtElementList from '../../components/ft-element-list/ft-element-list.vue' import ytch from 'yt-channel-info' +import Parser from 'rss-parser' export default Vue.extend({ name: 'Subscriptions', components: { 'ft-loader': FtLoader, 'ft-card': FtCard, + 'ft-button': FtButton, + 'ft-icon-button': FtIconButton, 'ft-flex-box': FtFlexBox, 'ft-element-list': FtElementList }, @@ -23,6 +28,10 @@ export default Vue.extend({ } }, computed: { + usingElectron: function () { + return this.$store.getters.getUsingElectron + }, + backendPreference: function () { return this.$store.getters.getBackendPreference }, @@ -31,10 +40,30 @@ export default Vue.extend({ return this.$store.getters.getBackendFallback }, + invidiousInstance: function () { + return this.$store.getters.getInvidiousInstance + }, + + 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 }, @@ -43,50 +72,99 @@ export default Vue.extend({ return this.$store.getters.getProfileSubscriptions }, + allSubscriptionsList: function () { + return this.$store.getters.getAllSubscriptionsList + }, + + historyCache: function () { + return this.$store.getters.getHistoryCache + }, + activeSubscriptionList: function () { return this.profileList[this.activeProfile].subscriptions - }, - - allSubscriptionsList: function () { - return this.profileList[0].subscriptions - }, - - sortedVideoList: function () { - const profileSubscriptions = JSON.parse(JSON.stringify(this.profileSubscriptions)) - return profileSubscriptions.videoList.sort((a, b) => { - if (a.title.toLowerCase() > b.title.toLowerCase()) { - return -1 - } - - if (a.title.toLowerCase() < b.title.toLowerCase()) { - return 1 - } - - console.log(a.title) - - return 0 - }) } }, - mounted: function () { - setTimeout(() => { - this.fetchActiveSubscriptionsLocal() - }, 1000) + watch: { + activeProfile: async function (val) { + 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() + } + } + }, + mounted: async function () { + this.isLoading = true + const dataLimit = sessionStorage.getItem('subscriptionLimit') + if (dataLimit !== null) { + this.dataLimit = dataLimit + } + setTimeout(async () => { + if (this.profileSubscriptions.videoList.length === 0) { + this.getSubscriptions() + } else { + 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.isLoading = false + } + }, 200) }, methods: { - fetchActiveSubscriptionsLocal: function () { + getSubscriptions: function () { if (this.activeSubscriptionList.length === 0) { + this.isLoading = false + this.videoList = [] return } this.isLoading = true this.updateShowProgressBar(true) + this.setProgressBarPercentage(0) let videoList = [] let channelCount = 0 this.activeSubscriptionList.forEach(async (channel) => { - const videos = await this.getChannelVideosLocalScraper(channel.id) - console.log(videos) + let videos = [] + + if (!this.usingElectron || this.backendPreference === 'invidious') { + if (this.useRssFeeds) { + videos = await this.getChannelVideosInvidiousRSS(channel.id) + } else { + videos = await this.getChannelVideosInvidiousScraper(channel.id) + } + } else { + if (this.useRssFeeds) { + videos = await this.getChannelVideosLocalRSS(channel.id) + } else { + videos = await this.getChannelVideosLocalScraper(channel.id) + } + } videoList = videoList.concat(videos) channelCount++ @@ -103,9 +181,24 @@ export default Vue.extend({ videoList: videoList } + 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) + + if (this.activeProfile === 0) { + this.updateAllSubscriptionsList(profileSubscriptions.videoList) + } } }) }, @@ -135,25 +228,75 @@ export default Vue.extend({ }, getChannelVideosLocalRSS: function (channelId) { - console.log('TODO') - }, + return new Promise((resolve, reject) => { + const parser = new Parser() + const feedUrl = `https://www.youtube.com/feeds/videos.xml?channel_id=${channelId}` - fetchActiveSubscriptionsInvidious: function () { - console.log('TODO') + parser.parseURL(feedUrl).then(async (feed) => { + resolve(await Promise.all(feed.items.map((video) => { + video.authorId = channelId + 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.log(err) + resolve([]) + }) + }) }, getChannelVideosInvidiousScraper: function (channelId) { - console.log('TODO') + return new Promise((resolve, reject) => { + const subscriptionsPayload = { + resource: 'channels/latest', + id: channelId, + params: {} + } + + this.invidiousAPICall(subscriptionsPayload).then((result) => { + resolve(result) + }) + }) }, getChannelVideosInvidiousRSS: function (channelId) { - console.log('TODO') + return new Promise((resolve, reject) => { + const parser = new Parser() + const feedUrl = `${this.invidiousInstance}/feed/channel/${channelId}` + + parser.parseURL(feedUrl).then(async (feed) => { + resolve(await Promise.all(feed.items.map((video) => { + video.authorId = channelId + 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 + }))) + }) + }) + }, + + increaseLimit: function () { + this.dataLimit += 100 + sessionStorage.setItem('subscriptionLimit', this.dataLimit) }, ...mapActions([ 'showToast', + 'invidiousAPICall', 'updateShowProgressBar', 'updateProfileSubscriptions', + 'updateAllSubscriptionsList', 'calculatePublishedDate' ]), diff --git a/src/renderer/views/Subscriptions/Subscriptions.vue b/src/renderer/views/Subscriptions/Subscriptions.vue index 4f31f6ce..85137098 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.vue +++ b/src/renderer/views/Subscriptions/Subscriptions.vue @@ -10,20 +10,20 @@ >

{{ $t("Subscriptions.Subscriptions") }}

- {{ $t("History['Your history list is currently empty.']") }} + {{ $t("Subscriptions['Your Subscription list is currently empty. Start adding subscriptions to see them here.']") }}

+ diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index 0769a239..99394fd8 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -70,7 +70,8 @@ Subscriptions: Latest Subscriptions: Latest Subscriptions 'Your Subscription list is currently empty. Start adding subscriptions to see them here.': Your Subscription list is currently empty. Start adding subscriptions to see them here. - 'Getting Subscriptions. Please wait.': Getting Subscriptions. Please wait. + 'Getting Subscriptions. Please wait.': Getting Subscriptions. Please wait. + Refresh Subscriptions: Refresh Subscriptions Trending: Trending Most Popular: Most Popular Playlists: Playlists @@ -180,6 +181,7 @@ Settings: Subscription Settings: Subscription Settings: Subscription Settings Hide Videos on Watch: Hide Videos on Watch + Fetch Feeds from RSS: Fetch Feeds from RSS Subscriptions Export Format: Subscriptions Export Format: Subscriptions Export Format #& Freetube @@ -260,6 +262,14 @@ Profile: Delete Profile: Delete Profile Are you sure you want to delete this profile?: Are you sure you want to delete this profile? All subscriptions will also be deleted.: All subscriptions will also be deleted. + Profile could not be found: Profile could not be found + Your profile name cannot be empty: Your profile name cannot be empty + Profile has been created: Profile has been created + Profile has been updated: Profile has been updated + Your default profile has been set to $: Your default profile has been set to $ + Removed $ from your profiles: Removed $ from your profiles + Your default profile has been changed to your primary profile: Your default profile has been changed to your primary profile + $ is now the active profile: $ is now the active profile #On Channel Page Channel: Subscriber: Subscriber