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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // @flow
  2. import _ from 'lodash';
  3. import { APP_WILL_MOUNT } from '../app';
  4. import { setAudioOnly } from '../audio-only';
  5. import { SET_LOCATION_URL } from '../connection/actionTypes'; // minimize imports to avoid circular imports
  6. import { getLocalParticipant, participantUpdated } from '../participants';
  7. import { MiddlewareRegistry } from '../redux';
  8. import { parseURLParams } from '../util';
  9. import { SETTINGS_UPDATED } from './actionTypes';
  10. import { updateSettings } from './actions';
  11. import { handleCallIntegrationChange, handleCrashReportingChange } from './functions';
  12. /**
  13. * The middleware of the feature base/settings. Distributes changes to the state
  14. * of base/settings to the states of other features computed from the state of
  15. * base/settings.
  16. *
  17. * @param {Store} store - The redux store.
  18. * @returns {Function}
  19. */
  20. MiddlewareRegistry.register(store => next => action => {
  21. const result = next(action);
  22. switch (action.type) {
  23. case APP_WILL_MOUNT:
  24. _initializeCallIntegration(store);
  25. break;
  26. case SETTINGS_UPDATED:
  27. _maybeHandleCallIntegrationChange(action);
  28. _maybeSetAudioOnly(store, action);
  29. _updateLocalParticipant(store, action);
  30. _maybeCrashReportingChange(action);
  31. break;
  32. case SET_LOCATION_URL:
  33. _updateLocalParticipantFromUrl(store);
  34. break;
  35. }
  36. return result;
  37. });
  38. /**
  39. * Initializes the audio device handler based on the `disableCallIntegration` setting.
  40. *
  41. * @param {Store} store - The redux store.
  42. * @private
  43. * @returns {void}
  44. */
  45. function _initializeCallIntegration({ getState }) {
  46. const { disableCallIntegration } = getState()['features/base/settings'];
  47. if (typeof disableCallIntegration === 'boolean') {
  48. handleCallIntegrationChange(disableCallIntegration);
  49. }
  50. }
  51. /**
  52. * Maps the settings field names to participant names where they don't match.
  53. * Currently there is only one such field, but may be extended in the future.
  54. *
  55. * @private
  56. * @param {string} settingsField - The name of the settings field to map.
  57. * @returns {string}
  58. */
  59. function _mapSettingsFieldToParticipant(settingsField) {
  60. switch (settingsField) {
  61. case 'displayName':
  62. return 'name';
  63. }
  64. return settingsField;
  65. }
  66. /**
  67. * Handles a change in the `disableCallIntegration` setting.
  68. *
  69. * @param {Object} action - The redux action.
  70. * @private
  71. * @returns {void}
  72. */
  73. function _maybeHandleCallIntegrationChange({ settings: { disableCallIntegration } }) {
  74. if (typeof disableCallIntegration === 'boolean') {
  75. handleCallIntegrationChange(disableCallIntegration);
  76. }
  77. }
  78. /**
  79. * Handles a change in the `disableCrashReporting` setting.
  80. *
  81. * @param {Object} action - The redux action.
  82. * @private
  83. * @returns {void}
  84. */
  85. function _maybeCrashReportingChange({ settings: { disableCrashReporting } }) {
  86. if (typeof disableCrashReporting === 'boolean') {
  87. handleCrashReportingChange(disableCrashReporting);
  88. }
  89. }
  90. /**
  91. * Updates {@code startAudioOnly} flag if it's updated in the settings.
  92. *
  93. * @param {Store} store - The redux store.
  94. * @param {Object} action - The redux action.
  95. * @private
  96. * @returns {void}
  97. */
  98. function _maybeSetAudioOnly(
  99. { dispatch },
  100. { settings: { startAudioOnly } }) {
  101. if (typeof startAudioOnly === 'boolean') {
  102. dispatch(setAudioOnly(startAudioOnly, true));
  103. }
  104. }
  105. /**
  106. * Updates the local participant according to settings changes.
  107. *
  108. * @param {Store} store - The redux store.
  109. * @param {Object} action - The dispatched action.
  110. * @private
  111. * @returns {void}
  112. */
  113. function _updateLocalParticipant({ dispatch, getState }, action) {
  114. const { settings } = action;
  115. const localParticipant = getLocalParticipant(getState());
  116. const newLocalParticipant = {
  117. ...localParticipant
  118. };
  119. for (const key in settings) {
  120. if (settings.hasOwnProperty(key)) {
  121. newLocalParticipant[_mapSettingsFieldToParticipant(key)]
  122. = settings[key];
  123. }
  124. }
  125. dispatch(participantUpdated(newLocalParticipant));
  126. }
  127. /**
  128. * Returns the userInfo set in the URL.
  129. *
  130. * @param {Store} store - The redux store.
  131. * @private
  132. * @returns {void}
  133. */
  134. function _updateLocalParticipantFromUrl({ dispatch, getState }) {
  135. const urlParams
  136. = parseURLParams(getState()['features/base/connection'].locationURL);
  137. const urlEmail = urlParams['userInfo.email'];
  138. const urlDisplayName = urlParams['userInfo.displayName'];
  139. if (!urlEmail && !urlDisplayName) {
  140. return;
  141. }
  142. const localParticipant = getLocalParticipant(getState());
  143. if (localParticipant) {
  144. const displayName = _.escape(urlDisplayName);
  145. const email = _.escape(urlEmail);
  146. dispatch(participantUpdated({
  147. ...localParticipant,
  148. email,
  149. name: displayName
  150. }));
  151. dispatch(updateSettings({
  152. displayName,
  153. email
  154. }));
  155. }
  156. }