"use client"; import { invoke } from "@tauri-apps/api/core"; import { useCallback, useEffect, useId, useMemo, useRef, useState, } from "react"; import { useTranslation } from "react-i18next"; import { GoPlus } from "react-icons/go"; import { LuCheck, LuChevronsUpDown } from "react-icons/lu"; import { LoadingButton } from "@/components/loading-button"; import { ProxyFormDialog } from "@/components/proxy-form-dialog"; import { SharedCamoufoxConfigForm } from "@/components/shared-camoufox-config-form"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Tabs, TabsContent } from "@/components/ui/tabs"; import { WayfernConfigForm } from "@/components/wayfern-config-form"; import { useBrowserDownload } from "@/hooks/use-browser-download"; import { useProxyEvents } from "@/hooks/use-proxy-events"; import { useVpnEvents } from "@/hooks/use-vpn-events"; import { getBrowserIcon } from "@/lib/browser-utils"; import { cn } from "@/lib/utils"; import type { BrowserReleaseTypes, CamoufoxConfig, CamoufoxOS, WayfernConfig, WayfernOS, } from "@/types"; const getCurrentOS = (): CamoufoxOS => { if (typeof navigator === "undefined") return "linux"; const platform = navigator.platform.toLowerCase(); if (platform.includes("win")) return "windows"; if (platform.includes("mac")) return "macos"; return "linux"; }; import { RippleButton } from "./ui/ripple"; type BrowserTypeString = "camoufox" | "wayfern"; interface CreateProfileDialogProps { isOpen: boolean; onClose: () => void; onCreateProfile: (profileData: { name: string; browserStr: BrowserTypeString; version: string; releaseType: string; proxyId?: string; vpnId?: string; camoufoxConfig?: CamoufoxConfig; wayfernConfig?: WayfernConfig; groupId?: string; extensionGroupId?: string; ephemeral?: boolean; dnsBlocklist?: string; launchHook?: string; password?: string; }) => Promise; selectedGroupId?: string; crossOsUnlocked?: boolean; } interface BrowserOption { value: BrowserTypeString; label: string; } const browserOptions: BrowserOption[] = [ { value: "camoufox", label: "Camoufox", }, { value: "wayfern", label: "Wayfern", }, ]; export function CreateProfileDialog({ isOpen, onClose, onCreateProfile, selectedGroupId, crossOsUnlocked = false, }: CreateProfileDialogProps) { const { t } = useTranslation(); const proxyListboxIdAntiDetect = useId(); const proxyListboxIdRegular = useId(); const [profileName, setProfileName] = useState(""); const [currentStep, setCurrentStep] = useState< "browser-selection" | "browser-config" >("browser-selection"); const [activeTab, setActiveTab] = useState("anti-detect"); // Browser selection states const [selectedBrowser, setSelectedBrowser] = useState(null); const [selectedProxyId, setSelectedProxyId] = useState(); const [proxyPopoverOpen, setProxyPopoverOpen] = useState(false); const [dnsBlocklist, setDnsBlocklist] = useState(""); const [launchHook, setLaunchHook] = useState(""); // Camoufox anti-detect states const [camoufoxConfig, setCamoufoxConfig] = useState(() => ({ geoip: true, // Default to automatic geoip os: getCurrentOS(), // Default to current OS })); // Wayfern anti-detect states const [wayfernConfig, setWayfernConfig] = useState(() => ({ os: getCurrentOS() as WayfernOS, // Default to current OS })); // Handle browser selection from the initial screen const handleBrowserSelect = (browser: BrowserTypeString) => { setSelectedBrowser(browser); setCurrentStep("browser-config"); }; // Handle back button const handleBack = () => { setCurrentStep("browser-selection"); setSelectedBrowser(null); setProfileName(""); setSelectedProxyId(undefined); setLaunchHook(""); }; const handleTabChange = (value: string) => { setActiveTab(value); setCurrentStep("browser-selection"); setSelectedBrowser(null); setProfileName(""); setSelectedProxyId(undefined); setLaunchHook(""); }; const [supportedBrowsers, setSupportedBrowsers] = useState([]); const { storedProxies } = useProxyEvents(); const { vpnConfigs } = useVpnEvents(); const [showProxyForm, setShowProxyForm] = useState(false); const [isCreating, setIsCreating] = useState(false); const [ephemeral, setEphemeral] = useState(false); const [enablePassword, setEnablePassword] = useState(false); const [password, setPassword] = useState(""); const [passwordConfirm, setPasswordConfirm] = useState(""); const [passwordError, setPasswordError] = useState(null); const PASSWORD_MIN_LEN = 8; const [selectedExtensionGroupId, setSelectedExtensionGroupId] = useState(); const [extensionGroups, setExtensionGroups] = useState< { id: string; name: string; extension_ids: string[] }[] >([]); useEffect(() => { if (isOpen) { void invoke<{ id: string; name: string; extension_ids: string[] }[]>( "list_extension_groups", ) .then(setExtensionGroups) .catch(() => { setExtensionGroups([]); }); } }, [isOpen]); const [releaseTypes, setReleaseTypes] = useState(); const [isLoadingReleaseTypes, setIsLoadingReleaseTypes] = useState(false); const [releaseTypesError, setReleaseTypesError] = useState( null, ); const loadingBrowserRef = useRef(null); // Use the browser download hook const { isBrowserDownloading, downloadBrowser, loadDownloadedVersions, isVersionDownloaded, downloadedVersionsMap, } = useBrowserDownload(); const loadSupportedBrowsers = useCallback(async () => { try { const browsers = await invoke("get_supported_browsers"); setSupportedBrowsers(browsers); } catch (error) { console.error("Failed to load supported browsers:", error); } }, []); const checkAndDownloadGeoIPDatabase = useCallback(async () => { try { const isAvailable = await invoke("is_geoip_database_available"); if (!isAvailable) { console.log("GeoIP database not available, downloading..."); await invoke("download_geoip_database"); console.log("GeoIP database downloaded successfully"); } } catch (error) { console.error("Failed to check/download GeoIP database:", error); // Don't show error to user as this is not critical for profile creation } }, []); const loadReleaseTypes = useCallback( async (browser: string) => { // Set loading state loadingBrowserRef.current = browser; setIsLoadingReleaseTypes(true); setReleaseTypesError(null); try { const rawReleaseTypes = await invoke( "get_browser_release_types", { browserStr: browser }, ); await loadDownloadedVersions(browser); // Only update state if this browser is still the one we're loading if (loadingBrowserRef.current === browser) { const filtered: BrowserReleaseTypes = {}; if (rawReleaseTypes.stable) filtered.stable = rawReleaseTypes.stable; setReleaseTypes(filtered); setReleaseTypesError(null); } } catch (error) { console.error(`Failed to load release types for ${browser}:`, error); // Fallback: still load downloaded versions and derive release type from them if possible try { const downloaded = await loadDownloadedVersions(browser); if (loadingBrowserRef.current === browser && downloaded.length > 0) { const latest = downloaded[0]; const fallback: BrowserReleaseTypes = {}; fallback.stable = latest; setReleaseTypes(fallback); setReleaseTypesError(null); } else if (loadingBrowserRef.current === browser) { // No downloaded versions and API failed - show error setReleaseTypesError( "Failed to fetch browser versions. Please check your internet connection and try again.", ); } } catch (e) { console.error( `Failed to load downloaded versions for ${browser}:`, e, ); if (loadingBrowserRef.current === browser) { setReleaseTypesError( "Failed to fetch browser versions. Please check your internet connection and try again.", ); } } } finally { // Clear loading state only if we're still loading this browser if (loadingBrowserRef.current === browser) { loadingBrowserRef.current = null; setIsLoadingReleaseTypes(false); } } }, [loadDownloadedVersions], ); // Load data when dialog opens useEffect(() => { if (isOpen) { void loadSupportedBrowsers(); // Load release types when a browser is selected if (selectedBrowser) { void loadReleaseTypes(selectedBrowser); } // Check and download GeoIP database if needed for Camoufox or Wayfern if (selectedBrowser === "camoufox" || selectedBrowser === "wayfern") { void checkAndDownloadGeoIPDatabase(); } } }, [ isOpen, loadSupportedBrowsers, loadReleaseTypes, checkAndDownloadGeoIPDatabase, selectedBrowser, ]); // Load release types when browser selection changes useEffect(() => { if (selectedBrowser) { // Cancel any previous loading loadingBrowserRef.current = null; // Clear previous release types immediately to prevent showing stale data setReleaseTypes({}); void loadReleaseTypes(selectedBrowser); } }, [selectedBrowser, loadReleaseTypes]); // Helper function to get the best available version respecting rules const getBestAvailableVersion = useCallback( (_browserType?: string) => { if (!releaseTypes) return null; if (releaseTypes.stable) { return { version: releaseTypes.stable, releaseType: "stable" as const }; } return null; }, [releaseTypes], ); const getCreatableVersion = useCallback( (browserType?: string) => { const bestVersion = getBestAvailableVersion(browserType); if (bestVersion && isVersionDownloaded(bestVersion.version)) { return bestVersion; } const browserDownloaded = downloadedVersionsMap[browserType ?? ""] ?? []; if (browserDownloaded.length > 0) { const fallbackVersion = browserDownloaded[0]; return { version: fallbackVersion, releaseType: "stable" as const, }; } return null; }, [getBestAvailableVersion, isVersionDownloaded, downloadedVersionsMap], ); const handleDownload = async (browserStr: string) => { const bestVersion = getBestAvailableVersion(browserStr); if (!bestVersion) { console.error("No version available for download"); return; } try { await downloadBrowser(browserStr, bestVersion.version); } catch (error) { console.error("Failed to download browser:", error); } }; const handleCreate = async () => { if (!profileName.trim()) return; if (enablePassword && !ephemeral) { if (password.length < PASSWORD_MIN_LEN) { setPasswordError( t("profilePassword.errors.tooShort", { min: PASSWORD_MIN_LEN }), ); return; } if (password !== passwordConfirm) { setPasswordError(t("profilePassword.errors.mismatch")); return; } } setPasswordError(null); setIsCreating(true); const isVpnSelection = selectedProxyId?.startsWith("vpn-") ?? false; const resolvedProxyId = isVpnSelection ? undefined : selectedProxyId; const resolvedVpnId = isVpnSelection && selectedProxyId ? selectedProxyId.slice(4) : undefined; const passwordToSet = enablePassword && !ephemeral && password.length >= PASSWORD_MIN_LEN ? password : undefined; try { if (activeTab === "anti-detect") { // Anti-detect browser - check if Wayfern or Camoufox is selected if (selectedBrowser === "wayfern") { const bestWayfernVersion = getCreatableVersion("wayfern"); if (!bestWayfernVersion) { console.error("No Wayfern version available"); return; } // The fingerprint will be generated at launch time by the Rust backend const finalWayfernConfig = { ...wayfernConfig }; await onCreateProfile({ name: profileName.trim(), browserStr: "wayfern" as BrowserTypeString, version: bestWayfernVersion.version, releaseType: bestWayfernVersion.releaseType, proxyId: resolvedProxyId, vpnId: resolvedVpnId, wayfernConfig: finalWayfernConfig, groupId: selectedGroupId && selectedGroupId !== "__all__" ? selectedGroupId : undefined, extensionGroupId: selectedExtensionGroupId, ephemeral, dnsBlocklist: dnsBlocklist || undefined, launchHook: launchHook.trim() || undefined, password: passwordToSet, }); } else { // Default to Camoufox const bestCamoufoxVersion = getCreatableVersion("camoufox"); if (!bestCamoufoxVersion) { console.error("No Camoufox version available"); return; } // The fingerprint will be generated at launch time by the Rust backend // We don't need to generate it here during profile creation const finalCamoufoxConfig = { ...camoufoxConfig }; await onCreateProfile({ name: profileName.trim(), browserStr: "camoufox" as BrowserTypeString, version: bestCamoufoxVersion.version, releaseType: bestCamoufoxVersion.releaseType, proxyId: resolvedProxyId, vpnId: resolvedVpnId, camoufoxConfig: finalCamoufoxConfig, groupId: selectedGroupId && selectedGroupId !== "__all__" ? selectedGroupId : undefined, extensionGroupId: selectedExtensionGroupId, ephemeral, dnsBlocklist: dnsBlocklist || undefined, launchHook: launchHook.trim() || undefined, password: passwordToSet, }); } } else { // Regular browser if (!selectedBrowser) { console.error("Missing required browser selection"); return; } // Use the best available version (stable preferred, nightly as fallback) const bestVersion = getCreatableVersion(selectedBrowser); if (!bestVersion) { console.error("No version available"); return; } await onCreateProfile({ name: profileName.trim(), browserStr: selectedBrowser, version: bestVersion.version, releaseType: bestVersion.releaseType, proxyId: selectedProxyId, groupId: selectedGroupId && selectedGroupId !== "__all__" ? selectedGroupId : undefined, dnsBlocklist: dnsBlocklist || undefined, launchHook: launchHook.trim() || undefined, password: passwordToSet, }); } handleClose(); } catch (error) { console.error("Failed to create profile:", error); } finally { setIsCreating(false); } }; const handleClose = () => { // Cancel any ongoing loading loadingBrowserRef.current = null; // Reset all states setProfileName(""); setCurrentStep("browser-selection"); setActiveTab("anti-detect"); setSelectedBrowser(null); setSelectedProxyId(undefined); setLaunchHook(""); setReleaseTypes({}); setIsLoadingReleaseTypes(false); setReleaseTypesError(null); setCamoufoxConfig({ geoip: true, // Reset to automatic geoip os: getCurrentOS(), // Reset to current OS }); setWayfernConfig({ os: getCurrentOS() as WayfernOS, // Reset to current OS }); setEphemeral(false); setEnablePassword(false); setPassword(""); setPasswordConfirm(""); setPasswordError(null); onClose(); }; const updateCamoufoxConfig = (key: keyof CamoufoxConfig, value: unknown) => { setCamoufoxConfig((prev) => ({ ...prev, [key]: value })); }; const updateWayfernConfig = (key: keyof WayfernConfig, value: unknown) => { setWayfernConfig((prev) => ({ ...prev, [key]: value })); }; // Check if browser version is downloaded and available const isBrowserVersionAvailable = useCallback( (browserStr: string) => { const bestVersion = getBestAvailableVersion(browserStr); return bestVersion && isVersionDownloaded(bestVersion.version); }, [isVersionDownloaded, getBestAvailableVersion], ); // Check if browser is currently downloading const isBrowserCurrentlyDownloading = useCallback( (browserStr: string) => { return isBrowserDownloading(browserStr); }, [isBrowserDownloading], ); const isCreateDisabled = useMemo(() => { if (!profileName.trim()) return true; if (!selectedBrowser) return true; if (isBrowserCurrentlyDownloading(selectedBrowser)) return true; if (!getCreatableVersion(selectedBrowser)) return true; return false; }, [ profileName, selectedBrowser, isBrowserCurrentlyDownloading, getCreatableVersion, ]); // Filter supported browsers for regular browsers const regularBrowsers = browserOptions.filter((browser) => supportedBrowsers.includes(browser.value), ); return ( {currentStep === "browser-selection" ? t("createProfile.title") : t("createProfile.configureTitle", { browser: selectedBrowser === "wayfern" ? t("createProfile.chromiumLabel") : t("createProfile.firefoxLabel"), })} {/* Tab list hidden - only anti-detect browsers are supported */}
{currentStep === "browser-selection" ? ( <> {/* Anti-Detect Browser Selection */}
{/* Wayfern (Chromium) - First */} {/* Camoufox (Firefox) - Second */}
{/* Regular Browser Selection */}

{t("createProfile.regular.title")}

{t("createProfile.regular.description")}

{regularBrowsers.map((browser) => { if (browser.value === "camoufox") return null; // Skip camoufox as it's handled in anti-detect tab const IconComponent = getBrowserIcon(browser.value); return ( ); })}
) : ( <> {/* Anti-Detect Configuration */}
{/* Profile Name */}
{ setProfileName(e.target.value); }} onKeyDown={(e) => { if ( e.key === "Enter" && !isCreateDisabled && !isCreating ) { void handleCreate(); } }} placeholder={t( "createProfile.profileNamePlaceholder", )} />
{/* Ephemeral Option */}
{ setEphemeral(checked === true); }} />

{t("profiles.ephemeralDescription")}

{/* Password Option */} {!ephemeral && (
{ setEnablePassword(checked === true); if (checked !== true) { setPassword(""); setPasswordConfirm(""); setPasswordError(null); } }} />

{t("createProfile.passwordProtect.description")}

{enablePassword && (
{ setPassword(e.target.value); setPasswordError(null); }} placeholder={t( "profilePassword.fields.newPassword", )} autoComplete="new-password" /> { setPasswordConfirm(e.target.value); setPasswordError(null); }} placeholder={t( "profilePassword.fields.confirm", )} autoComplete="new-password" /> {passwordError && (

{passwordError}

)}
)}
)} {selectedBrowser === "wayfern" ? ( // Wayfern Configuration
{/* Wayfern Download Status */} {isLoadingReleaseTypes && (

{t("createProfile.version.fetching")}

)} {!isLoadingReleaseTypes && releaseTypesError && (

{releaseTypesError}

selectedBrowser && loadReleaseTypes(selectedBrowser) } size="sm" variant="outline" > {t("common.buttons.retry")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !getBestAvailableVersion("wayfern") && (

{t("createProfile.platformUnavailable", { browser: "Wayfern", })}

)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading("wayfern") && !isBrowserVersionAvailable("wayfern") && getBestAvailableVersion("wayfern") && (

{t("createProfile.version.needsDownload", { browser: "Wayfern", version: getBestAvailableVersion("wayfern") ?.version, })}

{ void handleDownload("wayfern"); }} isLoading={isBrowserCurrentlyDownloading( "wayfern", )} size="sm" disabled={isBrowserCurrentlyDownloading( "wayfern", )} > {isBrowserCurrentlyDownloading("wayfern") ? t("common.buttons.downloading") : t("common.buttons.download")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading("wayfern") && isBrowserVersionAvailable("wayfern") && (
✓{" "} {t("createProfile.version.available", { browser: "Wayfern", version: getBestAvailableVersion("wayfern") ?.version, })}
)} {isBrowserCurrentlyDownloading("wayfern") && (
{t("createProfile.version.downloading", { browser: "Wayfern", version: getBestAvailableVersion("wayfern")?.version, })}
)}
) : selectedBrowser === "camoufox" ? ( // Camoufox Configuration
{/* Camoufox Download Status */} {isLoadingReleaseTypes && (

{t("createProfile.version.fetching")}

)} {!isLoadingReleaseTypes && releaseTypesError && (

{releaseTypesError}

selectedBrowser && loadReleaseTypes(selectedBrowser) } size="sm" variant="outline" > {t("common.buttons.retry")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !getBestAvailableVersion("camoufox") && (

{t("createProfile.platformUnavailable", { browser: "Camoufox", })}

)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading("camoufox") && !isBrowserVersionAvailable("camoufox") && getBestAvailableVersion("camoufox") && (

{t("createProfile.version.needsDownload", { browser: "Camoufox", version: getBestAvailableVersion("camoufox") ?.version, })}

{ void handleDownload("camoufox"); }} isLoading={isBrowserCurrentlyDownloading( "camoufox", )} size="sm" disabled={isBrowserCurrentlyDownloading( "camoufox", )} > {isBrowserCurrentlyDownloading("camoufox") ? t("common.buttons.downloading") : t("common.buttons.download")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading("camoufox") && isBrowserVersionAvailable("camoufox") && (
✓{" "} {t("createProfile.version.available", { browser: "Camoufox", version: getBestAvailableVersion("camoufox") ?.version, })}
)} {isBrowserCurrentlyDownloading("camoufox") && (
{t("createProfile.version.downloading", { browser: "Camoufox", version: getBestAvailableVersion("camoufox") ?.version, })}
)} {crossOsUnlocked && ( {t("createProfile.camoufoxWarning")} )}
) : ( // Regular Browser Configuration (should not happen in anti-detect tab)
{selectedBrowser && (
{isLoadingReleaseTypes && (

{t("createProfile.version.fetching")}

)} {!isLoadingReleaseTypes && releaseTypesError && (

{releaseTypesError}

selectedBrowser && loadReleaseTypes(selectedBrowser) } size="sm" variant="outline" > Retry
)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading( selectedBrowser, ) && !isBrowserVersionAvailable(selectedBrowser) && getBestAvailableVersion(selectedBrowser) && (

{t( "createProfile.version.latestNeedsDownload", { version: getBestAvailableVersion( selectedBrowser, )?.version, }, )}

{ void handleDownload(selectedBrowser); }} isLoading={isBrowserCurrentlyDownloading( selectedBrowser, )} className="ml-auto" size="sm" disabled={isBrowserCurrentlyDownloading( selectedBrowser, )} > {t("common.buttons.download")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading( selectedBrowser, ) && isBrowserVersionAvailable( selectedBrowser, ) && (
✓{" "} {t( "createProfile.version.latestAvailable", { version: getBestAvailableVersion( selectedBrowser, )?.version, }, )}
)} {isBrowserCurrentlyDownloading( selectedBrowser, ) && (
{t( "createProfile.version.latestDownloading", { version: getBestAvailableVersion( selectedBrowser, )?.version, }, )}
)}
)}
)} {/* Proxy / VPN Selection - Always visible */}
{ setShowProxyForm(true); }} className="px-2 h-7 text-xs" > {" "} {t("createProfile.proxy.addProxy")}
{storedProxies.length > 0 || vpnConfigs.length > 0 ? ( {t("createProfile.proxy.notFound")} { setSelectedProxyId(undefined); setProxyPopoverOpen(false); }} > {t("common.labels.none")} {storedProxies.map((proxy) => ( { setSelectedProxyId(proxy.id); setProxyPopoverOpen(false); }} > {proxy.name} ))} {vpnConfigs.length > 0 && ( {vpnConfigs.map((vpn) => ( { setSelectedProxyId( `vpn-${vpn.id}`, ); setProxyPopoverOpen(false); }} > WG {vpn.name} ))} )} ) : (
{t("createProfile.proxy.noProxiesAvailable")}
)}
{ setLaunchHook(e.target.value); }} placeholder={t( "createProfile.launchHook.placeholder", )} disabled={isCreating} />
{/* DNS Blocklist */}
{/* Extension Group */} {extensionGroups.length > 0 && (
)}
{/* Regular Browser Configuration */}
{/* Profile Name */}
{ setProfileName(e.target.value); }} onKeyDown={(e) => { if ( e.key === "Enter" && !isCreateDisabled && !isCreating ) { void handleCreate(); } }} placeholder={t( "createProfile.profileNamePlaceholder", )} />
{/* Regular Browser Configuration */}
{selectedBrowser && (
{isLoadingReleaseTypes && (

Fetching available versions...

)} {!isLoadingReleaseTypes && releaseTypesError && (

{releaseTypesError}

selectedBrowser && loadReleaseTypes(selectedBrowser) } size="sm" variant="outline" > {t("common.buttons.retry")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading( selectedBrowser, ) && !isBrowserVersionAvailable(selectedBrowser) && getBestAvailableVersion(selectedBrowser) && (

{t( "createProfile.version.latestNeedsDownload", { version: getBestAvailableVersion( selectedBrowser, )?.version, }, )}

{ void handleDownload(selectedBrowser); }} isLoading={isBrowserCurrentlyDownloading( selectedBrowser, )} className="ml-auto" size="sm" disabled={isBrowserCurrentlyDownloading( selectedBrowser, )} > {t("common.buttons.download")}
)} {!isLoadingReleaseTypes && !releaseTypesError && !isBrowserCurrentlyDownloading( selectedBrowser, ) && isBrowserVersionAvailable(selectedBrowser) && (
✓{" "} {t( "createProfile.version.latestAvailable", { version: getBestAvailableVersion( selectedBrowser, )?.version, }, )}
)} {isBrowserCurrentlyDownloading( selectedBrowser, ) && (
{t( "createProfile.version.latestDownloading", { version: getBestAvailableVersion(selectedBrowser) ?.version, }, )}
)}
)}
{/* Proxy / VPN Selection - Always visible */}
{ setShowProxyForm(true); }} className="px-2 h-7 text-xs" > {" "} {t("createProfile.proxy.addProxy")}
{storedProxies.length > 0 || vpnConfigs.length > 0 ? ( {t("createProfile.proxy.notFound")} { setSelectedProxyId(undefined); setProxyPopoverOpen(false); }} > {t("common.labels.none")} {storedProxies.map((proxy) => ( { setSelectedProxyId(proxy.id); setProxyPopoverOpen(false); }} > {proxy.name} ))} {vpnConfigs.length > 0 && ( {vpnConfigs.map((vpn) => ( { setSelectedProxyId( `vpn-${vpn.id}`, ); setProxyPopoverOpen(false); }} > WG {vpn.name} ))} )} ) : (
{t("createProfile.proxy.noProxiesAvailable")}
)}
{ setLaunchHook(e.target.value); }} placeholder={t( "createProfile.launchHook.placeholder", )} disabled={isCreating} />
)}
{currentStep === "browser-config" ? ( <> {t("common.buttons.back")} {t("common.buttons.create")} ) : ( {t("common.buttons.cancel")} )} { setShowProxyForm(false); }} />
); }