From 0b278ff525172ebe574eac3af867a75b14c2a6c6 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Thu, 28 May 2026 01:31:23 +0200 Subject: [PATCH] Add bulk migration in library indicator closes #1109 --- CHANGELOG.md | 1 + src/features/manga/Manga.types.ts | 4 +- .../manga/components/MangaActionMenuItems.tsx | 8 ++- src/features/migration/Migration.types.ts | 10 ++- src/features/migration/MigrationManager.ts | 2 + .../MigrationDestinationEntry.tsx | 19 +----- .../MigrationEntryThumbnail.tsx | 68 +++++++++++++++++++ .../migration-entry/MigrationMatchedEntry.tsx | 23 +------ src/i18n/locales/en.po | 1 + 9 files changed, 94 insertions(+), 42 deletions(-) create mode 100644 src/features/migration/components/migration-entry/MigrationEntryThumbnail.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index df14f4c6..49a80fa1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Migration**) Add a search option to ignore matches with missing chapters - (**Migration**) Add "local source" as a possible destination source - (**Migration**) Add option to abort entries that are searching or are waiting to get migrated +- (**Migration**) Add "in library" indicator ### Changed diff --git a/src/features/manga/Manga.types.ts b/src/features/manga/Manga.types.ts index 628d13ba..add823a4 100644 --- a/src/features/manga/Manga.types.ts +++ b/src/features/manga/Manga.types.ts @@ -32,9 +32,9 @@ import type { export type MangaCardMode = 'default' | 'source' | 'migrate.select.bulk' | 'migrate.select.single' | 'duplicate'; -type MangaCardBaseProps = Pick & +type MangaCardBaseProps = Pick & Omit & - Partial> & { + Partial> & { firstUnreadChapter?: | (ChapterIdInfo & ChapterSourceOrderInfo & ChapterReadInfo & ChapterNumberInfo & ChapterNameInfo) | null; diff --git a/src/features/manga/components/MangaActionMenuItems.tsx b/src/features/manga/components/MangaActionMenuItems.tsx index 38caa7cf..a4cd7bc5 100644 --- a/src/features/manga/components/MangaActionMenuItems.tsx +++ b/src/features/manga/components/MangaActionMenuItems.tsx @@ -36,6 +36,7 @@ import type { MangaAction, MangaDownloadInfo, MangaIdInfo, + MangaInLibraryInfo, MangaSourceIdInfo, MangaTitleInfo, MangaUnreadInfo, @@ -47,7 +48,12 @@ import { STABLE_EMPTY_ARRAY } from '@/base/Base.constants.ts'; type BaseProps = { onClose: () => void; setHideMenu: (hide: boolean) => void }; export type SingleModeProps = { - manga: MangaIdInfo & MangaTitleInfo & MangaSourceIdInfo & MangaDownloadInfo & MangaUnreadInfo; + manga: MangaIdInfo & + MangaTitleInfo & + MangaSourceIdInfo & + MangaDownloadInfo & + MangaUnreadInfo & + Pick; handleSelection?: SelectableCollectionReturnType['handleSelection']; }; diff --git a/src/features/migration/Migration.types.ts b/src/features/migration/Migration.types.ts index 53d70981..53adda3d 100644 --- a/src/features/migration/Migration.types.ts +++ b/src/features/migration/Migration.types.ts @@ -23,6 +23,7 @@ import type { MangaArtistInfo, MangaAuthorInfo, MangaIdInfo, + MangaInLibraryInfo, MangaSourceIdInfo, MangaThumbnailInfo, MangaTitleInfo, @@ -102,7 +103,14 @@ export enum MigrationEntryStatus { } export interface MigrationMatch - extends MangaIdInfo, MangaTitleInfo, MangaThumbnailInfo, MangaSourceIdInfo, MangaArtistInfo, MangaAuthorInfo { + extends + MangaIdInfo, + MangaTitleInfo, + MangaThumbnailInfo, + MangaSourceIdInfo, + MangaArtistInfo, + MangaAuthorInfo, + Pick { sourceTitle: SourceDisplayNameInfo['displayName'] | undefined; latestChapterNumber: ChapterNumberInfo['chapterNumber'] | undefined; missingChapters: number | undefined; diff --git a/src/features/migration/MigrationManager.ts b/src/features/migration/MigrationManager.ts index eb112261..358ee79b 100644 --- a/src/features/migration/MigrationManager.ts +++ b/src/features/migration/MigrationManager.ts @@ -249,6 +249,7 @@ export class MigrationManager { sourceTitle: cachedEntry?.source?.displayName ?? searchMatch.sourceTitle, latestChapterNumber: cachedEntry?.highestNumberedChapter?.chapterNumber ?? searchMatch.latestChapterNumber, missingChapters: searchMatch.missingChapters, + inLibrary: cachedEntry?.inLibrary ?? searchMatch.inLibrary, }; } @@ -955,6 +956,7 @@ export class MigrationManager { sourceId: manga.sourceId, sourceTitle: manga.source?.displayName, missingChapters: chapters ? Chapters.getMissingCount(chapters) : undefined, + inLibrary: manga.inLibrary, })); draftEntry.destSourceIdToSearchState[destSourceId] = true; diff --git a/src/features/migration/components/migration-entry/MigrationDestinationEntry.tsx b/src/features/migration/components/migration-entry/MigrationDestinationEntry.tsx index 3fe9b094..321aa6c2 100644 --- a/src/features/migration/components/migration-entry/MigrationDestinationEntry.tsx +++ b/src/features/migration/components/migration-entry/MigrationDestinationEntry.tsx @@ -18,8 +18,6 @@ import { MigrationManager } from '@/features/migration/MigrationManager.ts'; import { extractGraphqlExceptionInfo } from '@/lib/HelperFunctions.ts'; import { Confirmation } from '@/base/AppAwaitableComponent.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { ListCardAvatar } from '@/base/components/lists/cards/ListCardAvatar.tsx'; -import { Mangas } from '@/features/manga/services/Mangas.ts'; import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx'; import { MigrationEntryMetadataText } from '@/features/migration/components/migration-entry/MigrationEntryMetadataText.tsx'; import Typography from '@mui/material/Typography'; @@ -36,6 +34,7 @@ import Link from '@mui/material/Link'; import { Link as RouterLink } from 'react-router-dom'; import { useTheme } from '@mui/material/styles'; import { applyStyles } from '@/base/utils/ApplyStyles.ts'; +import { MigrationEntryThumbnail } from '@/features/migration/components/migration-entry/MigrationEntryThumbnail.tsx'; const EntryStatus = ({ sourceMangaId, @@ -153,21 +152,7 @@ const EntryData = (entry: MigrationMatch) => { return ( <> - - - + ['height']; +}) => { + const { id, title } = entry; + + const { t } = useLingui(); + + return ( + + e.stopPropagation()}> + + + {entry.inLibrary && ( + + + + + + )} + + ); +}; diff --git a/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx b/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx index 901c5da0..fcb89db0 100644 --- a/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx +++ b/src/features/migration/components/migration-entry/MigrationMatchedEntry.tsx @@ -12,8 +12,6 @@ import { MigrationEntryCard } from '@/features/migration/components/migration-en import { MigrationManager } from '@/features/migration/MigrationManager.ts'; import { MigrationEntryCardContent } from '@/features/migration/components/migration-entry/MigrationEntryCardContent.tsx'; import { AppRoutes } from '@/base/AppRoute.constants.ts'; -import { ListCardAvatar } from '@/base/components/lists/cards/ListCardAvatar.tsx'; -import { Mangas } from '@/features/manga/services/Mangas.ts'; import { TypographyMaxLines } from '@/base/components/texts/TypographyMaxLines.tsx'; import { MigrationEntryMetadataText } from '@/features/migration/components/migration-entry/MigrationEntryMetadataText.tsx'; import { MUIUtil } from '@/lib/mui/MUI.util.ts'; @@ -25,6 +23,7 @@ import CardActionArea from '@mui/material/CardActionArea'; import Link from '@mui/material/Link'; import { Link as RouterLink } from 'react-router-dom'; import { memo } from 'react'; +import { MigrationEntryThumbnail } from '@/features/migration/components/migration-entry/MigrationEntryThumbnail.tsx'; export const MigrationMatchedEntry = memo( ({ sourceMangaId, entry }: { sourceMangaId: MangaIdInfo['id']; entry: MigrationMatch }) => { @@ -36,25 +35,7 @@ export const MigrationMatchedEntry = memo( {(() => ( <> - e.stopPropagation()} - > - - + {entry.sourceTitle} diff --git a/src/i18n/locales/en.po b/src/i18n/locales/en.po index 7cafb5f1..9333bea1 100644 --- a/src/i18n/locales/en.po +++ b/src/i18n/locales/en.po @@ -1915,6 +1915,7 @@ msgstr "" #: src/features/manga/components/details/MangaDetails.tsx #: src/features/manga/components/MangaBadges.tsx +#: src/features/migration/components/migration-entry/MigrationEntryThumbnail.tsx msgid "In Library" msgstr "In Library"