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