Improve "chapter list" render performance

affected components:
- ChapterList
- ReaderChapterList
This commit is contained in:
schroda
2025-01-12 19:08:46 +01:00
parent e7c3c8609e
commit 97dba923b4
4 changed files with 28 additions and 17 deletions

View File

@@ -144,6 +144,11 @@ export const ChapterList = ({
const noChaptersFound = chapters.length === 0;
const noChaptersMatchingFilter = !noChaptersFound && visibleChapters.length === 0;
const onSelect = useCallback(
(id: number, selected: boolean, selectRange?: boolean) => handleSelection(id, selected, { selectRange }),
[],
);
if (isLoading || (noChaptersFound && isRefreshing)) {
return (
<Stack sx={{ justifyContent: 'center', alignItems: 'center', position: 'relative', flexGrow: 1 }}>
@@ -238,11 +243,8 @@ export const ChapterList = ({
<ChapterCard
chapter={chapters[index]}
selected={!areNoItemsSelected ? selectedItemIds.includes(chapters[index].id) : null}
allChapters={chapters}
showChapterNumber={options.showChapterNumber}
onSelect={(selected, selectRange) =>
handleSelection(chapters[index].id, selected, { selectRange })
}
onSelect={onSelect}
/>
)}
useWindowScroll={isMobileWidth}

View File

@@ -38,6 +38,9 @@ import {
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts';
import { ChapterCard } from '@/modules/chapter/components/cards/ChapterCard.tsx';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { GetChaptersMangaQuery } from '@/lib/graphql/generated/graphql.ts';
import { GET_CHAPTERS_MANGA } from '@/lib/graphql/queries/ChapterQuery.ts';
type BaseProps = { onClose: () => void; selectable?: boolean };
@@ -50,7 +53,6 @@ type TChapter = ChapterIdInfo &
type SingleModeProps = {
chapter: TChapter;
allChapters: TChapter[];
handleSelection?: SelectableCollectionReturnType<TChapter['id']>['handleSelection'];
canBeDownloaded: boolean;
};
@@ -65,7 +67,6 @@ type Props =
export const ChapterActionMenuItems = ({
chapter,
allChapters,
handleSelection,
canBeDownloaded = false,
selectedChapters = [],
@@ -77,6 +78,16 @@ export const ChapterActionMenuItems = ({
const isSingleMode = !!chapter;
const { isDownloaded, isRead, isBookmarked } = chapter ?? {};
const mangaChaptersResponse = requestManager.useGetMangaChapters<GetChaptersMangaQuery>(
GET_CHAPTERS_MANGA,
chapter?.mangaId ?? -1,
{
skip: !chapter,
fetchPolicy: 'cache-only',
},
);
const allChapters = mangaChaptersResponse.data?.chapters.nodes ?? [];
const {
settings: { deleteChaptersWithBookmark },
} = useMetadataServerSettings();

View File

@@ -17,7 +17,7 @@ import CardContent from '@mui/material/CardContent';
import IconButton from '@mui/material/IconButton';
import { useTheme } from '@mui/material/styles';
import Typography from '@mui/material/Typography';
import React, { MouseEvent, TouchEvent, useRef } from 'react';
import React, { memo, MouseEvent, TouchEvent, useRef } from 'react';
import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state';
@@ -51,15 +51,14 @@ type TChapter = ChapterIdInfo &
interface IProps {
mode?: 'manga.page' | 'reader';
chapter: TChapter;
allChapters: TChapter[];
showChapterNumber: boolean;
onSelect: (selected: boolean, isShiftKey?: boolean) => void;
onSelect: (id: number, selected: boolean, isShiftKey?: boolean) => void;
selected: boolean | null;
selectable?: boolean;
isActiveChapter?: boolean; // reader
}
export const ChapterCard: React.FC<IProps> = (props: IProps) => {
export const ChapterCard = memo((props: IProps) => {
const { t } = useTranslation();
const theme = useTheme();
@@ -68,7 +67,6 @@ export const ChapterCard: React.FC<IProps> = (props: IProps) => {
const {
mode = 'manga.page',
chapter,
allChapters,
showChapterNumber,
onSelect,
selected,
@@ -84,7 +82,7 @@ export const ChapterCard: React.FC<IProps> = (props: IProps) => {
event.preventDefault();
event.stopPropagation();
onSelect(!selected, event.shiftKey);
onSelect(chapter.id, !selected, event.shiftKey);
};
const handleClickOpenMenu = (
@@ -204,8 +202,7 @@ export const ChapterCard: React.FC<IProps> = (props: IProps) => {
<ChapterActionMenuItems
onClose={onClose}
chapter={chapter}
allChapters={allChapters}
handleSelection={() => onSelect(true)}
handleSelection={() => onSelect(chapter.id, true)}
canBeDownloaded={Chapters.isDownloadable(chapter)}
selectable={selectable}
/>
@@ -216,4 +213,4 @@ export const ChapterCard: React.FC<IProps> = (props: IProps) => {
)}
</PopupState>
);
};
});

View File

@@ -11,6 +11,8 @@ import { useMemo } from 'react';
import { ChapterCard } from '@/modules/chapter/components/cards/ChapterCard.tsx';
import { ReaderStateChapters } from '@/modules/reader/types/Reader.types.ts';
const onSelectNoop = () => {};
export const ReaderChapterList = ({
currentChapter,
chapters,
@@ -35,10 +37,9 @@ export const ReaderChapterList = ({
key={chapters[index].id}
mode="reader"
chapter={chapters[index]}
allChapters={chapters}
showChapterNumber={false}
selected={null}
onSelect={() => undefined}
onSelect={onSelectNoop}
selectable={false}
isActiveChapter={index === currentChapterIndex}
/>