add filter and badge for downloadCount (#62)

* Added the Download filter and download badge

* Update src/components/library/LibraryMangaGrid.tsx

Co-authored-by: Sascha Hahne <ntbm@users.noreply.github.com>

* - corrected some spelling mistakes

Co-authored-by: Sascha Hahne <ntbm@users.noreply.github.com>
This commit is contained in:
abhijeetChawla
2021-11-07 15:59:48 +05:30
committed by GitHub
parent f816abfdc9
commit 42c5c3042d
5 changed files with 63 additions and 23 deletions

View File

@@ -40,17 +40,21 @@ const MangaTitle = styled(Typography)({
textShadow: '0px 0px 3px #000000', textShadow: '0px 0px 3px #000000',
}); });
const UnreadBadge = styled(Typography)(({ theme }) => ({ const BadgeContainer = styled('div')({
display: 'flex',
position: 'absolute', position: 'absolute',
top: 2, top: 5,
left: 2, left: 5,
backgroundColor: theme.palette.primary.dark, height: 'fit-content',
borderRadius: '5px', borderRadius: '5px',
color: 'white', overflow: 'hidden',
padding: '0.1em', '& p': {
paddingInline: '0.3em', color: 'white',
fontSize: '1.05rem', padding: '0.1em',
})); paddingInline: '0.2em',
fontSize: '1.05rem',
},
});
const truncateText = (str: string, maxLength: number) => { const truncateText = (str: string, maxLength: number) => {
const ending = '...'; const ending = '...';
@@ -69,7 +73,7 @@ interface IProps {
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => { const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
const { const {
manga: { manga: {
id, title, thumbnailUrl, unreadCount: unread, id, title, thumbnailUrl, downloadCount, unreadCount: unread,
}, },
} = props; } = props;
@@ -93,12 +97,24 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
height: '100%', height: '100%',
}} }}
> >
{unread! > 0
&& ( <BadgeContainer>
<UnreadBadge> {unread! > 0 && (
<Typography
sx={{ backgroundColor: 'primary.dark' }}
>
{unread} {unread}
</UnreadBadge> </Typography>
) } )}
{downloadCount! > 0 && (
<Typography sx={{
backgroundColor: 'success.dark',
}}
>
{downloadCount}
</Typography>
)}
</BadgeContainer>
<SpinnerImage <SpinnerImage
alt={title} alt={title}
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`} src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
@@ -107,7 +123,6 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
width: '100%', width: '100%',
}} }}
spinnerStyle={{ spinnerStyle={{
minHeight: '400px',
display: 'grid', display: 'grid',
placeItems: 'center', placeItems: 'center',
}} }}

View File

@@ -23,15 +23,29 @@ function unreadFilter(unread: NullAndUndefined<boolean>, { unreadCount }: IManga
} }
} }
function downloadedFilter(downloaded: NullAndUndefined<boolean>,
{ downloadCount }: IMangaCard): boolean {
switch (downloaded) {
case true:
return !!downloadCount && downloadCount >= 1;
case false:
return downloadCount === 0;
default:
return true;
}
}
function queryFilter(query: NullAndUndefined<string>, { title }: IMangaCard): boolean { function queryFilter(query: NullAndUndefined<string>, { title }: IMangaCard): boolean {
if (!query) return true; if (!query) return true;
return title.toLowerCase().includes(query.toLowerCase()); return title.toLowerCase().includes(query.toLowerCase());
} }
function filterManga(mangas: IMangaCard[]): IMangaCard[] { function filterManga(mangas: IMangaCard[]): IMangaCard[] {
const { unread, query } = useLibraryOptions(); const { downloaded, unread, query } = useLibraryOptions();
return mangas 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) { export default function LibraryMangaGrid(props: IMangaGridProps) {

View File

@@ -13,10 +13,13 @@ import useLibraryOptions from 'util/useLibraryOptions';
import ThreeStateCheckbox from 'components/util/ThreeStateCheckbox'; import ThreeStateCheckbox from 'components/util/ThreeStateCheckbox';
function Options() { function Options() {
const { unread, setUnread } = useLibraryOptions(); const {
downloaded, setDownloaded, unread, setUnread,
} = useLibraryOptions();
return ( return (
<div> <div style={{ display: 'flex', flexDirection: 'column' }}>
<FormControlLabel control={<ThreeStateCheckbox name="Unread" checked={unread} onChange={setUnread} />} label="Unread" /> <FormControlLabel control={<ThreeStateCheckbox name="Unread" checked={unread} onChange={setUnread} />} label="Unread" />
<FormControlLabel control={<ThreeStateCheckbox name="Downloaded" checked={downloaded} onChange={setDownloaded} />} label="Downloaded" />
</div> </div>
); );
} }

2
src/typings.d.ts vendored
View File

@@ -35,6 +35,7 @@ interface IMangaCard {
title: string title: string
thumbnailUrl: string thumbnailUrl: string
unreadCount?: number unreadCount?: number
downloadCount?: number
} }
interface IManga { interface IManga {
@@ -58,6 +59,7 @@ interface IManga {
freshData: boolean freshData: boolean
unreadCount?: number unreadCount?: number
downloadCount?: number
} }
interface IChapter { interface IChapter {

View File

@@ -11,6 +11,8 @@ import { BooleanParam, useQueryParams, StringParam } from 'use-query-params';
export type NullAndUndefined<T> = T | null | undefined; export type NullAndUndefined<T> = T | null | undefined;
interface IUseLibraryOptions { interface IUseLibraryOptions {
downloaded: NullAndUndefined<boolean>
setDownloaded: (downloaded: NullAndUndefined<boolean>)=>void
unread: NullAndUndefined<boolean> unread: NullAndUndefined<boolean>
setUnread: (unread: NullAndUndefined<boolean>) => void setUnread: (unread: NullAndUndefined<boolean>) => void
query: NullAndUndefined<string> query: NullAndUndefined<string>
@@ -20,10 +22,14 @@ interface IUseLibraryOptions {
export default function useLibraryOptions(): IUseLibraryOptions { export default function useLibraryOptions(): IUseLibraryOptions {
const [searchQuery, setSearchQuery] = useQueryParams({ const [searchQuery, setSearchQuery] = useQueryParams({
downloaded: BooleanParam,
unread: BooleanParam, unread: BooleanParam,
query: StringParam, query: StringParam,
}); });
const { unread, query } = searchQuery; const { downloaded, unread, query } = searchQuery;
const setDownloaded = (newDownloaded: NullAndUndefined<boolean>) => {
setSearchQuery(Object.assign(searchQuery, { downloaded: newDownloaded }), 'replace');
};
const setUnread = (newUnread: NullAndUndefined<boolean>) => { const setUnread = (newUnread: NullAndUndefined<boolean>) => {
setSearchQuery(Object.assign(searchQuery, { unread: newUnread }), 'replace'); setSearchQuery(Object.assign(searchQuery, { unread: newUnread }), 'replace');
}; };
@@ -31,8 +37,8 @@ export default function useLibraryOptions(): IUseLibraryOptions {
setSearchQuery(Object.assign(searchQuery, { query: newQuery }), 'replace'); setSearchQuery(Object.assign(searchQuery, { query: newQuery }), 'replace');
}; };
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
const active = !(unread == undefined); const active = !(unread == undefined) || !(downloaded == undefined);
return { return {
unread, setUnread, active, query, setQuery, downloaded, setDownloaded, unread, setUnread, active, query, setQuery,
}; };
} }