From 85cec6fd8d62036df56a7d6b44c48404dd19050d Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Sat, 5 Jul 2025 17:15:28 +0200 Subject: [PATCH] Use filtered chapters for none manga bulk downloads For multiple manga it's not feasible to filter the chapters based on the active chapter list options. fixes #980 --- .../ChaptersDownloadActionMenuItems.tsx | 92 +++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/src/modules/chapter/components/actions/ChaptersDownloadActionMenuItems.tsx b/src/modules/chapter/components/actions/ChaptersDownloadActionMenuItems.tsx index 894f9f4c..f9475a3c 100644 --- a/src/modules/chapter/components/actions/ChaptersDownloadActionMenuItems.tsx +++ b/src/modules/chapter/components/actions/ChaptersDownloadActionMenuItems.tsx @@ -8,11 +8,27 @@ import MenuItem from '@mui/material/MenuItem'; import { useTranslation } from 'react-i18next'; +import gql from 'graphql-tag'; import { useMetadataServerSettings } from '@/modules/settings/services/ServerSettingsMetadata.ts'; import { Mangas } from '@/modules/manga/services/Mangas.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { MangaType } from '@/lib/graphql/generated/graphql.ts'; +import { + ChapterOrderBy, + GetChaptersMangaQuery, + GetChaptersMangaQueryVariables, + MangaType, + SortOrder, +} from '@/lib/graphql/generated/graphql.ts'; import { TranslationKey } from '@/Base.types.ts'; +import { MANGA_META_FIELDS } from '@/lib/graphql/fragments/MangaFragments.ts'; +import { getMangaMetadata } from '@/modules/manga/services/MangaMetadata.ts'; +import { requestManager } from '@/lib/requests/RequestManager.ts'; +import { GET_CHAPTERS_MANGA } from '@/lib/graphql/queries/ChapterQuery.ts'; +import { filterChapters } from '@/modules/chapter/utils/ChapterList.util.tsx'; +import { Chapters } from '@/modules/chapter/services/Chapters.ts'; +import { makeToast } from '@/modules/core/utils/Toast.ts'; +import { CHAPTER_ACTION_TO_TRANSLATION } from '@/modules/chapter/Chapter.constants.ts'; +import { getErrorMessage } from '@/lib/HelperFunctions.ts'; const DOWNLOAD_OPTIONS: { title: TranslationKey; @@ -32,6 +48,65 @@ const DOWNLOAD_OPTIONS: { { title: 'chapter.action.download.add.label.all', getCount: () => undefined, onlyUnread: false }, ]; +const handleDownload = async ( + mangaIds: MangaType['id'][], + onlyUnread: boolean, + size: number | undefined, + downloadAhead: boolean, +): Promise => { + const isMultiMangaManga = mangaIds.length > 1; + if (isMultiMangaManga) { + Mangas.performAction('download', mangaIds, { + downloadAhead, + onlyUnread, + size, + }).catch(defaultPromiseErrorHandler('ChaptersDownloadActionMenuItems::handleSelect:multiMangaMode')); + return; + } + + const mangaId = mangaIds[0]; + const manga = Mangas.getFromCache( + mangaId, + gql` + ${MANGA_META_FIELDS} + fragment MangaInLibraryState on MangaType { + id + meta { + ...MANGA_META_FIELDS + } + } + `, + 'MangaInLibraryState', + )!; + const meta = getMangaMetadata(manga); + const chapters = await requestManager.getChapters( + GET_CHAPTERS_MANGA, + { + condition: { mangaId: Number(mangaId) }, + order: [{ by: ChapterOrderBy.SourceOrder, byType: SortOrder.Desc }], + }, + ).response; + + const filteredChapters = filterChapters(chapters.data.chapters.nodes, meta); + const chaptersToDownload = filteredChapters + .filter((chapter) => { + if (onlyUnread && chapter.isRead) { + return false; + } + + return !chapter.isDownloaded; + }) + .slice(0, size); + + if (!chaptersToDownload.length) { + return; + } + + Chapters.performAction('download', Chapters.getIds(chaptersToDownload), {}).catch( + defaultPromiseErrorHandler('ChaptersDownloadActionMenuItems::handleSelect::singleMangaMode'), + ); +}; + export const ChaptersDownloadActionMenuItems = ({ mangaIds, closeMenu, @@ -46,11 +121,16 @@ export const ChaptersDownloadActionMenuItems = ({ } = useMetadataServerSettings(); const handleSelect = (size?: number, onlyUnread: boolean = true, downloadAhead: boolean = false) => { - Mangas.performAction('download', mangaIds, { - downloadAhead, - onlyUnread, - size, - }).catch(defaultPromiseErrorHandler('ChaptersDownloadActionMenuItems::handleSelect')); + handleDownload(mangaIds, onlyUnread, size, downloadAhead).catch((e) => + makeToast( + t(CHAPTER_ACTION_TO_TRANSLATION.download.error, { + count: size, + }), + 'error', + getErrorMessage(e), + ), + ); + closeMenu?.(); };