Introduce override filters while searching setting (#242)
* Introduced override filters while searching setting * update branch; change strings and method names * fix eslint issue * code review changes * moved search setting types into its own type --------- Co-authored-by: akxer <>
This commit is contained in:
@@ -12,6 +12,7 @@ import { useLibraryOptionsContext } from 'components/context/LibraryOptionsConte
|
|||||||
import { StringParam, useQueryParam } from 'use-query-params';
|
import { StringParam, useQueryParam } from 'use-query-params';
|
||||||
import { useMediaQuery, useTheme } from '@mui/material';
|
import { useMediaQuery, useTheme } from '@mui/material';
|
||||||
import { IMangaCard, LibrarySortMode, NullAndUndefined } from 'typings';
|
import { IMangaCard, LibrarySortMode, NullAndUndefined } from 'typings';
|
||||||
|
import { useSearchSettings } from 'util/searchSettings';
|
||||||
|
|
||||||
const FILTERED_OUT_MESSAGE = 'There are no Manga matching this filter';
|
const FILTERED_OUT_MESSAGE = 'There are no Manga matching this filter';
|
||||||
|
|
||||||
@@ -53,12 +54,12 @@ const filterManga = (
|
|||||||
query: NullAndUndefined<string>,
|
query: NullAndUndefined<string>,
|
||||||
unread: NullAndUndefined<boolean>,
|
unread: NullAndUndefined<boolean>,
|
||||||
downloaded: NullAndUndefined<boolean>,
|
downloaded: NullAndUndefined<boolean>,
|
||||||
|
ignoreFilters: boolean,
|
||||||
): IMangaCard[] =>
|
): IMangaCard[] =>
|
||||||
mangas.filter(
|
mangas.filter(
|
||||||
(manga) =>
|
(manga) =>
|
||||||
(queryFilter(query, manga) || queryGenreFilter(query, manga)) &&
|
(queryFilter(query, manga) || queryGenreFilter(query, manga)) &&
|
||||||
downloadedFilter(downloaded, manga) &&
|
(ignoreFilters || (downloadedFilter(downloaded, manga) && unreadFilter(unread, manga))),
|
||||||
unreadFilter(unread, manga),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortByUnread = (a: IMangaCard, b: IMangaCard): number =>
|
const sortByUnread = (a: IMangaCard, b: IMangaCard): number =>
|
||||||
@@ -120,11 +121,13 @@ const LibraryMangaGrid: React.FC<LibraryMangaGridProps & { lastLibraryUpdate: nu
|
|||||||
const isLargeScreen = useMediaQuery(theme.breakpoints.up('sm'));
|
const isLargeScreen = useMediaQuery(theme.breakpoints.up('sm'));
|
||||||
const defaultPageNumber = isLargeScreen ? 4 : 1;
|
const defaultPageNumber = isLargeScreen ? 4 : 1;
|
||||||
const [lastPageNum, setLastPageNum] = useState<number>(defaultPageNumber);
|
const [lastPageNum, setLastPageNum] = useState<number>(defaultPageNumber);
|
||||||
|
const { settings } = useSearchSettings();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFilteredManga(filterManga(mangas, query, unread, downloaded));
|
setFilteredManga(filterManga(mangas, query, unread, downloaded, settings.ignoreFilters));
|
||||||
setLastPageNum(defaultPageNumber);
|
setLastPageNum(defaultPageNumber);
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}, [mangas, query, unread, downloaded]);
|
}, [mangas, query, unread, downloaded, settings.ignoreFilters]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSortedManga(sortManga(filteredManga, options.sorts, options.sortDesc));
|
setSortedManga(sortManga(filteredManga, options.sorts, options.sortDesc));
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import NavbarContext from 'components/context/NavbarContext';
|
|||||||
import DarkTheme from 'components/context/DarkTheme';
|
import DarkTheme from 'components/context/DarkTheme';
|
||||||
import useLocalStorage from 'util/useLocalStorage';
|
import useLocalStorage from 'util/useLocalStorage';
|
||||||
import ListItemLink from 'components/util/ListItemLink';
|
import ListItemLink from 'components/util/ListItemLink';
|
||||||
|
import SearchSettings from 'screens/settings/SearchSettings';
|
||||||
|
|
||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
const { setTitle, setAction } = useContext(NavbarContext);
|
const { setTitle, setAction } = useContext(NavbarContext);
|
||||||
@@ -121,6 +122,7 @@ export default function Settings() {
|
|||||||
<Switch edge="end" checked={darkTheme} onChange={() => setDarkTheme(!darkTheme)} />
|
<Switch edge="end" checked={darkTheme} onChange={() => setDarkTheme(!darkTheme)} />
|
||||||
</ListItemSecondaryAction>
|
</ListItemSecondaryAction>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
<SearchSettings />
|
||||||
<ListItemButton>
|
<ListItemButton>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<ViewModuleIcon />
|
<ViewModuleIcon />
|
||||||
|
|||||||
34
src/screens/settings/SearchSettings.tsx
Normal file
34
src/screens/settings/SearchSettings.tsx
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { ListItem, ListItemText, Switch } from '@mui/material';
|
||||||
|
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
||||||
|
import React from 'react';
|
||||||
|
import { useSearchSettings } from 'util/searchSettings';
|
||||||
|
import { requestUpdateServerMetadata } from 'util/metadata';
|
||||||
|
import makeToast from 'components/util/Toast';
|
||||||
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
|
import { SearchMetadataKeys } from 'typings';
|
||||||
|
|
||||||
|
export default function SearchSettings() {
|
||||||
|
const { metadata, settings } = useSearchSettings();
|
||||||
|
|
||||||
|
const setSettingValue = (key: SearchMetadataKeys, value: boolean) => {
|
||||||
|
requestUpdateServerMetadata(metadata ?? {}, [[key, value]]).catch(() =>
|
||||||
|
makeToast('Failed to save the default search settings to the server', 'warning'),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<ListItem>
|
||||||
|
<ListItemIcon>
|
||||||
|
<SearchIcon />
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary="Ignore Filters when Searching" />
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
<Switch
|
||||||
|
edge="end"
|
||||||
|
checked={settings.ignoreFilters}
|
||||||
|
onChange={(e) => setSettingValue('ignoreFilters', e.target.checked)}
|
||||||
|
/>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -83,7 +83,9 @@ export type AllowedMetadataValueTypes = string | boolean | number | undefined;
|
|||||||
|
|
||||||
export type MangaMetadataKeys = keyof IReaderSettings;
|
export type MangaMetadataKeys = keyof IReaderSettings;
|
||||||
|
|
||||||
export type AppMetadataKeys = MangaMetadataKeys;
|
export type SearchMetadataKeys = keyof ISearchSettings;
|
||||||
|
|
||||||
|
export type AppMetadataKeys = MangaMetadataKeys | SearchMetadataKeys;
|
||||||
|
|
||||||
export type MetadataKeyValuePair = [AppMetadataKeys, AllowedMetadataValueTypes];
|
export type MetadataKeyValuePair = [AppMetadataKeys, AllowedMetadataValueTypes];
|
||||||
|
|
||||||
@@ -190,6 +192,10 @@ export interface IReaderSettings {
|
|||||||
readerType: ReaderType;
|
readerType: ReaderType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ISearchSettings {
|
||||||
|
ignoreFilters: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IReaderPage {
|
export interface IReaderPage {
|
||||||
index: number;
|
index: number;
|
||||||
src: string;
|
src: string;
|
||||||
|
|||||||
31
src/util/searchSettings.ts
Normal file
31
src/util/searchSettings.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { useQuery } from 'util/client';
|
||||||
|
import { getMetadataFrom } from 'util/metadata';
|
||||||
|
import { IMetadata, ISearchSettings, MetadataKeyValuePair } from 'typings';
|
||||||
|
|
||||||
|
export const getDefaultSettings = () =>
|
||||||
|
({
|
||||||
|
ignoreFilters: false,
|
||||||
|
} as ISearchSettings);
|
||||||
|
|
||||||
|
const getSearchSettingsWithDefaultValueFallback = (
|
||||||
|
meta?: IMetadata,
|
||||||
|
defaultSettings?: ISearchSettings,
|
||||||
|
applyMetadataMigration: boolean = true,
|
||||||
|
): ISearchSettings => ({
|
||||||
|
...(getMetadataFrom(
|
||||||
|
{ meta },
|
||||||
|
Object.entries(defaultSettings ?? getDefaultSettings()) as MetadataKeyValuePair[],
|
||||||
|
applyMetadataMigration,
|
||||||
|
) as unknown as ISearchSettings),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useSearchSettings = (): {
|
||||||
|
metadata?: IMetadata;
|
||||||
|
settings: ISearchSettings;
|
||||||
|
loading: boolean;
|
||||||
|
} => {
|
||||||
|
const { data: meta, loading } = useQuery<IMetadata>('/api/v1/meta');
|
||||||
|
const settings = getSearchSettingsWithDefaultValueFallback(meta);
|
||||||
|
|
||||||
|
return { metadata: meta, settings, loading };
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user