Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

subscriber.ts 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import { difference } from 'lodash-es';
  2. import { batch } from 'react-redux';
  3. import { IStore } from '../../app/types';
  4. import { hideNotification, showNotification } from '../../notifications/actions';
  5. import { NOTIFICATION_TIMEOUT_TYPE, RAISE_HAND_NOTIFICATION_ID } from '../../notifications/constants';
  6. import { getCurrentConference } from '../conference/functions';
  7. import {
  8. getDisableNextSpeakerNotification,
  9. getSsrcRewritingFeatureFlag,
  10. hasBeenNotified,
  11. isNextToSpeak } from '../config/functions.any';
  12. import { VIDEO_TYPE } from '../media/constants';
  13. import StateListenerRegistry from '../redux/StateListenerRegistry';
  14. import { NOTIFIED_TO_SPEAK } from './actionTypes';
  15. import { createVirtualScreenshareParticipant, participantLeft } from './actions';
  16. import {
  17. getParticipantById,
  18. getRemoteScreensharesBasedOnPresence,
  19. getVirtualScreenshareParticipantOwnerId
  20. } from './functions';
  21. import { FakeParticipant } from './types';
  22. StateListenerRegistry.register(
  23. /* selector */ state => state['features/base/tracks'],
  24. /* listener */(tracks, store) => _updateScreenshareParticipants(store)
  25. );
  26. StateListenerRegistry.register(
  27. /* selector */ state => state['features/base/participants'].remoteVideoSources,
  28. /* listener */(remoteVideoSources, store) => getSsrcRewritingFeatureFlag(store.getState())
  29. && _updateScreenshareParticipantsBasedOnPresence(store)
  30. );
  31. StateListenerRegistry.register(
  32. /* selector */ state => state['features/base/participants'].raisedHandsQueue,
  33. /* listener */ (raisedHandsQueue, store) => {
  34. if (raisedHandsQueue.length
  35. && isNextToSpeak(store.getState())
  36. && !hasBeenNotified(store.getState())
  37. && !getDisableNextSpeakerNotification(store.getState())
  38. && !store.getState()['features/visitors'].iAmVisitor) { // visitors raise hand to be promoted
  39. _notifyNextSpeakerInRaisedHandQueue(store);
  40. }
  41. if (!raisedHandsQueue[0]) {
  42. store.dispatch(hideNotification(RAISE_HAND_NOTIFICATION_ID));
  43. }
  44. }
  45. );
  46. /**
  47. * Compares the old and new screenshare lists provided and creates/removes the virtual screenshare participant
  48. * tiles accordingly.
  49. *
  50. * @param {Array<string>} oldScreenshareSourceNames - List of old screenshare source names.
  51. * @param {Array<string>} newScreenshareSourceNames - Current list of screenshare source names.
  52. * @param {Object} store - The redux store.
  53. * @returns {void}
  54. */
  55. function _createOrRemoveVirtualParticipants(
  56. oldScreenshareSourceNames: string[],
  57. newScreenshareSourceNames: string[],
  58. store: IStore): void {
  59. const { dispatch, getState } = store;
  60. const conference = getCurrentConference(getState());
  61. const removedScreenshareSourceNames = difference(oldScreenshareSourceNames, newScreenshareSourceNames);
  62. const addedScreenshareSourceNames = difference(newScreenshareSourceNames, oldScreenshareSourceNames);
  63. if (removedScreenshareSourceNames.length) {
  64. removedScreenshareSourceNames.forEach(id => dispatch(participantLeft(id, conference, {
  65. fakeParticipant: FakeParticipant.RemoteScreenShare
  66. })));
  67. }
  68. if (addedScreenshareSourceNames.length) {
  69. addedScreenshareSourceNames.forEach(id => dispatch(
  70. createVirtualScreenshareParticipant(id, false, conference)));
  71. }
  72. }
  73. /**
  74. * Handles creating and removing virtual screenshare participants.
  75. *
  76. * @param {*} store - The redux store.
  77. * @returns {void}
  78. */
  79. function _updateScreenshareParticipants(store: IStore): void {
  80. const { dispatch, getState } = store;
  81. const state = getState();
  82. const conference = getCurrentConference(state);
  83. const tracks = state['features/base/tracks'];
  84. const { sortedRemoteVirtualScreenshareParticipants, localScreenShare } = state['features/base/participants'];
  85. const previousScreenshareSourceNames = [ ...sortedRemoteVirtualScreenshareParticipants.keys() ];
  86. let newLocalSceenshareSourceName;
  87. const currentScreenshareSourceNames = tracks.reduce((acc: string[], track) => {
  88. if (track.videoType === VIDEO_TYPE.DESKTOP && !track.jitsiTrack.isMuted()) {
  89. const sourceName: string = track.jitsiTrack.getSourceName();
  90. // Ignore orphan tracks in ssrc-rewriting mode.
  91. if (!sourceName && getSsrcRewritingFeatureFlag(state)) {
  92. return acc;
  93. }
  94. if (track.local) {
  95. newLocalSceenshareSourceName = sourceName;
  96. } else if (getParticipantById(state, getVirtualScreenshareParticipantOwnerId(sourceName))) {
  97. acc.push(sourceName);
  98. }
  99. }
  100. return acc;
  101. }, []);
  102. if (!localScreenShare && newLocalSceenshareSourceName) {
  103. dispatch(createVirtualScreenshareParticipant(newLocalSceenshareSourceName, true, conference));
  104. }
  105. if (localScreenShare && !newLocalSceenshareSourceName) {
  106. dispatch(participantLeft(localScreenShare.id, conference, {
  107. fakeParticipant: FakeParticipant.LocalScreenShare
  108. }));
  109. }
  110. if (getSsrcRewritingFeatureFlag(state)) {
  111. return;
  112. }
  113. _createOrRemoveVirtualParticipants(previousScreenshareSourceNames, currentScreenshareSourceNames, store);
  114. }
  115. /**
  116. * Handles the creation and removal of remote virtual screenshare participants when ssrc-rewriting is enabled.
  117. *
  118. * @param {Object} store - The redux store.
  119. * @returns {void}
  120. */
  121. function _updateScreenshareParticipantsBasedOnPresence(store: IStore): void {
  122. const { getState } = store;
  123. const state = getState();
  124. const { sortedRemoteVirtualScreenshareParticipants } = state['features/base/participants'];
  125. const previousScreenshareSourceNames = [ ...sortedRemoteVirtualScreenshareParticipants.keys() ];
  126. const currentScreenshareSourceNames = getRemoteScreensharesBasedOnPresence(state);
  127. _createOrRemoveVirtualParticipants(previousScreenshareSourceNames, currentScreenshareSourceNames, store);
  128. }
  129. /**
  130. * Handles notifying the next speaker in the raised hand queue.
  131. *
  132. * @param {*} store - The redux store.
  133. * @returns {void}
  134. */
  135. function _notifyNextSpeakerInRaisedHandQueue(store: IStore): void {
  136. const { dispatch } = store;
  137. batch(() => {
  138. dispatch(showNotification({
  139. titleKey: 'notify.nextToSpeak',
  140. maxLines: 2
  141. }, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
  142. dispatch({
  143. type: NOTIFIED_TO_SPEAK
  144. });
  145. });
  146. }