mirror of
https://github.com/suitenumerique/meet.git
synced 2026-08-20 23:32:23 +00:00
🐛(frontend) unmount PiP portal synchronously on pagehide
When the PiP window closes, the browser destroys its document right after `pagehide`. If the portal unmount is left to React's async scheduling, it commits against a dead document and `removeChild` throws "NotFoundError", crashing the app. Subscribe `PictureInPicturePortal` to the Valtio store with `sync: true`, and use `flushSync` in `usePictureInPicture` on teardown so React unmounts the portal while the PiP document is still alive. Fix 019f42cf-86a9-7ad2-8e64-81b004ddc5de
This commit is contained in:
committed by
aleb_the_flash
parent
23bb3c39d0
commit
b8958e6e87
@@ -7,7 +7,9 @@ import { useEffect, useMemo } from 'react'
|
|||||||
import { CrossDocumentOverlaysContext } from '@/primitives/CrossDocumentOverlaysContext'
|
import { CrossDocumentOverlaysContext } from '@/primitives/CrossDocumentOverlaysContext'
|
||||||
|
|
||||||
const InternalPortal = ({ children }: { children: React.ReactNode }) => {
|
const InternalPortal = ({ children }: { children: React.ReactNode }) => {
|
||||||
const pipStoreSnap = useSnapshot(documentPictureInPictureStore)
|
const pipStoreSnap = useSnapshot(documentPictureInPictureStore, {
|
||||||
|
sync: true,
|
||||||
|
})
|
||||||
|
|
||||||
const container = useMemo(() => {
|
const container = useMemo(() => {
|
||||||
return pipStoreSnap?.window?.document.getElementById('root')
|
return pipStoreSnap?.window?.document.getElementById('root')
|
||||||
@@ -19,7 +21,7 @@ const InternalPortal = ({ children }: { children: React.ReactNode }) => {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
if (!container) return null
|
if (!container || !container.isConnected) return null
|
||||||
|
|
||||||
return createPortal(
|
return createPortal(
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ref, useSnapshot } from 'valtio'
|
import { ref, useSnapshot } from 'valtio'
|
||||||
import { useCallback, useMemo } from 'react'
|
import { useCallback, useMemo } from 'react'
|
||||||
|
import { flushSync } from 'react-dom'
|
||||||
import { documentPictureInPictureStore } from '@/stores/documentPictureInPicture'
|
import { documentPictureInPictureStore } from '@/stores/documentPictureInPicture'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
@@ -73,7 +74,9 @@ export const usePictureInPicture = () => {
|
|||||||
|
|
||||||
const cleanUp = () => {
|
const cleanUp = () => {
|
||||||
if (documentPictureInPictureStore.window === pipWindow) {
|
if (documentPictureInPictureStore.window === pipWindow) {
|
||||||
documentPictureInPictureStore.window = null
|
flushSync(() => {
|
||||||
|
documentPictureInPictureStore.window = null
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pipWindow.addEventListener('pagehide', () => cleanUp(), { once: true })
|
pipWindow.addEventListener('pagehide', () => cleanUp(), { once: true })
|
||||||
|
|||||||
Reference in New Issue
Block a user