"use client"; import { invoke } from "@tauri-apps/api/core"; import { emit } from "@tauri-apps/api/event"; import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { LuCheck, LuChevronsUpDown } from "react-icons/lu"; import { toast } from "sonner"; import { LoadingButton } from "@/components/loading-button"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { cn } from "@/lib/utils"; import type { BrowserProfile, StoredProxy, VpnConfig } from "@/types"; import { RippleButton } from "./ui/ripple"; interface ProxyAssignmentDialogProps { isOpen: boolean; onClose: () => void; selectedProfiles: string[]; onAssignmentComplete: () => void; profiles?: BrowserProfile[]; storedProxies?: StoredProxy[]; vpnConfigs?: VpnConfig[]; } export function ProxyAssignmentDialog({ isOpen, onClose, selectedProfiles, onAssignmentComplete, profiles = [], storedProxies = [], vpnConfigs = [], }: ProxyAssignmentDialogProps) { const { t } = useTranslation(); const [selectedId, setSelectedId] = useState(null); const [selectionType, setSelectionType] = useState<"none" | "proxy" | "vpn">( "none", ); const [isAssigning, setIsAssigning] = useState(false); const [proxyPopoverOpen, setProxyPopoverOpen] = useState(false); const [error, setError] = useState(null); const handleValueChange = useCallback((value: string) => { if (value === "none") { setSelectedId(null); setSelectionType("none"); } else if (value.startsWith("vpn-")) { setSelectedId(value.slice(4)); setSelectionType("vpn"); } else { setSelectedId(value); setSelectionType("proxy"); } }, []); const handleAssign = useCallback(async () => { setIsAssigning(true); setError(null); try { const validProfiles = selectedProfiles.filter((profileId) => { const profile = profiles.find((p) => p.id === profileId); return profile; }); if (validProfiles.length === 0) { setError(t("proxyAssignment.noValidProfiles")); setIsAssigning(false); return; } for (const profileId of validProfiles) { if (selectionType === "vpn") { await invoke("update_profile_vpn", { profileId, vpnId: selectedId, }); } else { await invoke("update_profile_proxy", { profileId, proxyId: selectionType === "proxy" ? selectedId : null, }); } } await emit("profile-updated"); onAssignmentComplete(); onClose(); } catch (err) { console.error("Failed to assign proxy/VPN to profiles:", err); const errorMessage = err instanceof Error ? err.message : t("proxyAssignment.failedFallback"); setError(errorMessage); toast.error(errorMessage); } finally { setIsAssigning(false); } }, [ selectedProfiles, selectedId, selectionType, profiles, onAssignmentComplete, onClose, t, ]); useEffect(() => { if (isOpen) { setSelectedId(null); setSelectionType("none"); setError(null); } }, [isOpen]); return ( {t("proxyAssignment.title")} {selectedProfiles.length === 1 ? t("proxyAssignment.description_one", { count: selectedProfiles.length, }) : t("proxyAssignment.description_other", { count: selectedProfiles.length, })}
    {selectedProfiles.map((profileId) => { const profile = profiles.find( (p: BrowserProfile) => p.id === profileId, ); const displayName = profile ? profile.name : profileId; return (
  • • {displayName}
  • ); })}
{t("proxyAssignment.notFound")} { handleValueChange("none"); setProxyPopoverOpen(false); }} > {t("proxyAssignment.noneOption")} {storedProxies .filter( (proxy) => !proxy.is_cloud_managed && !proxy.is_cloud_derived, ) .map((proxy) => ( { handleValueChange(proxy.id); setProxyPopoverOpen(false); }} > {proxy.name} ))} {vpnConfigs.length > 0 && ( {vpnConfigs.map((vpn) => ( { handleValueChange(`vpn-${vpn.id}`); setProxyPopoverOpen(false); }} > WG {vpn.name} ))} )}
{error && (
{error}
)}
{t("common.buttons.cancel")} void handleAssign()} > {t("proxyAssignment.assignButton")}
); }