import classNames from 'classnames'; import React, { useCallback, useMemo, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import TextTruncate from 'react-text-truncate'; import { REFRESH_SERIES, SERIES_SEARCH } from 'Commands/commandNames'; import IconButton from 'Components/Link/IconButton'; import Link from 'Components/Link/Link'; import SpinnerIconButton from 'Components/Link/SpinnerIconButton'; import SeriesTagList from 'Components/SeriesTagList'; import { icons } from 'Helpers/Props'; import DeleteSeriesModal from 'Series/Delete/DeleteSeriesModal'; import EditSeriesModal from 'Series/Edit/EditSeriesModal'; import SeriesIndexProgressBar from 'Series/Index/ProgressBar/SeriesIndexProgressBar'; import SeriesIndexPosterSelect from 'Series/Index/Select/SeriesIndexPosterSelect'; import { Statistics } from 'Series/Series'; import SeriesPoster from 'Series/SeriesPoster'; import { executeCommand } from 'Store/Actions/commandActions'; import dimensions from 'Styles/Variables/dimensions'; import fonts from 'Styles/Variables/fonts'; import translate from 'Utilities/String/translate'; import createSeriesIndexItemSelector from '../createSeriesIndexItemSelector'; import selectOverviewOptions from './selectOverviewOptions'; import SeriesIndexOverviewInfo from './SeriesIndexOverviewInfo'; import styles from './SeriesIndexOverview.css'; const columnPadding = parseInt(dimensions.seriesIndexColumnPadding); const columnPaddingSmallScreen = parseInt( dimensions.seriesIndexColumnPaddingSmallScreen ); const defaultFontSize = parseInt(fonts.defaultFontSize); const lineHeight = parseFloat(fonts.lineHeight); // Hardcoded height based on line-height of 32 + bottom margin of 10. // Less side-effecty than using react-measure. const TITLE_HEIGHT = 42; interface SeriesIndexOverviewProps { seriesId: number; sortKey: string; posterWidth: number; posterHeight: number; rowHeight: number; isSelectMode: boolean; isSmallScreen: boolean; } function SeriesIndexOverview(props: SeriesIndexOverviewProps) { const { seriesId, sortKey, posterWidth, posterHeight, rowHeight, isSelectMode, isSmallScreen, } = props; const { series, qualityProfile, isRefreshingSeries, isSearchingSeries } = useSelector(createSeriesIndexItemSelector(props.seriesId)); const overviewOptions = useSelector(selectOverviewOptions); const { title, monitored, status, path, titleSlug, nextAiring, previousAiring, added, overview, statistics = {} as Statistics, images, tags, network, } = series; const { seasonCount = 0, episodeCount = 0, episodeFileCount = 0, totalEpisodeCount = 0, sizeOnDisk = 0, } = statistics; const dispatch = useDispatch(); const [isEditSeriesModalOpen, setIsEditSeriesModalOpen] = useState(false); const [isDeleteSeriesModalOpen, setIsDeleteSeriesModalOpen] = useState(false); const onRefreshPress = useCallback(() => { dispatch( executeCommand({ name: REFRESH_SERIES, seriesId, }) ); }, [seriesId, dispatch]); const onSearchPress = useCallback(() => { dispatch( executeCommand({ name: SERIES_SEARCH, seriesId, }) ); }, [seriesId, dispatch]); const onEditSeriesPress = useCallback(() => { setIsEditSeriesModalOpen(true); }, [setIsEditSeriesModalOpen]); const onEditSeriesModalClose = useCallback(() => { setIsEditSeriesModalOpen(false); }, [setIsEditSeriesModalOpen]); const onDeleteSeriesPress = useCallback(() => { setIsEditSeriesModalOpen(false); setIsDeleteSeriesModalOpen(true); }, [setIsDeleteSeriesModalOpen]); const onDeleteSeriesModalClose = useCallback(() => { setIsDeleteSeriesModalOpen(false); }, [setIsDeleteSeriesModalOpen]); const link = `/series/${titleSlug}`; const elementStyle = { width: `${posterWidth}px`, height: `${posterHeight}px`, }; const contentHeight = useMemo(() => { const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding; return rowHeight - padding; }, [rowHeight, isSmallScreen]); const overviewHeight = contentHeight - TITLE_HEIGHT; return (