"use client"; import { invoke } from "@tauri-apps/api/core"; import { useCallback, useEffect, useState } from "react"; import { LoadingButton } from "@/components/loading-button"; import { SharedCamoufoxConfigForm } from "@/components/shared-camoufox-config-form"; import { Button } from "@/components/ui/button"; import { Combobox } from "@/components/ui/combobox"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { useBrowserDownload } from "@/hooks/use-browser-download"; import { getBrowserIcon, getCurrentOS } from "@/lib/browser-utils"; import type { BrowserReleaseTypes, CamoufoxConfig, StoredProxy } from "@/types"; type BrowserTypeString = | "mullvad-browser" | "firefox" | "firefox-developer" | "chromium" | "brave" | "zen" | "tor-browser" | "camoufox"; interface CreateProfileDialogProps { isOpen: boolean; onClose: () => void; onCreateProfile: (profileData: { name: string; browserStr: BrowserTypeString; version: string; releaseType: string; proxyId?: string; camoufoxConfig?: CamoufoxConfig; }) => Promise; } interface BrowserOption { value: BrowserTypeString; label: string; description: string; } const browserOptions: BrowserOption[] = [ { value: "firefox", label: "Firefox", description: "Mozilla's main web browser", }, { value: "firefox-developer", label: "Firefox Developer Edition", description: "Browser for developers with cutting-edge features", }, { value: "chromium", label: "Chromium", description: "Open-source version of Chrome", }, { value: "brave", label: "Brave", description: "Privacy-focused browser with ad blocking", }, { value: "zen", label: "Zen Browser", description: "Beautiful, customizable Firefox-based browser", }, { value: "mullvad-browser", label: "Mullvad Browser", description: "Privacy browser by Mullvad VPN", }, { value: "tor-browser", label: "Tor Browser", description: "Browse anonymously through the Tor network", }, ]; const IS_ANTI_DETECT_SUPPORTED = false; export function CreateProfileDialog({ isOpen, onClose, onCreateProfile, }: CreateProfileDialogProps) { const [profileName, setProfileName] = useState(""); const [activeTab, setActiveTab] = useState("regular"); // Regular browser states const [selectedBrowser, setSelectedBrowser] = useState(); const [selectedProxyId, setSelectedProxyId] = useState(); // Camoufox anti-detect states const [camoufoxConfig, setCamoufoxConfig] = useState({ enable_cache: true, // Cache enabled by default os: [getCurrentOS()], // Default to current OS }); // Common states const [availableReleaseTypes, setAvailableReleaseTypes] = useState({}); const [camoufoxReleaseTypes, setCamoufoxReleaseTypes] = useState({}); const [supportedBrowsers, setSupportedBrowsers] = useState([]); const [storedProxies, setStoredProxies] = useState([]); const [isCreating, setIsCreating] = useState(false); // Use the browser download hook const { isBrowserDownloading, downloadBrowser, loadDownloadedVersions, isVersionDownloaded, } = 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 loadStoredProxies = useCallback(async () => { try { const proxies = await invoke("get_stored_proxies"); setStoredProxies(proxies); } catch (error) { console.error("Failed to load stored proxies:", error); } }, []); const loadReleaseTypes = useCallback( async (browser: string) => { try { const releaseTypes = await invoke( "get_browser_release_types", { browserStr: browser }, ); if (browser === "camoufox") { setCamoufoxReleaseTypes(releaseTypes); } else { setAvailableReleaseTypes(releaseTypes); } // Load downloaded versions for this browser await loadDownloadedVersions(browser); } catch (error) { console.error(`Failed to load release types for ${browser}:`, error); } }, [loadDownloadedVersions], ); // Load data when dialog opens useEffect(() => { if (isOpen) { void loadSupportedBrowsers(); void loadStoredProxies(); // Load camoufox release types when dialog opens void loadReleaseTypes("camoufox"); } }, [isOpen, loadSupportedBrowsers, loadStoredProxies, loadReleaseTypes]); // Load release types when browser selection changes useEffect(() => { if (selectedBrowser) { void loadReleaseTypes(selectedBrowser); } }, [selectedBrowser, loadReleaseTypes]); const handleDownload = async (browserStr: string) => { const releaseTypes = browserStr === "camoufox" ? camoufoxReleaseTypes : availableReleaseTypes; const latestStableVersion = releaseTypes.stable; if (!latestStableVersion) { console.error("No stable version available for download"); return; } try { await downloadBrowser(browserStr, latestStableVersion); } catch (error) { console.error("Failed to download browser:", error); } }; const handleCreate = async () => { if (!profileName.trim()) return; setIsCreating(true); try { if (activeTab === "regular") { if (!selectedBrowser) { console.error("Missing required browser selection"); return; } // Use the latest stable version by default const latestStableVersion = availableReleaseTypes.stable; if (!latestStableVersion) { console.error("No stable version available"); return; } await onCreateProfile({ name: profileName.trim(), browserStr: selectedBrowser, version: latestStableVersion, releaseType: "stable", proxyId: selectedProxyId, }); } else { // Anti-detect tab - always use Camoufox with latest version const latestCamoufoxVersion = camoufoxReleaseTypes.stable; if (!latestCamoufoxVersion) { console.error("No Camoufox version available"); return; } await onCreateProfile({ name: profileName.trim(), browserStr: "camoufox" as BrowserTypeString, version: latestCamoufoxVersion, releaseType: "stable", proxyId: selectedProxyId, camoufoxConfig, }); } handleClose(); } catch (error) { console.error("Failed to create profile:", error); } finally { setIsCreating(false); } }; const handleClose = () => { // Reset all states setProfileName(""); setSelectedBrowser(undefined); setSelectedProxyId(undefined); setCamoufoxConfig({ enable_cache: true, os: [getCurrentOS()], // Reset to current OS }); setActiveTab("regular"); onClose(); }; const isCreateDisabled = () => { if (!profileName.trim()) return true; if (activeTab === "regular") { return !selectedBrowser || !availableReleaseTypes.stable; } else { // For anti-detect, we need camoufox to be available return !camoufoxReleaseTypes.stable; } }; const updateCamoufoxConfig = (key: keyof CamoufoxConfig, value: unknown) => { setCamoufoxConfig((prev) => ({ ...prev, [key]: value })); }; // Check if browser version is downloaded and available const isBrowserVersionAvailable = (browserStr: string) => { const releaseTypes = browserStr === "camoufox" ? camoufoxReleaseTypes : availableReleaseTypes; const latestStableVersion = releaseTypes.stable; return latestStableVersion && isVersionDownloaded(latestStableVersion); }; // Get the selected OS for warning const selectedOS = camoufoxConfig.os?.[0]; const currentOS = getCurrentOS(); const _showOSWarning = selectedOS && selectedOS !== currentOS && currentOS !== "unknown"; return ( Create New Profile Regular Browsers Anti-Detect
{/* Profile Name - Common to both tabs */}
setProfileName(e.target.value)} placeholder="Enter profile name" />
supportedBrowsers.includes(browser.value), ) .map((browser) => { const IconComponent = getBrowserIcon(browser.value); return { value: browser.value, label: browser.label, icon: IconComponent, }; })} value={selectedBrowser || ""} onValueChange={(value) => setSelectedBrowser(value as BrowserTypeString) } placeholder="Select a browser..." searchPlaceholder="Search browsers..." />
{selectedBrowser && (
{!isBrowserVersionAvailable(selectedBrowser) && availableReleaseTypes.stable && (

Latest stable version ( {availableReleaseTypes.stable}) needs to be downloaded

handleDownload(selectedBrowser)} isLoading={isBrowserDownloading(selectedBrowser)} size="sm" disabled={isBrowserDownloading(selectedBrowser)} > Download
)} {isBrowserVersionAvailable(selectedBrowser) && (
✓ Latest stable version ( {availableReleaseTypes.stable}) is available
)}
)}

Anti-Detect support is coming soon!

{IS_ANTI_DETECT_SUPPORTED && ( {/* Anti-Detect Description */}

Powered by Camoufox

{/* Camoufox Download Status */} {!isBrowserVersionAvailable("camoufox") && camoufoxReleaseTypes.stable && (

Camoufox version ({camoufoxReleaseTypes.stable}) needs to be downloaded

handleDownload("camoufox")} isLoading={isBrowserDownloading("camoufox")} size="sm" disabled={isBrowserDownloading("camoufox")} > Download
)} {isBrowserVersionAvailable("camoufox") && (
✓ Camoufox version ({camoufoxReleaseTypes.stable}) is available
)}
)} {/* Proxy Selection - Common to both tabs - Compact without card */} {storedProxies.length > 0 && (
)}
Create Profile
); }