diff --git a/src/components/MangaCard.tsx b/src/components/MangaCard.tsx index be6b7ad3..c0c15964 100644 --- a/src/components/MangaCard.tsx +++ b/src/components/MangaCard.tsx @@ -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', @@ -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', }); @@ -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 ( @@ -155,22 +163,42 @@ export const MangaCard = (props: IProps) => { placeItems: 'center', }} /> - {gridLayout !== GridLayout.Comfortable && ( - <> - - - - - {title} - - - - )} + <> + + + + {gridLayout !== GridLayout.Comfortable && ( + + + {title} + + + )} + + + {gridLayout === GridLayout.Comfortable && ( @@ -178,6 +206,10 @@ export const MangaCard = (props: IProps) => { { {title} - - {inLibraryIndicator && inLibrary && ( - - {t('manga.button.in_library')} - - )} - {showUnreadBadge && unread! > 0 && ( - {unread} - )} - {showDownloadBadge && downloadCount! > 0 && ( - - {downloadCount} - - )} - + + + {inLibraryIndicator && inLibrary && ( + + {t('manga.button.in_library')} + + )} + {showUnreadBadge && unread! > 0 && ( + {unread} + )} + {showDownloadBadge && downloadCount! > 0 && ( + + {downloadCount} + + )} + + + diff --git a/src/components/context/LibraryOptionsContext.tsx b/src/components/context/LibraryOptionsContext.tsx index 183853be..db2a2108 100644 --- a/src/components/context/LibraryOptionsContext.tsx +++ b/src/components/context/LibraryOptionsContext.tsx @@ -21,6 +21,7 @@ export enum GridLayout { } export const DefaultLibraryOptions: LibraryOptions = { + showContinueReadingButton: false, showDownloadBadge: false, showUnreadBadge: false, gridLayout: GridLayout.Compact, diff --git a/src/components/library/LibraryOptionsPanel.tsx b/src/components/library/LibraryOptionsPanel.tsx index 9de1fd9d..d89f2145 100644 --- a/src/components/library/LibraryOptionsPanel.tsx +++ b/src/components/library/LibraryOptionsPanel.tsx @@ -82,7 +82,8 @@ export const LibraryOptionsPanel: React.FC = ({ open, onClose }) => { )); } if (key === 'display') { - const { gridLayout, showDownloadBadge, showUnreadBadge, showTabSize } = options; + const { gridLayout, showContinueReadingButton, showDownloadBadge, showUnreadBadge, showTabSize } = + options; return ( <> {t('global.grid_layout.title')} @@ -110,12 +111,12 @@ export const LibraryOptionsPanel: React.FC = ({ open, onClose }) => { {t('library.option.display.badge.title')} handleFilterChange('showUnreadBadge', !showUnreadBadge)} /> handleFilterChange('showDownloadBadge', !showDownloadBadge)} /> @@ -125,6 +126,15 @@ export const LibraryOptionsPanel: React.FC = ({ open, onClose }) => { checked={showTabSize} onChange={() => handleFilterChange('showTabSize', !showTabSize)} /> + + {t('global.label.other')} + + handleFilterChange('showContinueReadingButton', !showContinueReadingButton) + } + /> ); } diff --git a/src/components/manga/ContinueReadingButton.tsx b/src/components/manga/ContinueReadingButton.tsx new file mode 100644 index 00000000..ff831dd2 --- /dev/null +++ b/src/components/manga/ContinueReadingButton.tsx @@ -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 ( + + + + ); +}; diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 1d7ccb47..956d8a39 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -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": { @@ -319,6 +319,7 @@ "loading": "Loading…", "never": "Never", "none": "None", + "other": "Other", "password": "Password", "sort": "Sort", "unknown": "Unknown", @@ -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" diff --git a/src/typings.ts b/src/typings.ts index 4aab13c8..5a76c7e2 100644 --- a/src/typings.ts +++ b/src/typings.ts @@ -340,6 +340,7 @@ enum GridLayout { export interface LibraryOptions { // display options + showContinueReadingButton: boolean; showDownloadBadge: boolean; showUnreadBadge: boolean; gridLayout: GridLayout;