diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index c39f7955..af68aee1 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -307,6 +307,7 @@ "title": "Display mode" }, "label": { + "advanced": "Advanced", "browse": "Browse", "client": "Client", "close": "Close", @@ -403,6 +404,18 @@ } }, "settings": { + "advanced": { + "database": { + "cleanup": { + "label": { + "description": "Remove non library manga from categories", + "error": "Could not remove non library manga from categories", + "success": "Removed non library manga from categories", + "title": "Cleanup database" + } + } + } + }, "general": { "add_to_library": { "category_selection": { diff --git a/src/lib/requests/RequestManager.ts b/src/lib/requests/RequestManager.ts index 4a8afa25..14773f27 100644 --- a/src/lib/requests/RequestManager.ts +++ b/src/lib/requests/RequestManager.ts @@ -1341,6 +1341,13 @@ export class RequestManager { return this.doRequest(GQLMethod.USE_QUERY, GET_MANGAS, variables, options); } + public getMangas( + variables: GetMangasQueryVariables, + options?: QueryOptions, + ): AbortabaleApolloQueryResponse { + return this.doRequest(GQLMethod.QUERY, GET_MANGAS, variables, options); + } + public getMangaThumbnailUrl(mangaId: number): string { return this.getValidImgUrlFor(`manga/${mangaId}/thumbnail`); } diff --git a/src/screens/settings/LibrarySettings.tsx b/src/screens/settings/LibrarySettings.tsx index 6a954c87..70682a90 100644 --- a/src/screens/settings/LibrarySettings.tsx +++ b/src/screens/settings/LibrarySettings.tsx @@ -8,14 +8,36 @@ import { useTranslation } from 'react-i18next'; import { useContext, useEffect } from 'react'; -import { List, ListItem, ListItemText, Switch } from '@mui/material'; +import { List, ListItem, ListItemButton, ListItemText, Switch } from '@mui/material'; import ListSubheader from '@mui/material/ListSubheader'; +import { t as translate } from 'i18next'; import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx'; import { GlobalUpdateSettings } from '@/components/settings/globalUpdate/GlobalUpdateSettings.tsx'; import { MetadataServerSettingKeys, MetadataServerSettings } from '@/typings.ts'; import { convertToGqlMeta, requestUpdateServerMetadata } from '@/util/metadata.ts'; import { makeToast } from '@/components/util/Toast.tsx'; import { useMetadataServerSettings } from '@/util/metadataServerSettings.ts'; +import { requestManager } from '@/lib/requests/RequestManager.ts'; +import { Mangas } from '@/lib/data/Mangas.ts'; + +const removeNonLibraryMangasFromCategories = async (): Promise => { + try { + const nonLibraryMangas = await requestManager.getMangas({ + filter: { inLibrary: { equalTo: false }, categoryId: { isNull: false } }, + }).response; + + const mangaIdsToRemove = Mangas.getIds(nonLibraryMangas.data.mangas.nodes); + + if (!mangaIdsToRemove.length) { + await requestManager.updateMangasCategories(mangaIdsToRemove, { + clearCategories: true, + }).response; + } + makeToast(translate('library.settings.advanced.database.cleanup.label.success'), 'success'); + } catch (e) { + makeToast(translate('library.settings.advanced.database.cleanup.label.error'), 'error'); + } +}; export function LibrarySettings() { const { t } = useTranslation(); @@ -72,6 +94,20 @@ export function LibrarySettings() { + + {t('global.label.advanced')} + + } + > + removeNonLibraryMangasFromCategories()}> + + + ); }