Prevent being able to migrate entry to itself

This commit is contained in:
schroda
2026-06-05 14:52:12 +02:00
parent 848753022a
commit 09c04f4b62
5 changed files with 17 additions and 4 deletions

View File

@@ -47,6 +47,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
- (**Migration**) Fix missing manual search option for in progress entry search without a selected match on mobile
- (**Migration**) Fix being unable to retry failed search for a match without a selected match
- (**Migration**) Fix selecting a destination from a source browse search page
- (**Migration**) Fix being able to migrate an entry to itself
- (**Reader**) Fix scrollbar appearing with "fit to widt/height/screen" page scale mode and applied safe area insets
- (**Reader**) Fix wrongly positioned mobile progress bar current page indicator
- (**Reader**) Fix mobile progress bar previous/next chapter button visibility on hover and while disabled

View File

@@ -157,7 +157,8 @@ const SourceSearchPreview = React.memo(
const { data: searchResult, isLoading, error, abortRequest } = results[0]!;
currentAbortRequest.current = abortRequest;
const mangas = searchResult?.fetchSourceManga?.mangas ?? STABLE_EMPTY_ARRAY;
const tmpMangas = searchResult?.fetchSourceManga?.mangas ?? STABLE_EMPTY_ARRAY;
const mangas = tmpMangas.filter((manga) => manga.id !== mangaId);
const noMangasFound = !error && !isLoading && !mangas.length;
useEffect(() => {

View File

@@ -24,6 +24,8 @@ import { getMetadataServerSettings } from '@/features/settings/services/ServerSe
import { Queue } from '@/lib/Queue.ts';
import type { TrackerIdInfo } from '@/features/tracker/Tracker.types.ts';
import { assertIsDefined } from '@/base/Asserts.ts';
import { t } from '@lingui/core/macro';
import { makeToast } from '@/base/utils/Toast.ts';
export class MangaMigration {
private static trackerQueue = new Map<TrackerIdInfo['id'], Queue>();
@@ -58,6 +60,11 @@ export class MangaMigration {
throw new Error('MangaMigration::migrate: missing manga data');
}
if (mangaToMigrate.id === mangaToMigrateTo.id) {
makeToast(t`Can't migrate an entry to itself`, 'error');
return;
}
if (migrateChapters && !mangaToMigrate.chapters) {
throw new Error('MangaMigration::migrate: missing chapters data');
}

View File

@@ -819,7 +819,8 @@ export class MigrationManager {
);
const uniqueSearchResults = uniqBy('id', searchResults);
const matches = uniqueSearchResults.filter(
(searchMatch) => enhancedCleanup(searchMatch.title) === enhancedCleanup(mangaTitle),
(searchMatch) =>
searchMatch.id !== mangaId && enhancedCleanup(searchMatch.title) === enhancedCleanup(mangaTitle),
);
const matchUpdatePromises = matches.map(async (match) => {

View File

@@ -108,6 +108,7 @@ const useSourceManga = (
filters: IPos[],
initialPages: number,
hideLibraryEntries: boolean,
mangaId?: MangaIdInfo['id'],
): [
AbortableApolloUseMutationPaginatedResponse<GetSourceMangasFetchMutation, GetSourceMangasFetchMutationVariables>[0],
AbortableApolloUseMutationPaginatedResponse<
@@ -168,7 +169,9 @@ const useSourceManga = (
pages.forEach((page, index) => {
const pageItems = page.data?.fetchSourceManga?.mangas ?? [];
const nonLibraryPageItems = pageItems.filter((item) => !hideLibraryEntries || !item.inLibrary);
const nonLibraryPageItems = pageItems.filter(
(item) => item.id !== mangaId && (!hideLibraryEntries || !item.inLibrary),
);
const uniqueItems = getUniqueMangas([...allItems, ...nonLibraryPageItems]);
const isLastPage = !isPageLoading && pages.length === index + 1;
@@ -287,7 +290,7 @@ export function SourceMangas() {
const [
loadPage,
{ data, error, isLoading: loading, size: lastPageNum, abortRequest, filteredOutAllItemsOfFetchedPage },
] = useSourceManga(sourceId, contentType, query, filtersToApply, 1, hideLibraryEntries);
] = useSourceManga(sourceId, contentType, query, filtersToApply, 1, hideLibraryEntries, mangaId);
currentAbortRequest.current = abortRequest;
const mangas = data?.fetchSourceManga?.mangas ?? STABLE_EMPTY_ARRAY;
const hasNextPage = !!data?.fetchSourceManga?.hasNextPage;