From f5dd57a2e949f847d1bf51f6a89dccce06368606 Mon Sep 17 00:00:00 2001 From: Cyril Date: Mon, 20 Jul 2026 13:42:23 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20apply=20OneToOneFocusLayo?= =?UTF-8?q?ut=20to=20main=20room=201-to-1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show remote fullscreen with local thumbnail when no pin. --- .gitignore | 1 + CHANGELOG.md | 4 +++ .../layout/components/OneToOneFocusLayout.tsx | 2 +- .../layout/components/StageLayout.tsx | 33 +++++++++++++++++-- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4f5dbf29..608168fe 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ db.sqlite3 # IDEs .idea/ .vscode/ +.cursor/ *.iml .devcontainer diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ff7947b..2e5bb3d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to ## [Unreleased] +### Added + +- ✨(frontend) share OneToOneFocusLayout between PiP and main room + ### Changed - 📱(frontend) collapse mobile control bar items on narrow viewports diff --git a/src/frontend/src/features/layout/components/OneToOneFocusLayout.tsx b/src/frontend/src/features/layout/components/OneToOneFocusLayout.tsx index 0541bad4..7cb9ed96 100644 --- a/src/frontend/src/features/layout/components/OneToOneFocusLayout.tsx +++ b/src/frontend/src/features/layout/components/OneToOneFocusLayout.tsx @@ -2,7 +2,7 @@ import { memo } from 'react' import type { TrackReferenceOrPlaceholder } from '@livekit/components-core' import { styled } from '@/styled-system/jsx' import { cva } from '@/styled-system/css' -import { ParticipantTile } from '@/features/rooms/livekit/components/ParticipantTile' +import { ParticipantTile } from '@/features/participantTile/components/ParticipantTile' import { getTrackKey } from '@/features/layout/utils/trackSelection' type OneToOneFocusLayoutProps = { diff --git a/src/frontend/src/features/layout/components/StageLayout.tsx b/src/frontend/src/features/layout/components/StageLayout.tsx index d4fc8e05..d859a5ff 100644 --- a/src/frontend/src/features/layout/components/StageLayout.tsx +++ b/src/frontend/src/features/layout/components/StageLayout.tsx @@ -12,7 +12,8 @@ import { import { Track } from 'livekit-client' import { useSnapshot } from 'valtio' import { clearPinnedTrack, layoutStore, setPinnedTrack } from '@/stores/layout' -import { useEffect, useRef } from 'react' +import { useEffect, useMemo, useRef } from 'react' +import { OneToOneFocusLayout } from '@/features/layout/components/OneToOneFocusLayout' export const StageLayout = () => { const lastAutoFocusedScreenShareTrack = @@ -36,6 +37,29 @@ export const StageLayout = () => { (track) => !isEqualTrackRef(track, pinnedTrackRef) ) + const cameraTracks = useMemo( + () => tracks.filter((t) => t.source === Track.Source.Camera), + [tracks] + ) + + const isOneToOne = + !pinnedTrackRef && + screenShareTracks.length === 0 && + cameraTracks.length <= 2 + + const oneToOneMainTrack = useMemo(() => { + if (!isOneToOne) return undefined + const remote = cameraTracks.find((t) => !t.participant?.isLocal) + const local = cameraTracks.find((t) => t.participant?.isLocal) + return remote ?? local + }, [isOneToOne, cameraTracks]) + + const oneToOneThumbnailTrack = useMemo(() => { + if (!isOneToOne) return undefined + const local = cameraTracks.find((t) => t.participant?.isLocal) + return oneToOneMainTrack === local ? undefined : local + }, [isOneToOne, cameraTracks, oneToOneMainTrack]) + /* eslint-disable react-hooks/exhaustive-deps */ // Code duplicated from LiveKit; this warning will be addressed in the refactoring. useEffect(() => { @@ -87,7 +111,12 @@ export const StageLayout = () => { return ( <> - {!pinnedTrackRef ? ( + {isOneToOne ? ( + + ) : !pinnedTrackRef ? (