diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 5e753a3e..119cb658 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -10,8 +10,10 @@ pub(crate) mod logging; mod lib_commands; #[cfg(target_os = "windows")] mod taskbar_win; +mod tray_runtime; pub(crate) use analysis_runtime::*; +pub(crate) use tray_runtime::*; use std::collections::HashMap; use std::sync::{Arc, Mutex, OnceLock, RwLock}; @@ -65,71 +67,6 @@ fn sync_cancel_flags() -> &'static Mutex>> { FLAGS.get_or_init(|| Mutex::new(HashMap::new())) } -/// Holds the live system-tray icon handle. `None` means the tray is currently hidden/removed. -/// Dropping the inner `TrayIcon` fully removes it from the OS notification area on all platforms. -type TrayState = Mutex>; - -/// Cached tray tooltip text. Updated by `set_tray_tooltip` and re-applied when the -/// icon is rebuilt (e.g. after the user toggles the tray off and on again). -/// Empty string means "use the default `Psysonic` tooltip". -type TrayTooltip = Mutex; - -#[derive(Default)] -struct TrayPlaybackState(Mutex); - -fn tray_state_icon(state: &str) -> &'static str { - match state { - "play" => "▶", - "pause" => "⏸", - _ => "⏹", - } -} - -/// Handles to all updatable tray menu items, kept around so `set_tray_menu_labels` -/// (i18n refresh) and `set_tray_tooltip` (track change) can re-text them without -/// rebuilding the whole tray icon. The `now_playing` slot is `Some` on Linux -/// only — it surfaces the current track as a disabled menu entry because -/// AppIndicator has no hover tooltip API. -struct TrayMenuItems { - play_pause: tauri::menu::MenuItem, - next: tauri::menu::MenuItem, - previous: tauri::menu::MenuItem, - show_hide: tauri::menu::MenuItem, - quit: tauri::menu::MenuItem, - #[cfg_attr(not(target_os = "linux"), allow(dead_code))] - now_playing: Option>, -} - -type TrayMenuItemsState = Mutex>; - -/// Cached translations for the tray menu. Defaults to English so the menu has -/// readable labels before the frontend has had a chance to run `set_tray_menu_labels`. -#[derive(Clone)] -struct TrayMenuLabels { - play_pause: String, - next: String, - previous: String, - show_hide: String, - quit: String, - #[cfg_attr(not(target_os = "linux"), allow(dead_code))] - nothing_playing: String, -} - -impl Default for TrayMenuLabels { - fn default() -> Self { - Self { - play_pause: "Play / Pause".into(), - next: "Next Track".into(), - previous: "Previous Track".into(), - show_hide: "Show / Hide".into(), - quit: "Exit Psysonic".into(), - nothing_playing: "Nothing playing".into(), - } - } -} - -type TrayMenuLabelsState = Mutex; - /// Shared handle to OS media controls (MPRIS2 on Linux, Now Playing on macOS, SMTC on Windows). /// `None` if souvlaki failed to initialize (e.g. no D-Bus session on Linux). type MprisControls = Mutex>; diff --git a/src-tauri/src/tray_runtime.rs b/src-tauri/src/tray_runtime.rs new file mode 100644 index 00000000..b6e56044 --- /dev/null +++ b/src-tauri/src/tray_runtime.rs @@ -0,0 +1,68 @@ +use std::sync::Mutex; + +use tauri::tray::TrayIcon; + +/// Holds the live system-tray icon handle. `None` means the tray is currently hidden/removed. +/// Dropping the inner `TrayIcon` fully removes it from the OS notification area on all platforms. +pub(crate) type TrayState = Mutex>; + +/// Cached tray tooltip text. Updated by `set_tray_tooltip` and re-applied when the +/// icon is rebuilt (e.g. after the user toggles the tray off and on again). +/// Empty string means "use the default `Psysonic` tooltip". +pub(crate) type TrayTooltip = Mutex; + +#[derive(Default)] +pub(crate) struct TrayPlaybackState(pub(crate) Mutex); + +pub(crate) fn tray_state_icon(state: &str) -> &'static str { + match state { + "play" => "▶", + "pause" => "⏸", + _ => "⏹", + } +} + +/// Handles to all updatable tray menu items, kept around so `set_tray_menu_labels` +/// (i18n refresh) and `set_tray_tooltip` (track change) can re-text them without +/// rebuilding the whole tray icon. The `now_playing` slot is `Some` on Linux +/// only — it surfaces the current track as a disabled menu entry because +/// AppIndicator has no hover tooltip API. +pub(crate) struct TrayMenuItems { + pub(crate) play_pause: tauri::menu::MenuItem, + pub(crate) next: tauri::menu::MenuItem, + pub(crate) previous: tauri::menu::MenuItem, + pub(crate) show_hide: tauri::menu::MenuItem, + pub(crate) quit: tauri::menu::MenuItem, + #[cfg_attr(not(target_os = "linux"), allow(dead_code))] + pub(crate) now_playing: Option>, +} + +pub(crate) type TrayMenuItemsState = Mutex>; + +/// Cached translations for the tray menu. Defaults to English so the menu has +/// readable labels before the frontend has had a chance to run `set_tray_menu_labels`. +#[derive(Clone)] +pub(crate) struct TrayMenuLabels { + pub(crate) play_pause: String, + pub(crate) next: String, + pub(crate) previous: String, + pub(crate) show_hide: String, + pub(crate) quit: String, + #[cfg_attr(not(target_os = "linux"), allow(dead_code))] + pub(crate) nothing_playing: String, +} + +impl Default for TrayMenuLabels { + fn default() -> Self { + Self { + play_pause: "Play / Pause".into(), + next: "Next Track".into(), + previous: "Previous Track".into(), + show_hide: "Show / Hide".into(), + quit: "Exit Psysonic".into(), + nothing_playing: "Nothing playing".into(), + } + } +} + +pub(crate) type TrayMenuLabelsState = Mutex;