From 40d7278383ce8cd6402ea7aa4d643f371e177d85 Mon Sep 17 00:00:00 2001
From: Svallinn <41585298+Svallinn@users.noreply.github.com>
Date: Sat, 3 Jul 2021 02:55:56 +0100
Subject: [PATCH] Invidious: Randomize instance on startup
There are now two separate settings related to Invidious instances:
- currentInvidiousInstance
- defaultInvidiousInstance
'currentInvidiousInstance' is a value that exists solely in memory
and it's the value used by the app to make the API calls,
while 'defaultInvidiousInstance' is the value that can be persisted
in the database by user action and will be used to initiate
the 'currentInvidiousInstance' on startup.
If the user has not saved a default value to the database,
'currentInvidiousInstance' is randomized from
a fetched list of viable candidates.
---
src/renderer/App.js | 18 +++-
.../components/data-settings/data-settings.js | 4 +-
.../ft-list-channel/ft-list-channel.js | 6 +-
.../ft-list-playlist/ft-list-playlist.js | 6 +-
.../components/ft-list-video/ft-list-video.js | 10 +--
.../ft-profile-channel-list.js | 8 +-
.../ft-profile-filter-channels-list.js | 8 +-
.../ft-share-button/ft-share-button.js | 8 +-
.../general-settings/general-settings.js | 86 ++++++++++---------
.../general-settings/general-settings.vue | 42 +++++++--
.../components/playlist-info/playlist-info.js | 6 +-
src/renderer/components/side-nav/side-nav.js | 6 +-
src/renderer/components/top-nav/top-nav.js | 4 +-
.../watch-video-comments.js | 8 +-
.../watch-video-info/watch-video-info.js | 4 +-
src/renderer/sass-partials/_settings.sass | 3 +
src/renderer/store/modules/invidious.js | 61 +++++++++++--
src/renderer/store/modules/settings.js | 10 ++-
src/renderer/views/Channel/Channel.js | 10 +--
src/renderer/views/Playlist/Playlist.js | 6 +-
.../views/Subscriptions/Subscriptions.js | 6 +-
src/renderer/views/Trending/Trending.js | 4 +-
src/renderer/views/Watch/Watch.js | 18 ++--
static/locales/en-US.yaml | 12 ++-
24 files changed, 234 insertions(+), 120 deletions(-)
diff --git a/src/renderer/App.js b/src/renderer/App.js
index 3e2074cd3..e44fdaced 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 8c3487626..a7c7f3775 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 93f0b1170..51639d56e 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 1d941d12f..d6305b9ec 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 b791d94c4..b114947dc 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 d5740bcb6..be061a479 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 6ab9fdba2..9fe3146ae 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 8ca4700c0..0efc7f15c 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 bb74a52c1..8082da5a7 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 c6d945536..cc4b26fb1 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.The currently set default instance is $').replace('$', defaultInvidiousInstance) }} +
+ ++ {{ $t('Settings.General Settings.No default instance has been set') }} +
++ {{ $t('Settings.General Settings.Current instance will be randomized on startup') }} +
+ +