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 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // @flow
  2. import { CONFERENCE_FAILED, CONFERENCE_JOINED } from '../base/conference';
  3. import { JitsiConferenceErrors, JitsiConferenceEvents } from '../base/lib-jitsi-meet';
  4. import { getFirstLoadableAvatarUrl } from '../base/participants';
  5. import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
  6. import { NOTIFICATION_TYPE, showNotification } from '../notifications';
  7. import { isPrejoinPageEnabled } from '../prejoin/functions';
  8. import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED } from './actionTypes';
  9. import {
  10. hideLobbyScreen,
  11. knockingParticipantLeft,
  12. openLobbyScreen,
  13. participantIsKnockingOrUpdated,
  14. setLobbyModeEnabled,
  15. startKnocking,
  16. setPasswordJoinFailed
  17. } from './actions';
  18. MiddlewareRegistry.register(store => next => action => {
  19. switch (action.type) {
  20. case CONFERENCE_FAILED:
  21. return _conferenceFailed(store, next, action);
  22. case CONFERENCE_JOINED:
  23. return _conferenceJoined(store, next, action);
  24. case KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED: {
  25. // We need the full update result to be in the store already
  26. const result = next(action);
  27. _findLoadableAvatarForKnockingParticipant(store, action.participant);
  28. return result;
  29. }
  30. }
  31. return next(action);
  32. });
  33. /**
  34. * Registers a change handler for state['features/base/conference'].conference to
  35. * set the event listeners needed for the lobby feature to operate.
  36. */
  37. StateListenerRegistry.register(
  38. state => state['features/base/conference'].conference,
  39. (conference, { dispatch }, previousConference) => {
  40. if (conference && !previousConference) {
  41. conference.on(JitsiConferenceEvents.MEMBERS_ONLY_CHANGED, enabled => {
  42. dispatch(setLobbyModeEnabled(enabled));
  43. });
  44. conference.on(JitsiConferenceEvents.LOBBY_USER_JOINED, (id, name) => {
  45. dispatch(participantIsKnockingOrUpdated({
  46. id,
  47. name
  48. }));
  49. });
  50. conference.on(JitsiConferenceEvents.LOBBY_USER_UPDATED, (id, participant) => {
  51. dispatch(participantIsKnockingOrUpdated({
  52. ...participant,
  53. id
  54. }));
  55. });
  56. conference.on(JitsiConferenceEvents.LOBBY_USER_LEFT, id => {
  57. dispatch(knockingParticipantLeft(id));
  58. });
  59. }
  60. });
  61. /**
  62. * Function to handle the conference failed event and navigate the user to the lobby screen
  63. * based on the failure reason.
  64. *
  65. * @param {Object} store - The Redux store.
  66. * @param {Function} next - The Redux next function.
  67. * @param {Object} action - The Redux action.
  68. * @returns {Object}
  69. */
  70. function _conferenceFailed({ dispatch, getState }, next, action) {
  71. const { error } = action;
  72. const state = getState();
  73. const nonFirstFailure = Boolean(state['features/base/conference'].membersOnly);
  74. if (error.name === JitsiConferenceErrors.MEMBERS_ONLY_ERROR) {
  75. if (typeof error.recoverable === 'undefined') {
  76. error.recoverable = true;
  77. }
  78. const result = next(action);
  79. dispatch(openLobbyScreen());
  80. if (isPrejoinPageEnabled(state) && !state['features/lobby'].knocking) {
  81. // prejoin is enabled, so we knock automatically
  82. dispatch(startKnocking());
  83. }
  84. dispatch(setPasswordJoinFailed(nonFirstFailure));
  85. return result;
  86. }
  87. dispatch(hideLobbyScreen());
  88. if (error.name === JitsiConferenceErrors.CONFERENCE_ACCESS_DENIED) {
  89. dispatch(showNotification({
  90. appearance: NOTIFICATION_TYPE.ERROR,
  91. hideErrorSupportLink: true,
  92. titleKey: 'lobby.joinRejectedMessage'
  93. }));
  94. }
  95. return next(action);
  96. }
  97. /**
  98. * Handles cleanup of lobby state when a conference is joined.
  99. *
  100. * @param {Object} store - The Redux store.
  101. * @param {Function} next - The Redux next function.
  102. * @param {Object} action - The Redux action.
  103. * @returns {Object}
  104. */
  105. function _conferenceJoined({ dispatch }, next, action) {
  106. dispatch(hideLobbyScreen());
  107. return next(action);
  108. }
  109. /**
  110. * Finds the loadable avatar URL and updates the participant accordingly.
  111. *
  112. * @param {Object} store - The Redux store.
  113. * @param {Object} participant - The knocking participant.
  114. * @returns {void}
  115. */
  116. function _findLoadableAvatarForKnockingParticipant({ dispatch, getState }, { id }) {
  117. const updatedParticipant = getState()['features/lobby'].knockingParticipants.find(p => p.id === id);
  118. const { disableThirdPartyRequests } = getState()['features/base/config'];
  119. if (!disableThirdPartyRequests && updatedParticipant && !updatedParticipant.loadableAvatarUrl) {
  120. getFirstLoadableAvatarUrl(updatedParticipant).then(loadableAvatarUrl => {
  121. if (loadableAvatarUrl) {
  122. dispatch(participantIsKnockingOrUpdated({
  123. loadableAvatarUrl,
  124. id
  125. }));
  126. }
  127. });
  128. }
  129. }