2025-01-12 15:02:33 +01:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) Contributors to the Suwayomi project
|
|
|
|
|
*
|
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import Box from '@mui/material/Box';
|
|
|
|
|
import CardActionArea from '@mui/material/CardActionArea';
|
|
|
|
|
import Card from '@mui/material/Card';
|
2025-03-10 23:10:28 +01:00
|
|
|
import { Link } from 'react-router-dom';
|
2026-07-05 18:55:09 +02:00
|
|
|
import { memo, useMemo } from 'react';
|
2025-08-16 02:48:46 +02:00
|
|
|
import { DownloadStateIndicator } from '@/base/components/downloads/DownloadStateIndicator.tsx';
|
2026-03-11 00:11:29 +01:00
|
|
|
import type { ChapterUpdateListFieldsFragment } from '@/lib/graphql/generated/graphql.ts';
|
2025-08-16 02:48:46 +02:00
|
|
|
import { AppRoutes } from '@/base/AppRoute.constants.ts';
|
2025-08-15 22:02:58 +02:00
|
|
|
import { ChapterCardThumbnail } from '@/features/chapter/components/cards/ChapterCardThumbnail.tsx';
|
|
|
|
|
import { ChapterCardMetadata } from '@/features/chapter/components/cards/ChapterCardMetadata.tsx';
|
|
|
|
|
import { ChapterDownloadButton } from '@/features/chapter/components/buttons/ChapterDownloadButton.tsx';
|
|
|
|
|
import { ChapterDownloadRetryButton } from '@/features/chapter/components/buttons/ChapterDownloadRetryButton.tsx';
|
|
|
|
|
import { Chapters } from '@/features/chapter/services/Chapters.ts';
|
2025-08-16 02:48:46 +02:00
|
|
|
import { ListCardContent } from '@/base/components/lists/cards/ListCardContent.tsx';
|
2026-07-05 18:55:09 +02:00
|
|
|
import { useLingui } from '@lingui/react/macro';
|
|
|
|
|
import { plural } from '@lingui/core/macro';
|
2025-01-12 15:02:33 +01:00
|
|
|
|
2026-07-05 18:55:09 +02:00
|
|
|
export const ChapterUpdateCard = memo(
|
|
|
|
|
({
|
|
|
|
|
chapter,
|
|
|
|
|
otherChapters,
|
|
|
|
|
}: {
|
|
|
|
|
chapter: ChapterUpdateListFieldsFragment;
|
|
|
|
|
otherChapters: ChapterUpdateListFieldsFragment[];
|
|
|
|
|
}) => {
|
|
|
|
|
const { manga } = chapter;
|
|
|
|
|
|
|
|
|
|
const { t } = useLingui();
|
|
|
|
|
|
|
|
|
|
const uniqueOtherChapters = useMemo(
|
|
|
|
|
() => Chapters.removeDuplicates(chapter, otherChapters),
|
|
|
|
|
[chapter, otherChapters],
|
|
|
|
|
);
|
|
|
|
|
const otherChaptersCount = uniqueOtherChapters.length;
|
|
|
|
|
const firstFewOtherChapters = uniqueOtherChapters.slice(-3);
|
|
|
|
|
|
|
|
|
|
const otherChaptersText = (() => {
|
|
|
|
|
if (!otherChaptersCount) {
|
|
|
|
|
return '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const firstFewUpdatesString = firstFewOtherChapters
|
|
|
|
|
.map((otherChapter) => `#${otherChapter.chapterNumber}`)
|
|
|
|
|
.toReversed()
|
|
|
|
|
.join(', ');
|
|
|
|
|
|
|
|
|
|
if (otherChaptersCount > firstFewOtherChapters.length) {
|
|
|
|
|
const remainingUpdatesCount = otherChaptersCount - firstFewOtherChapters.length;
|
|
|
|
|
|
|
|
|
|
return t`Plus chapters ${firstFewUpdatesString} and ${remainingUpdatesCount} more`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return plural(firstFewOtherChapters.length, {
|
|
|
|
|
one: `Plus chapter ${firstFewUpdatesString}`,
|
|
|
|
|
other: `Plus chapters ${firstFewUpdatesString}`,
|
|
|
|
|
});
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Card>
|
|
|
|
|
<CardActionArea
|
|
|
|
|
component={Link}
|
|
|
|
|
to={AppRoutes.reader.path(chapter.manga.id, chapter.sourceOrder)}
|
|
|
|
|
state={Chapters.getReaderOpenChapterLocationState(chapter)}
|
|
|
|
|
sx={{
|
|
|
|
|
color: (theme) => theme.palette.text[chapter.isRead ? 'disabled' : 'primary'],
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<ListCardContent sx={{ justifyContent: 'space-between' }}>
|
|
|
|
|
<Box sx={{ display: 'flex', flexGrow: 1, gap: 1 }}>
|
|
|
|
|
<ChapterCardThumbnail
|
|
|
|
|
mangaId={manga.id}
|
|
|
|
|
sourceId={manga.sourceId}
|
|
|
|
|
mangaTitle={manga.title}
|
|
|
|
|
thumbnailUrl={manga.thumbnailUrl}
|
|
|
|
|
thumbnailUrlLastFetched={manga.thumbnailUrlLastFetched}
|
|
|
|
|
/>
|
|
|
|
|
<ChapterCardMetadata
|
|
|
|
|
title={manga.title}
|
|
|
|
|
secondaryText={chapter.name}
|
|
|
|
|
ternaryText={otherChaptersText}
|
|
|
|
|
/>
|
|
|
|
|
</Box>
|
|
|
|
|
<DownloadStateIndicator chapterId={chapter.id} />
|
|
|
|
|
<ChapterDownloadRetryButton chapterId={chapter.id} />
|
|
|
|
|
<ChapterDownloadButton chapterId={chapter.id} isDownloaded={chapter.isDownloaded} />
|
|
|
|
|
</ListCardContent>
|
|
|
|
|
</CardActionArea>
|
|
|
|
|
</Card>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
);
|