import { usePayload } from "@/modules/redux/hooks/modal"; import { createAndDispatchTask } from "@/modules/task/utilities"; import { GetItemId, isMovie } from "@/utilities"; import { faCaretDown, faCheck, faDownload, faInfoCircle, faTimes, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import clsx from "clsx"; import { FunctionComponent, useCallback, useEffect, useMemo, useState, } from "react"; import { Badge, Button, Col, Collapse, Container, OverlayTrigger, Popover, Row, } from "react-bootstrap"; import { UseQueryResult } from "react-query"; 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; query: ( id?: number ) => UseQueryResult; } export function ManualSearchModal( props: Props & BaseModalProps ) { const { download, query: useSearch, ...modal } = props; const item = usePayload(modal.modalKey); const itemId = useMemo(() => GetItemId(item ?? {}), [item]); const [id, setId] = useState(undefined); // Cleanup the ID when user switches episode / movie useEffect(() => { if (itemId !== undefined && itemId !== id) { setId(undefined); } }, [id, itemId]); const results = useSearch(id); const isStale = results.data === undefined; const search = useCallback(() => { if (itemId !== undefined) { setId(itemId); results.refetch(); } }, [itemId, results]); 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; } return (
1 } )} onClick={() => 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 (results.isFetching) { return ; } else if (isStale) { return (

{item?.path ?? ""}

); } 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 ( ); };