(frontend) apply OneToOneFocusLayout to main room 1-to-1

Show remote fullscreen with local thumbnail when no pin.
This commit is contained in:
Cyril
2026-07-20 13:42:23 +02:00
committed by Ovgodd
parent ff8ddb009f
commit f5dd57a2e9
4 changed files with 37 additions and 3 deletions
+1
View File
@@ -75,6 +75,7 @@ db.sqlite3
# IDEs
.idea/
.vscode/
.cursor/
*.iml
.devcontainer
+4
View File
@@ -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
@@ -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 = {
@@ -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 ? (
<OneToOneFocusLayout
mainTrack={oneToOneMainTrack}
thumbnailTrack={oneToOneThumbnailTrack}
/>
) : !pinnedTrackRef ? (
<div className="lk-grid-layout-wrapper" style={{ height: 'auto' }}>
<GridLayout tracks={tracks} style={{ padding: 0 }}>
<ParticipantTile />