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.

reducer.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import { PARTICIPANT_ID_CHANGED } from '../participants';
  2. import { ReducerRegistry, set } from '../redux';
  3. import {
  4. SET_NO_SRC_DATA_NOTIFICATION_UID,
  5. TRACK_ADDED,
  6. TRACK_CREATE_CANCELED,
  7. TRACK_CREATE_ERROR,
  8. TRACK_NO_DATA_FROM_SOURCE,
  9. TRACK_REMOVED,
  10. TRACK_UPDATE_LAST_VIDEO_MEDIA_EVENT,
  11. TRACK_UPDATED,
  12. TRACK_WILL_CREATE
  13. } from './actionTypes';
  14. /**
  15. * Track type.
  16. *
  17. * @typedef {object} Track
  18. * @property {JitsiLocalTrack|JitsiRemoteTrack} jitsiTrack - The associated
  19. * {@code JitsiTrack} instance. Optional for local tracks if those are still
  20. * being created (ie {@code getUserMedia} is still in progress).
  21. * @property {Promise} [gumProcess] - If a local track is still being created,
  22. * it will have no {@code JitsiTrack}, but a {@code gumProcess} set to a
  23. * {@code Promise} with and extra {@code cancel()}.
  24. * @property {boolean} local=false - If the track is local.
  25. * @property {MEDIA_TYPE} mediaType=false - The media type of the track.
  26. * @property {boolean} mirror=false - The indicator which determines whether the
  27. * display/rendering of the track should be mirrored. It only makes sense in the
  28. * context of video (at least at the time of this writing).
  29. * @property {boolean} muted=false - If the track is muted.
  30. * @property {(string|undefined)} participantId - The ID of the participant whom
  31. * the track belongs to.
  32. * @property {boolean} videoStarted=false - If the video track has already
  33. * started to play.
  34. * @property {(VIDEO_TYPE|undefined)} videoType - The type of video track if
  35. * any.
  36. */
  37. /**
  38. * Reducer function for a single track.
  39. *
  40. * @param {Track|undefined} state - Track to be modified.
  41. * @param {Object} action - Action object.
  42. * @param {string} action.type - Type of action.
  43. * @param {string} action.name - Name of last media event.
  44. * @param {string} action.newValue - New participant ID value (in this
  45. * particular case).
  46. * @param {string} action.oldValue - Old participant ID value (in this
  47. * particular case).
  48. * @param {Track} action.track - Information about track to be changed.
  49. * @param {Participant} action.participant - Information about participant.
  50. * @returns {Track|undefined}
  51. */
  52. function track(state, action) {
  53. switch (action.type) {
  54. case PARTICIPANT_ID_CHANGED:
  55. if (state.participantId === action.oldValue) {
  56. return {
  57. ...state,
  58. participantId: action.newValue
  59. };
  60. }
  61. break;
  62. case TRACK_UPDATED: {
  63. const t = action.track;
  64. if (state.jitsiTrack === t.jitsiTrack) {
  65. // Make sure that there's an actual update in order to reduce the
  66. // risk of unnecessary React Component renders.
  67. for (const p in t) {
  68. if (state[p] !== t[p]) {
  69. // There's an actual update.
  70. return {
  71. ...state,
  72. ...t
  73. };
  74. }
  75. }
  76. }
  77. break;
  78. }
  79. case TRACK_UPDATE_LAST_VIDEO_MEDIA_EVENT: {
  80. const t = action.track;
  81. if (state.jitsiTrack === t) {
  82. if (state.lastMediaEvent !== action.name) {
  83. return {
  84. ...state,
  85. lastMediaEvent: action.name
  86. };
  87. }
  88. }
  89. break;
  90. }
  91. case TRACK_NO_DATA_FROM_SOURCE: {
  92. const t = action.track;
  93. if (state.jitsiTrack === t.jitsiTrack) {
  94. const isReceivingData = t.jitsiTrack.isReceivingData();
  95. if (state.isReceivingData !== isReceivingData) {
  96. return {
  97. ...state,
  98. isReceivingData
  99. };
  100. }
  101. }
  102. break;
  103. }
  104. }
  105. return state;
  106. }
  107. /**
  108. * Listen for actions that mutate (e.g. Add, remove) local and remote tracks.
  109. */
  110. ReducerRegistry.register('features/base/tracks', (state = [], action) => {
  111. switch (action.type) {
  112. case PARTICIPANT_ID_CHANGED:
  113. case TRACK_NO_DATA_FROM_SOURCE:
  114. case TRACK_UPDATE_LAST_VIDEO_MEDIA_EVENT:
  115. case TRACK_UPDATED:
  116. return state.map(t => track(t, action));
  117. case TRACK_ADDED: {
  118. let withoutTrackStub = state;
  119. if (action.track.local) {
  120. withoutTrackStub
  121. = state.filter(
  122. t => !t.local || t.mediaType !== action.track.mediaType);
  123. }
  124. return [ ...withoutTrackStub, action.track ];
  125. }
  126. case TRACK_CREATE_CANCELED:
  127. case TRACK_CREATE_ERROR: {
  128. return state.filter(t => !t.local || t.mediaType !== action.trackType);
  129. }
  130. case TRACK_REMOVED:
  131. return state.filter(t => t.jitsiTrack !== action.track.jitsiTrack);
  132. case TRACK_WILL_CREATE:
  133. return [ ...state, action.track ];
  134. default:
  135. return state;
  136. }
  137. });
  138. /**
  139. * Listen for actions that mutate the no-src-data state, like the current notification id.
  140. */
  141. ReducerRegistry.register('features/base/no-src-data', (state = {}, action) => {
  142. switch (action.type) {
  143. case SET_NO_SRC_DATA_NOTIFICATION_UID:
  144. return set(state, 'noSrcDataNotificationUid', action.uid);
  145. default:
  146. return state;
  147. }
  148. });