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

reducer.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // @flow
  2. import { ReducerRegistry, set } from '../redux';
  3. import { randomHexString } from '../util';
  4. import {
  5. DOMINANT_SPEAKER_CHANGED,
  6. PARTICIPANT_ID_CHANGED,
  7. PARTICIPANT_JOINED,
  8. PARTICIPANT_LEFT,
  9. PARTICIPANT_UPDATED,
  10. PIN_PARTICIPANT
  11. } from './actionTypes';
  12. import { LOCAL_PARTICIPANT_DEFAULT_ID, PARTICIPANT_ROLE } from './constants';
  13. /**
  14. * Participant object.
  15. * @typedef {Object} Participant
  16. * @property {string} id - Participant ID.
  17. * @property {string} name - Participant name.
  18. * @property {string} avatar - Path to participant avatar if any.
  19. * @property {string} role - Participant role.
  20. * @property {boolean} local - If true, participant is local.
  21. * @property {boolean} pinned - If true, participant is currently a
  22. * "PINNED_ENDPOINT".
  23. * @property {boolean} dominantSpeaker - If this participant is the dominant
  24. * speaker in the (associated) conference, {@code true}; otherwise,
  25. * {@code false}.
  26. * @property {string} email - Participant email.
  27. */
  28. declare var APP: Object;
  29. /**
  30. * These properties should not be bulk assigned when updating a particular
  31. * @see Participant.
  32. * @type {string[]}
  33. */
  34. const PARTICIPANT_PROPS_TO_OMIT_WHEN_UPDATE
  35. = [ 'dominantSpeaker', 'id', 'local', 'pinned' ];
  36. /**
  37. * Reducer function for a single participant.
  38. *
  39. * @param {Participant|undefined} state - Participant to be modified.
  40. * @param {Object} action - Action object.
  41. * @param {string} action.type - Type of action.
  42. * @param {Participant} action.participant - Information about participant to be
  43. * added/modified.
  44. * @param {JitsiConference} action.conference - Conference instance.
  45. * @private
  46. * @returns {Participant}
  47. */
  48. function _participant(state: Object = {}, action) {
  49. switch (action.type) {
  50. case DOMINANT_SPEAKER_CHANGED:
  51. // Only one dominant speaker is allowed.
  52. return (
  53. set(state, 'dominantSpeaker', state.id === action.participant.id));
  54. case PARTICIPANT_ID_CHANGED:
  55. if (state.id === action.oldValue) {
  56. return {
  57. ...state,
  58. id: action.newValue
  59. };
  60. }
  61. break;
  62. case PARTICIPANT_JOINED: {
  63. const participant = action.participant; // eslint-disable-line no-shadow
  64. const {
  65. avatarURL,
  66. connectionStatus,
  67. dominantSpeaker,
  68. email,
  69. isBot,
  70. local,
  71. name,
  72. pinned,
  73. role
  74. } = participant;
  75. let { avatarID, id } = participant;
  76. // avatarID
  77. //
  78. // TODO Get the avatarID of the local participant from localStorage.
  79. if (!avatarID && local) {
  80. avatarID = randomHexString(32);
  81. }
  82. // id
  83. //
  84. // XXX The situation of not having an ID for a remote participant should
  85. // not happen. Maybe we should raise an error in this case or generate a
  86. // random ID.
  87. if (!id && local) {
  88. id = LOCAL_PARTICIPANT_DEFAULT_ID;
  89. }
  90. return {
  91. avatarID,
  92. avatarURL,
  93. connectionStatus,
  94. dominantSpeaker: dominantSpeaker || false,
  95. email,
  96. id,
  97. isBot,
  98. local: local || false,
  99. name,
  100. pinned: pinned || false,
  101. role: role || PARTICIPANT_ROLE.NONE
  102. };
  103. }
  104. case PARTICIPANT_UPDATED: {
  105. const participant = action.participant; // eslint-disable-line no-shadow
  106. const { local } = participant;
  107. let { id } = participant;
  108. if (!id && local) {
  109. id = LOCAL_PARTICIPANT_DEFAULT_ID;
  110. }
  111. if (state.id === id) {
  112. const newState = { ...state };
  113. for (const key in participant) {
  114. if (participant.hasOwnProperty(key)
  115. && PARTICIPANT_PROPS_TO_OMIT_WHEN_UPDATE.indexOf(key)
  116. === -1) {
  117. newState[key] = participant[key];
  118. }
  119. }
  120. return newState;
  121. }
  122. break;
  123. }
  124. case PIN_PARTICIPANT:
  125. // Currently, only one pinned participant is allowed.
  126. return set(state, 'pinned', state.id === action.participant.id);
  127. }
  128. return state;
  129. }
  130. /**
  131. * Listen for actions which add, remove, or update the set of participants in
  132. * the conference.
  133. *
  134. * @param {Participant[]} state - List of participants to be modified.
  135. * @param {Object} action - Action object.
  136. * @param {string} action.type - Type of action.
  137. * @param {Participant} action.participant - Information about participant to be
  138. * added/removed/modified.
  139. * @returns {Participant[]}
  140. */
  141. ReducerRegistry.register('features/base/participants', (state = [], action) => {
  142. switch (action.type) {
  143. case DOMINANT_SPEAKER_CHANGED:
  144. case PARTICIPANT_ID_CHANGED:
  145. case PARTICIPANT_UPDATED:
  146. case PIN_PARTICIPANT:
  147. return state.map(p => _participant(p, action));
  148. case PARTICIPANT_JOINED:
  149. return [ ...state, _participant(undefined, action) ];
  150. case PARTICIPANT_LEFT:
  151. return state.filter(p => p.id !== action.participant.id);
  152. default:
  153. return state;
  154. }
  155. });