123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- // @ts-expect-error
- import { randomInt } from '@jitsi/js-utils/random';
- import React, { Component } from 'react';
- import { WithTranslation } from 'react-i18next';
- import { connect } from 'react-redux';
-
- import { appNavigate, reloadNow } from '../../../../app/actions.native';
- import { IReduxState, IStore } from '../../../../app/types';
- import { translate } from '../../../i18n/functions';
- import { isFatalJitsiConnectionError } from '../../../lib-jitsi-meet/functions.native';
- import { hideDialog } from '../../actions';
- import logger from '../../logger';
-
- import ConfirmDialog from './ConfirmDialog';
-
-
- /**
- * The type of the React {@code Component} props of
- * {@link PageReloadDialog}.
- */
- interface IProps extends WithTranslation {
- conferenceError?: Error;
- configError?: Error;
- connectionError?: Error;
- dispatch: IStore['dispatch'];
- isNetworkFailure: boolean;
- reason?: string;
- }
-
- /**
- * The type of the React {@code Component} state of
- * {@link PageReloadDialog}.
- */
- interface IPageReloadDialogState {
- timeLeft: number;
- }
-
- /**
- * Implements a React Component that is shown before the
- * conference is reloaded.
- * Shows a warning message and counts down towards the re-load.
- */
- class PageReloadDialog extends Component<IProps, IPageReloadDialogState> {
- _interval?: number;
- _timeoutSeconds: number;
-
- /**
- * Initializes a new PageReloadOverlay instance.
- *
- * @param {Object} props - The read-only properties with which the new
- * instance is to be initialized.
- * @public
- */
- constructor(props: IProps) {
- super(props);
-
- this._timeoutSeconds = 10 + randomInt(0, 20);
-
- this.state = {
- timeLeft: this._timeoutSeconds
- };
-
- this._onCancel = this._onCancel.bind(this);
- this._onReloadNow = this._onReloadNow.bind(this);
- this._onReconnecting = this._onReconnecting.bind(this);
- }
-
- /**
- * React Component method that executes once component is mounted.
- *
- * @inheritdoc
- * @returns {void}
- */
- componentDidMount() {
- const { timeLeft } = this.state;
-
- logger.info(
- `The conference will be reloaded after ${timeLeft} seconds.`
- );
-
- this._interval = setInterval(() =>
- this._onReconnecting(), 1000);
- }
-
- /**
- * Clears the timer interval.
- *
- * @inheritdoc
- * @returns {void}
- */
- componentWillUnmount() {
- if (this._interval) {
- clearInterval(this._interval);
- this._interval = undefined;
- }
- }
-
- /**
- * Handle clicking of the "Cancel" button. It will navigate back to the
- * welcome page.
- *
- * @private
- * @returns {boolean}
- */
- _onCancel() {
- const { dispatch } = this.props;
-
- clearInterval(this._interval ?? 0);
- dispatch(appNavigate(undefined));
-
- return true;
- }
-
- /**
- * Handles automatic reconnection.
- *
- * @private
- * @returns {void}
- */
- _onReconnecting() {
- const { dispatch } = this.props;
- const { timeLeft } = this.state;
-
- if (timeLeft === 0) {
- if (this._interval) {
- dispatch(hideDialog());
- this._onReloadNow();
- this._interval = undefined;
- }
- }
-
- this.setState({
- timeLeft: timeLeft - 1
- });
- }
-
- /**
- * Handle clicking on the "Reload Now" button. It will navigate to the same
- * conference URL as before immediately, without waiting for the timer to
- * kick in.
- *
- * @private
- * @returns {boolean}
- */
- _onReloadNow() {
- const { dispatch } = this.props;
-
- clearInterval(this._interval ?? 0);
- dispatch(reloadNow());
-
- return true;
- }
-
- /**
- * Implements React's {@link Component#render()}.
- *
- * @inheritdoc
- * @returns {ReactElement}
- */
- render() {
- const { isNetworkFailure, t } = this.props;
- const { timeLeft } = this.state;
-
- let message, title;
-
- if (isNetworkFailure) {
- title = 'dialog.conferenceDisconnectTitle';
- message = 'dialog.conferenceDisconnectMsg';
- } else {
- title = 'dialog.conferenceReloadTitle';
- message = 'dialog.conferenceReloadMsg';
- }
-
- return (
- <ConfirmDialog
- cancelLabel = 'dialog.Cancel'
- confirmLabel = 'dialog.rejoinNow'
- descriptionKey = { `${t(message, { seconds: timeLeft })}` }
- onCancel = { this._onCancel }
- onSubmit = { this._onReloadNow }
- title = { title } />
- );
- }
- }
-
- /**
- * Maps (parts of) the redux state to the associated component's props.
- *
- * @param {Object} state - The redux state.
- * @param {IProps} ownProps - The own props of the component.
- * @protected
- * @returns {{
- * isNetworkFailure: boolean,
- * reason: string
- * }}
- */
- function mapStateToProps(state: IReduxState, ownProps: IProps) {
- const { conferenceError, configError, connectionError } = ownProps;
- const fatalConnectionError
- = connectionError && isFatalJitsiConnectionError(connectionError);
- const isNetworkFailure = Boolean(configError || fatalConnectionError);
-
- let reason;
-
- if (conferenceError) {
- reason = `error.conference.${conferenceError.name}`;
- } else if (connectionError) {
- reason = `error.conference.${connectionError.name}`;
- } else if (configError) {
- reason = `error.config.${configError.name}`;
- } else {
- logger.error('No reload reason defined!');
- }
-
- return {
- isNetworkFailure,
- reason
- };
- }
-
- export default translate(connect(mapStateToProps)(PageReloadDialog));
|