diff --git a/src/renderer/App.js b/src/renderer/App.js index 3e2074cd..e44fdace 100644 --- a/src/renderer/App.js +++ b/src/renderer/App.js @@ -1,5 +1,5 @@ import Vue from 'vue' -import { mapActions } from 'vuex' +import { mapActions, mapMutations } from 'vuex' import { ObserveVisibility } from 'vue-observe-visibility' import FtFlexBox from './components/ft-flex-box/ft-flex-box.vue' import TopNav from './components/top-nav/top-nav.vue' @@ -79,10 +79,18 @@ export default Vue.extend({ }, externalPlayer: function () { return this.$store.getters.getExternalPlayer + }, + defaultInvidiousInstance: function () { + return this.$store.getters.getDefaultInvidiousInstance } }, mounted: function () { - this.grabUserSettings().then(() => { + this.grabUserSettings().then(async () => { + await this.fetchInvidiousInstances() + if (this.defaultInvidiousInstance === '') { + await this.setRandomCurrentInvidiousInstance() + } + this.grabAllProfiles(this.$t('Profile.All Channels')).then(async () => { this.grabHistory() this.grabAllPlaylists() @@ -378,6 +386,10 @@ export default Vue.extend({ } }, + ...mapMutations([ + 'setInvidiousInstancesList' + ]), + ...mapActions([ 'showToast', 'openExternalLink', @@ -387,6 +399,8 @@ export default Vue.extend({ 'grabAllPlaylists', 'getYoutubeUrlInfo', 'getExternalPlayerCmdArgumentsData', + 'fetchInvidiousInstances', + 'setRandomCurrentInvidiousInstance', 'setupListenerToSyncWindows' ]) } diff --git a/src/renderer/components/data-settings/data-settings.js b/src/renderer/components/data-settings/data-settings.js index 8c348762..a7c7f377 100644 --- a/src/renderer/components/data-settings/data-settings.js +++ b/src/renderer/components/data-settings/data-settings.js @@ -46,8 +46,8 @@ export default Vue.extend({ backendFallback: function () { return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, profileList: function () { return this.$store.getters.getProfileList diff --git a/src/renderer/components/ft-list-channel/ft-list-channel.js b/src/renderer/components/ft-list-channel/ft-list-channel.js index 93f0b117..51639d56 100644 --- a/src/renderer/components/ft-list-channel/ft-list-channel.js +++ b/src/renderer/components/ft-list-channel/ft-list-channel.js @@ -24,8 +24,8 @@ export default Vue.extend({ } }, computed: { - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, listType: function () { return this.$store.getters.getListType @@ -66,7 +66,7 @@ export default Vue.extend({ }, parseInvidiousData: function () { - this.thumbnail = this.data.authorThumbnails[2].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + this.thumbnail = this.data.authorThumbnails[2].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) this.channelName = this.data.author this.id = this.data.authorId if (this.hideChannelSubscriptions) { diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js index 1d941d12..d6305b9e 100644 --- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js +++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js @@ -29,8 +29,8 @@ export default Vue.extend({ } }, computed: { - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, listType: function () { @@ -79,7 +79,7 @@ export default Vue.extend({ parseInvidiousData: function () { this.title = this.data.title - this.thumbnail = this.data.playlistThumbnail.replace('https://i.ytimg.com', this.invidiousInstance).replace('hqdefault', 'mqdefault') + this.thumbnail = this.data.playlistThumbnail.replace('https://i.ytimg.com', this.currentInvidiousInstance).replace('hqdefault', 'mqdefault') this.channelName = this.data.author this.channelLink = this.data.authorUrl this.playlistLink = this.data.playlistId 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 b791d94c..b114947d 100644 --- a/src/renderer/components/ft-list-video/ft-list-video.js +++ b/src/renderer/components/ft-list-video/ft-list-video.js @@ -92,8 +92,8 @@ export default Vue.extend({ return this.$store.getters.getBackendPreference }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, inHistory: function () { @@ -103,11 +103,11 @@ export default Vue.extend({ }, invidiousUrl: function () { - return `${this.invidiousInstance}/watch?v=${this.id}` + return `${this.currentInvidiousInstance}/watch?v=${this.id}` }, invidiousChannelUrl: function () { - return `${this.invidiousInstance}/channel/${this.channelId}` + return `${this.currentInvidiousInstance}/channel/${this.channelId}` }, youtubeUrl: function () { @@ -156,7 +156,7 @@ export default Vue.extend({ thumbnail: function () { let baseUrl if (this.backendPreference === 'invidious') { - baseUrl = this.invidiousInstance + baseUrl = this.currentInvidiousInstance } else { baseUrl = 'https://i.ytimg.com' } diff --git a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js index d5740bcb..be061a47 100644 --- a/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js +++ b/src/renderer/components/ft-profile-channel-list/ft-profile-channel-list.js @@ -42,8 +42,8 @@ export default Vue.extend({ backendPreference: function () { return this.$store.getters.getBackendPreference }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, profileList: function () { return this.$store.getters.getProfileList @@ -80,7 +80,7 @@ export default Vue.extend({ return 0 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) } channel.selected = false return channel @@ -101,7 +101,7 @@ export default Vue.extend({ return 0 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) } channel.selected = false return channel diff --git a/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js b/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js index 6ab9fdba..9fe3146a 100644 --- a/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js +++ b/src/renderer/components/ft-profile-filter-channels-list/ft-profile-filter-channels-list.js @@ -35,8 +35,8 @@ export default Vue.extend({ backendPreference: function () { return this.$store.getters.getBackendPreference }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, profileList: function () { return this.$store.getters.getProfileList @@ -73,7 +73,7 @@ export default Vue.extend({ return index === -1 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) } channel.selected = false return channel @@ -100,7 +100,7 @@ export default Vue.extend({ return index === -1 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) } channel.selected = false return channel diff --git a/src/renderer/components/ft-share-button/ft-share-button.js b/src/renderer/components/ft-share-button/ft-share-button.js index 8ca4700c..0efc7f15 100644 --- a/src/renderer/components/ft-share-button/ft-share-button.js +++ b/src/renderer/components/ft-share-button/ft-share-button.js @@ -34,12 +34,12 @@ export default Vue.extend({ } }, computed: { - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, invidiousURL() { - let videoUrl = `${this.invidiousInstance}/watch?v=${this.id}` + let videoUrl = `${this.currentInvidiousInstance}/watch?v=${this.id}` // `playlistId` can be undefined if (this.playlistId && this.playlistId.length !== 0) { // `index` seems can be ignored @@ -49,7 +49,7 @@ export default Vue.extend({ }, invidiousEmbedURL() { - return `${this.invidiousInstance}/embed/${this.id}` + return `${this.currentInvidiousInstance}/embed/${this.id}` }, youtubeURL() { diff --git a/src/renderer/components/general-settings/general-settings.js b/src/renderer/components/general-settings/general-settings.js index bb74a52c..8082da5a 100644 --- a/src/renderer/components/general-settings/general-settings.js +++ b/src/renderer/components/general-settings/general-settings.js @@ -1,11 +1,11 @@ import Vue from 'vue' -import $ from 'jquery' -import { mapActions } from 'vuex' +import { mapActions, mapMutations } from 'vuex' import FtCard from '../ft-card/ft-card.vue' import FtSelect from '../ft-select/ft-select.vue' import FtInput from '../ft-input/ft-input.vue' import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue' import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' +import FtButton from '../ft-button/ft-button.vue' import debounce from 'lodash.debounce' @@ -16,11 +16,11 @@ export default Vue.extend({ 'ft-select': FtSelect, 'ft-input': FtInput, 'ft-toggle-switch': FtToggleSwitch, - 'ft-flex-box': FtFlexBox + 'ft-flex-box': FtFlexBox, + 'ft-button': FtButton }, data: function () { return { - showInvidiousInstances: false, instanceNames: [], instanceValues: [], backendValues: [ @@ -62,8 +62,8 @@ export default Vue.extend({ return this.$store.getters.getUsingElectron }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, enableSearchSuggestions: function () { return this.$store.getters.getEnableSearchSuggestions @@ -101,6 +101,12 @@ export default Vue.extend({ regionValues: function () { return this.$store.getters.getRegionValues }, + invidiousInstancesList: function () { + return this.$store.getters.getInvidiousInstancesList + }, + defaultInvidiousInstance: function () { + return this.$store.getters.getDefaultInvidiousInstance + }, localeOptions: function () { return ['system'].concat(Object.keys(this.$i18n.messages)) @@ -147,44 +153,42 @@ export default Vue.extend({ } }, mounted: function () { - const requestUrl = 'https://api.invidious.io/instances.json' - $.getJSON(requestUrl, (response) => { - console.log(response) - const instances = response.filter((instance) => { - if (instance[0].includes('.onion') || instance[0].includes('.i2p') || instance[0].includes('yewtu.be')) { - return false - } else { - return true - } - }) - - this.instanceNames = instances.map((instance) => { - return instance[0] - }) - - this.instanceValues = instances.map((instance) => { - return instance[1].uri.replace(/\/$/, '') - }) - - this.showInvidiousInstances = true - }).fail((xhr, textStatus, error) => { - console.log(xhr) - console.log(textStatus) - console.log(requestUrl) - console.log(error) - }) - - this.updateInvidiousInstanceBounce = debounce(this.updateInvidiousInstance, 500) + this.setCurrentInvidiousInstanceBounce = + debounce(this.setCurrentInvidiousInstance, 500) }, beforeDestroy: function () { - if (this.invidiousInstance === '') { - this.updateInvidiousInstance('https://invidious.snopyta.org') + if (this.currentInvidiousInstance === '') { + // FIXME: If we call an action from here, there's no guarantee it will finish + // before the component is destroyed, which could bring up some problems + // Since I can't see any way to await it (because lifecycle hooks must be + // synchronous), unfortunately, we have to copy/paste the logic + // from the `setRandomCurrentInvidiousInstance` action onto here + const instanceList = this.invidiousInstancesList + const randomIndex = Math.floor(Math.random() * instanceList.length) + this.setCurrentInvidiousInstance(instanceList[randomIndex]) } }, methods: { handleInvidiousInstanceInput: function (input) { - const invidiousInstance = input.replace(/\/$/, '') - this.updateInvidiousInstanceBounce(invidiousInstance) + const instance = input.replace(/\/$/, '') + this.setCurrentInvidiousInstanceBounce(instance) + }, + + handleSetDefaultInstanceClick: function () { + const instance = this.currentInvidiousInstance + this.updateDefaultInvidiousInstance(instance) + + const message = this.$t('Default Invidious instance has been set to $') + this.showToast({ + message: message.replace('$', instance) + }) + }, + + handleClearDefaultInstanceClick: function () { + this.updateDefaultInvidiousInstance('') + this.showToast({ + message: this.$t('Default Invidious instance has been cleared') + }) }, handlePreferredApiBackend: function (backend) { @@ -196,6 +200,10 @@ export default Vue.extend({ } }, + ...mapMutations([ + 'setCurrentInvidiousInstance' + ]), + ...mapActions([ 'showToast', 'updateEnableSearchSuggestions', @@ -204,11 +212,11 @@ export default Vue.extend({ 'updateCheckForBlogPosts', 'updateBarColor', 'updateBackendPreference', + 'updateDefaultInvidiousInstance', 'updateLandingPage', 'updateRegion', 'updateListType', 'updateThumbnailPreference', - 'updateInvidiousInstance', 'updateForceLocalBackendForLegacy', 'updateCurrentLocale' ]) diff --git a/src/renderer/components/general-settings/general-settings.vue b/src/renderer/components/general-settings/general-settings.vue index c6d94553..cc4b26fb 100644 --- a/src/renderer/components/general-settings/general-settings.vue +++ b/src/renderer/components/general-settings/general-settings.vue @@ -88,21 +88,47 @@ - - {{ $t('Settings.General Settings.View all Invidious instance information') }} - +
+ + {{ $t('Settings.General Settings.View all Invidious instance information') }} + +
+
+

+ {{ $t('Settings.General Settings.The currently set default instance is $').replace('$', defaultInvidiousInstance) }} +

+ + + + diff --git a/src/renderer/components/playlist-info/playlist-info.js b/src/renderer/components/playlist-info/playlist-info.js index d94b3599..e2234343 100644 --- a/src/renderer/components/playlist-info/playlist-info.js +++ b/src/renderer/components/playlist-info/playlist-info.js @@ -35,8 +35,8 @@ export default Vue.extend({ } }, computed: { - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, listType: function () { @@ -95,7 +95,7 @@ export default Vue.extend({ methods: { sharePlaylist: function (method) { const youtubeUrl = `https://youtube.com/playlist?list=${this.id}` - const invidiousUrl = `${this.invidiousInstance}/playlist?list=${this.id}` + const invidiousUrl = `${this.currentInvidiousInstance}/playlist?list=${this.id}` switch (method) { case 'copyYoutube': diff --git a/src/renderer/components/side-nav/side-nav.js b/src/renderer/components/side-nav/side-nav.js index 9d74e467..d5a52d41 100644 --- a/src/renderer/components/side-nav/side-nav.js +++ b/src/renderer/components/side-nav/side-nav.js @@ -15,8 +15,8 @@ export default Vue.extend({ backendPreference: function () { return this.$store.getters.getBackendPreference }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, profileList: function () { return this.$store.getters.getProfileList @@ -38,7 +38,7 @@ export default Vue.extend({ return 0 }).map((channel) => { if (this.backendPreference === 'invidious') { - channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + channel.thumbnail = channel.thumbnail.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) } return channel diff --git a/src/renderer/components/top-nav/top-nav.js b/src/renderer/components/top-nav/top-nav.js index 380ebfe2..4279455a 100644 --- a/src/renderer/components/top-nav/top-nav.js +++ b/src/renderer/components/top-nav/top-nav.js @@ -44,8 +44,8 @@ export default Vue.extend({ return this.$store.getters.getBarColor }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, backendFallback: function () { diff --git a/src/renderer/components/watch-video-comments/watch-video-comments.js b/src/renderer/components/watch-video-comments/watch-video-comments.js index c6f60db4..b4e46886 100644 --- a/src/renderer/components/watch-video-comments/watch-video-comments.js +++ b/src/renderer/components/watch-video-comments/watch-video-comments.js @@ -50,8 +50,8 @@ export default Vue.extend({ return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, hideCommentLikes: function () { return this.$store.getters.getHideCommentLikes @@ -276,7 +276,7 @@ export default Vue.extend({ const commentData = response.comments.map((comment) => { comment.showReplies = false comment.authorLink = comment.authorId - comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) if (this.hideCommentLikes) { comment.likes = null } else { @@ -342,7 +342,7 @@ export default Vue.extend({ const commentData = response.comments.map((comment) => { comment.showReplies = false comment.authorLink = comment.authorId - comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + comment.authorThumb = comment.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) if (this.hideCommentLikes) { comment.likes = null } else { diff --git a/src/renderer/components/watch-video-info/watch-video-info.js b/src/renderer/components/watch-video-info/watch-video-info.js index ef307690..918d901e 100644 --- a/src/renderer/components/watch-video-info/watch-video-info.js +++ b/src/renderer/components/watch-video-info/watch-video-info.js @@ -126,8 +126,8 @@ export default Vue.extend({ } }, computed: { - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, profileList: function () { diff --git a/src/renderer/sass-partials/_settings.sass b/src/renderer/sass-partials/_settings.sass index b9c52397..1a9cdf3c 100644 --- a/src/renderer/sass-partials/_settings.sass +++ b/src/renderer/sass-partials/_settings.sass @@ -24,6 +24,9 @@ @media only screen and (max-width: 680px) width: 90% +.center + text-align: center + @media only screen and (max-width: 460px) .generalSettingsFlexBox, .playerSettingsFlexBox, .externalPlayerSettingsFlexBox justify-content: flex-start diff --git a/src/renderer/store/modules/invidious.js b/src/renderer/store/modules/invidious.js index 3ca52392..88380f53 100644 --- a/src/renderer/store/modules/invidious.js +++ b/src/renderer/store/modules/invidious.js @@ -1,19 +1,58 @@ import $ from 'jquery' const state = { + currentInvidiousInstance: '', + invidiousInstancesList: null, isGetChannelInfoRunning: false } const getters = { - getIsGetChannelInfoRunning (state) { + getIsGetChannelInfoRunning(state) { return state.isGetChannelInfoRunning + }, + + getCurrentInvidiousInstance(state) { + return state.currentInvidiousInstance + }, + + getInvidiousInstancesList(state) { + return state.invidiousInstancesList } } const actions = { - invidiousAPICall ({ rootState }, payload) { + async fetchInvidiousInstances({ commit }) { + const requestUrl = 'https://api.invidious.io/instances.json' + + let response + try { + response = await $.getJSON(requestUrl) + } catch (err) { + console.log(err) + } + + const instances = response.filter((instance) => { + if (instance[0].includes('.onion') || instance[0].includes('.i2p') || instance[0].includes('yewtu.be')) { + return false + } else { + return true + } + }).map((instance) => { + return instance[1].uri.replace(/\/$/, '') + }) + + commit('setInvidiousInstancesList', instances) + }, + + setRandomCurrentInvidiousInstance({ commit, state }) { + const instanceList = state.invidiousInstancesList + const randomIndex = Math.floor(Math.random() * instanceList.length) + commit('setCurrentInvidiousInstance', instanceList[randomIndex]) + }, + + invidiousAPICall({ state }, payload) { return new Promise((resolve, reject) => { - const requestUrl = rootState.settings.invidiousInstance + '/api/v1/' + payload.resource + '/' + payload.id + '?' + $.param(payload.params) + const requestUrl = state.currentInvidiousInstance + '/api/v1/' + payload.resource + '/' + payload.id + '?' + $.param(payload.params) $.getJSON(requestUrl, (response) => { resolve(response) @@ -27,7 +66,7 @@ const actions = { }) }, - invidiousGetChannelInfo ({ commit, dispatch }, channelId) { + invidiousGetChannelInfo({ commit, dispatch }, channelId) { return new Promise((resolve, reject) => { commit('toggleIsGetChannelInfoRunning') @@ -48,7 +87,7 @@ const actions = { }) }, - invidiousGetPlaylistInfo ({ commit, dispatch }, payload) { + invidiousGetPlaylistInfo({ commit, dispatch }, payload) { return new Promise((resolve, reject) => { dispatch('invidiousAPICall', payload).then((response) => { resolve(response) @@ -61,7 +100,7 @@ const actions = { }) }, - invidiousGetVideoInformation ({ dispatch }, videoId) { + invidiousGetVideoInformation({ dispatch }, videoId) { return new Promise((resolve, reject) => { const payload = { resource: 'videos', @@ -81,8 +120,16 @@ const actions = { } const mutations = { - toggleIsGetChannelInfoRunning (state) { + toggleIsGetChannelInfoRunning(state) { state.isGetChannelInfoRunning = !state.isGetChannelInfoRunning + }, + + setCurrentInvidiousInstance(state, value) { + state.currentInvidiousInstance = value + }, + + setInvidiousInstancesList(state, value) { + state.invidiousInstancesList = value } } diff --git a/src/renderer/store/modules/settings.js b/src/renderer/store/modules/settings.js index cdf943a5..62c951cb 100644 --- a/src/renderer/store/modules/settings.js +++ b/src/renderer/store/modules/settings.js @@ -194,7 +194,6 @@ const state = { hideVideoLikesAndDislikes: false, hideVideoViews: false, hideWatchedSubs: false, - invidiousInstance: 'https://invidious.snopyta.org', landingPage: 'subscriptions', listType: 'grid', playNextVideo: false, @@ -250,6 +249,15 @@ const stateWithSideEffects = { } }, + defaultInvidiousInstance: { + defaultValue: '', + sideEffectsHandler: ({ commit, getters }, value) => { + if (value !== '' && getters.getCurrentInvidiousInstance !== value) { + commit('setCurrentInvidiousInstance', value) + } + } + }, + defaultVolume: { defaultValue: 1, sideEffectsHandler: (_, value) => { diff --git a/src/renderer/views/Channel/Channel.js b/src/renderer/views/Channel/Channel.js index 74a8f3c7..76577b3c 100644 --- a/src/renderer/views/Channel/Channel.js +++ b/src/renderer/views/Channel/Channel.js @@ -73,8 +73,8 @@ export default Vue.extend({ return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, sessionSearchHistory: function () { @@ -350,17 +350,17 @@ export default Vue.extend({ } else { this.subCount = response.subCount } - this.thumbnailUrl = response.authorThumbnails[3].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + this.thumbnailUrl = response.authorThumbnails[3].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) this.channelDescription = autolinker.link(response.description) this.relatedChannels = response.relatedChannels.map((channel) => { - channel.authorThumbnails[channel.authorThumbnails.length - 1].url = channel.authorThumbnails[channel.authorThumbnails.length - 1].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + channel.authorThumbnails[channel.authorThumbnails.length - 1].url = channel.authorThumbnails[channel.authorThumbnails.length - 1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) return channel }) this.latestVideos = response.latestVideos if (typeof (response.authorBanners) !== 'undefined') { - this.bannerUrl = response.authorBanners[0].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) + this.bannerUrl = response.authorBanners[0].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) } this.isLoading = false diff --git a/src/renderer/views/Playlist/Playlist.js b/src/renderer/views/Playlist/Playlist.js index 725f5f48..d40a91bc 100644 --- a/src/renderer/views/Playlist/Playlist.js +++ b/src/renderer/views/Playlist/Playlist.js @@ -34,8 +34,8 @@ export default Vue.extend({ backendFallback: function () { return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance } }, watch: { @@ -131,7 +131,7 @@ export default Vue.extend({ viewCount: result.viewCount, videoCount: result.videoCount, channelName: result.author, - channelThumbnail: result.authorThumbnails[2].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`), + channelThumbnail: result.authorThumbnails[2].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`), channelId: result.authorId, infoSource: 'invidious' } diff --git a/src/renderer/views/Subscriptions/Subscriptions.js b/src/renderer/views/Subscriptions/Subscriptions.js index e0b6ae56..619107cc 100644 --- a/src/renderer/views/Subscriptions/Subscriptions.js +++ b/src/renderer/views/Subscriptions/Subscriptions.js @@ -40,8 +40,8 @@ export default Vue.extend({ return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, hideWatchedSubs: function () { @@ -378,7 +378,7 @@ export default Vue.extend({ getChannelVideosInvidiousRSS: function (channel, failedAttempts = 0) { return new Promise((resolve, reject) => { const parser = new Parser() - const feedUrl = `${this.invidiousInstance}/feed/channel/${channel.id}` + const feedUrl = `${this.currentInvidiousInstance}/feed/channel/${channel.id}` parser.parseURL(feedUrl).then(async (feed) => { resolve(await Promise.all(feed.items.map((video) => { diff --git a/src/renderer/views/Trending/Trending.js b/src/renderer/views/Trending/Trending.js index 8581acf6..2b8a2353 100644 --- a/src/renderer/views/Trending/Trending.js +++ b/src/renderer/views/Trending/Trending.js @@ -31,8 +31,8 @@ export default Vue.extend({ backendFallback: function () { return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, region: function () { return this.$store.getters.getRegion.toUpperCase() diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js index 4058802f..eeab21f9 100644 --- a/src/renderer/views/Watch/Watch.js +++ b/src/renderer/views/Watch/Watch.js @@ -103,8 +103,8 @@ export default Vue.extend({ backendFallback: function () { return this.$store.getters.getBackendFallback }, - invidiousInstance: function () { - return this.$store.getters.getInvidiousInstance + currentInvidiousInstance: function () { + return this.$store.getters.getCurrentInvidiousInstance }, proxyVideos: function () { return this.$store.getters.getProxyVideos @@ -514,7 +514,7 @@ export default Vue.extend({ } this.dashSrc = this.createInvidiousDashManifest() - this.videoStoryboardSrc = `${this.invidiousInstance}/api/v1/storyboards/${this.videoId}?height=90` + this.videoStoryboardSrc = `${this.currentInvidiousInstance}/api/v1/storyboards/${this.videoId}?height=90` this.invidiousGetVideoInformation(this.videoId) .then(result => { @@ -540,14 +540,14 @@ export default Vue.extend({ } this.channelId = result.authorId this.channelName = result.author - this.channelThumbnail = result.authorThumbnails[1] ? result.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.invidiousInstance}/ggpht/`) : '' + this.channelThumbnail = result.authorThumbnails[1] ? result.authorThumbnails[1].url.replace('https://yt3.ggpht.com', `${this.currentInvidiousInstance}/ggpht/`) : '' this.videoPublished = result.published * 1000 this.videoDescriptionHtml = result.descriptionHtml this.recommendedVideos = result.recommendedVideos this.adaptiveFormats = result.adaptiveFormats this.isLive = result.liveNow this.captionHybridList = result.captions.map(caption => { - caption.url = this.invidiousInstance + caption.url + caption.url = this.currentInvidiousInstance + caption.url caption.type = '' caption.dataSource = 'invidious' return caption @@ -555,13 +555,13 @@ export default Vue.extend({ switch (this.thumbnailPreference) { case 'start': - this.thumbnail = `${this.invidiousInstance}/vi/${this.videoId}/maxres1.jpg` + this.thumbnail = `${this.currentInvidiousInstance}/vi/${this.videoId}/maxres1.jpg` break case 'middle': - this.thumbnail = `${this.invidiousInstance}/vi/${this.videoId}/maxres2.jpg` + this.thumbnail = `${this.currentInvidiousInstance}/vi/${this.videoId}/maxres2.jpg` break case 'end': - this.thumbnail = `${this.invidiousInstance}/vi/${this.videoId}/maxres3.jpg` + this.thumbnail = `${this.currentInvidiousInstance}/vi/${this.videoId}/maxres3.jpg` break default: this.thumbnail = result.videoThumbnails[0].url @@ -1033,7 +1033,7 @@ export default Vue.extend({ }, createInvidiousDashManifest: function () { - let url = `${this.invidiousInstance}/api/manifest/dash/id/${this.videoId}.mpd` + let url = `${this.currentInvidiousInstance}/api/manifest/dash/id/${this.videoId}.mpd` if (this.proxyVideos || !this.usingElectron) { url = url + '?local=true' diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index e543dde0..8762ff98 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -128,8 +128,13 @@ Settings: Beginning: Beginning Middle: Middle End: End - 'Invidious Instance (Default is https://invidious.snopyta.org)': Invidious Instance - (Default is https://invidious.snopyta.org) + Current Invidious Instance: Current Invidious Instance + # $ is replaced with the default Invidious instance + The currently set default instance is $: The currently set default instance is $ + No default instance has been set: No default instance has been set + Current instance will be randomized on startup: Current instance will be randomized on startup + Set Current Instance as Default: Set Current Instance as Default + Clear Default Instance: Clear Default Instance View all Invidious instance information: View all Invidious instance information Region for Trending: Region for Trending #! List countries @@ -647,6 +652,9 @@ Playing Next Video: Playing Next Video Playing Previous Video: Playing Previous Video Playing Next Video Interval: Playing next video in no time. Click to cancel. | Playing next video in {nextVideoInterval} second. Click to cancel. | Playing next video in {nextVideoInterval} seconds. Click to cancel. Canceled next video autoplay: Canceled next video autoplay +# $ is replaced with the default Invidious instance +Default Invidious instance has been set to $: Default Invidious instance has been set to $ +Default Invidious instance has been cleared: Default Invidious instance has been cleared 'The playlist has ended. Enable loop to continue playing': 'The playlist has ended. Enable loop to continue playing'