diff --git a/CHANGELOG.md b/CHANGELOG.md index 883770d2..5c27fd58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Migration**) Allow only 2 tracker requests per second - (**Migration**) Sort manga to migrate selection by title and by recently added to the library - (**Migration**) Sort destination source selection by same order as browse source page -- (**Migration**) Sort entries in search page by title +- (**Migration**) Sort entries in search/execution page by title ### Fixed diff --git a/src/features/migration/MigrationEntries.ts b/src/features/migration/MigrationEntries.ts new file mode 100644 index 00000000..94e80000 --- /dev/null +++ b/src/features/migration/MigrationEntries.ts @@ -0,0 +1,46 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import type { MigrationEntryStatus, TMigrationEntry } from '@/features/migration/Migration.types.ts'; + +export class MigrationEntries { + public static getExcluded(entries: TMigrationEntry[]): TMigrationEntry[] { + return entries.filter((entry) => entry.isExcluded); + } + + public static getHaveStatus(entries: TMigrationEntry[], ...statuses: MigrationEntryStatus[]): TMigrationEntry[] { + return entries.filter((entry) => statuses.includes(entry.status)); + } + + public static getHaveStatusSorted( + entries: TMigrationEntry[], + ...statuses: MigrationEntryStatus[] + ): TMigrationEntry[] { + return MigrationEntries.getHaveStatus(entries, ...statuses).toSorted((a, b) => + a.mangaTitle.localeCompare(b.mangaTitle), + ); + } + + public static getActiveEntriesSorted( + entries: TMigrationEntry[], + activeStatus: MigrationEntryStatus, + ...statuses: MigrationEntryStatus[] + ): TMigrationEntry[] { + return MigrationEntries.getHaveStatus(entries, ...statuses).toSorted((a, b) => { + if (a.status === activeStatus && b.status !== activeStatus) { + return -1; + } + + if (a.status !== activeStatus && b.status === activeStatus) { + return 1; + } + + return a.mangaTitle.localeCompare(b.mangaTitle); + }); + } +} diff --git a/src/features/migration/screens/MigrationExecute.tsx b/src/features/migration/screens/MigrationExecute.tsx index 54aeadf8..72740d23 100644 --- a/src/features/migration/screens/MigrationExecute.tsx +++ b/src/features/migration/screens/MigrationExecute.tsx @@ -17,6 +17,7 @@ import { DEFAULT_FULL_FAB_HEIGHT } from '@/base/components/buttons/StyledFab.tsx import { MigrationContinueButton } from '@/features/migration/components/MigrationContinueButton.tsx'; import { plural } from '@lingui/core/macro'; import { MigrationEntryGroup } from '@/features/migration/components/MIgrationEntryGroup.tsx'; +import { MigrationEntries } from '@/features/migration/MigrationEntries.ts'; export const MigrationExecute = () => { const { t } = useLingui(); @@ -42,38 +43,29 @@ export const MigrationExecute = () => { const entryList = useMemo(() => Object.values(entries), [entries]); const migratingEntries = useMemo( () => - entryList - .filter((entry) => - [MigrationEntryStatus.SEARCH_COMPLETE, MigrationEntryStatus.MIGRATING].includes(entry.status), - ) - .toSorted((a, b) => { - if (a.status === MigrationEntryStatus.MIGRATING && b.status !== MigrationEntryStatus.MIGRATING) { - return -1; - } - - if (a.status !== MigrationEntryStatus.MIGRATING && b.status === MigrationEntryStatus.MIGRATING) { - return 1; - } - - return entryList.indexOf(a) - entryList.indexOf(b); - }), + MigrationEntries.getActiveEntriesSorted( + entryList, + MigrationEntryStatus.MIGRATING, + MigrationEntryStatus.SEARCH_COMPLETE, + MigrationEntryStatus.MIGRATING, + ), [entryList], ); const migratedEntries = useMemo( - () => entryList.filter((entry) => entry.status === MigrationEntryStatus.MIGRATION_COMPLETE), + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.MIGRATION_COMPLETE), [entryList], ); const failedEntries = useMemo( - () => entryList.filter((entry) => entry.status === MigrationEntryStatus.MIGRATION_FAILED), + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.MIGRATION_FAILED), [entryList], ); - const excludedEntries = useMemo(() => entryList.filter((entry) => entry.isExcluded), [entryList]); + const excludedEntries = useMemo(() => MigrationEntries.getExcluded(entryList), [entryList]); const noMatchEntries = useMemo( - () => entryList.filter((entry) => entry.status === MigrationEntryStatus.NO_MATCH), + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.NO_MATCH), [entryList], ); const outdatedEntries = useMemo( - () => entryList.filter((entry) => entry.status === MigrationEntryStatus.OUTDATED), + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.OUTDATED), [entryList], ); diff --git a/src/features/migration/screens/MigrationSearch.tsx b/src/features/migration/screens/MigrationSearch.tsx index 1be21f1c..73555aef 100644 --- a/src/features/migration/screens/MigrationSearch.tsx +++ b/src/features/migration/screens/MigrationSearch.tsx @@ -17,13 +17,10 @@ import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts' import { DEFAULT_FULL_FAB_HEIGHT } from '@/base/components/buttons/StyledFab.tsx'; import { useMemo } from 'react'; import Stack from '@mui/material/Stack'; -import type { TMigrationEntry } from '@/features/migration/Migration.types.ts'; import { MigrationEntryStatus } from '@/features/migration/Migration.types.ts'; import { MigrationEntryGroup } from '@/features/migration/components/MIgrationEntryGroup.tsx'; import { plural } from '@lingui/core/macro'; - -const getEntries = (status: MigrationEntryStatus, entries: TMigrationEntry[]): TMigrationEntry[] => - entries.filter((entry) => entry.status === status).toSorted((a, b) => a.mangaTitle.localeCompare(b.mangaTitle)); +import { MigrationEntries } from '@/features/migration/MigrationEntries.ts'; export const MigrationSearch = () => { const { t } = useLingui(); @@ -37,27 +34,30 @@ export const MigrationSearch = () => { const entryList = useMemo(() => Object.values(entries), [entries]); const searchingEntries = useMemo( () => - entryList - .filter((entry) => - [MigrationEntryStatus.PENDING, MigrationEntryStatus.SEARCHING].includes(entry.status), - ) - .toSorted((a, b) => { - if (a.status === MigrationEntryStatus.SEARCHING && b.status !== MigrationEntryStatus.SEARCHING) { - return -1; - } - - if (a.status !== MigrationEntryStatus.SEARCHING && b.status === MigrationEntryStatus.SEARCHING) { - return 1; - } - - return a.mangaTitle.localeCompare(b.mangaTitle); - }), + MigrationEntries.getActiveEntriesSorted( + entryList, + MigrationEntryStatus.SEARCHING, + MigrationEntryStatus.PENDING, + MigrationEntryStatus.SEARCHING, + ), + [entryList], + ); + const failedEntries = useMemo( + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.SEARCH_FAILED), + [entryList], + ); + const noMatchEntries = useMemo( + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.NO_MATCH), + [entryList], + ); + const outdatedEntries = useMemo( + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.OUTDATED), + [entryList], + ); + const matchedEntries = useMemo( + () => MigrationEntries.getHaveStatusSorted(entryList, MigrationEntryStatus.SEARCH_COMPLETE), [entryList], ); - const failedEntries = useMemo(() => getEntries(MigrationEntryStatus.SEARCH_FAILED, entryList), [entryList]); - const noMatchEntries = useMemo(() => getEntries(MigrationEntryStatus.NO_MATCH, entryList), [entryList]); - const outdatedEntries = useMemo(() => getEntries(MigrationEntryStatus.OUTDATED, entryList), [entryList]); - const matchedEntries = useMemo(() => getEntries(MigrationEntryStatus.SEARCH_COMPLETE, entryList), [entryList]); const hasMigratableEntries = useMemo(() => !!MigrationManager.getMigratableEntries().length, [entryList]);