/* * 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/date.ts'; import { DownloadStateIndicator } from '@/components/molecules/DownloadStateIndicator.tsx'; import { DownloadType } from '@/lib/graphql/generated/graphql.ts'; import { TChapter } from '@/typings.ts'; import { ChapterActionMenuItems } from '@/components/chapter/ChapterActionMenuItems.tsx'; import { Menu } from '@/components/menu/Menu.tsx'; import { TypographyMaxLines } from '@/components/atoms/TypographyMaxLines.tsx'; interface IProps { chapter: TChapter; allChapters: TChapter[]; downloadChapter: DownloadType | undefined; showChapterNumber: boolean; onSelect: (selected: boolean, isShiftKey?: boolean) => void; selected: boolean | null; } export const ChapterCard: React.FC = (props: IProps) => { const { t } = useTranslation(); const theme = useTheme(); const menuButtonRef = useRef(null); const { chapter, allChapters, downloadChapter: dc, showChapterNumber, onSelect, selected } = 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')} ${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={!chapter.isDownloaded && !dc} /> )} )} )}
  • ); };