Skip to content

Commit 203af3e

Browse files
[Bugfix] add participant count to participant list and Composite people pane (#2911)
* add strings to component * add participant count to composites * Change files * Duplicate change files for beta release * build API files * update stable api * Update packages/react-composites CallWithChatComposite browser test snapshots * update title creation * fix cc * add test for large participant count * Update embed html bundle snapshots * Update packages/react-composites ChatComposite browser test snapshots * remove test.only * create large participant count test * fix lint * Update packages/react-composites CallWithChatComposite browser test snapshots * Update embed html bundle snapshots * Update packages/react-composites CallComposite browser test snapshots * fix test participant counts * fix lint * Update packages/react-composites CallWithChatComposite browser test snapshots * Update packages/react-composites CallComposite browser test snapshots * hide counter if count undefined * remove async useEffect * fix lint * fix API files * build API files * Update packages/react-composites CallWithChatComposite browser test snapshots * Update packages/react-composites ChatComposite browser test snapshots * Update embed html bundle snapshots * Update packages/react-composites CallComposite browser test snapshots * fix stable API * fix comments * fix bad name * fix missing docs * update string behavior for subtitle * Update packages/react-composites CallWithChatComposite browser test snapshots --------- Signed-off-by: Donald McEachern <94866715+dmceachernmsft@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 56d459f commit 203af3e

120 files changed

Lines changed: 237 additions & 53 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Introduce total participant counts to participant list and people pane in composites",
4+
"packageName": "@azure/communication-react",
5+
"email": "94866715+dmceachernmsft@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "prerelease",
3+
"comment": "Introduce total participant counts to participant list and people pane in composites",
4+
"packageName": "@azure/communication-react",
5+
"email": "94866715+dmceachernmsft@users.noreply.github.com",
6+
"dependentChangeType": "patch"
7+
}

packages/calling-component-bindings/review/beta/calling-component-bindings.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ export const microphoneButtonSelector: MicrophoneButtonSelector;
271271
export type ParticipantListSelector = (state: CallClientState, props: CallingBaseSelectorProps) => {
272272
participants: CallParticipantListParticipant[];
273273
myUserId: string;
274+
totalParticipantCount?: number;
274275
};
275276

276277
// @public

packages/calling-component-bindings/review/stable/calling-component-bindings.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ export const microphoneButtonSelector: MicrophoneButtonSelector;
196196
export type ParticipantListSelector = (state: CallClientState, props: CallingBaseSelectorProps) => {
197197
participants: CallParticipantListParticipant[];
198198
myUserId: string;
199+
totalParticipantCount?: number;
199200
};
200201

201202
// @public

packages/calling-component-bindings/src/participantListSelector.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { memoizedConvertAllremoteParticipants } from './utils/participantListSel
1717
/* @conditional-compile-remove(rooms) */
1818
import { memoizedConvertAllremoteParticipantsBeta } from './utils/participantListSelectorUtils';
1919
import { toFlatCommunicationIdentifier } from '@internal/acs-ui-common';
20+
import { getParticipantCount } from './baseSelectors';
2021
import { isPhoneNumberIdentifier } from '@azure/communication-common';
2122
/* @conditional-compile-remove(communication-common-beta-v3) */
2223
import { isMicrosoftBotIdentifier } from '@azure/communication-common';
@@ -92,6 +93,7 @@ export type ParticipantListSelector = (
9293
) => {
9394
participants: CallParticipantListParticipant[];
9495
myUserId: string;
96+
totalParticipantCount?: number;
9597
};
9698

9799
/**
@@ -100,16 +102,18 @@ export type ParticipantListSelector = (
100102
* @public
101103
*/
102104
export const participantListSelector: ParticipantListSelector = createSelector(
103-
[getIdentifier, getDisplayName, getRemoteParticipants, getIsScreenSharingOn, getIsMuted],
105+
[getIdentifier, getDisplayName, getRemoteParticipants, getIsScreenSharingOn, getIsMuted, getParticipantCount],
104106
(
105107
userId,
106108
displayName,
107109
remoteParticipants,
108110
isScreenSharingOn,
109-
isMuted
111+
isMuted,
112+
partitipantCount
110113
): {
111114
participants: CallParticipantListParticipant[];
112115
myUserId: string;
116+
totalParticipantCount?: number;
113117
} => {
114118
const participants = remoteParticipants
115119
? convertRemoteParticipantsToParticipantListParticipants(
@@ -125,9 +129,13 @@ export const participantListSelector: ParticipantListSelector = createSelector(
125129
// Local participant can never remove themselves.
126130
isRemovable: false
127131
});
132+
/* @conditional-compile-remove(total-participant-count) */
133+
const totalParticipantCount = partitipantCount;
128134
return {
129135
participants: participants,
130-
myUserId: userId
136+
myUserId: userId,
137+
/* @conditional-compile-remove(total-participant-count) */
138+
totalParticipantCount: totalParticipantCount
131139
};
132140
}
133141
);

