diff --git a/src/components/manga/MangaDetails.tsx b/src/components/manga/MangaDetails.tsx index 5f4c443e..e37ca40a 100644 --- a/src/components/manga/MangaDetails.tsx +++ b/src/components/manga/MangaDetails.tsx @@ -21,6 +21,8 @@ import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts'; import { CategorySelect } from '@/components/navbar/action/CategorySelect.tsx'; import { Mangas } from '@/lib/data/Mangas.ts'; import { SpinnerImage } from '@/components/util/SpinnerImage.tsx'; +import { defaultPromiseErrorHandler } from '@/util/defaultPromiseErrorHandler.ts'; +import { Categories } from '@/lib/data/Categories.ts'; const DetailsWrapper = styled('div')(({ theme }) => ({ width: '100%', @@ -177,6 +179,12 @@ export const MangaDetails: React.FC = ({ manga }) => { loading: areSettingsLoading, } = useMetadataServerSettings(); + const categories = requestManager.useGetCategories(); + const userCreatedCategories = useMemo( + () => Categories.getUserCreated(categories.data?.categories.nodes ?? []), + [categories.data?.categories.nodes], + ); + const [isCategorySelectOpen, setIsCategorySelectOpen] = useState(false); useEffect(() => { @@ -195,7 +203,21 @@ export const MangaDetails: React.FC = ({ manga }) => { }; const handleAddToLibraryClick = () => { - if (!showAddToLibraryCategorySelectDialog) { + if (categories.loading) { + makeToast(t('global.label.load_in_progress'), 'info'); + return; + } + + if (categories.error) { + makeToast(t('category.error.label.request_failure'), 'error'); + categories + .refetch() + .catch(defaultPromiseErrorHandler('MangaDetails::handleAddToLibraryClick: refetch categories')); + return; + } + + const showCategorySelectDialog = showAddToLibraryCategorySelectDialog && !!userCreatedCategories.length; + if (!showCategorySelectDialog) { addToLibrary(); return; } @@ -236,7 +258,7 @@ export const MangaDetails: React.FC = ({ manga }) => {
- + + {addToLibrary && ( + setDoNotShowAddToLibraryDialogAgain(e.target.checked)} + /> + )} + + + + + {!!allCategories.length && ( + + )} + + + ); diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 3f1b432d..956a7411 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -13,8 +13,7 @@ }, "no_categories_found": { "label": { - "hint": "You should make some from the settings.", - "info": "No categories found." + "info": "You don't have any categories yet." } } }, @@ -296,7 +295,9 @@ "cancel": "Cancel", "clear": "Clear", "copy": "Copy", + "create": "Create", "deselect": "Deselect", + "dont_show_dialog_again": "Don't show this dialog again", "edit": "Edit", "filter": "Filter", "latest": "Latest", @@ -370,6 +371,7 @@ "general": "General", "github": "GitHub", "links": "Links", + "load_in_progress": "Still loading required data…", "loading": "Loading…", "never": "Never", "none": "None", diff --git a/src/lib/data/Categories.ts b/src/lib/data/Categories.ts new file mode 100644 index 00000000..e9c338e6 --- /dev/null +++ b/src/lib/data/Categories.ts @@ -0,0 +1,28 @@ +/* + * 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 { TCategory } from '@/typings.ts'; + +export const DEFAULT_CATEGORY_ID = 0; + +export type CategoryIdInfo = Pick; +export type CategoryDefaultInfo = Pick; + +export class Categories { + static getIds(categories: CategoryIdInfo[]): number[] { + return categories.map((category) => category.id); + } + + static getUserCreated(categories: Category[]): Category[] { + return categories.filter((category) => category.id !== DEFAULT_CATEGORY_ID); + } + + static getDefaults(categories: Category[]): Category[] { + return categories.filter((category) => category.default); + } +}