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.js 3.0KB

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