items per row setting (#165)

* items per row setting

self explanatory

* make it better for user
This commit is contained in:
robo
2022-04-02 01:34:10 +01:00
committed by GitHub
parent 6215ad4663
commit 9ac66d08ef
3 changed files with 133 additions and 20 deletions

View File

@@ -71,6 +71,7 @@ const truncateText = (str: string, maxLength: number) => {
interface IProps {
manga: IMangaCard
gridLayout: number | undefined
dimensions: number
}
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
const {
@@ -79,15 +80,19 @@ const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref)
id, title, thumbnailUrl, downloadCount, unreadCount: unread, inLibrary,
},
gridLayout,
dimensions,
} = props;
const { options: { showUnreadBadge, showDownloadBadge } } = useLibraryOptionsContext();
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
const [useCache] = useLocalStorage<boolean>('useCache', true);
const [ItemWidth] = useLocalStorage<number>('ItemWidth', 300);
if (gridLayout !== 2) {
const colomns = Math.round(dimensions / ItemWidth);
return (
<Grid item xs={6} sm={4} md={3} lg={2}>
// @ts-ignore gridsize type isnt allowed to be a decimal but it works fine
<Grid item lg={12 / colomns}>
<Link to={`/manga/${id}/`} style={(gridLayout === 1) ? { textDecoration: 'none' } : {}}>
<Box
sx={{

View File

@@ -5,7 +5,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import React, { useEffect, useRef } from 'react';
import React, {
useEffect, useLayoutEffect, useRef, useState,
} from 'react';
import Grid from '@mui/material/Grid';
import EmptyView from 'components/util/EmptyView';
import LoadingPlaceholder from 'components/util/LoadingPlaceholder';
@@ -49,6 +51,23 @@ export default function MangaGrid(props: IMangaGridProps) {
};
}, [hasNextPage, mangas]);
const [dimensions, setDimensions] = useState(1);
const gridRef = useRef<HTMLDivElement>(null);
const TestDimensions = () => {
setDimensions(gridRef.current ? gridRef.current.offsetWidth : 0);
};
useLayoutEffect(TestDimensions, []);
let movementTimer: NodeJS.Timeout;
window.addEventListener('resize', () => {
clearInterval(movementTimer);
movementTimer = setTimeout(TestDimensions, 100);
});
if (mangas.length === 0) {
if (isLoading) {
mapped = (
@@ -79,6 +98,7 @@ export default function MangaGrid(props: IMangaGridProps) {
manga={it}
ref={lastManga}
gridLayout={gridLayout}
dimensions={dimensions}
/>
);
}
@@ -87,30 +107,33 @@ export default function MangaGrid(props: IMangaGridProps) {
key={it.id}
manga={it}
gridLayout={gridLayout}
dimensions={dimensions}
/>
);
});
}
return (
<Grid
container
spacing={1}
style={horisontal ? {
margin: 0,
width: '100%',
padding: '5px',
overflowX: 'scroll',
display: '-webkit-inline-box',
flexWrap: 'nowrap',
} : {
margin: 0,
width: '100%',
padding: '5px',
}}
>
{mapped}
</Grid>
<div ref={gridRef}>
<Grid
container
spacing={1}
style={horisontal ? {
margin: 0,
width: '100%',
padding: '5px',
overflowX: 'scroll',
display: '-webkit-inline-box',
flexWrap: 'nowrap',
} : {
margin: 0,
width: '100%',
padding: '5px',
}}
>
{mapped}
</Grid>
</div>
);
}

View File

@@ -27,6 +27,9 @@ import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import TextField from '@mui/material/TextField';
import FavoriteIcon from '@mui/icons-material/Favorite';
import Slider from '@mui/material/Slider';
import { DialogTitle, ListItemButton } from '@mui/material';
import ViewModuleIcon from '@mui/icons-material/ViewModule';
import NavbarContext from '../components/context/NavbarContext';
import DarkTheme from '../components/context/DarkTheme';
import useLocalStorage from '../util/useLocalStorage';
@@ -43,6 +46,10 @@ export default function Settings() {
const [dialogOpen, setDialogOpen] = useState(false);
const [dialogValue, setDialogValue] = useState(serverAddress);
const [dialogOpenItemWidth, setDialogOpenItemWidth] = useState(false);
const [ItemWidth, setItemWidth] = useLocalStorage<number>('ItemWidth', 6);
const [DialogItemWidth, setDialogItemWidth] = useState(ItemWidth);
const handleDialogOpen = () => {
setDialogValue(serverAddress);
setDialogOpen(true);
@@ -57,6 +64,29 @@ export default function Settings() {
setServerAddress(dialogValue);
};
const handleDialogOpenItemWidth = () => {
setDialogItemWidth(ItemWidth);
setDialogOpenItemWidth(true);
};
const handleDialogCancelItemWidth = () => {
setDialogOpenItemWidth(false);
};
const handleDialogSubmitItemWidth = () => {
setDialogOpenItemWidth(false);
setItemWidth(DialogItemWidth);
};
const handleDialogResetItemWidth = () => {
setDialogOpenItemWidth(false);
setItemWidth(300);
};
const handleChange = (event: Event, newValue: number | number[]) => {
setDialogItemWidth(newValue as number);
};
return (
<>
<List sx={{ padding: 0 }}>
@@ -85,6 +115,18 @@ export default function Settings() {
/>
</ListItemSecondaryAction>
</ListItem>
<ListItemButton>
<ListItemIcon>
<ViewModuleIcon />
</ListItemIcon>
<ListItemText
primary="Manga Item width"
secondary={`px:${ItemWidth}`}
onClick={() => {
handleDialogOpenItemWidth();
}}
/>
</ListItemButton>
<ListItem>
<ListItemIcon>
<FavoriteIcon />
@@ -168,6 +210,49 @@ export default function Settings() {
</Button>
</DialogActions>
</Dialog>
<Dialog open={dialogOpenItemWidth} onClose={handleDialogCancelItemWidth}>
<DialogTitle>
Manga Item width
</DialogTitle>
<DialogContent
sx={{
width: '98%',
margin: 'auto',
}}
>
<TextField
sx={{
width: '100%',
margin: 'auto',
}}
autoFocus
value={DialogItemWidth}
type="number"
onChange={(e) => setDialogItemWidth(parseInt(e.target.value, 10))}
/>
<Slider
aria-label="Manga Item width"
defaultValue={300}
value={DialogItemWidth}
step={10}
min={100}
max={1000}
onChange={handleChange}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleDialogResetItemWidth} color="primary">
Reset to Default
</Button>
<Button onClick={handleDialogCancelItemWidth} color="primary">
Cancel
</Button>
<Button onClick={handleDialogSubmitItemWidth} color="primary">
OK
</Button>
</DialogActions>
</Dialog>
</>
);
}