fix reader

This commit is contained in:
monoid 2021-01-09 02:28:40 +09:00
parent 714ba9aae7
commit 26bfa5785b
6 changed files with 80 additions and 26 deletions

View File

@ -102,8 +102,7 @@ export const ContentInfo = (props: {
allTag = allTag.filter(x => !x.startsWith("artist:")); allTag = allTag.filter(x => !x.startsWith("artist:"));
return (<Paper className={propclasses.root || rootName} elevation={4}> return (<Paper className={propclasses.root || rootName} elevation={4}>
<Link className={propclasses.thumbnail_anchor || thumbnail_anchor} component={RouterLink} to={{ <Link className={propclasses.thumbnail_anchor || thumbnail_anchor} component={RouterLink} to={{
pathname:makeContentReaderUrl(content.id), pathname:makeContentReaderUrl(content.id)
state:props.gallery
}}> }}>
<ThumbnailContainer content={content} <ThumbnailContainer content={content}
className={propclasses.thumbnail_content || thumbnail_content}/> className={propclasses.thumbnail_content || thumbnail_content}/>
@ -111,7 +110,6 @@ export const ContentInfo = (props: {
<Box className={propclasses.infoContainer || classes.infoContainer}> <Box className={propclasses.infoContainer || classes.infoContainer}>
<Link variant='h5' color='inherit' component={RouterLink} to={{ <Link variant='h5' color='inherit' component={RouterLink} to={{
pathname: props.gallery === undefined ? makeContentReaderUrl(content.id) : makeContentInfoUrl(content.id), pathname: props.gallery === undefined ? makeContentReaderUrl(content.id) : makeContentInfoUrl(content.id),
state:props.gallery
}} }}
className={propclasses.title || classes.title}> className={propclasses.title || classes.title}>
{content.title} {content.title}

View File

@ -106,8 +106,11 @@ const useStyles = makeStyles((theme: Theme) => ({
export const Headline = (prop: { export const Headline = (prop: {
children?: React.ReactNode, children?: React.ReactNode,
navListItem?: React.ReactNode,
isLogin?: boolean, isLogin?: boolean,
classes?:{
content?:string,
toolbar?:string,
},
menu: React.ReactNode menu: React.ReactNode
}) => { }) => {
const [v, setv] = useState(false); const [v, setv] = useState(false);
@ -174,7 +177,7 @@ export const Headline = (prop: {
color="inherit"> color="inherit">
<AccountCircle /> <AccountCircle />
</IconButton> </IconButton>
: <Button color="inherit">Login</Button> : <Button color="inherit" component={RouterLink} to="/login">Login</Button>
} }
</Toolbar> </Toolbar>
</AppBar> </AppBar>
@ -194,8 +197,8 @@ export const Headline = (prop: {
</Drawer> </Drawer>
</Hidden> </Hidden>
</nav> </nav>
<main className={classes.content}> <main className={prop.classes?.content || classes.content}>
<div className={classes.toolbar}></div> <div className={prop.classes?.toolbar || classes.toolbar}></div>
{prop.children} {prop.children}
</main> </main>
</div>); </div>);

View File

@ -4,7 +4,7 @@ import ContentAccessor, { Content } from '../accessor/contents';
import { LoadingCircle } from '../component/loading'; import { LoadingCircle } from '../component/loading';
import { Link, Paper, makeStyles, Theme, Box, useTheme, Typography } from '@material-ui/core'; import { Link, Paper, makeStyles, Theme, Box, useTheme, Typography } from '@material-ui/core';
import {ArrowBack as ArrowBackIcon } from '@material-ui/icons'; import {ArrowBack as ArrowBackIcon } from '@material-ui/icons';
import { MangaReader } from './reader/manga'; import { getPresenter } from './reader/reader';
import { ContentInfo, Headline, NavItem, NavList } from '../component/mod'; import { ContentInfo, Headline, NavItem, NavList } from '../component/mod';
import {BackLinkContext} from '../state'; import {BackLinkContext} from '../state';
@ -16,6 +16,18 @@ type ContentState = {
notfound: boolean, notfound: boolean,
} }
const useStyles = makeStyles((theme:Theme)=>({
noPaddingContent:{
display:'flex',
flexDirection: 'column',
flexGrow: 1,
},
noPaddingToolbar:{
flex: '0 1 auto',
...theme.mixins.toolbar,
}
}));
export const ContentAbout = (prop: { match: MatchType }) => { export const ContentAbout = (prop: { match: MatchType }) => {
const match = useRouteMatch<{id:string}>("/doc/:id"); const match = useRouteMatch<{id:string}>("/doc/:id");
if (match == null) { if (match == null) {
@ -36,7 +48,7 @@ export const ContentAbout = (prop: { match: MatchType }) => {
</BackLinkContext.Consumer> </BackLinkContext.Consumer>
</NavList> </NavList>
); );
useEffect(() => { useEffect(() => {
(async () => { (async () => {
console.log("mount content about"); console.log("mount content about");
@ -47,6 +59,8 @@ export const ContentAbout = (prop: { match: MatchType }) => {
})() })()
return ()=>{console.log("unmount content about")} return ()=>{console.log("unmount content about")}
}, []); }, []);
const classes = useStyles();
if (isNaN(id)) { if (isNaN(id)) {
return ( return (
<Headline menu={menu_list()}> <Headline menu={menu_list()}>
@ -68,17 +82,19 @@ export const ContentAbout = (prop: { match: MatchType }) => {
); );
} }
else{ else{
const ReaderPage = getPresenter(info.content);
return (<Switch> return (<Switch>
<Route exact path={`${prop.match.path}/:id`}> <Route exact path={`${prop.match.path}/:id`}>
<Headline menu={menu_list()}> <Headline menu={menu_list()}>
<ContentInfo content={info.content}></ContentInfo> <ContentInfo content={info.content}></ContentInfo>
</Headline> </Headline>
</Route> </Route>
<Route exact path={`${prop.match.path}/:id/reader`}> <Route exact path={`${prop.match.path}/:id/reader`}>
<Headline menu={menu_list(`${prop.match.path}/${id}`)}> <Headline menu={menu_list(`${prop.match.path}/${id}`)} classes={{
<MangaReader content={info.content}></MangaReader> content:classes.noPaddingContent,
toolbar:classes.noPaddingToolbar
}}>
<ReaderPage content={info.content}></ReaderPage>
</Headline> </Headline>
</Route> </Route>
<Route> <Route>

View File

@ -1,8 +1,6 @@
import React, {useState, useEffect} from 'react'; import React, {useState, useEffect} from 'react';
import {Redirect, Route ,Switch,useHistory, useRouteMatch, match as MatchType, Link as RouterLink} from 'react-router-dom'; import { Typography, useTheme } from '@material-ui/core';
import { LoadingCircle } from '../../component/loading'; import { Content } from '../../accessor/contents';
import { Link, Paper, makeStyles, Theme, Box, Typography } from '@material-ui/core';
import { Content, makeThumbnailUrl } from '../../accessor/contents';
type MangaType = "manga"|"artist cg"|"donjinshi"|"western" type MangaType = "manga"|"artist cg"|"donjinshi"|"western"
@ -16,13 +14,35 @@ export type PresentableTag = {
} }
export const MangaReader = (props:{content:Content})=>{ export const MangaReader = (props:{content:Content})=>{
const theme = useTheme();
const additional = props.content.additional; const additional = props.content.additional;
const [curPage,setCurPage] = useState(0);
if(!('page' in additional)){ if(!('page' in additional)){
console.error("invalid content : page read fail : "+ JSON.stringify(additional)); console.error("invalid content : page read fail : "+ JSON.stringify(additional));
return <Typography>Error. DB error. page restriction</Typography> return <Typography>Error. DB error. page restriction</Typography>
} }
const PageDown = ()=>setCurPage(Math.max(curPage - 1 , 0));
const PageUP = ()=>setCurPage(Math.min(curPage + 1, page - 1));
const page:number = additional['page'] as number; const page:number = additional['page'] as number;
return (<div>{[...Array(page).keys()].map(x=>(<img src={`/content/${props.content.id}/manga/${x}`} key={x} style={{maxHeight:'100%',maxWidth:'100%'}}></img>))}</div>); const onKeyUp = (e: KeyboardEvent)=>{
if(e.code === "ArrowLeft"){
PageDown();
}
else if(e.code === "ArrowRight"){
PageUP();
}
}
useEffect(()=>{
document.addEventListener("keydown",onKeyUp);
return ()=>{
document.removeEventListener("keydown",onKeyUp);
}
});
//theme.mixins.toolbar.minHeight;
return (<div style={{overflow: 'hidden', alignSelf:'center'}}>
<img onClick={PageUP} src={`/content/${props.content.id}/manga/${curPage}`}
style={{maxWidth:'100%', maxHeight:'calc(100vh - 64px)'}}></img>
</div>);
} }
export default MangaReader; export default MangaReader;

View File

@ -1,21 +1,31 @@
import { Typography } from '@material-ui/core';
import React from 'react'; import React from 'react';
import { Content, makeThumbnailUrl } from '../../accessor/contents'; import { Content, makeThumbnailUrl } from '../../accessor/contents';
import {MangaReader} from './manga'; import {MangaReader} from './manga';
import {VideoReader} from './video'
export type PresenterCollection = { export interface PagePresenterProp{
ReaderPage: (props:{content:Content,className?:string})=> JSX.Element; content:Content,
}; className?:string
}
interface PagePresenter{
(prop:PagePresenterProp):JSX.Element
}
export const getPresenter = (content:Content):PresenterCollection=>{ export const getPresenter = (content:Content):PagePresenter => {
return { switch (content.content_type) {
ReaderPage:MangaReader case "manga":
}; return MangaReader;
case "video":
return VideoReader;
}
return ()=><Typography variant='h2'>Not implemented reader</Typography>;
} }
export const ThumbnailContainer = (props:{content:Content, className?:string})=>{ export const ThumbnailContainer = (props:{content:Content, className?:string})=>{
const thumbnailurl = makeThumbnailUrl(props.content); const thumbnailurl = makeThumbnailUrl(props.content);
if(props.content.content_type === "video"){ if(props.content.content_type === "video"){
return (<video src={thumbnailurl} className={props.className}></video>) return (<video src={thumbnailurl} muted autoPlay loop className={props.className}></video>)
} }
else return (<img src={thumbnailurl} className={props.className}></img>) else return (<img src={thumbnailurl} className={props.className}></img>)
} }

View File

@ -0,0 +1,7 @@
import React from 'react';
import { Content } from '../../accessor/contents';
export const VideoReader = (props:{content:Content})=>{
const id = props.content.id;
return <video controls autoPlay src={`/content/${props.content.id}/video`} style={{maxHeight:'100%',maxWidth:'100%'}}></video>;
}