headline
This commit is contained in:
		
							parent
							
								
									541de21e66
								
							
						
					
					
						commit
						5002bc22f9
					
				
					 9 changed files with 271 additions and 190 deletions
				
			
		| 
						 | 
				
			
			@ -1,27 +1,24 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
import React, { useRef, useState } from 'react';
 | 
			
		||||
import ReactDom from 'react-dom';
 | 
			
		||||
import {BrowserRouter, Route, Switch as RouterSwitch} from 'react-router-dom';
 | 
			
		||||
import {Headline} from './page/headline';
 | 
			
		||||
import {Gallery} from './page/gallery';
 | 
			
		||||
import {ContentAbout} from './page/contentinfo';
 | 
			
		||||
import { Gallery, ContentAbout} from './page/mod';
 | 
			
		||||
 | 
			
		||||
import './css/style.css';
 | 
			
		||||
 | 
			
		||||
const FooProfile = ()=><div>test profile</div>;
 | 
			
		||||
const App = ()=> (
 | 
			
		||||
    <BrowserRouter>
 | 
			
		||||
        <Headline>
 | 
			
		||||
const App = () => {
 | 
			
		||||
    return (<BrowserRouter>
 | 
			
		||||
            <RouterSwitch>
 | 
			
		||||
                <Route path="/" exact component={Gallery}></Route>
 | 
			
		||||
                <Route path="/doc" component={ContentAbout}></Route>
 | 
			
		||||
                <Route path="/" exact render={()=><Gallery />}></Route>
 | 
			
		||||
                <Route path="/search" render={()=><Gallery />}></Route>
 | 
			
		||||
                <Route path="/doc" render={(prop)=><ContentAbout {...prop}/>}></Route>
 | 
			
		||||
                <Route path="/profile" component={FooProfile}></Route>
 | 
			
		||||
                <Route>
 | 
			
		||||
                    <div>404 Not Found</div>
 | 
			
		||||
                </Route>
 | 
			
		||||
            </RouterSwitch>
 | 
			
		||||
        </Headline>
 | 
			
		||||
    </BrowserRouter>
 | 
			
		||||
);
 | 
			
		||||
    </BrowserRouter>);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ReactDom.render(
 | 
			
		||||
    <App/>,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,34 +34,93 @@ const useStyles = makeStyles((theme: Theme) => ({
 | 
			
		|||
    title: {
 | 
			
		||||
        marginLeft: theme.spacing(1),
 | 
			
		||||
    },
 | 
			
		||||
    InfoContainer: {
 | 
			
		||||
    infoContainer: {
 | 
			
		||||
        padding: theme.spacing(2),
 | 
			
		||||
    },
 | 
			
		||||
    subinfoContainer: {
 | 
			
		||||
        display: 'grid',
 | 
			
		||||
        gridTemplateColumns: '100px auto',
 | 
			
		||||
        overflowY: 'hidden',
 | 
			
		||||
    },
 | 
			
		||||
    short_subinfoContainer:{
 | 
			
		||||
        [theme.breakpoints.up("xs")]:{
 | 
			
		||||
            display:'none',
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    short_root:{
 | 
			
		||||
        overflowY:'hidden',
 | 
			
		||||
        display:'flex',
 | 
			
		||||
        flexDirection: 'column',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            height:200,
 | 
			
		||||
            flexDirection: 'row',
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    short_thumbnail_anchor:{
 | 
			
		||||
        background: '#272733',
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        alignItems: 'center',
 | 
			
		||||
        justifyContent: 'center',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            width: theme.spacing(25),
 | 
			
		||||
            height: theme.spacing(25),
 | 
			
		||||
            flexShrink: 0,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    short_thumbnail_content: {
 | 
			
		||||
        maxWidth: '100%',
 | 
			
		||||
        maxHeight: '100%',
 | 
			
		||||
    },
 | 
			
		||||
}))
 | 
			
		||||
 | 
			
		||||
export const ContentInfo = (props: { content: Content, children?: React.ReactNode }) => {
 | 
			
		||||
export const ContentInfo = (props: {
 | 
			
		||||
    content: Content, children?: React.ReactNode, classes?: {
 | 
			
		||||
        root?: string,
 | 
			
		||||
        thumbnail_anchor?: string,
 | 
			
		||||
        thumbnail_content?: string,
 | 
			
		||||
        tag_list?: string,
 | 
			
		||||
        title?: string,
 | 
			
		||||
        infoContainer?: string,
 | 
			
		||||
        subinfoContainer?: string
 | 
			
		||||
    },
 | 
			
		||||
    gallery?:string,
 | 
			
		||||
    short?:boolean
 | 
			
		||||
}) => {
 | 
			
		||||
    const classes = useStyles();
 | 
			
		||||
    const theme = useTheme();
 | 
			
		||||
    const content = props?.content;
 | 
			
		||||
    const content = props.content;
 | 
			
		||||
    const propclasses = props.classes || {};
 | 
			
		||||
 | 
			
		||||
    const rootName = props.short ? classes.short_root : classes.root;
 | 
			
		||||
    const thumbnail_anchor = props.short ? classes.short_thumbnail_anchor : "";
 | 
			
		||||
    const thumbnail_content = props.short ? classes.short_thumbnail_content :
 | 
			
		||||
        classes.thumbnail_content;
 | 
			
		||||
    const subinfoContainer = props.short ? classes.short_subinfoContainer :
 | 
			
		||||
        classes.subinfoContainer;
 | 
			
		||||
    let allTag = content.tags;
 | 
			
		||||
    const artists = allTag.filter(x => x.startsWith("artist:")).map(x => x.substr(7));
 | 
			
		||||
    allTag = allTag.filter(x => !x.startsWith("artist:"));
 | 
			
		||||
    return (<Paper className={classes.root}>
 | 
			
		||||
        <Link component={RouterLink} to={makeContentReaderUrl(content.id)}>
 | 
			
		||||
            <ThumbnailContainer content={content} className={classes.thumbnail_content}></ThumbnailContainer>
 | 
			
		||||
    return (<Paper className={propclasses.root || rootName} elevation={4}>
 | 
			
		||||
        <Link className={propclasses.thumbnail_anchor || thumbnail_anchor} component={RouterLink} to={{
 | 
			
		||||
            pathname:makeContentReaderUrl(content.id),
 | 
			
		||||
            state:props.gallery
 | 
			
		||||
        }}>
 | 
			
		||||
            <ThumbnailContainer content={content} 
 | 
			
		||||
                className={propclasses.thumbnail_content || thumbnail_content}/>
 | 
			
		||||
        </Link>
 | 
			
		||||
        <Box style={{ padding: theme.spacing(1) }}>
 | 
			
		||||
            <Link variant='h5' color='inherit' component={RouterLink} to={makeContentReaderUrl(content.id)}
 | 
			
		||||
                className={classes.title}>
 | 
			
		||||
        <Box className={propclasses.infoContainer || classes.infoContainer}>
 | 
			
		||||
            <Link variant='h5' color='inherit' component={RouterLink} to={{
 | 
			
		||||
                pathname: props.gallery === undefined ? makeContentReaderUrl(content.id) : makeContentInfoUrl(content.id),
 | 
			
		||||
                state:props.gallery
 | 
			
		||||
            }}
 | 
			
		||||
                className={propclasses.title || classes.title}>
 | 
			
		||||
                {content.title}
 | 
			
		||||
            </Link>
 | 
			
		||||
            <Box className={classes.InfoContainer}>
 | 
			
		||||
            <Box className={propclasses.subinfoContainer || subinfoContainer}>
 | 
			
		||||
                <Typography variant='subtitle1'>Artist</Typography>
 | 
			
		||||
                <Box style={{ alignSelf: "center" }}>{artists.join(", ")}</Box>
 | 
			
		||||
                <Typography variant='subtitle1'>Tags</Typography>
 | 
			
		||||
                <Box className={classes.tag_list}>
 | 
			
		||||
                <Box className={propclasses.tag_list || classes.tag_list}>
 | 
			
		||||
                    {allTag.map(x => {
 | 
			
		||||
                        return (<TagChip key={x} label={x} clickable={true} tagname={x} size="small"></TagChip>);
 | 
			
		||||
                    })}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										71
									
								
								src/client/component/galleryinfo.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/client/component/galleryinfo.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,71 @@
 | 
			
		|||
import { Box, Paper, Link, useMediaQuery, Portal, List, ListItem, ListItemIcon, Tooltip, ListItemText } from '@material-ui/core';
 | 
			
		||||
import {useTheme, makeStyles, Theme} from '@material-ui/core/styles';
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import ContentAccessor,{QueryListOption, Content} from '../accessor/contents';
 | 
			
		||||
import {Link as RouterLink} from 'react-router-dom';
 | 
			
		||||
import { LoadingCircle, ContentInfo, NavList, NavItem } from './mod';
 | 
			
		||||
import {toQueryString} from '../accessor/util';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const useStyles = makeStyles((theme:Theme)=>({
 | 
			
		||||
    root:{
 | 
			
		||||
        display:"grid",
 | 
			
		||||
        gridGap: theme.spacing(4),
 | 
			
		||||
    },
 | 
			
		||||
    anchor_thumbnail:{
 | 
			
		||||
        background: '#272733',
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        alignItems: 'center',
 | 
			
		||||
        justifyContent: 'center',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            width: theme.spacing(25),
 | 
			
		||||
            height: theme.spacing(25),
 | 
			
		||||
            flexShrink: 0,
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    contentPaper:{
 | 
			
		||||
        overflowY:'hidden',
 | 
			
		||||
        display:'flex',
 | 
			
		||||
        flexDirection: 'column',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            height:200,
 | 
			
		||||
            flexDirection: 'row',
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    content_thumnail: {
 | 
			
		||||
        maxWidth: '100%',
 | 
			
		||||
        maxHeight: '100%',
 | 
			
		||||
    },
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export type GalleryProp = {
 | 
			
		||||
    option?:QueryListOption;
 | 
			
		||||
};
 | 
			
		||||
type GalleryState = {
 | 
			
		||||
    content:Content[]|undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const GalleryInfo = (props: GalleryProp)=>{
 | 
			
		||||
    const [state,setState]= useState<GalleryState>({content:undefined});
 | 
			
		||||
    useEffect(()=>{
 | 
			
		||||
        (async ()=>{
 | 
			
		||||
            const c = await ContentAccessor.findList(props.option);
 | 
			
		||||
            setState({content:c});
 | 
			
		||||
        })()
 | 
			
		||||
    },[props.option]);
 | 
			
		||||
    const classes = useStyles();
 | 
			
		||||
    const queryString = toQueryString(props.option||{});
 | 
			
		||||
 | 
			
		||||
    if(state.content === undefined){
 | 
			
		||||
        return (<LoadingCircle/>);
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
        return (<Box className={classes.root}>{
 | 
			
		||||
            state.content.map(x=>{
 | 
			
		||||
                return (<ContentInfo content={x} key={x.id} 
 | 
			
		||||
                    gallery={`/search?${queryString}`} short/>);
 | 
			
		||||
            })
 | 
			
		||||
            }
 | 
			
		||||
            </Box>);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,13 +1,13 @@
 | 
			
		|||
import ReactDom from 'react-dom';
 | 
			
		||||
import React, { useState } from 'react';
 | 
			
		||||
import React, { ReactNode, useState } from 'react';
 | 
			
		||||
import {
 | 
			
		||||
    Button, CssBaseline, Divider, IconButton, List, ListItem, Drawer,
 | 
			
		||||
    AppBar, Toolbar, Typography, InputBase, ListItemIcon, ListItemText, Menu, MenuItem,
 | 
			
		||||
    Hidden, Tooltip
 | 
			
		||||
    Hidden, Tooltip, Link
 | 
			
		||||
} from '@material-ui/core';
 | 
			
		||||
import { makeStyles, Theme, useTheme, fade } from '@material-ui/core/styles';
 | 
			
		||||
import { ChevronLeft, ChevronRight, Menu as MenuIcon, Search as SearchIcon, ArrowBack as ArrowBackIcon, AccountCircle } from '@material-ui/icons';
 | 
			
		||||
import {Link} from 'react-router-dom';
 | 
			
		||||
import { ChevronLeft, ChevronRight, Menu as MenuIcon, Search as SearchIcon, AccountCircle } from '@material-ui/icons';
 | 
			
		||||
import { Link as RouterLink, useRouteMatch } from 'react-router-dom';
 | 
			
		||||
 | 
			
		||||
const drawerWidth = 240;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -104,7 +104,12 @@ const useStyles = makeStyles((theme: Theme) => ({
 | 
			
		|||
    },
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
export const Headline = (prop: { children?: React.ReactNode, navListItem?: React.ReactNode, isLogin?:boolean}) => {
 | 
			
		||||
export const Headline = (prop: {
 | 
			
		||||
    children?: React.ReactNode,
 | 
			
		||||
    navListItem?: React.ReactNode,
 | 
			
		||||
    isLogin?: boolean,
 | 
			
		||||
    menu: React.ReactNode
 | 
			
		||||
}) => {
 | 
			
		||||
    const [v, setv] = useState(false);
 | 
			
		||||
    const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
 | 
			
		||||
    const classes = useStyles();
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +129,7 @@ export const Headline = (prop: { children?: React.ReactNode, navListItem?: React
 | 
			
		|||
        transformOrigin={{ horizontal: 'right', vertical: "top" }}
 | 
			
		||||
        onClose={handleProfileMenuClose}
 | 
			
		||||
    >
 | 
			
		||||
        <MenuItem component={Link} to='/profile'>Profile</MenuItem>
 | 
			
		||||
        <MenuItem component={RouterLink} to='/profile'>Profile</MenuItem>
 | 
			
		||||
        <MenuItem>Logout</MenuItem>
 | 
			
		||||
    </Menu>);
 | 
			
		||||
    const drawer_contents = (<>
 | 
			
		||||
| 
						 | 
				
			
			@ -134,17 +139,7 @@ export const Headline = (prop: { children?: React.ReactNode, navListItem?: React
 | 
			
		|||
            </IconButton>
 | 
			
		||||
        </div>
 | 
			
		||||
        <Divider />
 | 
			
		||||
            <List>
 | 
			
		||||
                <ListItem button key="Back">
 | 
			
		||||
                    <ListItemIcon>
 | 
			
		||||
                        <Tooltip title="back" placement="bottom">
 | 
			
		||||
                            <ArrowBackIcon></ArrowBackIcon>
 | 
			
		||||
                        </Tooltip>
 | 
			
		||||
                    </ListItemIcon>
 | 
			
		||||
                    <ListItemText primary="Back"></ListItemText>
 | 
			
		||||
                </ListItem>
 | 
			
		||||
                {prop.navListItem}
 | 
			
		||||
            </List>
 | 
			
		||||
        {prop.menu}
 | 
			
		||||
    </>);
 | 
			
		||||
    return (<div className={classes.root}>
 | 
			
		||||
        <CssBaseline />
 | 
			
		||||
| 
						 | 
				
			
			@ -157,9 +152,9 @@ export const Headline = (prop: { children?: React.ReactNode, navListItem?: React
 | 
			
		|||
                    className={classes.menuButton}>
 | 
			
		||||
                    <MenuIcon></MenuIcon>
 | 
			
		||||
                </IconButton>
 | 
			
		||||
                <Typography variant="h5" noWrap className={classes.title}>
 | 
			
		||||
                <Link variant="h5" noWrap className={classes.title} color="inherit" component={RouterLink} to="/">
 | 
			
		||||
                    Ionian
 | 
			
		||||
                </Typography>
 | 
			
		||||
                </Link>
 | 
			
		||||
                <div className={classes.grow}></div>
 | 
			
		||||
                <div className={classes.search}>
 | 
			
		||||
                    <div className={classes.searchIcon}>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,6 @@
 | 
			
		|||
export * from './contentinfo';
 | 
			
		||||
export * from './loading';
 | 
			
		||||
export * from './tagchip';
 | 
			
		||||
export * from './navlist';
 | 
			
		||||
export * from './galleryinfo';
 | 
			
		||||
export * from './headline';
 | 
			
		||||
							
								
								
									
										21
									
								
								src/client/component/navlist.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/client/component/navlist.tsx
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
import {List, ListItem, ListItemIcon, Tooltip, ListItemText} from '@material-ui/core';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import {Link as RouterLink} from 'react-router-dom';
 | 
			
		||||
import {LocationDescriptorObject} from 'history';
 | 
			
		||||
 | 
			
		||||
export const NavItem = (props:{name:string,to:string, icon:React.ReactElement<any,any>})=>{
 | 
			
		||||
    return (<ListItem button key={props.name} component={RouterLink} to={props.to}>
 | 
			
		||||
    <ListItemIcon>
 | 
			
		||||
        <Tooltip title={props.name.toLocaleLowerCase()} placement="bottom">
 | 
			
		||||
            {props.icon}
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
    </ListItemIcon>
 | 
			
		||||
    <ListItemText primary={props.name}></ListItemText>
 | 
			
		||||
</ListItem>);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const NavList = (props: {children?:React.ReactNode})=>{
 | 
			
		||||
    return (<List>
 | 
			
		||||
            {props.children}
 | 
			
		||||
        </List>);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,11 @@
 | 
			
		|||
import React, { useState, useEffect } from 'react';
 | 
			
		||||
import { Redirect, Route, Switch, useHistory, useRouteMatch, match as MatchType, Link as RouterLink } from 'react-router-dom';
 | 
			
		||||
import { Redirect, Route, Switch, useHistory, useRouteMatch, match as MatchType, Link as RouterLink, useParams, useLocation } from 'react-router-dom';
 | 
			
		||||
import ContentAccessor, { Content } from '../accessor/contents';
 | 
			
		||||
import { LoadingCircle } from '../component/loading';
 | 
			
		||||
import { Link, Paper, makeStyles, Theme, Box, useTheme, Typography } from '@material-ui/core';
 | 
			
		||||
import {ArrowBack as ArrowBackIcon } from '@material-ui/icons';
 | 
			
		||||
import { MangaReader } from './reader/manga';
 | 
			
		||||
import { ContentInfo } from '../component/mod';
 | 
			
		||||
import { ContentInfo, Headline, NavItem, NavList } from '../component/mod';
 | 
			
		||||
 | 
			
		||||
export const makeContentInfoUrl = (id: number) => `/doc/${id}`;
 | 
			
		||||
export const makeMangaReaderUrl = (id: number) => `/doc/${id}/reader`;
 | 
			
		||||
| 
						 | 
				
			
			@ -15,39 +16,65 @@ type ContentState = {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
export const ContentAbout = (prop: { match: MatchType }) => {
 | 
			
		||||
    const match = useRouteMatch("/doc/:id");
 | 
			
		||||
    const match = useRouteMatch<{id:string}>("/doc/:id");
 | 
			
		||||
    if (match == null) {
 | 
			
		||||
        throw new Error("unreachable");
 | 
			
		||||
    }
 | 
			
		||||
    const m = /\/doc\/(\d+)/.exec(match.url);
 | 
			
		||||
    const id = m !== null ? Number.parseInt(m[1]) : NaN;
 | 
			
		||||
    const id = Number.parseInt(match.params['id']);
 | 
			
		||||
    const [info, setInfo] = useState<ContentState>({ content: undefined, notfound:false });
 | 
			
		||||
    const location = useLocation();
 | 
			
		||||
    console.log("state : "+location.state);
 | 
			
		||||
    const menu_list = (
 | 
			
		||||
        <NavList>
 | 
			
		||||
            <NavItem name="Back" to="/" icon={<ArrowBackIcon/>}></NavItem>
 | 
			
		||||
        </NavList>
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        (async () => {
 | 
			
		||||
            console.log("mount content about");
 | 
			
		||||
            if (!isNaN(id)) {
 | 
			
		||||
                const c = await ContentAccessor.findById(id);
 | 
			
		||||
                setInfo({ content: c, notfound: c === undefined });
 | 
			
		||||
            }
 | 
			
		||||
        })()
 | 
			
		||||
        return ()=>{console.log("unmount content about")}
 | 
			
		||||
    }, []);
 | 
			
		||||
    if (isNaN(id)) {
 | 
			
		||||
        return (<Typography variant='h2'>Oops. Invalid ID</Typography>)
 | 
			
		||||
        return (
 | 
			
		||||
            <Headline menu={menu_list}>
 | 
			
		||||
                <Typography variant='h2'>Oops. Invalid ID</Typography>
 | 
			
		||||
            </Headline>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else if(info.notfound){
 | 
			
		||||
        return (<Typography variant='h2'>Content has been removed.</Typography>)
 | 
			
		||||
        return (
 | 
			
		||||
            <Headline menu={menu_list}>
 | 
			
		||||
                <Typography variant='h2'>Content has been removed.</Typography>
 | 
			
		||||
            </Headline>
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
    else if (info.content === undefined) {
 | 
			
		||||
        return (<LoadingCircle />);
 | 
			
		||||
        return (<Headline menu={menu_list}>
 | 
			
		||||
            <LoadingCircle />
 | 
			
		||||
        </Headline>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    else return (<Switch>
 | 
			
		||||
        <Route exact path={`${prop.match.path}/:id`}>
 | 
			
		||||
            <Headline menu={menu_list}>
 | 
			
		||||
                <ContentInfo content={info.content}></ContentInfo>
 | 
			
		||||
            </Headline>
 | 
			
		||||
        </Route>
 | 
			
		||||
        <Route exact path={`${prop.match.path}/:id/reader`}>
 | 
			
		||||
            <Headline menu={menu_list}>
 | 
			
		||||
                <MangaReader content={info.content}></MangaReader>
 | 
			
		||||
            </Headline>
 | 
			
		||||
        </Route>
 | 
			
		||||
        <Route>
 | 
			
		||||
            <Headline menu={menu_list}>
 | 
			
		||||
                <div>404 Not Found invalid url : {prop.match.path}</div>
 | 
			
		||||
            </Headline>
 | 
			
		||||
        </Route>
 | 
			
		||||
    </Switch>);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,108 +1,14 @@
 | 
			
		|||
import { Box, Paper, Link, useMediaQuery } from '@material-ui/core';
 | 
			
		||||
import React, { useEffect, useState } from 'react';
 | 
			
		||||
import ContentAccessor,{makeThumbnailUrl, QueryListOption, Content} from '../accessor/contents';
 | 
			
		||||
import {useTheme, makeStyles, Theme} from '@material-ui/core/styles';
 | 
			
		||||
import {Link as RouterLink} from 'react-router-dom';
 | 
			
		||||
import {makeContentInfoUrl} from './contentinfo';
 | 
			
		||||
import { LoadingCircle } from '../component/loading';
 | 
			
		||||
import {ThumbnailContainer} from './reader/reader';
 | 
			
		||||
import {TagChip} from '../component/tagchip';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { NavList, NavItem, Headline } from '../component/mod';
 | 
			
		||||
import {ArrowBack as ArrowBackIcon} from '@material-ui/icons';
 | 
			
		||||
import {GalleryInfo} from '../component/mod';
 | 
			
		||||
 | 
			
		||||
const useStyles = makeStyles((theme:Theme)=>({
 | 
			
		||||
    root:{
 | 
			
		||||
        display:"grid",
 | 
			
		||||
        gridGap: theme.spacing(4),
 | 
			
		||||
    },
 | 
			
		||||
    anchor_thumbnail:{
 | 
			
		||||
        background: '#272733',
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        alignItems: 'center',
 | 
			
		||||
        justifyContent: 'center',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            width: theme.spacing(25),
 | 
			
		||||
            height: theme.spacing(25),
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    contentPaper:{
 | 
			
		||||
        display:'flex',
 | 
			
		||||
        flexDirection: 'column',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            height:200,
 | 
			
		||||
            flexDirection: 'row',
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    content_thumnail: {
 | 
			
		||||
        maxWidth: '100%',
 | 
			
		||||
        maxHeight: '100%',
 | 
			
		||||
    },
 | 
			
		||||
    content_info:{
 | 
			
		||||
        padding: `${theme.spacing(1)}px ${theme.spacing(2)}px`,
 | 
			
		||||
        width: '100%',
 | 
			
		||||
        display: 'flex',
 | 
			
		||||
        flexDirection: 'column',
 | 
			
		||||
    },
 | 
			
		||||
    content_info_title:{
 | 
			
		||||
        marginLeft:theme.spacing(2),
 | 
			
		||||
    },
 | 
			
		||||
    tag_list:{
 | 
			
		||||
        display:'none',
 | 
			
		||||
        [theme.breakpoints.up("sm")]:{
 | 
			
		||||
            display: 'flex',
 | 
			
		||||
            justifyContent: 'flex-start',
 | 
			
		||||
            flexWrap: 'wrap',
 | 
			
		||||
            overflowY: 'hidden',
 | 
			
		||||
            '& > *': {
 | 
			
		||||
                margin: theme.spacing(0.5),
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}));
 | 
			
		||||
export const Gallery = ()=>{
 | 
			
		||||
    const menu_list = (<NavList>
 | 
			
		||||
        <NavItem name="Back" to="" icon={<ArrowBackIcon></ArrowBackIcon>}></NavItem>
 | 
			
		||||
    </NavList>);
 | 
			
		||||
 | 
			
		||||
export type GalleryProp = {
 | 
			
		||||
    option?:QueryListOption;
 | 
			
		||||
};
 | 
			
		||||
type GalleryState = {
 | 
			
		||||
    content:Content[]|undefined;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Gallery = (props: GalleryProp)=>{
 | 
			
		||||
    const [state,setState]= useState<GalleryState>({content:undefined});
 | 
			
		||||
    useEffect(()=>{
 | 
			
		||||
        (async ()=>{
 | 
			
		||||
            const c = await ContentAccessor.findList(props.option);
 | 
			
		||||
            setState({content:c});
 | 
			
		||||
        })()
 | 
			
		||||
    },[props.option]);
 | 
			
		||||
    const num = 1;
 | 
			
		||||
    const classes = useStyles();
 | 
			
		||||
    const theme = useTheme();
 | 
			
		||||
    const isMobile = !useMediaQuery(theme.breakpoints.up("sm"));
 | 
			
		||||
        if(state.content === undefined){
 | 
			
		||||
            return (<LoadingCircle/>);
 | 
			
		||||
        }
 | 
			
		||||
        else{
 | 
			
		||||
            return (<div className={classes.root}>{
 | 
			
		||||
                state.content.map(x=>{
 | 
			
		||||
                    const thumbnail_url = makeThumbnailUrl(x);
 | 
			
		||||
                    return (<Paper key={x.id} elevation={4} className={classes.contentPaper}>
 | 
			
		||||
                        <Link className={classes.anchor_thumbnail}
 | 
			
		||||
                             component={RouterLink} to={makeContentInfoUrl(x.id)}>
 | 
			
		||||
                            <ThumbnailContainer content={x} className={classes.content_thumnail}></ThumbnailContainer>
 | 
			
		||||
                        </Link>
 | 
			
		||||
                        <Box className={classes.content_info}>
 | 
			
		||||
                            <Link component={RouterLink} to={makeContentInfoUrl(x.id)} variant="h5" color="inherit"
 | 
			
		||||
                                className={classes.content_info_title}>
 | 
			
		||||
                                {x.title}
 | 
			
		||||
                            </Link>
 | 
			
		||||
                            <Box className={classes.tag_list}>
 | 
			
		||||
                                {x.tags.map(x=>{
 | 
			
		||||
                                    return (<TagChip key={x} label={x} clickable={true} tagname={x} size="small"></TagChip>);
 | 
			
		||||
                            })}
 | 
			
		||||
                            </Box>
 | 
			
		||||
                        </Box>
 | 
			
		||||
                    </Paper>);
 | 
			
		||||
                })
 | 
			
		||||
                }
 | 
			
		||||
                </div>);
 | 
			
		||||
        }
 | 
			
		||||
    return (<Headline menu={menu_list}>
 | 
			
		||||
        <GalleryInfo></GalleryInfo>
 | 
			
		||||
    </Headline>)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								src/client/page/mod.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								src/client/page/mod.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
export * from './contentinfo';
 | 
			
		||||
export * from './gallery';
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue