Files
suwayomi-material-you-webui/src/screens/Migrate.tsx

129 lines
4.9 KiB
TypeScript
Raw Normal View History

/*
* 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 { useContext, useEffect, useLayoutEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { NavBarContext } from '@/components/context/NavbarContext.tsx';
2024-10-05 16:09:34 +02:00
import { requestManager } from '@/lib/requests/requests/RequestManager.ts';
import { TMigratableSource } from '@/components/MigrationCard.tsx';
2024-10-05 16:09:34 +02:00
import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx';
import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx';
import { GridLayouts } from '@/components/source/GridLayouts.tsx';
2024-10-05 16:09:34 +02:00
import { useLocalStorage } from '@/modules/core/hooks/useStorage.tsx';
2024-10-05 19:33:09 +02:00
import { GridLayout } from '@/modules/library/contexts/LibraryOptionsContext.tsx';
2024-10-05 16:09:34 +02:00
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
import { GetSourceMigratableQuery, GetSourceMigratableQueryVariables } from '@/lib/graphql/generated/graphql.ts';
import { GET_SOURCE_MIGRATABLE } from '@/lib/graphql/queries/SourceQuery.ts';
import { SOURCE_BASE_FIELDS } from '@/lib/graphql/fragments/SourceFragments.ts';
2024-07-08 18:02:50 +02:00
import { BaseMangaGrid } from '@/components/source/BaseMangaGrid.tsx';
export const Migrate = () => {
const { t } = useTranslation();
const { setTitle, setAction } = useContext(NavBarContext);
const { sourceId: paramSourceId } = useParams<{ sourceId: string }>();
const [gridLayout, setGridLayout] = useLocalStorage('migrateGridLayout', GridLayout.List);
const fragmentSource = requestManager.graphQLClient.client.cache.readFragment<
Pick<TMigratableSource, 'id' | 'name'>
>({
id: requestManager.graphQLClient.client.cache.identify({ __typename: 'SourceType', id: paramSourceId }),
fragment: SOURCE_BASE_FIELDS,
});
const [isKnownSource, setIsKnownSource] = useState(fragmentSource !== null ? true : undefined);
const {
data: migratableSourceData,
loading: isSourceLoading,
error: sourceError,
refetch: refetchSource,
} = requestManager.useGetSource<GetSourceMigratableQuery, GetSourceMigratableQueryVariables>(
GET_SOURCE_MIGRATABLE,
paramSourceId,
{ skip: !!isKnownSource, notifyOnNetworkStatusChange: true },
);
const { sourceId, name } = {
sourceId: paramSourceId,
name: paramSourceId,
...fragmentSource,
...migratableSourceData?.source,
};
const {
data: migratableSourceMangasData,
loading: areMangasLoading,
error: mangasError,
refetch: refetchMangas,
} = requestManager.useGetMigratableSourceMangas(sourceId, {
skip: !isKnownSource,
notifyOnNetworkStatusChange: true,
});
useLayoutEffect(() => {
setTitle(name ?? sourceId ?? t('migrate.title'));
setAction(<GridLayouts gridLayout={gridLayout} onChange={setGridLayout} />);
return () => {
setTitle('');
setAction(null);
};
}, [t, name, sourceId, gridLayout]);
useEffect(() => {
if (isSourceLoading || isKnownSource) {
return;
}
setIsKnownSource(
!!migratableSourceData ||
!!sourceError?.message.includes("The field at path '/source' was declared as a non null type"),
);
}, [isSourceLoading, sourceError]);
const isLoadingSource = isSourceLoading || (!sourceError && !isKnownSource);
const isLoading = isLoadingSource || areMangasLoading;
if (isLoading) {
return <LoadingPlaceholder />;
}
const hasErrorSource = sourceError && isKnownSource === false;
const hasError = hasErrorSource || mangasError;
if (hasError) {
const error = (hasErrorSource ? sourceError : mangasError)!;
return (
2024-04-29 15:29:33 +02:00
<EmptyViewAbsoluteCentered
message={t('global.error.label.failed_to_load_data')}
messageExtra={error.message}
retry={() => {
if (hasErrorSource) {
refetchSource().catch(defaultPromiseErrorHandler('Migrate::refetchSource'));
}
if (mangasError) {
refetchMangas().catch(defaultPromiseErrorHandler('Migrate::refetchMangas'));
}
}}
/>
);
}
return (
2024-07-08 18:02:50 +02:00
<BaseMangaGrid
hasNextPage={false}
loadMore={() => {}}
isLoading={areMangasLoading}
2024-07-08 18:02:50 +02:00
mangas={migratableSourceMangasData?.mangas.nodes ?? []}
gridLayout={gridLayout}
mode="migrate.search"
/>
);
};