Remove duplication, simplify, comply with coding style

This commit is contained in:
Lyubomir Marinov 2017-01-10 15:55:31 -06:00
parent 4d5f82633b
commit 0912dbf130
15 changed files with 245 additions and 458 deletions

View File

@ -1,4 +1,5 @@
/* global APP, JitsiMeetJS, $, config, interfaceConfig, toastr */ /* global APP, JitsiMeetJS, $, config, interfaceConfig, toastr */
const logger = require("jitsi-meet-logger").getLogger(__filename); const logger = require("jitsi-meet-logger").getLogger(__filename);
var UI = {}; var UI = {};

View File

@ -1,17 +1,8 @@
import { setRoom } from '../base/conference'; import { setRoom } from '../base/conference';
import { import { getDomain, setDomain } from '../base/connection';
getDomain, import { loadConfig, setConfig } from '../base/lib-jitsi-meet';
setDomain
} from '../base/connection';
import {
loadConfig,
setConfig
} from '../base/lib-jitsi-meet';
import { import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from './actionTypes';
APP_WILL_MOUNT,
APP_WILL_UNMOUNT
} from './actionTypes';
import { import {
_getRoomAndDomainFromUrlString, _getRoomAndDomainFromUrlString,
_getRouteToRender, _getRouteToRender,
@ -20,9 +11,9 @@ import {
import './reducer'; import './reducer';
/** /**
* Temporary solution. Should dispatch actions related to * Temporary solution. Should dispatch actions related to initial settings of
* initial settings of the app like setting log levels, * the app like setting log levels, reading the config parameters from query
* reading the config parameters from query string etc. * string etc.
* *
* @returns {Function} * @returns {Function}
*/ */

View File

@ -1,13 +1,7 @@
/* global $ */
import React from 'react'; import React from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { import { browserHistory, Route, Router } from 'react-router';
browserHistory,
Route,
Router
} from 'react-router';
import { push, syncHistoryWithStore } from 'react-router-redux'; import { push, syncHistoryWithStore } from 'react-router-redux';
import { compose } from 'redux';
import { getDomain } from '../../base/connection'; import { getDomain } from '../../base/connection';
import { RouteRegistry } from '../../base/navigator'; import { RouteRegistry } from '../../base/navigator';
@ -45,9 +39,6 @@ export class App extends AbstractApp {
this.history = syncHistoryWithStore(browserHistory, props.store); this.history = syncHistoryWithStore(browserHistory, props.store);
// Bind event handlers so they are only bound once for every instance. // Bind event handlers so they are only bound once for every instance.
this._getRoute = this._getRoute.bind(this);
this._getRoutes = this._getRoutes.bind(this);
this._onRouteEnter = this._onRouteEnter.bind(this);
this._routerCreateElement = this._routerCreateElement.bind(this); this._routerCreateElement = this._routerCreateElement.bind(this);
} }
@ -74,44 +65,14 @@ export class App extends AbstractApp {
<Router <Router
createElement = { this._routerCreateElement } createElement = { this._routerCreateElement }
history = { this.history }> history = { this.history }>
{ this._getRoutes() } {
this._renderRoutes()
}
</Router> </Router>
</Provider> </Provider>
); );
} }
/**
* Method returns route for React Router.
*
* @param {Object} route - Object that describes route.
* @returns {ReactElement}
* @private
*/
_getRoute(route) {
const onEnter = route.onEnter || $.noop;
const handler = compose(this._onRouteEnter, onEnter);
return (
<Route
component = { route.component }
key = { route.component }
onEnter = { handler }
path = { route.path } />
);
}
/**
* Returns routes for application.
*
* @returns {Array}
* @private
*/
_getRoutes() {
const routes = RouteRegistry.getRoutes();
return routes.map(this._getRoute);
}
/** /**
* Navigates to a specific Route (via platform-specific means). * Navigates to a specific Route (via platform-specific means).
* *
@ -137,10 +98,18 @@ export class App extends AbstractApp {
* Invoked by react-router to notify this App that a Route is about to be * Invoked by react-router to notify this App that a Route is about to be
* rendered. * rendered.
* *
* @param {Route} route - The Route that is about to be rendered.
* @private * @private
* @returns {void} * @returns {void}
*/ */
_onRouteEnter() { _onRouteEnter(route, ...args) {
// Notify the route that it is about to be entered.
const onEnter = route.onEnter;
if (typeof onEnter === 'function') {
onEnter(...args);
}
// XXX The following is mandatory. Otherwise, moving back & forward // XXX The following is mandatory. Otherwise, moving back & forward
// through the browser's history could leave this App on the Conference // through the browser's history could leave this App on the Conference
// page without a room name. // page without a room name.
@ -159,6 +128,37 @@ export class App extends AbstractApp {
this._openURL(url); this._openURL(url);
} }
/**
* Renders a specific Route (for the purposes of the Router of this App).
*
* @param {Object} route - The Route to render.
* @returns {ReactElement}
* @private
*/
_renderRoute(route) {
const onEnter = (...args) => {
this._onRouteEnter(route, ...args);
};
return (
<Route
component = { route.component }
key = { route.component }
onEnter = { onEnter }
path = { route.path } />
);
}
/**
* Renders the Routes of the Router of this App.
*
* @returns {Array.<ReactElement>}
* @private
*/
_renderRoutes() {
return RouteRegistry.getRoutes().map(this._renderRoute, this);
}
/** /**
* Create a ReactElement from the specified component and props on behalf of * Create a ReactElement from the specified component and props on behalf of
* the associated Router. * the associated Router.

View File

@ -1,143 +1,24 @@
/* global APP, JitsiMeetJS, loggingConfig */ /* global APP, JitsiMeetJS, loggingConfig */
import { isRoomValid } from '../base/conference';
import { RouteRegistry } from '../base/navigator';
import { Conference } from '../conference';
import { WelcomePage } from '../welcome';
import getTokenData from '../../../modules/tokendata/TokenData';
import settings from '../../../modules/settings/Settings';
import URLProcessor from '../../../modules/config/URLProcessor'; import URLProcessor from '../../../modules/config/URLProcessor';
import KeyboardShortcut
from '../../../modules/keyboardshortcut/keyboardshortcut';
import settings from '../../../modules/settings/Settings';
import getTokenData from '../../../modules/tokendata/TokenData';
import JitsiMeetLogStorage from '../../../modules/util/JitsiMeetLogStorage'; import JitsiMeetLogStorage from '../../../modules/util/JitsiMeetLogStorage';
// eslint-disable-next-line max-len
import KeyboardShortcut from '../../../modules/keyboardshortcut/keyboardshortcut';
const Logger = require('jitsi-meet-logger'); const Logger = require('jitsi-meet-logger');
const LogCollector = Logger.LogCollector;
export * from './functions.native';
/** /**
* Gets room name and domain from URL object. * Temporary solution. Later we'll get rid of global APP and set its properties
* * in redux store.
* @param {URL} url - URL object.
* @private
* @returns {{
* domain: (string|undefined),
* room: (string|undefined)
* }}
*/
function _getRoomAndDomainFromUrlObject(url) {
let domain;
let room;
if (url) {
domain = url.hostname;
room = url.pathname.substr(1);
// Convert empty string to undefined to simplify checks.
if (room === '') {
room = undefined;
}
if (domain === '') {
domain = undefined;
}
}
return {
domain,
room
};
}
/**
* Gets conference room name and connection domain from URL.
*
* @param {(string|undefined)} url - URL.
* @returns {{
* domain: (string|undefined),
* room: (string|undefined)
* }}
*/
export function _getRoomAndDomainFromUrlString(url) {
// Rewrite the specified URL in order to handle special cases such as
// hipchat.com and enso.me which do not follow the common pattern of most
// Jitsi Meet deployments.
if (typeof url === 'string') {
// hipchat.com
let regex = /^(https?):\/\/hipchat.com\/video\/call\//gi;
let match = regex.exec(url);
if (!match) {
// enso.me
regex = /^(https?):\/\/enso\.me\/(?:call|meeting)\//gi;
match = regex.exec(url);
}
if (match && match.length > 1) {
/* eslint-disable no-param-reassign, prefer-template */
url
= match[1] /* URL protocol */
+ '://enso.hipchat.me/'
+ url.substring(regex.lastIndex);
/* eslint-enable no-param-reassign, prefer-template */
}
}
return _getRoomAndDomainFromUrlObject(_urlStringToObject(url));
}
/**
* Determines which route is to be rendered in order to depict a specific Redux
* store.
*
* @param {(Object|Function)} stateOrGetState - Redux state or Regux getState()
* method.
* @returns {Route}
*/
export function _getRouteToRender(stateOrGetState) {
const state
= typeof stateOrGetState === 'function'
? stateOrGetState()
: stateOrGetState;
const room = state['features/base/conference'].room;
const component = isRoomValid(room) ? Conference : WelcomePage;
return RouteRegistry.getRouteByComponent(component);
}
/**
* Parses a string into a URL (object).
*
* @param {(string|undefined)} url - The URL to parse.
* @private
* @returns {URL}
*/
function _urlStringToObject(url) {
let urlObj;
if (url) {
try {
urlObj = new URL(url);
} catch (ex) {
// The return value will signal the failure & the logged
// exception will provide the details to the developers.
console.log(`${url} seems to be not a valid URL, but it's OK`, ex);
}
}
return urlObj;
}
/**
* Temporary solution. Later we'll get rid of global APP
* and set its properties in redux store.
* *
* @returns {void} * @returns {void}
*/ */
export function init() { export function init() {
_setConfigParametersFromUrl(); URLProcessor.setConfigParametersFromUrl();
_initLogging(); _initLogging();
APP.keyboardshortcut = KeyboardShortcut; APP.keyboardshortcut = KeyboardShortcut;
@ -147,36 +28,14 @@ export function init() {
APP.translation.init(settings.getLanguage()); APP.translation.init(settings.getLanguage());
} }
/**
* Initializes logging in the app.
*
* @private
* @returns {void}
*/
function _initLogging() {
// Adjust logging level
configureLoggingLevels();
// Create the LogCollector and register it as the global log transport.
// It is done early to capture as much logs as possible. Captured logs
// will be cached, before the JitsiMeetLogStorage gets ready (statistics
// module is initialized).
if (!APP.logCollector && !loggingConfig.disableLogCollector) {
APP.logCollector = new LogCollector(new JitsiMeetLogStorage());
Logger.addGlobalTransport(APP.logCollector);
JitsiMeetJS.addGlobalLogTransport(APP.logCollector);
}
}
/** /**
* Adjusts the logging levels. * Adjusts the logging levels.
* *
* @private * @private
* @returns {void} * @returns {void}
*/ */
function configureLoggingLevels() { function _configureLoggingLevels() {
// NOTE The library Logger is separated from // NOTE The library Logger is separated from the app loggers, so the levels
// the app loggers, so the levels
// have to be set in two places // have to be set in two places
// Set default logging level // Set default logging level
@ -186,8 +45,8 @@ function configureLoggingLevels() {
Logger.setLogLevel(defaultLogLevel); Logger.setLogLevel(defaultLogLevel);
JitsiMeetJS.setLogLevel(defaultLogLevel); JitsiMeetJS.setLogLevel(defaultLogLevel);
// NOTE console was used on purpose here to go around the logging // NOTE console was used on purpose here to go around the logging and always
// and always print the default logging level to the console // print the default logging level to the console
console.info(`Default logging level set to: ${defaultLogLevel}`); console.info(`Default logging level set to: ${defaultLogLevel}`);
// Set log level for each logger // Set log level for each logger
@ -204,11 +63,22 @@ function configureLoggingLevels() {
} }
/** /**
* Sets config parameters from query string. * Initializes logging in the app.
* *
* @private * @private
* @returns {void} * @returns {void}
*/ */
function _setConfigParametersFromUrl() { function _initLogging() {
URLProcessor.setConfigParametersFromUrl(); // Adjust logging level
_configureLoggingLevels();
// Create the LogCollector and register it as the global log transport. It
// is done early to capture as much logs as possible. Captured logs will be
// cached, before the JitsiMeetLogStorage gets ready (statistics module is
// initialized).
if (!APP.logCollector && !loggingConfig.disableLogCollector) {
APP.logCollector = new Logger.LogCollector(new JitsiMeetLogStorage());
Logger.addGlobalTransport(APP.logCollector);
JitsiMeetJS.addGlobalLogTransport(APP.logCollector);
}
} }

View File

@ -1,14 +1,12 @@
/* global APP, JitsiMeetJS */ /* global APP, JitsiMeetJS */
import {
SET_DOMAIN
} from './actionTypes';
import './reducer';
import UIEvents from '../../../../service/UI/UIEvents'; import UIEvents from '../../../../service/UI/UIEvents';
const logger = require('jitsi-meet-logger').getLogger(__filename); import { SET_DOMAIN } from './actionTypes';
const ConferenceEvents = JitsiMeetJS.events.conference; import './reducer';
const JitsiConferenceEvents = JitsiMeetJS.events.conference;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/** /**
* Opens new connection. * Opens new connection.
@ -42,7 +40,7 @@ export function connect() {
// room. It will then restart the media session when someone // room. It will then restart the media session when someone
// eventually join the room which will start the stats again. // eventually join the room which will start the stats again.
APP.conference.addConferenceListener( APP.conference.addConferenceListener(
ConferenceEvents.BEFORE_STATISTICS_DISPOSED, JitsiConferenceEvents.BEFORE_STATISTICS_DISPOSED,
() => { () => {
if (APP.logCollector) { if (APP.logCollector) {
APP.logCollector.flush(); APP.logCollector.flush();
@ -74,8 +72,8 @@ export function connect() {
* @returns {Function} * @returns {Function}
*/ */
export function disconnect() { export function disconnect() {
// XXX For web based version we use conference // XXX For web based version we use conference hanging up logic from the old
// hanging up logic from the old app. // app.
return () => APP.conference.hangup(); return () => APP.conference.hangup();
} }

View File

@ -1,5 +1,3 @@
import React from 'react';
import JitsiMeetJS from './'; import JitsiMeetJS from './';
import { import {
LIB_DISPOSED, LIB_DISPOSED,
@ -42,9 +40,9 @@ export function initLib() {
throw new Error('Cannot initialize lib-jitsi-meet without config'); throw new Error('Cannot initialize lib-jitsi-meet without config');
} }
if (!React.View) {
// XXX Temporarily until conference.js is moved to the React app we // XXX Temporarily until conference.js is moved to the React app we
// shouldn't use JitsiMeetJS from the React app. // shouldn't use JitsiMeetJS from the React app.
if (typeof APP !== 'undefined') {
return Promise.resolve(); return Promise.resolve();
} }

View File

@ -1,5 +1,3 @@
import React from 'react';
import { loadScript } from '../../base/util'; import { loadScript } from '../../base/util';
/** /**
@ -10,10 +8,10 @@ import { loadScript } from '../../base/util';
* @returns {Promise<Object>} * @returns {Promise<Object>}
*/ */
export function loadConfig(host, path = '/config.js') { export function loadConfig(host, path = '/config.js') {
if (!React.View) { // Returns config.js file from global scope. We can't use the version that's
// Returns config.js file from global scope. We can't use the version // being used for the React Native app because the old/current Web app uses
// that's being used for the React Native app because the old/current // config from the global scope.
// Web app uses config from the global scope. if (typeof APP !== 'undefined') {
return Promise.resolve(window.config); return Promise.resolve(window.config);
} }

View File

@ -1,67 +0,0 @@
/* global APP, config */
import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
import BoshAddressChoice from '../../../modules/config/BoshAddressChoice';
import { obtainConfig, setTokenData } from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* If we have an HTTP endpoint for getting config.json configured
* we're going to read it and override properties from config.js and
* interfaceConfig.js. If there is no endpoint we'll just
* continue with initialization.
* Keep in mind that if the endpoint has been configured and we fail
* to obtain the config for any reason then the conference won't
* start and error message will be displayed to the user.
*
* @returns {Function}
*/
export function obtainConfigAndInit() {
return () => {
const room = APP.conference.roomName;
if (config.configLocation) {
const location = config.configLocation;
obtainConfig(location, room)
.then(_obtainConfigHandler)
.then(_initConference)
.catch(err => {
// Show obtain config error,
// pass the error object for report
APP.UI.messageHandler.openReportDialog(
null, 'dialog.connectError', err);
});
} else {
BoshAddressChoice.chooseAddress(config, room);
_initConference();
}
};
}
/**
* Obtain config handler.
*
* @returns {Promise}
* @private
*/
function _obtainConfigHandler() {
const now = window.performance.now();
APP.connectionTimes['configuration.fetched'] = now;
logger.log('(TIME) configuration fetched:\t', now);
return Promise.resolve();
}
/**
* Initialization of the app.
*
* @returns {void}
* @private
*/
function _initConference() {
setTokenData();
// Initialize the conference URL handler
APP.ConferenceUrl = new ConferenceUrl(window.location);
}

View File

@ -1,11 +1,9 @@
/* global $, APP, interfaceConfig */ /* global $, APP, interfaceConfig */
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect as reactReduxConnect } from 'react-redux'; import { connect as reactReduxConnect } from 'react-redux';
import { import { connect, disconnect } from '../../base/connection';
connect,
disconnect
} from '../../base/connection';
/** /**
* For legacy reasons, inline style for display none. * For legacy reasons, inline style for display none.
@ -19,6 +17,16 @@ const DISPLAY_NONE_STYLE = {
* Implements a React Component which renders initial conference layout * Implements a React Component which renders initial conference layout
*/ */
class Conference extends Component { class Conference extends Component {
/**
* Conference component's property types.
*
* @static
*/
static propTypes = {
dispatch: React.PropTypes.func
}
/** /**
* Until we don't rewrite UI using react components * Until we don't rewrite UI using react components
* we use UI.start from old app. Also method translates * we use UI.start from old app. Also method translates
@ -45,15 +53,6 @@ class Conference extends Component {
this.props.dispatch(disconnect()); this.props.dispatch(disconnect());
} }
/**
* Conference component's property types.
*
* @static
*/
static propTypes = {
dispatch: React.PropTypes.func
};
/** /**
* Initializes Conference component instance. * Initializes Conference component instance.
* *

View File

@ -1,108 +0,0 @@
/* global APP, config */
import HttpConfigFetch from '../../../modules/config/HttpConfigFetch';
import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
import BoshAddressChoice from '../../../modules/config/BoshAddressChoice';
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* If we have an HTTP endpoint for getting config.json configured
* we're going to read it and override properties from config.js and
* interfaceConfig.js. If there is no endpoint we'll just
* continue with initialization.
* Keep in mind that if the endpoint has been configured and we fail
* to obtain the config for any reason then the conference won't
* start and error message will be displayed to the user.
*
* @returns {Function}
*/
export function obtainConfigAndInit() {
// Skip initialization if conference is already initialized
if (!APP.ConferenceUrl) {
const room = APP.conference.roomName;
if (config.configLocation) {
const location = config.configLocation;
obtainConfig(location, room)
.then(_obtainConfigHandler)
.then(_initConference)
.catch(err => {
// Show obtain config error,
// pass the error object for report
APP.UI.messageHandler.openReportDialog(
null, 'dialog.connectError', err);
});
} else {
BoshAddressChoice.chooseAddress(config, room);
_initConference();
}
}
}
/**
* Obtain config handler.
*
* @returns {Promise}
* @private
*/
function _obtainConfigHandler() {
const now = window.performance.now();
APP.connectionTimes['configuration.fetched'] = now;
logger.log('(TIME) configuration fetched:\t', now);
return Promise.resolve();
}
/**
* Initialization of the app.
*
* @returns {void}
* @private
*/
function _initConference() {
setTokenData();
// Initialize the conference URL handler
APP.ConferenceUrl = new ConferenceUrl(window.location);
}
/**
* Promise wrapper on obtain config method.
* When HttpConfigFetch will be moved to React app
* it's better to use load config instead.
*
* @param {string} location - URL of the domain.
* @param {string} room - Room name.
* @returns {Promise}
*/
export function obtainConfig(location, room) {
return new Promise((resolve, reject) => {
HttpConfigFetch.obtainConfig(location, room, (success, error) => {
if (success) {
resolve();
} else {
reject(error);
}
});
});
}
/**
* If JWT token data it will be used for local user settings.
*
* @returns {void}
*/
export function setTokenData() {
const localUser = APP.tokenData.caller;
if (localUser) {
const email = localUser.getEmail();
const avatarUrl = localUser.getAvatarUrl();
const name = localUser.getName();
APP.settings.setEmail((email || '').trim(), true);
APP.settings.setAvatarUrl((avatarUrl || '').trim());
APP.settings.setDisplayName((name || '').trim(), true);
}
}

View File

@ -1,7 +1,14 @@
/* global APP, config */
import BoshAddressChoice from '../../../modules/config/BoshAddressChoice';
import HttpConfigFetch from '../../../modules/config/HttpConfigFetch';
import ConferenceUrl from '../../../modules/URL/ConferenceUrl';
import { RouteRegistry } from '../base/navigator'; import { RouteRegistry } from '../base/navigator';
import { Conference } from './components'; import { Conference } from './components';
import { obtainConfigAndInit } from './functions';
const logger = require('jitsi-meet-logger').getLogger(__filename);
/** /**
* Register route for Conference (page). * Register route for Conference (page).
@ -9,9 +16,111 @@ import { obtainConfigAndInit } from './functions';
RouteRegistry.register({ RouteRegistry.register({
component: Conference, component: Conference,
onEnter: () => { onEnter: () => {
// XXX: If config or jwt are set by hash or query parameters // XXX If config or jwt are set by hash or query parameters
// Getting raw URL before stripping it. // Getting raw URL before stripping it.
obtainConfigAndInit(); _obtainConfigAndInit();
}, },
path: '/:room' path: '/:room'
}); });
/**
* Initialization of the app.
*
* @private
* @returns {void}
*/
function _initConference() {
_setTokenData();
// Initialize the conference URL handler
APP.ConferenceUrl = new ConferenceUrl(window.location);
}
/**
* Promise wrapper on obtain config method. When HttpConfigFetch will be moved
* to React app it's better to use load config instead.
*
* @param {string} location - URL of the domain.
* @param {string} room - Room name.
* @private
* @returns {Promise}
*/
function _obtainConfig(location, room) {
return new Promise((resolve, reject) => {
HttpConfigFetch.obtainConfig(location, room, (success, error) => {
if (success) {
resolve();
} else {
reject(error);
}
});
});
}
/**
* If we have an HTTP endpoint for getting config.json configured we're going to
* read it and override properties from config.js and interfaceConfig.js. If
* there is no endpoint we'll just continue with initialization. Keep in mind
* that if the endpoint has been configured and we fail to obtain the config for
* any reason then the conference won't start and error message will be
* displayed to the user.
*
* @private
* @returns {void}
*/
function _obtainConfigAndInit() {
// Skip initialization if conference is initialized already.
if (typeof APP !== 'undefined' && !APP.ConferenceUrl) {
const location = config.configLocation;
const room = APP.conference.roomName;
if (location) {
_obtainConfig(location, room)
.then(() => {
_obtainConfigHandler();
_initConference();
})
.catch(err => {
// Show obtain config error.
APP.UI.messageHandler.openReportDialog(
null, 'dialog.connectError', err);
});
} else {
BoshAddressChoice.chooseAddress(config, room);
_initConference();
}
}
}
/**
* Obtain config handler.
*
* @private
* @returns {Promise}
*/
function _obtainConfigHandler() {
const now = window.performance.now();
APP.connectionTimes['configuration.fetched'] = now;
logger.log('(TIME) configuration fetched:\t', now);
}
/**
* If JWT token data it will be used for local user settings.
*
* @private
* @returns {void}
*/
function _setTokenData() {
const localUser = APP.tokenData.caller;
if (localUser) {
const email = localUser.getEmail();
const avatarUrl = localUser.getAvatarUrl();
const name = localUser.getName();
APP.settings.setEmail((email || '').trim(), true);
APP.settings.setAvatarUrl((avatarUrl || '').trim());
APP.settings.setDisplayName((name || '').trim(), true);
}
}

View File

@ -1,26 +1,10 @@
/* global APP */ /* global APP */
import { RouteRegistry } from '../base/navigator'; import { RouteRegistry } from '../base/navigator';
import { generateRoomWithoutSeparator } from '../base/util'; import { generateRoomWithoutSeparator } from '../base/util';
import { WelcomePage } from './components'; import { WelcomePage } from './components';
/**
* Function that checks if welcome page is enabled and if it isn't
* redirects to randomly created conference.
*
* @param {Object} nextState - Next router state.
* @param {Function} replace - Function to redirect to another path.
* @returns {void}
*/
function onEnter(nextState, replace) {
if (!APP.settings.isWelcomePageEnabled()) {
const generatedRoomname = generateRoomWithoutSeparator();
const normalizedRoomname = generatedRoomname.toLowerCase();
replace(`/${normalizedRoomname}`);
}
}
/** /**
* Register route for WelcomePage. * Register route for WelcomePage.
*/ */
@ -29,3 +13,20 @@ RouteRegistry.register({
onEnter, onEnter,
path: '/' path: '/'
}); });
/**
* If the Welcome page/screen is disabled, generates a (random) room (name) so
* that the Welcome page/screen is skipped and the Conference page/screen is
* presented instead.
*
* @param {Object} nextState - The next Router state.
* @param {Function} replace - The function to redirect to another path.
* @returns {void}
*/
function onEnter(nextState, replace) {
if (typeof APP !== 'undefined' && !APP.settings.isWelcomePageEnabled()) {
const room = generateRoomWithoutSeparator();
replace(`/${room}`);
}
}

View File

@ -61,7 +61,9 @@ class Root extends Component {
// XXX Start with an empty URL if getting the initial URL fails; // XXX Start with an empty URL if getting the initial URL fails;
// otherwise, nothing will be rendered. // otherwise, nothing will be rendered.
if (this.state.url !== null) {
this.setState({ url: null }); this.setState({ url: null });
}
}); });
} }

