fix(filmstrip) Make dominant speaker visible at all times (#11874)
* fix(filmstrip) Make dominant speaker visible at all times. * squash: address review comments.
This commit is contained in:
parent
5dbb17bc81
commit
c727b603af
|
@ -46,6 +46,59 @@ const AVATAR_CHECKER_FUNCTIONS = [
|
||||||
];
|
];
|
||||||
/* eslint-enable arrow-body-style, no-unused-vars */
|
/* eslint-enable arrow-body-style, no-unused-vars */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of active speakers that should be moved to the top of the sorted list of participants so that the
|
||||||
|
* dominant speaker is visible always on the vertical filmstrip in stage layout.
|
||||||
|
*
|
||||||
|
* @param {Function | Object} stateful - The (whole) redux state, or redux's {@code getState} function to be used to
|
||||||
|
* retrieve the state.
|
||||||
|
* @returns {Array<string>}
|
||||||
|
*/
|
||||||
|
export function getActiveSpeakersToBeDisplayed(stateful: Object | Function) {
|
||||||
|
const state = toState(stateful);
|
||||||
|
const {
|
||||||
|
fakeParticipants,
|
||||||
|
sortedRemoteScreenshares,
|
||||||
|
sortedRemoteVirtualScreenshareParticipants,
|
||||||
|
speakersList
|
||||||
|
} = state['features/base/participants'];
|
||||||
|
const { visibleRemoteParticipants } = state['features/filmstrip'];
|
||||||
|
|
||||||
|
// Do not re-sort the active speakers if all of them are currently visible.
|
||||||
|
if (typeof visibleRemoteParticipants === 'undefined' || speakersList.size <= visibleRemoteParticipants.size) {
|
||||||
|
return speakersList;
|
||||||
|
}
|
||||||
|
const activeSpeakers = new Map(speakersList);
|
||||||
|
let availableSlotsForActiveSpeakers = visibleRemoteParticipants.size;
|
||||||
|
|
||||||
|
// Remove screenshares from the count.
|
||||||
|
if (getMultipleVideoSupportFeatureFlag(state)) {
|
||||||
|
if (sortedRemoteVirtualScreenshareParticipants) {
|
||||||
|
availableSlotsForActiveSpeakers -= sortedRemoteVirtualScreenshareParticipants.size * 2;
|
||||||
|
for (const screenshare of Array.from(sortedRemoteVirtualScreenshareParticipants.keys())) {
|
||||||
|
const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare);
|
||||||
|
|
||||||
|
activeSpeakers.delete(ownerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (sortedRemoteScreenshares) {
|
||||||
|
availableSlotsForActiveSpeakers -= sortedRemoteScreenshares.size;
|
||||||
|
for (const id of Array.from(sortedRemoteScreenshares.keys())) {
|
||||||
|
activeSpeakers.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove shared video from the count.
|
||||||
|
if (fakeParticipants) {
|
||||||
|
availableSlotsForActiveSpeakers -= fakeParticipants.size;
|
||||||
|
}
|
||||||
|
const truncatedSpeakersList = Array.from(activeSpeakers).slice(0, availableSlotsForActiveSpeakers);
|
||||||
|
|
||||||
|
truncatedSpeakersList.sort((a, b) => a[1].localeCompare(b[1]));
|
||||||
|
|
||||||
|
return new Map(truncatedSpeakersList);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the first loadable avatar URL for a participant.
|
* Resolves the first loadable avatar URL for a participant.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import { getSourceNameSignalingFeatureFlag } from '../base/config';
|
import { getMultipleVideoSupportFeatureFlag } from '../base/config';
|
||||||
import { getVirtualScreenshareParticipantOwnerId } from '../base/participants';
|
import { getActiveSpeakersToBeDisplayed, getVirtualScreenshareParticipantOwnerId } from '../base/participants';
|
||||||
|
|
||||||
import { setRemoteParticipants } from './actions';
|
import { setRemoteParticipants } from './actions';
|
||||||
import { isFilmstripScrollVisible } from './functions';
|
import { isFilmstripScrollVisible } from './functions';
|
||||||
|
@ -34,42 +34,36 @@ export function updateRemoteParticipants(store: Object, participantId: ?number)
|
||||||
const {
|
const {
|
||||||
fakeParticipants,
|
fakeParticipants,
|
||||||
sortedRemoteParticipants,
|
sortedRemoteParticipants,
|
||||||
sortedRemoteScreenshares,
|
sortedRemoteScreenshares
|
||||||
speakersList
|
|
||||||
} = state['features/base/participants'];
|
} = state['features/base/participants'];
|
||||||
const remoteParticipants = new Map(sortedRemoteParticipants);
|
const remoteParticipants = new Map(sortedRemoteParticipants);
|
||||||
const screenShares = new Map(sortedRemoteScreenshares);
|
const screenShares = new Map(sortedRemoteScreenshares);
|
||||||
const screenShareParticipants = sortedRemoteVirtualScreenshareParticipants
|
const screenShareParticipants = sortedRemoteVirtualScreenshareParticipants
|
||||||
? [ ...sortedRemoteVirtualScreenshareParticipants.keys() ] : [];
|
? [ ...sortedRemoteVirtualScreenshareParticipants.keys() ] : [];
|
||||||
const sharedVideos = fakeParticipants ? Array.from(fakeParticipants.keys()) : [];
|
const sharedVideos = fakeParticipants ? Array.from(fakeParticipants.keys()) : [];
|
||||||
const speakers = new Map(speakersList);
|
const speakers = getActiveSpeakersToBeDisplayed(state);
|
||||||
|
|
||||||
if (getSourceNameSignalingFeatureFlag(state)) {
|
if (getMultipleVideoSupportFeatureFlag(state)) {
|
||||||
for (const screenshare of screenShareParticipants) {
|
for (const screenshare of screenShareParticipants) {
|
||||||
const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare);
|
const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare);
|
||||||
|
|
||||||
remoteParticipants.delete(ownerId);
|
remoteParticipants.delete(ownerId);
|
||||||
remoteParticipants.delete(screenshare);
|
remoteParticipants.delete(screenshare);
|
||||||
|
|
||||||
speakers.delete(ownerId);
|
|
||||||
speakers.delete(screenshare);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const screenshare of screenShares.keys()) {
|
for (const screenshare of screenShares.keys()) {
|
||||||
remoteParticipants.delete(screenshare);
|
remoteParticipants.delete(screenshare);
|
||||||
speakers.delete(screenshare);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const sharedVideo of sharedVideos) {
|
for (const sharedVideo of sharedVideos) {
|
||||||
remoteParticipants.delete(sharedVideo);
|
remoteParticipants.delete(sharedVideo);
|
||||||
speakers.delete(sharedVideo);
|
|
||||||
}
|
}
|
||||||
for (const speaker of speakers.keys()) {
|
for (const speaker of speakers.keys()) {
|
||||||
remoteParticipants.delete(speaker);
|
remoteParticipants.delete(speaker);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSourceNameSignalingFeatureFlag(state)) {
|
if (getMultipleVideoSupportFeatureFlag(state)) {
|
||||||
// Always update the order of the thumnails.
|
// Always update the order of the thumnails.
|
||||||
const participantsWithScreenShare = screenShareParticipants.reduce((acc, screenshare) => {
|
const participantsWithScreenShare = screenShareParticipants.reduce((acc, screenshare) => {
|
||||||
const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare);
|
const ownerId = getVirtualScreenshareParticipantOwnerId(screenshare);
|
||||||
|
|
Loading…
Reference in New Issue