Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

reducer.js 7.7KB

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