"use client"; import { invoke } from "@tauri-apps/api/core"; import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import { LoadingButton } from "@/components/loading-button"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import type { StoredProxy } from "@/types"; import { RippleButton } from "./ui/ripple"; interface ProxyFormData { name: string; proxy_type: string; host: string; port: number; username: string; password: string; } interface ProxyFormDialogProps { isOpen: boolean; onClose: () => void; editingProxy?: StoredProxy | null; } const DEFAULT_FORM: ProxyFormData = { name: "", proxy_type: "http", host: "", port: 8080, username: "", password: "", }; export function ProxyFormDialog({ isOpen, onClose, editingProxy, }: ProxyFormDialogProps) { const { t } = useTranslation(); const [isSubmitting, setIsSubmitting] = useState(false); const [form, setForm] = useState(DEFAULT_FORM); const resetForm = useCallback(() => { setForm(DEFAULT_FORM); }, []); useEffect(() => { if (!isOpen) { return; } if (!editingProxy) { resetForm(); return; } setForm({ name: editingProxy.name, proxy_type: editingProxy.proxy_settings.proxy_type, host: editingProxy.proxy_settings.host, port: editingProxy.proxy_settings.port, username: editingProxy.proxy_settings.username ?? "", password: editingProxy.proxy_settings.password ?? "", }); }, [editingProxy, isOpen, resetForm]); const handleSubmit = useCallback(async () => { if (!form.name.trim()) { toast.error(t("proxies.form.nameRequired")); return; } if (!form.host.trim() || !form.port) { toast.error(t("proxies.form.hostPortRequired")); return; } if ( form.proxy_type === "ss" && (!form.username.trim() || !form.password.trim()) ) { toast.error(t("proxies.form.ssCipherRequired")); return; } setIsSubmitting(true); try { const payload = { name: form.name.trim(), proxySettings: { proxy_type: form.proxy_type, host: form.host.trim(), port: form.port, username: form.username.trim() || undefined, password: form.password.trim() || undefined, }, }; if (editingProxy) { await invoke("update_stored_proxy", { proxyId: editingProxy.id, ...payload, }); toast.success(t("toasts.success.proxyUpdated")); } else { await invoke("create_stored_proxy", payload); toast.success(t("toasts.success.proxyCreated")); } onClose(); } catch (error) { console.error("Failed to save proxy:", error); const errorMessage = error instanceof Error ? error.message : String(error); toast.error(t("proxies.form.saveFailed", { error: errorMessage })); } finally { setIsSubmitting(false); } }, [editingProxy, form, onClose, t]); const handleClose = useCallback(() => { if (!isSubmitting) { onClose(); } }, [isSubmitting, onClose]); const isFormValid = form.name.trim() && form.host.trim() && form.port > 0 && form.port <= 65535 && (form.proxy_type !== "ss" || (form.username.trim() && form.password.trim())); return ( {editingProxy ? t("proxies.edit") : t("proxies.add")}
{ setForm({ ...form, name: e.target.value }); }} placeholder={t("proxies.form.namePlaceholder")} disabled={isSubmitting} />
{ setForm({ ...form, host: e.target.value }); }} placeholder={t("proxies.form.hostPlaceholder")} disabled={isSubmitting} />
{ setForm({ ...form, port: Number.parseInt(e.target.value, 10) || 0, }); }} placeholder={t("proxies.form.portPlaceholder")} min="1" max="65535" disabled={isSubmitting} />
{ setForm({ ...form, username: e.target.value }); }} placeholder={ form.proxy_type === "ss" ? t("proxies.form.cipherPlaceholder") : t("proxies.form.usernamePlaceholder") } disabled={isSubmitting} />
{ setForm({ ...form, password: e.target.value }); }} placeholder={t("proxies.form.passwordPlaceholder")} disabled={isSubmitting} />
{t("common.buttons.cancel")} {editingProxy ? t("proxies.edit") : t("proxies.add")}
); }