feat(room): кнопка микрофона в мини-окне (PiP)
Document PiP не показывает тулбар комнаты — во время звонка в мини-окне нельзя было замьютить себя, не разворачивая основное окно. Кнопка лежит поверх единственной плитки мини-плеера и использует тот же useTrackToggle, что и тулбар: React-контекст LiveKitRoom не разрывается порталом в pipWindow.document.body, поэтому состояние читается и меняется одинаково что в основном окне, что в мини-плеере.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useState, type ReactNode } from 'react'
|
||||
import { EyeOff, Users } from 'lucide-react'
|
||||
import { EyeOff, Mic, MicOff, Users } from 'lucide-react'
|
||||
import { Track, type Participant } from 'livekit-client'
|
||||
import {
|
||||
CarouselLayout,
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
isTrackReference,
|
||||
useRoomContext,
|
||||
useSpeakingParticipants,
|
||||
useTrackToggle,
|
||||
useTracks,
|
||||
type TrackReferenceOrPlaceholder,
|
||||
} from '@livekit/components-react'
|
||||
@@ -93,6 +94,29 @@ function hasLiveVideo(track: TrackReferenceOrPlaceholder): boolean {
|
||||
return isTrackReference(track) && !track.publication.isMuted
|
||||
}
|
||||
|
||||
/**
|
||||
* Кнопка микрофона поверх единственной плитки мини-плеера (задача A5): в
|
||||
* Document PiP своего тулбара нет вовсе, а звонок продолжается — без неё
|
||||
* замьютить себя можно, только развернув основное окно. `useTrackToggle` —
|
||||
* тот же хук, что и в `RoomToolbar`, читает/меняет состояние ЧЕРЕЗ
|
||||
* `RoomContext`, а не через DOM, поэтому работает одинаково что в основном
|
||||
* окне, что в портале, рендерящем эту сцену внутрь `pipWindow.document.body`
|
||||
* (React-контекст порталом не разрывается, в отличие от DOM-дерева).
|
||||
*/
|
||||
function PipMicToggle() {
|
||||
const mic = useTrackToggle({ source: Track.Source.Microphone })
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
{...mic.buttonProps}
|
||||
className={`room-pip-mic-toggle${mic.enabled ? '' : ' is-off'}`}
|
||||
aria-label={mic.enabled ? 'Выключить микрофон' : 'Включить микрофон'}
|
||||
>
|
||||
{mic.enabled ? <Mic className="lucide" aria-hidden="true" /> : <MicOff className="lucide" aria-hidden="true" />}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Основная сцена конференции: превью остальных участников + крупная плитка
|
||||
* активного спикера (FocusLayoutContainer + CarouselLayout при нескольких
|
||||
@@ -366,6 +390,7 @@ export function RoomStage({
|
||||
return (
|
||||
<section className="stage room-single-tile">
|
||||
{focusTrack && <RoomParticipantTile trackRef={focusTrack} onStopSharing={handleStopSharing} />}
|
||||
<PipMicToggle />
|
||||
<RoomAudioRenderer />
|
||||
</section>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user