mirror of https://github.com/jitsi/jitsi-meet
parent
bcc326c150
commit
88a11b9f3e
@ -0,0 +1,52 @@ |
||||
// @flow
|
||||
|
||||
import { SET_FILMSTRIP_ENABLED, SET_FILMSTRIP_VISIBLE, SET_REMOTE_PARTICIPANTS } from './actionTypes'; |
||||
|
||||
/** |
||||
* Sets whether the filmstrip is enabled. |
||||
* |
||||
* @param {boolean} enabled - Whether the filmstrip is enabled. |
||||
* @returns {{ |
||||
* type: SET_FILMSTRIP_ENABLED, |
||||
* enabled: boolean |
||||
* }} |
||||
*/ |
||||
export function setFilmstripEnabled(enabled: boolean) { |
||||
return { |
||||
type: SET_FILMSTRIP_ENABLED, |
||||
enabled |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Sets whether the filmstrip is visible. |
||||
* |
||||
* @param {boolean} visible - Whether the filmstrip is visible. |
||||
* @returns {{ |
||||
* type: SET_FILMSTRIP_VISIBLE, |
||||
* visible: boolean |
||||
* }} |
||||
*/ |
||||
export function setFilmstripVisible(visible: boolean) { |
||||
return { |
||||
type: SET_FILMSTRIP_VISIBLE, |
||||
visible |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* Sets the list of the reordered remote participants based on which the visible participants in the filmstrip will be |
||||
* determined. |
||||
* |
||||
* @param {Array<string>} participants - The list of the remote participant endpoint IDs. |
||||
* @returns {{ |
||||
type: SET_REMOTE_PARTICIPANTS, |
||||
participants: Array<string> |
||||
}} |
||||
*/ |
||||
export function setRemoteParticipants(participants: Array<string>) { |
||||
return { |
||||
type: SET_REMOTE_PARTICIPANTS, |
||||
participants |
||||
}; |
||||
} |
@ -0,0 +1,56 @@ |
||||
// @flow
|
||||
|
||||
import { setRemoteParticipants } from './actions'; |
||||
|
||||
/** |
||||
* Computes the reorderd list of the remote participants. |
||||
* |
||||
* @param {*} store - The redux store. |
||||
* @returns {void} |
||||
* @private |
||||
*/ |
||||
export function updateRemoteParticipants(store: Object) { |
||||
const state = store.getState(); |
||||
const { fakeParticipants, sortedRemoteParticipants, speakersList } = state['features/base/participants']; |
||||
const { remoteScreenShares } = state['features/video-layout']; |
||||
const screenShares = (remoteScreenShares || []).slice(); |
||||
let speakers = (speakersList || []).slice(); |
||||
const remoteParticipants = new Map(sortedRemoteParticipants); |
||||
const sharedVideos = fakeParticipants ? Array.from(fakeParticipants.keys()) : []; |
||||
|
||||
for (const screenshare of screenShares) { |
||||
remoteParticipants.delete(screenshare); |
||||
speakers = speakers.filter(speaker => speaker !== screenshare); |
||||
} |
||||
for (const sharedVideo of sharedVideos) { |
||||
remoteParticipants.delete(sharedVideo); |
||||
speakers = speakers.filter(speaker => speaker !== sharedVideo); |
||||
} |
||||
for (const speaker of speakers) { |
||||
remoteParticipants.delete(speaker); |
||||
} |
||||
const reorderedParticipants |
||||
= [ ...screenShares.reverse(), ...sharedVideos, ...speakers, ...Array.from(remoteParticipants.keys()) ]; |
||||
|
||||
store.dispatch(setRemoteParticipants(reorderedParticipants)); |
||||
} |
||||
|
||||
/** |
||||
* Private helper to calculate the reordered list of remote participants when a participant leaves. |
||||
* |
||||
* @param {*} store - The redux store. |
||||
* @param {string} participantId - The endpoint id of the participant leaving the call. |
||||
* @returns {void} |
||||
* @private |
||||
*/ |
||||
export function updateRemoteParticipantsOnLeave(store: Object, participantId: ?string = null) { |
||||
if (!participantId) { |
||||
return; |
||||
} |
||||
const state = store.getState(); |
||||
const { remoteParticipants } = state['features/filmstrip']; |
||||
const reorderedParticipants = new Set(remoteParticipants); |
||||
|
||||
reorderedParticipants.delete(participantId) |
||||
&& store.dispatch(setRemoteParticipants(Array.from(reorderedParticipants))); |
||||
} |
@ -0,0 +1,28 @@ |
||||
// @flow
|
||||
|
||||
import { PARTICIPANT_JOINED, PARTICIPANT_LEFT } from '../base/participants'; |
||||
import { MiddlewareRegistry } from '../base/redux'; |
||||
|
||||
import { updateRemoteParticipants, updateRemoteParticipantsOnLeave } from './functions'; |
||||
import './subscriber'; |
||||
|
||||
/** |
||||
* The middleware of the feature Filmstrip. |
||||
*/ |
||||
MiddlewareRegistry.register(store => next => action => { |
||||
const result = next(action); |
||||
|
||||
switch (action.type) { |
||||
case PARTICIPANT_JOINED: { |
||||
updateRemoteParticipants(store); |
||||
break; |
||||
} |
||||
case PARTICIPANT_LEFT: { |
||||
updateRemoteParticipantsOnLeave(store, action.participant?.id); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return result; |
||||
}); |
||||
|
@ -0,0 +1,38 @@ |
||||
// @flow
|
||||
|
||||
import { StateListenerRegistry } from '../base/redux'; |
||||
|
||||
import { updateRemoteParticipants } from './functions'; |
||||
|
||||
/** |
||||
* Listens for changes to the screensharing status of the remote participants to recompute the reordered list of the |
||||
* remote endpoints. |
||||
*/ |
||||
StateListenerRegistry.register( |
||||
/* selector */ state => state['features/video-layout'].remoteScreenShares, |
||||
/* listener */ (remoteScreenShares, store) => updateRemoteParticipants(store)); |
||||
|
||||
/** |
||||
* Listens for changes to the dominant speaker to recompute the reordered list of the remote endpoints. |
||||
*/ |
||||
StateListenerRegistry.register( |
||||
/* selector */ state => state['features/base/participants'].dominantSpeaker, |
||||
/* listener */ (dominantSpeaker, store) => _reorderDominantSpeakers(store)); |
||||
|
||||
/** |
||||
* Private helper function that reorders the remote participants based on dominant speaker changes. |
||||
* |
||||
* @param {*} store - The redux store. |
||||
* @returns {void} |
||||
* @private |
||||
*/ |
||||
function _reorderDominantSpeakers(store) { |
||||
const state = store.getState(); |
||||
const { dominantSpeaker, local } = state['features/base/participants']; |
||||
const { visibleRemoteParticipants } = state['features/filmstrip']; |
||||
|
||||
// Reorder the participants if the new dominant speaker is currently not visible.
|
||||
if (dominantSpeaker !== local?.id && !visibleRemoteParticipants.has(dominantSpeaker)) { |
||||
updateRemoteParticipants(store); |
||||
} |
||||
} |
@ -0,0 +1,3 @@ |
||||
// @flow
|
||||
|
||||
import './subscriber.any'; |
Loading…
Reference in new issue