From d7f88de061cc3bb8c28f1063efbbe4aa82abd8be Mon Sep 17 00:00:00 2001 From: Travis Shivers Date: Wed, 10 Jun 2020 19:32:35 -0500 Subject: [PATCH] Added option to enable or disable fetching config --- SettingsHelper.js | 21 +++--- src/App.vue | 53 +++++--------- src/components/autojoin.vue | 82 +++++++++++++++++++++ src/defaultsettings.js | 11 --- src/main.js | 34 +++++---- src/router/index.js | 90 +++++++++++------------- src/store/actions.js | 15 ++++ src/store/getters.js | 8 +-- src/store/index.js | 2 - src/store/modules/config/config.store.js | 36 ---------- src/store/modules/settings/getters.js | 35 +++++---- src/store/modules/synclounge/actions.js | 6 ++ src/store/modules/synclounge/getters.js | 10 +-- src/store/mutations.js | 27 ++++--- src/store/state.js | 8 +-- vue.config.js | 2 + 16 files changed, 242 insertions(+), 198 deletions(-) create mode 100644 src/components/autojoin.vue delete mode 100644 src/defaultsettings.js delete mode 100644 src/store/modules/config/config.store.js diff --git a/SettingsHelper.js b/SettingsHelper.js index 8127ca28..aace8042 100644 --- a/SettingsHelper.js +++ b/SettingsHelper.js @@ -1,7 +1,6 @@ const args = require('args-parser')(process.argv); const { coalesce } = require('./src/utils/helpers'); -const { defaultSettings } = require('./src/defaultsettings'); const readSettingsFile = (file) => { try { @@ -88,31 +87,31 @@ const fields = [ { local: 'autoplay', env: 'AUTOPLAY', - default: defaultSettings.autoplay, + default: true, type: 'boolean', }, { local: 'clientPollInterval', env: 'CLIENTPOLLINTERVAL', - default: defaultSettings.clientPollInterval, + default: 1000, type: 'number', }, { local: 'syncMode', env: 'SYNCMODE', - default: defaultSettings.syncMode, + default: 'cleanseek', type: 'string', }, { local: 'syncFlexibility', env: 'SYNCFLEXIBILITY', - default: defaultSettings.syncFlexibility, + default: 3000, type: 'number', }, { local: 'slPlayerQuality', env: 'SLPLAYERQUALITY', - default: defaultSettings.slPlayerQuality, + default: null, type: 'number', // null is allowed because null quality indicates Original nullable: true, @@ -121,13 +120,19 @@ const fields = [ // Valid values are in the range [0, 1] local: 'slPlayerVolume', env: 'SLPLAYERVOLUME', - default: defaultSettings.slPlayerVolume, + default: 1, type: 'number', }, { local: 'slPlayerForceTranscode', env: 'SLPLAYERFORCETRANSCODE', - default: defaultSettings.slPlayerForceTranscode, + default: false, + type: 'boolean', + }, + { + local: 'fetchConfig', + env: 'FETCH_CONFIG', + default: false, type: 'boolean', }, ]; diff --git a/src/App.vue b/src/App.vue index c94f1986..0959000a 100644 --- a/src/App.vue +++ b/src/App.vue @@ -102,16 +102,18 @@ fluid > - {{ configError }} + Failed to fetch config: {{ GET_CONFIGURATION_FETCHED_ERROR }} { this.snackbarMsg = msg; this.snackbar = true; @@ -433,22 +410,28 @@ export default { this.appIsFullscreen = isFullscreen; document.body.classList.toggle('is-fullscreen', isFullscreen); }); - - this.loading = false; }, created() { - this.configFetchPromise = this.fetchConfig(); + if (this.GET_CONFIG.fetchConfig) { + this.FETCH_CONFIG(); + } + + if (this.IS_AUTHENTICATED) { + // Kick off a bunch of requests that we need for later + this.FETCH_PLEX_USER(); + this.FETCH_PLEX_DEVICES_IF_NEEDED(); + } }, methods: { - ...mapActions('config', ['fetchConfig']), ...mapActions([ 'SET_LEFT_SIDEBAR_OPEN', 'SET_RIGHT_SIDEBAR_OPEN', 'TOGGLE_RIGHT_SIDEBAR_OPEN', 'FETCH_PLEX_DEVICES_IF_NEEDED', 'FETCH_PLEX_USER', + 'FETCH_CONFIG', ]), sendNotification() { diff --git a/src/components/autojoin.vue b/src/components/autojoin.vue new file mode 100644 index 00000000..00e4a283 --- /dev/null +++ b/src/components/autojoin.vue @@ -0,0 +1,82 @@ + + + + diff --git a/src/defaultsettings.js b/src/defaultsettings.js deleted file mode 100644 index 37e49c49..00000000 --- a/src/defaultsettings.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - defaultSettings: { - autoplay: true, - clientPollInterval: 1000, - syncMode: 'cleanseek', - syncFlexibility: 3000, - slPlayerForceTranscode: false, - slPlayerQuality: null, - slPlayerVolume: 1, - }, -}; diff --git a/src/main.js b/src/main.js index 70d9585c..d98552e8 100644 --- a/src/main.js +++ b/src/main.js @@ -50,24 +50,28 @@ window.EventBus.$on('command', (data) => { }); router.beforeEach((to, from, next) => { - // console.log('Route change', to, this, store) - if (to.matched.some((record) => record.meta.protected)) { + if (!store.getters.IS_AUTHENTICATED && to.matched.some((record) => record.meta.requiresAuth)) { + if (to.matched.some((record) => record.meta.redirectAfterAuth)) { + next({ + path: '/signin', + query: { + redirect: to.fullPath, + }, + }); + } else { + next('/signin'); + } + } else if (store.getters.GET_CONFIG.autoJoin + && to.matched.some((record) => record.meta.noAutoJoin)) { + next('/autojoin'); + } else if (!store.getters.getRoom && to.matched.some((record) => record.meta.protected)) { // this route requires us to be in a room with a client selected // if not, redirect to the needed stage - if (!store.getters.getRoom) { - return next({ - path: '/', - }); - } - next(); - } else { - if (!to.meta.protected) { - return next(); - } - router.push('/browse'); - } - return null; + next('/'); + } else { + next(); + } }); new Vue({ diff --git a/src/router/index.js b/src/router/index.js index e6edd8bd..d0120b06 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -6,34 +6,12 @@ Vue.use(Router); // Good guide: https://blog.sqreen.com/authentication-best-practices-vue/ - -// const ifNotAuthenticated = (to, from, next) => { -// if (!store.getters.IS_AUTHENTICATED) { -// next(); -// return; -// } -// next('/'); -// }; - -const ifAuthenticated = (to, from, next) => { - if (store.getters.IS_AUTHENTICATED) { +const requireAutoJoinEnabled = (to, from, next) => { + if (store.getters.GET_CONFIG.autoJoin) { next(); return; } - next('/signin'); -}; - -const ifAuthenticatedWithRedirect = (to, from, next) => { - if (store.getters.IS_AUTHENTICATED) { - next(); - return; - } - next({ - path: '/signin', - query: { - redirect: to.fullPath, - }, - }); + next('/'); }; // ==================== Router registration ==================== @@ -45,7 +23,10 @@ export default new Router({ path: '/', component: () => import('../components/createroom.vue'), name: 'CreateRoom', - beforeEnter: ifAuthenticated, + meta: { + requiresAuth: true, + noAutoJoin: true, + }, }, { path: '/signin', @@ -55,132 +36,145 @@ export default new Router({ }, { path: '/signout', - meta: {}, component: () => import('../components/signout.vue'), - beforeEnter: ifAuthenticated, + meta: { + requiresAuth: true, + }, + }, + { + path: '/autojoin', + meta: { + requiresAuth: true, + redirectAfterAuth: true, + }, + component: () => import('../components/autojoin.vue'), + name: 'autojoin', + beforeEnter: requireAutoJoinEnabled, }, { path: '/join/:server/:room', meta: { + noAutoJoin: true, + redirectAfterAuth: true, }, component: () => import('../components/join.vue'), props: true, name: 'join', - beforeEnter: ifAuthenticatedWithRedirect, }, { path: '/clientselect', - meta: { - }, component: () => import('../components/application/walkthrough.vue'), - beforeEnter: ifAuthenticated, + meta: { + requiresAuth: true, + }, }, { path: '/clientpicker', - meta: { - }, name: 'ClientPicker', component: () => import('../components/clientpicker.vue'), - beforeEnter: ifAuthenticated, + meta: { + requiresAuth: true, + }, }, { path: '/joinroom', - meta: { - }, component: () => import('../components/application/joinroom.vue'), - beforeEnter: ifAuthenticated, + meta: { + requiresAuth: true, + noAutoJoin: true, + }, }, { path: '/player', meta: { + requiresAuth: true, protected: true, }, component: () => import('../components/application/slplayer.vue'), - beforeEnter: ifAuthenticated, }, { path: '/nowplaying/:machineIdentifier/:ratingKey', meta: { + requiresAuth: true, protected: true, }, name: 'nowplaying', component: () => import('../components/application/plexbrowser/plexcontent.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse', meta: { + requiresAuth: true, protected: true, }, name: 'browse', component: () => import('../components/application/plexbrowser.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier', meta: { + requiresAuth: true, protected: true, }, name: 'server', component: () => import('../components/application/plexbrowser/plexserver.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier/:sectionId', meta: { + requiresAuth: true, protected: true, }, name: 'library', component: () => import('../components/application/plexbrowser/plexlibrary.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier/:sectionId/:ratingKey', meta: { + requiresAuth: true, protected: true, }, name: 'content', component: () => import('../components/application/plexbrowser/plexcontent.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier/:sectionId/tv/:ratingKey', meta: { + requiresAuth: true, protected: true, }, name: 'series', component: () => import('../components/application/plexbrowser/plexseries.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier/:sectionId/tv/:parentKey/:ratingKey', meta: { + requiresAuth: true, protected: true, }, name: 'season', component: () => import('../components/application/plexbrowser/plexseason.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier/:sectionId/tv/:grandparentKey/:parentKey/:ratingKey', meta: { + requiresAuth: true, protected: true, }, name: 'contentspecific', component: () => import('../components/application/plexbrowser/plexcontent.vue'), - beforeEnter: ifAuthenticated, }, { path: '/browse/:machineIdentifier/tv/:grandparentKey/:parentKey/:ratingKey', meta: { + requiresAuth: true, protected: true, }, name: 'contentnosection', component: () => import('../components/application/plexbrowser/plexcontent.vue'), - beforeEnter: ifAuthenticated, }, ], }); diff --git a/src/store/actions.js b/src/store/actions.js index 995ded35..c2485658 100644 --- a/src/store/actions.js +++ b/src/store/actions.js @@ -1,5 +1,8 @@ +import axios from 'axios'; + import delay from '@/utils/delay'; + function sendNotification(message) { return window.EventBus.$emit('notification', message); } @@ -195,4 +198,16 @@ export default { commit('SET_BACKGROUND', result); } }, + + FETCH_CONFIG: async ({ commit }) => { + const url = window.location.origin + window.location.pathname.replace(/\/+$/, ''); + try { + const { data } = await axios.get(`${url}/config`); + commit('SET_CONFIG', data); + } catch (e) { + commit('SET_CONFIGURATION_FETCH_ERROR', e); + } + + commit('SET_CONFIGURATION_FETCHED', true); + }, }; diff --git a/src/store/getters.js b/src/store/getters.js index aae591b5..500b1a6f 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -5,10 +5,6 @@ export default { getShownChat: (state) => state.shownChat, getStats: (state) => state.stats, getBlockAutoPlay: (state) => state.blockAutoPlay, - getAutoJoin: (state) => state.autoJoin, - getAutoJoinRoom: (state) => state.autoJoinRoom, - getAutoJoinPassword: (state) => state.autoJoinPassword, - getAutoJoinUrl: (state) => state.autoJoinUrl, // SETTINGS getExtAvailable: (state) => state.extAvailable, @@ -32,4 +28,8 @@ export default { GET_UP_NEXT_TRIGGERED: (state) => state.upNextTriggered, GET_UP_NEXT_POST_PLAY_DATA: (state) => state.upNextPostPlayData, GET_PLEX_SERVER_ID: (state) => state.plexServerId, + GET_CONFIG: (state) => state.configuration, + GET_AUTHENTICATION: (state) => state.configuration.authentication, + GET_CONFIGURATION_FETCHED: (state) => state.configurationFectched, + GET_CONFIGURATION_FETCHED_ERROR: (state) => state.configurationFetchedError, }; diff --git a/src/store/index.js b/src/store/index.js index de4e6f52..e34dc44f 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -8,7 +8,6 @@ import mutations from './mutations'; import getters from './getters'; import synclounge from './modules/synclounge'; -import config from './modules/config/config.store'; import settings from './modules/settings'; import plex from './modules/plex'; import slplayer from './modules/slplayer'; @@ -31,7 +30,6 @@ const store = new Vuex.Store({ modules: { synclounge, plex, - config, settings, slplayer, }, diff --git a/src/store/modules/config/config.store.js b/src/store/modules/config/config.store.js deleted file mode 100644 index 553eba80..00000000 --- a/src/store/modules/config/config.store.js +++ /dev/null @@ -1,36 +0,0 @@ -import axios from 'axios'; - -const initialState = () => ({ - configuration: {}, -}); - -const getters = { - GET_CONFIG: (state) => state.configuration, - GET_AUTHENTICATION: (state) => state.configuration.authentication, -}; - -const mutations = { - SET_CONFIG: (state, data) => { - state.configuration = data; - }, - SET_AUTHENTICATION: (state, auth) => { - state.configuration.authentication = auth; - }, -}; - -const actions = { - fetchConfig: async ({ commit }) => { - const url = window.location.origin + window.location.pathname.replace(/\/+$/, ''); - return axios.get(`${url}/config`).then(({ data }) => { - commit('SET_CONFIG', data); - }); - }, -}; - -export default { - namespaced: true, - state: initialState, - mutations, - actions, - getters, -}; diff --git a/src/store/modules/settings/getters.js b/src/store/modules/settings/getters.js index 8886bca8..27da9ee4 100644 --- a/src/store/modules/settings/getters.js +++ b/src/store/modules/settings/getters.js @@ -1,37 +1,44 @@ -const { defaultSettings } = require('@/defaultsettings'); + const { coalesce } = require('@/utils/helpers'); // Use stored value if not null, othewise fallback to config, then default values export default { - GET_AUTOPLAY: (state, getters, rootState, rootGetters) => coalesce(state.autoplay, rootGetters['config/GET_CONFIG'].autoplay, defaultSettings.autoplay), + GET_AUTOPLAY: (state, getters, rootState, rootGetters) => coalesce(state.autoplay, + rootGetters.GET_CONFIG.autoplay), + GET_CLIENTPOLLINTERVAL: (state, getters, rootState, rootGetters) => coalesce( state.clientPollInterval, - rootGetters['config/GET_CONFIG'].clientPollInterval, - defaultSettings.clientPollInterval, + rootGetters.GET_CONFIG.clientPollInterval, + ), - GET_SYNCMODE: (state, getters, rootState, rootGetters) => coalesce(state.syncMode, rootGetters['config/GET_CONFIG'].syncMode, defaultSettings.syncMode), + GET_SYNCMODE: (state, getters, rootState, rootGetters) => coalesce(state.syncMode, + rootGetters.GET_CONFIG.syncMode), + GET_SYNCFLEXIBILITY: (state, getters, rootState, rootGetters) => coalesce( state.syncFlexibility, - rootGetters['config/GET_CONFIG'].syncFlexibility, - defaultSettings.syncFlexibility, + rootGetters.GET_CONFIG.syncFlexibility, ), - GET_CUSTOMSERVER: (state, getters, rootState, rootGetters) => coalesce(state.customServer, rootGetters['config/GET_CONFIG'].customServer), + + GET_CUSTOMSERVER: (state, getters, rootState, rootGetters) => coalesce(state.customServer, + rootGetters.GET_CONFIG.customServer), + GET_BLOCKEDSERVERS: (state) => state.blockedServers, GET_SLPLAYERQUALITY: (state, getters, rootState, rootGetters) => coalesce( state.slPlayerQuality, - rootGetters['config/GET_CONFIG'].slPlayerQuality, - defaultSettings.slPlayerQuality, + rootGetters.GET_CONFIG.slPlayerQuality, + ) || null, + GET_SLPLAYERVOLUME: (state, getters, rootState, rootGetters) => coalesce( state.slPlayerVolume, - rootGetters['config/GET_CONFIG'].slPlayerVolume, - defaultSettings.slPlayerVolume, + rootGetters.GET_CONFIG.slPlayerVolume, ), + GET_SLPLAYERFORCETRANSCODE: (state, getters, rootState, rootGetters) => coalesce( state.slPlayerForceTranscode, - rootGetters['config/GET_CONFIG'].slPlayerForceTranscode, - defaultSettings.slPlayerForceTranscode, + rootGetters.GET_CONFIG.slPlayerForceTranscode, ), + GET_HIDEUSERNAME: (state) => state.hideUsername, GET_ALTUSERNAME: (state) => state.altUsername, GET_CLIENTIDENTIFIER: (state) => state.clientIdentifier, diff --git a/src/store/modules/synclounge/actions.js b/src/store/modules/synclounge/actions.js index bdbac42a..9744a037 100644 --- a/src/store/modules/synclounge/actions.js +++ b/src/store/modules/synclounge/actions.js @@ -523,4 +523,10 @@ export default { room: guid(), }); }, + + JOIN_CONFIG_SYNCLOUNGE_SERVER: ({ rootGetters, dispatch }) => dispatch('autoJoin', { + server: rootGetters.GET_CONFIG.autoJoinServer, + room: rootGetters.GET_CONFIG.autoJoinRoom, + password: rootGetters.GET_CONFIG.autoJoinPassword, + }), }; diff --git a/src/store/modules/synclounge/getters.js b/src/store/modules/synclounge/getters.js index 4ae700b9..c8a1fde4 100644 --- a/src/store/modules/synclounge/getters.js +++ b/src/store/modules/synclounge/getters.js @@ -36,17 +36,17 @@ export default { GET_SYNCLOUNGE_SERVERS: (state, getters, rootState, rootGetters) => { - if (rootGetters['config/GET_CONFIG'].servers && rootGetters['config/GET_CONFIG'].servers.length > 0) { - if (rootGetters['config/GET_CONFIG'].customServer) { + if (rootGetters.GET_CONFIG.servers && rootGetters.GET_CONFIG.servers.length > 0) { + if (rootGetters.GET_CONFIG.customServer) { console.error( "'customServer' setting provided with 'servers' setting. Ignoring 'customServer' setting.", ); } - return rootGetters['config/GET_CONFIG'].servers; + return rootGetters.GET_CONFIG.servers; } - if (rootGetters['config/GET_CONFIG'].customServer) { - return defaultSyncloungeServers.concat([rootGetters['config/GET_CONFIG'].customServer]); + if (rootGetters.GET_CONFIG.customServer) { + return defaultSyncloungeServers.concat([rootGetters.GET_CONFIG.customServer]); } return defaultSyncloungeServers.concat([rootGetters['settings/GET_CUSTOMSERVER']]); diff --git a/src/store/mutations.js b/src/store/mutations.js index e16bc167..4f67f4c1 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -1,24 +1,9 @@ import Vue from 'vue'; export default { - SET_PLEX(state, value) { - state.plex = value; - }, - SET_AUTOJOIN(state, value) { - state.autoJoin = value; - }, SET_BACKGROUND(state, value) { state.background = value; }, - SET_AUTOJOINROOM(state, value) { - state.autoJoinRoom = value; - }, - SET_AUTOJOINPASSWORD(state, value) { - state.autoJoinPassword = value; - }, - SET_AUTOJOINURL(state, value) { - state.autoJoinUrl = value; - }, SET_VALUE(state, data) { const [key, value] = data; @@ -46,4 +31,16 @@ export default { SET_PLEX_SERVER_ID: (state, id) => { state.plexServerId = id; }, + + SET_CONFIG: (state, data) => { + state.configuration = data; + }, + + SET_CONFIGURATION_FETCHED: (state, fetched) => { + state.configurationFetcehd = fetched; + }, + + SET_CONFIGURATION_FETCH_ERROR: (state, error) => { + state.configurationFetchError = error; + }, }; diff --git a/src/store/state.js b/src/store/state.js index 83850aa9..0d2f0c21 100644 --- a/src/store/state.js +++ b/src/store/state.js @@ -6,16 +6,14 @@ const state = () => ({ background: null, shownChat: false, blockAutoPlay: false, - autoJoin: false, - autoJoinUrl: null, - autoJoinRoom: null, - autoJoinPassword: null, - autoJoinUsername: null, extAvailable: false, lastRatingKey: null, manualSyncQueued: false, uuid: guid(), upNextCache: {}, + configuration: JSON.parse(process.env.VUE_APP_CONFIGURATION), + configurationFetched: false, + configurationFetchError: false, // SETTINGS stats: {}, diff --git a/vue.config.js b/vue.config.js index 54e2a30a..c716cbce 100644 --- a/vue.config.js +++ b/vue.config.js @@ -4,6 +4,8 @@ const { readSettings } = require('./SettingsHelper'); const settings = readSettings(); +process.env.VUE_APP_CONFIGURATION = JSON.stringify(settings); + process.env.VUE_APP_VERSION = require('./package.json').version; module.exports = {