mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-06-02 13:21:36 +02:00
refactor: better camoufox creationg handling
This commit is contained in:
@@ -1220,25 +1220,13 @@ impl BrowserRunner {
|
||||
{
|
||||
Ok(path) => path,
|
||||
Err(e) => {
|
||||
// Check if the expected archive is already present (manual download)
|
||||
let expected_archive_path = browser_dir.join(&download_info.filename);
|
||||
if expected_archive_path.exists() {
|
||||
println!(
|
||||
"Download failed, but found existing archive at {}. Continuing with extraction.",
|
||||
expected_archive_path.display()
|
||||
);
|
||||
expected_archive_path
|
||||
} else {
|
||||
// Remove only the registry entry; keep any files (including a partially downloaded archive)
|
||||
let _ = registry.remove_browser(&browser_str, &version);
|
||||
let _ = registry.save();
|
||||
// Remove browser-version pair from downloading set on error
|
||||
{
|
||||
let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap();
|
||||
downloading.remove(&download_key);
|
||||
}
|
||||
return Err(format!("Failed to download browser: {e}").into());
|
||||
}
|
||||
// Do NOT continue with extraction on failed downloads. Partial files may exist but are invalid.
|
||||
// Clean registry entry and stop here so the UI can show a single, clear error.
|
||||
let _ = registry.remove_browser(&browser_str, &version);
|
||||
let _ = registry.save();
|
||||
let mut downloading = DOWNLOADING_BROWSERS.lock().unwrap();
|
||||
downloading.remove(&download_key);
|
||||
return Err(format!("Failed to download browser: {e}").into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { GoPlus } from "react-icons/go";
|
||||
import { LoadingButton } from "@/components/loading-button";
|
||||
import { ProxyFormDialog } from "@/components/proxy-form-dialog";
|
||||
@@ -109,12 +109,13 @@ export function CreateProfileDialog({
|
||||
const [activeTab, setActiveTab] = useState("anti-detect");
|
||||
|
||||
// Regular browser states
|
||||
const [selectedBrowser, setSelectedBrowser] = useState<BrowserTypeString>();
|
||||
const [selectedBrowser, setSelectedBrowser] =
|
||||
useState<BrowserTypeString | null>("camoufox");
|
||||
const [selectedProxyId, setSelectedProxyId] = useState<string>();
|
||||
|
||||
const handleTabChange = (value: string) => {
|
||||
if (value === "regular") {
|
||||
setSelectedBrowser(undefined);
|
||||
setSelectedBrowser(null);
|
||||
} else if (value === "anti-detect") {
|
||||
setSelectedBrowser("camoufox");
|
||||
}
|
||||
@@ -355,7 +356,7 @@ export function CreateProfileDialog({
|
||||
|
||||
// Reset all states
|
||||
setProfileName("");
|
||||
setSelectedBrowser(undefined);
|
||||
setSelectedBrowser(null);
|
||||
setSelectedProxyId(undefined);
|
||||
setAvailableReleaseTypes({});
|
||||
setCamoufoxReleaseTypes({});
|
||||
@@ -366,40 +367,49 @@ export function CreateProfileDialog({
|
||||
onClose();
|
||||
};
|
||||
|
||||
const isCreateDisabled = () => {
|
||||
if (!profileName.trim()) return true;
|
||||
|
||||
if (!selectedBrowser) return true;
|
||||
|
||||
if (isBrowserCurrentlyDownloading(selectedBrowser)) return true;
|
||||
|
||||
if (!isBrowserVersionAvailable(selectedBrowser)) return true;
|
||||
|
||||
if (selectedBrowser === "camoufox") {
|
||||
return !getBestAvailableVersion(camoufoxReleaseTypes, selectedBrowser);
|
||||
}
|
||||
|
||||
return !getBestAvailableVersion(availableReleaseTypes, selectedBrowser);
|
||||
};
|
||||
|
||||
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 bestVersion = getBestAvailableVersion(releaseTypes, browserStr);
|
||||
return bestVersion && isVersionDownloaded(bestVersion.version);
|
||||
};
|
||||
const isBrowserVersionAvailable = useCallback(
|
||||
(browserStr: string) => {
|
||||
const releaseTypes =
|
||||
browserStr === "camoufox"
|
||||
? camoufoxReleaseTypes
|
||||
: availableReleaseTypes;
|
||||
const bestVersion = getBestAvailableVersion(releaseTypes, browserStr);
|
||||
return bestVersion && isVersionDownloaded(bestVersion.version);
|
||||
},
|
||||
[
|
||||
camoufoxReleaseTypes,
|
||||
availableReleaseTypes,
|
||||
isVersionDownloaded,
|
||||
getBestAvailableVersion,
|
||||
],
|
||||
);
|
||||
|
||||
// Check if browser is currently downloading
|
||||
const isBrowserCurrentlyDownloading = (browserStr: string) => {
|
||||
return isBrowserDownloading(browserStr);
|
||||
};
|
||||
const isBrowserCurrentlyDownloading = useCallback(
|
||||
(browserStr: string) => {
|
||||
return isBrowserDownloading(browserStr);
|
||||
},
|
||||
[isBrowserDownloading],
|
||||
);
|
||||
|
||||
console.log(selectedBrowser);
|
||||
const isCreateDisabled = useMemo(() => {
|
||||
if (!profileName.trim()) return true;
|
||||
if (!selectedBrowser) return true;
|
||||
if (isBrowserCurrentlyDownloading(selectedBrowser)) return true;
|
||||
if (!isBrowserVersionAvailable(selectedBrowser)) return true;
|
||||
|
||||
return false;
|
||||
}, [
|
||||
profileName,
|
||||
selectedBrowser,
|
||||
isBrowserCurrentlyDownloading,
|
||||
isBrowserVersionAvailable,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={handleClose}>
|
||||
@@ -639,7 +649,7 @@ export function CreateProfileDialog({
|
||||
<LoadingButton
|
||||
onClick={handleCreate}
|
||||
isLoading={isCreating}
|
||||
disabled={isCreateDisabled()}
|
||||
disabled={isCreateDisabled}
|
||||
>
|
||||
Create
|
||||
</LoadingButton>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import type { Event as TauriEvent } from "@tauri-apps/api/event";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { getBrowserDisplayName } from "@/lib/browser-utils";
|
||||
@@ -7,6 +8,7 @@ import {
|
||||
showDownloadToast,
|
||||
showErrorToast,
|
||||
showSuccessToast,
|
||||
showToast,
|
||||
} from "@/lib/toast-utils";
|
||||
|
||||
interface GithubRelease {
|
||||
@@ -257,21 +259,22 @@ export function useBrowserDownload() {
|
||||
// Legacy isDownloading for backwards compatibility
|
||||
const isDownloading = downloadingBrowsers.size > 0;
|
||||
|
||||
// Listen for download progress events
|
||||
// Listen for download progress events (browsers) and GeoIP progress events
|
||||
useEffect(() => {
|
||||
let unlistenFn: (() => void) | null = null;
|
||||
let unlistenBrowser: (() => void) | null = null;
|
||||
let unlistenGeoip: (() => void) | null = null;
|
||||
|
||||
const setupListener = async () => {
|
||||
const setupListeners = async () => {
|
||||
try {
|
||||
unlistenFn = await listen<DownloadProgress>(
|
||||
// Browser binaries download progress
|
||||
unlistenBrowser = await listen<DownloadProgress>(
|
||||
"download-progress",
|
||||
(event) => {
|
||||
async (event: TauriEvent<DownloadProgress>) => {
|
||||
const progress = event.payload;
|
||||
setDownloadProgress(progress);
|
||||
|
||||
const browserName = getBrowserDisplayName(progress.browser);
|
||||
|
||||
// Show toast with progress
|
||||
if (progress.stage === "downloading") {
|
||||
const speedMBps = (
|
||||
progress.speed_bytes_per_sec /
|
||||
@@ -291,6 +294,16 @@ export function useBrowserDownload() {
|
||||
} else if (progress.stage === "verifying") {
|
||||
showDownloadToast(browserName, progress.version, "verifying");
|
||||
} else if (progress.stage === "completed") {
|
||||
// On completion, refresh the downloaded versions for this browser and also refresh camoufox,
|
||||
// since the Create dialog implicitly uses camoufox on the anti-detect tab
|
||||
try {
|
||||
await Promise.all([
|
||||
loadDownloadedVersions(progress.browser),
|
||||
progress.browser !== "camoufox"
|
||||
? loadDownloadedVersions("camoufox")
|
||||
: Promise.resolve([]),
|
||||
]);
|
||||
} catch {}
|
||||
showDownloadToast(browserName, progress.version, "completed");
|
||||
setDownloadProgress(null);
|
||||
}
|
||||
@@ -299,20 +312,65 @@ export function useBrowserDownload() {
|
||||
} catch (error) {
|
||||
console.error("Failed to setup download progress listener:", error);
|
||||
}
|
||||
|
||||
try {
|
||||
// GeoIP database download progress
|
||||
unlistenGeoip = await listen<{
|
||||
stage: string;
|
||||
percentage: number;
|
||||
message: string;
|
||||
}>(
|
||||
"geoip-download-progress",
|
||||
(
|
||||
event: TauriEvent<{
|
||||
stage: string;
|
||||
percentage: number;
|
||||
message: string;
|
||||
}>,
|
||||
) => {
|
||||
const { stage, percentage } = event.payload;
|
||||
if (stage === "downloading") {
|
||||
showToast({
|
||||
id: "geoip-download",
|
||||
type: "download",
|
||||
title: "Downloading GeoIP database",
|
||||
stage: "downloading",
|
||||
progress: { percentage },
|
||||
});
|
||||
} else if (stage === "completed") {
|
||||
showToast({
|
||||
id: "geoip-download",
|
||||
type: "download",
|
||||
title: "GeoIP database downloaded successfully!",
|
||||
stage: "completed",
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Failed to setup GeoIP progress listener:", error);
|
||||
}
|
||||
};
|
||||
|
||||
setupListener();
|
||||
void setupListeners();
|
||||
|
||||
return () => {
|
||||
if (unlistenFn) {
|
||||
if (unlistenBrowser) {
|
||||
try {
|
||||
unlistenFn();
|
||||
unlistenBrowser();
|
||||
} catch (error) {
|
||||
console.error("Failed to cleanup download progress listener:", error);
|
||||
console.error("Failed to cleanup browser download listener:", error);
|
||||
}
|
||||
}
|
||||
if (unlistenGeoip) {
|
||||
try {
|
||||
unlistenGeoip();
|
||||
} catch (error) {
|
||||
console.error("Failed to cleanup GeoIP progress listener:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, [formatTime]);
|
||||
}, [formatTime, loadDownloadedVersions]);
|
||||
|
||||
return {
|
||||
availableVersions,
|
||||
|
||||
Reference in New Issue
Block a user