mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-27 18:56:58 +00:00
✨(frontend) apply OneToOneFocusLayout to main room 1-to-1
Show remote fullscreen with local thumbnail when no pin.
This commit is contained in:
@@ -75,6 +75,7 @@ db.sqlite3
|
|||||||
# IDEs
|
# IDEs
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
.cursor/
|
||||||
*.iml
|
*.iml
|
||||||
.devcontainer
|
.devcontainer
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ and this project adheres to
|
|||||||
- ✨(frontend) add participant color gradient when camera is off #1490
|
- ✨(frontend) add participant color gradient when camera is off #1490
|
||||||
- ✨(all) allow forcing SSO display name for authenticated users
|
- ✨(all) allow forcing SSO display name for authenticated users
|
||||||
- ➕(frontend) install vite-plugin-static-copy for MediaPipe WASM assets
|
- ➕(frontend) install vite-plugin-static-copy for MediaPipe WASM assets
|
||||||
|
- ✨(frontend) share OneToOneFocusLayout between PiP and main room
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
log,
|
log,
|
||||||
} from '@livekit/components-core'
|
} from '@livekit/components-core'
|
||||||
import { type Participant, RoomEvent, Track } from 'livekit-client'
|
import { type Participant, RoomEvent, Track } from 'livekit-client'
|
||||||
import React, { useCallback, useRef, useState, useEffect } from 'react'
|
import React, { useCallback, useMemo, useRef, useState, useEffect } from 'react'
|
||||||
import {
|
import {
|
||||||
ConnectionStateToast,
|
ConnectionStateToast,
|
||||||
FocusLayoutContainer,
|
FocusLayoutContainer,
|
||||||
@@ -40,6 +40,7 @@ import { useScreenReaderAnnounce } from '@/hooks/useScreenReaderAnnounce'
|
|||||||
import { ReactionPortals } from '@/features/reactions/components/ReactionPortals'
|
import { ReactionPortals } from '@/features/reactions/components/ReactionPortals'
|
||||||
import { CarouselLayout } from '@/features/layout/components/CarouselLayout'
|
import { CarouselLayout } from '@/features/layout/components/CarouselLayout'
|
||||||
import { GridLayout } from '@/features/layout/components/GridLayout'
|
import { GridLayout } from '@/features/layout/components/GridLayout'
|
||||||
|
import { OneToOneFocusLayout } from '@/features/layout/components/OneToOneFocusLayout'
|
||||||
import { RoomContentArea } from '@/features/layout/components/RoomContentArea'
|
import { RoomContentArea } from '@/features/layout/components/RoomContentArea'
|
||||||
import { usePictureInPicture } from '@/features/pip/hooks/usePictureInPicture'
|
import { usePictureInPicture } from '@/features/pip/hooks/usePictureInPicture'
|
||||||
import { PipRoomPlaceholder } from '@/features/pip/components/PipRoomPlaceholder'
|
import { PipRoomPlaceholder } from '@/features/pip/components/PipRoomPlaceholder'
|
||||||
@@ -123,6 +124,26 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
|
|||||||
(track) => !isEqualTrackRef(track, focusTrack)
|
(track) => !isEqualTrackRef(track, focusTrack)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const cameraTracks = useMemo(
|
||||||
|
() => tracks.filter((t) => t.source === Track.Source.Camera),
|
||||||
|
[tracks]
|
||||||
|
)
|
||||||
|
|
||||||
|
const isOneToOne = !focusTrack && 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])
|
||||||
|
|
||||||
const { isOpen: isPictureInPictureOpen } = usePictureInPicture()
|
const { isOpen: isPictureInPictureOpen } = usePictureInPicture()
|
||||||
|
|
||||||
// handle pin announcements
|
// handle pin announcements
|
||||||
@@ -258,7 +279,12 @@ export function VideoConference({ ...props }: VideoConferenceProps) {
|
|||||||
<PipRoomPlaceholder />
|
<PipRoomPlaceholder />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{!focusTrack ? (
|
{isOneToOne ? (
|
||||||
|
<OneToOneFocusLayout
|
||||||
|
mainTrack={oneToOneMainTrack}
|
||||||
|
thumbnailTrack={oneToOneThumbnailTrack}
|
||||||
|
/>
|
||||||
|
) : !focusTrack ? (
|
||||||
<div
|
<div
|
||||||
className="lk-grid-layout-wrapper"
|
className="lk-grid-layout-wrapper"
|
||||||
style={{ height: 'auto' }}
|
style={{ height: 'auto' }}
|
||||||
|
|||||||
Reference in New Issue
Block a user