feat(App): refactor App and split it into BaseApp and App (continued)

There doesn't seem to be a strong need for the initialized React
Component state in BaseApp so remove/delete it.
This commit is contained in:
Lyubo Marinov 2018-07-12 11:16:57 -05:00
parent dc246960df
commit bfdfb5321c
4 changed files with 55 additions and 73 deletions

View File

@ -10,7 +10,7 @@ import { appNavigate } from '../actions';
import { getDefaultURL } from '../functions';
/**
* {@code AbstractApp} component's property types.
* The type of React {@code Component} props of {@link AbstractApp}.
*/
export type Props = {
@ -49,8 +49,8 @@ export class AbstractApp extends BaseApp<Props, *> {
super.componentWillMount();
this._init.then(() => {
// If a URL was explicitly specified to this React Component,
// then open it; otherwise, use a default.
// If a URL was explicitly specified to this React Component, then
// open it; otherwise, use a default.
this._openURL(toURLString(this.props.url) || this._getDefaultURL());
});
}
@ -102,9 +102,9 @@ export class AbstractApp extends BaseApp<Props, *> {
* Creates an extra {@link ReactElement}s to be added (unconditionaly)
* alongside the main element.
*
* @returns {ReactElement}
* @abstract
* @protected
* @returns {ReactElement}
*/
_createExtraElement() {
return (

View File

@ -27,46 +27,46 @@ import type { Props as AbstractAppProps } from './AbstractApp';
declare var __DEV__;
/**
* App component's property types.
* The type of React {@code Component} props of {@link App}.
*/
type Props = AbstractAppProps & {
/**
* Whether the add people feature is enabled or not.
* Whether the add people feature is enabled.
*/
addPeopleEnabled: boolean,
/**
* Whether the dial-out feature is enabled or not.
* Whether the dial-out feature is enabled.
*/
dialOutEnabled: boolean,
/**
* Whether Picture-in-Picture is enabled. If {@code true}, a toolbar
* button is rendered in the {@link Conference} view to afford entering
* Whether Picture-in-Picture is enabled. If {@code true}, a toolbar button
* is rendered in the {@link Conference} view to afford entering
* Picture-in-Picture.
*/
pictureInPictureEnabled: boolean,
/**
* Whether the Welcome page is enabled. If {@code true}, the Welcome
* page is rendered when the {@link App} is not at a location (URL)
* identifying a Jitsi Meet conference/room.
* Whether the Welcome page is enabled. If {@code true}, the Welcome page is
* rendered when the {@link App} is not at a location (URL) identifying
* a Jitsi Meet conference/room.
*/
welcomePageEnabled: boolean
};
/**
* Root application component.
* Root app {@code Component} on mobile/React Native.
*
* @extends AbstractApp
*/
export class App extends AbstractApp {
/**
* Initializes a new App instance.
* Initializes a new {@code App} instance.
*
* @param {Object} props - The read-only React Component props with which
* the new instance is to be initialized.
* @param {Props} props - The read-only React {@code Component} props with
* which the new instance is to be initialized.
*/
constructor(props: Props) {
super(props);
@ -76,8 +76,8 @@ export class App extends AbstractApp {
// In the Release configuration, React Native will (intentionally) throw
// an unhandled JavascriptException for an unhandled JavaScript error.
// This will effectively kill the application. In accord with the Web,
// do not kill the application.
// This will effectively kill the app. In accord with the Web, do not
// kill the app.
this._maybeDisableExceptionsManager();
}
@ -130,10 +130,9 @@ export class App extends AbstractApp {
* {@link ExceptionsManager#handleException} on platforms and in
* configurations on/in which the use of the method in questions has been
* determined to be undesirable. For example, React Native will
* (intentionally) throw an unhandled JavascriptException for an
* (intentionally) throw an unhandled {@code JavascriptException} for an
* unhandled JavaScript error in the Release configuration. This will
* effectively kill the application. In accord with the Web, do not kill the
* application.
* effectively kill the app. In accord with the Web, do not kill the app.
*
* @private
* @returns {void}
@ -148,9 +147,9 @@ export class App extends AbstractApp {
// A solution based on RTCSetFatalHandler was implemented on iOS and
// it is preferred because it is at a later step of the
// error/exception handling and it is specific to fatal
// errors/exceptions which were observed to kill the application.
// The solution implemented bellow was tested on Android only so it
// is considered safest to use it there only.
// errors/exceptions which were observed to kill the app. The
// solution implemented bellow was tested on Android only so it is
// considered safest to use it there only.
return;
}
@ -167,10 +166,10 @@ export class App extends AbstractApp {
/**
* Notified by React's Linking API that a specific URL registered to be
* handled by this App was activated.
* handled by this app was activated.
*
* @param {Object} event - The details of the notification/event.
* @param {string} event.url - The URL registered to be handled by this App
* @param {string} event.url - The URL registered to be handled by this app
* which was activated.
* @private
* @returns {void}
@ -183,11 +182,11 @@ export class App extends AbstractApp {
/**
* Handles a (possibly unhandled) JavaScript error by preventing React Native
* from converting a fatal error into an unhandled native exception which will
* kill the application.
* kill the app.
*
* @param {Error} error - The (possibly unhandled) JavaScript error to handle.
* @param {boolean} fatal - True if the specified error is fatal; otherwise,
* false.
* @param {boolean} fatal - If the specified error is fatal, {@code true};
* otherwise, {@code false}.
* @private
* @returns {void}
*/
@ -195,12 +194,12 @@ function _handleException(error, fatal) {
if (fatal) {
// In the Release configuration, React Native will (intentionally) throw
// an unhandled JavascriptException for an unhandled JavaScript error.
// This will effectively kill the application. In accord with the Web,
// do not kill the application.
// This will effectively kill the app. In accord with the Web, do not
// kill the app.
console.error(error);
} else {
// Forward to the next globalHandler of ErrorUtils.
const next = _handleException.next;
const { next } = _handleException;
typeof next === 'function' && next(error, fatal);
}

View File

@ -11,11 +11,21 @@ import '../../video-layout';
import { AbstractApp } from './AbstractApp';
/**
* Root application component.
* Root app {@code Component} on Web/React.
*
* @extends AbstractApp
*/
export class App extends AbstractApp {
/**
* Gets a Location object from the window with information about the current
* location of the document.
*
* @inheritdoc
*/
getWindowLocation() {
return window.location;
}
/**
* Overrides the parent method to inject {@link AtlasKitThemeProvider} as
* the top most component.
@ -29,14 +39,4 @@ export class App extends AbstractApp {
</AtlasKitThemeProvider>
);
}
/**
* Gets a Location object from the window with information about the current
* location of the document.
*
* @inheritdoc
*/
getWindowLocation() {
return window.location;
}
}

View File

@ -20,21 +20,18 @@ import { appWillMount, appWillUnmount } from '../actions';
declare var APP: Object;
/**
* The type of the React {@code Component} state of {@link BaseApp}.
*/
type State = {
/**
* The state of the »possible« async initialization of
* the {@code BaseApp}.
*/
initialized: boolean,
/**
* The Route rendered by this {@code BaseApp}.
* The {@code Route} rendered by the {@code BaseApp}.
*/
route: Object,
/**
* The redux store used by this {@code BaseApp}.
* The redux store used by the {@code BaseApp}.
*/
store: Object
};
@ -57,7 +54,6 @@ export default class BaseApp extends Component<*, State> {
super(props);
this.state = {
initialized: false,
route: {},
// $FlowFixMe
@ -65,9 +61,8 @@ export default class BaseApp extends Component<*, State> {
};
/**
* Make the mobile {@code BaseApp} wait until the
* {@code AsyncStorage} implementation of {@code Storage} initializes
* fully.
* Make the mobile {@code BaseApp} wait until the {@code AsyncStorage}
* implementation of {@code Storage} initializes fully.
*
* @private
* @see {@link #_initStorage}
@ -83,32 +78,21 @@ export default class BaseApp extends Component<*, State> {
}
/**
* Initialize the application.
* Initializes the app.
*
* @inheritdoc
*/
componentWillMount() {
this._init.then(() => {
const { dispatch } = this.state.store;
dispatch(appWillMount(this));
// We set the initialized state here and not in the constructor to
// make sure that {@code componentWillMount} gets invoked before
// the app tries to render the actual app content.
this.setState({ initialized: true });
});
this._init.then(() => this.state.store.dispatch(appWillMount(this)));
}
/**
* De-initialize the application.
* De-initializes the app.
*
* @inheritdoc
*/
componentWillUnmount() {
const { dispatch } = this.state.store;
dispatch(appWillUnmount(this));
this.state.store.dispatch(appWillUnmount(this));
}
/**
@ -133,10 +117,9 @@ export default class BaseApp extends Component<*, State> {
* @returns {ReactElement}
*/
render() {
const { initialized, route, store } = this.state;
const { component } = route;
const { route: { component }, store } = this.state;
if (initialized && component) {
if (store && component) {
return (
<I18nextProvider i18n = { i18next }>
<Provider store = { store }>