You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

middleware.ts 3.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { IStore } from '../app/types';
  2. import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
  3. import {
  4. isFatalJitsiConferenceError,
  5. isFatalJitsiConnectionError
  6. } from '../base/lib-jitsi-meet/functions.any';
  7. import StateListenerRegistry from '../base/redux/StateListenerRegistry';
  8. import { openPageReloadDialog } from './actions';
  9. /**
  10. * Error type. Basically like Error, but augmented with a recoverable property.
  11. */
  12. type ErrorType = {
  13. /**
  14. * Error message.
  15. */
  16. message?: string;
  17. /**
  18. * Error name.
  19. */
  20. name: string;
  21. /**
  22. * Indicates whether this event is recoverable or not.
  23. */
  24. recoverable?: boolean;
  25. };
  26. /**
  27. * List of errors that are not fatal (or handled differently) so then the page reload dialog won't kick in.
  28. */
  29. const RN_NO_RELOAD_DIALOG_ERRORS = [
  30. JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED,
  31. JitsiConferenceErrors.CONFERENCE_DESTROYED,
  32. JitsiConferenceErrors.CONNECTION_ERROR,
  33. JitsiConferenceErrors.CONFERENCE_RESTARTED
  34. ];
  35. const ERROR_TYPES = {
  36. CONFIG: 'CONFIG',
  37. CONNECTION: 'CONNECTION',
  38. CONFERENCE: 'CONFERENCE'
  39. };
  40. /**
  41. * Gets the error type and whether it's fatal or not.
  42. *
  43. * @param {Object} state - The redux state.
  44. * @param {Object|string} error - The error to process.
  45. * @returns {void}
  46. */
  47. const getErrorExtraInfo = (state: any, error: ErrorType) => {
  48. const { error: conferenceError } = state['features/base/conference'];
  49. const { error: configError } = state['features/base/config'];
  50. const { error: connectionError } = state['features/base/connection'];
  51. if (error === conferenceError) {
  52. return {
  53. type: ERROR_TYPES.CONFERENCE, // @ts-ignore
  54. isFatal: isFatalJitsiConferenceError(error.name || error)
  55. };
  56. }
  57. if (error === configError) {
  58. return {
  59. type: ERROR_TYPES.CONFIG,
  60. isFatal: true
  61. };
  62. }
  63. if (error === connectionError) {
  64. return {
  65. type: ERROR_TYPES.CONNECTION, // @ts-ignore
  66. isFatal: isFatalJitsiConnectionError(error.name || error)
  67. };
  68. }
  69. };
  70. /**
  71. * State listener which emits the {@code fatalErrorOccurred} action which works
  72. * as a catch all for critical errors which have not been claimed by any other
  73. * feature for error recovery (the recoverable flag is not set).
  74. */
  75. StateListenerRegistry.register(
  76. /* selector */ state => {
  77. const { error: conferenceError } = state['features/base/conference'];
  78. const { error: configError } = state['features/base/config'];
  79. const { error: connectionError } = state['features/base/connection'];
  80. return configError || connectionError || conferenceError;
  81. },
  82. /* listener */ (error: ErrorType, store: IStore) => {
  83. const state = store.getState();
  84. if (!error) {
  85. return;
  86. }
  87. // eslint-disable-next-line no-negated-condition
  88. if (typeof APP !== 'undefined') {
  89. APP.API.notifyError({
  90. ...error,
  91. ...getErrorExtraInfo(state, error)
  92. });
  93. } else if (RN_NO_RELOAD_DIALOG_ERRORS.indexOf(error.name) === -1 && typeof error.recoverable === 'undefined') {
  94. setTimeout(() => {
  95. store.dispatch(openPageReloadDialog());
  96. }, 500);
  97. }
  98. }
  99. );