fixup! (feat) connect PiP to room and options menu

This commit is contained in:
Cyril
2026-01-23 11:24:19 +01:00
parent 2bdd8ddbaf
commit 99dcd34482
3 changed files with 82 additions and 23 deletions
@@ -36,25 +36,63 @@ const syncThemeAttribute = (source: Document, target: Document) => {
}
}
const cssVarNameCacheByElement = new WeakMap<HTMLElement, string[]>()
const cssVarNameCacheByUri = new Map<string, string[]>()
const syncCssVariables = (source: Document, target: Document) => {
const sourceView = source.defaultView
if (!sourceView) return
const applyVarsFrom = (element: HTMLElement | null) => {
if (!element) return
const styles = sourceView.getComputedStyle(element)
for (let i = 0; i < styles.length; i += 1) {
const property = styles[i]
if (!property.startsWith('--')) continue
const value = styles.getPropertyValue(property)
if (value) {
target.documentElement.style.setProperty(property, value)
const getCachedVarNames = () => {
const docEl = source.documentElement
if (!docEl) return []
const cachedByElement = cssVarNameCacheByElement.get(docEl)
if (cachedByElement) return cachedByElement
const cachedByUri = source.baseURI
? cssVarNameCacheByUri.get(source.baseURI)
: undefined
if (cachedByUri) return cachedByUri
const varNames = new Set<string>()
const collectVarsFrom = (element: HTMLElement | null) => {
if (!element) return
const styles = sourceView.getComputedStyle(element)
for (let i = 0; i < styles.length; i += 1) {
const property = styles[i]
if (property.startsWith('--')) {
varNames.add(property)
}
}
}
collectVarsFrom(source.documentElement)
collectVarsFrom(source.body)
const result = Array.from(varNames)
cssVarNameCacheByElement.set(docEl, result)
if (source.baseURI) {
cssVarNameCacheByUri.set(source.baseURI, result)
}
return result
}
applyVarsFrom(source.documentElement)
applyVarsFrom(source.body)
const varNames = getCachedVarNames()
if (!varNames.length) return
const rootStyles = sourceView.getComputedStyle(source.documentElement)
const bodyStyles = source.body
? sourceView.getComputedStyle(source.body)
: null
varNames.forEach((property) => {
const bodyValue = bodyStyles?.getPropertyValue(property)
const value = bodyValue || rootStyles.getPropertyValue(property)
if (value) {
target.documentElement.style.setProperty(property, value)
}
})
}
/**
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
type DocumentPictureInPicture = {
requestWindow: (options?: {
@@ -19,24 +19,44 @@ export const useDocumentPiP = ({
height?: number
} = {}) => {
const [pipWindow, setPipWindow] = useState<Window | null>(null)
const pipWindowRef = useRef<Window | null>(null)
const pendingPiPRef = useRef<Promise<Window | null> | null>(null)
const isSupported = useMemo(() => {
const [isSupported] = useState(() => {
if (typeof window === 'undefined') return false
return 'documentPictureInPicture' in window
}, [])
})
const openPiP = useCallback(async () => {
if (!isSupported) return null
if (pipWindow && !pipWindow.closed) return pipWindow
const existingWindow = pipWindowRef.current
if (existingWindow && !existingWindow.closed) return existingWindow
if (pendingPiPRef.current) return pendingPiPRef.current
// Request a new PiP window from the browser API.
const pip = (window as WindowWithDocumentPiP).documentPictureInPicture
if (!pip) return null
const win = await pip.requestWindow({ width, height })
setPipWindow(win)
return win
}, [height, isSupported, pipWindow, width])
const requestPromise = (async () => {
try {
const win = await pip.requestWindow({ width, height })
const currentWindow = pipWindowRef.current
if (currentWindow && !currentWindow.closed) return currentWindow
setPipWindow(win)
return win
} catch (error) {
// Avoid unhandled rejections if the user blocks or closes the request.
console.error('Failed to open Picture-in-Picture window', error)
return null
} finally {
pendingPiPRef.current = null
}
})()
pendingPiPRef.current = requestPromise
return requestPromise
}, [height, isSupported, width])
const closePiP = useCallback(() => {
if (!pipWindow) return
@@ -46,6 +66,10 @@ export const useDocumentPiP = ({
setPipWindow(null)
}, [pipWindow])
useEffect(() => {
pipWindowRef.current = pipWindow
}, [pipWindow])
useEffect(() => {
if (!pipWindow) return
@@ -17,8 +17,5 @@ export const useOverlayPortalContainer = () => {
*/
export const useOverlayBoundaryElement = () => {
const portalContainer = useOverlayPortalContainer()
return useMemo(() => {
if (portalContainer) return portalContainer
return undefined
}, [portalContainer])
return portalContainer
}