import React, { useState } from "react";
import he from 'he';
import { useTranslation } from "react-i18next";
import { makeStyles, withStyles, createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import Autocomplete from '@material-ui/lab/Autocomplete';
import TextField from '@material-ui/core/TextField';
import red from '@material-ui/core/colors/red';
import CssBaseline from '@material-ui/core/CssBaseline';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import Checkbox from '@material-ui/core/Checkbox';
import FormGroup from '@material-ui/core/FormGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import MenuOpenIcon from '@material-ui/icons/MenuOpen';
import Avatar from '@material-ui/core/Avatar';
import Collapse from '@material-ui/core/Collapse';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';
import CardActionArea from '@material-ui/core/CardActionArea';
import CardMedia from '@material-ui/core/CardMedia';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
import GridList from '@material-ui/core/GridList';
import GridListTile from '@material-ui/core/GridListTile';
import ShoppingCartIcon from '@material-ui/icons/ShoppingCart';
import SearchIcon from '@material-ui/icons/Search';
import Badge from '@material-ui/core/Badge';
import InputBase from '@material-ui/core/InputBase';
import BottomNavigation from '@material-ui/core/BottomNavigation';
import BottomNavigationAction from '@material-ui/core/BottomNavigationAction';
import Skeleton from '@material-ui/lab/Skeleton';
import Paper from '@material-ui/core/Paper';
import Divider from '@material-ui/core/Divider';
import Chip from '@material-ui/core/Chip';
import Rating from '@material-ui/lab/Rating';
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
import StoreIcon from '@material-ui/icons/Store';
import LibraryBooksIcon from '@material-ui/icons/LibraryBooks';
import HelpOutlineIcon from '@material-ui/icons/HelpOutline';
import NavigateNextIcon from '@material-ui/icons/NavigateNext';
import NavigateBeforeIcon from '@material-ui/icons/NavigateBefore';
import Grow from '@material-ui/core/Grow';
import Link from '@material-ui/core/Link';
import Breadcrumbs from '@material-ui/core/Breadcrumbs';
import Snackbar from '@material-ui/core/Snackbar';
import LazyLoad from 'react-lazyload';
import { CarouselProvider, Slider, Slide, ButtonBack, ButtonNext } from 'pure-react-carousel';
import useTimeout from 'use-timeout'
import { GlobalState, useGlobalState, useWindowDimensions } from './utils.js';
import 'pure-react-carousel/dist/react-carousel.es.css';
import 'fontsource-roboto';
import {
BrowserRouter as Router,
Switch,
Route,
Redirect,
Link as RouteLink,
useLocation
} from "react-router-dom";
const StyledBadge = withStyles((theme) => ({
badge: {
right: -3,
top: 13,
border: `2px solid ${theme.palette.background.paper}`,
padding: '0 4px',
},
}))(Badge);
const global = {
store: { data: new GlobalState({data:[], loaded:false}), location: '/store' },
library: { data: new GlobalState({data:[], loaded:false}), location: '/library' },
account: { data: new GlobalState({data:[], loaded:false}), location: '/account' },
status: new GlobalState(null),
}
function StoreItemDetails(props) {
const { t } = useTranslation();
const { height, width } = useWindowDimensions();
const cols = Math.floor(width / 240);
const classes = makeStyles((theme) => ({
root: { paddingLeft: cols > 1 ? 18 : 4, paddingRight: cols > 1 ? 18 : 4 },
controls: { position: 'relative', width: '100%', maxWidth: (cols > 4 ? 640 : '100%') },
prev: { position: 'absolute', left: cols > 1 ? -15 : -4, top: '50%', backgroundColor: 'rgba(0, 0, 0, 0.5)', color: 'white' },
next: { position: 'absolute', right: cols > 1 ? -15 : -4, top: '50%', backgroundColor: 'rgba(0, 0, 0, 0.5)', color: 'white' },
img: { width: '100%', height: (height > 1024 ? 480 : 240), objectFit: 'contain', backgroundImage: 'url(/loading.png)', backgroundRepeat: 'no-repeat', backgroundPosition: 'center' }
}))();
return (
{t('Store')}
author
id
{t('Circle')}: Some Circle
{t('Release')}: 2020年10月24日
{t('Format')}: WAV / mp3同梱
{t('Size')}: 6.09GB
1 ? 260 : '100%')}}>
セール特価:
1500円
ポイント:
200
大廃線により鉄路のほとんどが失われてしまった国――日ノ本。
それでも各地に、大廃線に抗い続ける鉄道事業者はぽつぽつと点在している。、
そうした鉄道各社・各路線の沿線の魅力を、音という切り口から紹介しようという企画、「蓄音レヱル」が、とある大新聞社の主催によって立ち上げられた。
音を探し出して紹介する大役を担うことになるのは、普段はその路線を走る列車の運転制御をサポートしている人形/人形型のモジュール、“レイルロオド”たち。
八ツ城から颯馬仙岱まで、隈元-鹿兒島両県の八ツ城海沿いを縫うように走る第三セクター鉄道事業者、肥薩みかん鉄道を走る紅にも、その依頼が届く。
「みかん鉄道沿線のいい音がする場所を教えたら――それを全国紙の記事で紹介してもらえるの!?
得しかないじゃん! ぼく、やるよ!」
旧南颯鉄道――いまは滅びてしまった鉄道事業者の最後の一両の動態機として、解体・廃棄された妹たちとの思い出を胸に、紅は相棒であるあなたの手をとり、音探しの旅へと駆け出します。
颯馬仙岱の大名物であるぴんこ団子を焼くを聞き、出深(いずみ)の飛来地に群れなすツルたちの鳴き声に耳をそばだて、牛之濱の潮溜まりで波と戯れ、日凪久の足湯でくつろいで――
紅とふたりで尋ねる沿線の音たちは、きっとあなたの鼓膜を、こころをここちよく揺すり、やわらかにほぐしてくれるでしょう。
まっすぐで純情な紅との音探しの旅。
どうぞ、そのお耳を澄ませてお楽しみください。
なし
);
}
function StoreItemSkeleton(props) {
return (
);
}
function StoreItem(props) {
const { t } = useTranslation();
const classes = makeStyles((theme) => ({
media: { height: 180, position: 'relative' },
cat: { position: 'absolute', bottom: 4, left: 4 },
price: { position: 'absolute', bottom: 4, right: 4 },
rating: {
position: 'absolute', top: 4, right: 4,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
padding: 4, borderRadius: 4,
},
content: { paddingLeft: 8 },
text: {
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
},
avatar: { backgroundColor: red[500] }
}))();
return (
}>
{props.data.author.substring(0, 2)}
}
title={props.data.title}
titleTypographyProps={{className: classes.text}}
subheader={props.data.author}
subheaderTypographyProps={{className: classes.text}}
/>
);
}
function StoreSeparator(props) {
const { t } = useTranslation();
const classes = makeStyles((theme) => ({
root: { margin: 4 },
}))();
return (
);
}
function StoreCarousel(props) {
const { height, width } = useWindowDimensions();
const cols = Math.floor(width / 240);
const tw = (cols > 1 ? (cols * 240 > width - 18 ? 240 - 20 : 240) : '100%')
const classes = makeStyles((theme) => ({
root: { paddingLeft: cols > 1 ? 18 : 4, paddingRight: cols > 1 ? 18 : 4 },
tile: { width: tw, marginRight: 'auto', marginLeft: 'auto' },
controls: { position: 'relative' },
prev: { position: 'absolute', left: cols > 1 ? -15 : -4, top: '50%', backgroundColor: 'rgba(0, 0, 0, 0.5)', color: 'white' },
next: { position: 'absolute', right: cols > 1 ? -15 : -4, top: '50%', backgroundColor: 'rgba(0, 0, 0, 0.5)', color: 'white' },
}))();
var skeletons = [];
for (var i = 0; props.loading && i < cols; i += 1) skeletons.push({});
return (
{props.data.map((item, index) => )}
{skeletons.length ? skeletons.map((item, index) => ) : null}
);
}
function StoreList(props) {
const { height, width } = useWindowDimensions();
const cols = Math.floor(width / 240);
const tw = (cols > 1 ? (cols * 240 > width - 18 ? 240 - 20 : 240) : '100%')
const classes = makeStyles((theme) => ({
list: { justifyContent: 'space-evenly', maxWidth: '100%' },
tile: { width: tw, marginRight: 'auto', marginLeft: 'auto' },
}))();
var extra = [];
for (var i = 0; i < cols - (props.data.length % cols); i += 1) extra.push({key: i});
var skeletons = [];
for (var i2 = 0; props.loading && i2 < Math.max(cols * (Math.floor(height / 240)) - cols * 2, 1); i2 += 1) skeletons.push({key: i2});
return (
1 ? 18 : 4, paddingRight: cols > 1 ? 18 : 4 }}>
{props.data.map(item => )}
{extra.map(item => )}
{skeletons.map(item => )}
);
}
function StoreView(props) {
const [state, setState] = useGlobalState(global.store.data);
const [, setStatus] = useGlobalState(global.status);
useTimeout(() => {
async function fetchData() {
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
try {
var result = await fetch('https://cors-anywhere.herokuapp.com/https://www.eisys-bcs.jp/data.json?key[]=dlsite-doujin_home_center2').then(result => result.json());
result = result.data.['dlsite-doujin_home_center2'].banners.map(item => { return {
id: 'no-id',
author: he.decode(item.title),
title: he.decode(item.title),
shortdesc: 'foobar',
desc: 'foobar',
img: 'https:' + item.ssl_path,
cat: 'Misc',
price: getRandomInt(3000) + '円',
rating: getRandomInt(5),
}})
} catch (err) {
result = [];
setStatus(err);
}
setState({data:result, loaded:true});
}
fetchData();
}, 600);
return (
<>
>
);
}
function LibraryView(props) {
const [state, setState] = useGlobalState(global.library.data);
const [, setStatus] = useGlobalState(global.status);
useTimeout(() => {
async function fetchData() {
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
try {
var result = await fetch('https://cors-anywhere.herokuapp.com/https://www.eisys-bcs.jp/data.json?key[]=dlsite-doujin_home_center2').then(result => result.json());
result = result.data.['dlsite-doujin_home_center2'].banners.map(item => { return {
id: 'no-id',
author: he.decode(item.title),
title: he.decode(item.title),
shortdesc: 'foobar',
desc: 'foobar',
img: 'https:' + item.ssl_path,
cat: 'Misc',
price: getRandomInt(3000) + '円',
rating: getRandomInt(5),
}})
} catch (err) {
result = [];
setStatus(err);
}
setState({data:result, loaded:true});
}
fetchData();
}, 600);
return (
<>
>
);
}
function AccountView(props) {
return <>>;
}
function ItemSearch(props) {
const { t } = useTranslation();
const classes = makeStyles((theme) => ({
search: {
padding: '2px 4px',
display: 'flex',
alignItems: 'center',
},
input: {
marginLeft: theme.spacing(1),
flex: 1,
},
iconButton: {
padding: 10,
},
}))();
const categories = ['Manga', 'CG', 'Audio', 'Video', 'Game']
const audience = [{key: 'All ages', value: true}, {key: 'Heterosexual', value: false}, {key: 'Homosexual', value: false}]
const keywords = [
t('RPG'),
t('Simulation'),
t('Stragety'),
t('Action'),
t('ASMR'),
t('Anime'),
t('3D'),
t('2D'),
t('Pixel art'),
t('Live action'),
t('Metal'),
t('Pop'),
t('Rock'),
];
const [menuOpen, setMenuOpen] = useState(false);
return (
<>
setMenuOpen(!menuOpen)}>
{menuOpen ? : }
{t('Keywords')}
option}
defaultValue={[]}
renderInput={(params) => }
/>
{t('Category')}
{categories.map(cat =>
}
key={cat} label={t(cat)}/>)}
{t('Audience')}
{audience.map(cat =>
}
key={cat.key} label={t(cat.key)}/>)}
>
);
}
function BottomBar(props) {
var location = useLocation();
const components = location.pathname.split('/');
switch (components[1]) {
case 'store': case 'library': case 'account': global[components[1]].location = location;
}
const { t } = useTranslation();
const classes = makeStyles((theme) => ({
stickyBottom: {
position: 'fixed',
width: '100%',
bottom: 0,
},
}))();
return (
} component={RouteLink} to={global.store.location}/>
} component={RouteLink} to={global.library.location}/>
} component={RouteLink} to={global.account.location}/>
);
}
function TopBar(props) {
var location = useLocation();
const components = location.pathname.split('/');
const { t } = useTranslation();
const classes = makeStyles((theme) => ({
title: { flexGrow: 1 },
backButton: { marginRight: theme.spacing(1) },
}))();
const search = (components[1] !== 'account');
return (
2} unmountOnExit>
window.history.back()}>
{t('DoujinSea')}
);
}
function Routing() {
const classes = makeStyles((theme) => ({
content: {
paddingTop: 105,
paddingBottom: 65,
minHeight: '100vh',
},
}))();
const [status, setStatus] = useGlobalState(global.status);
return (
<>
setStatus(null)}
autoHideDuration={6000}
anchorOrigin={{vertical: 'top', horizontal: 'center'}}
open={status !== null}
message={status ? status : ''}
key={status}
/>
>
);
}
export default function Main() {
const prefersDarkMode = false; // useMediaQuery('(prefers-color-scheme: dark)');
const theme = React.useMemo(() => createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
primary: red,
},
}), [prefersDarkMode]);
return (
<>
>
);
}