mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
fix: reset board scroll on link nav
Force scroll-to-top on link navigation while keeping POP restores, and scope Virtuoso keys per pathname to avoid cross-board scroll leakage.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom';
|
||||
import { Comment, useAccount, useAccountComments, useAccountSubplebbits, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
@@ -274,19 +274,33 @@ const Board = () => {
|
||||
|
||||
// save the last Virtuoso state to restore it when navigating back
|
||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
||||
// include pathname in key so each board has its own scroll state
|
||||
const virtuosoStateKey = `${location.pathname}-${sortType}-${timeFilterSeconds}`;
|
||||
const navigationType = useNavigationType();
|
||||
|
||||
// When entering a board via link (PUSH/REPLACE), force scroll to top to avoid inheriting prior view scroll.
|
||||
useEffect(() => {
|
||||
if (navigationType !== 'POP') {
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
|
||||
}
|
||||
}, [navigationType, location.pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
// capture the key at effect creation time to prevent race conditions during navigation
|
||||
const currentKey = virtuosoStateKey;
|
||||
const setLastVirtuosoState = () => {
|
||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||
if (snapshot?.ranges?.length) {
|
||||
lastVirtuosoStates[sortType + timeFilterSeconds] = snapshot;
|
||||
lastVirtuosoStates[currentKey] = snapshot;
|
||||
}
|
||||
});
|
||||
};
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [sortType, timeFilterSeconds]);
|
||||
}, [virtuosoStateKey]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterSeconds];
|
||||
// only restore scroll state on back/forward navigation (POP), not when clicking links (PUSH)
|
||||
const lastVirtuosoState = navigationType === 'POP' ? lastVirtuosoStates?.[virtuosoStateKey] : undefined;
|
||||
|
||||
useEffect(() => {
|
||||
const boardTitle = title ? title : shortAddress || subplebbitAddress;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useRef, useState, useCallback } from 'react';
|
||||
import { Link, useLocation, useParams } from 'react-router-dom';
|
||||
import { Link, useLocation, useNavigationType, useParams } from 'react-router-dom';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Comment, useAccount, useFeed, useSubplebbit, useBlock, useAccountComments } from '@plebbit/plebbit-react-hooks';
|
||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||
@@ -452,18 +452,32 @@ const Catalog = () => {
|
||||
|
||||
// save the last Virtuoso state to restore it when navigating back
|
||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
||||
// include pathname in key so each board has its own scroll state
|
||||
const virtuosoStateKey = `${location.pathname}-${sortType}-${timeFilterSeconds}-catalog`;
|
||||
const navigationType = useNavigationType();
|
||||
|
||||
// When entering a board via link (PUSH/REPLACE), force scroll to top to avoid inheriting prior view scroll.
|
||||
useEffect(() => {
|
||||
if (navigationType !== 'POP') {
|
||||
window.scrollTo({ top: 0, left: 0, behavior: 'auto' });
|
||||
}
|
||||
}, [navigationType, location.pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
// capture the key at effect creation time to prevent race conditions during navigation
|
||||
const currentKey = virtuosoStateKey;
|
||||
const setLastVirtuosoState = () =>
|
||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||
if (snapshot?.ranges?.length) {
|
||||
lastVirtuosoStates[sortType + timeFilterSeconds + 'catalog'] = snapshot;
|
||||
lastVirtuosoStates[currentKey] = snapshot;
|
||||
}
|
||||
});
|
||||
window.addEventListener('scroll', setLastVirtuosoState);
|
||||
return () => window.removeEventListener('scroll', setLastVirtuosoState);
|
||||
}, [sortType, timeFilterSeconds]);
|
||||
}, [virtuosoStateKey]);
|
||||
|
||||
const lastVirtuosoState = lastVirtuosoStates?.[sortType + timeFilterSeconds + 'catalog'];
|
||||
// only restore scroll state on back/forward navigation (POP), not when clicking links (PUSH)
|
||||
const lastVirtuosoState = navigationType === 'POP' ? lastVirtuosoStates?.[virtuosoStateKey] : undefined;
|
||||
|
||||
useEffect(() => {
|
||||
let documentTitle = title ? title : shortAddress;
|
||||
|
||||
Reference in New Issue
Block a user