staisfying results? with chapters scrolling

This commit is contained in:
Aria Moradi 2021-05-13 17:46:40 +04:30
parent 1e2eb11c13
commit dc012edf7d
8 changed files with 140 additions and 60 deletions

View File

@ -14,7 +14,7 @@
"react-lazyload": "^3.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-window": "^1.8.6",
"react-virtuoso": "^1.8.6",
"web-vitals": "^0.2.4"
},
"scripts": {
@ -40,7 +40,6 @@
"@types/react-dom": "^17.0.2",
"@types/react-lazyload": "^3.1.0",
"@types/react-router-dom": "^5.1.7",
"@types/react-window": "^1.8.3",
"@typescript-eslint/eslint-plugin": "4.23.0",
"@typescript-eslint/parser": "4.23.0",
"eslint": "^7.26.0",

View File

@ -7,12 +7,15 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { makeStyles, useTheme } from '@material-ui/core/styles';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import Typography from '@material-ui/core/Typography';
import { Link, useHistory } from 'react-router-dom';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
const useStyles = makeStyles((theme) => ({
root: {
@ -47,41 +50,63 @@ interface IProps{
export default function ChapterCard(props: IProps) {
const classes = useStyles();
const history = useHistory();
const theme = useTheme();
const { chapter } = props;
const dateStr = chapter.uploadDate && new Date(chapter.uploadDate).toISOString().slice(0, 10);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<>
<li>
<Card>
<CardContent className={classes.root}>
<div style={{ display: 'flex' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Typography variant="h5" component="h2">
{chapter.name}
{chapter.chapterNumber > 0 && ` : ${chapter.chapterNumber}`}
</Typography>
<Typography variant="caption" display="block" gutterBottom>
{chapter.scanlator}
{chapter.scanlator && ' '}
{dateStr}
</Typography>
</div>
</div>
<Link
to={`/manga/${chapter.mangaId}/chapter/${chapter.chapterIndex}`}
style={{ textDecoration: 'none' }}
style={{
textDecoration: 'none',
color: theme.palette.text.primary,
}}
>
<Button
variant="outlined"
style={{ marginLeft: 20 }}
>
open
<div style={{ display: 'flex' }}>
<div style={{ display: 'flex', flexDirection: 'column' }}>
</Button>
<Typography variant="h5" component="h2">
{chapter.name}
{chapter.chapterNumber > 0 && ` : ${chapter.chapterNumber}`}
</Typography>
<Typography variant="caption" display="block" gutterBottom>
{chapter.scanlator}
{chapter.scanlator && ' '}
{dateStr}
</Typography>
</div>
</div>
</Link>
<IconButton aria-label="more" onClick={handleClick}>
<MoreVertIcon />
</IconButton>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
{/* <MenuItem onClick={handleClose}>Download</MenuItem> */}
<MenuItem onClick={handleClose}>Bookmark</MenuItem>
<MenuItem onClick={handleClose}>Mark as Read</MenuItem>
<MenuItem onClick={handleClose}>Mark previous as Read</MenuItem>
</Menu>
</CardContent>
</Card>
</li>

View File

@ -10,7 +10,7 @@ import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
// roboto font
import 'fontsource-roboto';
import '@fontsource/roboto';
ReactDOM.render(
<React.StrictMode>

View File

@ -7,9 +7,9 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import React, { useEffect, useState, useContext } from 'react';
import { makeStyles, Theme } from '@material-ui/core/styles';
import { makeStyles, Theme, useTheme } from '@material-ui/core/styles';
import { useParams } from 'react-router-dom';
import CircularProgress from '@material-ui/core/CircularProgress';
import { Virtuoso } from 'react-virtuoso';
import ChapterCard from '../components/ChapterCard';
import MangaDetails from '../components/MangaDetails';
import NavbarContext from '../context/NavbarContext';
@ -41,13 +41,26 @@ const useStyles = makeStyles((theme: Theme) => ({
},
}));
const InnerItem = React.memo(({ chapters, index }: any) => {
React.useEffect(() => {
console.log('inner mounting', index);
return () => {
console.log('inner unmounting', index);
};
}, [index]);
return (
<ChapterCard chapter={chapters[index]} />
);
});
export default function Manga() {
const classes = useStyles();
const theme = useTheme();
const { setTitle } = useContext(NavbarContext);
useEffect(() => { setTitle('Manga'); }, []); // delegate setting topbar action to MangaDetails
const { id } = useParams<{id: string}>();
const { id } = useParams<{ id: string }>();
const [manga, setManga] = useState<IManga>();
const [chapters, setChapters] = useState<IChapter[]>([]);
@ -67,16 +80,10 @@ export default function Manga() {
.then((data) => setChapters(data));
}, []);
const chapterCards = (
<LoadingPlaceholder
shouldRender={chapters.length > 0}
>
<ol className={classes.chapters}>
{chapters.map((chapter) => (<ChapterCard chapter={chapter} />))}
</ol>
</LoadingPlaceholder>
);
const itemContent = (index:any) => {
console.log('providing content', index);
return <InnerItem chapters={chapters} index={index} />;
};
return (
<div className={classes.root}>
@ -85,7 +92,32 @@ export default function Manga() {
component={MangaDetails}
componentProps={{ manga }}
/>
{chapterCards}
<LoadingPlaceholder
shouldRender={chapters.length > 0}
>
{/* <ol >
{chapters.map((chapter) => ())}
</ol> */}
<Virtuoso
style={
{
width: '100vw',
height: '100%',
[theme.breakpoints.up('md')]: {
height: 'calc(100vh - 64px)',
width: '50vw',
},
}
}
className={classes.chapters}
totalCount={chapters.length}
itemContent={itemContent}
useWindowScroll={window.innerWidth < 960}
overscan={window.innerHeight * 0.5}
/>
</LoadingPlaceholder>
</div>
);
}

View File

@ -50,7 +50,7 @@ export default function Reader() {
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
const { chapterIndex, mangaId } = useParams<{chapterIndex: string, mangaId: string}>();
const { chapterIndex, mangaId } = useParams<{ chapterIndex: string, mangaId: string }>();
const [manga, setManga] = useState<IMangaCard | IManga>({ id: +mangaId, title: '', thumbnailUrl: '' });
const [chapter, setChapter] = useState<IChapter | IPartialChpter>(initialChapter());
const [curPage, setCurPage] = useState<number>(0);

View File

@ -27,7 +27,7 @@ export default function SearchSingle() {
const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => { setTitle('Search'); setAction(<></>); }, []);
const { sourceId } = useParams<{sourceId: string}>();
const { sourceId } = useParams<{ sourceId: string }>();
const classes = useStyles();
const [error, setError] = useState<boolean>(false);
const [mangas, setMangas] = useState<IMangaCard[]>([]);

View File

@ -15,7 +15,7 @@ export default function SourceMangas(props: { popular: boolean }) {
const { setTitle, setAction } = useContext(NavbarContext);
useEffect(() => { setTitle('Source'); setAction(<></>); }, []);
const { sourceId } = useParams<{sourceId: string}>();
const { sourceId } = useParams<{ sourceId: string }>();
const [mangas, setMangas] = useState<IMangaCard[]>([]);
const [hasNextPage, setHasNextPage] = useState<boolean>(false);
const [lastPageNum, setLastPageNum] = useState<number>(1);

View File

@ -1157,7 +1157,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.14.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
@ -1928,13 +1928,6 @@
dependencies:
"@types/react" "*"
"@types/react-window@^1.8.3":
version "1.8.3"
resolved "https://registry.yarnpkg.com/@types/react-window/-/react-window-1.8.3.tgz#14f74b144b4e3df9421eb31182dc580b7ccc7617"
integrity sha512-Xf+IR2Zyiyh/6z1CM8kv1aQba3S3X/hBXt4tH+T9bDSIGwFhle0GZFZGTSU8nw2cUT3UNbCHDjhxVQVZPtE8cA==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^17.0.2":
version "17.0.5"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.5.tgz#3d887570c4489011f75a3fc8f965bf87d09a1bea"
@ -2118,6 +2111,18 @@
"@typescript-eslint/types" "4.23.0"
eslint-visitor-keys "^2.0.0"
"@virtuoso.dev/react-urx@^0.2.5":
version "0.2.6"
resolved "https://registry.yarnpkg.com/@virtuoso.dev/react-urx/-/react-urx-0.2.6.tgz#e1d8bc717723b2fc23d80ea4e07703dbc276448b"
integrity sha512-+PLQ2iWmSH/rW7WGPEf+Kkql+xygHFL43Jij5aREde/O9mE0OFFGqeetA2a6lry3LDVWzupPntvvWhdaYw0TyA==
dependencies:
"@virtuoso.dev/urx" "^0.2.6"
"@virtuoso.dev/urx@^0.2.5", "@virtuoso.dev/urx@^0.2.6":
version "0.2.6"
resolved "https://registry.yarnpkg.com/@virtuoso.dev/urx/-/urx-0.2.6.tgz#0028c49e52037e673993900d32abea83262fbd53"
integrity sha512-EKJ0WvJgWaXIz6zKbh9Q63Bcq//p8OHXHbdz4Fy+ruhjJCyI8ADE8E5gwSqBoUchaiYlgwKrT+sX4L2h/H+hMg==
"@webassemblyjs/ast@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
@ -3668,7 +3673,7 @@ core-js@^2.4.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-js@^3.6.5:
core-js@^3.5.0, core-js@^3.6.5:
version "3.12.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.12.1.tgz#6b5af4ff55616c08a44d386f1f510917ff204112"
integrity sha512-Ne9DKPHTObRuB09Dru5AjwKjY4cJHVGu+y5f7coGn1E9Grkc3p2iBwE9AI/nJzsE29mQF7oq+mhYYRqOMFN1Bw==
@ -7370,7 +7375,7 @@ media-typer@0.3.0:
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
"memoize-one@>=3.1.1 <6", memoize-one@^5.1.1:
memoize-one@^5.1.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
@ -9093,7 +9098,7 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
promise@^8.1.0:
promise@^8.0.3, promise@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e"
integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==
@ -9285,6 +9290,18 @@ raw-body@2.4.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
react-app-polyfill@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz#890f8d7f2842ce6073f030b117de9130a5f385f0"
integrity sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==
dependencies:
core-js "^3.5.0"
object-assign "^4.1.1"
promise "^8.0.3"
raf "^3.4.1"
regenerator-runtime "^0.13.3"
whatwg-fetch "^3.0.0"
react-app-polyfill@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-2.0.0.tgz#a0bea50f078b8a082970a9d853dc34b6dcc6a3cf"
@ -9491,13 +9508,15 @@ react-transition-group@^4.4.0:
loose-envify "^1.4.0"
prop-types "^15.6.2"
react-window@^1.8.6:
react-virtuoso@^1.8.6:
version "1.8.6"
resolved "https://registry.yarnpkg.com/react-window/-/react-window-1.8.6.tgz#d011950ac643a994118632665aad0c6382e2a112"
integrity sha512-8VwEEYyjz6DCnGBsd+MgkD0KJ2/OXFULyDtorIiTz+QzwoP94tBoA7CnbtyXMm+cCeAUER5KJcPtWl9cpKbOBg==
resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-1.8.6.tgz#dc7d79ee9e309c13700296ff65b04f6ebecdcbaa"
integrity sha512-WFSI4YzdyAFrr3CuZnQ8cmubGMJjgmgyuhx/OpWLls1uK9O43s+6DMr9oBXHAgvCDjS3Nd3vkIJAhsJBJzS1nQ==
dependencies:
"@babel/runtime" "^7.0.0"
memoize-one ">=3.1.1 <6"
"@virtuoso.dev/react-urx" "^0.2.5"
"@virtuoso.dev/urx" "^0.2.5"
react-app-polyfill "^1.0.6"
resize-observer-polyfill "^1.5.1"
react@^17.0.2:
version "17.0.2"
@ -9612,7 +9631,7 @@ regenerator-runtime@^0.11.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7:
regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7:
version "0.13.7"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
@ -9767,6 +9786,11 @@ requires-port@^1.0.0:
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
resize-observer-polyfill@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@ -11564,7 +11588,7 @@ whatwg-encoding@^1.0.5:
dependencies:
iconv-lite "0.4.24"
whatwg-fetch@^3.4.1:
whatwg-fetch@^3.0.0, whatwg-fetch@^3.4.1:
version "3.6.2"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==