Files
suwayomi-material-you-webui/src/components/manga/MangaCard.tsx

123 lines
3.7 KiB
TypeScript
Raw Normal View History

/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
2021-01-26 23:32:12 +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-01-29 14:25:18 +03:30
import React from 'react';
2021-09-09 17:51:22 +04:30
import makeStyles from '@mui/styles/makeStyles';
import Card from '@mui/material/Card';
import CardActionArea from '@mui/material/CardActionArea';
import Typography from '@mui/material/Typography';
2021-01-19 20:20:28 +03:30
import { Link } from 'react-router-dom';
2021-09-09 17:51:22 +04:30
import { Grid } from '@mui/material';
import useLocalStorage from 'util/useLocalStorage';
2021-05-28 19:37:26 +04:30
import SpinnerImage from 'components/SpinnerImage';
2020-12-25 17:42:22 +01:00
const useStyles = makeStyles((theme) => ({
2020-12-25 17:42:22 +01:00
root: {
height: '100%',
width: '100%',
display: 'flex',
},
wrapper: {
position: 'relative',
height: '100%',
},
gradient: {
position: 'absolute',
top: 0,
width: '100%',
height: '100%',
background: 'linear-gradient(to bottom, transparent, #000000)',
opacity: 0.5,
},
title: {
position: 'absolute',
bottom: 0,
padding: '0.5em',
color: 'white',
2021-08-29 21:46:20 +04:30
fontSize: '1.05rem',
textShadow: '0px 0px 3px #000000',
2020-12-25 17:42:22 +01:00
},
badge: {
position: 'absolute',
top: 2,
left: 2,
backgroundColor: theme.palette.primary.dark,
borderRadius: 5,
color: 'white',
padding: '0.1em',
paddingInline: '0.3em',
fontSize: '1.05rem',
},
2020-12-25 17:42:22 +01:00
image: {
height: '100%',
width: '100%',
},
2021-05-28 19:37:26 +04:30
spinner: {
minHeight: '400px',
display: 'grid',
placeItems: 'center',
2021-05-28 19:37:26 +04:30
},
}));
2020-12-25 17:42:22 +01:00
2021-08-29 21:46:20 +04:30
const truncateText = (str: string, maxLength: number) => {
const ending = '...';
// trim the string to the maximum length
const trimmedString = str.substr(0, maxLength - ending.length);
if (trimmedString.length < str.length) {
return trimmedString + ending;
}
return str;
};
2020-12-25 17:42:22 +01:00
interface IProps {
manga: IMangaCard
2020-12-25 17:42:22 +01:00
}
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
2020-12-25 17:42:22 +01:00
const {
manga: {
id, title, thumbnailUrl, unreadCount: unread,
2021-01-29 14:25:18 +03:30
},
2020-12-25 17:42:22 +01:00
} = props;
const classes = useStyles();
2021-03-07 22:35:27 +03:30
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
2021-09-18 20:59:23 +04:30
const [useCache] = useLocalStorage<boolean>('useCache', true);
2020-12-25 17:42:22 +01:00
return (
2021-01-23 01:58:18 +03:30
<Grid item xs={6} sm={4} md={3} lg={2}>
<Link to={`/manga/${id}/`}>
<Card className={classes.root} ref={ref}>
<CardActionArea>
<div className={classes.wrapper}>
{unread
? (
<Typography className={classes.badge} component="span">
{unread}
</Typography>
)
: null}
2021-05-28 19:37:26 +04:30
<SpinnerImage
2021-01-23 01:58:18 +03:30
alt={title}
2021-09-18 20:59:23 +04:30
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
2021-05-28 19:37:26 +04:30
spinnerClassName={classes.spinner}
imgClassName={classes.image}
2021-01-23 01:58:18 +03:30
/>
<div className={classes.gradient} />
2021-08-29 21:46:20 +04:30
<Typography className={classes.title}>
{truncateText(title, 61)}
</Typography>
2021-01-23 01:58:18 +03:30
</div>
</CardActionArea>
</Card>
</Link>
</Grid>
2020-12-25 17:42:22 +01:00
);
2021-01-22 21:11:00 +03:30
});
export default MangaCard;