diff --git a/src/components/MangaCard.tsx b/src/components/MangaCard.tsx index b7e4bbf13d..aa3f8c0367 100644 --- a/src/components/MangaCard.tsx +++ b/src/components/MangaCard.tsx @@ -40,17 +40,21 @@ const MangaTitle = styled(Typography)({ textShadow: '0px 0px 3px #000000', }); -const UnreadBadge = styled(Typography)(({ theme }) => ({ +const BadgeContainer = styled('div')({ + display: 'flex', position: 'absolute', - top: 2, - left: 2, - backgroundColor: theme.palette.primary.dark, + top: 5, + left: 5, + height: 'fit-content', borderRadius: '5px', - color: 'white', - padding: '0.1em', - paddingInline: '0.3em', - fontSize: '1.05rem', -})); + overflow: 'hidden', + '& p': { + color: 'white', + padding: '0.1em', + paddingInline: '0.2em', + fontSize: '1.05rem', + }, +}); const truncateText = (str: string, maxLength: number) => { const ending = '...'; @@ -69,7 +73,7 @@ interface IProps { const MangaCard = React.forwardRef((props: IProps, ref) => { const { manga: { - id, title, thumbnailUrl, unreadCount: unread, + id, title, thumbnailUrl, downloadCount, unreadCount: unread, }, } = props; @@ -93,12 +97,24 @@ const MangaCard = React.forwardRef((props: IProps, ref) height: '100%', }} > - {unread! > 0 - && ( - + + + {unread! > 0 && ( + {unread} - - ) } + + )} + {downloadCount! > 0 && ( + + {downloadCount} + + )} + ((props: IProps, ref) width: '100%', }} spinnerStyle={{ - minHeight: '400px', display: 'grid', placeItems: 'center', }} diff --git a/src/components/library/LibraryMangaGrid.tsx b/src/components/library/LibraryMangaGrid.tsx index dd86300015..13a6bb0c5c 100644 --- a/src/components/library/LibraryMangaGrid.tsx +++ b/src/components/library/LibraryMangaGrid.tsx @@ -23,15 +23,29 @@ function unreadFilter(unread: NullAndUndefined, { unreadCount }: IManga } } +function downloadedFilter(downloaded: NullAndUndefined, + { downloadCount }: IMangaCard): boolean { + switch (downloaded) { + case true: + return !!downloadCount && downloadCount >= 1; + case false: + return downloadCount === 0; + default: + return true; + } +} + function queryFilter(query: NullAndUndefined, { title }: IMangaCard): boolean { if (!query) return true; return title.toLowerCase().includes(query.toLowerCase()); } function filterManga(mangas: IMangaCard[]): IMangaCard[] { - const { unread, query } = useLibraryOptions(); + const { downloaded, unread, query } = useLibraryOptions(); return mangas - .filter((manga) => unreadFilter(unread, manga) && queryFilter(query, manga)); + .filter((manga) => downloadedFilter(downloaded, manga) + && unreadFilter(unread, manga) + && queryFilter(query, manga)); } export default function LibraryMangaGrid(props: IMangaGridProps) { diff --git a/src/components/library/LibraryOptions.tsx b/src/components/library/LibraryOptions.tsx index 1795dfc400..7bc1b00ff3 100644 --- a/src/components/library/LibraryOptions.tsx +++ b/src/components/library/LibraryOptions.tsx @@ -13,10 +13,13 @@ import useLibraryOptions from 'util/useLibraryOptions'; import ThreeStateCheckbox from 'components/util/ThreeStateCheckbox'; function Options() { - const { unread, setUnread } = useLibraryOptions(); + const { + downloaded, setDownloaded, unread, setUnread, + } = useLibraryOptions(); return ( -
+
} label="Unread" /> + } label="Downloaded" />
); } diff --git a/src/typings.d.ts b/src/typings.d.ts index 5913ed6313..1bbf9a555a 100644 --- a/src/typings.d.ts +++ b/src/typings.d.ts @@ -35,6 +35,7 @@ interface IMangaCard { title: string thumbnailUrl: string unreadCount?: number + downloadCount?: number } interface IManga { @@ -58,6 +59,7 @@ interface IManga { freshData: boolean unreadCount?: number + downloadCount?: number } interface IChapter { diff --git a/src/util/useLibraryOptions.ts b/src/util/useLibraryOptions.ts index 50d4bba9a2..5b3450e7c6 100644 --- a/src/util/useLibraryOptions.ts +++ b/src/util/useLibraryOptions.ts @@ -11,6 +11,8 @@ import { BooleanParam, useQueryParams, StringParam } from 'use-query-params'; export type NullAndUndefined = T | null | undefined; interface IUseLibraryOptions { + downloaded: NullAndUndefined + setDownloaded: (downloaded: NullAndUndefined)=>void unread: NullAndUndefined setUnread: (unread: NullAndUndefined) => void query: NullAndUndefined @@ -20,10 +22,14 @@ interface IUseLibraryOptions { export default function useLibraryOptions(): IUseLibraryOptions { const [searchQuery, setSearchQuery] = useQueryParams({ + downloaded: BooleanParam, unread: BooleanParam, query: StringParam, }); - const { unread, query } = searchQuery; + const { downloaded, unread, query } = searchQuery; + const setDownloaded = (newDownloaded: NullAndUndefined) => { + setSearchQuery(Object.assign(searchQuery, { downloaded: newDownloaded }), 'replace'); + }; const setUnread = (newUnread: NullAndUndefined) => { setSearchQuery(Object.assign(searchQuery, { unread: newUnread }), 'replace'); }; @@ -31,8 +37,8 @@ export default function useLibraryOptions(): IUseLibraryOptions { setSearchQuery(Object.assign(searchQuery, { query: newQuery }), 'replace'); }; // eslint-disable-next-line eqeqeq - const active = !(unread == undefined); + const active = !(unread == undefined) || !(downloaded == undefined); return { - unread, setUnread, active, query, setQuery, + downloaded, setDownloaded, unread, setUnread, active, query, setQuery, }; }