mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at main 53 lines 1.7 kB view raw
1import { 2 useCallback, 3 useEffect, 4 useRef, 5 useState, 6 useSyncExternalStore, 7} from 'react' 8 9import {isFirefox, isSafari} from '#/lib/browser' 10import {isWeb} from '#/platform/detection' 11 12function fullscreenSubscribe(onChange: () => void) { 13 document.addEventListener('fullscreenchange', onChange) 14 return () => document.removeEventListener('fullscreenchange', onChange) 15} 16 17export function useFullscreen(ref?: React.RefObject<HTMLElement | null>) { 18 if (!isWeb) throw new Error("'useFullscreen' is a web-only hook") 19 const isFullscreen = useSyncExternalStore(fullscreenSubscribe, () => 20 Boolean(document.fullscreenElement), 21 ) 22 const scrollYRef = useRef<null | number>(null) 23 const [prevIsFullscreen, setPrevIsFullscreen] = useState(isFullscreen) 24 25 const toggleFullscreen = useCallback(() => { 26 if (isFullscreen) { 27 document.exitFullscreen() 28 } else { 29 if (!ref) throw new Error('No ref provided') 30 if (!ref.current) return 31 scrollYRef.current = window.scrollY 32 ref.current.requestFullscreen() 33 } 34 }, [isFullscreen, ref]) 35 36 useEffect(() => { 37 if (prevIsFullscreen === isFullscreen) return 38 setPrevIsFullscreen(isFullscreen) 39 40 // Chrome has an issue where it doesn't scroll back to the top after exiting fullscreen 41 // Let's play it safe and do it if not FF or Safari, since anything else will probably be chromium 42 if (prevIsFullscreen && !isFirefox && !isSafari) { 43 setTimeout(() => { 44 if (scrollYRef.current !== null) { 45 window.scrollTo(0, scrollYRef.current) 46 scrollYRef.current = null 47 } 48 }, 100) 49 } 50 }, [isFullscreen, prevIsFullscreen]) 51 52 return [isFullscreen, toggleFullscreen] as const 53}