您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

reducer.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. // @flow
  2. import _ from 'lodash';
  3. import { equals, ReducerRegistry, set } from '../redux';
  4. import { CONFIG_WILL_LOAD, LOAD_CONFIG_ERROR, SET_CONFIG } from './actionTypes';
  5. import { _cleanupConfig } from './functions';
  6. /**
  7. * The initial state of the feature base/config when executing in a
  8. * non-React Native environment. The mandatory configuration to be passed to
  9. * JitsiMeetJS#init(). The app will download config.js from the Jitsi Meet
  10. * deployment and take its values into account but the values bellow will be
  11. * enforced (because they are essential to the correct execution of the
  12. * application).
  13. *
  14. * @type {Object}
  15. */
  16. const INITIAL_NON_RN_STATE = {
  17. };
  18. /**
  19. * The initial state of the feature base/config when executing in a React Native
  20. * environment. The mandatory configuration to be passed to JitsiMeetJS#init().
  21. * The app will download config.js from the Jitsi Meet deployment and take its
  22. * values into account but the values bellow will be enforced (because they are
  23. * essential to the correct execution of the application).
  24. *
  25. * @type {Object}
  26. */
  27. const INITIAL_RN_STATE = {
  28. analytics: {},
  29. // FIXME The support for audio levels in lib-jitsi-meet polls the statistics
  30. // of WebRTC at a short interval multiple times a second. Unfortunately,
  31. // React Native is slow to fetch these statistics from the native WebRTC
  32. // API, through the React Native bridge and eventually to JavaScript.
  33. // Because the audio levels are of no interest to the mobile app, it is
  34. // fastest to merely disable them.
  35. disableAudioLevels: true,
  36. p2p: {
  37. disableH264: false,
  38. preferH264: true
  39. }
  40. };
  41. ReducerRegistry.register(
  42. 'features/base/config',
  43. (state = _getInitialState(), action) => {
  44. switch (action.type) {
  45. case CONFIG_WILL_LOAD:
  46. return {
  47. error: undefined,
  48. /**
  49. * The URL of the location associated with/configured by this
  50. * configuration.
  51. *
  52. * @type URL
  53. */
  54. locationURL: action.locationURL
  55. };
  56. case LOAD_CONFIG_ERROR:
  57. // XXX LOAD_CONFIG_ERROR is one of the settlement execution paths of
  58. // the asynchronous "loadConfig procedure/process" started with
  59. // CONFIG_WILL_LOAD. Due to the asynchronous nature of it, whoever
  60. // is settling the process needs to provide proof that they have
  61. // started it and that the iteration of the process being completed
  62. // now is still of interest to the app.
  63. if (state.locationURL === action.locationURL) {
  64. return {
  65. /**
  66. * The {@link Error} which prevented the loading of the
  67. * configuration of the associated {@code locationURL}.
  68. *
  69. * @type Error
  70. */
  71. error: action.error
  72. };
  73. }
  74. break;
  75. case SET_CONFIG:
  76. return _setConfig(state, action);
  77. }
  78. return state;
  79. });
  80. /**
  81. * Gets the initial state of the feature base/config. The mandatory
  82. * configuration to be passed to JitsiMeetJS#init(). The app will download
  83. * config.js from the Jitsi Meet deployment and take its values into account but
  84. * the values bellow will be enforced (because they are essential to the correct
  85. * execution of the application).
  86. *
  87. * @returns {Object}
  88. */
  89. function _getInitialState() {
  90. return (
  91. navigator.product === 'ReactNative'
  92. ? INITIAL_RN_STATE
  93. : INITIAL_NON_RN_STATE);
  94. }
  95. /**
  96. * Reduces a specific Redux action SET_CONFIG of the feature
  97. * base/lib-jitsi-meet.
  98. *
  99. * @param {Object} state - The Redux state of the feature base/lib-jitsi-meet.
  100. * @param {Action} action - The Redux action SET_CONFIG to reduce.
  101. * @private
  102. * @returns {Object} The new state of the feature base/lib-jitsi-meet after the
  103. * reduction of the specified action.
  104. */
  105. function _setConfig(state, { config }) {
  106. // The mobile app bundles jitsi-meet and lib-jitsi-meet at build time and
  107. // does not download them at runtime from the deployment on which it will
  108. // join a conference. The downloading is planned for implementation in the
  109. // future (later rather than sooner) but is not implemented yet at the time
  110. // of this writing and, consequently, we must provide legacy support in the
  111. // meantime.
  112. // eslint-disable-next-line no-param-reassign
  113. config = _translateLegacyConfig(config);
  114. const newState = _.merge(
  115. {},
  116. config,
  117. { error: undefined },
  118. // The config of _getInitialState() is meant to override the config
  119. // downloaded from the Jitsi Meet deployment because the former contains
  120. // values that are mandatory.
  121. _getInitialState()
  122. );
  123. _cleanupConfig(newState);
  124. return equals(state, newState) ? state : newState;
  125. }
  126. /**
  127. * Constructs a new config {@code Object}, if necessary, out of a specific
  128. * config {@code Object} which is in the latest format supported by jitsi-meet.
  129. * Such a translation from an old config format to a new/the latest config
  130. * format is necessary because the mobile app bundles jitsi-meet and
  131. * lib-jitsi-meet at build time and does not download them at runtime from the
  132. * deployment on which it will join a conference.
  133. *
  134. * @param {Object} oldValue - The config {@code Object} which may or may not be
  135. * in the latest form supported by jitsi-meet and from which a new config
  136. * {@code Object} is to be constructed if necessary.
  137. * @returns {Object} A config {@code Object} which is in the latest format
  138. * supported by jitsi-meet.
  139. */
  140. function _translateLegacyConfig(oldValue: Object) {
  141. // jitsi/jitsi-meet#3ea2f005787c9f49c48febaeed9dc0340fe0a01b
  142. let newValue = oldValue;
  143. const oldConfigToNewConfig = {
  144. p2p: [
  145. [ 'backToP2PDelay', 'backToP2PDelay' ],
  146. [ 'enableP2P', 'enabled' ],
  147. [ 'p2pStunServers', 'stunServers' ]
  148. ],
  149. analytics: [
  150. [ 'analyticsScriptUrls', 'scriptURLs' ],
  151. [ 'googleAnalyticsTrackingId', 'googleAnalyticsTrackingId' ]
  152. ]
  153. };
  154. // Translate the old config properties into the new config.p2p properties.
  155. Object.keys(oldConfigToNewConfig).forEach(section => {
  156. if (typeof oldValue[section] !== 'object') {
  157. newValue = set(newValue, section, {});
  158. }
  159. for (const [ oldKey, newKey ] of oldConfigToNewConfig[section]) {
  160. if (oldKey in newValue && !(newKey in newValue[section])) {
  161. const v = newValue[oldKey];
  162. // Do not modify oldValue.
  163. if (newValue === oldValue) {
  164. newValue = {
  165. ...newValue
  166. };
  167. }
  168. delete newValue[oldKey];
  169. // Do not modify the section because it may be from oldValue
  170. // i.e. do not modify oldValue.
  171. newValue[section] = {
  172. ...newValue[section],
  173. [newKey]: v
  174. };
  175. }
  176. }
  177. });
  178. return newValue;
  179. }