mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-28 11:16:58 +00:00
♻️(frontend) share a PiP-aware element size hook
Reuse a single ResizeObserver hook in the PiP control bar.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { styled } from '@/styled-system/jsx'
|
import { styled } from '@/styled-system/jsx'
|
||||||
import { useRef, useMemo, useState, useEffect, useCallback } from 'react'
|
import { useRef, useMemo } from 'react'
|
||||||
import { AudioDevicesControl } from '@/features/rooms/livekit/components/controls/Device/AudioDevicesControl'
|
import { AudioDevicesControl } from '@/features/rooms/livekit/components/controls/Device/AudioDevicesControl'
|
||||||
import { VideoDeviceControl } from '@/features/rooms/livekit/components/controls/Device/VideoDeviceControl'
|
import { VideoDeviceControl } from '@/features/rooms/livekit/components/controls/Device/VideoDeviceControl'
|
||||||
import { ScreenShareToggle } from '@/features/rooms/livekit/components/controls/ScreenShareToggle'
|
import { ScreenShareToggle } from '@/features/rooms/livekit/components/controls/ScreenShareToggle'
|
||||||
@@ -7,6 +7,7 @@ import { LeaveButton } from '@/features/rooms/livekit/components/controls/LeaveB
|
|||||||
import { SubtitlesToggle } from '@/features/rooms/livekit/components/controls/SubtitlesToggle'
|
import { SubtitlesToggle } from '@/features/rooms/livekit/components/controls/SubtitlesToggle'
|
||||||
import { HandToggle } from '@/features/rooms/livekit/components/controls/HandToggle'
|
import { HandToggle } from '@/features/rooms/livekit/components/controls/HandToggle'
|
||||||
import { StartMediaButton } from '@/features/rooms/livekit/components/controls/StartMediaButton'
|
import { StartMediaButton } from '@/features/rooms/livekit/components/controls/StartMediaButton'
|
||||||
|
import { usePipElementSize } from '../hooks/usePipElementSize'
|
||||||
import { PipOptionsMenu } from './controls/PipOptionsMenu'
|
import { PipOptionsMenu } from './controls/PipOptionsMenu'
|
||||||
import { PipReactionsToggle } from './PipReactionsToggle'
|
import { PipReactionsToggle } from './PipReactionsToggle'
|
||||||
|
|
||||||
@@ -46,43 +47,13 @@ function getHiddenControls(
|
|||||||
return hidden
|
return hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ResizeObserver that works inside the PiP document context
|
|
||||||
* (the global singleton from the main window cannot observe PiP elements).
|
|
||||||
*/
|
|
||||||
function usePipSize(ref: React.RefObject<HTMLElement | null>) {
|
|
||||||
const [width, setWidth] = useState(0)
|
|
||||||
|
|
||||||
const measure = useCallback(() => {
|
|
||||||
if (ref.current) setWidth(ref.current.getBoundingClientRect().width)
|
|
||||||
}, [ref])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const el = ref.current
|
|
||||||
if (!el) return
|
|
||||||
|
|
||||||
measure()
|
|
||||||
|
|
||||||
const RO =
|
|
||||||
el.ownerDocument.defaultView?.ResizeObserver ?? window.ResizeObserver
|
|
||||||
const observer = new RO((entries) => {
|
|
||||||
const entry = entries[0]
|
|
||||||
if (entry) setWidth(entry.contentRect.width)
|
|
||||||
})
|
|
||||||
observer.observe(el)
|
|
||||||
return () => observer.disconnect()
|
|
||||||
}, [ref, measure])
|
|
||||||
|
|
||||||
return width
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PipControlBar = ({
|
export const PipControlBar = ({
|
||||||
showScreenShare,
|
showScreenShare,
|
||||||
}: {
|
}: {
|
||||||
showScreenShare: boolean
|
showScreenShare: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
const width = usePipSize(containerRef)
|
const { width } = usePipElementSize(containerRef)
|
||||||
|
|
||||||
const hidden = useMemo(
|
const hidden = useMemo(
|
||||||
() => getHiddenControls(width, showScreenShare),
|
() => getHiddenControls(width, showScreenShare),
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { useCallback, useEffect, useState, type RefObject } from 'react'
|
||||||
|
|
||||||
|
type Size = { width: number; height: number }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observes an element's size, even when mounted in the PiP document.
|
||||||
|
* Resolves `ResizeObserver` from the element's own window.
|
||||||
|
*/
|
||||||
|
export const usePipElementSize = <T extends HTMLElement>(
|
||||||
|
ref: RefObject<T | null>
|
||||||
|
): Size => {
|
||||||
|
const [size, setSize] = useState<Size>({ width: 0, height: 0 })
|
||||||
|
|
||||||
|
const measure = useCallback(() => {
|
||||||
|
const el = ref.current
|
||||||
|
if (!el) return
|
||||||
|
const rect = el.getBoundingClientRect()
|
||||||
|
setSize({ width: rect.width, height: rect.height })
|
||||||
|
}, [ref])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const el = ref.current
|
||||||
|
if (!el) return
|
||||||
|
|
||||||
|
measure()
|
||||||
|
|
||||||
|
const RO =
|
||||||
|
el.ownerDocument.defaultView?.ResizeObserver ?? window.ResizeObserver
|
||||||
|
if (!RO) return
|
||||||
|
|
||||||
|
const observer = new RO((entries) => {
|
||||||
|
const entry = entries[0]
|
||||||
|
if (!entry) return
|
||||||
|
const { width, height } = entry.contentRect
|
||||||
|
setSize({ width, height })
|
||||||
|
})
|
||||||
|
observer.observe(el)
|
||||||
|
return () => observer.disconnect()
|
||||||
|
}, [ref, measure])
|
||||||
|
|
||||||
|
return size
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user