Compare commits

...

11 Commits

Author SHA1 Message Date
zhom 3bec00a2cd chore: reset lock file 2025-07-11 03:43:52 +04:00
zhom 3b78971df8 chore: pnpm update 2025-07-11 03:31:05 +04:00
zhom 5f9a716f62 chore: version bump 2025-07-11 03:22:36 +04:00
zhom 4d07984d99 chore: hide camoufox 2025-07-11 03:22:11 +04:00
zhom 188e14e5b5 style: copy 2025-07-11 03:10:53 +04:00
zhom bc1b9e9757 style: copy 2025-07-11 03:10:00 +04:00
zhom e742e5fdfa style: copy 2025-07-11 03:09:38 +04:00
zhom 9ce7757cb2 chore: version bump 2025-07-08 06:26:39 +04:00
zhom 3ca454a2c5 style: adjust modal height 2025-07-08 04:57:25 +04:00
zhom 689ac8e3ca fix: windows build correct string literal 2025-07-07 07:34:55 +04:00
zhom 0e1c5dcfb6 docs: add feature description 2025-07-07 07:33:41 +04:00
19 changed files with 393 additions and 402 deletions
+1 -1
View File
@@ -52,7 +52,7 @@ jobs:
with:
prompt-file: issue_analysis.txt
system-prompt: |
You are an issue validation assistant for Donut Browser, an anti-detect browser.
You are an issue validation assistant for Donut Browser, an browser orchestrator.
Analyze the provided issue content and determine if it contains sufficient information based on these requirements:
@@ -62,7 +62,7 @@ jobs:
with:
prompt-file: commits.txt
system-prompt: |
You are an expert technical writer tasked with generating comprehensive release notes for Donut Browser, a powerful anti-detect browser.
You are an expert technical writer tasked with generating comprehensive release notes for Donut Browser, a powerful browser orchestrator.
Analyze the provided commit messages and generate well-structured release notes following this format:
+5
View File
@@ -17,6 +17,7 @@
"cmdk",
"codegen",
"CTYPE",
"datareporting",
"devedition",
"doesn",
"donutbrowser",
@@ -32,12 +33,14 @@
"gettimezone",
"gifs",
"gsettings",
"healthreport",
"hkcu",
"icns",
"idletime",
"Inno",
"KHTML",
"launchservices",
"letterboxing",
"libatk",
"libayatana",
"libcairo",
@@ -63,6 +66,7 @@
"objc",
"orhun",
"osascript",
"peerconnection",
"pixbuf",
"plasmohq",
"prefs",
@@ -94,6 +98,7 @@
"timedatectl",
"titlebar",
"Torbrowser",
"trackingprotection",
"turbopack",
"udeps",
"unlisten",
+2 -2
View File
@@ -1,7 +1,7 @@
<div align="center">
<img src="assets/logo.png" alt="Donut Browser Logo" width="150">
<h1>Donut Browser</h1>
<strong>A powerful anti-detect browser that puts you in control of your browsing experience. 🍩</strong>
<strong>A powerful browser orchestrator that puts you in control of your browsing experience. 🍩</strong>
</div>
<br>
@@ -27,7 +27,7 @@
## Donut Browser
> A free and open source anti-detect browser built with [Tauri](https://v2.tauri.app/).
> A free and open source browser orchestrator built with [Tauri](https://v2.tauri.app/).
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/preview-dark.png" />
+2 -2
View File
@@ -154,7 +154,7 @@ program
}
});
// Command for Camoufox anti-detect browser
// Command for Camoufox browser orchestrator
program
.command("camoufox")
.argument("<action>", "launch, stop, list, or open-url for Camoufox browser")
@@ -239,7 +239,7 @@ program
// Firefox preferences
.option("--firefox-prefs <prefs>", "Firefox user preferences (JSON string)")
.description("launch and manage Camoufox anti-detect browser instances")
.description("launch and manage Camoufox browser orchestrator instances")
.action(async (action: string, options: any) => {
try {
if (action === "launch") {
+2 -2
View File
@@ -2,7 +2,7 @@
"name": "donutbrowser",
"private": true,
"license": "AGPL-3.0",
"version": "0.7.0",
"version": "0.7.2",
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
@@ -58,7 +58,7 @@
"@biomejs/biome": "2.0.6",
"@tailwindcss/postcss": "^4.1.11",
"@tauri-apps/cli": "^2.6.2",
"@types/node": "^24.0.10",
"@types/node": "^24.0.13",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^4.6.0",
+294 -337
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -971,7 +971,7 @@ dependencies = [
[[package]]
name = "donutbrowser"
version = "0.7.0"
version = "0.7.2"
dependencies = [
"async-trait",
"base64 0.22.1",
+2 -2
View File
@@ -1,7 +1,7 @@
[package]
name = "donutbrowser"
version = "0.7.0"
description = "Simple Yet Powerful Anti-Detect Browser"
version = "0.7.2"
description = "Simple Yet Powerful Browser Orchestrator"
authors = ["zhom@github"]
edition = "2021"
default-run = "donutbrowser"
+1 -1
View File
@@ -2,7 +2,7 @@
Version=1.0
Type=Application
Name=Donut Browser
Comment=Simple Yet Powerful Anti-Detect Browser
Comment=Simple Yet Powerful Browser Orchestrator
Exec=donutbrowser %u
Icon=donutbrowser
StartupNotify=true
+1 -1
View File
@@ -455,7 +455,7 @@ impl AppAutoUpdater {
percentage: Some(percentage),
speed: Some(format!("{speed:.1}")),
eta: Some(eta),
message: format!("Downloading update... {percentage:.1}%"),
message: "Downloading update...".to_string(),
},
);
+2 -2
View File
@@ -158,7 +158,7 @@ mod windows {
app_key
.set_value(
"ApplicationDescription",
&"Donut Browser - Simple Yet Powerful Anti-Detect Browser",
&"Donut Browser - Simple Yet Powerful Browser Orchestrator",
)
.map_err(|e| format!("Failed to set ApplicationDescription: {}", e))?;
@@ -174,7 +174,7 @@ mod windows {
capabilities
.set_value(
"ApplicationDescription",
&"Donut Browser - Simple Yet Powerful Anti-Detect Browser",
&"Donut Browser - Simple Yet Powerful Browser Orchestrator",
)
.map_err(|e| format!("Failed to set Capabilities description: {}", e))?;
+1 -1
View File
@@ -238,7 +238,7 @@ mod windows {
let hours = &offset_str[..colon_pos];
let minutes = &offset_str[colon_pos + 1..];
if let (Ok(h), Ok(m)) = (hours.parse::<i32>(), minutes.parse::<i32>()) {
return format!("{:+03d}:{:02d}", h, m);
return format!("{:+03}:{:02}", h, m);
}
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "Donut Browser",
"version": "0.7.0",
"version": "0.7.2",
"identifier": "com.donutbrowser",
"build": {
"beforeDevCommand": "pnpm dev",
+9 -3
View File
@@ -141,7 +141,9 @@ export default function Home() {
const profileList = await invoke<BrowserProfile[]>(
"list_browser_profiles",
);
setProfiles(profileList);
setProfiles(
profileList.filter((profile) => profile.browser !== "camoufox"),
);
// Check for missing binaries after loading profiles
await checkMissingBinaries();
@@ -189,7 +191,9 @@ export default function Home() {
const profileList = await invoke<BrowserProfile[]>(
"list_browser_profiles",
);
setProfiles(profileList);
setProfiles(
profileList.filter((profile) => profile.browser !== "camoufox"),
);
// TODO: remove after a few version bumps, needed to properly display migrated profiles
setTimeout(async () => {
@@ -197,7 +201,9 @@ export default function Home() {
const profiles = await invoke<BrowserProfile[]>(
"list_browser_profiles",
);
setProfiles(profiles);
setProfiles(
profiles.filter((profile) => profile.browser !== "camoufox"),
);
}
await sleep(500);
}, 0);
+1 -1
View File
@@ -140,7 +140,7 @@ export function CamoufoxConfigDialog({
</DialogTitle>
</DialogHeader>
<ScrollArea className="flex-1 pr-6 h-[350px]">
<ScrollArea className="flex-1 pr-6 h-[320px]">
<div className="py-4 space-y-6">
{/* Operating System */}
<div className="space-y-3">
+43 -42
View File
@@ -25,7 +25,7 @@ import {
} from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useBrowserDownload } from "@/hooks/use-browser-download";
import { getBrowserIcon } from "@/lib/browser-utils";
import { getBrowserIcon, getCurrentOS } from "@/lib/browser-utils";
import type { BrowserReleaseTypes, CamoufoxConfig, StoredProxy } from "@/types";
type BrowserTypeString =
@@ -95,15 +95,7 @@ const browserOptions: BrowserOption[] = [
},
];
const getCurrentOS = () => {
if (typeof window !== "undefined") {
const userAgent = window.navigator.userAgent;
if (userAgent.includes("Win")) return "windows";
if (userAgent.includes("Mac")) return "macos";
if (userAgent.includes("Linux")) return "linux";
}
return "unknown";
};
const IS_ANTI_DETECT_SUPPORTED = false;
export function CreateProfileDialog({
isOpen,
@@ -325,7 +317,7 @@ export function CreateProfileDialog({
<TabsTrigger value="anti-detect">Anti-Detect</TabsTrigger>
</TabsList>
<ScrollArea className="flex-1 pr-6 h-[350px]">
<ScrollArea className="flex-1 pr-6 h-[320px]">
<div className="py-4 space-y-6">
{/* Profile Name - Common to both tabs */}
<div className="space-y-2">
@@ -396,45 +388,54 @@ export function CreateProfileDialog({
</TabsContent>
<TabsContent value="anti-detect" className="mt-0 space-y-6">
{/* Anti-Detect Description */}
<div className="p-3 text-center bg-blue-50 rounded-md border border-blue-200 dark:bg-blue-950 dark:border-blue-800">
<p className="text-sm text-blue-800 dark:text-blue-200">
Powered by Camoufox
Anti-Detect support is coming soon!
</p>
</div>
</TabsContent>
{IS_ANTI_DETECT_SUPPORTED && (
<TabsContent value="anti-detect" className="mt-0 space-y-6">
{/* Anti-Detect Description */}
<div className="p-3 text-center bg-blue-50 rounded-md border border-blue-200 dark:bg-blue-950 dark:border-blue-800">
<p className="text-sm text-blue-800 dark:text-blue-200">
Powered by Camoufox
</p>
</div>
<div className="space-y-6">
{/* Camoufox Download Status */}
{!isBrowserVersionAvailable("camoufox") &&
camoufoxReleaseTypes.stable && (
<div className="flex gap-3 items-center p-3 bg-amber-50 rounded-md border border-amber-200">
<p className="text-sm text-amber-800">
Camoufox version ({camoufoxReleaseTypes.stable}) needs
to be downloaded
</p>
<LoadingButton
onClick={() => handleDownload("camoufox")}
isLoading={isBrowserDownloading("camoufox")}
size="sm"
disabled={isBrowserDownloading("camoufox")}
>
Download
</LoadingButton>
<div className="space-y-6">
{/* Camoufox Download Status */}
{!isBrowserVersionAvailable("camoufox") &&
camoufoxReleaseTypes.stable && (
<div className="flex gap-3 items-center p-3 bg-amber-50 rounded-md border border-amber-200">
<p className="text-sm text-amber-800">
Camoufox version ({camoufoxReleaseTypes.stable})
needs to be downloaded
</p>
<LoadingButton
onClick={() => handleDownload("camoufox")}
isLoading={isBrowserDownloading("camoufox")}
size="sm"
disabled={isBrowserDownloading("camoufox")}
>
Download
</LoadingButton>
</div>
)}
{isBrowserVersionAvailable("camoufox") && (
<div className="p-3 text-sm text-green-600 bg-green-50 rounded-md border border-green-200">
Camoufox version ({camoufoxReleaseTypes.stable}) is
available
</div>
)}
{isBrowserVersionAvailable("camoufox") && (
<div className="p-3 text-sm text-green-600 bg-green-50 rounded-md border border-green-200">
Camoufox version ({camoufoxReleaseTypes.stable}) is
available
</div>
)}
<SharedCamoufoxConfigForm
config={camoufoxConfig}
onConfigChange={updateCamoufoxConfig}
/>
</div>
</TabsContent>
<SharedCamoufoxConfigForm
config={camoufoxConfig}
onConfigChange={updateCamoufoxConfig}
/>
</div>
</TabsContent>
)}
{/* Proxy Selection - Common to both tabs - Compact without card */}
{storedProxies.length > 0 && (
+14 -2
View File
@@ -45,7 +45,12 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { useTableSorting } from "@/hooks/use-table-sorting";
import { getBrowserDisplayName, getBrowserIcon } from "@/lib/browser-utils";
import {
getBrowserDisplayName,
getBrowserIcon,
getCurrentOS,
} from "@/lib/browser-utils";
import { cn } from "@/lib/utils";
import type { BrowserProfile, StoredProxy } from "@/types";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
@@ -524,9 +529,16 @@ export function ProfilesDataTable({
getCoreRowModel: getCoreRowModel(),
});
const platform = getCurrentOS();
return (
<>
<ScrollArea className="h-[400px] rounded-md border">
<ScrollArea
className={cn(
"rounded-md border",
platform === "macos" ? "h-[380px]" : "h-[320px]",
)}
>
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
+10
View File
@@ -49,3 +49,13 @@ export function getBrowserIcon(browserType: string) {
return null;
}
}
export const getCurrentOS = () => {
if (typeof window !== "undefined") {
const userAgent = window.navigator.userAgent;
if (userAgent.includes("Win")) return "windows";
if (userAgent.includes("Mac")) return "macos";
if (userAgent.includes("Linux")) return "linux";
}
return "unknown";
};