feat: windows support

This commit is contained in:
zhom
2026-02-15 11:48:59 +04:00
parent dd5afac951
commit 63453331ff
46 changed files with 2445 additions and 328 deletions
+13 -10
View File
@@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize};
use tao::event::{Event, StartCause};
use tao::event_loop::{ControlFlow, EventLoopBuilder};
use tokio::runtime::Runtime;
use tray_icon::TrayIcon;
use tray_icon::{MouseButton, TrayIcon, TrayIconEvent};
use donutbrowser_lib::daemon::{autostart, services, tray};
@@ -162,10 +162,7 @@ fn run_daemon() {
}
// Prepare tray menu and icon (but don't create the tray icon yet)
// Show "Starting..." state initially
let tray_menu = tray::TrayMenu::new();
tray_menu.update_api_status(None);
tray_menu.update_mcp_status(false);
let icon = tray::load_icon();
let menu_channel = MenuEvent::receiver();
@@ -208,8 +205,6 @@ fn run_daemon() {
mcp_running,
} => {
log::info!("[daemon] Services started successfully");
tray_menu.update_api_status(api_port);
tray_menu.update_mcp_status(mcp_running);
// Update state file
let mut state = read_state();
@@ -221,16 +216,13 @@ fn run_daemon() {
}
ServiceStatus::Failed(e) => {
log::error!("Failed to start services: {}", e);
// Keep tray icon running, show error state
tray_menu.update_api_status(None);
tray_menu.update_mcp_status(false);
}
}
}
// Process menu events
while let Ok(event) = menu_channel.try_recv() {
if event.id == tray_menu.open_item.id() || event.id == tray_menu.preferences_item.id() {
if event.id == tray_menu.open_item.id() {
tray::open_gui();
} else if event.id == tray_menu.quit_item.id() {
log::info!("[daemon] Quit requested");
@@ -238,6 +230,17 @@ fn run_daemon() {
}
}
// Handle tray icon click (left-click opens the app)
while let Ok(event) = TrayIconEvent::receiver().try_recv() {
if let TrayIconEvent::Click {
button: MouseButton::Left,
..
} = event
{
tray::open_gui();
}
}
// Use swap to only run cleanup once
if SHOULD_QUIT.swap(false, Ordering::SeqCst) {
// Cleanup
+25 -13
View File
@@ -291,19 +291,31 @@ async fn main() {
log::error!("Proxy worker starting, looking for config id: {}", id);
log::error!("Process PID: {}", std::process::id());
let config = match get_proxy_config(id) {
Some(config) => {
log::error!(
"Found config: id={}, port={:?}, upstream={}",
config.id,
config.local_port,
config.upstream_url
);
config
}
None => {
log::error!("Proxy configuration {} not found", id);
process::exit(1);
// Retry config loading to handle file system race condition on Windows
// where the config file may not be immediately visible after being written
let config = {
let mut attempts = 0;
loop {
if let Some(config) = get_proxy_config(id) {
log::error!(
"Found config: id={}, port={:?}, upstream={}",
config.id,
config.local_port,
config.upstream_url
);
break config;
}
attempts += 1;
if attempts >= 10 {
log::error!(
"Proxy configuration {} not found after {} attempts",
id,
attempts
);
process::exit(1);
}
log::error!("Config {} not found yet, retrying ({}/10)...", id, attempts);
std::thread::sleep(std::time::Duration::from_millis(50));
}
};