Skip to content

Commit c1744c5

Browse files
authored
Retain pinned participants after holding call (#4319)
* Retain pinned participants after holding call in CallComposite and CallWithChatComposite * Change files * Duplicate change files for beta release * remove unused import * fix cc
1 parent 1165f51 commit c1744c5

5 files changed

Lines changed: 61 additions & 3 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "patch",
3+
"area": "fix",
4+
"workstream": "Pinned participants",
5+
"comment": "Retain pinned participants after holding call in CallComposite and CallWithChatComposite",
6+
"packageName": "@azure/communication-react",
7+
"email": "79475487+mgamis-msft@users.noreply.github.com",
8+
"dependentChangeType": "patch"
9+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"type": "patch",
3+
"area": "fix",
4+
"workstream": "Pinned participants",
5+
"comment": "Retain pinned participants after holding call in CallComposite and CallWithChatComposite",
6+
"packageName": "@azure/communication-react",
7+
"email": "79475487+mgamis-msft@users.noreply.github.com",
8+
"dependentChangeType": "patch"
9+
}

packages/react-composites/src/composites/CallComposite/CallComposite.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ const MainScreen = (props: MainScreenProps): JSX.Element => {
430430
const alternateCallerId = adapter.getState().alternateCallerId;
431431
const leavePageStyle = useMemo(() => leavingPageStyle(palette), [palette]);
432432
let pageElement: JSX.Element | undefined;
433+
const [pinnedParticipants, setPinnedParticipants] = useState<string[]>([]);
433434
switch (page) {
434435
case 'configuration':
435436
pageElement = (
@@ -590,6 +591,8 @@ const MainScreen = (props: MainScreenProps): JSX.Element => {
590591
userSetOverflowGalleryPosition={userSetOverflowGalleryPosition}
591592
/* @conditional-compile-remove(capabilities) */
592593
capabilitiesChangedNotificationBarProps={capabilitiesChangedNotificationBarProps}
594+
pinnedParticipants={pinnedParticipants}
595+
setPinnedParticipants={setPinnedParticipants}
593596
/>
594597
);
595598
break;

packages/react-composites/src/composites/CallComposite/components/MediaGallery.tsx

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export interface MediaGalleryProps {
6161
localVideoTileOptions?: boolean | LocalVideoTileOptions;
6262
userSetOverflowGalleryPosition?: 'Responsive' | 'horizontalTop';
6363
userSetGalleryLayout: VideoGalleryLayout;
64+
pinnedParticipants?: string[];
65+
setPinnedParticipants?: (pinnedParticipants: string[]) => void;
6466
/* @conditional-compile-remove(spotlight) */
6567
setIsPromptOpen: (isOpen: boolean) => void;
6668
/* @conditional-compile-remove(spotlight) */
@@ -73,8 +75,13 @@ export interface MediaGalleryProps {
7375
* @private
7476
*/
7577
export const MediaGallery = (props: MediaGalleryProps): JSX.Element => {
76-
/* @conditional-compile-remove(spotlight) */
77-
const { setIsPromptOpen, setPromptProps, hideSpotlightButtons } = props;
78+
const {
79+
pinnedParticipants = [],
80+
setPinnedParticipants,
81+
/* @conditional-compile-remove(spotlight) */ setIsPromptOpen,
82+
/* @conditional-compile-remove(spotlight) */ setPromptProps,
83+
/* @conditional-compile-remove(spotlight) */ hideSpotlightButtons
84+
} = props;
7885

7986
const videoGalleryProps = usePropsFor(VideoGallery);
8087
const cameraSwitcherCameras = useSelector(localVideoCameraCycleButtonSelector);
@@ -159,6 +166,24 @@ export const MediaGallery = (props: MediaGalleryProps): JSX.Element => {
159166
setPromptProps
160167
);
161168

169+
const onPinParticipant = useMemo(() => {
170+
return setPinnedParticipants
171+
? (userId: string) => {
172+
if (!pinnedParticipants.includes(userId)) {
173+
setPinnedParticipants(pinnedParticipants.concat(userId));
174+
}
175+
}
176+
: undefined;
177+
}, [setPinnedParticipants, pinnedParticipants]);
178+
179+
const onUnpinParticipant = useMemo(() => {
180+
return setPinnedParticipants
181+
? (userId: string) => {
182+
setPinnedParticipants(pinnedParticipants.filter((participantId) => participantId !== userId));
183+
}
184+
: undefined;
185+
}, [setPinnedParticipants, pinnedParticipants]);
186+
162187
const VideoGalleryMemoized = useMemo(() => {
163188
const layoutBasedOnUserSelection = (): VideoGalleryLayout => {
164189
return props.localVideoTileOptions ? layoutBasedOnTilePosition : props.userSetGalleryLayout;
@@ -184,6 +209,9 @@ export const MediaGallery = (props: MediaGalleryProps): JSX.Element => {
184209
? '9:16'
185210
: '16:9'
186211
}
212+
pinnedParticipants={pinnedParticipants}
213+
onPinParticipant={onPinParticipant}
214+
onUnpinParticipant={onUnpinParticipant}
187215
/* @conditional-compile-remove(reaction) */
188216
reactionResources={reactionResources}
189217
/* @conditional-compile-remove(spotlight) */
@@ -209,6 +237,9 @@ export const MediaGallery = (props: MediaGalleryProps): JSX.Element => {
209237
containerAspectRatio,
210238

211239
props.userSetGalleryLayout,
240+
pinnedParticipants,
241+
onPinParticipant,
242+
onUnpinParticipant,
212243
layoutBasedOnTilePosition,
213244
/* @conditional-compile-remove(reaction) */
214245
reactionResources,

packages/react-composites/src/composites/CallComposite/pages/CallPage.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export interface CallPageProps {
5555
userSetOverflowGalleryPosition?: 'Responsive' | 'horizontalTop';
5656
onSetUserSetOverflowGalleryPosition?: (position: 'Responsive' | 'horizontalTop') => void;
5757
onCloseChatPane?: () => void;
58+
pinnedParticipants?: string[];
59+
setPinnedParticipants?: (pinnedParticipants: string[]) => void;
5860
}
5961

6062
/**
@@ -71,7 +73,9 @@ export const CallPage = (props: CallPageProps): JSX.Element => {
7173
onUserSetGalleryLayoutChange,
7274
userSetOverflowGalleryPosition = 'Responsive',
7375
onSetUserSetOverflowGalleryPosition,
74-
onCloseChatPane
76+
onCloseChatPane,
77+
pinnedParticipants,
78+
setPinnedParticipants
7579
} = props;
7680

7781
// To use useProps to get these states, we need to create another file wrapping Call,
@@ -129,6 +133,8 @@ export const CallPage = (props: CallPageProps): JSX.Element => {
129133
localVideoTileOptions={options?.localVideoTile}
130134
userSetOverflowGalleryPosition={userSetOverflowGalleryPosition}
131135
userSetGalleryLayout={galleryLayout}
136+
pinnedParticipants={pinnedParticipants}
137+
setPinnedParticipants={setPinnedParticipants}
132138
/* @conditional-compile-remove(spotlight) */
133139
setIsPromptOpen={setIsPromptOpen}
134140
/* @conditional-compile-remove(spotlight) */

0 commit comments

Comments
 (0)