Scroll to top when changing shown data in source browse

The current scroll position was preserved when changing the shown content type (browse, latest, filters) or when changing the filters.

Regression introduced with aab3e25031
This commit is contained in:
schroda
2024-04-16 02:49:08 +02:00
parent 80ad5e06be
commit 1f227ce886
2 changed files with 19 additions and 29 deletions

View File

@@ -126,6 +126,9 @@ const HorizontalGrid = forwardRef(
),
);
export const getGridSnapshotKey = (location: ReturnType<typeof useLocation>) =>
`MangaGrid-snapshot-location-${location.key}`;
const VerticalGrid = forwardRef(
(
{
@@ -148,7 +151,7 @@ const VerticalGrid = forwardRef(
) => {
const location = useLocation<{ snapshot?: GridStateSnapshot }>();
const snapshotSessionKey = `MangaGrid-snapshot-location-${location.key}`;
const snapshotSessionKey = getGridSnapshotKey(location);
const [snapshot] = useSessionStorage<GridStateSnapshot | undefined>(snapshotSessionKey, undefined);
const persistGridStateTimeout = useRef<NodeJS.Timeout | undefined>();

View File

@@ -38,6 +38,8 @@ import {
import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx';
import { useMetadataServerSettings } from '@/lib/metadata/metadataServerSettings.ts';
import { useSessionStorage } from '@/util/useStorage.tsx';
import { AppStorage } from '@/util/AppStorage.ts';
import { getGridSnapshotKey } from '@/components/MangaGrid.tsx';
const ContentTypeMenu = styled('div')(({ theme }) => ({
display: 'flex',
@@ -218,7 +220,8 @@ export function SourceMangas() {
const { sourceId } = useParams<{ sourceId: string }>();
const navigate = useNavigate();
const { key: locationKey, state: locationState } = useLocation();
const location = useLocation();
const { key: locationKey, state: locationState } = location;
const { contentType: initialContentType = SourceContentType.POPULAR, clearCache = false } =
useLocation<{
contentType: SourceContentType;
@@ -248,7 +251,6 @@ export function SourceMangas() {
currentFiltersToApply ?? [],
);
const [dialogFiltersToApply, setDialogFiltersToApply] = useState<IPos[]>(filtersToApply);
const [resetScrollPosition, setResetScrollPosition] = useState(false);
const [currentContentType, setCurrentContentType] = useSessionStorage<SourceContentType | undefined>(
`source-mangas-${sourceId}-content-type`,
initialContentType,
@@ -266,9 +268,15 @@ export function SourceMangas() {
[sourceId],
);
const scrollToTop = useCallback(() => {
AppStorage.session.setItem(getGridSnapshotKey(location), undefined);
window.scrollTo(0, 0);
}, [locationKey]);
const setFiltersToApply = (filters: IPos[]) => {
setCurrentFiltersToApply(filters);
setLocationFiltersToApply(filters);
scrollToTop();
};
const setContentType = (newContentType: SourceContentType) => {
@@ -300,7 +308,7 @@ export function SourceMangas() {
const updateContentType = useCallback(
(newContentType: SourceContentType, newSearch?: string | null) => {
setContentType(newContentType);
setResetScrollPosition(true);
scrollToTop();
if (query && !newSearch) {
navigate(
@@ -313,16 +321,7 @@ export function SourceMangas() {
);
}
},
[setContentType, query],
);
const updateLocationFilters = useCallback(
(updatedFilters: IPos[]) => {
if (contentType === SourceContentType.SEARCH) {
setFiltersToApply(updatedFilters);
}
},
[contentType, query],
[setContentType, query, scrollToTop],
);
const setSearchContentType = !!query && contentType !== SourceContentType.SEARCH;
@@ -338,12 +337,10 @@ export function SourceMangas() {
loadPage(lastPageNum + 1);
}, [lastPageNum, hasNextPage, contentType]);
const resetFilters = useCallback(async () => {
const resetFilters = useCallback(() => {
setDialogFiltersToApply([]);
setFiltersToApply([]);
updateLocationFilters([]);
setResetScrollPosition(true);
}, [sourceId, contentType, updateLocationFilters]);
}, [sourceId, contentType]);
useEffect(() => {
if (filteredOutAllItemsOfFetchedPage && hasNextPage && !loading) {
@@ -373,7 +370,7 @@ export function SourceMangas() {
// with strict mode + dev mode the first request will be aborted. due to using SWR there won't be an
// immediate second request since it's the same key. instead the "second" request will be the error handling of SWR
abortRequest(new Error(`SourceMangas(${sourceId}): search string changed`));
setResetScrollPosition(true);
scrollToTop();
},
[query],
);
@@ -406,15 +403,6 @@ export function SourceMangas() {
};
}, [t, source]);
useEffect(() => {
if (!resetScrollPosition) {
return;
}
window.scrollTo(0, 0);
setResetScrollPosition(false);
}, [resetScrollPosition]);
return (
<StyledGridWrapper hasContent={!!mangas.length}>
<ContentTypeMenu>
@@ -459,7 +447,6 @@ export function SourceMangas() {
updateFilterValue={setDialogFiltersToApply}
setTriggerUpdate={() => {
setFiltersToApply(dialogFiltersToApply);
updateLocationFilters(dialogFiltersToApply);
}}
resetFilterValue={resetFilters}
update={dialogFiltersToApply}