ref(participants) use enum type to store fake participants (#12316)

This commit is contained in:
Mihaela Dumitru 2022-10-06 14:12:57 +03:00 committed by GitHub
parent be7f2643df
commit d0c22806ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 294 additions and 193 deletions

View File

@ -19,7 +19,9 @@ import { JitsiTrackEvents } from '../../../react/features/base/lib-jitsi-meet';
import { VIDEO_TYPE } from '../../../react/features/base/media';
import {
getParticipantById,
getParticipantDisplayName
getParticipantDisplayName,
isLocalScreenshareParticipant,
isScreenShareParticipant
} from '../../../react/features/base/participants';
import {
getVideoTrackByParticipant,
@ -265,8 +267,7 @@ export default class LargeVideoManager {
let isVideoRenderable;
if (getSourceNameSignalingFeatureFlag(state)) {
const tracks = state['features/base/tracks'];
const videoTrack = getVideoTrackByParticipant(tracks, participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
// Remove track streaming status listener from the old track and add it to the new track,
// in order to stop updating track streaming status for the old track and start it for the new track.
@ -292,7 +293,10 @@ export default class LargeVideoManager {
const streamingStatusActive = isTrackStreamingStatusActive(videoTrack);
isVideoRenderable = !isVideoMuted
&& (APP.conference.isLocalId(id) || participant?.isLocalScreenShare || streamingStatusActive);
&& (APP.conference.isLocalId(id)
|| isLocalScreenshareParticipant(participant)
|| streamingStatusActive
);
this.videoTrack?.jitsiTrack?.getVideoType() === VIDEO_TYPE.DESKTOP
&& logger.debug(`Remote track ${videoTrack?.jitsiTrack}, isVideoMuted=${isVideoMuted},`
+ ` streamingStatusActive=${streamingStatusActive}, isVideoRenderable=${isVideoRenderable}`);
@ -309,7 +313,7 @@ export default class LargeVideoManager {
// progress.
const legacyScreenshare = getMultipleVideoSupportFeatureFlag(state)
&& videoType === VIDEO_TYPE.DESKTOP
&& !participant.isVirtualScreenshareParticipant;
&& !isScreenShareParticipant(participant);
const showAvatar
= isVideoContainer
@ -329,11 +333,10 @@ export default class LargeVideoManager {
if ((!shouldDisplayTileView(state) || participant?.pinned) // In theory the tile view may not be
// enabled yet when we auto pin the participant.
&& participant && !participant.local && !participant.isFakeParticipant) {
&& participant && !participant.local && !participant.fakeParticipant) {
// remote participant only
const tracks = state['features/base/tracks'];
const track = getVideoTrackByParticipant(tracks, participant);
const track = getVideoTrackByParticipant(state, participant);
const isScreenSharing = track?.videoType === 'desktop';
@ -365,8 +368,7 @@ export default class LargeVideoManager {
let messageKey;
if (getSourceNameSignalingFeatureFlag(state)) {
const tracks = state['features/base/tracks'];
const videoTrack = getVideoTrackByParticipant(tracks, participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
messageKey = isTrackStreamingStatusInactive(videoTrack) ? 'connection.LOW_BANDWIDTH' : null;
} else {
@ -619,8 +621,7 @@ export default class LargeVideoManager {
const state = APP.store.getState();
if (getSourceNameSignalingFeatureFlag(state)) {
const tracks = state['features/base/tracks'];
const videoTrack = getVideoTrackByParticipant(tracks, participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
// eslint-disable-next-line no-param-reassign
show = !APP.conference.isLocalId(this.id)

View File

@ -6,7 +6,9 @@ import { getMultipleVideoSupportFeatureFlag } from '../../../react/features/base
import { MEDIA_TYPE, VIDEO_TYPE } from '../../../react/features/base/media';
import {
getParticipantById,
getPinnedParticipant
getPinnedParticipant,
isScreenShareParticipant,
isScreenShareParticipantById
} from '../../../react/features/base/participants';
import {
getTrackByMediaTypeAndParticipant,
@ -90,12 +92,13 @@ const VideoLayout = {
getRemoteVideoType(id) {
const state = APP.store.getState();
const participant = getParticipantById(state, id);
const isScreenShare = isScreenShareParticipantById(state, id);
if (participant?.isFakeParticipant) {
if (participant?.fakeParticipant && !isScreenShare) {
return VIDEO_TYPE.CAMERA;
}
if (getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShare) {
return VIDEO_TYPE.DESKTOP;
}
@ -190,7 +193,7 @@ const VideoLayout = {
let videoTrack;
if (getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShareParticipant(participant)) {
videoTrack = getVirtualScreenshareParticipantTrack(tracks, id);
} else {
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);

View File

@ -36,7 +36,7 @@ import {
getVirtualScreenshareParticipantOwnerId
} from './functions';
import logger from './logger';
import { Participant } from './types';
import { FakeParticipant, Participant } from './types';
/**
* Create an action for when dominant speaker changes.
@ -386,10 +386,8 @@ export function hiddenParticipantLeft(id: string) {
* instance.
* @param {Object} participantLeftProps - Other participant properties.
* @typedef {Object} participantLeftProps
* @param {FakeParticipant|undefined} participantLeftProps.fakeParticipant - The type of fake participant.
* @param {boolean} participantLeftProps.isReplaced - Whether the participant is to be replaced in the meeting.
* @param {boolean} participantLeftProps.isVirtualScreenshareParticipant - Whether the participant is a
* virtual screen share participant.
* @param {boolean} participantLeftProps.isFakeParticipant - Whether the participant is a fake participant.
*
* @returns {{
* type: PARTICIPANT_LEFT,
@ -404,11 +402,9 @@ export function participantLeft(id: string, conference: any, participantLeftProp
type: PARTICIPANT_LEFT,
participant: {
conference,
fakeParticipant: participantLeftProps.fakeParticipant,
id,
isReplaced: participantLeftProps.isReplaced,
isVirtualScreenshareParticipant: participantLeftProps.isVirtualScreenshareParticipant,
isWhiteboard: participantLeftProps.isWhiteboard,
isFakeParticipant: participantLeftProps.isFakeParticipant
isReplaced: participantLeftProps.isReplaced
}
};
}
@ -538,9 +534,8 @@ export function createVirtualScreenshareParticipant(sourceName: string, local: b
dispatch(participantJoined({
conference: state['features/base/conference'].conference,
fakeParticipant: local ? FakeParticipant.LocalScreenShare : FakeParticipant.RemoteScreenShare,
id: sourceName,
isVirtualScreenshareParticipant: true,
isLocalScreenShare: local,
name: ownerName
}));
};

View File

@ -13,6 +13,7 @@ import { connect } from '../../redux';
import { TestHint } from '../../testing/components';
import { getVideoTrackByParticipant } from '../../tracks';
import { getParticipantById, shouldRenderParticipantVideo } from '../functions';
import { FakeParticipant } from '../types';
import styles from './styles';
@ -31,11 +32,11 @@ type Props = {
_connectionStatus: string,
/**
* True if the participant which this component represents is fake.
* The type of participant if the participant which this component represents is fake.
*
* @private
*/
_isFakeParticipant: boolean,
_fakeParticipant?: FakeParticipant,
/**
* The name of the participant which this component represents.
@ -174,7 +175,7 @@ class ParticipantView extends Component<Props> {
render() {
const {
_connectionStatus: connectionStatus,
_isFakeParticipant,
_fakeParticipant,
_renderVideo: renderVideo,
_videoTrack: videoTrack,
disableVideo,
@ -190,7 +191,7 @@ class ParticipantView extends Component<Props> {
? this.props.testHintId
: `org.jitsi.meet.Participant#${this.props.participantId}`;
const renderSharedVideo = _isFakeParticipant && !disableVideo;
const renderSharedVideo = _fakeParticipant && !disableVideo;
return (
<Container
@ -208,7 +209,7 @@ class ParticipantView extends Component<Props> {
{ renderSharedVideo && <SharedVideo /> }
{ !_isFakeParticipant && renderVideo
{ !_fakeParticipant && renderVideo
&& <VideoTrack
onPress = { onPress }
videoTrack = { videoTrack }
@ -248,8 +249,7 @@ class ParticipantView extends Component<Props> {
function _mapStateToProps(state, ownProps) {
const { disableVideo, participantId } = ownProps;
const participant = getParticipantById(state, participantId);
const tracks = state['features/base/tracks'];
const videoTrack = getVideoTrackByParticipant(tracks, participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
let connectionStatus;
let participantName;
@ -257,7 +257,7 @@ function _mapStateToProps(state, ownProps) {
_connectionStatus:
connectionStatus
|| JitsiParticipantConnectionStatus.ACTIVE,
_isFakeParticipant: participant && participant.isFakeParticipant,
_fakeParticipant: participant?.fakeParticipant,
_participantName: participantName,
_renderVideo: shouldRenderParticipantVideo(state, participantId) && !disableVideo,
_videoTrack: videoTrack

View File

@ -2,7 +2,7 @@
// @ts-ignore
import { getGravatarURL } from '@jitsi/js-utils/avatar';
import { IStore } from '../../app/types';
import { IState, IStore } from '../../app/types';
// @ts-ignore
import { isStageFilmstripAvailable } from '../../filmstrip/functions';
import { IStateful } from '../app/types';
@ -24,7 +24,7 @@ import {
} from './constants';
// @ts-ignore
import { preloadImage } from './preloadImage';
import { Participant } from './types';
import { FakeParticipant, Participant } from './types';
/**
* Temp structures for avatar urls to be checked/preloaded.
@ -34,10 +34,10 @@ const AVATAR_CHECKED_URLS = new Map();
/* eslint-disable arrow-body-style, no-unused-vars */
const AVATAR_CHECKER_FUNCTIONS = [
(participant: Participant) => {
return participant?.isJigasi ? JIGASI_PARTICIPANT_ICON : null;
return isJigasiParticipant(participant) ? JIGASI_PARTICIPANT_ICON : null;
},
(participant: Participant) => {
return participant?.isWhiteboard ? WHITEBOARD_PARTICIPANT_ICON : null;
return isWhiteboardParticipant(participant) ? WHITEBOARD_PARTICIPANT_ICON : null;
},
(participant: Participant) => {
return participant?.avatarURL ? participant.avatarURL : null;
@ -115,7 +115,7 @@ export function getActiveSpeakersToBeDisplayed(stateful: IStateful) {
}
}
// Remove shared video from the count.
// Remove fake participants from the count.
if (fakeParticipants) {
availableSlotsForActiveSpeakers -= fakeParticipants.size;
}
@ -301,6 +301,69 @@ export function getFakeParticipants(stateful: IStateful) {
return toState(stateful)['features/base/participants'].fakeParticipants;
}
/**
* Returns whether the fake participant is Jigasi.
*
* @param {Participant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's a Jigasi participant.
*/
function isJigasiParticipant(participant?: Participant): boolean {
return participant?.fakeParticipant === FakeParticipant.Jigasi;
}
/**
* Returns whether the fake participant is a local screenshare.
*
* @param {Participant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's a local screenshare participant.
*/
export function isLocalScreenshareParticipant(participant?: Participant): boolean {
return participant?.fakeParticipant === FakeParticipant.LocalScreenShare;
}
/**
* Returns whether the fake participant is a remote screenshare.
*
* @param {Participant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's a remote screenshare participant.
*/
export function isRemoteScreenshareParticipant(participant?: Participant): boolean {
return participant?.fakeParticipant === FakeParticipant.RemoteScreenShare;
}
/**
* Returns whether the fake participant is of local or virtual screenshare type.
*
* @param {IState} state - The (whole) redux state, or redux's.
* @param {string|undefined} participantId - The participant id.
* @returns {boolean} - True if it's one of the two.
*/
export function isScreenShareParticipantById(state: IState, participantId?: string): boolean {
const participant = getParticipantByIdOrUndefined(state, participantId);
return isScreenShareParticipant(participant);
}
/**
* Returns whether the fake participant is of local or virtual screenshare type.
*
* @param {Participant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's one of the two.
*/
export function isScreenShareParticipant(participant?: Participant): boolean {
return isLocalScreenshareParticipant(participant) || isRemoteScreenshareParticipant(participant);
}
/**
* Returns whether the fake participant is a whiteboard.
*
* @param {Participant|undefined} participant - The participant entity.
* @returns {boolean} - True if it's a whiteboard participant.
*/
export function isWhiteboardParticipant(participant?: Participant): boolean {
return participant?.fakeParticipant === FakeParticipant.Whiteboard;
}
/**
* Returns a count of the known remote participants in the passed in redux state.
*
@ -349,15 +412,16 @@ export function getParticipantCountWithFake(stateful: IStateful) {
* @returns {string}
*/
export function getParticipantDisplayName(stateful: IStateful, id: string): string {
const participant = getParticipantById(stateful, id);
const state = toState(stateful);
const participant = getParticipantById(state, id);
const {
defaultLocalDisplayName,
defaultRemoteDisplayName
} = toState(stateful)['features/base/config'];
} = state['features/base/config'];
if (participant) {
if (participant.isVirtualScreenshareParticipant) {
return getScreenshareParticipantDisplayName(stateful, id);
if (isScreenShareParticipant(participant)) {
return getScreenshareParticipantDisplayName(state, id);
}
if (participant.name) {
@ -546,7 +610,7 @@ export function shouldRenderParticipantVideo(stateful: IStateful, id: string) {
}
/* First check if we have an unmuted video track. */
const videoTrack = getVideoTrackByParticipant(state['features/base/tracks'], participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
if (!shouldRenderVideoTrack(videoTrack, /* waitForVideoStarted */ false)) {
return false;

View File

@ -74,11 +74,13 @@ import {
getRaiseHandsQueue,
getRemoteParticipants,
hasRaisedHand,
isLocalParticipantModerator
isLocalParticipantModerator,
isScreenShareParticipant,
isWhiteboardParticipant
} from './functions';
import logger from './logger';
import { PARTICIPANT_JOINED_FILE, PARTICIPANT_LEFT_FILE } from './sounds';
import { IJitsiParticipant } from './types';
import { FakeParticipant, IJitsiParticipant } from './types';
import './subscriber';
@ -267,19 +269,19 @@ MiddlewareRegistry.register(store => next => action => {
}
case PARTICIPANT_JOINED: {
const { isVirtualScreenshareParticipant, isWhiteboard } = action.participant;
// Do not play sounds when a virtual participant tile is created for screenshare.
(!isVirtualScreenshareParticipant && !isWhiteboard) && _maybePlaySounds(store, action);
// Do not play sounds when a screenshare or whiteboard participant tile is created for screenshare.
(!isScreenShareParticipant(action.participant)
&& !isWhiteboardParticipant(action.participant)
) && _maybePlaySounds(store, action);
return _participantJoinedOrUpdated(store, next, action);
}
case PARTICIPANT_LEFT: {
const { isVirtualScreenshareParticipant, isWhiteboard } = action.participant;
// Do not play sounds when a tile for screenshare is removed.
(!isVirtualScreenshareParticipant && !isWhiteboard) && _maybePlaySounds(store, action);
// Do not play sounds when a tile for screenshare or whiteboard is removed.
(!isScreenShareParticipant(action.participant)
&& !isWhiteboardParticipant(action.participant)
) && _maybePlaySounds(store, action);
break;
}
@ -436,7 +438,7 @@ StateListenerRegistry.register(
store.dispatch(participantUpdated({
conference,
id: participant.getId(),
isJigasi: value
fakeParticipant: value ? FakeParticipant.Jigasi : undefined
})),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
'features_screen-sharing': (participant: IJitsiParticipant, value: string) =>

View File

@ -18,7 +18,12 @@ import {
SET_LOADABLE_AVATAR_URL
} from './actionTypes';
import { LOCAL_PARTICIPANT_DEFAULT_ID, PARTICIPANT_ROLE } from './constants';
import { isParticipantModerator } from './functions';
import {
isLocalScreenshareParticipant,
isParticipantModerator,
isRemoteScreenshareParticipant,
isScreenShareParticipant
} from './functions';
import { LocalParticipant, Participant } from './types';
/**
@ -241,10 +246,8 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
case PARTICIPANT_JOINED: {
const participant = _participantJoined(action);
const {
fakeParticipant,
id,
isFakeParticipant,
isLocalScreenShare,
isVirtualScreenshareParticipant,
name,
pinned
} = participant;
@ -281,7 +284,7 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
};
}
if (isLocalScreenShare) {
if (isLocalScreenshareParticipant(participant)) {
return {
...state,
localScreenShare: participant
@ -300,7 +303,7 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
// The sort order of participants is preserved since Map remembers the original insertion order of the keys.
state.sortedRemoteParticipants = new Map(sortedRemoteParticipants);
if (isVirtualScreenshareParticipant) {
if (isRemoteScreenshareParticipant(participant)) {
const sortedRemoteVirtualScreenshareParticipants = [ ...state.sortedRemoteVirtualScreenshareParticipants ];
sortedRemoteVirtualScreenshareParticipants.push([ id, name ?? '' ]);
@ -308,7 +311,8 @@ ReducerRegistry.register<IParticipantsState>('features/base/participants',
state.sortedRemoteVirtualScreenshareParticipants = new Map(sortedRemoteVirtualScreenshareParticipants);
}
if (isFakeParticipant) {
// Exclude the screenshare participant from the fake participant count to avoid duplicates.
if (fakeParticipant && !isScreenShareParticipant(participant)) {
state.fakeParticipants.set(id, participant);
}
@ -509,12 +513,8 @@ function _participantJoined({ participant }: { participant: Participant; }) {
connectionStatus,
dominantSpeaker,
email,
isFakeParticipant,
isVirtualScreenshareParticipant,
isLocalScreenShare,
fakeParticipant,
isReplacing,
isJigasi,
isWhiteboard,
loadableAvatarUrl,
local,
name,
@ -543,13 +543,9 @@ function _participantJoined({ participant }: { participant: Participant; }) {
connectionStatus,
dominantSpeaker: dominantSpeaker || false,
email,
fakeParticipant,
id,
isFakeParticipant,
isVirtualScreenshareParticipant,
isLocalScreenShare,
isReplacing,
isJigasi,
isWhiteboard,
loadableAvatarUrl,
local: local || false,
name,

View File

@ -9,6 +9,7 @@ import {
import StateListenerRegistry from '../redux/StateListenerRegistry';
import { createVirtualScreenshareParticipant, participantLeft } from './actions';
import { FakeParticipant } from './types';
StateListenerRegistry.register(
/* selector */ state => state['features/base/tracks'],
@ -56,8 +57,8 @@ function _updateScreenshareParticipants({ getState, dispatch }: IStore) {
if (localScreenShare && !newLocalSceenshareSourceName) {
dispatch(participantLeft(localScreenShare.id, conference, {
isReplaced: undefined,
isVirtualScreenshareParticipant: true
fakeParticipant: FakeParticipant.LocalScreenShare,
isReplaced: undefined
}));
}
}
@ -67,8 +68,8 @@ function _updateScreenshareParticipants({ getState, dispatch }: IStore) {
if (removedScreenshareSourceNames.length) {
removedScreenshareSourceNames.forEach(id => dispatch(participantLeft(id, conference, {
isReplaced: undefined,
isVirtualScreenshareParticipant: true
fakeParticipant: FakeParticipant.RemoteScreenShare,
isReplaced: undefined
})));
}

View File

@ -1,3 +1,11 @@
export enum FakeParticipant {
Jigasi = 'Jigasi',
LocalScreenShare = 'LocalScreenShare',
RemoteScreenShare = 'RemoteScreenShare',
SharedVideo = 'SharedVideo',
Whiteboard = 'Whiteboard'
}
export interface Participant {
avatarURL?: string;
botType?: string;
@ -8,18 +16,14 @@ export interface Participant {
e2eeEnabled?: boolean;
e2eeSupported?: boolean;
email?: string;
fakeParticipant?: FakeParticipant;
features?: {
'screen-sharing'?: boolean | string;
};
getId?: Function;
id: string;
isFakeParticipant?: boolean;
isJigasi?: boolean;
isLocalScreenShare?: boolean;
isReplaced?: boolean;
isReplacing?: number;
isVirtualScreenshareParticipant?: boolean;
isWhiteboard?: boolean;
jwtId?: string;
loadableAvatarUrl?: string;
loadableAvatarUrlUseCORS?: boolean;

View File

@ -1,7 +1,7 @@
import { IState, IStore } from '../../app/types';
import { getMultipleVideoSupportFeatureFlag } from '../config/functions.any';
import { MEDIA_TYPE, VIDEO_TYPE } from '../media/constants';
import { getParticipantById } from '../participants/functions';
import { getParticipantById, isScreenShareParticipant } from '../participants/functions';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { getTrackByMediaTypeAndParticipant, getVirtualScreenshareParticipantTrack } from '../tracks';
@ -31,7 +31,7 @@ export function getRemoteVideoType({ getState }: IStore, id: string) {
const state = getState();
const participant = getParticipantById(state, id);
if (getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShareParticipant(participant)) {
return VIDEO_TYPE.DESKTOP;
}
@ -51,7 +51,7 @@ export function isLargeVideoReceived({ getState }: IStore): boolean {
const tracks = state['features/base/tracks'];
let videoTrack;
if (getMultipleVideoSupportFeatureFlag(state) && largeVideoParticipant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShareParticipant(largeVideoParticipant)) {
videoTrack = getVirtualScreenshareParticipantTrack(tracks, largeVideoParticipantId);
} else {
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideoParticipantId);
@ -75,7 +75,7 @@ export function isRemoteVideoReceived({ getState }: IStore, id: string): boolean
const participant = getParticipantById(state, id);
let videoTrack;
if (getMultipleVideoSupportFeatureFlag(state) && participant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShareParticipant(participant)) {
videoTrack = getVirtualScreenshareParticipantTrack(tracks, id);
} else {
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, id);

View File

@ -8,7 +8,11 @@ import { isMobileBrowser } from '../environment/utils';
import JitsiMeetJS, { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
import { setAudioMuted } from '../media/actions';
import { MEDIA_TYPE, MediaType, VIDEO_TYPE } from '../media/constants';
import { getParticipantByIdOrUndefined, getVirtualScreenshareParticipantOwnerId } from '../participants/functions';
import {
getParticipantByIdOrUndefined,
getVirtualScreenshareParticipantOwnerId,
isScreenShareParticipant
} from '../participants/functions';
import { Participant } from '../participants/types';
import { toState } from '../redux/functions';
import {
@ -47,7 +51,7 @@ export function isParticipantMediaMuted(participant: Participant, mediaType: Med
if (participant?.local) {
return isLocalTrackMuted(tracks, mediaType);
} else if (!participant?.isFakeParticipant) {
} else if (!participant?.fakeParticipant) {
return isRemoteTrackMuted(tracks, mediaType, participant.id);
}
@ -420,19 +424,21 @@ export function getLocalJitsiAudioTrack(state: IState) {
/**
* Returns track of specified media type for specified participant.
*
* @param {ITrack[]} tracks - List of all tracks.
* @param {IState} state - The redux state.
* @param {Participant} participant - Participant Object.
* @returns {(Track|undefined)}
*/
export function getVideoTrackByParticipant(
tracks: ITrack[],
state: IState,
participant?: Participant) {
if (!participant) {
return;
}
if (participant?.isVirtualScreenshareParticipant) {
const tracks = state['features/base/tracks'];
if (isScreenShareParticipant(participant)) {
return getVirtualScreenshareParticipantTrack(tracks, participant.id);
}
@ -448,8 +454,7 @@ export function getVideoTrackByParticipant(
*/
export function getSourceNameByParticipantId(state: IState, participantId: string) {
const participant = getParticipantByIdOrUndefined(state, participantId);
const tracks = state['features/base/tracks'];
const track = getVideoTrackByParticipant(tracks, participant);
const track = getVideoTrackByParticipant(state, participant);
return track?.jitsiTrack?.getSourceName();
}

View File

@ -13,7 +13,11 @@ import { IState } from '../../../app/types';
import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
import { translate } from '../../../base/i18n/functions';
import { MEDIA_TYPE } from '../../../base/media/constants';
import { getLocalParticipant, getParticipantById } from '../../../base/participants/functions';
import {
getLocalParticipant,
getParticipantById,
isScreenShareParticipant
} from '../../../base/participants/functions';
// @ts-ignore
import { Popover } from '../../../base/popover';
import {
@ -401,7 +405,7 @@ export function _mapStateToProps(state: IState, ownProps: Props) {
let firstVideoTrack;
if (sourceNameSignalingEnabled && participant?.isVirtualScreenshareParticipant) {
if (sourceNameSignalingEnabled && isScreenShareParticipant(participant)) {
firstVideoTrack = getVirtualScreenshareParticipantTrack(tracks, participantId);
} else {
firstVideoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, participantId);

View File

@ -6,7 +6,7 @@ import type { Dispatch } from 'redux';
import { getSourceNameSignalingFeatureFlag } from '../../../base/config';
import { translate } from '../../../base/i18n';
import { MEDIA_TYPE } from '../../../base/media';
import { getLocalParticipant, getParticipantById } from '../../../base/participants';
import { getLocalParticipant, getParticipantById, isScreenShareParticipant } from '../../../base/participants';
import { connect } from '../../../base/redux';
import { getSourceNameByParticipantId, getTrackByMediaTypeAndParticipant } from '../../../base/tracks';
import { ConnectionStatsTable } from '../../../connection-stats';
@ -352,7 +352,7 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
_disableShowMoreStats: state['features/base/config'].disableShowMoreStats,
_isConnectionStatusInactive,
_isConnectionStatusInterrupted,
_isVirtualScreenshareParticipant: sourceNameSignalingEnabled && participant?.isVirtualScreenshareParticipant,
_isVirtualScreenshareParticipant: sourceNameSignalingEnabled && isScreenShareParticipant(participant),
_isLocalVideo: participant?.local,
_region: participant?.region,
_sourceName: getSourceNameByParticipantId(state, participantId),

View File

@ -72,7 +72,7 @@ function _mapStateToProps(state: IState, ownProps: Partial<Props>) {
return {
_participantName: getParticipantDisplayName(state, ownProps.participantId ?? ''),
_render: participant && (!participant?.local || ownProps.contained) && !participant?.isFakeParticipant
_render: participant && (!participant?.local || ownProps.contained) && !participant?.fakeParticipant
};
}

View File

@ -8,7 +8,11 @@ import { makeStyles } from 'tss-react/mui';
import { IState } from '../../../app/types';
// @ts-ignore
import { isDisplayNameVisible } from '../../../base/config/functions.any';
import { getLocalParticipant, getParticipantDisplayName } from '../../../base/participants/functions';
import {
getLocalParticipant,
getParticipantDisplayName,
isWhiteboardParticipant
} from '../../../base/participants/functions';
import { Participant } from '../../../base/participants/types';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
// @ts-ignore
@ -64,7 +68,7 @@ const StageParticipantNameLabel = () => {
&& nameToDisplay
&& selectedId !== localId
&& !isTileView
&& !largeVideoParticipant?.isWhiteboard
&& !isWhiteboardParticipant(largeVideoParticipant)
) {
return (
<div

View File

@ -12,6 +12,7 @@ import {
getParticipantById,
getParticipantCount,
getRemoteParticipants,
isScreenShareParticipant,
participantUpdated
} from '../base/participants';
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
@ -94,11 +95,11 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
}
case PARTICIPANT_JOINED: {
const result = next(action);
const { e2eeEnabled, e2eeSupported, isVirtualScreenshareParticipant, local } = action.participant;
const { e2eeEnabled, e2eeSupported, local } = action.participant;
const { everyoneEnabledE2EE } = getState()['features/e2ee'];
const participantCount = getParticipantCount(getState);
if (isVirtualScreenshareParticipant) {
if (isScreenShareParticipant(action.participant)) {
return result;
}
@ -138,9 +139,9 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
const participant = getParticipantById(previosState, action.participant?.id) || {};
const result = next(action);
const newState = getState();
const { e2eeEnabled = false, e2eeSupported = false, isVirtualScreenshareParticipant } = participant;
const { e2eeEnabled = false, e2eeSupported = false } = participant;
if (isVirtualScreenshareParticipant) {
if (isScreenShareParticipant(participant)) {
return result;
}

View File

@ -163,10 +163,10 @@ MiddlewareRegistry.register(store => next => action => {
case PARTICIPANT_LEFT: {
const { participant } = action;
const { isFakeParticipant, isVirtualScreenshareParticipant, isWhiteboard } = participant;
const { fakeParticipant } = participant;
// Skip sending participant left event for fake or virtual screenshare participants.
if (isFakeParticipant || isVirtualScreenshareParticipant || isWhiteboard) {
// Skip sending participant left event for fake participants.
if (fakeParticipant) {
break;
}
@ -177,13 +177,13 @@ MiddlewareRegistry.register(store => next => action => {
const state = store.getState();
const { defaultRemoteDisplayName } = state['features/base/config'];
const { participant } = action;
const { id, isFakeParticipant, isVirtualScreenshareParticipant, local, name } = participant;
const { fakeParticipant, id, local, name } = participant;
// The version of external api outside of middleware did not emit
// the local participant being created.
if (!local) {
// Skip sending participant joined event for fake or virtual screenshare participants.
if (isFakeParticipant || isVirtualScreenshareParticipant) {
// Skip sending participant joined event for fake participants.
if (fakeParticipant) {
break;
}

View File

@ -15,8 +15,10 @@ import {
getParticipantCount,
hasRaisedHand,
isEveryoneModerator,
isScreenShareParticipant,
pinParticipant
} from '../../../base/participants';
import { FakeParticipant } from '../../../base/participants/types';
import { Container } from '../../../base/react';
import { connect } from '../../../base/redux';
import {
@ -57,9 +59,9 @@ type Props = {
_gifSrc: ?string,
/**
* Indicates whether the participant is fake.
* The type of participant if the participant is fake.
*/
_isFakeParticipant: boolean,
_fakeParticipant?: FakeParticipant,
/**
* Indicates whether the participant is screen sharing.
@ -189,13 +191,13 @@ class Thumbnail extends PureComponent<Props> {
* @returns {void}
*/
_onThumbnailLongPress() {
const { _participantId, _local, _isFakeParticipant, _localVideoOwner, dispatch } = this.props;
const { _fakeParticipant, _participantId, _local, _localVideoOwner, dispatch } = this.props;
if (_isFakeParticipant && _localVideoOwner) {
if (_fakeParticipant && _localVideoOwner) {
dispatch(showSharedVideoMenu(_participantId));
}
if (!_isFakeParticipant) {
if (!_fakeParticipant) {
dispatch(showContextMenuDetails(_participantId, _local));
}
}
@ -208,9 +210,9 @@ class Thumbnail extends PureComponent<Props> {
_renderIndicators() {
const {
_audioMuted: audioMuted,
_fakeParticipant,
_isScreenShare: isScreenShare,
_isVirtualScreenshare,
_isFakeParticipant,
_renderModeratorIndicator: renderModeratorIndicator,
_participantId: participantId,
_pinned,
@ -219,7 +221,7 @@ class Thumbnail extends PureComponent<Props> {
} = this.props;
const indicators = [];
if (!_isFakeParticipant) {
if (!_fakeParticipant) {
indicators.push(<View
key = 'top-left-indicators'
style = { [
@ -342,8 +344,8 @@ class Thumbnail extends PureComponent<Props> {
*/
render() {
const {
_fakeParticipant,
_gifSrc,
_isFakeParticipant,
_isScreenShare: isScreenShare,
_isVirtualScreenshare,
_participantId: participantId,
@ -378,7 +380,7 @@ class Thumbnail extends PureComponent<Props> {
: <>
<ParticipantView
avatarSize = { tileView ? AVATAR_SIZE * 1.5 : AVATAR_SIZE }
disableVideo = { isScreenShare || _isFakeParticipant }
disableVideo = { isScreenShare || _fakeParticipant }
participantId = { participantId }
zOrder = { 1 } />
{
@ -406,7 +408,7 @@ function _mapStateToProps(state, ownProps) {
const localParticipantId = getLocalParticipant(state).id;
const id = participant?.id;
const audioTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, id);
const videoTrack = getVideoTrackByParticipant(tracks, participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
const isMultiStreamSupportEnabled = getMultipleVideoSupportFeatureFlag(state);
const isScreenShare = videoTrack?.videoType === VIDEO_TYPE.DESKTOP;
const participantCount = getParticipantCount(state);
@ -419,10 +421,10 @@ function _mapStateToProps(state, ownProps) {
return {
_audioMuted: audioTrack?.muted ?? true,
_fakeParticipant: participant?.fakeParticipant,
_gifSrc: mode === 'chat' ? null : gifSrc,
_isFakeParticipant: participant?.isFakeParticipant,
_isScreenShare: isScreenShare,
_isVirtualScreenshare: isMultiStreamSupportEnabled && participant?.isVirtualScreenshareParticipant,
_isVirtualScreenshare: isMultiStreamSupportEnabled && isScreenShareParticipant(participant),
_local: participant?.local,
_localVideoOwner: Boolean(ownerId === localParticipantId),
_participantId: id,

View File

@ -3,7 +3,11 @@
import React, { Component } from 'react';
import { MEDIA_TYPE } from '../../../base/media';
import { PARTICIPANT_ROLE, getParticipantByIdOrUndefined } from '../../../base/participants';
import {
PARTICIPANT_ROLE,
getParticipantByIdOrUndefined,
isScreenShareParticipantById
} from '../../../base/participants';
import { connect } from '../../../base/redux';
import {
getVideoTrackByParticipant,
@ -104,8 +108,9 @@ function _mapStateToProps(state, ownProps) {
if (participant?.local) {
isAudioMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.AUDIO);
} else if (!participant?.isFakeParticipant) { // remote participants excluding shared video
const track = getVideoTrackByParticipant(tracks, participant);
} else if (!participant?.fakeParticipant || isScreenShareParticipantById(state, participantID)) {
// remote participants excluding shared video
const track = getVideoTrackByParticipant(state, participant);
isScreenSharing = track?.videoType === 'desktop';
isAudioMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.AUDIO, participantID);

View File

@ -22,7 +22,10 @@ import { pinParticipant } from '../../../base/participants/actions';
import {
getLocalParticipant,
getParticipantByIdOrUndefined,
hasRaisedHand
hasRaisedHand,
isLocalScreenshareParticipant,
isScreenShareParticipant,
isWhiteboardParticipant
} from '../../../base/participants/functions';
import { Participant } from '../../../base/participants/types';
import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants';
@ -1050,7 +1053,7 @@ class Thumbnail extends Component<Props, State> {
_thumbnailType === THUMBNAIL_TYPE.TILE && 'tile-view-mode'
) }>
<ThumbnailTopIndicators
disableConnectionIndicator = { _participant?.isWhiteboard }
disableConnectionIndicator = { isWhiteboardParticipant(_participant) }
hidePopover = { this._hidePopover }
indicatorsClassName = { classes.indicatorsBackground }
isHovered = { isHovered }
@ -1067,10 +1070,9 @@ class Thumbnail extends Component<Props, State> {
) }>
<ThumbnailBottomIndicators
className = { classes.indicatorsBackground }
isVirtualScreenshareParticipant = { false }
local = { local }
participantId = { id }
showStatusIndicators = { !_participant?.isWhiteboard }
showStatusIndicators = { !isWhiteboardParticipant(_participant) }
thumbnailType = { _thumbnailType } />
</div>
{!_gifSrc && this._renderAvatar(styles.avatar) }
@ -1115,13 +1117,16 @@ class Thumbnail extends Component<Props, State> {
return null;
}
const { isFakeParticipant, isLocalScreenShare, isWhiteboard, local } = _participant;
const { fakeParticipant, local } = _participant;
if (local) {
return this._renderParticipant(true);
}
if (isFakeParticipant && !isWhiteboard) {
if (fakeParticipant
&& !isWhiteboardParticipant(_participant)
&& !_isVirtualScreenshareParticipant
) {
return this._renderFakeParticipant();
}
@ -1141,7 +1146,7 @@ class Thumbnail extends Component<Props, State> {
classes = { classes }
containerClassName = { this._getContainerClassName() }
isHovered = { isHovered }
isLocal = { isLocalScreenShare }
isLocal = { isLocalScreenshareParticipant(_participant) }
isMobile = { _isMobile }
onClick = { this._onClick }
onMouseEnter = { this._onMouseEnter }
@ -1177,11 +1182,12 @@ function _mapStateToProps(state: IState, ownProps: any): Object {
const isLocal = participant?.local ?? true;
const multipleVideoSupportEnabled = getMultipleVideoSupportFeatureFlag(state);
const sourceNameSignalingEnabled = getSourceNameSignalingFeatureFlag(state);
const _isVirtualScreenshareParticipant = multipleVideoSupportEnabled && isScreenShareParticipant(participant);
const tracks = state['features/base/tracks'];
let _videoTrack;
if (multipleVideoSupportEnabled && participant?.isVirtualScreenshareParticipant) {
if (_isVirtualScreenshareParticipant) {
_videoTrack = getVirtualScreenshareParticipantTrack(tracks, id);
} else {
_videoTrack = isLocal
@ -1304,7 +1310,7 @@ function _mapStateToProps(state: IState, ownProps: any): Object {
_isScreenSharing: _videoTrack?.videoType === 'desktop',
_isTestModeEnabled: isTestModeEnabled(state),
_isVideoPlayable: id && isVideoPlayable(state, id),
_isVirtualScreenshareParticipant: multipleVideoSupportEnabled && participant?.isVirtualScreenshareParticipant,
_isVirtualScreenshareParticipant,
_localFlipX: Boolean(localFlipX),
_multipleVideoSupport: multipleVideoSupportEnabled,
_participant: participant,

View File

@ -4,12 +4,14 @@ import React from 'react';
import { useSelector } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { IState } from '../../../app/types';
import {
getMultipleVideoSupportFeatureFlag,
isDisplayNameVisible,
isNameReadOnly
// @ts-ignore
} from '../../../base/config/functions.any';
import { isScreenShareParticipantById } from '../../../base/participants/functions';
// @ts-ignore
import DisplayName from '../../../display-name/components/web/DisplayName';
import { THUMBNAIL_TYPE } from '../../constants';
@ -26,11 +28,6 @@ type Props = {
*/
className: string;
/**
* Whether it is a virtual screenshare participant thumbnail.
*/
isVirtualScreenshareParticipant: boolean;
/**
* Whether or not the indicators are for the local participant.
*/
@ -73,7 +70,6 @@ const useStyles = makeStyles()(() => {
const ThumbnailBottomIndicators = ({
className,
isVirtualScreenshareParticipant,
local,
participantId,
showStatusIndicators = true,
@ -84,6 +80,9 @@ const ThumbnailBottomIndicators = ({
const _defaultLocalDisplayName = interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME;
const _isMultiStreamEnabled = useSelector(getMultipleVideoSupportFeatureFlag);
const _showDisplayName = useSelector(isDisplayNameVisible);
const isVirtualScreenshareParticipant = useSelector(
(state: IState) => isScreenShareParticipantById(state, participantId)
);
return (<div className = { className }>
{

View File

@ -8,6 +8,7 @@ import { IState } from '../../../app/types';
// @ts-ignore
import { getMultipleVideoSupportFeatureFlag } from '../../../base/config';
import { isMobileBrowser } from '../../../base/environment/utils';
import { isScreenShareParticipantById } from '../../../base/participants/functions';
// @ts-ignore
import ConnectionIndicator from '../../../connection-indicator/components/web/ConnectionIndicator';
import { STATS_POPOVER_POSITION, THUMBNAIL_TYPE } from '../../constants';
@ -46,11 +47,6 @@ type Props = {
*/
isHovered: boolean;
/**
* Whether or not the thumbnail is a virtual screen share participant.
*/
isVirtualScreenshareParticipant?: boolean;
/**
* Whether or not the indicators are for the local participant.
*/
@ -93,7 +89,6 @@ const ThumbnailTopIndicators = ({
disableConnectionIndicator,
hidePopover,
indicatorsClassName,
isVirtualScreenshareParticipant,
isHovered,
local,
participantId,
@ -112,6 +107,9 @@ const ThumbnailTopIndicators = ({
|| Boolean(useSelector((state: IState) => state['features/base/config'].connectionIndicators?.disabled));
const _isMultiStreamEnabled = useSelector(getMultipleVideoSupportFeatureFlag);
const showConnectionIndicator = isHovered || !_connectionIndicatorAutoHideEnabled;
const isVirtualScreenshareParticipant = useSelector(
(state: IState) => isScreenShareParticipantById(state, participantId)
);
if (_isMultiStreamEnabled && isVirtualScreenshareParticipant) {
return (

View File

@ -147,7 +147,6 @@ const VirtualScreenshareParticipant = ({
<ThumbnailTopIndicators
currentLayout = { currentLayout }
isHovered = { isHovered }
isVirtualScreenshareParticipant = { true }
participantId = { participantId }
thumbnailType = { thumbnailType } />
</div>
@ -159,7 +158,6 @@ const VirtualScreenshareParticipant = ({
<ThumbnailBottomIndicators
className = { classes.indicatorsBackground }
currentLayout = { currentLayout }
isVirtualScreenshareParticipant = { true }
local = { false }
participantId = { participantId }
showStatusIndicators = { true } />

View File

@ -8,7 +8,8 @@ import {
getParticipantById,
getParticipantCount,
getParticipantCountWithFake,
getPinnedParticipant
getPinnedParticipant,
isScreenShareParticipant
} from '../base/participants';
import { toState } from '../base/redux';
import { shouldHideSelfView } from '../base/settings/functions.any';
@ -129,7 +130,8 @@ export function isVideoPlayable(stateful: Object | Function, id: String) {
const isVideoMuted = isLocalTrackMuted(tracks, MEDIA_TYPE.VIDEO);
isPlayable = Boolean(videoTrack) && !isVideoMuted && !isAudioOnly;
} else if (!participant?.isFakeParticipant) { // remote participants excluding shared video
} else if (!participant?.fakeParticipant || isScreenShareParticipant(participant)) {
// remote participants excluding shared video
const isVideoMuted = isRemoteTrackMuted(tracks, MEDIA_TYPE.VIDEO, id);
if (getSourceNameSignalingFeatureFlag(state)) {
@ -589,7 +591,7 @@ export function getDisplayModeInput(props: Object, state: Object) {
connectionStatus: _participant?.connectionStatus,
canPlayEventReceived,
videoStream: Boolean(_videoTrack),
isRemoteParticipant: !_participant?.isFakeParticipant && !_participant?.local,
isRemoteParticipant: !_participant?.fakeParticipant && !_participant?.local,
isScreenSharing: _isScreenSharing,
isVirtualScreenshareParticipant: _isVirtualScreenshareParticipant,
multipleVideoSupport: _multipleVideoSupport,

View File

@ -9,7 +9,8 @@ import {
PARTICIPANT_LEFT,
getDominantSpeakerParticipant,
getLocalParticipant,
getLocalScreenShareParticipant
getLocalScreenShareParticipant,
isScreenShareParticipant
} from '../base/participants';
import { MiddlewareRegistry } from '../base/redux';
import { CLIENT_RESIZED } from '../base/responsive-ui';
@ -108,7 +109,7 @@ MiddlewareRegistry.register(store => next => action => {
}
case PARTICIPANT_JOINED: {
result = next(action);
if (action.participant?.isLocalScreenShare) {
if (isScreenShareParticipant(action.participant)) {
break;
}

View File

@ -255,7 +255,7 @@ function _mapStateToProps(state) {
const { participantId } = state['features/large-video'];
const participant = getParticipantById(state, participantId);
const { clientHeight: height, clientWidth: width } = state['features/base/responsive-ui'];
const videoTrack = getVideoTrackByParticipant(state['features/base/tracks'], participant);
const videoTrack = getVideoTrackByParticipant(state, participant);
let disableVideo = false;
if (participant?.local) {

View File

@ -5,7 +5,7 @@ import React, { Component } from 'react';
import VideoLayout from '../../../../modules/UI/videolayout/VideoLayout';
import { getMultipleVideoSupportFeatureFlag } from '../../base/config';
import { MEDIA_TYPE, VIDEO_TYPE } from '../../base/media';
import { getLocalParticipant } from '../../base/participants';
import { getLocalParticipant, isScreenShareParticipant } from '../../base/participants';
import { Watermarks } from '../../base/react';
import { connect } from '../../base/redux';
import { getTrackByMediaTypeAndParticipant, getVirtualScreenshareParticipantTrack } from '../../base/tracks';
@ -346,7 +346,7 @@ function _mapStateToProps(state) {
const largeVideoParticipant = getLargeVideoParticipant(state);
let videoTrack;
if (getMultipleVideoSupportFeatureFlag(state) && largeVideoParticipant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShareParticipant(largeVideoParticipant)) {
videoTrack = getVirtualScreenshareParticipantTrack(tracks, largeVideoParticipant?.id);
} else {
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideoParticipant?.id);

View File

@ -3,6 +3,7 @@
import VideoLayout from '../../../modules/UI/videolayout/VideoLayout';
import { getMultipleVideoSupportFeatureFlag } from '../base/config';
import { MEDIA_TYPE } from '../base/media';
import { isScreenShareParticipant } from '../base/participants';
import { StateListenerRegistry } from '../base/redux';
import { getTrackByMediaTypeAndParticipant, getVirtualScreenshareParticipantTrack } from '../base/tracks';
@ -27,7 +28,7 @@ StateListenerRegistry.register(
const tracks = state['features/base/tracks'];
let videoTrack;
if (getMultipleVideoSupportFeatureFlag(state) && largeVideoParticipant?.isVirtualScreenshareParticipant) {
if (getMultipleVideoSupportFeatureFlag(state) && isScreenShareParticipant(largeVideoParticipant)) {
videoTrack = getVirtualScreenshareParticipantTrack(tracks, largeVideoParticipant?.id);
} else {
videoTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.VIDEO, largeVideoParticipant?.id);

View File

@ -32,7 +32,8 @@ import {
PARTICIPANT_LEFT,
getLocalParticipant,
getParticipantById,
getRemoteParticipants
getRemoteParticipants,
isScreenShareParticipant
} from '../../base/participants';
import { MiddlewareRegistry, StateListenerRegistry } from '../../base/redux';
import { getLocalTracks, isLocalTrackMuted, toggleScreensharing } from '../../base/tracks';
@ -182,7 +183,7 @@ MiddlewareRegistry.register(store => next => action => {
const { participant } = action;
if (participant.isVirtualScreenshareParticipant) {
if (isScreenShareParticipant(participant)) {
break;
}
@ -343,7 +344,7 @@ function _registerForNativeEvents(store) {
participantsInfo.push(_participantToParticipantInfo(localParticipant));
remoteParticipants.forEach(participant => {
if (!participant.isFakeParticipant) {
if (!participant.fakeParticipant) {
participantsInfo.push(_participantToParticipantInfo(participant));
}
});

View File

@ -9,7 +9,9 @@ import { PARTICIPANT_ROLE } from '../base/participants/constants';
import {
getLocalParticipant,
getParticipantById,
getParticipantDisplayName
getParticipantDisplayName,
isScreenShareParticipant,
isWhiteboardParticipant
} from '../base/participants/functions';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import StateListenerRegistry from '../base/redux/StateListenerRegistry';
@ -132,8 +134,8 @@ MiddlewareRegistry.register(store => next => action => {
// Do not display notifications for the virtual screenshare and whiteboard tiles.
if (conference
&& !p.local
&& !p.isVirtualScreenshareParticipant
&& !p.isWhiteboard
&& !isScreenShareParticipant(p)
&& !isWhiteboardParticipant(p)
&& !joinLeaveNotificationsDisabled()
&& !p.isReplacing) {
dispatch(showParticipantJoinedNotification(
@ -153,8 +155,8 @@ MiddlewareRegistry.register(store => next => action => {
// Do not display notifications for the virtual screenshare tiles.
if (participant
&& !participant.local
&& !participant.isVirtualScreenshareParticipant
&& !participant.isWhiteboard
&& !isScreenShareParticipant(participant)
&& !isWhiteboardParticipant(participant)
&& !action.participant.isReplaced) {
dispatch(showParticipantLeftNotification(
getParticipantDisplayName(state, participant.id)

View File

@ -10,6 +10,7 @@ import {
hasRaisedHand,
isParticipantModerator
} from '../../../base/participants';
import { FakeParticipant } from '../../../base/participants/types';
import { connect } from '../../../base/redux';
import {
isParticipantAudioMuted,
@ -40,9 +41,9 @@ type Props = {
_displayName: string,
/**
* True if the participant is fake.
* The type of fake participant.
*/
_isFakeParticipant: boolean,
_fakeParticipant: FakeParticipant,
/**
* Whether or not the user is a moderator.
@ -110,16 +111,16 @@ class MeetingParticipantItem extends PureComponent<Props> {
*/
_onPress() {
const {
_fakeParticipant,
_local,
_localVideoOwner,
_isFakeParticipant,
_participantID,
dispatch
} = this.props;
if (_isFakeParticipant && _localVideoOwner) {
if (_fakeParticipant && _localVideoOwner) {
dispatch(showSharedVideoMenu(_participantID));
} else if (!_isFakeParticipant) {
} else if (!_fakeParticipant) {
if (_local) {
dispatch(showConnectionStatus(_participantID));
} else {
@ -188,8 +189,8 @@ function mapStateToProps(state, ownProps): Object {
_audioMediaState: audioMediaState,
_disableModeratorIndicator: disableModeratorIndicator,
_displayName: getParticipantDisplayName(state, participant?.id),
_fakeParticipant: participant?.fakeParticipant,
_isAudioMuted,
_isFakeParticipant: Boolean(participant?.isFakeParticipant),
_isModerator: isParticipantModerator(participant),
_local: Boolean(participant?.local),
_localVideoOwner: Boolean(ownerId === localParticipantId),

View File

@ -102,7 +102,7 @@ class MeetingParticipantContextMenu extends Component<Props> {
thumbnailMenu: false
};
if (_participant?.isFakeParticipant) {
if (_participant?.fakeParticipant) {
return (
<FakeParticipantContextMenu
{ ...props }

View File

@ -252,7 +252,7 @@ function MeetingParticipantItem({
<ParticipantItem
actionsTrigger = { ACTION_TRIGGER.HOVER }
{
...(_participant?.isFakeParticipant ? {} : {
...(_participant?.fakeParticipant ? {} : {
audioMediaState,
videoMediaState: _videoMediaState
})
@ -269,7 +269,7 @@ function MeetingParticipantItem({
raisedHand = { _raisedHand }
youText = { youText }>
{!overflowDrawer && !_participant?.isFakeParticipant
{!overflowDrawer && !_participant?.fakeParticipant
&& <>
{!isInBreakoutRoom && (
<ParticipantQuickAction
@ -286,7 +286,7 @@ function MeetingParticipantItem({
</>
}
{!overflowDrawer && (_localVideoOwner || _participant?.isWhiteboard) && _participant?.isFakeParticipant && (
{!overflowDrawer && (_localVideoOwner || _participant?.fakeParticipant) && (
<ParticipantActionEllipsis
accessibilityLabel = { participantActionEllipsisLabel }
onClick = { onContextMenu } />

View File

@ -13,7 +13,7 @@ import participantsPaneTheme from '../../../base/components/themes/participantsP
// @ts-ignore
import { isToolbarButtonEnabled } from '../../../base/config/functions.web';
import { MEDIA_TYPE } from '../../../base/media/constants';
import { getParticipantById } from '../../../base/participants/functions';
import { getParticipantById, isScreenShareParticipant } from '../../../base/participants/functions';
import { connect } from '../../../base/redux/functions';
import { withPixelLineHeight } from '../../../base/styles/functions.web';
import Input from '../../../base/ui/components/web/Input';
@ -174,7 +174,7 @@ function _mapStateToProps(state: IState): Object {
sortedParticipantIds = sortedParticipantIds.filter((id: any) => {
const participant = getParticipantById(state, id);
return !participant?.isVirtualScreenshareParticipant;
return !isScreenShareParticipant(participant);
});
const participantsCount = sortedParticipantIds.length;

View File

@ -3,7 +3,8 @@
import {
getParticipantById,
getVirtualScreenshareParticipantByOwnerId,
getVirtualScreenshareParticipantOwnerId
getVirtualScreenshareParticipantOwnerId,
isScreenShareParticipant
} from '../base/participants';
import { StateListenerRegistry } from '../base/redux';
@ -24,7 +25,7 @@ StateListenerRegistry.register(
const participant = getParticipantById(state, participantId);
if (participant?.isVirtualScreenshareParticipant) {
if (isScreenShareParticipant(participant)) {
// multistream support is enabled and the user has selected the desktop sharing thumbnail.
const id = getVirtualScreenshareParticipantOwnerId(participantId);

View File

@ -13,6 +13,7 @@ import {
participantLeft,
pinParticipant
} from '../base/participants';
import { FakeParticipant } from '../base/participants/types';
import { MiddlewareRegistry } from '../base/redux';
import { RESET_SHARED_VIDEO_STATUS, SET_SHARED_VIDEO_STATUS } from './actionTypes';
@ -55,7 +56,7 @@ MiddlewareRegistry.register(store => next => action => {
const videoParticipant = getParticipantById(state, value);
dispatch(participantLeft(value, conference, {
isFakeParticipant: videoParticipant?.isFakeParticipant
fakeParticipant: videoParticipant?.fakeParticipant
}));
if (localParticipantId !== from) {
@ -162,8 +163,8 @@ function handleSharingVideoStatus(store, videoUrl, { state, time, from, muted },
dispatch(participantJoined({
conference,
fakeParticipant: FakeParticipant.SharedVideo,
id: videoUrl,
isFakeParticipant: true,
avatarURL,
name: VIDEO_PLAYER_PARTICIPANT_NAME
}));

View File

@ -124,7 +124,7 @@ export function updateAutoPinnedParticipant(
const pinned = getPinnedParticipant(getState);
// if the pinned participant is shared video or some other fake participant we want to skip auto-pinning
if (pinned?.isFakeParticipant) {
if (pinned?.fakeParticipant) {
return;
}

View File

@ -39,7 +39,7 @@ MiddlewareRegistry.register(store => next => action => {
if (!getAutoPinSetting() || isFollowMeActive(store)) {
break;
}
shouldUpdateAutoPin = getParticipantById(store.getState(), action.participant.id)?.isFakeParticipant;
shouldUpdateAutoPin = Boolean(getParticipantById(store.getState(), action.participant.id)?.fakeParticipant);
break;
}
}

View File

@ -9,6 +9,7 @@ import TogglePinToStageButton from '../../../../features/video-menu/components/w
// @ts-ignore
import { Avatar } from '../../../base/avatar';
import { IconShareVideo } from '../../../base/icons/svg';
import { isWhiteboardParticipant } from '../../../base/participants/functions';
import { Participant } from '../../../base/participants/types';
import ContextMenu from '../../../base/ui/components/web/ContextMenu';
import ContextMenuItemGroup from '../../../base/ui/components/web/ContextMenuItemGroup';
@ -106,7 +107,7 @@ const FakeParticipantContextMenu = ({
}, [ setWhiteboardOpen ]);
const _getActions = useCallback(() => {
if (participant.isWhiteboard) {
if (isWhiteboardParticipant(participant)) {
return [ {
accessibilityLabel: t('toolbar.hideWhiteboard'),
icon: IconShareVideo,
@ -123,7 +124,7 @@ const FakeParticipantContextMenu = ({
text: t('toolbar.stopSharedVideo')
} ];
}
}, [ localVideoOwner, participant.isWhiteboard ]);
}, [ localVideoOwner, participant.fakeParticipant ]);
return (
<ContextMenu
@ -148,9 +149,11 @@ const FakeParticipantContextMenu = ({
<ContextMenuItemGroup
actions = { _getActions() }>
{participant.isWhiteboard && <TogglePinToStageButton
key = 'pinToStage'
participantID = { WHITEBOARD_ID } />}
{isWhiteboardParticipant(participant) && (
<TogglePinToStageButton
key = 'pinToStage'
participantID = { WHITEBOARD_ID } />
)}
</ContextMenuItemGroup>
</ContextMenu>

View File

@ -250,7 +250,7 @@ class RemoteVideoMenuTriggerButton extends Component<Props> {
thumbnailMenu: true
};
if (_participant?.isFakeParticipant) {
if (_participant?.fakeParticipant) {
return (
<FakeParticipantContextMenu
{ ...props }

View File

@ -13,7 +13,6 @@ import { RESET_WHITEBOARD, SET_WHITEBOARD_OPEN } from './actionTypes';
import { getCollabDetails, getCollabServerUrl, isWhiteboardPresent } from './functions';
import { WHITEBOARD_ID, WHITEBOARD_PARTICIPANT_NAME } from './constants';
import { resetWhiteboard, setWhiteboardOpen, setupWhiteboard } from './actions';
import { getCurrentRoomId } from '../breakout-rooms/functions';
// @ts-ignore
import { addStageParticipant } from '../filmstrip/actions.web';
@ -21,6 +20,8 @@ import { addStageParticipant } from '../filmstrip/actions.web';
// @ts-ignore
import { isStageFilmstripAvailable } from '../filmstrip/functions';
import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
import { FakeParticipant } from '../base/participants/types';
import { getCurrentRoomId } from '../breakout-rooms/functions';
const focusWhiteboard = (store: IStore) => {
const { dispatch, getState } = store;
@ -32,9 +33,8 @@ const focusWhiteboard = (store: IStore) => {
if (!isPresent) {
dispatch(participantJoined({
conference,
fakeParticipant: FakeParticipant.Whiteboard,
id: WHITEBOARD_ID,
isFakeParticipant: true,
isWhiteboard: true,
name: WHITEBOARD_PARTICIPANT_NAME
}));
}
@ -85,11 +85,11 @@ MiddlewareRegistry.register((store: IStore) => (next: Function) => async (action
return;
}
dispatch(participantLeft(WHITEBOARD_ID, conference, { isWhiteboard: true }));
dispatch(participantLeft(WHITEBOARD_ID, conference, { fakeParticipant: FakeParticipant.Whiteboard }));
break;
}
case RESET_WHITEBOARD: {
dispatch(participantLeft(WHITEBOARD_ID, conference, { isWhiteboard: true }));
dispatch(participantLeft(WHITEBOARD_ID, conference, { fakeParticipant: FakeParticipant.Whiteboard }));
break;
}
}