forked from Suwayomi/Suwayomi-WebUI
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMangaCard.tsx
122 lines (114 loc) · 3.7 KB
/
MangaCard.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
* Copyright (C) Contributors to the Suwayomi project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* 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 React from 'react';
import makeStyles from '@mui/styles/makeStyles';
import Card from '@mui/material/Card';
import CardActionArea from '@mui/material/CardActionArea';
import Typography from '@mui/material/Typography';
import { Link } from 'react-router-dom';
import { Grid } from '@mui/material';
import useLocalStorage from 'util/useLocalStorage';
import SpinnerImage from 'components/SpinnerImage';
const useStyles = makeStyles((theme) => ({
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',
fontSize: '1.05rem',
textShadow: '0px 0px 3px #000000',
},
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',
},
image: {
height: '100%',
width: '100%',
},
spinner: {
minHeight: '400px',
display: 'grid',
placeItems: 'center',
},
}));
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;
};
interface IProps {
manga: IMangaCard
}
const MangaCard = React.forwardRef<HTMLDivElement, IProps>((props: IProps, ref) => {
const {
manga: {
id, title, thumbnailUrl, unreadCount: unread,
},
} = props;
const classes = useStyles();
const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
const [useCache] = useLocalStorage<boolean>('useCache', true);
return (
<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}
<SpinnerImage
alt={title}
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
spinnerClassName={classes.spinner}
imgClassName={classes.image}
/>
<div className={classes.gradient} />
<Typography className={classes.title}>
{truncateText(title, 61)}
</Typography>
</div>
</CardActionArea>
</Card>
</Link>
</Grid>
);
});
export default MangaCard;