ref(config): override config from URL on mobile

Moves the things around to be able to override the config with the URL
params specified in the hash part of the location URI to which the app
is navigating to.
This commit is contained in:
paweldomas 2018-03-06 10:08:23 -06:00 committed by Lyubo Marinov
parent 6a066c3079
commit ef52f09910
3 changed files with 78 additions and 51 deletions

View File

@ -1,10 +1,13 @@
/* @flow */ // @flow
import type { Dispatch } from 'redux';
import { import {
CONFIG_WILL_LOAD, CONFIG_WILL_LOAD,
LOAD_CONFIG_ERROR, LOAD_CONFIG_ERROR,
SET_CONFIG SET_CONFIG
} from './actionTypes'; } from './actionTypes';
import { setConfigFromURLParams } from './functions';
/** /**
* Signals that the configuration for a specific locationURL will be loaded now. * Signals that the configuration for a specific locationURL will be loaded now.
@ -51,14 +54,36 @@ export function loadConfigError(error: Error, locationURL: string | URL) {
* *
* @param {Object} config - The configuration to be represented by the feature * @param {Object} config - The configuration to be represented by the feature
* base/config. * base/config.
* @returns {{ * @returns {Function}
* type: SET_CONFIG,
* config: Object
* }}
*/ */
export function setConfig(config: Object = {}) { export function setConfig(config: Object = {}) {
return { return (dispatch: Dispatch<*>, getState: Function) => {
const { locationURL } = getState()['features/base/connection'];
// Now that the loading of the config was successful override the values
// with the parameters passed in the hash part of the location URI.
// TODO We're still in the middle ground between old Web with config,
// interfaceConfig, and loggingConfig used via global variables and new
// Web and mobile reading the respective values from the redux store.
// On React Native there's no interfaceConfig at all yet and
// loggingConfig is not loaded but there's a default value in the redux
// store.
// Only the config will be overridden on React Native, as the other
// globals will be undefined here. It's intentional - we do not care to
// override those configs yet.
locationURL
&& setConfigFromURLParams(
// On Web the config also comes from the window.config global,
// but it is resolved in the loadConfig procedure.
config,
window.interfaceConfig,
window.loggingConfig,
locationURL);
dispatch({
type: SET_CONFIG, type: SET_CONFIG,
config config
});
}; };
} }

View File

