diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 74472b7d6..4ece05179 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -164,6 +164,7 @@ fn initialize_core_logic(app_handle: &AppHandle) { app_handle.manage(model_manager.clone()); app_handle.manage(transcription_manager.clone()); app_handle.manage(history_manager.clone()); + app_handle.manage(tray::CurrentTrayIconState::new()); // Note: Shortcuts are NOT initialized here. // The frontend is responsible for calling the `initialize_shortcuts` command @@ -253,7 +254,7 @@ fn initialize_core_logic(app_handle: &AppHandle) { log::error!("Failed to switch model via tray: {}", e); } } - tray::update_tray_menu(&app_clone, &tray::TrayIconState::Idle, None); + tray::update_tray_menu(&app_clone, None); }); } _ => {} @@ -263,7 +264,7 @@ fn initialize_core_logic(app_handle: &AppHandle) { app_handle.manage(tray); // Initialize tray menu with idle state - utils::update_tray_menu(app_handle, &utils::TrayIconState::Idle, None); + utils::update_tray_menu(app_handle, None); // Apply show_tray_icon setting let settings = settings::get_settings(app_handle); @@ -274,7 +275,7 @@ fn initialize_core_logic(app_handle: &AppHandle) { // Refresh tray menu when model state changes let app_handle_for_listener = app_handle.clone(); app_handle.listen("model-state-changed", move |_| { - tray::update_tray_menu(&app_handle_for_listener, &tray::TrayIconState::Idle, None); + tray::update_tray_menu(&app_handle_for_listener, None); }); // Get the autostart manager and configure based on user setting diff --git a/src-tauri/src/shortcut/mod.rs b/src-tauri/src/shortcut/mod.rs index 6d179f175..6913e9966 100644 --- a/src-tauri/src/shortcut/mod.rs +++ b/src-tauri/src/shortcut/mod.rs @@ -1077,7 +1077,7 @@ pub fn change_app_language_setting(app: AppHandle, language: String) -> Result<( settings::write_settings(&app, settings); // Refresh the tray menu with the new language - tray::update_tray_menu(&app, &tray::TrayIconState::Idle, Some(&language)); + tray::update_tray_menu(&app, Some(&language)); Ok(()) } diff --git a/src-tauri/src/tray.rs b/src-tauri/src/tray.rs index 39cfcb008..242a4b595 100644 --- a/src-tauri/src/tray.rs +++ b/src-tauri/src/tray.rs @@ -4,20 +4,37 @@ use crate::managers::transcription::TranscriptionManager; use crate::settings; use crate::tray_i18n::get_tray_translations; use log::{error, info, warn}; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use tauri::image::Image; use tauri::menu::{CheckMenuItem, Menu, MenuItem, PredefinedMenuItem, Submenu}; use tauri::tray::TrayIcon; use tauri::{AppHandle, Manager, Theme}; use tauri_plugin_clipboard_manager::ClipboardExt; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum TrayIconState { Idle, Recording, Transcribing, } +/// Tauri managed state holding the last icon state set via `change_tray_icon`. +pub struct CurrentTrayIconState(pub Mutex); + +impl CurrentTrayIconState { + pub fn new() -> Self { + Self(Mutex::new(TrayIconState::Idle)) + } + + pub fn get(&self) -> TrayIconState { + *self.0.lock().unwrap() + } + + fn set(&self, state: TrayIconState) { + *self.0.lock().unwrap() = state; + } +} + #[derive(Clone, Debug, PartialEq)] pub enum AppTheme { Dark, @@ -66,7 +83,10 @@ pub fn change_tray_icon(app: &AppHandle, icon: TrayIconState) { let tray = app.state::(); let theme = get_current_theme(app); - let icon_path = get_icon_path(theme, icon.clone()); + // Store current state + app.state::().set(icon); + + let icon_path = get_icon_path(theme, icon); let _ = tray.set_icon(Some( Image::from_path( @@ -78,10 +98,11 @@ pub fn change_tray_icon(app: &AppHandle, icon: TrayIconState) { )); // Update menu based on state - update_tray_menu(app, &icon, None); + update_tray_menu(app, None); } -pub fn update_tray_menu(app: &AppHandle, state: &TrayIconState, locale: Option<&str>) { +pub fn update_tray_menu(app: &AppHandle, locale: Option<&str>) { + let state = app.state::().get(); let settings = settings::get_settings(app); let locale = locale.unwrap_or(&settings.app_language);