2021-03-26 04:17:02 +04:30
|
|
|
/*
|
|
|
|
|
* Copyright (C) Contributors to the Suwayomi project
|
|
|
|
|
*
|
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
2021-01-26 23:32:12 +03:30
|
|
|
* 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/. */
|
|
|
|
|
|
2023-02-06 10:06:33 +01:00
|
|
|
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
2021-09-09 17:51:22 +04:30
|
|
|
import Grid from '@mui/material/Grid';
|
2021-10-30 16:10:34 +03:30
|
|
|
import EmptyView from 'components/util/EmptyView';
|
|
|
|
|
import LoadingPlaceholder from 'components/util/LoadingPlaceholder';
|
2022-03-12 04:46:55 +00:00
|
|
|
import { Typography } from '@mui/material';
|
|
|
|
|
import { Box } from '@mui/system';
|
2023-02-05 16:15:20 +01:00
|
|
|
import MangaCard from 'components/MangaCard';
|
|
|
|
|
import { GridLayout } from 'components/context/LibraryOptionsContext';
|
2021-01-20 15:26:52 +03:30
|
|
|
|
2023-02-06 10:06:33 +01:00
|
|
|
export interface IMangaGridProps {
|
|
|
|
|
mangas: IMangaCard[];
|
|
|
|
|
isLoading: boolean;
|
|
|
|
|
message?: string;
|
|
|
|
|
messageExtra?: JSX.Element;
|
|
|
|
|
hasNextPage: boolean;
|
|
|
|
|
lastPageNum: number;
|
|
|
|
|
setLastPageNum: (lastPageNum: number) => void;
|
|
|
|
|
gridLayout?: GridLayout;
|
2023-02-12 20:43:41 +05:30
|
|
|
horizontal?: boolean | undefined;
|
2023-02-06 10:06:33 +01:00
|
|
|
noFaces?: boolean | undefined;
|
|
|
|
|
inLibraryIndicator?: boolean;
|
2021-01-20 15:26:52 +03:30
|
|
|
}
|
|
|
|
|
|
2022-11-24 21:04:30 +01:00
|
|
|
const MangaGrid: React.FC<IMangaGridProps> = (props) => {
|
2021-01-22 21:11:00 +03:30
|
|
|
const {
|
2023-02-06 10:06:33 +01:00
|
|
|
mangas,
|
|
|
|
|
isLoading,
|
|
|
|
|
message,
|
|
|
|
|
messageExtra,
|
|
|
|
|
hasNextPage,
|
|
|
|
|
lastPageNum,
|
|
|
|
|
setLastPageNum,
|
|
|
|
|
gridLayout,
|
2023-02-12 20:43:41 +05:30
|
|
|
horizontal,
|
2023-02-06 10:06:33 +01:00
|
|
|
noFaces,
|
2022-11-24 21:04:30 +01:00
|
|
|
inLibraryIndicator,
|
2021-01-22 21:11:00 +03:30
|
|
|
} = props;
|
2021-01-20 15:26:52 +03:30
|
|
|
let mapped;
|
2021-09-09 18:37:23 +04:30
|
|
|
const lastManga = useRef<HTMLDivElement>(null);
|
2021-01-22 21:11:00 +03:30
|
|
|
|
|
|
|
|
const scrollHandler = () => {
|
|
|
|
|
if (lastManga.current) {
|
|
|
|
|
const rect = lastManga.current.getBoundingClientRect();
|
2023-02-06 10:06:33 +01:00
|
|
|
if ((rect.y + rect.height) / window.innerHeight < 2 && hasNextPage) {
|
2021-01-22 21:11:00 +03:30
|
|
|
setLastPageNum(lastPageNum + 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
window.addEventListener('scroll', scrollHandler, true);
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener('scroll', scrollHandler, true);
|
|
|
|
|
};
|
|
|
|
|
}, [hasNextPage, mangas]);
|
2021-01-20 15:26:52 +03:30
|
|
|
|
2022-04-02 01:34:10 +01:00
|
|
|
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);
|
|
|
|
|
});
|
|
|
|
|
|
2021-01-20 15:26:52 +03:30
|
|
|
if (mangas.length === 0) {
|
2021-10-24 22:56:10 +03:30
|
|
|
if (isLoading) {
|
2023-02-06 10:06:33 +01:00
|
|
|
mapped = <LoadingPlaceholder />;
|
2021-10-24 22:56:10 +03:30
|
|
|
} else {
|
2022-03-12 04:46:55 +00:00
|
|
|
mapped = noFaces ? (
|
|
|
|
|
<Box
|
|
|
|
|
sx={{
|
|
|
|
|
margin: 'auto',
|
|
|
|
|
}}
|
|
|
|
|
>
|
2023-02-06 10:06:33 +01:00
|
|
|
<Typography variant="h5">{message}</Typography>
|
2022-03-12 04:46:55 +00:00
|
|
|
{messageExtra}
|
|
|
|
|
</Box>
|
|
|
|
|
) : (
|
2021-10-24 22:56:10 +03:30
|
|
|
<EmptyView message={message!} messageExtra={messageExtra} />
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-01-20 15:26:52 +03:30
|
|
|
} else {
|
2022-11-24 21:04:30 +01:00
|
|
|
mapped = mangas.map((it, idx) => (
|
|
|
|
|
<MangaCard
|
|
|
|
|
key={it.id}
|
|
|
|
|
manga={it}
|
|
|
|
|
ref={idx === mangas.length - 1 ? lastManga : undefined}
|
|
|
|
|
gridLayout={gridLayout}
|
|
|
|
|
dimensions={dimensions}
|
|
|
|
|
inLibraryIndicator={inLibraryIndicator}
|
|
|
|
|
/>
|
|
|
|
|
));
|
2021-01-20 15:26:52 +03:30
|
|
|
}
|
|
|
|
|
|
2021-01-22 21:11:00 +03:30
|
|
|
return (
|
2022-04-02 01:34:10 +01:00
|
|
|
<div ref={gridRef}>
|
|
|
|
|
<Grid
|
|
|
|
|
container
|
|
|
|
|
spacing={1}
|
2023-02-06 10:06:33 +01:00
|
|
|
style={
|
2023-02-12 20:43:41 +05:30
|
|
|
horizontal
|
2023-02-06 10:06:33 +01:00
|
|
|
? {
|
|
|
|
|
margin: 0,
|
|
|
|
|
width: '100%',
|
|
|
|
|
padding: '5px',
|
|
|
|
|
overflowX: 'scroll',
|
|
|
|
|
display: '-webkit-inline-box',
|
|
|
|
|
flexWrap: 'nowrap',
|
|
|
|
|
}
|
|
|
|
|
: {
|
|
|
|
|
margin: 0,
|
|
|
|
|
width: '100%',
|
|
|
|
|
padding: '5px',
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-04-02 01:34:10 +01:00
|
|
|
>
|
|
|
|
|
{mapped}
|
|
|
|
|
</Grid>
|
|
|
|
|
</div>
|
2021-01-22 21:11:00 +03:30
|
|
|
);
|
2022-11-24 21:04:30 +01:00
|
|
|
};
|
2021-01-22 21:11:00 +03:30
|
|
|
|
|
|
|
|
MangaGrid.defaultProps = {
|
2021-10-24 22:56:10 +03:30
|
|
|
message: '',
|
2021-09-19 17:30:34 +04:30
|
|
|
messageExtra: undefined,
|
2021-01-22 21:11:00 +03:30
|
|
|
};
|
2022-11-24 21:04:30 +01:00
|
|
|
|
|
|
|
|
export default MangaGrid;
|