tachiyomi-extensions-inspector/webUI/react/src/components/ReaderNavBar.tsx

357 lines
14 KiB
TypeScript
Raw Normal View History

2021-03-18 19:16:24 +01:00
/* eslint-disable @typescript-eslint/no-unused-vars */
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
2021-03-18 19:16:24 +01:00
* 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 IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import KeyboardArrowLeftIcon from '@material-ui/icons/KeyboardArrowLeft';
import KeyboardArrowRightIcon from '@material-ui/icons/KeyboardArrowRight';
2021-03-23 00:20:55 +01:00
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@material-ui/icons/KeyboardArrowUp';
2021-03-18 19:16:24 +01:00
import { makeStyles, Theme, useTheme } from '@material-ui/core/styles';
import React, { useContext, useEffect, useState } from 'react';
import Typography from '@material-ui/core/Typography';
2021-03-23 00:20:55 +01:00
import { useHistory, Link } from 'react-router-dom';
2021-03-18 19:16:24 +01:00
import Slide from '@material-ui/core/Slide';
import Fade from '@material-ui/core/Fade';
import Zoom from '@material-ui/core/Zoom';
2021-03-19 12:22:20 +01:00
import { Switch } from '@material-ui/core';
2021-03-23 00:20:55 +01:00
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
import Collapse from '@material-ui/core/Collapse';
import Button from '@material-ui/core/Button';
2021-03-23 00:58:23 +01:00
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
2021-03-18 19:16:24 +01:00
import DarkTheme from '../context/DarkTheme';
2021-03-23 00:20:55 +01:00
import NavBarContext from '../context/NavbarContext';
2021-03-18 19:16:24 +01:00
2021-03-19 12:22:20 +01:00
const useStyles = (settings: IReaderSettings) => makeStyles((theme: Theme) => ({
2021-03-18 19:16:24 +01:00
// main container and root div need to change classes...
AppMainContainer: {
display: 'none',
},
AppRootElment: {
display: 'flex',
},
root: {
2021-03-19 12:22:20 +01:00
position: settings.staticNav ? 'sticky' : 'fixed',
2021-03-18 19:16:24 +01:00
top: 0,
left: 0,
minWidth: '300px',
height: '100vh',
overflowY: 'auto',
backgroundColor: '#0a0b0b',
'& header': {
backgroundColor: '#363b3d',
display: 'flex',
alignItems: 'center',
minHeight: '64px',
paddingLeft: '24px',
paddingRight: '24px',
transition: 'left 2s ease',
'& button': {
flexGrow: 0,
flexShrink: 0,
},
'& button:nth-child(1)': {
marginRight: '16px',
},
'& button:nth-child(3)': {
marginRight: '-12px',
},
'& h1': {
fontSize: '1.25rem',
flexGrow: 1,
},
},
2021-03-23 00:20:55 +01:00
'& hr': {
margin: '0 16px',
height: '1px',
border: '0',
backgroundColor: 'rgb(38, 41, 43)',
},
},
navigation: {
margin: '0 16px',
'& > span:nth-child(1)': {
textAlign: 'center',
display: 'block',
marginTop: '16px',
},
'& $navigationChapters': {
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gridTemplateAreas: '"prev next"',
gridColumnGap: '5px',
margin: '10px 0',
'& a': {
flexGrow: 1,
textDecoration: 'none',
'& button': {
width: '100%',
padding: '5px 8px',
textTransform: 'none',
},
},
},
},
navigationChapters: {}, // dummy rule
settingsCollapsseHeader: {
'& span': {
fontWeight: 'bold',
},
2021-03-18 19:16:24 +01:00
},
openDrawerButton: {
position: 'fixed',
top: 0 + 20,
left: 10 + 20,
height: '40px',
width: '40px',
borderRadius: 5,
backgroundColor: 'black',
'&:hover': {
backgroundColor: 'black',
},
},
}));
2021-03-19 12:22:20 +01:00
export const defaultReaderSettings = () => ({
staticNav: false,
showPageNumber: true,
2021-03-28 00:33:46 +01:00
continuesPageGap: false,
2021-03-19 12:22:20 +01:00
} as IReaderSettings);
2021-03-18 19:16:24 +01:00
interface IProps {
settings: IReaderSettings
setSettings: React.Dispatch<React.SetStateAction<IReaderSettings>>
2021-03-23 00:20:55 +01:00
manga: IManga | IMangaCard
chapter: IChapter | IPartialChpter
curPage: number
2021-03-18 19:16:24 +01:00
}
export default function ReaderNavBar(props: IProps) {
const { title } = useContext(NavBarContext);
const { darkTheme } = useContext(DarkTheme);
const history = useHistory();
2021-03-23 00:20:55 +01:00
const {
settings, setSettings, manga, chapter, curPage,
} = props;
2021-03-19 12:22:20 +01:00
const [drawerOpen, setDrawerOpen] = useState(false || settings.staticNav);
2021-03-23 00:58:23 +01:00
const [drawerVisible, setDrawerVisible] = useState(false || settings.staticNav);
2021-03-18 19:16:24 +01:00
const [hideOpenButton, setHideOpenButton] = useState(false);
const [prevScrollPos, setPrevScrollPos] = useState(0);
2021-03-23 00:20:55 +01:00
const [settingsCollapseOpen, setSettingsCollapseOpen] = useState(false);
2021-03-18 19:16:24 +01:00
const theme = useTheme();
2021-03-19 12:22:20 +01:00
const classes = useStyles(settings)();
2021-03-18 19:16:24 +01:00
2021-03-19 12:22:20 +01:00
const setSettingValue = (key: string, value: any) => setSettings({ ...settings, [key]: value });
2021-03-18 19:16:24 +01:00
const handleScroll = () => {
const currentScrollPos = window.pageYOffset;
if (Math.abs(currentScrollPos - prevScrollPos) > 20) {
setHideOpenButton(currentScrollPos > prevScrollPos);
setPrevScrollPos(currentScrollPos);
}
};
useEffect(() => {
window.addEventListener('scroll', handleScroll);
const rootEl = document.querySelector('#root')!;
const mainContainer = document.querySelector('#appMainContainer')!;
rootEl.classList.add(classes.AppRootElment);
mainContainer.classList.add(classes.AppMainContainer);
return () => {
rootEl.classList.remove(classes.AppRootElment);
mainContainer.classList.remove(classes.AppMainContainer);
2021-03-23 00:58:23 +01:00
window.removeEventListener('scroll', handleScroll);
2021-03-18 19:16:24 +01:00
};
2021-03-19 12:22:20 +01:00
}, [handleScroll]);// handleScroll changes on every render
2021-03-18 19:16:24 +01:00
return (
<>
2021-03-23 00:58:23 +01:00
<ClickAwayListener onClickAway={() => (drawerVisible && setDrawerOpen(false))}>
<Slide
direction="right"
in={drawerOpen}
timeout={200}
appear={false}
mountOnEnter
unmountOnExit
onEntered={() => setDrawerVisible(true)}
onExited={() => setDrawerVisible(false)}
>
<div className={classes.root}>
<header>
2021-03-19 12:22:20 +01:00
<IconButton
edge="start"
color="inherit"
aria-label="menu"
disableRipple
2021-03-23 00:58:23 +01:00
onClick={() => history.push(`/manga/${manga.id}`)}
2021-03-19 12:22:20 +01:00
>
2021-03-23 00:58:23 +01:00
<CloseIcon />
2021-03-19 12:22:20 +01:00
</IconButton>
2021-03-23 00:58:23 +01:00
<Typography variant="h1">
{title}
</Typography>
{!settings.staticNav
&& (
2021-03-23 00:20:55 +01:00
<IconButton
edge="start"
color="inherit"
aria-label="menu"
disableRipple
2021-03-23 00:58:23 +01:00
onClick={() => setDrawerOpen(false)}
2021-03-23 00:20:55 +01:00
>
2021-03-23 00:58:23 +01:00
<KeyboardArrowLeftIcon />
2021-03-23 00:20:55 +01:00
</IconButton>
2021-03-23 00:58:23 +01:00
) }
</header>
<ListItem ContainerComponent="div" className={classes.settingsCollapsseHeader}>
<ListItemText primary="Reader Settings" />
<ListItemSecondaryAction>
<IconButton
edge="start"
color="inherit"
aria-label="menu"
disableRipple
disableFocusRipple
onClick={() => setSettingsCollapseOpen(!settingsCollapseOpen)}
>
{settingsCollapseOpen && <KeyboardArrowUpIcon />}
{!settingsCollapseOpen && <KeyboardArrowDownIcon />}
</IconButton>
</ListItemSecondaryAction>
</ListItem>
<Collapse in={settingsCollapseOpen} timeout="auto" unmountOnExit>
<List>
<ListItem>
<ListItemText primary="Static Navigation" />
<ListItemSecondaryAction>
<Switch
edge="end"
checked={settings.staticNav}
onChange={(e) => setSettingValue('staticNav', e.target.checked)}
/>
</ListItemSecondaryAction>
</ListItem>
<ListItem>
<ListItemText primary="Show page number" />
<ListItemSecondaryAction>
<Switch
edge="end"
checked={settings.showPageNumber}
onChange={(e) => setSettingValue('showPageNumber', e.target.checked)}
/>
</ListItemSecondaryAction>
2021-03-28 00:33:46 +01:00
</ListItem>
<ListItem>
<ListItemText primary="Continues Page gap" />
<ListItemSecondaryAction>
<Switch
edge="end"
checked={settings.continuesPageGap}
onChange={(e) => setSettingValue('continuesPageGap', e.target.checked)}
/>
</ListItemSecondaryAction>
2021-03-23 00:58:23 +01:00
</ListItem>
</List>
</Collapse>
<hr />
<div className={classes.navigation}>
<span>
Currently on page
{' '}
{curPage + 1}
{' '}
of
{' '}
{chapter.pageCount}
</span>
<div className={classes.navigationChapters}>
2021-05-14 15:01:07 +02:00
{chapter.index > 1
2021-03-23 00:20:55 +01:00
&& (
<Link
style={{ gridArea: 'prev' }}
2021-05-14 15:01:07 +02:00
to={`/manga/${manga.id}/chapter/${chapter.index - 1}`}
2021-03-23 00:20:55 +01:00
>
<Button
variant="outlined"
startIcon={<KeyboardArrowLeftIcon />}
>
Chapter
{' '}
2021-05-14 15:01:07 +02:00
{chapter.index - 1}
2021-03-23 00:20:55 +01:00
</Button>
</Link>
)}
2021-05-14 15:01:07 +02:00
{chapter.index < chapter.chapterCount
2021-03-23 00:20:55 +01:00
&& (
<Link
style={{ gridArea: 'next' }}
2021-05-14 15:01:07 +02:00
to={`/manga/${manga.id}/chapter/${chapter.index + 1}`}
2021-03-23 00:20:55 +01:00
>
<Button
variant="outlined"
endIcon={<KeyboardArrowRightIcon />}
>
Chapter
{' '}
2021-05-14 15:01:07 +02:00
{chapter.index + 1}
2021-03-23 00:20:55 +01:00
</Button>
</Link>
)}
2021-03-23 00:58:23 +01:00
</div>
2021-03-23 00:20:55 +01:00
</div>
</div>
2021-03-23 00:58:23 +01:00
</Slide>
</ClickAwayListener>
2021-03-18 19:16:24 +01:00
<Zoom in={!drawerOpen}>
<Fade in={!hideOpenButton}>
<IconButton
className={classes.openDrawerButton}
edge="start"
color="inherit"
aria-label="menu"
disableRipple
disableFocusRipple
onClick={() => setDrawerOpen(true)}
>
<KeyboardArrowRightIcon />
</IconButton>
</Fade>
</Zoom>
</>
);
}