Optionally ignore outdated matches during bulk migration
This commit is contained in:
@@ -52,6 +52,7 @@ export const ENTRY_STATUS_TRANSLATION: Record<MigrationEntryStatus, MessageDescr
|
|||||||
[MigrationEntryStatus.SEARCH_COMPLETE]: msg`Match found`,
|
[MigrationEntryStatus.SEARCH_COMPLETE]: msg`Match found`,
|
||||||
[MigrationEntryStatus.SEARCH_FAILED]: msg`Search failed`,
|
[MigrationEntryStatus.SEARCH_FAILED]: msg`Search failed`,
|
||||||
[MigrationEntryStatus.NO_MATCH]: msg`No match found`,
|
[MigrationEntryStatus.NO_MATCH]: msg`No match found`,
|
||||||
|
[MigrationEntryStatus.OUTDATED]: msg`Only outdated matches found`,
|
||||||
[MigrationEntryStatus.MIGRATING]: msg`Migrating…`,
|
[MigrationEntryStatus.MIGRATING]: msg`Migrating…`,
|
||||||
[MigrationEntryStatus.MIGRATION_COMPLETE]: msg`Successfully migrated`,
|
[MigrationEntryStatus.MIGRATION_COMPLETE]: msg`Successfully migrated`,
|
||||||
[MigrationEntryStatus.MIGRATION_FAILED]: msg`Migration failed`,
|
[MigrationEntryStatus.MIGRATION_FAILED]: msg`Migration failed`,
|
||||||
@@ -62,6 +63,7 @@ export const MIGRATE_SEARCH_ENTRY_GROUPS = [
|
|||||||
MigrationEntryStatus.SEARCHING,
|
MigrationEntryStatus.SEARCHING,
|
||||||
MigrationEntryStatus.SEARCH_FAILED,
|
MigrationEntryStatus.SEARCH_FAILED,
|
||||||
MigrationEntryStatus.NO_MATCH,
|
MigrationEntryStatus.NO_MATCH,
|
||||||
|
MigrationEntryStatus.OUTDATED,
|
||||||
MigrationEntryStatus.SEARCH_COMPLETE,
|
MigrationEntryStatus.SEARCH_COMPLETE,
|
||||||
] as const satisfies readonly MigrationEntryStatus[];
|
] as const satisfies readonly MigrationEntryStatus[];
|
||||||
|
|
||||||
@@ -72,6 +74,7 @@ export const MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE: Record<
|
|||||||
[MigrationEntryStatus.SEARCHING]: true,
|
[MigrationEntryStatus.SEARCHING]: true,
|
||||||
[MigrationEntryStatus.SEARCH_FAILED]: false,
|
[MigrationEntryStatus.SEARCH_FAILED]: false,
|
||||||
[MigrationEntryStatus.NO_MATCH]: false,
|
[MigrationEntryStatus.NO_MATCH]: false,
|
||||||
|
[MigrationEntryStatus.OUTDATED]: false,
|
||||||
[MigrationEntryStatus.SEARCH_COMPLETE]: false,
|
[MigrationEntryStatus.SEARCH_COMPLETE]: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,6 +82,7 @@ export const MIGRATE_EXECUTE_ENTRY_GROUPS = [
|
|||||||
MigrationEntryStatus.MIGRATING,
|
MigrationEntryStatus.MIGRATING,
|
||||||
MigrationEntryStatus.MIGRATION_FAILED,
|
MigrationEntryStatus.MIGRATION_FAILED,
|
||||||
MigrationEntryStatus.NO_MATCH,
|
MigrationEntryStatus.NO_MATCH,
|
||||||
|
MigrationEntryStatus.OUTDATED,
|
||||||
MigrationEntryStatus.EXCLUDED,
|
MigrationEntryStatus.EXCLUDED,
|
||||||
MigrationEntryStatus.MIGRATION_COMPLETE,
|
MigrationEntryStatus.MIGRATION_COMPLETE,
|
||||||
] as const satisfies readonly MigrationEntryStatus[];
|
] as const satisfies readonly MigrationEntryStatus[];
|
||||||
@@ -90,6 +94,7 @@ export const MIGRATE_EXECUTE_ENTRY_GROUP_EXPAND_DEFAULT_STATE: Record<
|
|||||||
[MigrationEntryStatus.MIGRATING]: true,
|
[MigrationEntryStatus.MIGRATING]: true,
|
||||||
[MigrationEntryStatus.MIGRATION_FAILED]: false,
|
[MigrationEntryStatus.MIGRATION_FAILED]: false,
|
||||||
[MigrationEntryStatus.NO_MATCH]: false,
|
[MigrationEntryStatus.NO_MATCH]: false,
|
||||||
|
[MigrationEntryStatus.OUTDATED]: false,
|
||||||
[MigrationEntryStatus.EXCLUDED]: false,
|
[MigrationEntryStatus.EXCLUDED]: false,
|
||||||
[MigrationEntryStatus.MIGRATION_COMPLETE]: false,
|
[MigrationEntryStatus.MIGRATION_COMPLETE]: false,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export type MetadataMigrationSettings = {
|
|||||||
|
|
||||||
export interface MigrationBulkSearchSettings {
|
export interface MigrationBulkSearchSettings {
|
||||||
selectHighestChapterNumberSource: boolean;
|
selectHighestChapterNumberSource: boolean;
|
||||||
|
ignoreOutdatedMatches: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum MigrationPhase {
|
export enum MigrationPhase {
|
||||||
@@ -76,6 +77,7 @@ export enum MigrationEntryStatus {
|
|||||||
SEARCHING = 'searching',
|
SEARCHING = 'searching',
|
||||||
SEARCH_COMPLETE = 'search_complete',
|
SEARCH_COMPLETE = 'search_complete',
|
||||||
SEARCH_FAILED = 'search_failed',
|
SEARCH_FAILED = 'search_failed',
|
||||||
|
OUTDATED = 'outdated',
|
||||||
NO_MATCH = 'no_match',
|
NO_MATCH = 'no_match',
|
||||||
MIGRATING = 'migrating',
|
MIGRATING = 'migrating',
|
||||||
MIGRATION_COMPLETE = 'migration_complete',
|
MIGRATION_COMPLETE = 'migration_complete',
|
||||||
|
|||||||
@@ -378,6 +378,7 @@ export class MigrationManager {
|
|||||||
...MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE,
|
...MIGRATE_SEARCH_ENTRY_GROUP_EXPAND_DEFAULT_STATE,
|
||||||
[MigrationEntryStatus.SEARCHING]: false,
|
[MigrationEntryStatus.SEARCHING]: false,
|
||||||
[MigrationEntryStatus.NO_MATCH]: !allSearchesFailed && !searchProgress.success,
|
[MigrationEntryStatus.NO_MATCH]: !allSearchesFailed && !searchProgress.success,
|
||||||
|
[MigrationEntryStatus.OUTDATED]: !allSearchesFailed && !searchProgress.success,
|
||||||
[MigrationEntryStatus.SEARCH_FAILED]: allSearchesFailed,
|
[MigrationEntryStatus.SEARCH_FAILED]: allSearchesFailed,
|
||||||
[MigrationEntryStatus.SEARCH_COMPLETE]: !!searchProgress.success,
|
[MigrationEntryStatus.SEARCH_COMPLETE]: !!searchProgress.success,
|
||||||
};
|
};
|
||||||
@@ -730,7 +731,7 @@ export class MigrationManager {
|
|||||||
mainSignal: AbortSignal,
|
mainSignal: AbortSignal,
|
||||||
options: MigrationBulkSearchSettings,
|
options: MigrationBulkSearchSettings,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const { selectHighestChapterNumberSource } = options;
|
const { selectHighestChapterNumberSource, ignoreOutdatedMatches } = options;
|
||||||
|
|
||||||
const state = MigrationManager.getState();
|
const state = MigrationManager.getState();
|
||||||
const entry = state.entries[mangaId];
|
const entry = state.entries[mangaId];
|
||||||
@@ -837,6 +838,7 @@ export class MigrationManager {
|
|||||||
destSourceId,
|
destSourceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ignoreOutdatedMatch = ignoreOutdatedMatches && !hasNewerChapter;
|
||||||
const isPreferredSourcePriorityMatch =
|
const isPreferredSourcePriorityMatch =
|
||||||
hasHigherSourcePriority && !selectHighestChapterNumberSource;
|
hasHigherSourcePriority && !selectHighestChapterNumberSource;
|
||||||
const isPreferredChapterNumberMatch =
|
const isPreferredChapterNumberMatch =
|
||||||
@@ -845,7 +847,8 @@ export class MigrationManager {
|
|||||||
(hasHigherSourcePriority && hasSameLatestChapterAsSelectedMatch) ||
|
(hasHigherSourcePriority && hasSameLatestChapterAsSelectedMatch) ||
|
||||||
!draftMatchEntry);
|
!draftMatchEntry);
|
||||||
|
|
||||||
const isPreferredMatch = isPreferredSourcePriorityMatch || isPreferredChapterNumberMatch;
|
const isPreferredMatch =
|
||||||
|
!ignoreOutdatedMatch && (isPreferredSourcePriorityMatch || isPreferredChapterNumberMatch);
|
||||||
if (isPreferredMatch) {
|
if (isPreferredMatch) {
|
||||||
draftEntry.selectedMatchMangaId = bestMatch.id;
|
draftEntry.selectedMatchMangaId = bestMatch.id;
|
||||||
draftEntry.selectedMatchSourceId = destSourceId;
|
draftEntry.selectedMatchSourceId = destSourceId;
|
||||||
@@ -873,7 +876,12 @@ export class MigrationManager {
|
|||||||
|
|
||||||
if (draftEntry.searchMatches.length) {
|
if (draftEntry.searchMatches.length) {
|
||||||
draft.searchProgress.success += 1;
|
draft.searchProgress.success += 1;
|
||||||
|
|
||||||
|
if (draftEntry.selectedMatchMangaId != null) {
|
||||||
draftEntry.status = MigrationEntryStatus.SEARCH_COMPLETE;
|
draftEntry.status = MigrationEntryStatus.SEARCH_COMPLETE;
|
||||||
|
} else {
|
||||||
|
draftEntry.status = MigrationEntryStatus.OUTDATED;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
draftEntry.status = MigrationEntryStatus.NO_MATCH;
|
draftEntry.status = MigrationEntryStatus.NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,34 @@ export const MigrationBulkSearchOptionsDialog = ({
|
|||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
|
|
||||||
const [selectHighestChapterNumberSource, setSelectHighestChapterNumberSource] = useState(false);
|
const [selectHighestChapterNumberSource, setSelectHighestChapterNumberSource] = useState(false);
|
||||||
|
const [ignoreOutdatedMatches, setIgnoreOutdatesMatches] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={isVisible} fullWidth onClose={onDismiss} onTransitionExited={onExitComplete}>
|
<Dialog open={isVisible} fullWidth onClose={onDismiss} onTransitionExited={onExitComplete}>
|
||||||
<DialogTitle>{t`Search options`}</DialogTitle>
|
<DialogTitle>{t`Search options`}</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<CheckboxInput
|
||||||
|
label={
|
||||||
|
<Stack
|
||||||
|
sx={{
|
||||||
|
// Padding comes from the MUI Checkbox component
|
||||||
|
pt: '9px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography>{t`Ignore matches without newer chapters`}</Typography>
|
||||||
|
<Typography
|
||||||
|
variant="body2"
|
||||||
|
color="textSecondary"
|
||||||
|
>{t`Do not automatically select matches if they are behind the current source. They will still be shown in the found matches`}</Typography>
|
||||||
|
</Stack>
|
||||||
|
}
|
||||||
|
sx={{
|
||||||
|
alignItems: 'start',
|
||||||
|
}}
|
||||||
|
checked={ignoreOutdatedMatches}
|
||||||
|
onChange={(_, checked) => setIgnoreOutdatesMatches(checked)}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Stack
|
<Stack
|
||||||
direction="row"
|
direction="row"
|
||||||
@@ -82,6 +106,7 @@ export const MigrationBulkSearchOptionsDialog = ({
|
|||||||
onClick={() =>
|
onClick={() =>
|
||||||
onSubmit({
|
onSubmit({
|
||||||
selectHighestChapterNumberSource,
|
selectHighestChapterNumberSource,
|
||||||
|
ignoreOutdatedMatches,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ export const MigrationExecute = () => {
|
|||||||
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH),
|
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH),
|
||||||
[entryList],
|
[entryList],
|
||||||
);
|
);
|
||||||
|
const outdatedEntries = useMemo(
|
||||||
|
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.OUTDATED),
|
||||||
|
[entryList],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -102,6 +106,15 @@ export const MigrationExecute = () => {
|
|||||||
color="warning"
|
color="warning"
|
||||||
isMigrating
|
isMigrating
|
||||||
/>
|
/>
|
||||||
|
<MigrationEntryGroup
|
||||||
|
status={MigrationEntryStatus.OUTDATED}
|
||||||
|
title={plural(outdatedEntries.length, {
|
||||||
|
one: '1 entry with only outdated matches',
|
||||||
|
other: '# entries with only outdated matches',
|
||||||
|
})}
|
||||||
|
entries={outdatedEntries}
|
||||||
|
color="warning"
|
||||||
|
/>
|
||||||
<MigrationEntryGroup
|
<MigrationEntryGroup
|
||||||
status={MigrationEntryStatus.EXCLUDED}
|
status={MigrationEntryStatus.EXCLUDED}
|
||||||
title={plural(excludedEntries.length, {
|
title={plural(excludedEntries.length, {
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ export const MigrationSearch = () => {
|
|||||||
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH),
|
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH),
|
||||||
[entryList],
|
[entryList],
|
||||||
);
|
);
|
||||||
|
const outdatedEntries = useMemo(
|
||||||
|
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.OUTDATED),
|
||||||
|
[entryList],
|
||||||
|
);
|
||||||
const matchedEntries = useMemo(
|
const matchedEntries = useMemo(
|
||||||
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.SEARCH_COMPLETE),
|
() => entryList.filter((entry) => entry.status === MigrationEntryStatus.SEARCH_COMPLETE),
|
||||||
[entryList],
|
[entryList],
|
||||||
@@ -103,6 +107,15 @@ export const MigrationSearch = () => {
|
|||||||
entries={noMatchEntries}
|
entries={noMatchEntries}
|
||||||
color="warning"
|
color="warning"
|
||||||
/>
|
/>
|
||||||
|
<MigrationEntryGroup
|
||||||
|
status={MigrationEntryStatus.OUTDATED}
|
||||||
|
title={plural(outdatedEntries.length, {
|
||||||
|
one: '1 entry with only outdated matches',
|
||||||
|
other: '# entries with only outdated matches',
|
||||||
|
})}
|
||||||
|
entries={outdatedEntries}
|
||||||
|
color="warning"
|
||||||
|
/>
|
||||||
<MigrationEntryGroup
|
<MigrationEntryGroup
|
||||||
status={MigrationEntryStatus.SEARCH_COMPLETE}
|
status={MigrationEntryStatus.SEARCH_COMPLETE}
|
||||||
title={plural(matchedEntries.length, {
|
title={plural(matchedEntries.length, {
|
||||||
|
|||||||
@@ -63,6 +63,12 @@ msgstr "{0, plural, one {# Tracker} other {# Tracker}}"
|
|||||||
msgid "{0, plural, one {1 entry with no match} other {# entries with no match}}"
|
msgid "{0, plural, one {1 entry with no match} other {# entries with no match}}"
|
||||||
msgstr "{0, plural, one {1 entry with no match} other {# entries with no match}}"
|
msgstr "{0, plural, one {1 entry with no match} other {# entries with no match}}"
|
||||||
|
|
||||||
|
#. placeholder {0}: outdatedEntries.length
|
||||||
|
#: src/features/migration/screens/MigrationExecute.tsx
|
||||||
|
#: src/features/migration/screens/MigrationSearch.tsx
|
||||||
|
msgid "{0, plural, one {1 entry with only outdated matches} other {# entries with only outdated matches}}"
|
||||||
|
msgstr "{0, plural, one {1 entry with only outdated matches} other {# entries with only outdated matches}}"
|
||||||
|
|
||||||
#. placeholder {0}: excludedEntries.length
|
#. placeholder {0}: excludedEntries.length
|
||||||
#: src/features/migration/screens/MigrationExecute.tsx
|
#: src/features/migration/screens/MigrationExecute.tsx
|
||||||
msgid "{0, plural, one {1 excluded entry} other {# excluded entries}}"
|
msgid "{0, plural, one {1 excluded entry} other {# excluded entries}}"
|
||||||
@@ -1334,6 +1340,10 @@ msgstr "Display file sizes in binary (KiB, MiB, GiB) instead of decimal (KB, MB,
|
|||||||
msgid "Display mode"
|
msgid "Display mode"
|
||||||
msgstr "Display mode"
|
msgstr "Display mode"
|
||||||
|
|
||||||
|
#: src/features/migration/components/MigrationBulkSearchOptionsDialog.tsx
|
||||||
|
msgid "Do not automatically select matches if they are behind the current source. They will still be shown in the found matches"
|
||||||
|
msgstr "Do not automatically select matches if they are behind the current source. They will still be shown in the found matches"
|
||||||
|
|
||||||
#: src/features/settings/components/koreaderSync/KoreaderSyncSettings.tsx
|
#: src/features/settings/components/koreaderSync/KoreaderSyncSettings.tsx
|
||||||
msgid "Document matching method"
|
msgid "Document matching method"
|
||||||
msgstr "Document matching method"
|
msgstr "Document matching method"
|
||||||
@@ -1823,6 +1833,10 @@ msgstr "Ignore automatic chapter downloads for entries with unread chapters"
|
|||||||
msgid "Ignore filters when searching"
|
msgid "Ignore filters when searching"
|
||||||
msgstr "Ignore filters when searching"
|
msgstr "Ignore filters when searching"
|
||||||
|
|
||||||
|
#: src/features/migration/components/MigrationBulkSearchOptionsDialog.tsx
|
||||||
|
msgid "Ignore matches without newer chapters"
|
||||||
|
msgstr "Ignore matches without newer chapters"
|
||||||
|
|
||||||
#: src/features/downloads/screens/DownloadSettings.tsx
|
#: src/features/downloads/screens/DownloadSettings.tsx
|
||||||
msgid "Ignore re-uploaded chapters"
|
msgid "Ignore re-uploaded chapters"
|
||||||
msgstr "Ignore re-uploaded chapters"
|
msgstr "Ignore re-uploaded chapters"
|
||||||
@@ -2520,6 +2534,10 @@ msgstr "Oneshot"
|
|||||||
msgid "Ongoing"
|
msgid "Ongoing"
|
||||||
msgstr "Ongoing"
|
msgstr "Ongoing"
|
||||||
|
|
||||||
|
#: src/features/migration/Migration.constants.ts
|
||||||
|
msgid "Only outdated matches found"
|
||||||
|
msgstr "Only outdated matches found"
|
||||||
|
|
||||||
#: src/features/downloads/components/DownloadAheadSetting.tsx
|
#: src/features/downloads/components/DownloadAheadSetting.tsx
|
||||||
msgid "Only works if the current chapter plus the next chapter are already downloaded."
|
msgid "Only works if the current chapter plus the next chapter are already downloaded."
|
||||||
msgstr "Only works if the current chapter plus the next chapter are already downloaded."
|
msgstr "Only works if the current chapter plus the next chapter are already downloaded."
|
||||||
|
|||||||
Reference in New Issue
Block a user