Add bookmarked filter in library (#687)
This commit is contained in:
@@ -28,6 +28,7 @@ export const DefaultLibraryOptions: LibraryOptions = {
|
|||||||
SourcegridLayout: GridLayout.Compact,
|
SourcegridLayout: GridLayout.Compact,
|
||||||
|
|
||||||
downloaded: undefined,
|
downloaded: undefined,
|
||||||
|
bookmarked: undefined,
|
||||||
sortDesc: undefined,
|
sortDesc: undefined,
|
||||||
sorts: undefined,
|
sorts: undefined,
|
||||||
unread: undefined,
|
unread: undefined,
|
||||||
|
|||||||
@@ -70,6 +70,11 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
|
|||||||
checked={options.downloaded}
|
checked={options.downloaded}
|
||||||
onChange={(c) => handleFilterChange('downloaded', c)}
|
onChange={(c) => handleFilterChange('downloaded', c)}
|
||||||
/>
|
/>
|
||||||
|
<ThreeStateCheckboxInput
|
||||||
|
label={t('global.filter.label.bookmarked')}
|
||||||
|
checked={options.bookmarked}
|
||||||
|
onChange={(c) => handleFilterChange('bookmarked', c)}
|
||||||
|
/>
|
||||||
<FormLabel sx={{ mt: 2 }}>{t('global.filter.label.tracked')}</FormLabel>
|
<FormLabel sx={{ mt: 2 }}>{t('global.filter.label.tracked')}</FormLabel>
|
||||||
{loggedInTrackers.map((tracker) => (
|
{loggedInTrackers.map((tracker) => (
|
||||||
<ThreeStateCheckboxInput
|
<ThreeStateCheckboxInput
|
||||||
|
|||||||
@@ -35,6 +35,17 @@ const downloadedFilter = (downloaded: NullAndUndefined<boolean>, { downloadCount
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bookmarkedFilter = (bookmarked: NullAndUndefined<boolean>, { bookmarkCount }: TManga): boolean => {
|
||||||
|
switch (bookmarked) {
|
||||||
|
case true:
|
||||||
|
return !!bookmarkCount && bookmarkCount >= 1;
|
||||||
|
case false:
|
||||||
|
return bookmarkCount === 0;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const queryFilter = (query: NullAndUndefined<string>, { title }: TManga): boolean => {
|
const queryFilter = (query: NullAndUndefined<string>, { title }: TManga): boolean => {
|
||||||
if (!query) return true;
|
if (!query) return true;
|
||||||
return title.toLowerCase().includes(query.toLowerCase());
|
return title.toLowerCase().includes(query.toLowerCase());
|
||||||
@@ -68,6 +79,7 @@ const filterManga = (
|
|||||||
query: NullAndUndefined<string>,
|
query: NullAndUndefined<string>,
|
||||||
unread: NullAndUndefined<boolean>,
|
unread: NullAndUndefined<boolean>,
|
||||||
downloaded: NullAndUndefined<boolean>,
|
downloaded: NullAndUndefined<boolean>,
|
||||||
|
bookmarked: NullAndUndefined<boolean>,
|
||||||
tracker: LibraryOptions['tracker'],
|
tracker: LibraryOptions['tracker'],
|
||||||
ignoreFilters: boolean,
|
ignoreFilters: boolean,
|
||||||
): TManga[] =>
|
): TManga[] =>
|
||||||
@@ -76,7 +88,10 @@ const filterManga = (
|
|||||||
const matchesSearch = queryFilter(query, manga) || queryGenreFilter(query, manga);
|
const matchesSearch = queryFilter(query, manga) || queryGenreFilter(query, manga);
|
||||||
const matchesFilters =
|
const matchesFilters =
|
||||||
ignoreFiltersWhileSearching ||
|
ignoreFiltersWhileSearching ||
|
||||||
(downloadedFilter(downloaded, manga) && unreadFilter(unread, manga) && trackerFilter(tracker, manga));
|
(downloadedFilter(downloaded, manga) &&
|
||||||
|
unreadFilter(unread, manga) &&
|
||||||
|
bookmarkedFilter(bookmarked, manga) &&
|
||||||
|
trackerFilter(tracker, manga));
|
||||||
|
|
||||||
return matchesSearch && matchesFilters;
|
return matchesSearch && matchesFilters;
|
||||||
});
|
});
|
||||||
@@ -136,12 +151,12 @@ const sortManga = (
|
|||||||
export const useGetVisibleLibraryMangas = (mangas: TManga[]) => {
|
export const useGetVisibleLibraryMangas = (mangas: TManga[]) => {
|
||||||
const [query] = useQueryParam('query', StringParam);
|
const [query] = useQueryParam('query', StringParam);
|
||||||
const { options } = useLibraryOptionsContext();
|
const { options } = useLibraryOptionsContext();
|
||||||
const { unread, downloaded, tracker } = options;
|
const { unread, downloaded, bookmarked, tracker } = options;
|
||||||
const { settings } = useMetadataServerSettings();
|
const { settings } = useMetadataServerSettings();
|
||||||
|
|
||||||
const filteredMangas = useMemo(
|
const filteredMangas = useMemo(
|
||||||
() => filterManga(mangas, query, unread, downloaded, tracker, settings.ignoreFilters),
|
() => filterManga(mangas, query, unread, downloaded, bookmarked, tracker, settings.ignoreFilters),
|
||||||
[mangas, query, unread, downloaded, tracker, settings.ignoreFilters],
|
[mangas, query, unread, downloaded, bookmarked, tracker, settings.ignoreFilters],
|
||||||
);
|
);
|
||||||
const sortedMangas = useMemo(
|
const sortedMangas = useMemo(
|
||||||
() => sortManga(filteredMangas, options.sorts, options.sortDesc),
|
() => sortManga(filteredMangas, options.sorts, options.sortDesc),
|
||||||
@@ -150,7 +165,7 @@ export const useGetVisibleLibraryMangas = (mangas: TManga[]) => {
|
|||||||
|
|
||||||
const isATrackFilterActive = Object.values(options.tracker).some((trackFilterState) => trackFilterState != null);
|
const isATrackFilterActive = Object.values(options.tracker).some((trackFilterState) => trackFilterState != null);
|
||||||
const showFilteredOutMessage =
|
const showFilteredOutMessage =
|
||||||
(unread != null || downloaded != null || !!query || isATrackFilterActive) &&
|
(unread != null || downloaded != null || bookmarked != null || !!query || isATrackFilterActive) &&
|
||||||
filteredMangas.length === 0 &&
|
filteredMangas.length === 0 &&
|
||||||
mangas.length > 0;
|
mangas.length > 0;
|
||||||
|
|
||||||
|
|||||||
@@ -291,6 +291,7 @@ export const PARTIAL_MANGA_FIELDS = gql`
|
|||||||
...BASE_MANGA_FIELDS
|
...BASE_MANGA_FIELDS
|
||||||
unreadCount
|
unreadCount
|
||||||
downloadCount
|
downloadCount
|
||||||
|
bookmarkCount
|
||||||
categories {
|
categories {
|
||||||
nodes {
|
nodes {
|
||||||
...FULL_CATEGORY_FIELDS
|
...FULL_CATEGORY_FIELDS
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -117,6 +117,10 @@ export const UPDATE_CHAPTER = gql`
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
manga @include(if: $getBookmarked) {
|
||||||
|
id
|
||||||
|
bookmarkCount
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deleteDownloadedChapter(input: { id: $chapterIdToDelete }) @include(if: $deleteChapter) {
|
deleteDownloadedChapter(input: { id: $chapterIdToDelete }) @include(if: $deleteChapter) {
|
||||||
@@ -163,6 +167,10 @@ export const UPDATE_CHAPTERS = gql`
|
|||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
manga @include(if: $getBookmarked) {
|
||||||
|
id
|
||||||
|
bookmarkCount
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
deleteDownloadedChapters(input: { ids: $chapterIdsToDelete }) @include(if: $deleteChapters) {
|
deleteDownloadedChapters(input: { ids: $chapterIdsToDelete }) @include(if: $deleteChapters) {
|
||||||
|
|||||||
@@ -101,7 +101,10 @@ export interface IMangaCard {
|
|||||||
|
|
||||||
export type TManga = GetMangaQuery['manga'];
|
export type TManga = GetMangaQuery['manga'];
|
||||||
|
|
||||||
export type TPartialManga = OptionalProperty<TManga, 'unreadCount' | 'downloadCount' | 'categories' | 'chapters'>;
|
export type TPartialManga = OptionalProperty<
|
||||||
|
TManga,
|
||||||
|
'unreadCount' | 'downloadCount' | 'bookmarkCount' | 'categories' | 'chapters'
|
||||||
|
>;
|
||||||
|
|
||||||
export interface IManga {
|
export interface IManga {
|
||||||
id: number;
|
id: number;
|
||||||
@@ -388,6 +391,7 @@ export interface LibraryOptions {
|
|||||||
|
|
||||||
// filter options
|
// filter options
|
||||||
downloaded: NullAndUndefined<boolean>;
|
downloaded: NullAndUndefined<boolean>;
|
||||||
|
bookmarked: NullAndUndefined<boolean>;
|
||||||
unread: NullAndUndefined<boolean>;
|
unread: NullAndUndefined<boolean>;
|
||||||
sorts: NullAndUndefined<LibrarySortMode>;
|
sorts: NullAndUndefined<LibrarySortMode>;
|
||||||
sortDesc: NullAndUndefined<boolean>;
|
sortDesc: NullAndUndefined<boolean>;
|
||||||
|
|||||||
Reference in New Issue
Block a user