/* * 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 BookmarkIcon from '@mui/icons-material/Bookmark'; import MoreVertIcon from '@mui/icons-material/MoreVert'; import CardActionArea from '@mui/material/CardActionArea'; import Checkbox from '@mui/material/Checkbox'; import Stack from '@mui/material/Stack'; import Tooltip from '@mui/material/Tooltip'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import IconButton from '@mui/material/IconButton'; import { useTheme } from '@mui/material/styles'; import Typography from '@mui/material/Typography'; import React, { MouseEvent, TouchEvent, useRef } from 'react'; import { Link } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import PopupState, { bindMenu, bindTrigger } from 'material-ui-popup-state'; import { useLongPress } from 'use-long-press'; import { getDateString } from '@/util/DateHelper.ts'; import { DownloadStateIndicator } from '@/modules/core/components/DownloadStateIndicator.tsx'; import { ChapterType } from '@/lib/graphql/generated/graphql.ts'; import { ChapterActionMenuItems } from '@/modules/chapter/components/actions/ChapterActionMenuItems.tsx'; import { Menu } from '@/modules/core/components/menu/Menu.tsx'; import { TypographyMaxLines } from '@/modules/core/components/TypographyMaxLines.tsx'; import { ChapterBookmarkInfo, ChapterDownloadInfo, ChapterDownloadStatus, ChapterIdInfo, ChapterMangaInfo, ChapterNumberInfo, ChapterReadInfo, ChapterScanlatorInfo, } from '@/modules/chapter/services/Chapters.ts'; import { ChaptersWithMeta } from '@/modules/chapter/services/ChaptersWithMeta.ts'; type TChapter = ChapterIdInfo & ChapterMangaInfo & ChapterDownloadInfo & ChapterReadInfo & ChapterBookmarkInfo & ChapterNumberInfo & ChapterScanlatorInfo & Pick; interface IProps { mode?: 'manga.page' | 'reader'; chapter: TChapter; allChapters: TChapter[]; downloadChapter: ChapterDownloadStatus | undefined; showChapterNumber: boolean; onSelect: (selected: boolean, isShiftKey?: boolean) => void; selected: boolean | null; selectable?: boolean; isActiveChapter?: boolean; // reader } export const ChapterCard: React.FC = (props: IProps) => { const { t } = useTranslation(); const theme = useTheme(); const menuButtonRef = useRef(null); const { mode = 'manga.page', chapter, allChapters, downloadChapter: dc, showChapterNumber, onSelect, selected, selectable = true, isActiveChapter = false, } = props; const isSelecting = selected !== null; const { isDownloaded } = chapter; const handleClick = (event: MouseEvent | TouchEvent) => { if (!isSelecting) return; event.preventDefault(); event.stopPropagation(); onSelect(!selected, event.shiftKey); }; const handleClickOpenMenu = ( event: React.MouseEvent | React.TouchEvent, openMenu: (e: React.SyntheticEvent) => void, ) => { event.stopPropagation(); event.preventDefault(); openMenu(event); }; const longPressBind = useLongPress((event, { context: openMenu }) => { if (!isSelecting && !!menuButtonRef.current) { handleClickOpenMenu(event, () => (openMenu as (event: Element) => void)?.(menuButtonRef.current!)); return; } // eslint-disable-next-line no-param-reassign event.shiftKey = true; handleClick(event); }); return ( {(popupState) => ( handleClick(e)} {...longPressBind(popupState.open)} > {chapter.isBookmarked && ( )} {showChapterNumber ? `${t('chapter.title_one')} ${chapter.chapterNumber}` : chapter.name} {chapter.scanlator} {getDateString(Number(chapter.uploadDate ?? 0), true)} {isDownloaded && ` • ${t('chapter.status.label.downloaded')}`} {dc && } {selected === null ? ( handleClickOpenMenu(e, popupState.open)} onTouchStart={(e) => handleClickOpenMenu(e, popupState.open)} aria-label="more" size="large" > ) : ( )} {!isSelecting && popupState.isOpen && ( {(onClose) => ( onSelect(true)} canBeDownloaded={ChaptersWithMeta.isDownloadable({ chapter, downloadChapter: dc, })} selectable={selectable} /> )} )} )} ); };