diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f062a82..639debf 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -526,7 +526,7 @@ dependencies = [ [[package]] name = "codex-switcher" -version = "0.1.5" +version = "0.1.6" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4263105..d11bd1e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -13,7 +13,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] tauri-build = { version = "2", features = [] } [dependencies] -tauri = { version = "2.10", features = [] } +tauri = { version = "2.10", features = ["tray-icon"] } tauri-plugin-opener = "2" tauri-plugin-dialog = "2.6" tauri-plugin-process = "2" diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6e4ea19..4d85e0c 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -12,10 +12,23 @@ use commands::{ import_accounts_slim_text, list_accounts, refresh_all_accounts_usage, rename_account, set_masked_account_ids, start_login, switch_account, warmup_account, warmup_all_accounts, }; +use tauri::{ + AppHandle, Manager, RunEvent, WindowEvent, + menu::{MenuBuilder, MenuItemBuilder}, + tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, +}; + +fn show_main_window(app: &AppHandle) { + if let Some(window) = app.get_webview_window("main") { + let _ = window.show(); + let _ = window.unminimize(); + let _ = window.set_focus(); + } +} #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - tauri::Builder::default() + let app = tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_process::init()) @@ -23,8 +36,47 @@ pub fn run() { #[cfg(desktop)] app.handle() .plugin(tauri_plugin_updater::Builder::new().build())?; + + let show = MenuItemBuilder::with_id("show", "Open Codex Switcher").build(app)?; + let quit = MenuItemBuilder::with_id("quit", "Quit").build(app)?; + let menu = MenuBuilder::new(app).items(&[&show, &quit]).build()?; + + TrayIconBuilder::with_id("main-tray") + .icon( + app.default_window_icon() + .expect("default window icon is required") + .clone(), + ) + .tooltip("Codex Switcher") + .menu(&menu) + .show_menu_on_left_click(false) + .on_menu_event(|app, event| match event.id().as_ref() { + "show" => show_main_window(app), + "quit" => app.exit(0), + _ => {} + }) + .on_tray_icon_event(|tray, event| { + if let TrayIconEvent::Click { + button: MouseButton::Left, + button_state: MouseButtonState::Up, + .. + } = event + { + show_main_window(tray.app_handle()); + } + }) + .build(app)?; + Ok(()) }) + .on_window_event(|window, event| { + if let WindowEvent::CloseRequested { api, .. } = event { + api.prevent_close(); + let _ = window.hide(); + #[cfg(target_os = "macos")] + let _ = window.app_handle().set_dock_visibility(false); + } + }) .invoke_handler(tauri::generate_handler![ // Account management list_accounts, @@ -52,6 +104,12 @@ pub fn run() { // Process detection check_codex_processes, ]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); + .build(tauri::generate_context!()) + .expect("error while building tauri application"); + + app.run(|app, event| { + if let RunEvent::Reopen { .. } = event { + show_main_window(app); + } + }); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index d2b7422..0a26082 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -26,6 +26,9 @@ "bundle": { "active": true, "targets": "all", + "macOS": { + "minimumSystemVersion": "10.13" + }, "icon": [ "icons/32x32.png", "icons/128x128.png",