diff --git a/app/mobile/engagement/page.tsx b/app/mobile/engagement/page.tsx index f682f75..6008c67 100644 --- a/app/mobile/engagement/page.tsx +++ b/app/mobile/engagement/page.tsx @@ -172,6 +172,38 @@ export default function MobileEngagementPage() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [sortKey]); + // D-04 fallback: the mobile shell's
is overflow-y-auto, so Next.js's + // built-in scrollRestoration (which targets window) doesn't help. Persist the + // inner scroll position across navigations via sessionStorage so back from + // /mobile/engagement/[userId] restores the row the user tapped. + const restoredScrollRef = useRef(false); + useEffect(() => { + const main = document.querySelector('main'); + if (!main) return; + let raf = 0; + const onScroll = () => { + if (raf) return; + raf = requestAnimationFrame(() => { + raf = 0; + sessionStorage.setItem('mobile-engagement-list-scroll', String(main.scrollTop)); + }); + }; + main.addEventListener('scroll', onScroll, { passive: true }); + return () => { + main.removeEventListener('scroll', onScroll); + if (raf) cancelAnimationFrame(raf); + }; + }, []); + useEffect(() => { + if (restoredScrollRef.current) return; + if (usersLoading || users.length === 0) return; + const main = document.querySelector('main'); + if (!main) return; + const saved = sessionStorage.getItem('mobile-engagement-list-scroll'); + if (saved) main.scrollTop = parseInt(saved, 10); + restoredScrollRef.current = true; + }, [usersLoading, users.length]); + // IntersectionObserver — D-18 (mirrors Phase 4/6 pattern, rootMargin '200px') const sentinelRef = useRef(null); useEffect(() => {