From 2ab9427c0943036c70b923dd5bbfdcaae8011a07 Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Mon, 29 Jun 2026 23:21:14 -0400 Subject: [PATCH] lotus(#4): pin camera into spotlight during screenshare (A5) Review found the manual pin only chose among cameras when no screenshare was active; during a screenshare the screenshare won the spotlight and the pinned camera was demoted to an ignored PiP. Apply the override at the spotlightAndPip$ level: when a pin is explicitly set, surface that camera in the spotlight alongside the shared screen. No manual pin = unchanged. Note: a pin persists if the pinned user briefly leaves and rejoins; the host clears it via focus_participant{userId:null} (by design). Co-Authored-By: Claude Opus 4.8 --- src/state/CallViewModel/CallViewModel.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index d9cc9245..a1290061 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -1011,7 +1011,22 @@ export function createCallViewModel$( return screenShares$.pipe( switchMap((screenShares) => { if (screenShares.length > 0) - return of({ spotlight: screenShares, pip$: spotlightSpeaker$ }); + // [lotus #4/A5] During a screenshare, if the host has explicitly + // pinned a participant, surface that camera in the spotlight + // alongside the shared screen (the whole point of "focus camera + // during screenshare"). With no manual pin this is unchanged: + // the screenshare alone is spotlighted. + return combineLatest([manualSpotlightUserId$, userMedia$]).pipe( + map(([manualUserId, mediaItems]) => { + const pinned = + manualUserId !== null + ? mediaItems.find((m) => m.userId === manualUserId) + : undefined; + return pinned + ? { spotlight: [...screenShares, pinned], pip$: of(undefined) } + : { spotlight: screenShares, pip$: spotlightSpeaker$ }; + }), + ); return spotlightSpeaker$.pipe( map((speaker) => ({