add comfortable grid option (#152)

* move sorts to copy tachiyomi

is now in a tab along with filter ad display same as tachiyomi

* add comfortable grid

and all the stuff needed to make it easy to add more

* Revert "Merge remote-tracking branch 'upstream/master' into grid-types-(comfortable/list)"

This reverts commit 33eed92e8f7259ddce0e34ab59f721553bbb7e93, reversing
changes made to d699955345e253d2b2c2d837e76509a39b3bef00.
This commit is contained in:
robo
2022-03-06 16:45:25 +00:00
committed by GitHub
parent 08a53053b2
commit 0a63d60880
7 changed files with 113 additions and 46 deletions

View File

@@ -13,7 +13,7 @@ import { Link } from 'react-router-dom';
import { Grid } from '@mui/material';
import useLocalStorage from 'util/useLocalStorage';
import SpinnerImage from 'components/util/SpinnerImage';
import { styled } from '@mui/system';
import { Box, styled } from '@mui/system';
import { useLibraryOptionsContext } from 'components/context/LibraryOptionsContext';
const BottomGradient = styled('div')({
@@ -70,12 +70,14 @@ const truncateText = (str: string, maxLength: number) => {
interface IProps {
manga: IMangaCard
gridLayout: number | undefined
}
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
const {
manga: {
id, title, thumbnailUrl, downloadCount, unreadCount: unread,
},
gridLayout,
} = props;
const { options: { showUnreadBadge, showDownloadBadge } } = useLibraryOptionsContext();
@@ -84,60 +86,83 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
return (
<Grid item xs={6} sm={4} md={3} lg={2}>
<Link to={`/manga/${id}/`}>
<Card
<Link to={`/manga/${id}/`} style={(gridLayout === 1) ? { textDecoration: 'none' } : {}}>
<Box
sx={{
// force standard aspect ratio of manga covers
aspectRatio: '225/350',
display: 'flex',
flexDirection: 'column',
}}
ref={ref}
>
<CardActionArea
<Card
sx={{
position: 'relative',
height: '100%',
// force standard aspect ratio of manga covers
aspectRatio: '225/350',
display: 'flex',
}}
ref={ref}
>
<BadgeContainer>
{ showUnreadBadge && unread! > 0 && (
<Typography
sx={{ backgroundColor: 'primary.dark' }}
>
{unread}
</Typography>
)}
{ showDownloadBadge && downloadCount! > 0 && (
<Typography sx={{
backgroundColor: 'success.dark',
}}
>
{downloadCount}
</Typography>
)}
</BadgeContainer>
<SpinnerImage
alt={title}
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
imgStyle={{
<CardActionArea
sx={{
position: 'relative',
height: '100%',
width: '100%',
objectFit: 'cover',
}}
spinnerStyle={{
display: 'grid',
placeItems: 'center',
}}
/>
<BottomGradient />
<BottomGradientDoubledDown />
>
<MangaTitle>
<BadgeContainer>
{ showUnreadBadge && unread! > 0 && (
<Typography
sx={{ backgroundColor: 'primary.dark' }}
>
{unread}
</Typography>
)}
{ showDownloadBadge && downloadCount! > 0 && (
<Typography sx={{
backgroundColor: 'success.dark',
}}
>
{downloadCount}
</Typography>
)}
</BadgeContainer>
<SpinnerImage
alt={title}
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
imgStyle={{
height: '100%',
width: '100%',
objectFit: 'cover',
}}
spinnerStyle={{
display: 'grid',
placeItems: 'center',
}}
/>
{(gridLayout === 1) ? (<></>) : (
<>
<BottomGradient />
<BottomGradientDoubledDown />
</>
)}
{(gridLayout === 1) ? (
<></>
) : (
<MangaTitle>
{truncateText(title, 61)}
</MangaTitle>
)}
</CardActionArea>
</Card>
{(gridLayout === 1) ? (
<MangaTitle
sx={{
position: 'relative',
}}
>
{truncateText(title, 61)}
</MangaTitle>
</CardActionArea>
</Card>
) : (<></>)}
</Box>
</Link>
</Grid>
);

View File

@@ -19,11 +19,13 @@ export interface IMangaGridProps{
hasNextPage: boolean
lastPageNum: number
setLastPageNum: (lastPageNum: number) => void
gridLayout?: number | undefined
}
export default function MangaGrid(props: IMangaGridProps) {
const {
mangas, isLoading, message, messageExtra, hasNextPage, lastPageNum, setLastPageNum,
mangas, isLoading, message, messageExtra,
hasNextPage, lastPageNum, setLastPageNum, gridLayout,
} = props;
let mapped;
const lastManga = useRef<HTMLDivElement>(null);
@@ -61,6 +63,7 @@ export default function MangaGrid(props: IMangaGridProps) {
key={it.id}
manga={it}
ref={lastManga}
gridLayout={gridLayout}
/>
);
}
@@ -68,6 +71,7 @@ export default function MangaGrid(props: IMangaGridProps) {
<MangaCard
key={it.id}
manga={it}
gridLayout={gridLayout}
/>
);
});

View File

@@ -8,12 +8,13 @@
import React, { useContext } from 'react';
type ContextType = {
// display options
options: LibraryDisplayOptions;
setOptions: React.Dispatch<React.SetStateAction<LibraryDisplayOptions>>;
};
const LibraryOptionsContext = React.createContext<ContextType>({
options: { showDownloadBadge: false, showUnreadBadge: false },
options: { showDownloadBadge: false, showUnreadBadge: false, gridLayout: 0 },
setOptions: () => {},
});

View File

@@ -9,6 +9,7 @@
import React from 'react';
import MangaGrid, { IMangaGridProps } from 'components/MangaGrid';
import useLibraryOptions from 'util/useLibraryOptions';
import { useLibraryOptionsContext } from 'components/context/LibraryOptionsContext';
const FILTERED_OUT_MESSAGE = 'There are no Manga matching this filter';
@@ -79,6 +80,7 @@ export default function LibraryMangaGrid(props: IMangaGridProps) {
mangas, isLoading, hasNextPage, lastPageNum, setLastPageNum, message,
} = props;
const { options } = useLibraryOptionsContext();
const { active, query } = useLibraryOptions();
const filteredManga = filterManga(mangas);
const sortedManga = sortManga(filteredManga);
@@ -93,6 +95,7 @@ export default function LibraryMangaGrid(props: IMangaGridProps) {
lastPageNum={lastPageNum}
setLastPageNum={setLastPageNum}
message={showFilteredOutMessage ? FILTERED_OUT_MESSAGE : message}
gridLayout={options.gridLayout}
/>
);
}

View File

@@ -21,6 +21,7 @@ import {
ListItemButton,
ListItemIcon,
ListItemText,
Radio,
} from '@mui/material';
import useLibraryOptions from 'util/useLibraryOptions';
import ThreeStateCheckbox from 'components/util/ThreeStateCheckbox';
@@ -111,9 +112,41 @@ function dispalyTab(currentTab: number) {
) {
setOptions((prev) => ({ ...prev, [e.target.name]: checked }));
}
function setGridContextOptions(
e: React.ChangeEvent<HTMLInputElement>,
checked: boolean,
) {
if (checked) {
setOptions((prev) => ({ ...prev, gridLayout: parseInt(e.target.name, 10) }));
}
}
return (
<TabPanel index={2} currentIndex={currentTab}>
<Stack direction="column">
DISPLAY MODE
<FormControlLabel
label="Compact grid"
control={(
<Radio
name="0"
checked={options.gridLayout === 0 || options.gridLayout === undefined}
onChange={setGridContextOptions}
/>
)}
/>
<FormControlLabel
label="Comfortable grid"
control={(
<Radio
name="1"
checked={options.gridLayout === 1}
onChange={setGridContextOptions}
/>
)}
/>
BADGES
<FormControlLabel
label="Unread Badges"
control={(

View File

@@ -15,7 +15,7 @@ interface IProps {
export default function LibraryOptionsContextProvider({ children }: IProps) {
const [options, setOptions] = useLocalStorage<LibraryDisplayOptions>('libraryOptions',
{ showDownloadBadge: false, showUnreadBadge: false });
{ showDownloadBadge: false, showUnreadBadge: false, gridLayout: 0 });
return (
<LibraryOptionsContext.Provider value={{ options, setOptions }}>

1
src/typings.d.ts vendored
View File

@@ -264,4 +264,5 @@ type ChapterOptionsReducerAction =
interface LibraryDisplayOptions {
showDownloadBadge: boolean
showUnreadBadge: boolean
gridLayout: number
}