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-03-18 21:46:24 +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/. */
|
|
|
|
|
|
2021-09-09 17:51:22 +04:30
|
|
|
import IconButton from '@mui/material/IconButton';
|
|
|
|
|
import CloseIcon from '@mui/icons-material/Close';
|
|
|
|
|
import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft';
|
|
|
|
|
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
|
|
|
|
|
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
|
|
|
|
|
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
|
2021-12-01 03:03:52 +03:30
|
|
|
import React, { useEffect, useState } from 'react';
|
2021-09-09 17:51:22 +04:30
|
|
|
import Typography from '@mui/material/Typography';
|
2023-02-08 18:37:39 +01:00
|
|
|
import { useHistory, useLocation } from 'react-router-dom';
|
2021-09-09 17:51:22 +04:30
|
|
|
import Slide from '@mui/material/Slide';
|
|
|
|
|
import Fade from '@mui/material/Fade';
|
|
|
|
|
import Zoom from '@mui/material/Zoom';
|
2023-02-08 18:26:09 +01:00
|
|
|
import { Divider, FormControl, MenuItem, Select } from '@mui/material';
|
2021-09-09 17:51:22 +04:30
|
|
|
import ListItem from '@mui/material/ListItem';
|
|
|
|
|
import ListItemText from '@mui/material/ListItemText';
|
|
|
|
|
import ListItemSecondaryAction from '@mui/material/ListItemSecondaryAction';
|
|
|
|
|
import Collapse from '@mui/material/Collapse';
|
2021-12-01 03:03:52 +03:30
|
|
|
import { styled } from '@mui/system';
|
2022-11-21 01:33:45 +01:00
|
|
|
import useBackTo from 'util/useBackTo';
|
2023-02-05 16:15:20 +01:00
|
|
|
import ReaderSettingsOptions from 'components/reader/ReaderSettingsOptions';
|
2021-12-01 03:03:52 +03:30
|
|
|
|
|
|
|
|
const Root = styled('div')(({ theme }) => ({
|
|
|
|
|
top: 0,
|
|
|
|
|
left: 0,
|
|
|
|
|
width: '300px',
|
|
|
|
|
minWidth: '300px',
|
|
|
|
|
height: '100vh',
|
|
|
|
|
overflowY: 'auto',
|
|
|
|
|
backgroundColor: theme.palette.background.default,
|
|
|
|
|
|
|
|
|
|
'& header': {
|
2022-11-26 13:51:56 +01:00
|
|
|
backgroundColor: theme.palette.action.hover,
|
2021-11-15 17:21:31 +03:30
|
|
|
display: 'flex',
|
2021-12-01 03:03:52 +03:30
|
|
|
alignItems: 'center',
|
|
|
|
|
minHeight: '64px',
|
|
|
|
|
paddingLeft: '24px',
|
|
|
|
|
paddingRight: '24px',
|
2021-11-15 17:21:31 +03:30
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
transition: 'left 2s ease',
|
2021-11-15 17:21:31 +03:30
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
'& button': {
|
|
|
|
|
flexGrow: 0,
|
|
|
|
|
flexShrink: 0,
|
2021-03-23 03:50:55 +04:30
|
|
|
},
|
2021-11-15 17:21:31 +03:30
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
'& button:nth-child(1)': {
|
|
|
|
|
marginRight: '16px',
|
2021-11-14 15:51:08 +05:30
|
|
|
},
|
2021-03-23 03:50:55 +04:30
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
'& h1': {
|
|
|
|
|
fontSize: '1.25rem',
|
|
|
|
|
flexGrow: 1,
|
2021-03-23 03:50:55 +04:30
|
|
|
},
|
2021-11-14 15:51:08 +05:30
|
|
|
},
|
2021-12-01 03:03:52 +03:30
|
|
|
}));
|
2021-11-15 17:21:31 +03:30
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
const Navigation = styled('div')({
|
|
|
|
|
margin: '0 16px',
|
|
|
|
|
'& > span:nth-child(1)': {
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
display: 'block',
|
|
|
|
|
marginTop: '16px',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2023-02-08 18:26:09 +01:00
|
|
|
const PageNavigation = styled('div')({
|
|
|
|
|
display: 'flex',
|
|
|
|
|
flexWrap: 'wrap',
|
|
|
|
|
alignContent: 'center',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
justifyContent: 'center',
|
|
|
|
|
});
|
|
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
const ChapterNavigation = styled('div')({
|
|
|
|
|
display: 'grid',
|
2023-02-08 18:37:39 +01:00
|
|
|
gridTemplateRows: 'auto auto auto',
|
|
|
|
|
gridTemplateColumns: '0fr 1fr 0fr',
|
|
|
|
|
gridTemplateAreas: '"pre current next"',
|
2021-12-01 03:03:52 +03:30
|
|
|
gridColumnGap: '5px',
|
|
|
|
|
margin: '10px 0',
|
|
|
|
|
|
|
|
|
|
'& a': {
|
|
|
|
|
textDecoration: 'none',
|
2023-02-08 18:37:39 +01:00
|
|
|
color: 'inherit',
|
|
|
|
|
display: 'flex',
|
|
|
|
|
flexWrap: 'wrap',
|
|
|
|
|
alignContent: 'center',
|
2021-11-14 15:51:08 +05:30
|
|
|
},
|
2021-12-01 03:03:52 +03:30
|
|
|
});
|
|
|
|
|
|
2023-02-08 18:26:09 +01:00
|
|
|
const MenuProps = { PaperProps: { style: { maxHeight: 150 } } };
|
|
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
const OpenDrawerButton = styled(IconButton)(({ theme }) => ({
|
|
|
|
|
position: 'fixed',
|
|
|
|
|
top: 0 + 20,
|
|
|
|
|
left: 10 + 20,
|
|
|
|
|
height: '40px',
|
|
|
|
|
width: '40px',
|
|
|
|
|
borderRadius: 5,
|
2022-11-26 13:51:56 +01:00
|
|
|
backgroundColor: theme.palette.custom.main,
|
2021-12-01 03:03:52 +03:30
|
|
|
'&:hover': {
|
2022-11-26 13:51:56 +01:00
|
|
|
backgroundColor: theme.palette.custom.light,
|
2021-12-01 03:03:52 +03:30
|
|
|
},
|
2021-10-17 16:18:30 +05:30
|
|
|
}));
|
2021-03-18 21:46:24 +03:30
|
|
|
|
|
|
|
|
interface IProps {
|
2023-02-06 10:06:33 +01:00
|
|
|
settings: IReaderSettings;
|
|
|
|
|
setSettingValue: (key: keyof IReaderSettings, value: string | boolean) => void;
|
|
|
|
|
manga: IManga | IMangaCard;
|
|
|
|
|
chapter: IChapter;
|
|
|
|
|
curPage: number;
|
2023-02-08 18:26:09 +01:00
|
|
|
setCurPage: (page: number) => void;
|
2021-03-18 21:46:24 +03:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function ReaderNavBar(props: IProps) {
|
|
|
|
|
const history = useHistory();
|
2022-11-21 01:33:45 +01:00
|
|
|
const backTo = useBackTo();
|
2023-01-06 17:15:29 +01:00
|
|
|
const location = useLocation<{
|
2023-02-06 10:06:33 +01:00
|
|
|
prevDrawerOpen?: boolean;
|
|
|
|
|
prevSettingsCollapseOpen?: boolean;
|
2023-01-06 17:15:29 +01:00
|
|
|
}>();
|
2023-02-06 10:06:33 +01:00
|
|
|
const { prevDrawerOpen, prevSettingsCollapseOpen } = location.state ?? {};
|
2021-03-18 21:46:24 +03:30
|
|
|
|
2023-02-08 18:26:09 +01:00
|
|
|
const { settings, setSettingValue, manga, chapter, curPage, setCurPage } = props;
|
2021-03-19 14:52:20 +03:30
|
|
|
|
2023-01-06 17:15:29 +01:00
|
|
|
const [drawerOpen, setDrawerOpen] = useState(settings.staticNav || prevDrawerOpen);
|
|
|
|
|
const [updateDrawerOnRender, setUpdateDrawerOnRender] = useState(true);
|
|
|
|
|
const [hideOpenButton, setHideOpenButton] = useState(settings.staticNav || prevDrawerOpen);
|
2021-03-18 21:46:24 +03:30
|
|
|
const [prevScrollPos, setPrevScrollPos] = useState(0);
|
2023-02-08 18:19:26 +01:00
|
|
|
const [settingsCollapseOpen, setSettingsCollapseOpen] = useState(prevSettingsCollapseOpen ?? true);
|
2021-03-18 21:46:24 +03:30
|
|
|
|
2023-01-06 17:15:29 +01:00
|
|
|
const updateSettingValue = (key: keyof IReaderSettings, value: string | boolean) => {
|
|
|
|
|
// prevent closing the navBar when updating the "staticNav" setting
|
|
|
|
|
setUpdateDrawerOnRender(key !== 'staticNav');
|
|
|
|
|
setSettingValue(key, value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const updateDrawer = (open: boolean) => {
|
|
|
|
|
setDrawerOpen(open);
|
|
|
|
|
setHideOpenButton(open);
|
|
|
|
|
};
|
2021-03-18 21:46:24 +03:30
|
|
|
|
|
|
|
|
const handleScroll = () => {
|
|
|
|
|
const currentScrollPos = window.pageYOffset;
|
|
|
|
|
|
|
|
|
|
if (Math.abs(currentScrollPos - prevScrollPos) > 20) {
|
|
|
|
|
setHideOpenButton(currentScrollPos > prevScrollPos);
|
|
|
|
|
setPrevScrollPos(currentScrollPos);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-01-06 17:15:29 +01:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (updateDrawerOnRender) {
|
|
|
|
|
updateDrawer(settings.staticNav);
|
|
|
|
|
}
|
|
|
|
|
}, [settings.staticNav]);
|
|
|
|
|
|
2021-03-18 21:46:24 +03:30
|
|
|
useEffect(() => {
|
|
|
|
|
window.addEventListener('scroll', handleScroll);
|
|
|
|
|
|
2023-02-06 10:06:33 +01:00
|
|
|
const rootEl: HTMLDivElement = document.querySelector('#root')!;
|
|
|
|
|
const mainContainer: HTMLDivElement = document.querySelector('#appMainContainer')!;
|
2021-03-18 21:46:24 +03:30
|
|
|
|
2021-12-01 03:03:52 +03:30
|
|
|
// main container and root div need to change styles...
|
|
|
|
|
rootEl.style.display = 'flex';
|
|
|
|
|
mainContainer.style.display = 'none';
|
2021-03-18 21:46:24 +03:30
|
|
|
|
|
|
|
|
return () => {
|
2021-12-01 03:03:52 +03:30
|
|
|
rootEl.style.display = 'block';
|
|
|
|
|
mainContainer.style.display = 'block';
|
2021-03-23 04:28:23 +04:30
|
|
|
window.removeEventListener('scroll', handleScroll);
|
2021-03-18 21:46:24 +03:30
|
|
|
};
|
2023-02-06 10:06:33 +01:00
|
|
|
}, [handleScroll]); // handleScroll changes on every render
|
2021-03-18 21:46:24 +03:30
|
|
|
|
2022-11-21 01:33:45 +01:00
|
|
|
const handleClose = () => {
|
|
|
|
|
if (backTo.back) history.goBack();
|
|
|
|
|
else if (backTo.url) history.push(backTo.url);
|
|
|
|
|
else history.push(`/manga/${manga.id}`);
|
|
|
|
|
};
|
|
|
|
|
|
2021-03-18 21:46:24 +03:30
|
|
|
return (
|
|
|
|
|
<>
|
2023-02-08 18:19:26 +01:00
|
|
|
<Slide direction="right" in={drawerOpen} timeout={200} appear={false} mountOnEnter unmountOnExit>
|
2023-02-06 10:06:33 +01:00
|
|
|
<Root
|
|
|
|
|
sx={{
|
|
|
|
|
position: settings.staticNav ? 'sticky' : 'fixed',
|
|
|
|
|
}}
|
2021-12-01 03:03:52 +03:30
|
|
|
>
|
2021-05-15 23:22:37 +04:30
|
|
|
<header>
|
2023-02-06 10:06:33 +01:00
|
|
|
{!settings.staticNav && (
|
2021-12-01 03:03:52 +03:30
|
|
|
<IconButton
|
|
|
|
|
edge="start"
|
|
|
|
|
color="inherit"
|
|
|
|
|
aria-label="menu"
|
|
|
|
|
disableRipple
|
2023-01-06 17:15:29 +01:00
|
|
|
onClick={() => updateDrawer(false)}
|
2021-12-01 03:03:52 +03:30
|
|
|
size="large"
|
|
|
|
|
>
|
|
|
|
|
<KeyboardArrowLeftIcon />
|
|
|
|
|
</IconButton>
|
|
|
|
|
)}
|
2023-02-08 18:19:26 +01:00
|
|
|
<Typography variant="h1" textOverflow="ellipsis" overflow="hidden" sx={{ py: 1 }}>
|
2021-09-07 04:25:13 +08:00
|
|
|
{chapter.name}
|
|
|
|
|
</Typography>
|
|
|
|
|
<IconButton
|
|
|
|
|
edge="start"
|
|
|
|
|
color="inherit"
|
|
|
|
|
aria-label="menu"
|
|
|
|
|
disableRipple
|
2022-11-21 01:33:45 +01:00
|
|
|
onClick={handleClose}
|
2021-09-09 17:51:22 +04:30
|
|
|
size="large"
|
2021-12-01 03:03:52 +03:30
|
|
|
sx={{ mr: -1 }}
|
2021-09-07 04:25:13 +08:00
|
|
|
>
|
|
|
|
|
<CloseIcon />
|
|
|
|
|
</IconButton>
|
2021-05-15 23:22:37 +04:30
|
|
|
</header>
|
2021-12-01 03:03:52 +03:30
|
|
|
<ListItem
|
|
|
|
|
ContainerComponent="div"
|
|
|
|
|
sx={{
|
|
|
|
|
'& span': {
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
>
|
2021-05-15 23:22:37 +04:30
|
|
|
<ListItemText primary="Reader Settings" />
|
|
|
|
|
<ListItemSecondaryAction>
|
2021-03-23 03:50:55 +04:30
|
|
|
<IconButton
|
|
|
|
|
edge="start"
|
|
|
|
|
color="inherit"
|
|
|
|
|
aria-label="menu"
|
|
|
|
|
disableRipple
|
2021-05-15 23:22:37 +04:30
|
|
|
disableFocusRipple
|
|
|
|
|
onClick={() => setSettingsCollapseOpen(!settingsCollapseOpen)}
|
2021-09-09 17:51:22 +04:30
|
|
|
size="large"
|
2021-03-23 03:50:55 +04:30
|
|
|
>
|
2021-05-15 23:22:37 +04:30
|
|
|
{settingsCollapseOpen && <KeyboardArrowUpIcon />}
|
|
|
|
|
{!settingsCollapseOpen && <KeyboardArrowDownIcon />}
|
2021-03-23 03:50:55 +04:30
|
|
|
</IconButton>
|
2021-05-15 23:22:37 +04:30
|
|
|
</ListItemSecondaryAction>
|
|
|
|
|
</ListItem>
|
|
|
|
|
<Collapse in={settingsCollapseOpen} timeout="auto" unmountOnExit>
|
2023-01-06 17:34:16 +01:00
|
|
|
<ReaderSettingsOptions
|
|
|
|
|
setSettingValue={updateSettingValue}
|
|
|
|
|
staticNav={settings.staticNav}
|
|
|
|
|
showPageNumber={settings.showPageNumber}
|
2023-01-06 18:19:45 +01:00
|
|
|
loadNextOnEnding={settings.loadNextOnEnding}
|
2023-01-06 17:34:16 +01:00
|
|
|
readerType={settings.readerType}
|
|
|
|
|
/>
|
2021-05-15 23:22:37 +04:30
|
|
|
</Collapse>
|
2022-11-26 13:51:56 +01:00
|
|
|
<Divider sx={{ my: 1, mx: 2 }} />
|
2021-12-01 03:03:52 +03:30
|
|
|
<Navigation>
|
2023-02-08 18:26:09 +01:00
|
|
|
<PageNavigation>
|
|
|
|
|
<span>Currently on page</span>
|
2023-02-12 16:11:29 +01:00
|
|
|
<FormControl size="small" sx={{ margin: '0 5px' }} disabled={chapter.pageCount === -1}>
|
2023-02-08 18:26:09 +01:00
|
|
|
<Select
|
|
|
|
|
MenuProps={MenuProps}
|
|
|
|
|
value={chapter.pageCount > -1 ? curPage : ''}
|
|
|
|
|
displayEmpty
|
|
|
|
|
onChange={({ target: { value: selectedPage } }) => {
|
|
|
|
|
setCurPage(Number(selectedPage));
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{Array(Math.max(0, chapter.pageCount))
|
|
|
|
|
.fill(1)
|
|
|
|
|
.map((ignoreValue, index) => (
|
|
|
|
|
// eslint-disable-next-line react/no-array-index-key
|
|
|
|
|
<MenuItem key={`Page#${index}`} value={index}>
|
|
|
|
|
{index + 1}
|
|
|
|
|
</MenuItem>
|
|
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<span>{`of ${chapter.pageCount}`}</span>
|
|
|
|
|
</PageNavigation>
|
2021-12-01 03:03:52 +03:30
|
|
|
<ChapterNavigation>
|
2023-02-08 18:37:39 +01:00
|
|
|
<IconButton
|
|
|
|
|
title="Previous Chapter"
|
|
|
|
|
sx={{ gridArea: 'pre' }}
|
|
|
|
|
disabled={chapter.index <= 1}
|
|
|
|
|
onClick={() => {
|
|
|
|
|
history.replace({
|
2023-01-06 17:15:29 +01:00
|
|
|
pathname: `/manga/${manga.id}/chapter/${chapter.index - 1}`,
|
|
|
|
|
state: {
|
|
|
|
|
prevDrawerOpen: drawerOpen,
|
|
|
|
|
prevSettingsCollapseOpen: settingsCollapseOpen,
|
|
|
|
|
},
|
2023-02-08 18:37:39 +01:00
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<KeyboardArrowLeftIcon />
|
|
|
|
|
</IconButton>
|
2023-02-12 16:11:29 +01:00
|
|
|
<FormControl sx={{ gridArea: 'current' }} size="small" disabled={chapter.index < 1}>
|
2023-02-08 18:37:39 +01:00
|
|
|
<Select
|
|
|
|
|
MenuProps={MenuProps}
|
|
|
|
|
value={chapter.index >= 1 ? chapter.index : ''}
|
|
|
|
|
displayEmpty
|
|
|
|
|
onChange={({ target: { value: selectedChapter } }) => {
|
|
|
|
|
history.replace({
|
|
|
|
|
pathname: `/manga/${manga.id}/chapter/${selectedChapter}`,
|
|
|
|
|
state: {
|
|
|
|
|
prevDrawerOpen: drawerOpen,
|
|
|
|
|
prevSettingsCollapseOpen: settingsCollapseOpen,
|
|
|
|
|
},
|
|
|
|
|
});
|
2023-01-06 17:15:29 +01:00
|
|
|
}}
|
2021-03-23 03:50:55 +04:30
|
|
|
>
|
2023-02-08 18:37:39 +01:00
|
|
|
{Array(Math.max(0, chapter.chapterCount))
|
|
|
|
|
.fill(1)
|
|
|
|
|
.map((ignoreValue, index) => (
|
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
|
|
// eslint-disable-next-line react/no-array-index-key
|
2023-02-12 16:11:29 +01:00
|
|
|
<MenuItem key={`Chapter#${index + 1}`} value={index + 1}>{`Chapter ${
|
|
|
|
|
index + 1
|
|
|
|
|
}`}</MenuItem>
|
2023-02-08 18:37:39 +01:00
|
|
|
))}
|
|
|
|
|
</Select>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<IconButton
|
|
|
|
|
title="Next Chapter"
|
|
|
|
|
sx={{ gridArea: 'next' }}
|
2023-02-12 16:11:29 +01:00
|
|
|
disabled={chapter.index < 1 || chapter.index >= chapter.chapterCount}
|
2023-02-08 18:37:39 +01:00
|
|
|
onClick={() => {
|
|
|
|
|
history.replace({
|
2023-01-06 17:15:29 +01:00
|
|
|
pathname: `/manga/${manga.id}/chapter/${chapter.index + 1}`,
|
|
|
|
|
state: {
|
|
|
|
|
prevDrawerOpen: drawerOpen,
|
|
|
|
|
prevSettingsCollapseOpen: settingsCollapseOpen,
|
|
|
|
|
},
|
2023-02-08 18:37:39 +01:00
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<KeyboardArrowRightIcon />
|
|
|
|
|
</IconButton>
|
2021-12-01 03:03:52 +03:30
|
|
|
</ChapterNavigation>
|
|
|
|
|
</Navigation>
|
|
|
|
|
</Root>
|
2021-05-15 23:22:37 +04:30
|
|
|
</Slide>
|
2021-03-18 21:46:24 +03:30
|
|
|
<Zoom in={!drawerOpen}>
|
|
|
|
|
<Fade in={!hideOpenButton}>
|
2021-12-01 03:03:52 +03:30
|
|
|
<OpenDrawerButton
|
2021-03-18 21:46:24 +03:30
|
|
|
edge="start"
|
|
|
|
|
aria-label="menu"
|
|
|
|
|
disableRipple
|
|
|
|
|
disableFocusRipple
|
2023-01-06 17:15:29 +01:00
|
|
|
onClick={() => updateDrawer(true)}
|
2021-09-09 17:51:22 +04:30
|
|
|
size="large"
|
2021-03-18 21:46:24 +03:30
|
|
|
>
|
|
|
|
|
<KeyboardArrowRightIcon />
|
2021-12-01 03:03:52 +03:30
|
|
|
</OpenDrawerButton>
|
2021-03-18 21:46:24 +03:30
|
|
|
</Fade>
|
|
|
|
|
</Zoom>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|