From 3987655f2af186d6b3bdcb934b330c616df9e75c Mon Sep 17 00:00:00 2001 From: Bettenbuk Zoltan Date: Mon, 8 Apr 2019 13:18:35 +0200 Subject: [PATCH] Refactor config loading --- package-lock.json | 4 +- package.json | 2 +- react/features/app/actions.js | 216 +++++------------- react/features/app/components/index.js | 2 + react/features/app/index.js | 2 + .../features/base/lib-jitsi-meet/functions.js | 10 +- webpack.config.js | 15 +- 7 files changed, 78 insertions(+), 173 deletions(-) diff --git a/package-lock.json b/package-lock.json index 26d3f242bc..53c1e9949d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5519,8 +5519,8 @@ } }, "eslint-config-jitsi": { - "version": "github:jitsi/eslint-config-jitsi#1f3fbcea8baa1ab95929a351be3977e00cb162ec", - "from": "github:jitsi/eslint-config-jitsi#1.0.0", + "version": "github:jitsi/eslint-config-jitsi#5f9fe4fd00be471ab6f5d06f77ffc90bba0853e8", + "from": "github:jitsi/eslint-config-jitsi#1.0.1", "dev": true }, "eslint-import-resolver-node": { diff --git a/package.json b/package.json index 44d96fd19d..e5fd8eb03e 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "clean-css": "3.4.25", "css-loader": "0.28.7", "eslint": "5.6.1", - "eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#1.0.0", + "eslint-config-jitsi": "github:jitsi/eslint-config-jitsi#1.0.1", "eslint-plugin-flowtype": "2.50.3", "eslint-plugin-import": "2.14.0", "eslint-plugin-jsdoc": "3.8.0", diff --git a/react/features/app/actions.js b/react/features/app/actions.js index 75f7b7645d..fe6ec4edff 100644 --- a/react/features/app/actions.js +++ b/react/features/app/actions.js @@ -31,176 +31,70 @@ declare var APP: Object; * @returns {Function} */ export function appNavigate(uri: ?string) { - return (dispatch: Dispatch, getState: Function) => - _appNavigateToOptionalLocation(dispatch, getState, parseURIString(uri)); -} + return async (dispatch: Dispatch, getState: Function) => { + let location = parseURIString(uri); -/** - * Triggers an in-app navigation to a specific location URI. - * - * @param {Dispatch} dispatch - The redux {@code dispatch} function. - * @param {Function} getState - The redux function that gets/retrieves the redux - * state. - * @param {Object} newLocation - The location URI to navigate to. The value - * cannot be undefined and is assumed to have all properties such as - * {@code host}, {@code contextRoot}, and {@code room} defined. Depending on the - * property, it may have a value equal to {@code undefined} and that may be - * acceptable. - * @private - * @returns {Promise} - */ -function _appNavigateToMandatoryLocation( - dispatch: Dispatch, getState: Function, - newLocation: Object -): Promise { - const { room } = newLocation; - const locationURL = new URL(newLocation.toString()); + // If the specified location (URI) does not identify a host, use the app's + // default. + if (!location || !location.host) { + const defaultLocation = parseURIString(getDefaultURL(getState)); - dispatch(configWillLoad(locationURL)); + if (location) { + location.host = defaultLocation.host; - return ( - _loadConfig(dispatch, getState, newLocation) - .then( - config => loadConfigSettled(/* error */ undefined, config), - error => loadConfigSettled(error, /* config */ undefined)) - .then(() => dispatch(setRoom(room)))); + // FIXME Turn location's host, hostname, and port properties into + // setters in order to reduce the risks of inconsistent state. + location.hostname = defaultLocation.hostname; + location.pathname + = defaultLocation.pathname + location.pathname.substr(1); + location.port = defaultLocation.port; + location.protocol = defaultLocation.protocol; + } else { + location = defaultLocation; + } + } + + location.protocol || (location.protocol = 'https:'); + const locationURL = new URL(location.toString()); + + dispatch(configWillLoad(locationURL)); + + let protocol = location.protocol.toLowerCase(); + const { contextRoot, host, room } = location; + + // The React Native app supports an app-specific scheme which is sure to not + // be supported by fetch. + protocol !== 'http:' && protocol !== 'https:' && (protocol = 'https:'); + + const baseURL = `${protocol}//${host}${contextRoot || '/'}`; + let url = `${baseURL}config.js`; + + // XXX In order to support multiple shards, tell the room to the deployment. + room && (url += `?room=${room.toLowerCase()}`); + + let config; + + try { + config = await loadConfig(url); + dispatch(storeConfig(baseURL, config)); + } catch (error) { + config = restoreConfig(baseURL); + + if (!config) { + dispatch(loadConfigError(error, locationURL)); + + return; + } + } - /** - * Notifies that an attempt to load a configuration has completed. Due to - * the asynchronous nature of the loading, the specified {@code config} may - * or may not be required by the time the notification arrives. - * - * @param {string|undefined} error - If the loading has failed, the error - * detailing the cause of the failure. - * @param {Object|undefined} config - If the loading has succeeded, the - * loaded configuration. - * @returns {void} - */ - function loadConfigSettled(error, config) { - // Due to the asynchronous nature of the loading, the specified config - // may or may not be required by the time the notification arrives. If - // we receive the config for a location we are no longer interested in, - // "ignore" it - deliver it to the external API, for example, but do not - // proceed with the appNavigate procedure/process. if (getState()['features/base/config'].locationURL === locationURL) { dispatch(setLocationURL(locationURL)); dispatch(setConfig(config)); + dispatch(setRoom(room)); } else { - // eslint-disable-next-line no-param-reassign - error || (error = new Error('Config no longer needed!')); - - // XXX The failure could be, for example, because of a - // certificate-related error. In which case the connection will fail - // later in Strophe anyway. - dispatch(loadConfigError(error, locationURL)); - - throw error; + dispatch(loadConfigError(new Error('Config no longer needed!'), locationURL)); } - } -} - -/** - * Triggers an in-app navigation to a specific or undefined location (URI). - * - * @param {Dispatch} dispatch - The redux {@code dispatch} function. - * @param {Function} getState - The redux function that gets/retrieves the redux - * state. - * @param {Object} location - The location (URI) to navigate to. The value may - * be undefined. - * @private - * @returns {void} - */ -function _appNavigateToOptionalLocation( - dispatch: Dispatch, getState: Function, - location: Object) { - // If the specified location (URI) does not identify a host, use the app's - // default. - if (!location || !location.host) { - const defaultLocation = parseURIString(getDefaultURL(getState)); - - if (location) { - location.host = defaultLocation.host; - - // FIXME Turn location's host, hostname, and port properties into - // setters in order to reduce the risks of inconsistent state. - location.hostname = defaultLocation.hostname; - location.pathname - = defaultLocation.pathname + location.pathname.substr(1); - location.port = defaultLocation.port; - location.protocol = defaultLocation.protocol; - } else { - // eslint-disable-next-line no-param-reassign - location = defaultLocation; - } - } - - location.protocol || (location.protocol = 'https:'); - - return _appNavigateToMandatoryLocation(dispatch, getState, location); -} - -/** - * Loads config.js from a specific host. - * - * @param {Dispatch} dispatch - The redux {@code dispatch} function. - * @param {Function} getState - The redux {@code getState} function. - * @param {Object} location - The location URI which specifies the host to load - * the config.js from. - * @private - * @returns {Promise} - */ -function _loadConfig( - dispatch: Dispatch, - getState: Function, - { contextRoot, host, protocol, room }) { - // XXX As the mobile/React Native app does not employ config on the - // WelcomePage, do not download config.js from the deployment when - // navigating to the WelcomePage - the perceived/visible navigation will be - // faster. - if (!room && typeof APP === 'undefined') { - return Promise.resolve(); - } - - /* eslint-disable no-param-reassign */ - - protocol = protocol.toLowerCase(); - - // The React Native app supports an app-specific scheme which is sure to not - // be supported by fetch (or whatever loadConfig utilizes). - protocol !== 'http:' && protocol !== 'https:' && (protocol = 'https:'); - - // TDOO userinfo - - const baseURL = `${protocol}//${host}${contextRoot || '/'}`; - let url = `${baseURL}config.js`; - - // XXX In order to support multiple shards, tell the room to the deployment. - room && (url += `?room=${room.toLowerCase()}`); - - /* eslint-enable no-param-reassign */ - - return loadConfig(url).then( - /* onFulfilled */ config => { - // FIXME If the config is no longer needed (in the terms of - // _loadConfig) and that happened because of an intervening - // _loadConfig for the same baseURL, then the unneeded config may be - // stored after the needed config. Anyway. - dispatch(storeConfig(baseURL, config)); - - return config; - }, - /* onRejected */ error => { - // XXX The (down)loading of config failed. Try to use the last - // successfully fetched for that deployment. It may not match the - // shard. - const config = restoreConfig(baseURL); - - if (config) { - return config; - } - - throw error; - }); + }; } /** diff --git a/react/features/app/components/index.js b/react/features/app/components/index.js index ac7ba3b3a2..8a04b4b5c2 100644 --- a/react/features/app/components/index.js +++ b/react/features/app/components/index.js @@ -1 +1,3 @@ +// @flow + export * from './App'; diff --git a/react/features/app/index.js b/react/features/app/index.js index 0f9be4294f..46a00713e0 100644 --- a/react/features/app/index.js +++ b/react/features/app/index.js @@ -1,3 +1,5 @@ +// @flow + export * from './actions'; export * from './components'; export * from './functions'; diff --git a/react/features/base/lib-jitsi-meet/functions.js b/react/features/base/lib-jitsi-meet/functions.js index 9e016099e2..6e2c913ccf 100644 --- a/react/features/base/lib-jitsi-meet/functions.js +++ b/react/features/base/lib-jitsi-meet/functions.js @@ -100,20 +100,14 @@ export function isFatalJitsiConnectionError(error: Object | string) { * Loads config.js from a specific remote server. * * @param {string} url - The URL to load. - * @param {number} [timeout] - The timeout in milliseconds for the {@code url} - * to load. If not specified, a default value deemed appropriate for the purpose - * is used. * @returns {Promise} */ -export function loadConfig( - url: string, - timeout: ?number = 10 /* seconds */ * 1000 /* in milliseconds */ -): Promise { +export function loadConfig(url: string): Promise { let promise; if (typeof APP === 'undefined') { promise - = loadScript(url, timeout) + = loadScript(url, 2.5 * 1000 /* Timeout in ms */) .then(() => { const { config } = window; diff --git a/webpack.config.js b/webpack.config.js index c026d27678..fd017fe98a 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -56,7 +56,20 @@ const config = { // Tell babel to avoid compiling imports into CommonJS // so that webpack may do tree shaking. - { modules: false } + { + modules: false, + + // Specify our target browsers so no transpiling is + // done unnecessarily. For browsers not specified + // here, the ES2015+ profile will be used. + targets: { + chrome: 58, + electron: 2, + firefox: 54, + safari: 11 + } + + } ], require.resolve('@babel/preset-flow'), require.resolve('@babel/preset-react')