Handle scrolling for ClaimListDiscover that exists in the middle of a page.

## Issue
5090: When sorting channels, switching between Trending/Top/New returns viewer to the top of the page

## Approach
- Add an optional parameter to `ClaimListDiscover/Header` to add an additional anchor ID when building a new search URL.
- Clients then add the anchor ID on the desired location.
- The code that handles the scrolling then checks if the `location` contains an anchor hash. If it does, we'll scroll to that element; else, the existing behavior will be used.
This commit is contained in:
infiinte-persistence 2020-11-26 01:09:58 +08:00 committed by Sean Yesmunt
parent 4b53d1267c
commit d8787cb4c5
4 changed files with 25 additions and 6 deletions

View file

@ -63,6 +63,7 @@ type Props = {
forceShowReposts?: boolean, forceShowReposts?: boolean,
languageSetting: string, languageSetting: string,
searchInLanguage: boolean, searchInLanguage: boolean,
scrollAnchor?: string,
}; };
function ClaimListDiscover(props: Props) { function ClaimListDiscover(props: Props) {
@ -110,6 +111,7 @@ function ClaimListDiscover(props: Props) {
forceShowReposts = false, forceShowReposts = false,
languageSetting, languageSetting,
searchInLanguage, searchInLanguage,
scrollAnchor,
} = props; } = props;
const didNavigateForward = history.action === 'PUSH'; const didNavigateForward = history.action === 'PUSH';
const { search } = location; const { search } = location;
@ -468,6 +470,7 @@ function ClaimListDiscover(props: Props) {
setPage={setPage} setPage={setPage}
tileLayout={tileLayout} tileLayout={tileLayout}
hideFilters={hideFilters} hideFilters={hideFilters}
scrollAnchor={scrollAnchor}
/> />
); );

View file

@ -33,6 +33,7 @@ type Props = {
hideFilters: boolean, hideFilters: boolean,
searchInLanguage: boolean, searchInLanguage: boolean,
languageSetting: string, languageSetting: string,
scrollAnchor?: string,
}; };
function ClaimListHeader(props: Props) { function ClaimListHeader(props: Props) {
@ -56,6 +57,7 @@ function ClaimListHeader(props: Props) {
hideFilters, hideFilters,
searchInLanguage, searchInLanguage,
languageSetting, languageSetting,
scrollAnchor,
} = props; } = props;
const { action, push, location } = useHistory(); const { action, push, location } = useHistory();
const { search } = location; const { search } = location;
@ -202,7 +204,7 @@ function ClaimListHeader(props: Props) {
} }
break; break;
} }
return `?${newUrlParams.toString()}`; return `?${newUrlParams.toString()}` + (scrollAnchor ? '#' + scrollAnchor : '');
} }
return ( return (

View file

@ -61,8 +61,9 @@ if ('scrollRestoration' in history) {
type Props = { type Props = {
currentScroll: number, currentScroll: number,
isAuthenticated: boolean, isAuthenticated: boolean,
location: { pathname: string, search: string }, location: { pathname: string, search: string, hash: string },
history: { history: {
action: string,
entries: { title: string }[], entries: { title: string }[],
goBack: () => void, goBack: () => void,
goForward: () => void, goForward: () => void,
@ -108,7 +109,7 @@ function PrivateRoute(props: PrivateRouteProps) {
function AppRouter(props: Props) { function AppRouter(props: Props) {
const { const {
currentScroll, currentScroll,
location: { pathname, search }, location: { pathname, search, hash },
isAuthenticated, isAuthenticated,
history, history,
uri, uri,
@ -177,9 +178,17 @@ function AppRouter(props: Props) {
useEffect(() => { useEffect(() => {
if (!hasLinkedCommentInUrl) { if (!hasLinkedCommentInUrl) {
window.scrollTo(0, currentScroll); if (hash && history.action === 'PUSH') {
const id = hash.replace('#', '');
const element = document.getElementById(id);
if (element) {
window.scrollTo(0, element.offsetTop);
}
} else {
window.scrollTo(0, currentScroll);
}
} }
}, [currentScroll, pathname, search, resetScroll, hasLinkedCommentInUrl]); }, [currentScroll, pathname, search, hash, resetScroll, hasLinkedCommentInUrl]);
// react-router doesn't decode pathanmes before doing the route matching check // react-router doesn't decode pathanmes before doing the route matching check
// We have to redirect here because if we redirect on the server, it might get encoded again // We have to redirect here because if we redirect on the server, it might get encoded again

View file

@ -10,6 +10,8 @@ import * as CS from 'constants/claim_search';
import { toCapitalCase } from 'util/string'; import { toCapitalCase } from 'util/string';
import { SIMPLE_SITE } from 'config'; import { SIMPLE_SITE } from 'config';
const MORE_CHANNELS_ANCHOR = 'MoreChannels';
type Props = { type Props = {
followedTags: Array<Tag>, followedTags: Array<Tag>,
subscribedChannels: Array<Subscription>, subscribedChannels: Array<Subscription>,
@ -119,13 +121,16 @@ function ChannelsFollowingDiscover(props: Props) {
<ClaimTilesDiscover {...options} /> <ClaimTilesDiscover {...options} />
</div> </div>
))} ))}
<h1 className="claim-grid__title">{__('More Channels')}</h1> <h1 id={MORE_CHANNELS_ANCHOR} className="claim-grid__title">
{__('More Channels')}
</h1>
{/* odysee: claimIds = PRIMARY_CONTENT_CHANNEL_IDS if simplesite CLD */} {/* odysee: claimIds = PRIMARY_CONTENT_CHANNEL_IDS if simplesite CLD */}
<ClaimListDiscover <ClaimListDiscover
defaultOrderBy={CS.ORDER_BY_TRENDING} defaultOrderBy={CS.ORDER_BY_TRENDING}
defaultFreshness={CS.FRESH_ALL} defaultFreshness={CS.FRESH_ALL}
claimType={CS.CLAIM_CHANNEL} claimType={CS.CLAIM_CHANNEL}
channelIds={SIMPLE_SITE ? PRIMARY_CONTENT_CHANNEL_IDS : undefined} channelIds={SIMPLE_SITE ? PRIMARY_CONTENT_CHANNEL_IDS : undefined}
scrollAnchor={MORE_CHANNELS_ANCHOR}
/> />
</Page> </Page>
); );