From 0ffaa0fb3e72b6a603bf969eefb8b1444130e8c3 Mon Sep 17 00:00:00 2001 From: matsuaa Date: Sat, 4 Jul 2026 15:29:41 +0200 Subject: [PATCH] Chapters grouped by manga series (#1085) * show only the last chapter red * fix : case when a load has not enough different manga * fix : problems with the load of chapters * Fix "filteredOutAllItemsOfFetchedPage" determination * Remove logic to load until scrollbar appears `Virtuoso` (list) doesn't have the same issue as `GridVirtuoso`, i.e. `endReached` gets called on initial render in case there weren't enough items * Increase history page size (50 -> 150) Due to the new filtering, it can take forever to load the initial pages/next pages * Use lodash "uniqBy" for filtering * Update changelog --------- Co-authored-by: schroda <50052685+schroda@users.noreply.github.com> --- CHANGELOG.md | 1 + src/features/history/screens/History.tsx | 24 +++++++++++++++++++----- src/lib/requests/RequestManager.ts | 2 +- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d910119e..3d5a856d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Reader**) Improve preloading pages from the previous/next chapter - (**Category**) Require confirmation before deleting a category - (**Download**) Respect manga chapter filters on bulk manga download in the library +- (**History**) Show only the last read chapter per manga ### Fixed diff --git a/src/features/history/screens/History.tsx b/src/features/history/screens/History.tsx index b4ad75e0..73e5c724 100644 --- a/src/features/history/screens/History.tsx +++ b/src/features/history/screens/History.tsx @@ -7,7 +7,7 @@ */ import Typography from '@mui/material/Typography'; -import React, { useCallback, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useLingui } from '@lingui/react/macro'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx'; @@ -22,6 +22,7 @@ import { ChapterHistoryCard } from '@/features/history/components/ChapterHistory import { Chapters } from '@/features/chapter/services/Chapters.ts'; import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts'; import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts'; +import uniqBy from 'lodash/fp/uniqBy'; export const History: React.FC = () => { const { t } = useLingui(); @@ -38,8 +39,13 @@ export const History: React.FC = () => { fetchPolicy: 'cache-and-network', }); const hasNextPage = !!chapterHistoryData?.chapters.pageInfo.hasNextPage; - const endCursor = chapterHistoryData?.chapters.pageInfo.endCursor; - const readEntries = chapterHistoryData?.chapters.nodes ?? STABLE_EMPTY_ARRAY; + + const allReadEntries = chapterHistoryData?.chapters.nodes ?? STABLE_EMPTY_ARRAY; + const readEntries = useMemo(() => uniqBy('mangaId', allReadEntries), [allReadEntries]); + + const [prevReadEntriesLength, setPrevReadEntriesLength] = useState(0); + const filteredOutAllItemsOfFetchedPage = allReadEntries.length > 0 && readEntries.length === prevReadEntriesLength; + const groupedHistory = useMemo( () => Object.entries(Chapters.groupByDate(readEntries, 'lastReadAt')), [readEntries], @@ -60,8 +66,16 @@ export const History: React.FC = () => { return; } - fetchMore({ variables: { offset: readEntries.length } }); - }, [hasNextPage, endCursor]); + fetchMore({ variables: { offset: allReadEntries.length } }).then(() => + setPrevReadEntriesLength(readEntries.length), + ); + }, [hasNextPage, allReadEntries.length, readEntries.length]); + + useEffect(() => { + if (filteredOutAllItemsOfFetchedPage && hasNextPage && !isLoading) { + loadMore(); + } + }, [filteredOutAllItemsOfFetchedPage, isLoading, hasNextPage, loadMore]); if (error) { return ( diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index 37e5a469..a94ad54d 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -3478,7 +3478,7 @@ export class RequestManager { initialPages: number = 1, options?: QueryHookOptions, ): AbortableApolloUseQueryResponse { - const PAGE_SIZE = 50; + const PAGE_SIZE = 150; const CACHE_KEY = 'useGetRecentlyReadChapters'; const offset = this.cache.getResponseFor(CACHE_KEY, undefined) ?? 0;