fix(08-02): preserve engagement list scroll across profile navigation (D-04)
The mobile shell's <main> is overflow-y-auto, so Next.js's built-in scrollRestoration (window-only) doesn't restore the list's inner scroll when returning from /mobile/engagement/[userId]. Persist the scroll position to sessionStorage on scroll (rAF-throttled) and restore once after the first users page loads. Restoration is gated to the first load only, so changing period/sort doesn't yank the viewport — and uses a single sessionStorage key, so returning to the list later still lands where you were.
This commit is contained in:
parent
81079ad89f
commit
6bdc937861
1 changed files with 32 additions and 0 deletions
|
|
@ -172,6 +172,38 @@ export default function MobileEngagementPage() {
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [sortKey]);
|
||||
|
||||
// D-04 fallback: the mobile shell's <main> 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<HTMLDivElement | null>(null);
|
||||
useEffect(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue