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>
This commit is contained in:
@@ -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
|
- (**Reader**) Improve preloading pages from the previous/next chapter
|
||||||
- (**Category**) Require confirmation before deleting a category
|
- (**Category**) Require confirmation before deleting a category
|
||||||
- (**Download**) Respect manga chapter filters on bulk manga download in the library
|
- (**Download**) Respect manga chapter filters on bulk manga download in the library
|
||||||
|
- (**History**) Show only the last read chapter per manga
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Typography from '@mui/material/Typography';
|
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 { useLingui } from '@lingui/react/macro';
|
||||||
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
import { requestManager } from '@/lib/requests/RequestManager.ts';
|
||||||
import { LoadingPlaceholder } from '@/base/components/feedback/LoadingPlaceholder.tsx';
|
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 { Chapters } from '@/features/chapter/services/Chapters.ts';
|
||||||
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
|
import { useAppTitle } from '@/features/navigation-bar/hooks/useAppTitle.ts';
|
||||||
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts';
|
||||||
|
import uniqBy from 'lodash/fp/uniqBy';
|
||||||
|
|
||||||
export const History: React.FC = () => {
|
export const History: React.FC = () => {
|
||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
@@ -38,8 +39,13 @@ export const History: React.FC = () => {
|
|||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
});
|
});
|
||||||
const hasNextPage = !!chapterHistoryData?.chapters.pageInfo.hasNextPage;
|
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(
|
const groupedHistory = useMemo(
|
||||||
() => Object.entries(Chapters.groupByDate(readEntries, 'lastReadAt')),
|
() => Object.entries(Chapters.groupByDate(readEntries, 'lastReadAt')),
|
||||||
[readEntries],
|
[readEntries],
|
||||||
@@ -60,8 +66,16 @@ export const History: React.FC = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchMore({ variables: { offset: readEntries.length } });
|
fetchMore({ variables: { offset: allReadEntries.length } }).then(() =>
|
||||||
}, [hasNextPage, endCursor]);
|
setPrevReadEntriesLength(readEntries.length),
|
||||||
|
);
|
||||||
|
}, [hasNextPage, allReadEntries.length, readEntries.length]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (filteredOutAllItemsOfFetchedPage && hasNextPage && !isLoading) {
|
||||||
|
loadMore();
|
||||||
|
}
|
||||||
|
}, [filteredOutAllItemsOfFetchedPage, isLoading, hasNextPage, loadMore]);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3478,7 +3478,7 @@ export class RequestManager {
|
|||||||
initialPages: number = 1,
|
initialPages: number = 1,
|
||||||
options?: QueryHookOptions<GetChaptersHistoryQuery, GetChaptersHistoryQueryVariables>,
|
options?: QueryHookOptions<GetChaptersHistoryQuery, GetChaptersHistoryQueryVariables>,
|
||||||
): AbortableApolloUseQueryResponse<GetChaptersHistoryQuery, GetChaptersHistoryQueryVariables> {
|
): AbortableApolloUseQueryResponse<GetChaptersHistoryQuery, GetChaptersHistoryQueryVariables> {
|
||||||
const PAGE_SIZE = 50;
|
const PAGE_SIZE = 150;
|
||||||
const CACHE_KEY = 'useGetRecentlyReadChapters';
|
const CACHE_KEY = 'useGetRecentlyReadChapters';
|
||||||
|
|
||||||
const offset = this.cache.getResponseFor<number>(CACHE_KEY, undefined) ?? 0;
|
const offset = this.cache.getResponseFor<number>(CACHE_KEY, undefined) ?? 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user