/* * 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 FormLabel from '@mui/material/FormLabel'; import RadioGroup from '@mui/material/RadioGroup'; import { useTranslation } from 'react-i18next'; import { CheckboxInput } from '@/modules/core/components/inputs/CheckboxInput.tsx'; import { RadioInput } from '@/modules/core/components/inputs/RadioInput.tsx'; import { SortRadioInput } from '@/modules/core/components/inputs/SortRadioInput.tsx'; import { ThreeStateCheckboxInput } from '@/modules/core/components/inputs/ThreeStateCheckboxInput.tsx'; import { OptionsTabs } from '@/modules/core/components/OptionsTabs.tsx'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { Trackers } from '@/modules/tracker/services/Trackers.ts'; import { GetTrackersSettingsQuery, MangaStatus } from '@/lib/graphql/generated/graphql.ts'; import { GET_TRACKERS_SETTINGS } from '@/lib/graphql/queries/TrackerQuery.ts'; import { createUpdateCategoryMetadata, useGetCategoryMetadata } from '@/modules/category/services/CategoryMetadata.ts'; import { makeToast } from '@/modules/core/utils/Toast.ts'; import { createUpdateMetadataServerSettings, useMetadataServerSettings, } from '@/modules/settings/services/ServerSettingsMetadata.ts'; import { TranslationKey } from '@/Base.types.ts'; import { LibrarySortMode } from '@/modules/library/Library.types.ts'; import { CategoryMetadataInfo } from '@/modules/category/Category.types.ts'; import { statusToTranslationKey } from '@/modules/manga/Manga.constants.ts'; import { GridLayout } from '@/modules/core/Core.types.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts'; const TITLES: { [key in 'filter' | 'sort' | 'display']: TranslationKey } = { filter: 'global.label.filter', sort: 'global.label.sort', display: 'global.label.display', }; const SORT_OPTIONS: [LibrarySortMode, TranslationKey][] = [ ['unreadChapters', 'library.option.sort.label.by_unread_chapters'], ['totalChapters', 'library.option.sort.label.by_total_chapters'], ['alphabetically', 'library.option.sort.label.alphabetically'], ['dateAdded', 'library.option.sort.label.by_date_added'], ['lastRead', 'library.option.sort.label.by_last_read'], ['latestFetchedChapter', 'library.option.sort.label.by_latest_fetched_chapter'], ['latestUploadedChapter', 'library.option.sort.label.by_latest_uploaded_chapter'], ]; export const LibraryOptionsPanel = ({ category, open, onClose, }: { category: CategoryMetadataInfo; open: boolean; onClose: () => void; }) => { const { t } = useTranslation(); const trackerList = requestManager.useGetTrackerList(GET_TRACKERS_SETTINGS); const loggedInTrackers = Trackers.getLoggedIn(trackerList.data?.trackers.nodes ?? []); const categoryLibraryOptions = useGetCategoryMetadata(category); const updateCategoryLibraryOptions = createUpdateCategoryMetadata(category, (e) => makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)), ); const { settings: { showTabSize }, } = useMetadataServerSettings(); const setSettingValue = createUpdateMetadataServerSettings<'showTabSize'>((e) => makeToast(t('search.error.label.failed_to_save_settings'), 'error', getErrorMessage(e)), ); return ( open={open} onClose={onClose} tabs={['filter', 'sort', 'display']} tabTitle={(key) => t(TITLES[key])} tabContent={(key) => { if (key === 'filter') { return ( <> updateCategoryLibraryOptions('hasUnreadChapters', c)} /> updateCategoryLibraryOptions('hasReadChapters', c)} /> updateCategoryLibraryOptions('hasDownloadedChapters', c)} /> updateCategoryLibraryOptions('hasBookmarkedChapters', c)} /> updateCategoryLibraryOptions('hasDuplicateChapters', c)} /> {t('manga.label.status')} {Object.values(MangaStatus).map((status) => ( updateCategoryLibraryOptions('hasStatus', { ...categoryLibraryOptions.hasStatus, [status]: checked, }) } /> ))} {t('global.filter.label.tracked')} {loggedInTrackers.map((tracker) => ( updateCategoryLibraryOptions('hasTrackerBinding', { ...categoryLibraryOptions.hasTrackerBinding, [tracker.id]: checked, }) } /> ))} ); } if (key === 'sort') { return SORT_OPTIONS.map(([mode, label]) => ( mode !== categoryLibraryOptions.sortBy ? updateCategoryLibraryOptions('sortBy', mode) : updateCategoryLibraryOptions('sortDesc', !categoryLibraryOptions.sortDesc) } /> )); } if (key === 'display') { const { gridLayout, showContinueReadingButton, showDownloadBadge, showUnreadBadge } = categoryLibraryOptions; return ( <> {t('global.grid_layout.title')} updateCategoryLibraryOptions('gridLayout', Number(e.target.value))} value={gridLayout} > {t('library.option.display.badge.title')} updateCategoryLibraryOptions('showUnreadBadge', !showUnreadBadge)} /> updateCategoryLibraryOptions('showDownloadBadge', !showDownloadBadge)} /> {t('library.option.display.tab.title')} setSettingValue('showTabSize', !showTabSize)} /> {t('global.label.other')} updateCategoryLibraryOptions( 'showContinueReadingButton', !showContinueReadingButton, ) } /> ); } return null; }} /> ); };