import React, { Fragment, useRef, useState } from "react"; import { useMutation } from "react-query"; import { Dialog, Transition } from "@headlessui/react"; import { XMarkIcon } from "@heroicons/react/24/solid"; import { classNames, sleep } from "../../utils"; import { Form, Formik, useFormikContext } from "formik"; import DEBUG from "../../components/debug"; import { queryClient } from "../../App"; import { APIClient } from "../../api/APIClient"; import { DownloadClientTypeOptions } from "../../domain/constants"; import { toast } from "react-hot-toast"; import Toast from "../../components/notifications/Toast"; import { useToggle } from "../../hooks/hooks"; import { DeleteModal } from "../../components/modals"; import { NumberFieldWide, PasswordFieldWide, RadioFieldsetWide, SwitchGroupWide, TextFieldWide } from "../../components/inputs"; import DownloadClient from "../../screens/settings/DownloadClient"; interface InitialValuesSettings { basic?: { auth: boolean; username: string; password: string; }; rules?: { enabled?: boolean; ignore_slow_torrents?: boolean; download_speed_threshold?: number; max_active_downloads?: number; }; } interface InitialValues { name: string; type: DownloadClientType; enabled: boolean; host: string; port: number; tls: boolean; tls_skip_verify: boolean; username: string; password: string; settings: InitialValuesSettings; } function FormFieldsDeluge() { const { values: { tls } } = useFormikContext(); return (
{tls && ( )}
); } function FormFieldsArr() { const { values: { settings } } = useFormikContext(); return (
{settings.basic?.auth === true && ( <> )}
); } function FormFieldsQbit() { const { values: { port, tls, settings } } = useFormikContext(); return (
{port > 0 && ( )} {tls && ( )} {settings.basic?.auth === true && ( <> )}
); } function FormFieldsRTorrent() { return (
); } function FormFieldsTransmission() { const { values: { tls } } = useFormikContext(); return (
{tls && ( )}
); } export interface componentMapType { [key: string]: React.ReactElement; } export const componentMap: componentMapType = { DELUGE_V1: , DELUGE_V2: , QBITTORRENT: , RTORRENT: , TRANSMISSION: , RADARR: , SONARR: , LIDARR: , WHISPARR: }; function FormFieldsRulesBasic() { const { values: { settings } } = useFormikContext(); return (
Rules

Manage max downloads.

{settings && settings.rules?.enabled === true && ( )}
); } function FormFieldsRules() { const { values: { settings } } = useFormikContext(); return (
Rules

Manage max downloads etc.

{settings.rules?.enabled === true && ( <> {settings.rules?.ignore_slow_torrents === true && ( )} )}
); } export const rulesComponentMap: componentMapType = { DELUGE_V1: , DELUGE_V2: , QBITTORRENT: }; interface formButtonsProps { isSuccessfulTest: boolean; isErrorTest: boolean; isTesting: boolean; cancelFn: () => void; testFn: (data: unknown) => void; values: unknown; type: "CREATE" | "UPDATE"; toggleDeleteModal?: () => void; } function DownloadClientFormButtons({ type, isSuccessfulTest, isErrorTest, isTesting, cancelFn, testFn, values, toggleDeleteModal }: formButtonsProps) { const test = () => { testFn(values); }; return (
{type === "UPDATE" && ( )}
); } interface formProps { isOpen: boolean; toggle: () => void; } export function DownloadClientAddForm({ isOpen, toggle }: formProps) { const [isTesting, setIsTesting] = useState(false); const [isSuccessfulTest, setIsSuccessfulTest] = useState(false); const [isErrorTest, setIsErrorTest] = useState(false); const mutation = useMutation( (client: DownloadClient) => APIClient.download_clients.create(client), { onSuccess: () => { queryClient.invalidateQueries(["downloadClients"]); toast.custom((t) => ); toggle(); }, onError: () => { toast.custom((t) => ); } } ); const testClientMutation = useMutation( (client: DownloadClient) => APIClient.download_clients.test(client), { onMutate: () => { setIsTesting(true); setIsErrorTest(false); setIsSuccessfulTest(false); }, onSuccess: () => { sleep(1000) .then(() => { setIsTesting(false); setIsSuccessfulTest(true); }) .then(() => { sleep(2500).then(() => { setIsSuccessfulTest(false); }); }); }, onError: () => { console.log("not added"); setIsTesting(false); setIsErrorTest(true); sleep(2500).then(() => { setIsErrorTest(false); }); } } ); const onSubmit = (data: unknown) => { mutation.mutate(data as DownloadClient); }; const testClient = (data: unknown) => { testClientMutation.mutate(data as DownloadClient); }; const initialValues: InitialValues = { name: "", type: "QBITTORRENT", enabled: true, host: "", port: 0, tls: false, tls_skip_verify: false, username: "", password: "", settings: {} }; return (
{({ handleSubmit, values }) => (
Add client

Add download client.

{componentMap[values.type]}
{rulesComponentMap[values.type]} )}
); } interface updateFormProps { isOpen: boolean; toggle: () => void; client: DownloadClient; } export function DownloadClientUpdateForm({ client, isOpen, toggle }: updateFormProps) { const [isTesting, setIsTesting] = useState(false); const [isSuccessfulTest, setIsSuccessfulTest] = useState(false); const [isErrorTest, setIsErrorTest] = useState(false); const [deleteModalIsOpen, toggleDeleteModal] = useToggle(false); const mutation = useMutation( (client: DownloadClient) => APIClient.download_clients.update(client), { onSuccess: () => { queryClient.invalidateQueries(["downloadClients"]); toast.custom((t) => ); toggle(); } } ); const deleteMutation = useMutation( (clientID: number) => APIClient.download_clients.delete(clientID), { onSuccess: () => { queryClient.invalidateQueries(); toast.custom((t) => ); toggleDeleteModal(); } } ); const testClientMutation = useMutation( (client: DownloadClient) => APIClient.download_clients.test(client), { onMutate: () => { setIsTesting(true); setIsErrorTest(false); setIsSuccessfulTest(false); }, onSuccess: () => { sleep(1000) .then(() => { setIsTesting(false); setIsSuccessfulTest(true); }) .then(() => { sleep(2500).then(() => { setIsSuccessfulTest(false); }); }); }, onError: () => { setIsTesting(false); setIsErrorTest(true); sleep(2500).then(() => { setIsErrorTest(false); }); } } ); const onSubmit = (data: unknown) => { mutation.mutate(data as DownloadClient); }; const cancelButtonRef = useRef(null); const cancelModalButtonRef = useRef(null); const deleteAction = () => { deleteMutation.mutate(client.id); }; const testClient = (data: unknown) => { testClientMutation.mutate(data as DownloadClient); }; const initialValues = { id: client.id, name: client.name, type: client.type, enabled: client.enabled, host: client.host, port: client.port, tls: client.tls, tls_skip_verify: client.tls_skip_verify, username: client.username, password: client.password, settings: client.settings }; return (
{({ handleSubmit, values }) => { return (
Edit client

Edit download client settings.

{componentMap[values.type]}
{rulesComponentMap[values.type]} ); }}
); }