diff --git a/src/modules/updates/components/ChapterUpdateCard.tsx b/src/modules/updates/components/ChapterUpdateCard.tsx new file mode 100644 index 00000000..4ce5d830 --- /dev/null +++ b/src/modules/updates/components/ChapterUpdateCard.tsx @@ -0,0 +1,148 @@ +/* + * 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 DownloadIcon from '@mui/icons-material/Download'; +import Box from '@mui/material/Box'; +import CardActionArea from '@mui/material/CardActionArea'; +import Tooltip from '@mui/material/Tooltip'; +import Avatar from '@mui/material/Avatar'; +import Card from '@mui/material/Card'; +import CardContent from '@mui/material/CardContent'; +import IconButton from '@mui/material/IconButton'; +import { Link, useLocation } from 'react-router-dom'; +import Refresh from '@mui/icons-material/Refresh'; +import { useTranslation } from 'react-i18next'; +import { DownloadStateIndicator } from '@/modules/core/components/DownloadStateIndicator.tsx'; +import { ChapterUpdateListFieldsFragment, DownloadState } from '@/lib/graphql/generated/graphql.ts'; +import { Mangas } from '@/modules/manga/services/Mangas.ts'; +import { SpinnerImage } from '@/modules/core/components/SpinnerImage.tsx'; +import { TypographyMaxLines } from '@/modules/core/components/TypographyMaxLines.tsx'; +import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; +import { requestManager } from '@/lib/requests/RequestManager.ts'; +import { makeToast } from '@/modules/core/utils/Toast.ts'; +import { getErrorMessage } from '@/lib/HelperFunctions.ts'; +import { Chapters } from '@/modules/chapter/services/Chapters.ts'; + +export const ChapterUpdateCard = ({ chapter }: { chapter: ChapterUpdateListFieldsFragment }) => { + const { manga } = chapter; + const download = Chapters.getDownloadStatusFromCache(chapter.id); + + const { t } = useTranslation(); + const location = useLocation(); + + const handleRetry = async () => { + try { + await requestManager.addChapterToDownloadQueue(chapter.id).response; + } catch (e) { + makeToast(t('download.queue.error.label.failed_to_remove'), 'error', getErrorMessage(e)); + } + }; + + const downloadChapter = () => { + requestManager + .addChapterToDownloadQueue(chapter.id) + .response.catch((e) => + makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)), + ); + }; + + return ( + + theme.palette.text[chapter.isRead ? 'disabled' : 'primary'], + }} + > + + + + + + + + + + {manga.title} + + + {chapter.name} + + + + {download && } + {download?.state === DownloadState.Error && ( + + { + e.preventDefault(); + e.stopPropagation(); + handleRetry(); + }} + size="large" + > + + + + )} + {download == null && !chapter.isDownloaded && ( + + { + e.stopPropagation(); + e.preventDefault(); + downloadChapter(); + }} + size="large" + > + + + + )} + + + + ); +}; diff --git a/src/modules/updates/screens/Updates.tsx b/src/modules/updates/screens/Updates.tsx index f3954c51..da8a7afa 100644 --- a/src/modules/updates/screens/Updates.tsx +++ b/src/modules/updates/screens/Updates.tsx @@ -6,39 +6,23 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import DownloadIcon from '@mui/icons-material/Download'; -import Box from '@mui/material/Box'; -import CardActionArea from '@mui/material/CardActionArea'; -import Tooltip from '@mui/material/Tooltip'; -import Avatar from '@mui/material/Avatar'; -import Card from '@mui/material/Card'; -import CardContent from '@mui/material/CardContent'; -import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import React, { useCallback, useContext, useLayoutEffect, useMemo, useRef, useState } from 'react'; -import { Link, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import Refresh from '@mui/icons-material/Refresh'; import { requestManager } from '@/lib/requests/RequestManager.ts'; import { LoadingPlaceholder } from '@/modules/core/components/placeholder/LoadingPlaceholder.tsx'; import { EmptyViewAbsoluteCentered } from '@/modules/core/components/placeholder/EmptyViewAbsoluteCentered.tsx'; -import { DownloadStateIndicator } from '@/modules/core/components/DownloadStateIndicator.tsx'; -import { ChapterType, DownloadState } from '@/lib/graphql/generated/graphql.ts'; +import { ChapterType } from '@/lib/graphql/generated/graphql.ts'; import { NavBarContext } from '@/modules/navigation-bar/contexts/NavbarContext.tsx'; import { UpdateChecker } from '@/modules/core/components/UpdateChecker.tsx'; import { StyledGroupedVirtuoso } from '@/modules/core/components/virtuoso/StyledGroupedVirtuoso.tsx'; import { StyledGroupHeader } from '@/modules/core/components/virtuoso/StyledGroupHeader.tsx'; import { StyledGroupItemWrapper } from '@/modules/core/components/virtuoso/StyledGroupItemWrapper.tsx'; -import { Mangas } from '@/modules/manga/services/Mangas.ts'; -import { SpinnerImage } from '@/modules/core/components/SpinnerImage.tsx'; import { dateTimeFormatter, epochToDate, getDateString } from '@/util/DateHelper.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; -import { TypographyMaxLines } from '@/modules/core/components/TypographyMaxLines.tsx'; -import { ChapterIdInfo, Chapters } from '@/modules/chapter/services/Chapters.ts'; -import { makeToast } from '@/modules/core/utils/Toast.ts'; import { VirtuosoUtil } from '@/lib/virtuoso/Virtuoso.util.tsx'; -import { AppRoutes } from '@/modules/core/AppRoute.constants.ts'; import { getErrorMessage } from '@/lib/HelperFunctions.ts'; +import { ChapterUpdateCard } from '@/modules/updates/components/ChapterUpdateCard.tsx'; const groupByDate = (updates: Pick[]): [date: string, items: number][] => { if (!updates.length) { @@ -56,7 +40,6 @@ const groupByDate = (updates: Pick[]): [date: string, export const Updates: React.FC = () => { const { t } = useTranslation(); - const location = useLocation(); const { setTitle, setAction } = useContext(NavBarContext); const { @@ -107,22 +90,6 @@ export const Updates: React.FC = () => { }; }, [t, lastUpdateTimestamp]); - const handleRetry = async (chapter: ChapterIdInfo) => { - try { - await requestManager.addChapterToDownloadQueue(chapter.id).response; - } catch (e) { - makeToast(t('download.queue.error.label.failed_to_remove'), 'error', getErrorMessage(e)); - } - }; - - const downloadChapter = (chapter: ChapterIdInfo) => { - requestManager - .addChapterToDownloadQueue(chapter.id) - .response.catch((e) => - makeToast(t('global.error.label.failed_to_save_changes'), 'error', getErrorMessage(e)), - ); - }; - const loadMore = useCallback(() => { if (!hasNextPage) { return; @@ -178,111 +145,11 @@ export const Updates: React.FC = () => { )} computeItemKey={computeItemKey} - itemContent={(index) => { - const chapter = updateEntries[index]; - const { manga } = chapter; - const download = Chapters.getDownloadStatusFromCache(chapter.id); - - return ( - - - theme.palette.text[chapter.isRead ? 'disabled' : 'primary'], - }} - > - - - - - - - - - - {manga.title} - - - {chapter.name} - - - - {download && } - {download?.state === DownloadState.Error && ( - - { - e.preventDefault(); - e.stopPropagation(); - handleRetry(download.chapter); - }} - size="large" - > - - - - )} - {download == null && !chapter.isDownloaded && ( - - { - e.stopPropagation(); - e.preventDefault(); - downloadChapter(chapter); - }} - size="large" - > - - - - )} - - - - - ); - }} + itemContent={(index) => ( + + + + )} /> );