mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-09-24 10:20:50 +02:00
reactor: better handling of camoufox management
This commit is contained in:
@@ -818,7 +818,7 @@ impl ApiClient {
|
|||||||
Ok(filtered_releases)
|
Ok(filtered_releases)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a Brave release has compatible assets for the given platform and architecture
|
/// Check if a Camoufox release has compatible assets for the given platform and architecture
|
||||||
fn has_compatible_camoufox_asset(
|
fn has_compatible_camoufox_asset(
|
||||||
&self,
|
&self,
|
||||||
assets: &[crate::browser::GithubAsset],
|
assets: &[crate::browser::GithubAsset],
|
||||||
@@ -835,9 +835,9 @@ impl ApiClient {
|
|||||||
_ => return false,
|
_ => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Look for assets matching the pattern: camoufox-{version}-{release}-{os}.{arch}.zip
|
// Look for assets matching the pattern: camoufox-{version}-beta.{number}-{os}.{arch}.zip
|
||||||
// Use ends_with for precise matching to avoid false positives
|
// The separator before OS is a dash, e.g., camoufox-135.0.1-beta.24-lin.x86_64.zip
|
||||||
let pattern = format!(".{os_name}.{arch_name}.zip");
|
let pattern = format!("-{os_name}.{arch_name}.zip");
|
||||||
assets.iter().any(|asset| {
|
assets.iter().any(|asset| {
|
||||||
let name = asset.name.to_lowercase();
|
let name = asset.name.to_lowercase();
|
||||||
name.starts_with("camoufox-") && name.ends_with(&pattern)
|
name.starts_with("camoufox-") && name.ends_with(&pattern)
|
||||||
|
|||||||
@@ -310,7 +310,8 @@ impl Downloader {
|
|||||||
os: &str,
|
os: &str,
|
||||||
arch: &str,
|
arch: &str,
|
||||||
) -> Option<String> {
|
) -> Option<String> {
|
||||||
// Camoufox asset naming pattern: camoufox-{version}-{release}-{os}.{arch}.zip
|
// Camoufox asset naming pattern: camoufox-{version}-beta.{number}-{os}.{arch}.zip
|
||||||
|
// Example: camoufox-135.0.1-beta.24-lin.x86_64.zip
|
||||||
let (os_name, arch_name) = match (os, arch) {
|
let (os_name, arch_name) = match (os, arch) {
|
||||||
("windows", "x64") => ("win", "x86_64"),
|
("windows", "x64") => ("win", "x86_64"),
|
||||||
("windows", "arm64") => ("win", "arm64"),
|
("windows", "arm64") => ("win", "arm64"),
|
||||||
@@ -322,7 +323,8 @@ impl Downloader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Use ends_with for precise matching to avoid false positives
|
// Use ends_with for precise matching to avoid false positives
|
||||||
let pattern = format!(".{os_name}.{arch_name}.zip");
|
// The separator before OS is a dash: -lin.x86_64.zip, -mac.arm64.zip, etc.
|
||||||
|
let pattern = format!("-{os_name}.{arch_name}.zip");
|
||||||
let asset = assets.iter().find(|asset| {
|
let asset = assets.iter().find(|asset| {
|
||||||
let name = asset.name.to_lowercase();
|
let name = asset.name.to_lowercase();
|
||||||
name.starts_with("camoufox-") && name.ends_with(&pattern)
|
name.starts_with("camoufox-") && name.ends_with(&pattern)
|
||||||
|
|||||||
@@ -142,6 +142,10 @@ export function CreateProfileDialog({
|
|||||||
const [showProxyForm, setShowProxyForm] = useState(false);
|
const [showProxyForm, setShowProxyForm] = useState(false);
|
||||||
const [isCreating, setIsCreating] = useState(false);
|
const [isCreating, setIsCreating] = useState(false);
|
||||||
const [releaseTypes, setReleaseTypes] = useState<BrowserReleaseTypes>();
|
const [releaseTypes, setReleaseTypes] = useState<BrowserReleaseTypes>();
|
||||||
|
const [isLoadingReleaseTypes, setIsLoadingReleaseTypes] = useState(false);
|
||||||
|
const [releaseTypesError, setReleaseTypesError] = useState<string | null>(
|
||||||
|
null,
|
||||||
|
);
|
||||||
const loadingBrowserRef = useRef<string | null>(null);
|
const loadingBrowserRef = useRef<string | null>(null);
|
||||||
|
|
||||||
// Use the browser download hook
|
// Use the browser download hook
|
||||||
@@ -179,6 +183,8 @@ export function CreateProfileDialog({
|
|||||||
async (browser: string) => {
|
async (browser: string) => {
|
||||||
// Set loading state
|
// Set loading state
|
||||||
loadingBrowserRef.current = browser;
|
loadingBrowserRef.current = browser;
|
||||||
|
setIsLoadingReleaseTypes(true);
|
||||||
|
setReleaseTypesError(null);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const rawReleaseTypes = await invoke<BrowserReleaseTypes>(
|
const rawReleaseTypes = await invoke<BrowserReleaseTypes>(
|
||||||
@@ -207,6 +213,7 @@ export function CreateProfileDialog({
|
|||||||
filtered.stable = rawReleaseTypes.stable;
|
filtered.stable = rawReleaseTypes.stable;
|
||||||
setReleaseTypes(filtered);
|
setReleaseTypes(filtered);
|
||||||
}
|
}
|
||||||
|
setReleaseTypesError(null);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to load release types for ${browser}:`, error);
|
console.error(`Failed to load release types for ${browser}:`, error);
|
||||||
@@ -223,17 +230,29 @@ export function CreateProfileDialog({
|
|||||||
fallback.stable = latest;
|
fallback.stable = latest;
|
||||||
}
|
}
|
||||||
setReleaseTypes(fallback);
|
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) {
|
} catch (e) {
|
||||||
console.error(
|
console.error(
|
||||||
`Failed to load downloaded versions for ${browser}:`,
|
`Failed to load downloaded versions for ${browser}:`,
|
||||||
e,
|
e,
|
||||||
);
|
);
|
||||||
|
if (loadingBrowserRef.current === browser) {
|
||||||
|
setReleaseTypesError(
|
||||||
|
"Failed to fetch browser versions. Please check your internet connection and try again.",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// Clear loading state only if we're still loading this browser
|
// Clear loading state only if we're still loading this browser
|
||||||
if (loadingBrowserRef.current === browser) {
|
if (loadingBrowserRef.current === browser) {
|
||||||
loadingBrowserRef.current = null;
|
loadingBrowserRef.current = null;
|
||||||
|
setIsLoadingReleaseTypes(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -377,6 +396,8 @@ export function CreateProfileDialog({
|
|||||||
setSelectedBrowser(null);
|
setSelectedBrowser(null);
|
||||||
setSelectedProxyId(undefined);
|
setSelectedProxyId(undefined);
|
||||||
setReleaseTypes({});
|
setReleaseTypes({});
|
||||||
|
setIsLoadingReleaseTypes(false);
|
||||||
|
setReleaseTypesError(null);
|
||||||
setCamoufoxConfig({
|
setCamoufoxConfig({
|
||||||
geoip: true, // Reset to automatic geoip
|
geoip: true, // Reset to automatic geoip
|
||||||
os: getCurrentOS(), // Reset to current OS
|
os: getCurrentOS(), // Reset to current OS
|
||||||
@@ -553,7 +574,34 @@ export function CreateProfileDialog({
|
|||||||
// Camoufox Configuration
|
// Camoufox Configuration
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
{/* Camoufox Download Status */}
|
{/* Camoufox Download Status */}
|
||||||
{!isBrowserCurrentlyDownloading("camoufox") &&
|
{isLoadingReleaseTypes && (
|
||||||
|
<div className="flex gap-3 items-center p-3 rounded-md border">
|
||||||
|
<div className="w-4 h-4 rounded-full border-2 animate-spin border-muted/40 border-t-primary" />
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Fetching available versions...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoadingReleaseTypes && releaseTypesError && (
|
||||||
|
<div className="flex gap-3 items-center p-3 rounded-md border border-destructive/50 bg-destructive/10">
|
||||||
|
<p className="flex-1 text-sm text-destructive">
|
||||||
|
{releaseTypesError}
|
||||||
|
</p>
|
||||||
|
<RippleButton
|
||||||
|
onClick={() =>
|
||||||
|
selectedBrowser &&
|
||||||
|
loadReleaseTypes(selectedBrowser)
|
||||||
|
}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
Retry
|
||||||
|
</RippleButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoadingReleaseTypes &&
|
||||||
|
!releaseTypesError &&
|
||||||
|
!isBrowserCurrentlyDownloading("camoufox") &&
|
||||||
!isBrowserVersionAvailable("camoufox") &&
|
!isBrowserVersionAvailable("camoufox") &&
|
||||||
getBestAvailableVersion("camoufox") && (
|
getBestAvailableVersion("camoufox") && (
|
||||||
<div className="flex gap-3 items-center p-3 rounded-md border">
|
<div className="flex gap-3 items-center p-3 rounded-md border">
|
||||||
@@ -580,7 +628,9 @@ export function CreateProfileDialog({
|
|||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isBrowserCurrentlyDownloading("camoufox") &&
|
{!isLoadingReleaseTypes &&
|
||||||
|
!releaseTypesError &&
|
||||||
|
!isBrowserCurrentlyDownloading("camoufox") &&
|
||||||
isBrowserVersionAvailable("camoufox") && (
|
isBrowserVersionAvailable("camoufox") && (
|
||||||
<div className="p-3 text-sm rounded-md border text-muted-foreground">
|
<div className="p-3 text-sm rounded-md border text-muted-foreground">
|
||||||
{(() => {
|
{(() => {
|
||||||
@@ -607,13 +657,41 @@ export function CreateProfileDialog({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
// Regular Browser Configuration
|
// Regular Browser Configuration (should not happen in anti-detect tab)
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{selectedBrowser && (
|
{selectedBrowser && (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{!isBrowserCurrentlyDownloading(
|
{isLoadingReleaseTypes && (
|
||||||
selectedBrowser,
|
<div className="flex gap-3 items-center">
|
||||||
) &&
|
<div className="w-4 h-4 rounded-full border-2 animate-spin border-muted/40 border-t-primary" />
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Fetching available versions...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoadingReleaseTypes &&
|
||||||
|
releaseTypesError && (
|
||||||
|
<div className="flex gap-3 items-center p-3 rounded-md border border-destructive/50 bg-destructive/10">
|
||||||
|
<p className="flex-1 text-sm text-destructive">
|
||||||
|
{releaseTypesError}
|
||||||
|
</p>
|
||||||
|
<RippleButton
|
||||||
|
onClick={() =>
|
||||||
|
selectedBrowser &&
|
||||||
|
loadReleaseTypes(selectedBrowser)
|
||||||
|
}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
Retry
|
||||||
|
</RippleButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoadingReleaseTypes &&
|
||||||
|
!releaseTypesError &&
|
||||||
|
!isBrowserCurrentlyDownloading(
|
||||||
|
selectedBrowser,
|
||||||
|
) &&
|
||||||
!isBrowserVersionAvailable(selectedBrowser) &&
|
!isBrowserVersionAvailable(selectedBrowser) &&
|
||||||
getBestAvailableVersion(selectedBrowser) && (
|
getBestAvailableVersion(selectedBrowser) && (
|
||||||
<div className="flex gap-3 items-center">
|
<div className="flex gap-3 items-center">
|
||||||
@@ -643,9 +721,11 @@ export function CreateProfileDialog({
|
|||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isBrowserCurrentlyDownloading(
|
{!isLoadingReleaseTypes &&
|
||||||
selectedBrowser,
|
!releaseTypesError &&
|
||||||
) &&
|
!isBrowserCurrentlyDownloading(
|
||||||
|
selectedBrowser,
|
||||||
|
) &&
|
||||||
isBrowserVersionAvailable(
|
isBrowserVersionAvailable(
|
||||||
selectedBrowser,
|
selectedBrowser,
|
||||||
) && (
|
) && (
|
||||||
@@ -739,9 +819,36 @@ export function CreateProfileDialog({
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{selectedBrowser && (
|
{selectedBrowser && (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{!isBrowserCurrentlyDownloading(
|
{isLoadingReleaseTypes && (
|
||||||
selectedBrowser,
|
<div className="flex gap-3 items-center">
|
||||||
) &&
|
<div className="w-4 h-4 rounded-full border-2 animate-spin border-muted/40 border-t-primary" />
|
||||||
|
<p className="text-sm text-muted-foreground">
|
||||||
|
Fetching available versions...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoadingReleaseTypes && releaseTypesError && (
|
||||||
|
<div className="flex gap-3 items-center p-3 rounded-md border border-destructive/50 bg-destructive/10">
|
||||||
|
<p className="flex-1 text-sm text-destructive">
|
||||||
|
{releaseTypesError}
|
||||||
|
</p>
|
||||||
|
<RippleButton
|
||||||
|
onClick={() =>
|
||||||
|
selectedBrowser &&
|
||||||
|
loadReleaseTypes(selectedBrowser)
|
||||||
|
}
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
>
|
||||||
|
Retry
|
||||||
|
</RippleButton>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isLoadingReleaseTypes &&
|
||||||
|
!releaseTypesError &&
|
||||||
|
!isBrowserCurrentlyDownloading(
|
||||||
|
selectedBrowser,
|
||||||
|
) &&
|
||||||
!isBrowserVersionAvailable(selectedBrowser) &&
|
!isBrowserVersionAvailable(selectedBrowser) &&
|
||||||
getBestAvailableVersion(selectedBrowser) && (
|
getBestAvailableVersion(selectedBrowser) && (
|
||||||
<div className="flex gap-3 items-center">
|
<div className="flex gap-3 items-center">
|
||||||
@@ -771,9 +878,11 @@ export function CreateProfileDialog({
|
|||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!isBrowserCurrentlyDownloading(
|
{!isLoadingReleaseTypes &&
|
||||||
selectedBrowser,
|
!releaseTypesError &&
|
||||||
) &&
|
!isBrowserCurrentlyDownloading(
|
||||||
|
selectedBrowser,
|
||||||
|
) &&
|
||||||
isBrowserVersionAvailable(selectedBrowser) && (
|
isBrowserVersionAvailable(selectedBrowser) && (
|
||||||
<div className="text-sm text-muted-foreground">
|
<div className="text-sm text-muted-foreground">
|
||||||
{(() => {
|
{(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user