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 { 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 { Comment, useAccount, useAccountComments, useAccountSubplebbits, useBlock, useFeed, useSubplebbit } from '@plebbit/plebbit-react-hooks';
|
||||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||||
import { Trans, useTranslation } from 'react-i18next';
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
@@ -274,19 +274,33 @@ const Board = () => {
|
|||||||
|
|
||||||
// save the last Virtuoso state to restore it when navigating back
|
// save the last Virtuoso state to restore it when navigating back
|
||||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
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(() => {
|
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 = () => {
|
const setLastVirtuosoState = () => {
|
||||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||||
if (snapshot?.ranges?.length) {
|
if (snapshot?.ranges?.length) {
|
||||||
lastVirtuosoStates[sortType + timeFilterSeconds] = snapshot;
|
lastVirtuosoStates[currentKey] = snapshot;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
window.addEventListener('scroll', setLastVirtuosoState);
|
window.addEventListener('scroll', setLastVirtuosoState);
|
||||||
return () => window.removeEventListener('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(() => {
|
useEffect(() => {
|
||||||
const boardTitle = title ? title : shortAddress || subplebbitAddress;
|
const boardTitle = title ? title : shortAddress || subplebbitAddress;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useMemo, useRef, useState, useCallback } from 'react';
|
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 { Trans, useTranslation } from 'react-i18next';
|
||||||
import { Comment, useAccount, useFeed, useSubplebbit, useBlock, useAccountComments } from '@plebbit/plebbit-react-hooks';
|
import { Comment, useAccount, useFeed, useSubplebbit, useBlock, useAccountComments } from '@plebbit/plebbit-react-hooks';
|
||||||
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
import { Virtuoso, VirtuosoHandle, StateSnapshot } from 'react-virtuoso';
|
||||||
@@ -452,18 +452,32 @@ const Catalog = () => {
|
|||||||
|
|
||||||
// save the last Virtuoso state to restore it when navigating back
|
// save the last Virtuoso state to restore it when navigating back
|
||||||
const virtuosoRef = useRef<VirtuosoHandle | null>(null);
|
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(() => {
|
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 = () =>
|
const setLastVirtuosoState = () =>
|
||||||
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
virtuosoRef.current?.getState((snapshot: StateSnapshot) => {
|
||||||
if (snapshot?.ranges?.length) {
|
if (snapshot?.ranges?.length) {
|
||||||
lastVirtuosoStates[sortType + timeFilterSeconds + 'catalog'] = snapshot;
|
lastVirtuosoStates[currentKey] = snapshot;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.addEventListener('scroll', setLastVirtuosoState);
|
window.addEventListener('scroll', setLastVirtuosoState);
|
||||||
return () => window.removeEventListener('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(() => {
|
useEffect(() => {
|
||||||
let documentTitle = title ? title : shortAddress;
|
let documentTitle = title ? title : shortAddress;
|
||||||
|
|||||||
Reference in New Issue
Block a user