import { useState, useLayoutEffect, useCallback, useEffect, useRef, type ReactNode } from 'react'; import { useLocation } from 'react-router-dom'; import { NavigationMemoryContext } from './navigationMemoryContext'; export function NavigationMemoryProvider({ children }: { children: ReactNode }) { const location = useLocation(); const { pathname, search } = location; const [mainContentPath, setMainContentPath] = useState(pathname); const [mainContentSearch, setMainContentSearch] = useState(search); const [scrollPositions, setScrollPositions] = useState>({}); const [pageStates, setPageStates] = useState>({}); const setScrollPosition = useCallback((path: string, pos: number) => { setScrollPositions((prev) => { if (prev[path] === pos) return prev; return { ...prev, [path]: pos }; }); }, []); const clearScrollPosition = useCallback((path: string) => { setScrollPositions((prev) => { if (!(path in prev)) return prev; const next = { ...prev }; delete next[path]; return next; }); }, []); const setPageState = useCallback((path: string, newStateOrUpdater: any) => { setPageStates((prev) => { const oldState = prev[path]; const newState = typeof newStateOrUpdater === 'function' ? newStateOrUpdater(oldState) : newStateOrUpdater; if (oldState === newState) return prev; return { ...prev, [path]: newState }; }); }, []); const updateMainContent = useCallback((path: string, s: string) => { setMainContentPath(path); setMainContentSearch(s); }, []); useLayoutEffect(() => { const isPostUrl = pathname.startsWith('/post/'); const isProfileUrl = pathname.match(/^\/profile\/[^/]+$/); if (!isPostUrl && !isProfileUrl) { // eslint-disable-next-line react-hooks/set-state-in-effect updateMainContent(pathname, search); } }, [pathname, search, updateMainContent]); const lastKnownScrollRef = useRef>({}); useEffect(() => { const handleScroll = () => { lastKnownScrollRef.current[pathname + search] = window.scrollY; setScrollPosition(pathname + search, window.scrollY); }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => { window.removeEventListener('scroll', handleScroll); const currentScroll = window.scrollY; const lastKnown = lastKnownScrollRef.current[pathname + search]; if (lastKnown === undefined || Math.abs(currentScroll - lastKnown) < 5) { setScrollPosition(pathname + search, currentScroll); } }; }, [pathname, search, setScrollPosition]); return ( {children} ); }