[RN] Prepare to display BlankPage more
For example, while config.js and other files are being loaded before the navigation to Conference is feasible.
This commit is contained in:
parent
6545a7a1bb
commit
45a1ae26ca
|
@ -46,22 +46,22 @@ function _appNavigateToMandatoryLocation(
|
|||
.then(() => dispatch(setRoom(newLocation.room)));
|
||||
|
||||
/**
|
||||
* Notifies that an attempt to load a config(uration) has completed. Due to
|
||||
* the asynchronous native of the loading, the specified <tt>config</tt> may
|
||||
* Notifies that an attempt to load a configuration has completed. Due to
|
||||
* the asynchronous nature of the loading, the specified <tt>config</tt> may
|
||||
* or may not be required by the time the notification arrives.
|
||||
*
|
||||
* @param {string|undefined} err - If the loading has failed, the error
|
||||
* @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 config(uration).
|
||||
* loaded configuration.
|
||||
* @returns {void}
|
||||
*/
|
||||
function configLoaded(err, config) {
|
||||
// FIXME Due to the asynchronous native of the loading, the specified
|
||||
function configLoaded(error, config) {
|
||||
// FIXME Due to the asynchronous nature of the loading, the specified
|
||||
// config may or may not be required by the time the notification
|
||||
// arrives.
|
||||
|
||||
if (err) {
|
||||
if (error) {
|
||||
// XXX The failure could be, for example, because of a
|
||||
// certificate-related error. In which case the connection will
|
||||
// fail later in Strophe anyway even if we use the default
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
import { RouteRegistry } from '../../base/react';
|
||||
import { MiddlewareRegistry, ReducerRegistry } from '../../base/redux';
|
||||
import { toURLString } from '../../base/util';
|
||||
import { BlankPage } from '../../welcome';
|
||||
|
||||
import { appNavigate, appWillMount, appWillUnmount } from '../actions';
|
||||
|
||||
|
@ -194,13 +195,14 @@ export class AbstractApp extends Component {
|
|||
*/
|
||||
render() {
|
||||
const { route } = this.state;
|
||||
const component = (route && route.component) || BlankPage;
|
||||
|
||||
if (route) {
|
||||
if (component) {
|
||||
return (
|
||||
<I18nextProvider i18n = { i18next }>
|
||||
<Provider store = { this._getStore() }>
|
||||
{
|
||||
this._createElement(route.component)
|
||||
this._createElement(component)
|
||||
}
|
||||
</Provider>
|
||||
</I18nextProvider>
|
||||
|
@ -372,15 +374,20 @@ export class AbstractApp extends Component {
|
|||
// onEnter. During the removal of react-router, modifications were
|
||||
// minimized by preserving the onEnter interface:
|
||||
// (1) Router would provide its nextState to the Route's onEnter. As the
|
||||
// role of Router is now this AbstractApp, provide its nextState.
|
||||
// role of Router is now this AbstractApp and we use redux, provide the
|
||||
// redux store instead.
|
||||
// (2) A replace function would be provided to the Route in case it
|
||||
// chose to redirect to another path.
|
||||
route && this._onRouteEnter(route, nextState, pathname => {
|
||||
this._openURL(pathname);
|
||||
route && this._onRouteEnter(route, this._getStore(), pathname => {
|
||||
if (pathname) {
|
||||
this._openURL(pathname);
|
||||
|
||||
// Do not proceed with the route because it chose to redirect to
|
||||
// another path.
|
||||
nextState = undefined;
|
||||
// Do not proceed with the route because it chose to redirect to
|
||||
// another path.
|
||||
nextState = undefined;
|
||||
} else {
|
||||
nextState.route = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
// XXX React's setState is asynchronous which means that the value of
|
||||
|
|
|
@ -4,7 +4,7 @@ import { isRoomValid } from '../base/conference';
|
|||
import { RouteRegistry } from '../base/react';
|
||||
import { toState } from '../base/redux';
|
||||
import { Conference } from '../conference';
|
||||
import { Entryway } from '../welcome';
|
||||
import { WelcomePage } from '../welcome';
|
||||
|
||||
/**
|
||||
* Determines which route is to be rendered in order to depict a specific Redux
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { Component } from 'react';
|
||||
|
||||
import { destroyLocalTracks } from '../../base/tracks';
|
||||
|
||||
/**
|
||||
* A React <tt>Component</tt> which represents a blank page. Destroys the local
|
||||
* tracks upon mounting since no media is desired when this component utilized.
|
||||
* Renders nothing.
|
||||
*/
|
||||
export default class AbstractBlankPage extends Component {
|
||||
/**
|
||||
* <tt>AbstractBlankPage</tt> React <tt>Component</tt>'s prop types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the local tracks (if any) since no media is desired when this
|
||||
* component is rendered.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentWillMount() {
|
||||
this.props.dispatch(destroyLocalTracks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}. Returns null because the
|
||||
* purpose of this component is to destroy the local tracks and render
|
||||
* nothing.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {null}
|
||||
*/
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,39 +1,58 @@
|
|||
/* @flow */
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import React, { Component } from 'react';
|
||||
import { ActivityIndicator, View } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import AbstractBlankPage from './AbstractBlankPage';
|
||||
import { destroyLocalTracks } from '../../base/tracks';
|
||||
|
||||
import { isWelcomePageAppEnabled } from '../functions';
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
* Mobile/React Native implementation of <tt>AbstractBlankPage</tt>. Since this
|
||||
* is the <tt>Component</tt> rendered when there is no <tt>WelcomePage</tt>,
|
||||
* it will show a progress indicator when there are ongoing network requests
|
||||
* (notably, the loading of config.js before joining a conference). The use case
|
||||
* which prompted the introduction of this <tt>Component</tt> is mobile where
|
||||
* SDK users probably disable the <tt>WelcomePage</tt>.
|
||||
* The React <tt>Component</tt> displayed by <tt>AbstractApp</tt> when it has no
|
||||
* <tt>Route</tt> to render. Renders a progress indicator when there are ongoing
|
||||
* network requests.
|
||||
*/
|
||||
class BlankPage extends AbstractBlankPage {
|
||||
class BlankPage extends Component {
|
||||
/**
|
||||
* <tt>BlankPage</tt> React <tt>Component</tt>'s prop types.
|
||||
*
|
||||
* @static
|
||||
*/
|
||||
static propTypes = {
|
||||
...AbstractBlankPage.propTypes,
|
||||
|
||||
/**
|
||||
* Indicates whether there is network activity i.e. ongoing network
|
||||
* requests.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_networkActivity: PropTypes.bool
|
||||
_networkActivity: PropTypes.bool,
|
||||
|
||||
/**
|
||||
* The indicator which determines whether <tt>WelcomePage</tt> is (to
|
||||
* be) rendered.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_welcomePageEnabled: PropTypes.bool,
|
||||
|
||||
dispatch: PropTypes.func
|
||||
};
|
||||
|
||||
/**
|
||||
* Destroys the local tracks (if any) since no media is desired when this
|
||||
* component is rendered.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {void}
|
||||
*/
|
||||
componentWillMount() {
|
||||
this.props._welcomePageEnabled
|
||||
|| this.props.dispatch(destroyLocalTracks());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
|
@ -59,7 +78,8 @@ class BlankPage extends AbstractBlankPage {
|
|||
* @param {Object} state - The redux state.
|
||||
* @private
|
||||
* @returns {{
|
||||
* networkActivity: boolean
|
||||
* _networkActivity: boolean,
|
||||
* _welcomePageEnabled: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
|
@ -67,7 +87,8 @@ function _mapStateToProps(state) {
|
|||
|
||||
return {
|
||||
_networkActivity:
|
||||
Boolean(requests && (requests.length || requests.size))
|
||||
Boolean(requests && (requests.length || requests.size)),
|
||||
_welcomePageEnabled: isWelcomePageAppEnabled(state)
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1 @@
|
|||
import AbstractBlankPage from './AbstractBlankPage';
|
||||
|
||||
/**
|
||||
* Default <tt>BlankPage</tt> implementation for Web/React. It's not currently
|
||||
* in use but it's here for symmetry with mobile/React Native should we choose
|
||||
* to take advantage of it in the future. Destroys the local tracks and renders
|
||||
* nothing.
|
||||
*/
|
||||
export default class BlankPage extends AbstractBlankPage {
|
||||
}
|
||||
export default undefined;
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import BlankPage from './BlankPage';
|
||||
import WelcomePage from './WelcomePage';
|
||||
|
||||
/**
|
||||
* A React <tt>Component</tt> which is rendered when there is no (valid) room
|
||||
* (name) i.e. it is the opposite of <tt>Conference</tt>. Generally and
|
||||
* historically, it is <tt>WelcomePage</tt>. However, Jitsi Meet SDK for Android
|
||||
* and iOS allows the use of the (JavaScript) app without <tt>WelcomePage</tt>
|
||||
* and it needs to display something between conferences.
|
||||
*/
|
||||
class Entryway extends Component {
|
||||
/**
|
||||
* <tt>Entryway</tt>'s React <tt>Component</tt> prop types.
|
||||
*/
|
||||
static propTypes = {
|
||||
/**
|
||||
* The indicator which determines whether <tt>WelcomePage</tt> is (to
|
||||
* be) rendered.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_welcomePageEnabled: PropTypes.bool
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements React's {@link Component#render()}.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
return (
|
||||
this.props._welcomePageEnabled ? <WelcomePage /> : <BlankPage />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps (parts of) the redux state to the associated Entryway's props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @private
|
||||
* @returns {{
|
||||
* _welcomePageEnabled: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
let welcomePageEnabled;
|
||||
|
||||
if (navigator.product === 'ReactNative') {
|
||||
// We introduced the welcomePageEnabled prop on App in Jitsi Meet SDK
|
||||
// for Android and iOS. There isn't a strong reason not to introduce it
|
||||
// on Web but there're a few considerations to be taken before I go
|
||||
// there among which:
|
||||
// - Enabling/disabling the Welcome page on Web historically
|
||||
// automatically redirects to a random room and that does not make sense
|
||||
// on mobile (right now).
|
||||
const { app } = state['features/app'];
|
||||
|
||||
welcomePageEnabled = Boolean(app && app.props.welcomePageEnabled);
|
||||
} else {
|
||||
welcomePageEnabled = true;
|
||||
}
|
||||
|
||||
return {
|
||||
_welcomePageEnabled: welcomePageEnabled
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(Entryway);
|
|
@ -1,3 +1,2 @@
|
|||
export { default as BlankPage } from './BlankPage';
|
||||
export { default as Entryway } from './Entryway';
|
||||
export { default as WelcomePage } from './WelcomePage';
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/* @flow */
|
||||
|
||||
import { toState } from '../base/redux';
|
||||
|
||||
declare var APP: Object;
|
||||
declare var config: Object;
|
||||
|
||||
export * from './roomnameGenerator';
|
||||
|
||||
/**
|
||||
* Determines whether the <tt>WelcomePage</tt> is enabled by the app itself
|
||||
* (e.g. programmatically via the Jitsi Meet SDK for Android and iOS). Not to be
|
||||
* confused with {@link isWelcomePageUserEnabled}.
|
||||
*
|
||||
* @param {Object|Function} stateOrGetState - The redux state or
|
||||
* {@link getState} function.
|
||||
* @returns {boolean} If the <tt>WelcomePage</tt> is enabled by the app, then
|
||||
* <tt>true</tt>; otherwise, <tt>false</tt>.
|
||||
*/
|
||||
export function isWelcomePageAppEnabled(stateOrGetState: Object | Function) {
|
||||
let b;
|
||||
|
||||
if (navigator.product === 'ReactNative') {
|
||||
// We introduced the welcomePageEnabled prop on App in Jitsi Meet SDK
|
||||
// for Android and iOS. There isn't a strong reason not to introduce it
|
||||
// on Web but there're a few considerations to be taken before I go
|
||||
// there among which:
|
||||
// - Enabling/disabling the Welcome page on Web historically
|
||||
// automatically redirects to a random room and that does not make sense
|
||||
// on mobile (right now).
|
||||
const { app } = toState(stateOrGetState)['features/app'];
|
||||
|
||||
b = Boolean(app && app.props.welcomePageEnabled);
|
||||
} else {
|
||||
b = true;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the <tt>WelcomePage</tt> is enabled by the user either
|
||||
* herself or through her deployment config(uration). Not to be confused with
|
||||
* {@link isWelcomePageAppEnabled}.
|
||||
*
|
||||
* @param {Object|Function} stateOrGetState - The redux state or
|
||||
* {@link getState} function.
|
||||
* @returns {boolean} If the <tt>WelcomePage</tt> is enabled by the user, then
|
||||
* <tt>true</tt>; otherwise, <tt>false</tt>.
|
||||
*/
|
||||
export function isWelcomePageUserEnabled(stateOrGetState: Object | Function) {
|
||||
return (
|
||||
typeof APP === 'undefined'
|
||||
? true
|
||||
: toState(stateOrGetState)['features/base/config'].enableWelcomePage
|
||||
&& APP.settings.isWelcomePageEnabled());
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import './route';
|
||||
|
||||
export * from './components';
|
||||
export * from './functions';
|
||||
|
|
|
@ -2,47 +2,34 @@
|
|||
|
||||
import { RouteRegistry } from '../base/react';
|
||||
|
||||
import { Entryway } from './components';
|
||||
import { generateRoomWithoutSeparator } from './roomnameGenerator';
|
||||
|
||||
declare var APP: Object;
|
||||
declare var config: Object;
|
||||
import { WelcomePage } from './components';
|
||||
import {
|
||||
generateRoomWithoutSeparator,
|
||||
isWelcomePageAppEnabled,
|
||||
isWelcomePageUserEnabled
|
||||
} from './functions';
|
||||
|
||||
/**
|
||||
* Register route for Entryway.
|
||||
* Register route for <tt>WelcomePage</tt>.
|
||||
*/
|
||||
RouteRegistry.register({
|
||||
component: Entryway,
|
||||
component: WelcomePage,
|
||||
onEnter,
|
||||
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.
|
||||
* Skips the <tt>WelcomePage</tt> if it is disabled (by the app or the user).
|
||||
*
|
||||
* @param {Object} nextState - The next Router state.
|
||||
* @param {Object} store - The redux store.
|
||||
* @param {Function} replace - The function to redirect to another path.
|
||||
* @returns {void}
|
||||
*/
|
||||
function onEnter(nextState, replace) {
|
||||
// The disabling of the Welcome page by redirecting to a random room name is
|
||||
// a feature (1) we have on Web/React and (2) we do not want on mobile/React
|
||||
// Native (at the time of this writing).
|
||||
if (typeof APP === 'object'
|
||||
|
||||
// TODO Technically, there is features/base/config now so it is
|
||||
// preferable to read config(uration) values from there and not rely
|
||||
// on a global variable. However, the redux store is not available
|
||||
// here at the time of this writing. Given the current (1) Web
|
||||
// exclusivity of the feature and (2) the reliance on other global
|
||||
// variables (e.g. APP), go with the global variable for now in
|
||||
// order to minimize the effort involved.
|
||||
&& !(config.enableWelcomePage
|
||||
&& APP.settings.isWelcomePageEnabled())) {
|
||||
const room = generateRoomWithoutSeparator();
|
||||
|
||||
replace(`/${room}`);
|
||||
function onEnter({ getState }, replace) {
|
||||
if (isWelcomePageAppEnabled(getState)) {
|
||||
isWelcomePageUserEnabled(getState)
|
||||
|| replace(`/${generateRoomWithoutSeparator()}`);
|
||||
} else {
|
||||
replace(undefined);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue