Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions react/features/base/participants/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
isRemoteScreenshareParticipant,
isScreenShareParticipant
} from './functions';
import logger from './logger';
import { FakeParticipant, ILocalParticipant, IParticipant, ISourceInfo } from './types';

/**
Expand Down Expand Up @@ -352,6 +353,8 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
sortedRemoteVirtualScreenshareParticipants.sort((a, b) => a[1].localeCompare(b[1]));

state.sortedRemoteVirtualScreenshareParticipants = new Map(sortedRemoteVirtualScreenshareParticipants);

logger.debug('Remote screenshare participant joined', id);
}

// Exclude the screenshare participant from the fake participant count to avoid duplicates.
Expand Down Expand Up @@ -436,6 +439,8 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
if (sortedRemoteVirtualScreenshareParticipants.has(id)) {
sortedRemoteVirtualScreenshareParticipants.delete(id);
state.sortedRemoteVirtualScreenshareParticipants = new Map(sortedRemoteVirtualScreenshareParticipants);

logger.debug('Remote screenshare participant left', id);
}

if (oldParticipant && !oldParticipant.fakeParticipant && !isLocalScreenShare) {
Expand Down
16 changes: 11 additions & 5 deletions react/features/base/participants/subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
getRemoteScreensharesBasedOnPresence,
getVirtualScreenshareParticipantOwnerId
} from './functions';
import logger from './logger';
import { FakeParticipant } from './types';

StateListenerRegistry.register(
Expand Down Expand Up @@ -69,14 +70,19 @@ function _createOrRemoveVirtualParticipants(
const addedScreenshareSourceNames = difference(newScreenshareSourceNames, oldScreenshareSourceNames);

if (removedScreenshareSourceNames.length) {
removedScreenshareSourceNames.forEach(id => dispatch(participantLeft(id, conference, {
fakeParticipant: FakeParticipant.RemoteScreenShare
})));
removedScreenshareSourceNames.forEach(id => {
logger.debug('Dispatching participantLeft for virtual screenshare', id);
dispatch(participantLeft(id, conference, {
fakeParticipant: FakeParticipant.RemoteScreenShare
}));
});
}

if (addedScreenshareSourceNames.length) {
addedScreenshareSourceNames.forEach(id => dispatch(
createVirtualScreenshareParticipant(id, false, conference)));
addedScreenshareSourceNames.forEach(id => {
logger.debug('Creating virtual screenshare participant', id);
dispatch(createVirtualScreenshareParticipant(id, false, conference));
});
}
}

Expand Down
27 changes: 19 additions & 8 deletions react/features/video-layout/functions.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getReceiverVideoQualityLevel } from '../video-quality/functions';
import { getMinHeightForQualityLvlMap } from '../video-quality/selector';

import { LAYOUTS } from './constants';
import logger from './logger';

/**
* A selector for retrieving the current automatic pinning setting.
Expand Down Expand Up @@ -113,39 +114,49 @@ export function shouldDisplayTileView(state: IReduxState) {
* Private helper to automatically pin the latest screen share stream or unpin
* if there are no more screen share streams.
*
* @param {Array<string>} screenShares - Array containing the list of all the screen sharing endpoints
* @param {Array<string>} previousScreenShares - Array containing the list of all the screen sharing endpoints
* before the update was triggered (including the ones that have been removed from redux because of the update).
* @param {Array<string>} currentScreenShares - Array containing the current list of screen sharing endpoints.
* @param {Store} store - The redux store.
* @returns {void}
*/
export function updateAutoPinnedParticipant(
screenShares: Array<string>, { dispatch, getState }: IStore) {
const state = getState();
const remoteScreenShares = state['features/video-layout'].remoteScreenShares;
previousScreenShares: Array<string>,
currentScreenShares: Array<string>,
{ dispatch, getState }: IStore) {
const pinned = getPinnedParticipant(getState);

// if the pinned participant is shared video or some other fake participant we want to skip auto-pinning
if (pinned?.fakeParticipant && pinned.fakeParticipant !== FakeParticipant.RemoteScreenShare) {
logger.debug('Skipping auto-pin: pinned participant is non-screenshare virtual participant', pinned.id);

return;
}

// Unpin the screen share when the screen sharing participant leaves. Switch to tile view if no other
// participant was pinned before screen share was auto-pinned, pin the previously pinned participant otherwise.
if (!remoteScreenShares?.length) {
if (!currentScreenShares?.length) {
let participantId = null;

if (pinned && !screenShares.find(share => share === pinned.id)) {
if (pinned && !previousScreenShares.find((share: string) => share === pinned.id)) {
participantId = pinned.id;
}

logger.debug('No more screenshares, unpinning or restoring previous pin', participantId);
dispatch(pinParticipant(participantId));

return;
}

const latestScreenShareParticipantId = remoteScreenShares[remoteScreenShares.length - 1];
const latestScreenShareParticipantId = currentScreenShares[currentScreenShares.length - 1];

if (latestScreenShareParticipantId) {
dispatch(pinParticipant(latestScreenShareParticipantId));
const alreadyPinned = pinned?.id === latestScreenShareParticipantId;

if (!alreadyPinned) {
logger.debug(`Auto pinning latest screen share participant: ${latestScreenShareParticipantId}`);
dispatch(pinParticipant(latestScreenShareParticipantId));
}
}
}

Expand Down
14 changes: 11 additions & 3 deletions react/features/video-layout/middleware.any.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { isFollowMeActive } from '../follow-me/functions';
import { SET_TILE_VIEW } from './actionTypes';
import { setTileView } from './actions';
import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions';

import logger from './logger';
import './subscriber';

let previousTileViewEnabled: boolean | undefined;
Expand All @@ -27,13 +27,21 @@ MiddlewareRegistry.register(store => next => action => {

// we want to extract the leaving participant and check its type before actually the participant being removed.
let shouldUpdateAutoPin = false;
let oldScreenShares: Array<string> = [];

switch (action.type) {
case PARTICIPANT_LEFT: {
if (!getAutoPinSetting() || isFollowMeActive(store)) {
logger.debug('Auto pinning is disabled or Follow Me is active, skipping auto pinning.');

break;
}
shouldUpdateAutoPin = Boolean(getParticipantById(store.getState(), action.participant.id)?.fakeParticipant);

if (shouldUpdateAutoPin) {
// Capture the old screenshare list before the reducer runs
oldScreenShares = store.getState()['features/video-layout'].remoteScreenShares || [];
}
break;
}
}
Expand Down Expand Up @@ -75,9 +83,9 @@ MiddlewareRegistry.register(store => next => action => {
}

if (shouldUpdateAutoPin) {
const screenShares = store.getState()['features/video-layout'].remoteScreenShares || [];
const newScreenShares = store.getState()['features/video-layout'].remoteScreenShares || [];

updateAutoPinnedParticipant(screenShares, store);
updateAutoPinnedParticipant(oldScreenShares, newScreenShares, store);
}

return result;
Expand Down
7 changes: 6 additions & 1 deletion react/features/video-layout/subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { isFollowMeActive } from '../follow-me/functions';

import { virtualScreenshareParticipantsUpdated } from './actions';
import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions';
import logger from './logger';

StateListenerRegistry.register(
/* selector */ state => state['features/base/participants'].sortedRemoteVirtualScreenshareParticipants,
Expand All @@ -22,14 +23,18 @@ StateListenerRegistry.register(
knownSharingParticipantIds.forEach(participantId => {
if (!newScreenSharesOrder.includes(participantId)) {
newScreenSharesOrder.push(participantId);
logger.debug('Adding new screenshare to list', participantId);
}
});

if (!equals(oldScreenSharesOrder, newScreenSharesOrder)) {
logger.debug('Screenshare order changed, dispatching update');
store.dispatch(virtualScreenshareParticipantsUpdated(newScreenSharesOrder));

if (getAutoPinSetting() && !isFollowMeActive(store)) {
updateAutoPinnedParticipant(oldScreenSharesOrder, store);
updateAutoPinnedParticipant(oldScreenSharesOrder, newScreenSharesOrder, store);
} else {
logger.debug('Auto pinning is disabled or Follow Me is active, skipping auto pinning of screenshare.');
}
}
});