import React, { useCallback, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import ProtocolLabel from 'Activity/Queue/ProtocolLabel'; import { Error } from 'App/State/AppSectionState'; import IconButton from 'Components/Link/IconButton'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import ProgressBar from 'Components/ProgressBar'; import RelativeDateCell from 'Components/Table/Cells/RelativeDateCell'; import TableRowCell from 'Components/Table/Cells/TableRowCell'; import TableSelectCell from 'Components/Table/Cells/TableSelectCell'; import Column from 'Components/Table/Column'; import TableRow from 'Components/Table/TableRow'; import Tooltip from 'Components/Tooltip/Tooltip'; import DownloadProtocol from 'DownloadClient/DownloadProtocol'; import { icons, kinds, tooltipPositions } from 'Helpers/Props'; import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal'; import Language from 'Language/Language'; import MovieFormats from 'Movie/MovieFormats'; import MovieLanguages from 'Movie/MovieLanguages'; import MovieQuality from 'Movie/MovieQuality'; import MovieTitleLink from 'Movie/MovieTitleLink'; import useMovie from 'Movie/useMovie'; import { QualityModel } from 'Quality/Quality'; import { grabQueueItem, removeQueueItem } from 'Store/Actions/queueActions'; import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector'; import CustomFormat from 'typings/CustomFormat'; import { SelectStateInputProps } from 'typings/props'; import { QueueTrackedDownloadState, QueueTrackedDownloadStatus, StatusMessage, } from 'typings/Queue'; import formatBytes from 'Utilities/Number/formatBytes'; import formatCustomFormatScore from 'Utilities/Number/formatCustomFormatScore'; import translate from 'Utilities/String/translate'; import QueueStatusCell from './QueueStatusCell'; import RemoveQueueItemModal, { RemovePressProps } from './RemoveQueueItemModal'; import TimeleftCell from './TimeleftCell'; import styles from './QueueRow.css'; interface QueueRowProps { id: number; movieId?: number; downloadId?: string; title: string; status: string; trackedDownloadStatus?: QueueTrackedDownloadStatus; trackedDownloadState?: QueueTrackedDownloadState; statusMessages?: StatusMessage[]; errorMessage?: string; languages: Language[]; quality: QualityModel; customFormats?: CustomFormat[]; customFormatScore: number; protocol: DownloadProtocol; indexer?: string; outputPath?: string; downloadClient?: string; downloadClientHasPostImportCategory?: boolean; estimatedCompletionTime?: string; added?: string; timeleft?: string; size: number; sizeleft: number; isGrabbing?: boolean; grabError?: Error; isRemoving?: boolean; isSelected?: boolean; columns: Column[]; onSelectedChange: (options: SelectStateInputProps) => void; onQueueRowModalOpenOrClose: (isOpen: boolean) => void; } function QueueRow(props: QueueRowProps) { const { id, movieId, downloadId, title, status, trackedDownloadStatus, trackedDownloadState, statusMessages, errorMessage, languages, quality, customFormats = [], customFormatScore, protocol, indexer, outputPath, downloadClient, downloadClientHasPostImportCategory, estimatedCompletionTime, added, timeleft, size, sizeleft, isGrabbing = false, grabError, isRemoving = false, isSelected, columns, onSelectedChange, onQueueRowModalOpenOrClose, } = props; const dispatch = useDispatch(); const movie = useMovie(movieId); const { showRelativeDates, shortDateFormat, timeFormat } = useSelector( createUISettingsSelector() ); const [isRemoveQueueItemModalOpen, setIsRemoveQueueItemModalOpen] = useState(false); const [isInteractiveImportModalOpen, setIsInteractiveImportModalOpen] = useState(false); const handleGrabPress = useCallback(() => { dispatch(grabQueueItem({ id })); }, [id, dispatch]); const handleInteractiveImportPress = useCallback(() => { onQueueRowModalOpenOrClose(true); setIsInteractiveImportModalOpen(true); }, [setIsInteractiveImportModalOpen, onQueueRowModalOpenOrClose]); const handleInteractiveImportModalClose = useCallback(() => { onQueueRowModalOpenOrClose(false); setIsInteractiveImportModalOpen(false); }, [setIsInteractiveImportModalOpen, onQueueRowModalOpenOrClose]); const handleRemoveQueueItemPress = useCallback(() => { onQueueRowModalOpenOrClose(true); setIsRemoveQueueItemModalOpen(true); }, [setIsRemoveQueueItemModalOpen, onQueueRowModalOpenOrClose]); const handleRemoveQueueItemModalConfirmed = useCallback( (payload: RemovePressProps) => { onQueueRowModalOpenOrClose(false); dispatch(removeQueueItem({ id, ...payload })); setIsRemoveQueueItemModalOpen(false); }, [id, setIsRemoveQueueItemModalOpen, onQueueRowModalOpenOrClose, dispatch] ); const handleRemoveQueueItemModalClose = useCallback(() => { onQueueRowModalOpenOrClose(false); setIsRemoveQueueItemModalOpen(false); }, [setIsRemoveQueueItemModalOpen, onQueueRowModalOpenOrClose]); const progress = size ? 100 - (sizeleft / size) * 100 : 0; const showInteractiveImport = status === 'completed' && trackedDownloadStatus === 'warning'; const isPending = status === 'delay' || status === 'downloadClientUnavailable'; return ( {columns.map((column) => { const { name, isVisible } = column; if (!isVisible) { return null; } if (name === 'status') { return ( ); } if (name === 'movies.sortTitle') { return ( {movie ? ( ) : ( title )} ); } if (name === 'year') { return ( {movie ? movie.year : ''} ); } if (name === 'languages') { return ( ); } if (name === 'quality') { return ( {quality ? : null} ); } if (name === 'customFormats') { return ( ); } if (name === 'customFormatScore') { return ( } position={tooltipPositions.BOTTOM} /> ); } if (name === 'protocol') { return ( ); } if (name === 'indexer') { return {indexer}; } if (name === 'downloadClient') { return {downloadClient}; } if (name === 'title') { return {title}; } if (name === 'size') { return {formatBytes(size)}; } if (name === 'outputPath') { return {outputPath}; } if (name === 'estimatedCompletionTime') { return ( ); } if (name === 'progress') { return ( {!!progress && ( )} ); } if (name === 'added') { return ; } if (name === 'actions') { return ( {showInteractiveImport ? ( ) : null} {isPending ? ( ) : null} ); } return null; })} ); } export default QueueRow;