Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

PageReloadDialog.tsx 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // @ts-ignore
  2. import { randomInt } from '@jitsi/js-utils/random';
  3. import React, { Component } from 'react';
  4. import { WithTranslation } from 'react-i18next';
  5. import { connect } from 'react-redux';
  6. import { appNavigate, reloadNow } from '../../../../app/actions.native';
  7. import { IReduxState, IStore } from '../../../../app/types';
  8. import { translate } from '../../../i18n/functions';
  9. import { isFatalJitsiConnectionError } from '../../../lib-jitsi-meet/functions.native';
  10. import { hideDialog } from '../../actions';
  11. import logger from '../../logger';
  12. // @ts-ignore
  13. import ConfirmDialog from './ConfirmDialog';
  14. /**
  15. * The type of the React {@code Component} props of
  16. * {@link PageReloadDialog}.
  17. */
  18. interface IPageReloadDialogProps extends WithTranslation {
  19. dispatch: IStore['dispatch'];
  20. isNetworkFailure: boolean;
  21. reason?: string;
  22. }
  23. /**
  24. * The type of the React {@code Component} state of
  25. * {@link PageReloadDialog}.
  26. */
  27. interface IPageReloadDialogState {
  28. timeLeft: number;
  29. }
  30. /**
  31. * Implements a React Component that is shown before the
  32. * conference is reloaded.
  33. * Shows a warning message and counts down towards the re-load.
  34. */
  35. class PageReloadDialog extends Component<IPageReloadDialogProps, IPageReloadDialogState> {
  36. // @ts-ignore
  37. _interval: IntervalID;
  38. _timeoutSeconds: number;
  39. /**
  40. * Initializes a new PageReloadOverlay instance.
  41. *
  42. * @param {Object} props - The read-only properties with which the new
  43. * instance is to be initialized.
  44. * @public
  45. */
  46. constructor(props: IPageReloadDialogProps) {
  47. super(props);
  48. this._timeoutSeconds = 10 + randomInt(0, 20);
  49. this.state = {
  50. timeLeft: this._timeoutSeconds
  51. };
  52. this._onCancel = this._onCancel.bind(this);
  53. this._onReloadNow = this._onReloadNow.bind(this);
  54. this._onReconnecting = this._onReconnecting.bind(this);
  55. }
  56. /**
  57. * React Component method that executes once component is mounted.
  58. *
  59. * @inheritdoc
  60. * @returns {void}
  61. */
  62. componentDidMount() {
  63. const { timeLeft } = this.state;
  64. logger.info(
  65. `The conference will be reloaded after ${timeLeft} seconds.`
  66. );
  67. this._interval = setInterval(() =>
  68. this._onReconnecting(), 1000);
  69. }
  70. /**
  71. * Clears the timer interval.
  72. *
  73. * @inheritdoc
  74. * @returns {void}
  75. */
  76. componentWillUnmount() {
  77. if (this._interval) {
  78. clearInterval(this._interval);
  79. this._interval = undefined;
  80. }
  81. }
  82. /**
  83. * Handle clicking of the "Cancel" button. It will navigate back to the
  84. * welcome page.
  85. *
  86. * @private
  87. * @returns {boolean}
  88. */
  89. _onCancel() {
  90. const { dispatch } = this.props;
  91. clearInterval(this._interval);
  92. dispatch(appNavigate(undefined));
  93. return true;
  94. }
  95. /**
  96. * Handles automatic reconnection.
  97. *
  98. * @private
  99. * @returns {void}
  100. */
  101. _onReconnecting() {
  102. const { dispatch } = this.props;
  103. const { timeLeft } = this.state;
  104. if (timeLeft === 0) {
  105. if (this._interval) {
  106. dispatch(hideDialog());
  107. this._onReloadNow();
  108. this._interval = undefined;
  109. }
  110. }
  111. this.setState({
  112. timeLeft: timeLeft - 1
  113. });
  114. }
  115. /**
  116. * Handle clicking on the "Reload Now" button. It will navigate to the same
  117. * conference URL as before immediately, without waiting for the timer to
  118. * kick in.
  119. *
  120. * @private
  121. * @returns {boolean}
  122. */
  123. _onReloadNow() {
  124. const { dispatch } = this.props;
  125. clearInterval(this._interval);
  126. dispatch(reloadNow());
  127. return true;
  128. }
  129. /**
  130. * Implements React's {@link Component#render()}.
  131. *
  132. * @inheritdoc
  133. * @returns {ReactElement}
  134. */
  135. render() {
  136. const { isNetworkFailure, t } = this.props;
  137. const { timeLeft } = this.state;
  138. let message, title;
  139. if (isNetworkFailure) {
  140. title = 'dialog.conferenceDisconnectTitle';
  141. message = 'dialog.conferenceDisconnectMsg';
  142. } else {
  143. title = 'dialog.conferenceReloadTitle';
  144. message = 'dialog.conferenceReloadMsg';
  145. }
  146. return (
  147. <ConfirmDialog
  148. cancelLabel = 'dialog.Cancel'
  149. confirmLabel = 'dialog.rejoinNow'
  150. descriptionKey = { `${t(message, { seconds: timeLeft })}` }
  151. onCancel = { this._onCancel }
  152. onSubmit = { this._onReloadNow }
  153. title = { title } />
  154. );
  155. }
  156. }
  157. /**
  158. * Maps (parts of) the redux state to the associated component's props.
  159. *
  160. * @param {Object} state - The redux state.
  161. * @protected
  162. * @returns {{
  163. * isNetworkFailure: boolean,
  164. * reason: string
  165. * }}
  166. */
  167. function mapStateToProps(state: IReduxState) {
  168. const { error: conferenceError } = state['features/base/conference'];
  169. const { error: configError } = state['features/base/config'];
  170. const { error: connectionError } = state['features/base/connection'];
  171. const { fatalError } = state['features/overlay'];
  172. const fatalConnectionError
  173. // @ts-ignore
  174. = connectionError && isFatalJitsiConnectionError(connectionError);
  175. const fatalConfigError = fatalError === configError;
  176. const isNetworkFailure = Boolean(fatalConfigError || fatalConnectionError);
  177. let reason;
  178. if (conferenceError) {
  179. reason = `error.conference.${conferenceError.name}`;
  180. } else if (connectionError) {
  181. reason = `error.conference.${connectionError.name}`;
  182. } else if (configError) {
  183. reason = `error.config.${configError.name}`;
  184. } else {
  185. logger.error('No reload reason defined!');
  186. }
  187. return {
  188. isNetworkFailure,
  189. reason
  190. };
  191. }
  192. export default translate(connect(mapStateToProps)(PageReloadDialog));