import { useEpisodesProvider, useMoviesProvider } from "@/apis/hooks"; import { usePayload } from "@/modules/redux/hooks/modal"; import { createAndDispatchTask } from "@/modules/task/utilities"; import { isMovie } from "@/utilities"; import { faCaretDown, faCheck, faDownload, faInfoCircle, faTimes, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FunctionComponent, useCallback, useMemo, useState } from "react"; import { Badge, Button, Col, Collapse, Container, OverlayTrigger, Popover, Row, } from "react-bootstrap"; import { Column } from "react-table"; import { BaseModal, BaseModalProps, LoadingIndicator, PageTable } from ".."; import Language from "../bazarr/Language"; type SupportType = Item.Movie | Item.Episode; interface Props { download: (item: T, result: SearchResultType) => Promise; } export function ManualSearchModal( props: Props & BaseModalProps ) { const { download, ...modal } = props; const item = usePayload(modal.modalKey); const [episodeId, setEpisodeId] = useState(undefined); const [radarrId, setRadarrId] = useState(undefined); const episodes = useEpisodesProvider(episodeId); const movies = useMoviesProvider(radarrId); const isInitial = episodeId === undefined && radarrId === undefined; const isFetching = episodes.isFetching || movies.isFetching; const results = useMemo( () => [...(episodes.data ?? []), ...(movies.data ?? [])], [episodes.data, movies.data] ); const search = useCallback(() => { setEpisodeId(undefined); setRadarrId(undefined); if (item) { if (isMovie(item)) { setRadarrId(item.radarrId); movies.refetch(); } else { setEpisodeId(item.sonarrEpisodeId); episodes.refetch(); } } }, [episodes, item, movies]); const columns = useMemo[]>( () => [ { Header: "Score", accessor: (d) => `${d.score}%`, }, { accessor: "language", Cell: ({ row: { original }, value }) => { const lang: Language.Info = { code2: value, hi: original.hearing_impaired === "True", forced: original.forced === "True", name: "", }; return ( ); }, }, { Header: "Provider", accessor: "provider", Cell: (row) => { const value = row.value; const { url } = row.row.original; if (url) { return ( {value} ); } else { return value; } }, }, { Header: "Release", accessor: "release_info", className: "text-nowrap", Cell: (row) => { const value = row.value; const [open, setOpen] = useState(false); const items = useMemo( () => value.slice(1).map((v, idx) => ( {v} )), [value] ); if (value.length === 0) { return Cannot get release info; } const cls = [ "release-container", "d-flex", "justify-content-between", "align-items-center", ]; if (value.length > 1) { cls.push("release-multi"); } return (
setOpen((o) => !o)}>
{value[0]}
{items}
{value.length > 1 && ( )}
); }, }, { Header: "Upload", accessor: (d) => d.uploader ?? "-", }, { accessor: "matches", Cell: (row) => { const { matches, dont_matches } = row.row.original; return ; }, }, { accessor: "subtitle", Cell: ({ row }) => { const result = row.original; return ( ); }, }, ], [download, item] ); const content = () => { if (isInitial) { return (

{item?.path ?? ""}

); } else if (isFetching) { return ; } else { return ( <>

{item?.path ?? ""}

); } }; const footer = ( ); const title = useMemo(() => { let title = "Unknown"; if (item) { if (item.sceneName) { title = item.sceneName; } else if (isMovie(item)) { title = item.title; } else { title = item.title; } } return `Search - ${title}`; }, [item]); return ( {content()} ); } const StateIcon: FunctionComponent<{ matches: string[]; dont: string[] }> = ({ matches, dont, }) => { let icon = faCheck; let color = "var(--success)"; if (dont.length > 0) { icon = faInfoCircle; color = "var(--warning)"; } const matchElements = useMemo( () => matches.map((v, idx) => (

{v}

)), [matches] ); const dontElements = useMemo( () => dont.map((v, idx) => (

{v}

)), [dont] ); const popover = useMemo( () => ( {matchElements} {dontElements} ), [matchElements, dontElements] ); return ( ); };