@ -179,7 +179,7 @@ export function obtainConfig(
* @returns {void} * @returns {void}
*/ */
export function overrideConfigJSON( export function overrideConfigJSON(
config: Object, interfaceConfig: Object, loggingConfig: Object, config: ?Object, interfaceConfig: ?Object, loggingConfig: ?Object,
json: Object) { json: Object) {
for (const configName of Object.keys(json)) { for (const configName of Object.keys(json)) {
let configObj; let configObj;
@ -212,6 +212,8 @@ export function overrideConfigJSON(
} }
} }
/* eslint-enable max-params, no-shadow */
/** /**
* Whitelist only config.js, skips this for others configs * Whitelist only config.js, skips this for others configs
* (interfaceConfig, loggingConfig). * (interfaceConfig, loggingConfig).
@ -220,9 +222,9 @@ export function overrideConfigJSON(
* @param {string} configName - The config name, one of config, * @param {string} configName - The config name, one of config,
* interfaceConfig, loggingConfig. * interfaceConfig, loggingConfig.
* @param {Object} configJSON - The object with keys and values to override. * @param {Object} configJSON - The object with keys and values to override.
* @private
* @returns {Object} - The result object only with the keys * @returns {Object} - The result object only with the keys
* that are whitelisted. * that are whitelisted.
* @private
*/ */
function _getWhitelistedJSON(configName, configJSON) { function _getWhitelistedJSON(configName, configJSON) {
if (configName !== 'config') { if (configName !== 'config') {
@ -232,40 +234,48 @@ function _getWhitelistedJSON(configName, configJSON) {
return _.pick(configJSON, WHITELISTED_KEYS); return _.pick(configJSON, WHITELISTED_KEYS);
} }
/* eslint-enable max-params, no-shadow */ /* eslint-disable max-params */
/** /**
* Converts 'URL_PARAMS' to JSON object. * Inspects the hash part of the location URI and overrides values specified
* We have: * there in the corresponding config objects given as the arguments. The syntax
* { * is: {@code https://server.com/room#config.debug=true
* "config.disableAudioLevels": false, * &interfaceConfig.showButton=false&loggingConfig.something=1}.
* "config.channelLastN": -1,
* "interfaceConfig.APP_NAME": "Jitsi Meet"
* }.
* We want to have:
* {
* "config": {
* "disableAudioLevels": false,
* "channelLastN": -1
* },
* interfaceConfig: {
* "APP_NAME": "Jitsi Meet"
* }
* }.
* *
* In the hash part each parameter will be parsed to JSON and then the root
* object will be matched with the corresponding config object given as the
* argument to this function.
*
* @param {Object} config - This is the general config.
* @param {Object} interfaceConfig - This is the interface config.
* @param {Object} loggingConfig - The logging config.
* @param {URI} location - The new location to which the app is navigating to.
* @returns {void} * @returns {void}
*/ */
export function setConfigFromURLParams() { export function setConfigFromURLParams(
const params = parseURLParams(window.location); config: ?Object,
interfaceConfig: ?Object,
const { config, interfaceConfig, loggingConfig } = window; loggingConfig: ?Object,
location: Object) {
const params = parseURLParams(location);
const json = {}; const json = {};
// TODO We're still in the middle ground between old Web with config, // At this point we have:
// interfaceConfig, and loggingConfig used via global variables and new Web // params = {
// and mobile reading the respective values from the redux store. On React // "config.disableAudioLevels": false,
// Native there's no interfaceConfig at all yet and loggingConfig is not // "config.channelLastN": -1,
// loaded but there's a default value in the redux store. // "interfaceConfig.APP_NAME": "Jitsi Meet"
// }
// We want to have:
// json = {
// config: {
// "disableAudioLevels": false,
// "channelLastN": -1
// },
// interfaceConfig: {
// "APP_NAME": "Jitsi Meet"
// }
// }
config && (json.config = {}); config && (json.config = {});
interfaceConfig && (json.interfaceConfig = {}); interfaceConfig && (json.interfaceConfig = {});
loggingConfig && (json.loggingConfig = {}); loggingConfig && (json.loggingConfig = {});
@ -284,3 +294,5 @@ export function setConfigFromURLParams() {
overrideConfigJSON(config, interfaceConfig, loggingConfig, json); overrideConfigJSON(config, interfaceConfig, loggingConfig, json);
} }
/* eslint-enable max-params */

View File

@ -1,6 +1,5 @@
// @flow // @flow
import { setConfigFromURLParams } from '../config';
import { toState } from '../redux'; import { toState } from '../redux';
import { loadScript } from '../util'; import { loadScript } from '../util';
@ -12,7 +11,7 @@ const JitsiConferenceErrors = JitsiMeetJS.errors.conference;
const JitsiConnectionErrors = JitsiMeetJS.errors.connection; const JitsiConnectionErrors = JitsiMeetJS.errors.connection;
/** /**
* Creates a JitsiLocalTrack model from the given device id. * Creates a {@link JitsiLocalTrack} model from the given device id.
* *
* @param {string} type - The media type of track being created. Expected values * @param {string} type - The media type of track being created. Expected values
* are "video" or "audio". * are "video" or "audio".
@ -107,9 +106,9 @@ export function isFatalJitsiConnectionError(error: Object | string) {
* Loads config.js from a specific remote server. * Loads config.js from a specific remote server.
* *
* @param {string} url - The URL to load. * @param {string} url - The URL to load.
* @param {number} [timeout] - The timeout for the configuration to be loaded, * @param {number} [timeout] - The timeout in milliseconds for the {@code url}
* in milliseconds. If not specified, a default value deamed appropriate for the * to load. If not specified, a default value deemed appropriate for the purpose
* purpsoe is used. * is used.
* @returns {Promise<Object>} * @returns {Promise<Object>}
*/ */
export function loadConfig( export function loadConfig(
@ -145,14 +144,5 @@ export function loadConfig(
promise = Promise.resolve(window.config); promise = Promise.resolve(window.config);
} }
// FIXME It's neither here nor there at the time of this writing where
// config, interfaceConfig, and loggingConfig should be overwritten by URL
// params.
promise = promise.then(value => {
setConfigFromURLParams();
return value;
});
return promise; return promise;
} }