2018-06-26 12:18:29 +00:00
|
|
|
// @flow
|
|
|
|
|
2022-04-08 12:24:58 +00:00
|
|
|
import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
|
2021-08-25 12:23:40 +00:00
|
|
|
import {
|
|
|
|
isFatalJitsiConferenceError,
|
|
|
|
isFatalJitsiConnectionError
|
2022-04-08 12:24:58 +00:00
|
|
|
} from '../base/lib-jitsi-meet/functions';
|
2018-06-26 12:18:29 +00:00
|
|
|
import { StateListenerRegistry } from '../base/redux';
|
|
|
|
|
|
|
|
import { setFatalError } from './actions';
|
|
|
|
|
|
|
|
declare var APP: Object;
|
|
|
|
|
2022-01-07 10:54:42 +00:00
|
|
|
/**
|
|
|
|
* Error type. Basically like Error, but augmented with a recoverable property.
|
|
|
|
*/
|
|
|
|
type ErrorType = {|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Error message.
|
|
|
|
*/
|
|
|
|
message?: string,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Error name.
|
|
|
|
*/
|
|
|
|
name: string,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Indicates whether this event is recoverable or not.
|
|
|
|
*/
|
|
|
|
recoverable?: boolean
|
|
|
|
|};
|
|
|
|
|
2020-04-15 13:13:43 +00:00
|
|
|
/**
|
|
|
|
* List of errors that are not fatal (or handled differently) so then the overlays won't kick in.
|
|
|
|
*/
|
2020-05-20 08:25:31 +00:00
|
|
|
const NON_OVERLAY_ERRORS = [
|
2020-04-15 13:13:43 +00:00
|
|
|
JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED,
|
|
|
|
JitsiConferenceErrors.CONFERENCE_DESTROYED,
|
|
|
|
JitsiConferenceErrors.CONNECTION_ERROR
|
|
|
|
];
|
|
|
|
|
2021-08-25 12:23:40 +00:00
|
|
|
const ERROR_TYPES = {
|
|
|
|
CONFIG: 'CONFIG',
|
|
|
|
CONNECTION: 'CONNECTION',
|
|
|
|
CONFERENCE: 'CONFERENCE'
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the error type and whether it's fatal or not.
|
|
|
|
*
|
|
|
|
* @param {Function} getState - The redux function for fetching the current state.
|
|
|
|
* @param {Object|string} error - The error to process.
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
const getErrorExtraInfo = (getState, error) => {
|
|
|
|
const state = getState();
|
|
|
|
const { error: conferenceError } = state['features/base/conference'];
|
|
|
|
const { error: configError } = state['features/base/config'];
|
|
|
|
const { error: connectionError } = state['features/base/connection'];
|
|
|
|
|
|
|
|
if (error === conferenceError) {
|
|
|
|
return {
|
|
|
|
type: ERROR_TYPES.CONFERENCE,
|
|
|
|
isFatal: isFatalJitsiConferenceError(error.name || error)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error === configError) {
|
|
|
|
return {
|
|
|
|
type: ERROR_TYPES.CONFIG,
|
|
|
|
isFatal: true
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error === connectionError) {
|
|
|
|
return {
|
|
|
|
type: ERROR_TYPES.CONNECTION,
|
|
|
|
isFatal: isFatalJitsiConnectionError(error.name || error)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-06-26 12:18:29 +00:00
|
|
|
/**
|
|
|
|
* 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;
|
|
|
|
},
|
2022-01-07 10:54:42 +00:00
|
|
|
/* listener */ (error: ErrorType, { dispatch, getState }) => {
|
2021-08-25 12:23:40 +00:00
|
|
|
if (!error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof APP !== 'undefined') {
|
|
|
|
APP.API.notifyError({
|
2022-01-07 10:54:42 +00:00
|
|
|
...error,
|
2021-08-25 12:23:40 +00:00
|
|
|
...getErrorExtraInfo(getState, error)
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NON_OVERLAY_ERRORS.indexOf(error.name) === -1 && typeof error.recoverable === 'undefined') {
|
|
|
|
dispatch(setFatalError(error));
|
|
|
|
}
|
2018-06-26 12:18:29 +00:00
|
|
|
}
|
|
|
|
);
|