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.4KB

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