Merge pull request #3179 from jitsi/reload_screen_a_catch_all

[RN] Reload screen a catch all
This commit is contained in:
Saúl Ibarra Corretgé 2018-06-26 17:07:06 +02:00 committed by GitHub
commit a5d0bfe1d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 107 additions and 7 deletions

View File

@ -21,3 +21,15 @@ export const MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED
* @public
*/
export const SUSPEND_DETECTED = Symbol('SUSPEND_DETECTED');
/**
* Adjust the state of the fatal error which shows/hides the reload screen. See
* action methods's description for more info about each of the fields.
*
* {
* type: SET_FATAL_ERROR,
* fatalError: ?Object
* }
* @public
*/
export const SET_FATAL_ERROR = Symbol('SET_FATAL_ERROR');

View File

@ -3,6 +3,7 @@ import { toURLString } from '../base/util';
import {
MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
SET_FATAL_ERROR,
SUSPEND_DETECTED
} from './actionTypes';
@ -37,6 +38,8 @@ export function mediaPermissionPromptVisibilityChanged(isVisible, browser) {
*/
export function _reloadNow() {
return (dispatch, getState) => {
dispatch(setFatalError(undefined));
const { locationURL } = getState()['features/base/connection'];
logger.info(`Reloading the conference using URL: ${locationURL}`);
@ -62,3 +65,22 @@ export function suspendDetected() {
type: SUSPEND_DETECTED
};
}
/**
* The action indicates that an unrecoverable error has occurred and the reload
* screen will be displayed or hidden.
*
* @param {Object} fatalError - A critical error which was not claimed by any
* feature for error recovery (the recoverable flag was not set). If
* {@code undefined} then any fatal error currently stored will be discarded.
* @returns {{
* type: SET_FATAL_ERROR,
* fatalError: ?Error
* }}
*/
export function setFatalError(fatalError) {
return {
type: SET_FATAL_ERROR,
fatalError
};
}

View File

@ -77,6 +77,25 @@ export default class AbstractPageReloadOverlay extends Component<*, *> {
* {@code false}, otherwise.
*/
static needsRender(state: Object) {
// FIXME web does not rely on the 'recoverable' flag set on an error
// action, but on a predefined list of fatal errors. Because of that
// the value of 'fatalError' which relies on the flag should not be used
// on web yet (until conference/connection and their errors handling is
// not unified).
return typeof APP === 'undefined'
? Boolean(state['features/overlay'].fatalError)
: this.needsRenderWeb(state);
}
/**
* Determines whether this overlay needs to be rendered (according to a
* specific redux state). Called by {@link OverlayContainer}.
*
* @param {Object} state - The redux state.
* @returns {boolean} - If this overlay needs to be rendered, {@code true};
* {@code false}, otherwise.
*/
static needsRenderWeb(state: Object) {
const conferenceError = state['features/base/conference'].error;
const configError = state['features/base/config'].error;
const connectionError = state['features/base/connection'].error;
@ -273,13 +292,14 @@ export default class AbstractPageReloadOverlay extends Component<*, *> {
* }}
*/
export function abstractMapStateToProps(state: Object) {
const { error: conferenceError } = state['features/base/conference'];
const { error: configError } = state['features/base/config'];
const { error: connectionError } = state['features/base/connection'];
const { fatalError } = state['features/overlay'];
return {
details: connectionError ? connectionError.details : undefined,
isNetworkFailure: Boolean(configError || connectionError),
reason: (configError || connectionError || conferenceError).message
details: fatalError && fatalError.details,
isNetworkFailure:
fatalError === configError || fatalError === connectionError,
reason: fatalError && fatalError.message
};
}

View File

@ -6,10 +6,9 @@ import { appNavigate } from '../../app';
import { translate } from '../../base/i18n';
import { LoadingIndicator } from '../../base/react';
import { _reloadNow } from '../actions';
import AbstractPageReloadOverlay, { abstractMapStateToProps }
from './AbstractPageReloadOverlay';
import { _reloadNow, setFatalError } from '../actions';
import OverlayFrame from './OverlayFrame';
import { pageReloadOverlay as styles } from './styles';
@ -42,6 +41,7 @@ class PageReloadOverlay extends AbstractPageReloadOverlay {
*/
_onCancel() {
clearInterval(this._interval);
this.props.dispatch(setFatalError(undefined));
this.props.dispatch(appNavigate(undefined));
}

View File

@ -1,4 +1,5 @@
export * from './actions';
export * from './components';
import './middleware';
import './reducer';

View File

@ -0,0 +1,27 @@
// @flow
import { StateListenerRegistry } from '../base/redux';
import { setFatalError } from './actions';
declare var APP: Object;
/**
* State listener which emits the {@code fatalErrorOccurred} action which works
* as a catch all for critical errors which have not been claimed by any other
* feature for error recovery (the recoverable flag is not set).
*/
StateListenerRegistry.register(
/* selector */ state => {
const { error: conferenceError } = state['features/base/conference'];
const { error: configError } = state['features/base/config'];
const { error: connectionError } = state['features/base/connection'];
return configError || connectionError || conferenceError;
},
/* listener */ (error, { dispatch }) => {
error
&& typeof error.recoverable === 'undefined'
&& dispatch(setFatalError(error));
}
);

View File

@ -4,6 +4,7 @@ import { assign, ReducerRegistry, set } from '../base/redux';
import {
MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED,
SET_FATAL_ERROR,
SUSPEND_DETECTED
} from './actionTypes';
@ -12,11 +13,14 @@ import {
*
* FIXME: these pieces of state should probably be in a different place.
*/
ReducerRegistry.register('features/overlay', (state = {}, action) => {
ReducerRegistry.register('features/overlay', (state = { }, action) => {
switch (action.type) {
case MEDIA_PERMISSION_PROMPT_VISIBILITY_CHANGED:
return _mediaPermissionPromptVisibilityChanged(state, action);
case SET_FATAL_ERROR:
return _setFatalError(state, action);
case SUSPEND_DETECTED:
return _suspendDetected(state);
}
@ -54,3 +58,17 @@ function _mediaPermissionPromptVisibilityChanged(
function _suspendDetected(state) {
return set(state, 'suspendDetected', true);
}
/**
* Reduces a specific redux action {@code SET_FATAL_ERROR} of the feature
* overlay.
*
* @param {Object} state - The redux state of the feature overlay.
* @param {Error} fatalError - If the value is set it indicates that a fatal
* error has occurred and that the reload screen is to be displayed.
* @returns {Object}
* @private
*/
function _setFatalError(state, { fatalError }) {
return set(state, 'fatalError', fatalError);
}