Rename library option variable names
This commit is contained in:
@@ -26,21 +26,21 @@ export const DefaultLibraryOptions: LibraryOptions = {
|
||||
showDownloadBadge: false,
|
||||
showUnreadBadge: false,
|
||||
gridLayout: GridLayout.Compact,
|
||||
SourcegridLayout: GridLayout.Compact,
|
||||
sourceGridLayout: GridLayout.Compact,
|
||||
|
||||
showTabSize: false,
|
||||
|
||||
// sort options
|
||||
sortDesc: undefined,
|
||||
sorts: undefined,
|
||||
sortBy: undefined,
|
||||
|
||||
// filter options
|
||||
downloaded: undefined,
|
||||
bookmarked: undefined,
|
||||
unread: undefined,
|
||||
hasDownloadedChapters: undefined,
|
||||
hasBookmarkedChapters: undefined,
|
||||
hasUnreadChapters: undefined,
|
||||
hasDuplicateChapters: undefined,
|
||||
tracker: {},
|
||||
status: {} as LibraryOptions['status'],
|
||||
hasTrackerBinding: {},
|
||||
hasStatus: {} as LibraryOptions['hasStatus'],
|
||||
};
|
||||
|
||||
export const LibraryOptionsContext = React.createContext<ContextType>({
|
||||
|
||||
@@ -30,13 +30,13 @@ const TITLES: { [key in 'filter' | 'sort' | 'display']: TranslationKey } = {
|
||||
};
|
||||
|
||||
const SORT_OPTIONS: [LibrarySortMode, TranslationKey][] = [
|
||||
['sortToRead', 'library.option.sort.label.by_unread_chapters'],
|
||||
['sortTotalChapters', 'library.option.sort.label.by_total_chapters'],
|
||||
['sortAlph', 'library.option.sort.label.alphabetically'],
|
||||
['sortDateAdded', 'library.option.sort.label.by_date_added'],
|
||||
['sortLastRead', 'library.option.sort.label.by_last_read'],
|
||||
['sortLatestFetchedChapter', 'library.option.sort.label.by_latest_fetched_chapter'],
|
||||
['sortLatestUploadedChapter', 'library.option.sort.label.by_latest_uploaded_chapter'],
|
||||
['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'],
|
||||
];
|
||||
|
||||
interface IProps {
|
||||
@@ -67,18 +67,18 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
||||
<>
|
||||
<ThreeStateCheckboxInput
|
||||
label={t('global.filter.label.unread')}
|
||||
checked={options.unread}
|
||||
onChange={(c) => handleFilterChange('unread', c)}
|
||||
checked={options.hasUnreadChapters}
|
||||
onChange={(c) => handleFilterChange('hasUnreadChapters', c)}
|
||||
/>
|
||||
<ThreeStateCheckboxInput
|
||||
label={t('global.filter.label.downloaded')}
|
||||
checked={options.downloaded}
|
||||
onChange={(c) => handleFilterChange('downloaded', c)}
|
||||
checked={options.hasDownloadedChapters}
|
||||
onChange={(c) => handleFilterChange('hasDownloadedChapters', c)}
|
||||
/>
|
||||
<ThreeStateCheckboxInput
|
||||
label={t('global.filter.label.bookmarked')}
|
||||
checked={options.bookmarked}
|
||||
onChange={(c) => handleFilterChange('bookmarked', c)}
|
||||
checked={options.hasBookmarkedChapters}
|
||||
onChange={(c) => handleFilterChange('hasBookmarkedChapters', c)}
|
||||
/>
|
||||
<ThreeStateCheckboxInput
|
||||
label={t('global.filter.label.duplicate_chapters')}
|
||||
@@ -89,10 +89,10 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
||||
{Object.values(MangaStatus).map((status) => (
|
||||
<ThreeStateCheckboxInput
|
||||
label={t(statusToTranslationKey[status])}
|
||||
checked={options.status[status]}
|
||||
checked={options.hasStatus[status]}
|
||||
onChange={(checked) =>
|
||||
handleFilterChange('status', {
|
||||
...options.status,
|
||||
handleFilterChange('hasStatus', {
|
||||
...options.hasStatus,
|
||||
[status]: checked,
|
||||
})
|
||||
}
|
||||
@@ -103,9 +103,12 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
||||
<ThreeStateCheckboxInput
|
||||
key={tracker.id}
|
||||
label={tracker.name}
|
||||
checked={options.tracker[tracker.id]}
|
||||
checked={options.hasTrackerBinding[tracker.id]}
|
||||
onChange={(checked) =>
|
||||
handleFilterChange('tracker', { ...options.tracker, [tracker.id]: checked })
|
||||
handleFilterChange('hasTrackerBinding', {
|
||||
...options.hasTrackerBinding,
|
||||
[tracker.id]: checked,
|
||||
})
|
||||
}
|
||||
/>
|
||||
))}
|
||||
@@ -117,11 +120,11 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
||||
<SortRadioInput
|
||||
key={mode}
|
||||
label={t(label)}
|
||||
checked={options.sorts === mode}
|
||||
checked={options.sortBy === mode}
|
||||
sortDescending={options.sortDesc}
|
||||
onClick={() =>
|
||||
mode !== options.sorts
|
||||
? handleFilterChange('sorts', mode)
|
||||
mode !== options.sortBy
|
||||
? handleFilterChange('sortBy', mode)
|
||||
: handleFilterChange('sortDesc', !options.sortDesc)
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -11,8 +11,8 @@ import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
|
||||
import { LibraryOptionsPanel } from '@/components/library/LibraryOptionsPanel';
|
||||
import { useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext.tsx';
|
||||
|
||||
export const LibraryToolbarMenu: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -20,9 +20,9 @@ export const LibraryToolbarMenu: React.FC = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { options } = useLibraryOptionsContext();
|
||||
const active =
|
||||
options.downloaded != null ||
|
||||
options.unread != null ||
|
||||
Object.values(options.tracker).some((trackerFilterStatus) => trackerFilterStatus != null);
|
||||
options.hasDownloadedChapters != null ||
|
||||
options.hasUnreadChapters != null ||
|
||||
Object.values(options.hasTrackerBinding).some((trackerFilterStatus) => trackerFilterStatus != null);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -77,7 +77,7 @@ const querySearchManga = (
|
||||
performSearch([query], [source?.displayName]);
|
||||
|
||||
type TMangaTrackerFilter = { trackRecords: { nodes: Pick<TrackRecordType, 'id' | 'trackerId'>[] } };
|
||||
const trackerFilter = (trackFilters: LibraryOptions['tracker'], manga: TMangaTrackerFilter): boolean =>
|
||||
const trackerFilter = (trackFilters: LibraryOptions['hasTrackerBinding'], manga: TMangaTrackerFilter): boolean =>
|
||||
Object.entries(trackFilters)
|
||||
.map(([trackFilterId, trackFilterState]) => {
|
||||
const isTrackerBound = manga.trackRecords.nodes.some(
|
||||
@@ -93,28 +93,40 @@ const trackerFilter = (trackFilters: LibraryOptions['tracker'], manga: TMangaTra
|
||||
.every(Boolean);
|
||||
|
||||
type TMangaStatusFilter = Pick<MangaType, 'status'>;
|
||||
const statusFilter = (statusFilters: LibraryOptions['status'], manga: TMangaStatusFilter): boolean =>
|
||||
const statusFilter = (statusFilters: LibraryOptions['hasStatus'], manga: TMangaStatusFilter): boolean =>
|
||||
Object.entries(statusFilters)
|
||||
.map(([status, statusFilterState]) => triStateFilterBoolean(statusFilterState, status === manga.status))
|
||||
.every(Boolean);
|
||||
|
||||
type TMangaFilterOptions = Pick<
|
||||
LibraryOptions,
|
||||
'unread' | 'downloaded' | 'bookmarked' | 'hasDuplicateChapters' | 'tracker' | 'status'
|
||||
| 'hasUnreadChapters'
|
||||
| 'hasDownloadedChapters'
|
||||
| 'hasBookmarkedChapters'
|
||||
| 'hasDuplicateChapters'
|
||||
| 'hasTrackerBinding'
|
||||
| 'hasStatus'
|
||||
>;
|
||||
type TMangaFilter = Pick<MangaType, 'downloadCount' | 'unreadCount' | 'bookmarkCount' | 'hasDuplicateChapters'> &
|
||||
TMangaTrackerFilter &
|
||||
TMangaStatusFilter;
|
||||
const filterManga = (
|
||||
manga: TMangaFilter,
|
||||
{ unread, downloaded, bookmarked, hasDuplicateChapters, tracker, status }: TMangaFilterOptions,
|
||||
{
|
||||
hasDownloadedChapters,
|
||||
hasUnreadChapters,
|
||||
hasBookmarkedChapters,
|
||||
hasDuplicateChapters,
|
||||
hasTrackerBinding,
|
||||
hasStatus,
|
||||
}: TMangaFilterOptions,
|
||||
): boolean =>
|
||||
triStateFilterNumber(downloaded, manga.downloadCount) &&
|
||||
triStateFilterNumber(unread, manga.unreadCount) &&
|
||||
triStateFilterNumber(bookmarked, manga.bookmarkCount) &&
|
||||
triStateFilterNumber(hasDownloadedChapters, manga.downloadCount) &&
|
||||
triStateFilterNumber(hasUnreadChapters, manga.unreadCount) &&
|
||||
triStateFilterNumber(hasBookmarkedChapters, manga.bookmarkCount) &&
|
||||
triStateFilterBoolean(hasDuplicateChapters, manga.hasDuplicateChapters) &&
|
||||
trackerFilter(tracker, manga) &&
|
||||
statusFilter(status, manga);
|
||||
trackerFilter(hasTrackerBinding, manga) &&
|
||||
statusFilter(hasStatus, manga);
|
||||
|
||||
type TMangasFilter = TMangaQueryFilter & TMangaFilter;
|
||||
const filterMangas = <Manga extends TMangasFilter>(
|
||||
@@ -150,27 +162,27 @@ const sortManga = <Manga extends TMangaSort>(
|
||||
const result = [...manga];
|
||||
|
||||
switch (sort) {
|
||||
case 'sortAlph':
|
||||
case 'alphabetically':
|
||||
result.sort((a, b) => sortByString(a.title, b.title));
|
||||
break;
|
||||
case 'sortDateAdded':
|
||||
case 'dateAdded':
|
||||
result.sort((a, b) => sortByNumber(a.inLibraryAt, b.inLibraryAt));
|
||||
break;
|
||||
case 'sortToRead':
|
||||
case 'unreadChapters':
|
||||
result.sort((a, b) => sortByNumber(a.unreadCount, b.unreadCount));
|
||||
break;
|
||||
case 'sortLastRead':
|
||||
case 'lastRead':
|
||||
result.sort((a, b) => sortByNumber(a.lastReadChapter?.lastReadAt, b.lastReadChapter?.lastReadAt));
|
||||
break;
|
||||
case 'sortLatestUploadedChapter':
|
||||
case 'latestUploadedChapter':
|
||||
result.sort((a, b) =>
|
||||
sortByNumber(a.latestUploadedChapter?.uploadDate, b.latestUploadedChapter?.uploadDate),
|
||||
);
|
||||
break;
|
||||
case 'sortLatestFetchedChapter':
|
||||
case 'latestFetchedChapter':
|
||||
result.sort((a, b) => sortByNumber(a.latestFetchedChapter?.fetchedAt, b.latestFetchedChapter?.fetchedAt));
|
||||
break;
|
||||
case 'sortTotalChapters':
|
||||
case 'totalChapters':
|
||||
result.sort((a, b) => sortByNumber(a.chapters.totalCount, b.chapters.totalCount));
|
||||
break;
|
||||
default:
|
||||
@@ -192,30 +204,48 @@ export const useGetVisibleLibraryMangas = <Manga extends MangaIdInfo & TMangasFi
|
||||
} => {
|
||||
const [query] = useQueryParam('query', StringParam);
|
||||
const { options } = useLibraryOptionsContext();
|
||||
const { unread, downloaded, bookmarked, tracker, hasDuplicateChapters, status } = options;
|
||||
const {
|
||||
hasUnreadChapters,
|
||||
hasDownloadedChapters,
|
||||
hasBookmarkedChapters,
|
||||
hasTrackerBinding,
|
||||
hasDuplicateChapters,
|
||||
hasStatus,
|
||||
} = options;
|
||||
const { settings } = useMetadataServerSettings();
|
||||
|
||||
const filteredMangas = useMemo(
|
||||
() =>
|
||||
filterMangas(mangas, query, {
|
||||
unread,
|
||||
downloaded,
|
||||
bookmarked,
|
||||
hasDuplicateChapters,
|
||||
tracker,
|
||||
status,
|
||||
...options,
|
||||
ignoreFilters: settings.ignoreFilters,
|
||||
}),
|
||||
[mangas, query, unread, downloaded, bookmarked, hasDuplicateChapters, tracker, settings.ignoreFilters],
|
||||
[
|
||||
mangas,
|
||||
query,
|
||||
hasUnreadChapters,
|
||||
hasDownloadedChapters,
|
||||
hasBookmarkedChapters,
|
||||
hasTrackerBinding,
|
||||
hasDuplicateChapters,
|
||||
hasStatus,
|
||||
settings.ignoreFilters,
|
||||
],
|
||||
);
|
||||
const sortedMangas = useMemo(
|
||||
() => sortManga(filteredMangas, options.sorts, options.sortDesc),
|
||||
[filteredMangas, options.sorts, options.sortDesc],
|
||||
() => sortManga(filteredMangas, options.sortBy, options.sortDesc),
|
||||
[filteredMangas, options.sortBy, options.sortDesc],
|
||||
);
|
||||
|
||||
const isATrackFilterActive = Object.values(options.tracker).some((trackFilterState) => trackFilterState != null);
|
||||
const isATrackFilterActive = Object.values(options.hasTrackerBinding).some(
|
||||
(trackFilterState) => trackFilterState != null,
|
||||
);
|
||||
const showFilteredOutMessage =
|
||||
(unread != null || downloaded != null || bookmarked != null || !!query || isATrackFilterActive) &&
|
||||
(hasUnreadChapters != null ||
|
||||
hasDownloadedChapters != null ||
|
||||
hasBookmarkedChapters != null ||
|
||||
!!query ||
|
||||
isATrackFilterActive) &&
|
||||
filteredMangas.length === 0 &&
|
||||
mangas.length > 0;
|
||||
|
||||
|
||||
@@ -252,13 +252,13 @@ export type ChapterOptionsReducerAction =
|
||||
| { type: 'showChapterNumber' };
|
||||
|
||||
export type LibrarySortMode =
|
||||
| 'sortToRead'
|
||||
| 'sortAlph'
|
||||
| 'sortDateAdded'
|
||||
| 'sortLastRead'
|
||||
| 'sortLatestFetchedChapter'
|
||||
| 'sortLatestUploadedChapter'
|
||||
| 'sortTotalChapters';
|
||||
| 'unreadChapters'
|
||||
| 'totalChapters'
|
||||
| 'alphabetically'
|
||||
| 'dateAdded'
|
||||
| 'lastRead'
|
||||
| 'latestFetchedChapter'
|
||||
| 'latestUploadedChapter';
|
||||
|
||||
enum GridLayout {
|
||||
Compact = 0,
|
||||
@@ -272,20 +272,20 @@ export interface LibraryOptions {
|
||||
showDownloadBadge: boolean;
|
||||
showUnreadBadge: boolean;
|
||||
gridLayout: GridLayout;
|
||||
SourcegridLayout: GridLayout;
|
||||
sourceGridLayout: GridLayout;
|
||||
showTabSize: boolean;
|
||||
|
||||
// sort options
|
||||
sorts: NullAndUndefined<LibrarySortMode>;
|
||||
sortBy: NullAndUndefined<LibrarySortMode>;
|
||||
sortDesc: NullAndUndefined<boolean>;
|
||||
|
||||
// filter options
|
||||
downloaded: NullAndUndefined<boolean>;
|
||||
bookmarked: NullAndUndefined<boolean>;
|
||||
unread: NullAndUndefined<boolean>;
|
||||
hasDownloadedChapters: NullAndUndefined<boolean>;
|
||||
hasBookmarkedChapters: NullAndUndefined<boolean>;
|
||||
hasUnreadChapters: NullAndUndefined<boolean>;
|
||||
hasDuplicateChapters: NullAndUndefined<boolean>;
|
||||
showTabSize: boolean;
|
||||
tracker: Record<TrackerType['id'], NullAndUndefined<boolean>>;
|
||||
status: Record<MangaStatus, NullAndUndefined<boolean>>;
|
||||
hasTrackerBinding: Record<TrackerType['id'], NullAndUndefined<boolean>>;
|
||||
hasStatus: Record<MangaStatus, NullAndUndefined<boolean>>;
|
||||
}
|
||||
|
||||
export type ServerSettings = GetServerSettingsQuery['settings'];
|
||||
|
||||
Reference in New Issue
Block a user