fix(scroll): resolve race condition in onClick scroll-to-top behavior

This commit is contained in:
plebeius.eth
2023-10-05 16:42:47 +02:00
parent bdb661b0dc
commit d5715e29eb
12 changed files with 124 additions and 287 deletions
+6
View File
@@ -45,6 +45,12 @@ export default function App() {
const location = useLocation();
const isElectron = window.electron && window.electron.isElectron;
useEffect(() => {
if (location.state?.scrollToTop) {
window.scrollTo(0, 0);
}
}, [location]);
const [, setNewErrorMessage] = useError();
const [, setNewSuccessMessage] = useSuccess();
const [, setNewInfoMessage] = useInfo();
+12 -18
View File
@@ -2,7 +2,7 @@ import React, { Fragment, useCallback, useEffect, useMemo, useState, useRef } fr
import { confirmAlert } from 'react-confirm-alert';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { Tooltip } from 'react-tooltip';
import { Virtuoso } from 'react-virtuoso';
import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
@@ -541,7 +541,12 @@ const All = () => {
navigate(`/p/${selected}`);
};
const location = useLocation();
useEffect(() => {
if (location.state?.scrollToTop) {
lastVirtuosoStates[`all`] = null;
}
const setLastVirtuosoState = () => {
virtuosoRef.current?.getState((snapshot) => {
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
@@ -552,7 +557,7 @@ const All = () => {
window.addEventListener('scroll', setLastVirtuosoState);
return () => window.removeEventListener('scroll', setLastVirtuosoState);
}, []);
}, [location.state?.scrollToTop]);
const lastVirtuosoState = lastVirtuosoStates['all'];
@@ -578,14 +583,9 @@ const All = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -652,10 +652,9 @@ const All = () => {
</Link>
&nbsp;
<Link
to='/'
to={{ pathname: '/', state: { scrollToTop: true } }}
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -3486,14 +3485,9 @@ const All = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
</span>
{defaultSubplebbits.map((subplebbit, index) => (
+14 -20
View File
@@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { confirmAlert } from 'react-confirm-alert';
import { Tooltip } from 'react-tooltip';
import { Virtuoso } from 'react-virtuoso';
@@ -777,7 +777,12 @@ const AllCatalog = () => {
setSelectedFeed(feed.filter((feed) => feed.title === title));
};
const location = useLocation();
useEffect(() => {
if (location.state?.scrollToTop) {
lastVirtuosoStates[`allCatalog`] = null;
}
const setLastVirtuosoState = () => {
virtuosoRef.current?.getState((snapshot) => {
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
@@ -788,7 +793,7 @@ const AllCatalog = () => {
window.addEventListener('scroll', setLastVirtuosoState);
return () => window.removeEventListener('scroll', setLastVirtuosoState);
}, [selectedAddress]);
}, [selectedAddress, location.state?.scrollToTop]);
const lastVirtuosoState = lastVirtuosoStates['allCatalog'];
@@ -813,14 +818,9 @@ const AllCatalog = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -894,10 +894,9 @@ const AllCatalog = () => {
</Link>
&nbsp;
<Link
to='/'
to={{ pathname: '/', state: { scrollToTop: true } }}
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -933,11 +932,11 @@ const AllCatalog = () => {
</select>
</span>
<div className='return-button' id='return-button-desktop'>
[<Link to={`/p/all`}>Return</Link>]
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>Return</Link>]
</div>
<div id='return-button-mobile'>
<span className='btn-wrap-catalog btn-wrap'>
<Link to={`/p/all`}>Return</Link>
<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>Return</Link>
</span>
</div>
{subplebbits.state === 'succeeded' ? null : (
@@ -1008,14 +1007,9 @@ const AllCatalog = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
+15 -37
View File
@@ -1,7 +1,7 @@
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
import { confirmAlert } from 'react-confirm-alert';
import { Tooltip } from 'react-tooltip';
import { Virtuoso } from 'react-virtuoso';
@@ -698,7 +698,12 @@ const Board = () => {
}
};
const location = useLocation();
useEffect(() => {
if (location.state?.scrollToTop) {
lastVirtuosoStates[selectedAddress] = null;
}
const setLastVirtuosoState = () => {
virtuosoRef.current?.getState((snapshot) => {
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
@@ -709,7 +714,7 @@ const Board = () => {
window.addEventListener('scroll', setLastVirtuosoState);
return () => window.removeEventListener('scroll', setLastVirtuosoState);
}, [selectedAddress]);
}, [selectedAddress, location.state?.scrollToTop]);
const lastVirtuosoState = lastVirtuosoStates[selectedAddress];
@@ -736,14 +741,9 @@ const Board = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -813,10 +813,9 @@ const Board = () => {
</Link>
&nbsp;
<Link
to='/'
to={{ pathname: '/', state: { scrollToTop: true } }}
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -919,16 +918,8 @@ const Board = () => {
</select>
</span>
<div id='catalog-button-desktop'>
[
<Link
to={`/p/${selectedAddress}/catalog`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Catalog
</Link>
]{subplebbit.roles && subplebbit?.roles?.[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
{subplebbit.roles && subplebbit?.roles?.[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
</div>
{subplebbit?.state === 'succeeded' ? (
<>
@@ -952,14 +943,7 @@ const Board = () => {
)}
<div id='catalog-button-mobile'>
<span className='btn-wrap'>
<Link
to={`/p/${selectedAddress}/catalog`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Catalog
</Link>
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
</span>
</div>
</TopBar>
@@ -3759,7 +3743,6 @@ const Board = () => {
to={`/p/${selectedAddress}/c/${thread.cid}`}
onClick={() => {
setSelectedThread(thread.cid);
window.scrollTo(0, 0);
}}
className='button-mobile'
>
@@ -4568,14 +4551,9 @@ const Board = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;
</span>
{defaultSubplebbits.map((subplebbit, index) => (
+15 -36
View File
@@ -1,7 +1,7 @@
import React, { useCallback, useLayoutEffect, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom';
import { confirmAlert } from 'react-confirm-alert';
import { Tooltip } from 'react-tooltip';
import { Virtuoso } from 'react-virtuoso';
@@ -1462,7 +1462,12 @@ const Catalog = () => {
}
};
const location = useLocation();
useEffect(() => {
if (location.state?.scrollToTop) {
lastVirtuosoStates[`${selectedAddress}-catalog`] = null;
}
const setLastVirtuosoState = () => {
virtuosoRef.current?.getState((snapshot) => {
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
@@ -1473,7 +1478,7 @@ const Catalog = () => {
window.addEventListener('scroll', setLastVirtuosoState);
return () => window.removeEventListener('scroll', setLastVirtuosoState);
}, [selectedAddress]);
}, [selectedAddress, location.state?.scrollToTop]);
const lastVirtuosoState = lastVirtuosoStates[`${selectedAddress}-catalog`];
@@ -1498,14 +1503,9 @@ const Catalog = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -1580,10 +1580,9 @@ const Catalog = () => {
</Link>
&nbsp;
<Link
to='/'
to={{ pathname: '/', state: { scrollToTop: true } }}
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -1688,16 +1687,8 @@ const Catalog = () => {
</select>
</span>
<div className='return-button' id='return-button-desktop'>
[
<Link
to={`/p/${selectedAddress}`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Return
</Link>
]{subplebbit.roles && subplebbit?.roles[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
{subplebbit.roles && subplebbit?.roles[account?.author?.address]?.role === 'admin' ? <BoardSettings subplebbit={subplebbit} /> : null}
</div>
{subplebbit.state === 'succeeded' ? (
<>
@@ -1721,14 +1712,7 @@ const Catalog = () => {
)}
<div id='return-button-mobile'>
<span className='btn-wrap-catalog btn-wrap'>
<Link
to={`/p/${selectedAddress}`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Return
</Link>
<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>
</span>
</div>
<hr />
@@ -1793,14 +1777,9 @@ const Catalog = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;
</span>
{defaultSubplebbits.map((subplebbit, index) => (
+9 -32
View File
@@ -160,14 +160,9 @@ const Description = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -245,7 +240,6 @@ const Description = () => {
to='/'
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -275,25 +269,13 @@ const Description = () => {
<PostForm selectedStyle={selectedStyle}>
<ReplyFormLink id='post-form-link' selectedStyle={selectedStyle} style={{ marginBottom: '10px' }}>
<div id='return-button-mobile'>
<span
className='btn-wrap'
onClick={() => {
window.scrollTo(0, 0);
}}
>
<Link to={`/p/${selectedAddress}`}>Return</Link>
<span className='btn-wrap'>
<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>
</span>
</div>
<div id='catalog-button-mobile'>
<span className='btn-wrap'>
<Link
to={`/p/${selectedAddress}/catalog`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Catalog
</Link>
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
</span>
</div>
<div id='bottom-button-mobile'>
@@ -323,10 +305,10 @@ const Description = () => {
</select>
</span>
<span className='return-button' id='return-button-desktop'>
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
</span>
<span className='return-button catalog-button' id='catalog-button-desktop'>
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
</span>
<span className='return-button catalog-button' id='bottom-button-desktop'>
[
@@ -694,14 +676,9 @@ const Description = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;
</span>
{defaultSubplebbits.map((subplebbit, index) => (
+8 -42
View File
@@ -31,7 +31,6 @@ const PopularThreads = ({ commentCid }) => {
onClick={() => {
setSelectedTitle(subplebbit?.title);
setSelectedAddress(comment?.subplebbitAddress);
window.scrollTo(0, 0);
}}
>
{commentMediaInfo?.type === 'webpage' && commentMediaInfo?.thumbnail ? (
@@ -223,13 +222,7 @@ const Home = () => {
</a>
</h3>
&nbsp;
<Link
to='/p/all'
id='button'
onClick={() => {
window.scrollTo(0, 0);
}}
>
<Link to={{ pathname: '/p/all', state: { scrollToTop: true } }} id='button'>
[view all]
</Link>
<ul>
@@ -239,10 +232,10 @@ const Home = () => {
<Link
key={`default-link-${index}`}
className='boardlink'
onClick={() => {
window.scrollTo(0, 0);
to={{
pathname: `/p/${address}`,
state: { scrollToTop: true },
}}
to={`/p/${address}`}
>
{address}
</Link>
@@ -273,14 +266,7 @@ const Home = () => {
{defaultNsfwSubplebbits.slice(0, showAllSFWBoards ? undefined : 18).map((subplebbit, index) => (
<li key={`default-${index}`}>
<OfflineIndicator address={subplebbit.address} className='disconnected' isText={true} />
<Link
key={`default-link-${index}`}
className='boardlink'
onClick={() => {
window.scrollTo(0, 0);
}}
to={`/p/${subplebbit.address}`}
>
<Link key={`default-link-${index}`} className='boardlink' to={{ pathname: `/p/${subplebbit.address}`, state: { scrollToTop: true } }}>
{subplebbit.address}
</Link>
&nbsp;
@@ -297,13 +283,7 @@ const Home = () => {
<div className='column'>
<h3 style={{ textDecoration: 'underline', display: 'inline' }}>Subscriptions</h3>
&nbsp;
<Link
to='/p/subscriptions'
id='button'
onClick={() => {
window.scrollTo(0, 0);
}}
>
<Link to={{ pathname: '/p/subscriptions', state: { scrollToTop: true } }} id='button'>
[view all]
</Link>
<br />
@@ -312,14 +292,7 @@ const Home = () => {
{account?.subscriptions?.slice(0, showAllSubscriptions ? undefined : 18).map((subscription, index) => (
<li key={`sub-${index}`}>
<OfflineIndicator address={subscription} className='disconnected' isText={true} />
<Link
key={`sub-link-${index}`}
className='boardlink'
onClick={() => {
window.scrollTo(0, 0);
}}
to={`/p/${subscription}`}
>
<Link key={`sub-link-${index}`} className='boardlink' to={{ pathname: `/p/${subscription}`, state: { scrollToTop: true } }}>
{subscription}
</Link>
&nbsp;
@@ -340,14 +313,7 @@ const Home = () => {
{accountSubplebbitsAddresses?.slice(0, showAllSubscriptions ? undefined : 18).map((subplebbit, index) => (
<li key={`sub-${index}`}>
<OfflineIndicator address={subplebbit} className='disconnected' isText={true} />
<Link
key={`sub-link-${index}`}
className='boardlink'
onClick={() => {
window.scrollTo(0, 0);
}}
to={`/p/${subplebbit}`}
>
<Link key={`sub-link-${index}`} className='boardlink' to={{ pathname: `/p/${subplebbit}`, state: { scrollToTop: true } }}>
{subplebbit}
</Link>
&nbsp;
+2 -7
View File
@@ -120,14 +120,9 @@ const Pending = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
+9 -32
View File
@@ -170,14 +170,9 @@ const Rules = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -255,7 +250,6 @@ const Rules = () => {
to='/'
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -285,25 +279,13 @@ const Rules = () => {
<PostForm selectedStyle={selectedStyle}>
<ReplyFormLink id='post-form-link' selectedStyle={selectedStyle} style={{ marginBottom: '10px' }}>
<div id='return-button-mobile'>
<span
className='btn-wrap'
onClick={() => {
window.scrollTo(0, 0);
}}
>
<Link to={`/p/${selectedAddress}`}>Return</Link>
<span className='btn-wrap'>
<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>
</span>
</div>
<div id='catalog-button-mobile'>
<span className='btn-wrap'>
<Link
to={`/p/${selectedAddress}/catalog`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Catalog
</Link>
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
</span>
</div>
<div id='bottom-button-mobile'>
@@ -333,10 +315,10 @@ const Rules = () => {
</select>
</span>
<span className='return-button' id='return-button-desktop'>
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
</span>
<span className='return-button catalog-button' id='catalog-button-desktop'>
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
</span>
<span className='return-button catalog-button' id='bottom-button-desktop'>
[
@@ -630,14 +612,9 @@ const Rules = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;
</span>
{defaultSubplebbits.map((subplebbit, index) => (
+10 -11
View File
@@ -2,7 +2,7 @@ import React, { Fragment, useCallback, useEffect, useMemo, useState, useRef } fr
import { confirmAlert } from 'react-confirm-alert';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { Tooltip } from 'react-tooltip';
import { Virtuoso } from 'react-virtuoso';
import { useAccount, useAccountComments, useFeed, usePublishCommentEdit, useSubplebbits } from '@plebbit/plebbit-react-hooks';
@@ -540,7 +540,12 @@ const Subscriptions = () => {
navigate(`/p/${selected}`);
};
const location = useLocation();
useEffect(() => {
if (location.state?.scrollToTop) {
lastVirtuosoStates[`subscriptions`] = null;
}
const setLastVirtuosoState = () => {
virtuosoRef.current?.getState((snapshot) => {
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
@@ -551,7 +556,7 @@ const Subscriptions = () => {
window.addEventListener('scroll', setLastVirtuosoState);
return () => window.removeEventListener('scroll', setLastVirtuosoState);
}, []);
}, [location.state?.scrollToTop]);
const lastVirtuosoState = lastVirtuosoStates['subscriptions'];
@@ -577,14 +582,9 @@ const Subscriptions = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -651,10 +651,9 @@ const Subscriptions = () => {
</Link>
&nbsp;
<Link
to='/'
to={{ pathname: '/', state: { scrollToTop: true } }}
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
+14 -19
View File
@@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Helmet } from 'react-helmet-async';
import { Link, useNavigate } from 'react-router-dom';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { confirmAlert } from 'react-confirm-alert';
import { Tooltip } from 'react-tooltip';
import { Virtuoso } from 'react-virtuoso';
@@ -710,7 +710,6 @@ const SubscriptionsCatalog = () => {
isSettingsOpen,
setIsSettingsOpen,
originalCommentContent,
selectedAddress,
setSelectedAddress,
selectedStyle,
setSelectedTitle,
@@ -777,18 +776,23 @@ const SubscriptionsCatalog = () => {
navigate(`/p/${selected}`);
};
const location = useLocation();
useEffect(() => {
if (location.state?.scrollToTop) {
lastVirtuosoStates[`subscriptionsCatalog`] = null;
}
const setLastVirtuosoState = () => {
virtuosoRef.current?.getState((snapshot) => {
if (snapshot?.scrollTop === 0 || snapshot?.ranges?.length) {
lastVirtuosoStates[`${selectedAddress}-catalog`] = snapshot;
lastVirtuosoStates[`subscriptionsCatalog`] = snapshot;
}
});
};
window.addEventListener('scroll', setLastVirtuosoState);
return () => window.removeEventListener('scroll', setLastVirtuosoState);
}, [selectedAddress]);
}, [location.state?.scrollToTop]);
const lastVirtuosoState = lastVirtuosoStates['subscriptionsCatalog'];
@@ -813,14 +817,9 @@ const SubscriptionsCatalog = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -894,10 +893,9 @@ const SubscriptionsCatalog = () => {
</Link>
&nbsp;
<Link
to='/'
to={{ pathname: '/', state: { scrollToTop: true } }}
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -941,11 +939,11 @@ const SubscriptionsCatalog = () => {
</select>
</span>
<div className='return-button' id='return-button-desktop'>
[<Link to={`/p/subscriptions`}>Return</Link>]
[<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Return</Link>]
</div>
<div id='return-button-mobile'>
<span className='btn-wrap-catalog btn-wrap'>
<Link to={`/p/subscriptions`}>Return</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Return</Link>
</span>
</div>
{subplebbits.state === 'succeeded' ? null : (
@@ -1015,10 +1013,7 @@ const SubscriptionsCatalog = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
[<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
+10 -33
View File
@@ -664,14 +664,9 @@ const Thread = () => {
<NavBar selectedStyle={selectedStyle}>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;[
{defaultSubplebbits.map((subplebbit, index) => (
<span className='boardList' key={`span-${subplebbit.address}`}>
@@ -749,7 +744,6 @@ const Thread = () => {
to='/'
onClick={() => {
handleStyleChange({ target: { value: 'Yotsuba' } });
window.scrollTo(0, 0);
}}
>
Home
@@ -779,25 +773,13 @@ const Thread = () => {
<PostForm selectedStyle={selectedStyle} name='post' action='' method='post' enctype='multipart/form-data'>
<ReplyFormLink id='post-form-link' showReplyFormLink={showPostFormLink} selectedStyle={selectedStyle}>
<div id='return-button-mobile'>
<span
className='btn-wrap'
onClick={() => {
window.scrollTo(0, 0);
}}
>
<span className='btn-wrap'>
<Link to={`/p/${selectedAddress}`}>Return</Link>
</span>
</div>
<div id='catalog-button-mobile'>
<span className='btn-wrap'>
<Link
to={`/p/${selectedAddress}/catalog`}
onClick={() => {
window.scrollTo(0, 0);
}}
>
Catalog
</Link>
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
</span>
</div>
<div id='bottom-button-mobile'>
@@ -898,7 +880,7 @@ const Thread = () => {
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
</span>
<span className='return-button catalog-button' id='catalog-button-desktop'>
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
</span>
<span className='return-button catalog-button' id='bottom-button-desktop'>
[
@@ -3043,10 +3025,10 @@ const Thread = () => {
<div id='bottombar-desktop'>
<hr />
<span className='bottom-bar-return'>
[<Link to={`/p/${selectedAddress}`}>Return</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}`, state: { scrollToTop: true } }}>Return</Link>]
</span>
<span className='bottom-bar-catalog'>
[<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>]
[<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>]
</span>
<span className='bottom-bar-top'>
[
@@ -3151,7 +3133,7 @@ const Thread = () => {
</div>
<div id='catalog-button-mobile' style={{ paddingRight: '2px' }}>
<span className='btn-wrap'>
<Link to={`/p/${selectedAddress}/catalog`}>Catalog</Link>
<Link to={{ pathname: `/p/${selectedAddress}/catalog`, state: { scrollToTop: true } }}>Catalog</Link>
</span>
</div>
<span className='bottom-bar-top'>
@@ -3232,14 +3214,9 @@ const Thread = () => {
>
<>
<span className='boardList'>
[
<Link to={`/p/all`} onClick={() => window.scrollTo(0, 0)}>
All
</Link>
[<Link to={{ pathname: `/p/all`, state: { scrollToTop: true } }}>All</Link>
 / 
<Link to={`/p/subscriptions`} onClick={() => window.scrollTo(0, 0)}>
Subscriptions
</Link>
<Link to={{ pathname: `/p/subscriptions`, state: { scrollToTop: true } }}>Subscriptions</Link>
]&nbsp;
</span>
{defaultSubplebbits.map((subplebbit, index) => (