core: refactor routing (continued)

This commit is contained in:
Lyubo Marinov 2018-07-11 22:57:44 -05:00
parent 155e02bbfb
commit c203215c54
12 changed files with 72 additions and 84 deletions

View File

@ -2320,13 +2320,14 @@ export default {
* @private
*/
_initDeviceList() {
if (JitsiMeetJS.mediaDevices.isDeviceListAvailable()
&& JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
JitsiMeetJS.mediaDevices.enumerateDevices(devices => {
// Ugly way to synchronize real device IDs with local
// storage and settings menu. This is a workaround until
// getConstraints() method will be implemented
// in browsers.
const { mediaDevices } = JitsiMeetJS;
if (mediaDevices.isDeviceListAvailable()
&& mediaDevices.isDeviceChangeAvailable()) {
mediaDevices.enumerateDevices(devices => {
// Ugly way to synchronize real device IDs with local storage
// and settings menu. This is a workaround until
// getConstraints() method will be implemented in browsers.
const { dispatch } = APP.store;
if (this.localAudio) {
@ -2334,7 +2335,6 @@ export default {
micDeviceId: this.localAudio.getDeviceId()
}));
}
if (this.localVideo) {
dispatch(updateSettings({
cameraDeviceId: this.localVideo.getDeviceId()
@ -2347,9 +2347,8 @@ export default {
});
this.deviceChangeListener = devices =>
window.setTimeout(
() => this._onDeviceListChanged(devices), 0);
JitsiMeetJS.mediaDevices.addEventListener(
window.setTimeout(() => this._onDeviceListChanged(devices), 0);
mediaDevices.addEventListener(
JitsiMediaDevicesEvents.DEVICE_LIST_CHANGED,
this.deviceChangeListener);
}

View File

@ -78,10 +78,10 @@ function _appNavigateToMandatoryLocation(
*/
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.
// 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));
@ -90,8 +90,8 @@ function _appNavigateToMandatoryLocation(
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.
// certificate-related error. In which case the connection will fail
// later in Strophe anyway.
dispatch(loadConfigError(error, locationURL));
throw error;

View File

@ -23,8 +23,8 @@ import { OverlayContainer } from '../../overlay';
import { appNavigate, appWillMount, appWillUnmount } from '../actions';
/**
* The default URL to open if no other was specified to {@code AbstractApp}
* via props.
* The default URL to open if no other was specified to {@code AbstractApp} via
* props.
*
* FIXME: This is not at the best place here. This should be either in the
* base/settings feature or a default in base/config.
@ -78,6 +78,12 @@ export class AbstractApp extends Component {
this.state = {
/**
* The state of the »possible« async initialization of
* the {@code AbstractApp}.
*/
appAsyncInitialized: false,
/**
* The Route rendered by this {@code AbstractApp}.
*
@ -85,12 +91,6 @@ export class AbstractApp extends Component {
*/
route: {},
/**
* The state of the »possible« async initialization of
* the {@code AbstractApp}.
*/
appAsyncInitialized: false,
/**
* The redux store used by this {@code AbstractApp}.
*
@ -239,8 +239,7 @@ export class AbstractApp extends Component {
* @returns {ReactElement}
*/
render() {
const { appAsyncInitialized, route } = this.state;
const { component } = route;
const { appAsyncInitialized, route: { component } } = this.state;
if (appAsyncInitialized && component) {
return (
@ -357,7 +356,7 @@ export class AbstractApp extends Component {
return (
this.props.defaultURL
|| this._getStore().getState()['features/base/settings']
.serverURL
.serverURL
|| DEFAULT_URL);
}
@ -435,9 +434,7 @@ export class AbstractApp extends Component {
// performed before setState completes, the app may not navigate to the
// expected route. In order to mitigate the problem, _navigate was
// changed to return a Promise.
return new Promise(resolve => {
this.setState({ route }, resolve);
});
return new Promise(resolve => this.setState({ route }, resolve));
}
/**

View File

@ -3,7 +3,6 @@
import { NativeModules } from 'react-native';
export * from './functions.any';
export * from './router';
/**
* Returns application name.

View File

@ -1,7 +1,6 @@
// @flow
export * from './functions.any';
export * from './router';
declare var interfaceConfig: Object;

View File

@ -1,4 +1,5 @@
// @flow
import type { Component } from 'react';
import { isRoomValid } from '../base/conference';
@ -35,11 +36,11 @@ export type Route = {
* Determines which route is to be rendered in order to depict a specific Redux
* store.
*
* @param {(Object|Function)} stateful - Redux state or Regux getState()
* method.
* @param {(Function|Object)} stateful - THe redux store, state, or
* {@code getState} function.
* @returns {Promise<Route>}
*/
export function getRouteToRender(stateful: Object | Function): Promise<Route> {
export function _getRouteToRender(stateful: Function | Object): Promise<Route> {
const state = toState(stateful);
const { room } = state['features/base/conference'];
const isMobileApp = navigator.product === 'ReactNative';
@ -51,11 +52,11 @@ export function getRouteToRender(stateful: Object | Function): Promise<Route> {
};
return new Promise(resolve => {
// First check if the current endpoint supports WebRTC. We are
// First, check if the current endpoint supports WebRTC. We are
// intentionally not performing the check for mobile browsers because:
// - the welcome page is mobile ready
// - if the URL points to a conference, getDeepLinkingPage will take
// care of it
// - the WelcomePage is mobile ready;
// - if the URL points to a conference, getDeepLinkingPage will take
// care of it.
if (!isMobileBrowser && !JitsiMeetJS.isWebRtcSupported()) {
route.component = UnsupportedDesktopBrowser;
resolve(route);
@ -70,8 +71,8 @@ export function getRouteToRender(stateful: Object | Function): Promise<Route> {
} else {
// Update the location if it doesn't match. This happens when a
// room is joined from the welcome page. The reason for doing
// this instead of using the history API is that we want to
// load the config.js which takes the room into account.
// this instead of using the history API is that we want to load
// the config.js which takes the room into account.
const { locationURL } = state['features/base/connection'];
// eslint-disable-next-line no-negated-condition
@ -91,8 +92,8 @@ export function getRouteToRender(stateful: Object | Function): Promise<Route> {
}
if (!isWelcomePageUserEnabled(state)) {
// Web: if the welcome page is disabled, go directly to a
// random room.
// Web: if the welcome page is disabled, go directly to a random
// room.
let href = window.location.href;

View File

@ -7,7 +7,7 @@ import {
} from '../base/connection';
import { MiddlewareRegistry } from '../base/redux';
import { getRouteToRender } from './router';
import { _getRouteToRender } from './getRouteToRender';
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
@ -74,7 +74,7 @@ function _navigate({ getState }) {
const state = getState();
const { app } = state['features/app'];
getRouteToRender(state).then(route => app._navigate(route));
_getRouteToRender(state).then(route => app._navigate(route));
}
/**

View File

@ -149,6 +149,24 @@ const logger = require('jitsi-meet-logger').getLogger(__filename);
export { default as getRoomName } from './getRoomName';
export { parseURLParams };
/**
* 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 from which the config is to be
* obtained.
* @param {string} room - Room name.
* @private
* @returns {Promise<void>}
*/
export function obtainConfig(location: string, room: string): Promise<void> {
return new Promise((resolve, reject) =>
_obtainConfig(location, room, (success, error) => {
success ? resolve() : reject(error);
})
);
}
/**
* Sends HTTP POST request to specified {@code endpoint}. In request the name
* of the room is included in JSON format:
@ -163,10 +181,7 @@ export { parseURLParams };
* @param {Function} complete - The callback to invoke upon success or failure.
* @returns {void}
*/
export function obtainConfig(
endpoint: string,
roomName: string,
complete: Function) {
function _obtainConfig(endpoint: string, roomName: string, complete: Function) {
logger.info(`Send config request to ${endpoint} for room: ${roomName}`);
$.ajax(
endpoint,

View File

@ -20,10 +20,8 @@ export {
*/
export function connect() {
return (dispatch: Dispatch<*>, getState: Function) => {
const state = getState();
// XXX Lib-jitsi-meet does not accept uppercase letters.
const room = state['features/base/conference'].room.toLowerCase();
const room = getState()['features/base/conference'].room.toLowerCase();
// XXX For web based version we use conference initialization logic
// from the old app (at the moment of writing).

View File

@ -184,8 +184,6 @@ class Conference extends Component<Props> {
componentWillReceiveProps(nextProps: Props) {
const {
_locationURL: oldLocationURL,
_onConnect,
_onDisconnect,
_participantCount: oldParticipantCount,
_room: oldRoom,
_setToolboxVisible
@ -197,10 +195,10 @@ class Conference extends Component<Props> {
} = nextProps;
// If the location URL changes we need to reconnect.
oldLocationURL !== newLocationURL && _onDisconnect();
oldLocationURL !== newLocationURL && this.props._onDisconnect();
// Start the connection process when there is a (valid) room.
oldRoom !== newRoom && newRoom && _onConnect();
oldRoom !== newRoom && newRoom && this.props._onConnect();
if (oldParticipantCount === 1) {
newParticipantCount > 1 && _setToolboxVisible(false);
@ -342,9 +340,7 @@ class Conference extends Component<Props> {
* @returns {React$Node}
*/
_renderConferenceNotification() {
return ConferenceNotification
? <ConferenceNotification />
: undefined;
return ConferenceNotification ? <ConferenceNotification /> : undefined;
}
}
@ -356,6 +352,7 @@ class Conference extends Component<Props> {
* @returns {{
* _onConnect: Function,
* _onDisconnect: Function,
* _onHardwareBackPress: Function,
* _setToolboxVisible: Function
* }}
*/

View File

@ -28,24 +28,6 @@ declare var interfaceConfig: Object;
const logger = require('jitsi-meet-logger').getLogger(__filename);
/**
* 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 from which the config is to be
* obtained.
* @param {string} room - Room name.
* @private
* @returns {Promise}
*/
function _obtainConfig(location: string, room: string) {
return new Promise((resolve, reject) =>
obtainConfig(location, room, (success, error) => {
success ? resolve() : reject(error);
})
);
}
/**
* DOM events for when full screen mode has changed. Different browsers need
* different vendor prefixes.
@ -119,7 +101,7 @@ class Conference extends Component<Props> {
const { configLocation } = config;
if (configLocation) {
_obtainConfig(configLocation, this.props._room)
obtainConfig(configLocation, this.props._room)
.then(() => {
const now = window.performance.now();
@ -133,8 +115,8 @@ class Conference extends Component<Props> {
// Show obtain config error.
APP.UI.messageHandler.showError({
titleKey: 'connection.CONNFAIL',
descriptionKey: 'dialog.connectError'
descriptionKey: 'dialog.connectError',
titleKey: 'connection.CONNFAIL'
});
});
} else {
@ -253,7 +235,8 @@ class Conference extends Component<Props> {
* @param {Object} state - The Redux state.
* @private
* @returns {{
* _iAmRecorder: boolean
* _iAmRecorder: boolean,
* _room: ?string
* }}
*/
function _mapStateToProps(state) {

View File

@ -10,11 +10,11 @@ import { NetworkActivityIndicator } from '../../mobile/network-activity';
import LocalVideoTrackUnderlay from './LocalVideoTrackUnderlay';
/**
* {@code BlankPage} React {@code Component}'s prop types.
* The type of React {@code Component} props of {@link BlankPage}.
*/
type Props = {
dispatch: Dispatch<*>
}
};
/**
* The React {@code Component} displayed by {@code AbstractApp} when it has no