View File

@ -1,20 +1,15 @@
/* global APP */ /* global APP */
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { browserHistory } from 'react-router'; import { browserHistory } from 'react-router';
import { import { routerMiddleware, routerReducer } from 'react-router-redux';
routerMiddleware,
routerReducer
} from 'react-router-redux';
import { compose, createStore } from 'redux'; import { compose, createStore } from 'redux';
import Thunk from 'redux-thunk'; import Thunk from 'redux-thunk';
import config from './config'; import config from './config';
import { App } from './features/app'; import { App } from './features/app';
import { import { MiddlewareRegistry, ReducerRegistry } from './features/base/redux';
MiddlewareRegistry,
ReducerRegistry
} from './features/base/redux';
const logger = require('jitsi-meet-logger').getLogger(__filename); const logger = require('jitsi-meet-logger').getLogger(__filename);
@ -49,7 +44,7 @@ if (typeof window === 'object'
const store = createStore(reducer, middleware); const store = createStore(reducer, middleware);
/** /**
* Render the app when DOM tree has been loaded. * Renders the app when the DOM tree has been loaded.
*/ */
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const now = window.performance.now(); const now = window.performance.now();
@ -67,8 +62,8 @@ document.addEventListener('DOMContentLoaded', () => {
}); });
/** /**
* Stop collecting the logs and disposing the API when * Stops collecting the logs and disposing the API when the user closes the
* user closes the page. * page.
*/ */
window.addEventListener('beforeunload', () => { window.addEventListener('beforeunload', () => {
// Stop the LogCollector // Stop the LogCollector