Skip to content

Commit

Permalink
Add continue read button to library (#505)
Browse files Browse the repository at this point in the history
  • Loading branch information
schroda authored Dec 19, 2023
1 parent 663e20f commit 2f8c284
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 48 deletions.
126 changes: 83 additions & 43 deletions src/components/MangaCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ 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 { Avatar, Box, CardContent, styled, Tooltip } from '@mui/material';
import { Avatar, Box, CardContent, Stack, styled, Tooltip } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { requestManager } from '@/lib/requests/RequestManager.ts';
import { GridLayout, useLibraryOptionsContext } from '@/components/context/LibraryOptionsContext';
import { SpinnerImage } from '@/components/util/SpinnerImage';
import { TPartialManga } from '@/typings.ts';
import { ContinueReadingButton } from '@/components/manga/ContinueReadingButton.tsx';

const BottomGradient = styled('div')({
position: 'absolute',
Expand Down Expand Up @@ -44,11 +45,6 @@ const MangaTitle = styled(Typography)({
});

const GridMangaTitle = styled(MangaTitle)({
width: '100%',
position: 'absolute',
bottom: 0,
margin: '0.5em 0',
padding: '0 0.5em',
fontSize: '1.05rem',
});

Expand All @@ -75,17 +71,29 @@ export const MangaCard = (props: IProps) => {
const { t } = useTranslation();

const {
manga: { id, title, thumbnailUrl: tmpThumbnailUrl, downloadCount, unreadCount: unread, inLibrary },
manga: {
id,
title,
thumbnailUrl: tmpThumbnailUrl,
downloadCount,
unreadCount: unread,
inLibrary,
lastReadChapter,
chapters,
},
gridLayout,
inLibraryIndicator,
} = props;
const thumbnailUrl = tmpThumbnailUrl ?? 'nonExistingMangaUrl';
const {
options: { showUnreadBadge, showDownloadBadge },
options: { showContinueReadingButton, showUnreadBadge, showDownloadBadge },
} = useLibraryOptionsContext();

const mangaLinkTo = `/manga/${id}/`;

const nextChapterIndexToRead = (lastReadChapter?.sourceOrder ?? 0) + 1;
const isLatestChapterRead = chapters?.totalCount === lastReadChapter?.sourceOrder;

if (gridLayout !== GridLayout.List) {
return (
<Link to={mangaLinkTo} style={gridLayout === GridLayout.Comfortable ? { textDecoration: 'none' } : {}}>
Expand Down Expand Up @@ -155,29 +163,53 @@ export const MangaCard = (props: IProps) => {
placeItems: 'center',
}}
/>
{gridLayout !== GridLayout.Comfortable && (
<>
<BottomGradient />
<BottomGradientDoubledDown />
<Tooltip title={title} placement="top">
<GridMangaTitle
sx={{
color: 'white',
textShadow: '0px 0px 3px #000000',
}}
>
{title}
</GridMangaTitle>
</Tooltip>
</>
)}
<>
<BottomGradient />
<BottomGradientDoubledDown />
<Stack
direction="row"
justifyContent={gridLayout !== GridLayout.Comfortable ? 'space-between' : 'end'}
alignItems="end"
sx={{
position: 'absolute',
bottom: 0,
width: '100%',
margin: '0.5em 0',
padding: '0 0.5em',
gap: '0.5em',
}}
>
{gridLayout !== GridLayout.Comfortable && (
<Tooltip title={title} placement="top">
<GridMangaTitle
sx={{
color: 'white',
textShadow: '0px 0px 3px #000000',
}}
>
{title}
</GridMangaTitle>
</Tooltip>
)}
<ContinueReadingButton
showContinueReadingButton={showContinueReadingButton}
isLatestChapterRead={isLatestChapterRead}
nextChapterIndexToRead={nextChapterIndexToRead}
mangaLinkTo={mangaLinkTo}
/>
</Stack>
</>
</CardActionArea>
</Card>
{gridLayout === GridLayout.Comfortable && (
<Tooltip title={title} placement="top">
<GridMangaTitle
sx={{
position: 'relative',
width: '100%',
bottom: 0,
margin: '0.5em 0',
padding: '0 0.5em',
color: 'text.primary',
height: '3rem',
}}
Expand Down Expand Up @@ -237,25 +269,33 @@ export const MangaCard = (props: IProps) => {
<MangaTitle variant="h5">{title}</MangaTitle>
</Tooltip>
</Box>
<BadgeContainer>
{inLibraryIndicator && inLibrary && (
<Typography sx={{ backgroundColor: 'primary.dark' }}>
{t('manga.button.in_library')}
</Typography>
)}
{showUnreadBadge && unread! > 0 && (
<Typography sx={{ backgroundColor: 'primary.dark' }}>{unread}</Typography>
)}
{showDownloadBadge && downloadCount! > 0 && (
<Typography
sx={{
backgroundColor: 'success.dark',
}}
>
{downloadCount}
</Typography>
)}
</BadgeContainer>
<Stack direction="row" alignItems="center" gap="5px">
<BadgeContainer>
{inLibraryIndicator && inLibrary && (
<Typography sx={{ backgroundColor: 'primary.dark' }}>
{t('manga.button.in_library')}
</Typography>
)}
{showUnreadBadge && unread! > 0 && (
<Typography sx={{ backgroundColor: 'primary.dark' }}>{unread}</Typography>
)}
{showDownloadBadge && downloadCount! > 0 && (
<Typography
sx={{
backgroundColor: 'success.dark',
}}
>
{downloadCount}
</Typography>
)}
</BadgeContainer>
<ContinueReadingButton
showContinueReadingButton={showContinueReadingButton}
isLatestChapterRead={isLatestChapterRead}
nextChapterIndexToRead={nextChapterIndexToRead}
mangaLinkTo={mangaLinkTo}
/>
</Stack>
</CardContent>
</CardActionArea>
</Card>
Expand Down
1 change: 1 addition & 0 deletions src/components/context/LibraryOptionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum GridLayout {
}

export const DefaultLibraryOptions: LibraryOptions = {
showContinueReadingButton: false,
showDownloadBadge: false,
showUnreadBadge: false,
gridLayout: GridLayout.Compact,
Expand Down
16 changes: 13 additions & 3 deletions src/components/library/LibraryOptionsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
));
}
if (key === 'display') {
const { gridLayout, showDownloadBadge, showUnreadBadge, showTabSize } = options;
const { gridLayout, showContinueReadingButton, showDownloadBadge, showUnreadBadge, showTabSize } =
options;
return (
<>
<FormLabel>{t('global.grid_layout.title')}</FormLabel>
Expand Down Expand Up @@ -110,12 +111,12 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
<FormLabel sx={{ mt: 2 }}>{t('library.option.display.badge.title')}</FormLabel>
<CheckboxInput
label={t('library.option.display.badge.label.unread_badges')}
checked={showUnreadBadge === true}
checked={showUnreadBadge}
onChange={() => handleFilterChange('showUnreadBadge', !showUnreadBadge)}
/>
<CheckboxInput
label={t('library.option.display.badge.label.download_badges')}
checked={showDownloadBadge === true}
checked={showDownloadBadge}
onChange={() => handleFilterChange('showDownloadBadge', !showDownloadBadge)}
/>

Expand All @@ -125,6 +126,15 @@ export const LibraryOptionsPanel: React.FC<IProps> = ({ open, onClose }) => {
checked={showTabSize}
onChange={() => handleFilterChange('showTabSize', !showTabSize)}
/>

<FormLabel sx={{ mt: 2 }}>{t('global.label.other')}</FormLabel>
<CheckboxInput
label={t('library.option.display.other.label.show_continue_reading_button')}
checked={showContinueReadingButton}
onChange={() =>
handleFilterChange('showContinueReadingButton', !showContinueReadingButton)
}
/>
</>
);
}
Expand Down
46 changes: 46 additions & 0 deletions src/components/manga/ContinueReadingButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 { useTranslation } from 'react-i18next';
import { Button, Tooltip } from '@mui/material';
import PlayArrowIcon from '@mui/icons-material/PlayArrow';

export const ContinueReadingButton = ({
showContinueReadingButton,
isLatestChapterRead,
nextChapterIndexToRead,
mangaLinkTo,
}: {
showContinueReadingButton: boolean;
isLatestChapterRead: boolean;
nextChapterIndexToRead: number;
mangaLinkTo: string;
}) => {
const { t } = useTranslation();

const isFirstChapter = nextChapterIndexToRead === 1;

if (!showContinueReadingButton || isLatestChapterRead) {
return null;
}

return (
<Tooltip title={t(isFirstChapter ? 'global.button.start' : 'global.button.resume')}>
<Button
variant="contained"
size="small"
sx={{ minWidth: 'unset' }}
href={`${mangaLinkTo}chapter/${nextChapterIndexToRead}`}
onClick={(e) => e.stopPropagation()}
onMouseDown={(e) => e.stopPropagation()}
>
<PlayArrowIcon />
</Button>
</Tooltip>
);
};
10 changes: 8 additions & 2 deletions src/i18n/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@
"queue": {
"error": {
"label": {
"failed_to_remove": "Could not remove the download from the queue.",
"failed_delete_all": "Could not remove all downloads from the queue"
"failed_delete_all": "Could not remove all downloads from the queue",
"failed_to_remove": "Could not remove the download from the queue."
}
},
"label": {
Expand Down Expand Up @@ -319,6 +319,7 @@
"loading": "Loading…",
"never": "Never",
"none": "None",
"other": "Other",
"password": "Password",
"sort": "Sort",
"unknown": "Unknown",
Expand Down Expand Up @@ -379,6 +380,11 @@
},
"title": "Badges"
},
"other": {
"label": {
"show_continue_reading_button": "Show continue reading button"
}
},
"tab": {
"label": {
"show_number_of_items": "Show number of items"
Expand Down
1 change: 1 addition & 0 deletions src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ enum GridLayout {

export interface LibraryOptions {
// display options
showContinueReadingButton: boolean;
showDownloadBadge: boolean;
showUnreadBadge: boolean;
gridLayout: GridLayout;
Expand Down

0 comments on commit 2f8c284

Please sign in to comment.