diff options
author | Samuel Newman <mozzius@protonmail.com> | 2024-09-10 06:37:57 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-09 22:37:57 -0700 |
commit | 66239ba11dd38056d1215327f160a0bb61d49320 (patch) | |
tree | 19a8363f8875c789aafca5161f5032c6539c766d /src/components/hooks | |
parent | 0f6be244a6bd4bbeb86b9914e8a5fe58a14b6809 (diff) | |
download | voidsky-66239ba11dd38056d1215327f160a0bb61d49320.tar.zst |
[Video] Fix fullscreen on Chrome (#5246)
Diffstat (limited to 'src/components/hooks')
-rw-r--r-- | src/components/hooks/useFullscreen.ts | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/components/hooks/useFullscreen.ts b/src/components/hooks/useFullscreen.ts new file mode 100644 index 000000000..498f22223 --- /dev/null +++ b/src/components/hooks/useFullscreen.ts @@ -0,0 +1,53 @@ +import { + useCallback, + useEffect, + useRef, + useState, + useSyncExternalStore, +} from 'react' + +import {isFirefox, isSafari} from '#/lib/browser' +import {isWeb} from '#/platform/detection' + +function fullscreenSubscribe(onChange: () => void) { + document.addEventListener('fullscreenchange', onChange) + return () => document.removeEventListener('fullscreenchange', onChange) +} + +export function useFullscreen(ref?: React.RefObject<HTMLElement>) { + if (!isWeb) throw new Error("'useFullscreen' is a web-only hook") + const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () => + Boolean(document.fullscreenElement), + ) + const scrollYRef = useRef<null | number>(null) + const [prevIsFullscreen, setPrevIsFullscreen] = useState(isFullscreen) + + const toggleFullscreen = useCallback(() => { + if (isFullscreen) { + document.exitFullscreen() + } else { + if (!ref) throw new Error('No ref provided') + if (!ref.current) return + scrollYRef.current = window.scrollY + ref.current.requestFullscreen() + } + }, [isFullscreen, ref]) + + useEffect(() => { + if (prevIsFullscreen === isFullscreen) return + setPrevIsFullscreen(isFullscreen) + + // Chrome has an issue where it doesn't scroll back to the top after exiting fullscreen + // Let's play it safe and do it if not FF or Safari, since anything else will probably be chromium + if (prevIsFullscreen && !isFirefox && !isSafari) { + setTimeout(() => { + if (scrollYRef.current !== null) { + window.scrollTo(0, scrollYRef.current) + scrollYRef.current = null + } + }, 100) + } + }, [isFullscreen, prevIsFullscreen]) + + return [isFullscreen, toggleFullscreen] as const +} |