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

View file

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

View file

@ -61,8 +61,9 @@ if ('scrollRestoration' in history) {
type Props = {
currentScroll: number,
isAuthenticated: boolean,
location: { pathname: string, search: string },
location: { pathname: string, search: string, hash: string },
history: {
action: string,
entries: { title: string }[],
goBack: () => void,
goForward: () => void,
@ -108,7 +109,7 @@ function PrivateRoute(props: PrivateRouteProps) {
function AppRouter(props: Props) {
const {
currentScroll,
location: { pathname, search },
location: { pathname, search, hash },
isAuthenticated,
history,
uri,
@ -177,9 +178,17 @@ function AppRouter(props: Props) {
useEffect(() => {
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
// 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 { SIMPLE_SITE } from 'config';
const MORE_CHANNELS_ANCHOR = 'MoreChannels';
type Props = {
followedTags: Array<Tag>,
subscribedChannels: Array<Subscription>,
@ -119,13 +121,16 @@ function ChannelsFollowingDiscover(props: Props) {
<ClaimTilesDiscover {...options} />
</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 */}
<ClaimListDiscover
defaultOrderBy={CS.ORDER_BY_TRENDING}
defaultFreshness={CS.FRESH_ALL}
claimType={CS.CLAIM_CHANNEL}
channelIds={SIMPLE_SITE ? PRIMARY_CONTENT_CHANNEL_IDS : undefined}
scrollAnchor={MORE_CHANNELS_ANCHOR}
/>
</Page>
);