From 3d514d357a8c514a46ce08032470742b67047567 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Fri, 8 May 2026 15:19:26 +0200 Subject: [PATCH] Optionally ignore outdated matches during bulk migration --- src/features/migration/Migration.constants.ts | 5 ++++ src/features/migration/Migration.types.ts | 2 ++ src/features/migration/MigrationManager.ts | 14 ++++++++--- .../MigrationBulkSearchOptionsDialog.tsx | 25 +++++++++++++++++++ .../migration/screens/MigrationExecute.tsx | 13 ++++++++++ .../migration/screens/MigrationSearch.tsx | 13 ++++++++++ src/i18n/locales/en.po | 18 +++++++++++++ 7 files changed, 87 insertions(+), 3 deletions(-) diff --git a/src/features/migration/Migration.constants.ts b/src/features/migration/Migration.constants.ts index 3a2721fb..83bb28ea 100644 --- a/src/features/migration/Migration.constants.ts +++ b/src/features/migration/Migration.constants.ts @@ -52,6 +52,7 @@ export const ENTRY_STATUS_TRANSLATION: Record { - const { selectHighestChapterNumberSource } = options; + const { selectHighestChapterNumberSource, ignoreOutdatedMatches } = options; const state = MigrationManager.getState(); const entry = state.entries[mangaId]; @@ -837,6 +838,7 @@ export class MigrationManager { destSourceId, ); + const ignoreOutdatedMatch = ignoreOutdatedMatches && !hasNewerChapter; const isPreferredSourcePriorityMatch = hasHigherSourcePriority && !selectHighestChapterNumberSource; const isPreferredChapterNumberMatch = @@ -845,7 +847,8 @@ export class MigrationManager { (hasHigherSourcePriority && hasSameLatestChapterAsSelectedMatch) || !draftMatchEntry); - const isPreferredMatch = isPreferredSourcePriorityMatch || isPreferredChapterNumberMatch; + const isPreferredMatch = + !ignoreOutdatedMatch && (isPreferredSourcePriorityMatch || isPreferredChapterNumberMatch); if (isPreferredMatch) { draftEntry.selectedMatchMangaId = bestMatch.id; draftEntry.selectedMatchSourceId = destSourceId; @@ -873,7 +876,12 @@ export class MigrationManager { if (draftEntry.searchMatches.length) { draft.searchProgress.success += 1; - draftEntry.status = MigrationEntryStatus.SEARCH_COMPLETE; + + if (draftEntry.selectedMatchMangaId != null) { + draftEntry.status = MigrationEntryStatus.SEARCH_COMPLETE; + } else { + draftEntry.status = MigrationEntryStatus.OUTDATED; + } } else { draftEntry.status = MigrationEntryStatus.NO_MATCH; } diff --git a/src/features/migration/components/MigrationBulkSearchOptionsDialog.tsx b/src/features/migration/components/MigrationBulkSearchOptionsDialog.tsx index ad18e394..cdd6e097 100644 --- a/src/features/migration/components/MigrationBulkSearchOptionsDialog.tsx +++ b/src/features/migration/components/MigrationBulkSearchOptionsDialog.tsx @@ -29,10 +29,34 @@ export const MigrationBulkSearchOptionsDialog = ({ const { t } = useLingui(); const [selectHighestChapterNumberSource, setSelectHighestChapterNumberSource] = useState(false); + const [ignoreOutdatedMatches, setIgnoreOutdatesMatches] = useState(false); return ( {t`Search options`} + + + {t`Ignore matches without newer chapters`} + {t`Do not automatically select matches if they are behind the current source. They will still be shown in the found matches`} + + } + sx={{ + alignItems: 'start', + }} + checked={ignoreOutdatedMatches} + onChange={(_, checked) => setIgnoreOutdatesMatches(checked)} + /> + onSubmit({ selectHighestChapterNumberSource, + ignoreOutdatedMatches, }) } > diff --git a/src/features/migration/screens/MigrationExecute.tsx b/src/features/migration/screens/MigrationExecute.tsx index 722818e1..1ab18ab7 100644 --- a/src/features/migration/screens/MigrationExecute.tsx +++ b/src/features/migration/screens/MigrationExecute.tsx @@ -60,6 +60,10 @@ export const MigrationExecute = () => { () => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH), [entryList], ); + const outdatedEntries = useMemo( + () => entryList.filter((entry) => entry.status === MigrationEntryStatus.OUTDATED), + [entryList], + ); return ( <> @@ -102,6 +106,15 @@ export const MigrationExecute = () => { color="warning" isMigrating /> + { () => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH), [entryList], ); + const outdatedEntries = useMemo( + () => entryList.filter((entry) => entry.status === MigrationEntryStatus.OUTDATED), + [entryList], + ); const matchedEntries = useMemo( () => entryList.filter((entry) => entry.status === MigrationEntryStatus.SEARCH_COMPLETE), [entryList], @@ -103,6 +107,15 @@ export const MigrationSearch = () => { entries={noMatchEntries} color="warning" /> +