packages/communication-react/review/beta/communication-react.api.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,7 @@ export interface ComponentStrings {
18611861
MicrophoneSitePermissionsDeniedSafari: SitePermissionsStrings;
18621862
MicrophoneSitePermissionsRequest: SitePermissionsStrings;
18631863
participantItem: ParticipantItemStrings;
1864+
ParticipantList: ParticipantListStrings;
18641865
participantsButton: ParticipantsButtonStrings;
18651866
screenShareButton: ScreenShareButtonStrings;
18661867
sendBox: SendBoxStrings;
@@ -3196,15 +3197,23 @@ export type ParticipantListProps = {
31963197
onParticipantClick?: (participant?: ParticipantListParticipant) => void;
31973198
styles?: ParticipantListStyles;
31983199
showParticipantOverflowTooltip?: boolean;
3200+
totalParticipantCount?: number;
3201+
strings?: ParticipantListStrings;
31993202
participantAriaLabelledBy?: string;
32003203
};
32013204

32023205
// @public
32033206
export type ParticipantListSelector = (state: CallClientState, props: CallingBaseSelectorProps) => {
32043207
participants: CallParticipantListParticipant[];
32053208
myUserId: string;
3209+
totalParticipantCount?: number;
32063210
};
32073211

3212+
// @beta
3213+
export interface ParticipantListStrings {
3214+
overflowParticipantCount?: string;
3215+
}
3216+
32083217
// @public
32093218
export interface ParticipantListStyles extends BaseCustomStyles {
32103219
participantItemStyles?: ParticipantListItemStyles;

packages/communication-react/review/stable/communication-react.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2216,6 +2216,7 @@ export type ParticipantListProps = {
22162216
export type ParticipantListSelector = (state: CallClientState, props: CallingBaseSelectorProps) => {
22172217
participants: CallParticipantListParticipant[];
22182218
myUserId: string;
2219+
totalParticipantCount?: number;
22192220
};
22202221

22212222
// @public

packages/communication-react/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ export type {
151151
MicrophoneSitePermissionsProps
152152
} from '../../react-components/src';
153153

154+
/* @conditional-compile-remove(total-participant-count) */
155+
export type { ParticipantListStrings } from '../../react-components/src';
156+
154157
/* @conditional-compile-remove(mention) */
155158
export type {
156159
MentionOptions,

packages/react-components/review/beta/react-components.api.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ export interface ComponentStrings {
618618
MicrophoneSitePermissionsDeniedSafari: SitePermissionsStrings;
619619
MicrophoneSitePermissionsRequest: SitePermissionsStrings;
620620
participantItem: ParticipantItemStrings;
621+
ParticipantList: ParticipantListStrings;
621622
participantsButton: ParticipantsButtonStrings;
622623
screenShareButton: ScreenShareButtonStrings;
623624
sendBox: SendBoxStrings;
@@ -1618,9 +1619,16 @@ export type ParticipantListProps = {
16181619
onParticipantClick?: (participant?: ParticipantListParticipant) => void;
16191620
styles?: ParticipantListStyles;
16201621
showParticipantOverflowTooltip?: boolean;
1622+
totalParticipantCount?: number;
1623+
strings?: ParticipantListStrings;
16211624
participantAriaLabelledBy?: string;
16221625
};
16231626

1627+
// @beta
1628+
export interface ParticipantListStrings {
1629+
overflowParticipantCount?: string;
1630+
}
1631+
16241632
// @public
16251633
export interface ParticipantListStyles extends BaseCustomStyles {
16261634
participantItemStyles?: ParticipantListItemStyles;

packages/react-components/src/components/ParticipantList.tsx

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
PersonaPresence,
1111
Stack
1212
} from '@fluentui/react';
13+
/* @conditional-compile-remove(total-participant-count) */
14+
import { Text } from '@fluentui/react';
1315
import React, { useCallback, useMemo } from 'react';
1416
import { useIdentifiers } from '../identifiers';
1517
import { useLocale } from '../localization';
@@ -23,6 +25,7 @@ import {
2325
} from '../types';
2426
import { ParticipantItem, ParticipantItemStrings, ParticipantItemStyles } from './ParticipantItem';
2527
import { iconStyles, participantListItemStyle, participantListStyle } from './styles/ParticipantList.styles';
28+
import { _formatString } from '@internal/acs-ui-common';
2629

2730
/**
2831
* Styles for the {@link ParticipantList} {@link ParticipantItem}.
@@ -44,6 +47,19 @@ export interface ParticipantListStyles extends BaseCustomStyles {
4447
participantItemStyles?: ParticipantListItemStyles;
4548
}
4649

50+
/* @conditional-compile-remove(total-participant-count) */
51+
/**
52+
* Strings for the {@link ParticipantList}.
53+
*
54+
* @beta
55+
*/
56+
export interface ParticipantListStrings {
57+
/**
58+
* String for rendering the count of participants not contained in the displayed participant list
59+
*/
60+
overflowParticipantCount?: string;
61+
}
62+
4763
/**
4864
* A callback for providing custom menu items for each participant in {@link ParticipantList}.
4965
*
@@ -85,6 +101,12 @@ export type ParticipantListProps = {
85101
styles?: ParticipantListStyles;
86102
/** Optional value to determine if the tooltip should be shown for participants or not */
87103
showParticipantOverflowTooltip?: boolean;
104+
/* @conditional-compile-remove(total-participant-count) */
105+
/** Total number of people in the call. This number can be larger than the remote participant count. */
106+
totalParticipantCount?: number;
107+
/* @conditional-compile-remove(total-participant-count) */
108+
/** Strings for the participant list */
109+
strings?: ParticipantListStrings;
88110
/** Optional aria-lablledby prop that prefixes each ParticipantItem aria-label */
89111
participantAriaLabelledBy?: string;
90112
};
@@ -190,11 +212,17 @@ export const ParticipantList = (props: ParticipantListProps): JSX.Element => {
190212
onRenderParticipant,
191213
onFetchParticipantMenuItems,
192214
showParticipantOverflowTooltip,
215+
/* @conditional-compile-remove(total-participant-count) */
216+
totalParticipantCount,
217+
/* @conditional-compile-remove(total-participant-count) */
218+
strings,
193219
participantAriaLabelledBy
194220
} = props;
195221

196222
const ids = useIdentifiers();
197-
const strings = useLocale().strings.participantItem;
223+
const participantItemStrings = useLocale().strings.participantItem;
224+
/* @conditional-compile-remove(total-participant-count) */
225+
const participantListStrings = useLocale().strings.ParticipantList;
198226

199227
const displayedParticipants: ParticipantListParticipant[] = useMemo(() => {
200228
return onRenderParticipant ? participants : getParticipantsForDefaultRender(participants, excludeMe, myUserId);
@@ -209,7 +237,7 @@ export const ParticipantList = (props: ParticipantListProps): JSX.Element => {
209237
if (participant.userId !== myUserId && onRemoveParticipant && participantIsRemovable) {
210238
menuItems.push({
211239
key: 'remove',
212-
text: strings.removeButtonLabel,
240+
text: participantItemStrings.removeButtonLabel,
213241
onClick: () => onRemoveParticipant(participant.userId),
214242
itemProps: {
215243
styles: props.styles?.participantItemStyles?.participantSubMenuItemsStyles
@@ -230,22 +258,27 @@ export const ParticipantList = (props: ParticipantListProps): JSX.Element => {
230258
onFetchParticipantMenuItems,
231259
onRemoveParticipant,
232260
props.styles?.participantItemStyles?.participantSubMenuItemsStyles,
233-
strings.removeButtonLabel
261+
participantItemStrings.removeButtonLabel
234262
]
235263
);
236264

237265
const participantItemStyles = useMemo(
238266
() => merge(participantListItemStyle, props.styles?.participantItemStyles),
239267
[props.styles?.participantItemStyles]
240268
);
269+
270+
/* @conditional-compile-remove(total-participant-count) */
271+
const overflowParticipantCountString =
272+
strings?.overflowParticipantCount ?? participantListStrings?.overflowParticipantCount;
273+
241274
return (
242275
<Stack data-ui-id={ids.participantList} className={mergeStyles(participantListStyle, props.styles?.root)}>
243276
{displayedParticipants.map((participant: ParticipantListParticipant) =>
244277
onRenderParticipant
245278
? onRenderParticipant(participant)
246279
: onRenderParticipantDefault(
247280
participant,
248-
strings,
281+
participantItemStrings,
249282
myUserId,
250283
onRenderAvatar,
251284
createParticipantMenuItems,
@@ -255,6 +288,17 @@ export const ParticipantList = (props: ParticipantListProps): JSX.Element => {
255288
participantAriaLabelledBy
256289
)
257290
)}
291+
{
292+
/* @conditional-compile-remove(total-participant-count) */ overflowParticipantCountString &&
293+
totalParticipantCount &&
294+
totalParticipantCount > displayedParticipants.length && (
295+
<Text style={{ fontWeight: 400, margin: '0.5rem' }}>
296+
{_formatString(overflowParticipantCountString, {
297+
overflowCount: `${totalParticipantCount - displayedParticipants.length}`
298+
})}
299+
</Text>
300+
)
301+
}
258302
</Stack>
259303
);
260304
};

0 commit comments

Comments
 (0)