import { createContext , ReactNode , useContext , useEffect , useMemo , useState } from 'react' ; import { FADE_TIME_MS } from 'components/FadeTransitioner/FadeTransitioner' ; type GalleryNavigationContextType = { historyStackLength : number ; } ; const GalleryNavigationContext = createContext < GalleryNavigationContextType | undefined > ( undefined ) ; function useGalleryNavigationContext ( ) { const value = useContext ( GalleryNavigationContext ) ; if ( ! value ) { throw new Error ( 'Missing GalleryNavigationContext somewhere above this component.' ) ; } return value ; } type Props = { children : ReactNode ; } ; export function GalleryNavigationProvider ( { children } ) { const [ historyStackLength , setHistoryStackLength ] = useState ( 0 ) ; useEffect ( ( ) => { const originalPushState = window . history . pushState ; window . history . pushState = ( ... args ) => { function setupScrollJankFix ( ) { let scrollY = window . scrollY ; function handleScroll ( ) { window . scrollTo ( { top : scrollY } ) ; scrollY = window . scrollY ; window . removeEventListener ( 'scroll' , handleScroll ) ; } window . addEventListener ( 'scroll' , handleScroll ) ; } setupScrollJankFix ( ) ; originalPushState . bind ( window . history ) ( ... args ) ; setHistoryStackLength ( window . history . state . idx ?? 0 ) ; } ; function handlePopState ( ) { const originalScrollTo = window . scrollTo ; window . scrollTo = ( ... args ) => { setTimeout ( ( ) => { originalScrollTo ( ... args ) ; } , FADE_TIME_MS ) ; window . scrollTo = originalScrollTo ; } ; setHistoryStackLength ( window . history . state . idx ?? 0 ) ; } window . addEventListener ( 'popstate' , handlePopState ) ; return ( ) => { window . history . pushState = originalPushState ; window . removeEventListener ( 'popstate' , handlePopState ) ; } ; } , [ ] ) ; const value = useMemo < GalleryNavigationContextType > ( ( ) => ( { historyStackLength , } ) , [ historyStackLength ] ) ; return ( < GalleryNavigationContext . Provider value = { value } > { children } < /GalleryNavigationContext.Provider>); } export function useCanGoBack ( ) { const { historyStackLength } = useGalleryNavigationContext ( ) ; return historyStackLength > 0 ; }