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.

middleware.any.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // @flow
  2. import { batch } from 'react-redux';
  3. import { CONFERENCE_JOIN_IN_PROGRESS, CONFERENCE_LEFT } from '../base/conference/actionTypes';
  4. import { getCurrentConference } from '../base/conference/functions';
  5. import { MEDIA_TYPE } from '../base/media';
  6. import {
  7. PARTICIPANT_LEFT,
  8. getLocalParticipant,
  9. getParticipantById,
  10. participantJoined,
  11. participantLeft,
  12. pinParticipant
  13. } from '../base/participants';
  14. import { FakeParticipant } from '../base/participants/types';
  15. import { MiddlewareRegistry } from '../base/redux';
  16. import { RESET_SHARED_VIDEO_STATUS, SET_SHARED_VIDEO_STATUS } from './actionTypes';
  17. import {
  18. resetSharedVideoStatus,
  19. setSharedVideoStatus
  20. } from './actions.any';
  21. import { PLAYBACK_STATUSES, SHARED_VIDEO, VIDEO_PLAYER_PARTICIPANT_NAME } from './constants';
  22. import { isSharingStatus } from './functions';
  23. import logger from './logger';
  24. declare var APP: Object;
  25. /**
  26. * Middleware that captures actions related to video sharing and updates
  27. * components not hooked into redux.
  28. *
  29. * @param {Store} store - The redux store.
  30. * @returns {Function}
  31. */
  32. MiddlewareRegistry.register(store => next => action => {
  33. const { dispatch, getState } = store;
  34. const state = getState();
  35. switch (action.type) {
  36. case CONFERENCE_JOIN_IN_PROGRESS: {
  37. const { conference } = action;
  38. const localParticipantId = getLocalParticipant(state)?.id;
  39. conference.addCommandListener(SHARED_VIDEO,
  40. ({ value, attributes }) => {
  41. const { from } = attributes;
  42. const sharedVideoStatus = attributes.state;
  43. if (isSharingStatus(sharedVideoStatus)) {
  44. handleSharingVideoStatus(store, value, attributes, conference);
  45. } else if (sharedVideoStatus === 'stop') {
  46. const videoParticipant = getParticipantById(state, value);
  47. dispatch(participantLeft(value, conference, {
  48. fakeParticipant: videoParticipant?.fakeParticipant
  49. }));
  50. if (localParticipantId !== from) {
  51. dispatch(resetSharedVideoStatus());
  52. }
  53. }
  54. }
  55. );
  56. break;
  57. }
  58. case CONFERENCE_LEFT:
  59. dispatch(resetSharedVideoStatus());
  60. break;
  61. case PARTICIPANT_LEFT: {
  62. const conference = getCurrentConference(state);
  63. const { ownerId: stateOwnerId, videoUrl: statevideoUrl } = state['features/shared-video'];
  64. if (action.participant.id === stateOwnerId) {
  65. batch(() => {
  66. dispatch(resetSharedVideoStatus());
  67. dispatch(participantLeft(statevideoUrl, conference));
  68. });
  69. }
  70. break;
  71. }
  72. case SET_SHARED_VIDEO_STATUS: {
  73. const conference = getCurrentConference(state);
  74. const localParticipantId = getLocalParticipant(state)?.id;
  75. const { videoUrl, status, ownerId, time, muted, volume } = action;
  76. const operator = status === PLAYBACK_STATUSES.PLAYING ? 'is' : '';
  77. logger.debug(`User with id: ${ownerId} ${operator} ${status} video sharing.`);
  78. if (typeof APP !== 'undefined') {
  79. APP.API.notifyAudioOrVideoSharingToggled(MEDIA_TYPE.VIDEO, status, ownerId);
  80. }
  81. if (localParticipantId === ownerId) {
  82. sendShareVideoCommand({
  83. conference,
  84. localParticipantId,
  85. muted,
  86. status,
  87. time,
  88. id: videoUrl,
  89. volume
  90. });
  91. }
  92. break;
  93. }
  94. case RESET_SHARED_VIDEO_STATUS: {
  95. const localParticipantId = getLocalParticipant(state)?.id;
  96. const { ownerId: stateOwnerId, videoUrl: statevideoUrl } = state['features/shared-video'];
  97. if (!stateOwnerId) {
  98. break;
  99. }
  100. logger.debug(`User with id: ${stateOwnerId} stop video sharing.`);
  101. if (typeof APP !== 'undefined') {
  102. APP.API.notifyAudioOrVideoSharingToggled(MEDIA_TYPE.VIDEO, 'stop', stateOwnerId);
  103. }
  104. if (localParticipantId === stateOwnerId) {
  105. const conference = getCurrentConference(state);
  106. sendShareVideoCommand({
  107. conference,
  108. id: statevideoUrl,
  109. localParticipantId,
  110. muted: true,
  111. status: 'stop',
  112. time: 0,
  113. volume: 0
  114. });
  115. }
  116. break;
  117. }
  118. }
  119. return next(action);
  120. });
  121. /**
  122. * Handles the playing, pause and start statuses for the shared video.
  123. * Dispatches participantJoined event and, if necessary, pins it.
  124. * Sets the SharedVideoStatus if the event was triggered by the local user.
  125. *
  126. * @param {Store} store - The redux store.
  127. * @param {string} videoUrl - The id of the video to the shared.
  128. * @param {Object} attributes - The attributes received from the share video command.
  129. * @param {JitsiConference} conference - The current conference.
  130. * @returns {void}
  131. */
  132. function handleSharingVideoStatus(store, videoUrl, { state, time, from, muted }, conference) {
  133. const { dispatch, getState } = store;
  134. const localParticipantId = getLocalParticipant(getState()).id;
  135. const oldStatus = getState()['features/shared-video']?.status;
  136. if (state === 'start' || ![ 'playing', 'pause', 'start' ].includes(oldStatus)) {
  137. const youtubeId = videoUrl.match(/http/) ? false : videoUrl;
  138. const avatarURL = youtubeId ? `https://img.youtube.com/vi/${youtubeId}/0.jpg` : '';
  139. dispatch(participantJoined({
  140. conference,
  141. fakeParticipant: FakeParticipant.SharedVideo,
  142. id: videoUrl,
  143. avatarURL,
  144. name: VIDEO_PLAYER_PARTICIPANT_NAME
  145. }));
  146. dispatch(pinParticipant(videoUrl));
  147. }
  148. if (localParticipantId !== from) {
  149. dispatch(setSharedVideoStatus({
  150. muted: muted === 'true',
  151. ownerId: from,
  152. status: state,
  153. time: Number(time),
  154. videoUrl
  155. }));
  156. }
  157. }
  158. /* eslint-disable max-params */
  159. /**
  160. * Sends SHARED_VIDEO command.
  161. *
  162. * @param {string} id - The id of the video.
  163. * @param {string} status - The status of the shared video.
  164. * @param {JitsiConference} conference - The current conference.
  165. * @param {string} localParticipantId - The id of the local participant.
  166. * @param {string} time - The seek position of the video.
  167. * @returns {void}
  168. */
  169. function sendShareVideoCommand({ id, status, conference, localParticipantId, time, muted, volume }) {
  170. conference.sendCommandOnce(SHARED_VIDEO, {
  171. value: id,
  172. attributes: {
  173. from: localParticipantId,
  174. muted,
  175. state: status,
  176. time,
  177. volume
  178. }
  179. });
  180. }