diff --git a/src/components/MangaGrid.tsx b/src/components/MangaGrid.tsx index a2b3c056..d43acb8d 100644 --- a/src/components/MangaGrid.tsx +++ b/src/components/MangaGrid.tsx @@ -126,6 +126,9 @@ const HorizontalGrid = forwardRef( ), ); +export const getGridSnapshotKey = (location: ReturnType) => + `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(snapshotSessionKey, undefined); const persistGridStateTimeout = useRef(); diff --git a/src/screens/SourceMangas.tsx b/src/screens/SourceMangas.tsx index 734de31a..e83c8c13 100644 --- a/src/screens/SourceMangas.tsx +++ b/src/screens/SourceMangas.tsx @@ -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(filtersToApply); - const [resetScrollPosition, setResetScrollPosition] = useState(false); const [currentContentType, setCurrentContentType] = useSessionStorage( `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 ( @@ -459,7 +447,6 @@ export function SourceMangas() { updateFilterValue={setDialogFiltersToApply} setTriggerUpdate={() => { setFiltersToApply(dialogFiltersToApply); - updateLocationFilters(dialogFiltersToApply); }} resetFilterValue={resetFilters} update={dialogFiltersToApply}