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

129 lines
3.9 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 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-10-30 16:10:34 +03:30
import SpinnerImage from 'components/util/SpinnerImage';
2021-10-31 21:02:45 +03:30
import { styled } from '@mui/system';
2020-12-25 17:42:22 +01:00
2021-10-31 21:02:45 +03:30
const BottomGradient = styled('div')({
position: 'absolute',
bottom: 0,
width: '100%',
height: '30%',
background: 'linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 100%)',
});
const BottomGradientDoubledDown = styled('div')({
position: 'absolute',
bottom: 0,
width: '100%',
height: '20%',
background: 'linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 100%)',
});
2021-05-28 19:37:26 +04:30
2021-10-31 21:02:45 +03:30
const MangaTitle = styled(Typography)({
position: 'absolute',
bottom: 0,
padding: '0.5em',
color: 'white',
fontSize: '1.05rem',
textShadow: '0px 0px 3px #000000',
});
const UnreadBadge = styled(Typography)(({ theme }) => ({
position: 'absolute',
top: 2,
left: 2,
backgroundColor: theme.palette.primary.dark,
borderRadius: '5px',
color: 'white',
padding: '0.1em',
paddingInline: '0.3em',
fontSize: '1.05rem',
}));
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;
2021-10-31 21:02:45 +03:30
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}/`}>
2021-10-31 21:02:45 +03:30
<Card
sx={{
// force standard aspect ratio of manga covers
aspectRatio: '225/350',
display: 'flex',
}}
ref={ref}
>
<CardActionArea
sx={{
position: 'relative',
height: '100%',
}}
>
{unread! > 0
&& (
<UnreadBadge>
{unread}
</UnreadBadge>
) }
<SpinnerImage
alt={title}
src={`${serverAddress}${thumbnailUrl}?useCache=${useCache}`}
imgStyle={{
height: '100%',
width: '100%',
}}
spinnerStyle={{
minHeight: '400px',
display: 'grid',
placeItems: 'center',
}}
/>
<BottomGradient />
<BottomGradientDoubledDown />
<MangaTitle>
{truncateText(title, 61)}
</MangaTitle>
2021-01-23 01:58:18 +03:30
</CardActionArea>
</Card>
</Link>
</Grid>
2020-12-25 17:42:22 +01:00
);
2021-01-22 21:11:00 +03:30
});
export default MangaCard;