communication-react-19
Version:
React library for building modern communication user experiences utilizing Azure Communication Services (React 19 compatible fork)
115 lines • 6.45 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { createSelector } from 'reselect';
import { getIdentifier, getDisplayName, getIsScreenSharingOn, getIsMuted, getCapabilities } from './baseSelectors';
import { getRole } from './baseSelectors';
import { isHideAttendeeNamesEnabled } from './baseSelectors';
import { _convertParticipantState, _updateUserDisplayNames } from './utils/callUtils';
import { memoizedConvertAllremoteParticipants } from './utils/participantListSelectorUtils';
import { memoizedConvertToVideoTileReaction, memoizedSpotlight } from './utils/participantListSelectorUtils';
import { getLocalParticipantRaisedHand } from './baseSelectors';
import { getLocalParticipantReactionState } from './baseSelectors';
import { getSpotlightCallFeature } from './baseSelectors';
import { toFlatCommunicationIdentifier } from "../../acs-ui-common/src";
import { getParticipantCount } from './baseSelectors';
import { isMicrosoftTeamsAppIdentifier, isPhoneNumberIdentifier } from '@azure/communication-common';
import { maskDisplayNameWithRole } from './utils/callUtils';
import { getRemoteParticipantsExcludingConsumers } from './getRemoteParticipantsExcludingConsumers';
const convertRemoteParticipantsToParticipantListParticipants = (remoteParticipants, localUserCanRemoveOthers, isHideAttendeeNamesEnabled, localUserRole, spotlightedParticipants) => {
const conversionCallback = (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
memoizeFn) => {
return (remoteParticipants
// Filter out MicrosoftBot participants
.filter((participant) => {
return !isMicrosoftTeamsAppIdentifier(participant.identifier);
})
/**
* hiding participants who are inLobby, idle, or connecting in ACS clients till we can admit users through ACS clients.
* phone users will be in the connecting state until they are connected to the call.
*/
.filter((participant) => {
return (!['InLobby', 'Idle', 'Connecting', 'Disconnected'].includes(participant.state) ||
isPhoneNumberIdentifier(participant.identifier));
})
.map((participant) => {
const isScreenSharing = Object.values(participant.videoStreams).some((videoStream) => videoStream.mediaStreamType === 'ScreenSharing' && videoStream.isAvailable);
/**
* We want to check the participant to see if they are a PSTN participant joining the call
* and mapping their state to be 'Ringing'
*/
const state = _convertParticipantState(participant);
const displayName = maskDisplayNameWithRole(participant.displayName, localUserRole, participant.role, isHideAttendeeNamesEnabled);
const remoteParticipantReaction = memoizedConvertToVideoTileReaction(participant.reactionState);
const spotlight = memoizedSpotlight(spotlightedParticipants, toFlatCommunicationIdentifier(participant.identifier));
return memoizeFn(toFlatCommunicationIdentifier(participant.identifier), displayName, state, participant.isMuted, isScreenSharing, participant.isSpeaking, participant.raisedHand, localUserCanRemoveOthers, remoteParticipantReaction, spotlight, participant.mediaAccess);
})
.sort((a, b) => {
var _a, _b;
const nameA = ((_a = a.displayName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
const nameB = ((_b = b.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()) || '';
if (nameA < nameB) {
return -1;
}
else if (nameA > nameB) {
return 1;
}
else {
return 0;
}
}));
};
return memoizedConvertAllremoteParticipants(conversionCallback);
};
/**
* Selects data that drives {@link ParticipantList} component.
*
* @public
*/
export const participantListSelector = createSelector([
getIdentifier,
getDisplayName,
getRemoteParticipantsExcludingConsumers,
getIsScreenSharingOn,
getIsMuted,
getLocalParticipantRaisedHand,
getRole,
getParticipantCount,
isHideAttendeeNamesEnabled,
getLocalParticipantReactionState,
getSpotlightCallFeature,
getCapabilities
], (userId, displayName, remoteParticipants, isScreenSharingOn, isMuted, raisedHand, role, partitipantCount, isHideAttendeeNamesEnabled, localParticipantReactionState, spotlightCallFeature, capabilities) => {
const localUserCanRemoveOthers = localUserCanRemoveOthersTrampoline(role);
const participants = remoteParticipants
? convertRemoteParticipantsToParticipantListParticipants(_updateUserDisplayNames(Object.values(remoteParticipants)), localUserCanRemoveOthers, isHideAttendeeNamesEnabled, role, spotlightCallFeature === null || spotlightCallFeature === void 0 ? void 0 : spotlightCallFeature.spotlightedParticipants)
: [];
participants.push({
userId: userId,
displayName: displayName,
isScreenSharing: isScreenSharingOn,
isMuted: isMuted,
raisedHand: raisedHand,
state: 'Connected',
// Local participant can never remove themselves.
isRemovable: false,
reaction: memoizedConvertToVideoTileReaction(localParticipantReactionState),
spotlight: memoizedSpotlight(spotlightCallFeature === null || spotlightCallFeature === void 0 ? void 0 : spotlightCallFeature.spotlightedParticipants, userId),
mediaAccess: {
isAudioPermitted: (capabilities === null || capabilities === void 0 ? void 0 : capabilities.unmuteMic) ? capabilities.unmuteMic.isPresent : true,
isVideoPermitted: (capabilities === null || capabilities === void 0 ? void 0 : capabilities.turnVideoOn) ? capabilities.turnVideoOn.isPresent : true
}
});
/* @conditional-compile-remove(total-participant-count) */
const totalParticipantCount = partitipantCount;
return {
participants: participants,
myUserId: userId,
/* @conditional-compile-remove(total-participant-count) */
totalParticipantCount: totalParticipantCount
};
});
const localUserCanRemoveOthersTrampoline = (role) => {
return role === 'Presenter' || role === 'Unknown' || role === undefined;
};
//# sourceMappingURL=participantListSelector.js.map