Skip to content

Commit 0de3e80

Browse files
authored
Fix screen sharing cannot be removed from focus (livekit#519)
1 parent 4e3f45e commit 0de3e80

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@livekit/components-react": patch
3+
---
4+
5+
Fix autofocus logic in the `VideoConference` component that prevented screen sharing from being removed from focus. Fix `usePinnedTracks` not returning `undefined` state.

packages/react/src/hooks/usePinnedTracks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ export function usePinnedTracks(layoutContext?: LayoutContextType): TrackReferen
1111
return layoutContext.pin.state;
1212
}
1313
return [];
14-
}, [layoutContext]);
14+
}, [layoutContext.pin.state]);
1515
}

packages/react/src/prefabs/VideoConference.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { usePinnedTracks } from '../hooks/usePinnedTracks';
1515
import { CarouselLayout } from '../components/layout/CarouselLayout';
1616
import { useCreateLayoutContext } from '../context/layout-context';
1717
import { ParticipantTile } from '../components';
18+
import type { TrackReferenceOrPlaceholder } from '@livekit/components-core';
1819

1920
/**
2021
* @public
@@ -41,6 +42,7 @@ export interface VideoConferenceProps extends React.HTMLAttributes<HTMLDivElemen
4142
*/
4243
export function VideoConference({ chatMessageFormatter, ...props }: VideoConferenceProps) {
4344
const [widgetState, setWidgetState] = React.useState<WidgetState>({ showChat: false });
45+
const lastAutoFocusedScreenShareTrack = React.useRef<TrackReferenceOrPlaceholder | null>(null);
4446

4547
const tracks = useTracks(
4648
[
@@ -65,18 +67,25 @@ export function VideoConference({ chatMessageFormatter, ...props }: VideoConfere
6567
const carouselTracks = tracks.filter((track) => !isEqualTrackRef(track, focusTrack));
6668

6769
React.useEffect(() => {
68-
// if screen share tracks are published, and no pin is set explicitly, auto set the screen share
69-
if (screenShareTracks.length > 0 && focusTrack === undefined) {
70+
// If screen share tracks are published, and no pin is set explicitly, auto set the screen share.
71+
if (screenShareTracks.length > 0 && lastAutoFocusedScreenShareTrack.current === null) {
72+
log.debug('Auto set screen share focus:', { newScreenShareTrack: screenShareTracks[0] });
7073
layoutContext.pin.dispatch?.({ msg: 'set_pin', trackReference: screenShareTracks[0] });
74+
lastAutoFocusedScreenShareTrack.current = screenShareTracks[0];
7175
} else if (
72-
(screenShareTracks.length === 0 && focusTrack?.source === Track.Source.ScreenShare) ||
73-
tracks.length <= 1
76+
lastAutoFocusedScreenShareTrack.current &&
77+
!screenShareTracks.some(
78+
(track) =>
79+
track.publication.trackSid ===
80+
lastAutoFocusedScreenShareTrack.current?.publication?.trackSid,
81+
)
7482
) {
83+
log.debug('Auto clearing screen share focus.');
7584
layoutContext.pin.dispatch?.({ msg: 'clear_pin' });
85+
lastAutoFocusedScreenShareTrack.current = null;
7686
}
7787
}, [
78-
JSON.stringify(screenShareTracks.map((ref) => ref.publication.trackSid)),
79-
tracks.length,
88+
screenShareTracks.map((ref) => ref.publication.trackSid).join(),
8089
focusTrack?.publication?.trackSid,
8190
]);
8291

0 commit comments

Comments
 (0)