Added option to enable or disable fetching config

This commit is contained in:
Travis Shivers 2020-06-10 19:32:35 -05:00
parent c3f7770858
commit d7f88de061
16 changed files with 242 additions and 198 deletions

View File

@ -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',
},
];

View File

@ -102,16 +102,18 @@
fluid
>
<v-alert
v-if="GET_CONFIGURATION_FETCHED_ERROR"
width="100%"
:dismissible="true"
type="error"
class="mt-0 mb-0"
>
{{ configError }}
Failed to fetch config: {{ GET_CONFIGURATION_FETCHED_ERROR }}
</v-alert>
<v-container
v-if="(loading || (getPlex && !IS_DONE_FETCHING_DEVICES)) && $route.protected"
v-if="(GET_CONFIG.fetchConfig && !GET_CONFIGURATION_FETCHED
|| (getPlex && !IS_DONE_FETCHING_DEVICES)) && $route.protected"
fill-height
>
<v-row
@ -206,12 +208,8 @@ export default {
initialized: false,
donateDialog: false,
loading: true,
configError: null,
snackbar: false,
snackbarMsg: false,
configFetchPromise: null,
items: [
{
@ -252,8 +250,10 @@ export default {
'getLogos',
'IS_DONE_FETCHING_DEVICES',
'IS_AUTHENTICATED',
'GET_CONFIG',
'GET_CONFIGURATION_FETCHED',
'GET_CONFIGURATION_FETCHED_ERROR',
]),
...mapGetters('config', ['GET_CONFIG']),
...mapState(['isRightSidebarOpen']),
extAvailable() {
@ -380,30 +380,7 @@ export default {
},
},
async mounted() {
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();
}
try {
await this.configFetchPromise;
} catch (e) {
this.configError = `Failed to fetch config: ${e}`;
}
if (this.GET_CONFIG) {
if (this.GET_CONFIG.autoJoin && this.GET_CONFIG.autoJoin === true) {
this.$store.commit('SET_AUTOJOIN', true);
this.$store.commit('SET_AUTOJOINROOM', this.GET_CONFIG.autoJoinRoom);
this.$store.commit('SET_AUTOJOINURL', this.GET_CONFIG.autoJoinServer);
this.$store.commit('SET_AUTOJOINPASSWORD', this.GET_CONFIG.autoJoinPassword);
}
}
mounted() {
window.EventBus.$on('notification', (msg) => {
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() {

View File

@ -0,0 +1,82 @@
<template>
<v-row
class="pt-2 pa-4"
justify="center"
>
<v-col md="6">
<v-card
:loading="loading"
class="pa-4"
>
<v-alert
v-if="error"
type="error"
>
Unable to autojoin
</v-alert>
<v-card-title>
Welcome to SyncLounge
</v-card-title>
<v-card-actions>
<v-btn
class="primary"
x-large
text
:disabled="loading"
@click="join"
>
Join
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'AutoJoin',
data() {
return {
error: false,
loading: false,
};
},
computed: {
...mapGetters([
'getLogos',
]),
},
methods: {
...mapActions([
'JOIN_CONFIG_SYNCLOUNGE_SERVER',
]),
async join() {
this.error = false;
this.loading = true;
try {
await this.JOIN_CONFIG_SYNCLOUNGE_SERVER();
} catch (e) {
console.error(e);
this.error = true;
}
this.loading = false;
if (!this.error) {
this.$router.push('/browse');
}
},
},
};
</script>

View File

@ -1,11 +0,0 @@
module.exports = {
defaultSettings: {
autoplay: true,
clientPollInterval: 1000,
syncMode: 'cleanseek',
syncFlexibility: 3000,
slPlayerForceTranscode: false,
slPlayerQuality: null,
slPlayerVolume: 1,
},
};

View File

@ -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({

View File

@ -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,
},
],
});

View File

@ -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);
},
};

View File

@ -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,
};

View File

@ -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,
},

View File

@ -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,
};

View File

@ -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,

View File

@ -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,
}),
};

View File

@ -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']]);

View File

@ -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;
},
};

View File

@ -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: {},

View File

@ -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 = {