diff --git a/desktop/tauri/src-tauri/Cargo.lock b/desktop/tauri/src-tauri/Cargo.lock index a6d2c84b..78940eec 100644 --- a/desktop/tauri/src-tauri/Cargo.lock +++ b/desktop/tauri/src-tauri/Cargo.lock @@ -210,6 +210,7 @@ dependencies = [ "assert_matches", "cached", "ctor", + "dark-light", "dataurl", "dirs 1.0.5", "futures-util", @@ -227,7 +228,7 @@ dependencies = [ "open", "reqwest 0.12.5", "rfd", - "rust-ini", + "rust-ini 0.20.0", "serde", "serde_json", "sha", @@ -1634,6 +1635,22 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "dark-light" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a76fa97167fa740dcdbfe18e8895601e1bc36525f09b044e00916e717c03a3c" +dependencies = [ + "dconf_rs", + "detect-desktop-environment", + "dirs 4.0.0", + "objc", + "rust-ini 0.18.0", + "web-sys", + "winreg 0.10.1", + "zbus", +] + [[package]] name = "darling" version = "0.14.4" @@ -1744,6 +1761,12 @@ dependencies = [ "url", ] +[[package]] +name = "dconf_rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7046468a81e6a002061c01e6a7c83139daf91b11c30e66795b13217c2d885c8b" + [[package]] name = "der" version = "0.7.9" @@ -1818,6 +1841,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "detect-desktop-environment" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21d8ad60dd5b13a4ee6bd8fa2d5d88965c597c67bce32b5fc49c94f55cb50810" + [[package]] name = "deunicode" version = "1.6.0" @@ -1869,13 +1898,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -1888,6 +1926,17 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users 0.4.5", + "winapi", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -1940,6 +1989,12 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + [[package]] name = "dlv-list" version = "0.5.2" @@ -4821,13 +4876,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list 0.3.0", + "hashbrown 0.12.3", +] + [[package]] name = "ordered-multimap" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" dependencies = [ - "dlv-list", + "dlv-list 0.5.2", "hashbrown 0.14.5", ] @@ -6124,6 +6189,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap 0.4.3", +] + [[package]] name = "rust-ini" version = "0.20.0" @@ -6131,7 +6206,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e0698206bcb8882bf2a9ecb4c1e7785db57ff052297085a6efd4fe42302068a" dependencies = [ "cfg-if", - "ordered-multimap", + "ordered-multimap 0.7.3", ] [[package]] @@ -9416,6 +9491,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "winreg" version = "0.50.0" diff --git a/desktop/tauri/src-tauri/Cargo.toml b/desktop/tauri/src-tauri/Cargo.toml index 02ca6ee1..aef1abe3 100644 --- a/desktop/tauri/src-tauri/Cargo.toml +++ b/desktop/tauri/src-tauri/Cargo.toml @@ -53,6 +53,8 @@ reqwest = { version = "0.12" } rfd = { version = "*", default-features = false, features = [ "tokio", "gtk3", "common-controls-v6" ] } open = "5.1.3" +dark-light = "1.1.1" + # Linux only [target.'cfg(target_os = "linux")'.dependencies] glib = "0.18.4" diff --git a/desktop/tauri/src-tauri/src/main.rs b/desktop/tauri/src-tauri/src/main.rs index 515df217..584326e1 100644 --- a/desktop/tauri/src-tauri/src/main.rs +++ b/desktop/tauri/src-tauri/src/main.rs @@ -20,7 +20,6 @@ mod window; use log::{debug, error, info}; use portmaster::PortmasterExt; -use tauri_plugin_window_state::{AppHandleExt, StateFlags, WindowExt}; use traymenu::setup_tray_menu; use window::{close_splash_window, create_main_window}; diff --git a/desktop/tauri/src-tauri/src/service/mod.rs b/desktop/tauri/src-tauri/src/service/mod.rs index b14efce7..7dd03e7b 100644 --- a/desktop/tauri/src-tauri/src/service/mod.rs +++ b/desktop/tauri/src-tauri/src/service/mod.rs @@ -46,6 +46,7 @@ pub trait ServiceManager { fn start(&self) -> Result; } +#[allow(dead_code)] struct EmptyServiceManager(); impl ServiceManager for EmptyServiceManager { diff --git a/desktop/tauri/src-tauri/src/traymenu.rs b/desktop/tauri/src-tauri/src/traymenu.rs index 2d3da537..0fbd8912 100644 --- a/desktop/tauri/src-tauri/src/traymenu.rs +++ b/desktop/tauri/src-tauri/src/traymenu.rs @@ -41,12 +41,56 @@ lazy_static! { const PM_TRAY_ICON_ID: &'static str = "pm_icon"; // Icons -const BLUE_ICON: &'static [u8] = include_bytes!("../../../../assets/data/icons/pm_light_blue.ico"); -const RED_ICON: &'static [u8] = include_bytes!("../../../../assets/data/icons/pm_light_red.ico"); -const YELLOW_ICON: &'static [u8] = - include_bytes!("../../../../assets/data/icons/pm_light_yellow.ico"); -const GREEN_ICON: &'static [u8] = - include_bytes!("../../../../assets/data/icons/pm_light_green.ico"); + +fn get_green_icon() -> &'static [u8] { + const LIGHT_GREEN_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_light_green.ico"); + const DARK_GREEN_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_dark_green.ico"); + + let mode = dark_light::detect(); + match mode { + dark_light::Mode::Light => DARK_GREEN_ICON, + _ => LIGHT_GREEN_ICON, + } +} + +fn get_blue_icon() -> &'static [u8] { + const LIGHT_BLUE_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_light_blue.ico"); + const DARK_BLUE_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_dark_blue.ico"); + let mode = dark_light::detect(); + match mode { + dark_light::Mode::Light => DARK_BLUE_ICON, + _ => LIGHT_BLUE_ICON, + } +} + +fn get_red_icon() -> &'static [u8] { + const LIGHT_RED_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_light_red.ico"); + const DARK_RED_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_dark_red.ico"); + let mode = dark_light::detect(); + match mode { + dark_light::Mode::Light => DARK_RED_ICON, + _ => LIGHT_RED_ICON, + } +} + +fn get_yellow_icon() -> &'static [u8] { + const LIGHT_YELLOW_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_light_yellow.ico"); + + const DARK_YELLOW_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_dark_yellow.ico"); + let mode = dark_light::detect(); + match mode { + dark_light::Mode::Light => DARK_YELLOW_ICON, + _ => LIGHT_YELLOW_ICON, + } +} pub fn setup_tray_menu( app: &mut tauri::App, @@ -105,7 +149,7 @@ pub fn setup_tray_menu( .build()?; let icon = TrayIconBuilder::with_id(PM_TRAY_ICON_ID) - .icon(Image::from_bytes(RED_ICON).unwrap()) + .icon(Image::from_bytes(get_red_icon()).unwrap()) .menu(&menu) .on_menu_event(move |app, event| match event.id().as_ref() { "exit_ui" => { @@ -205,11 +249,11 @@ pub fn update_icon(icon: AppIcon, subsystems: HashMap, spn_st } let next_icon = match failure.0 { - subsystem::FAILURE_WARNING => YELLOW_ICON, - subsystem::FAILURE_ERROR => RED_ICON, + subsystem::FAILURE_WARNING => get_yellow_icon(), + subsystem::FAILURE_ERROR => get_red_icon(), _ => match spn_status.as_str() { - "connected" | "connecting" => BLUE_ICON, - _ => GREEN_ICON, + "connected" | "connecting" => get_blue_icon(), + _ => get_green_icon(), }, }; @@ -289,7 +333,7 @@ pub async fn tray_handler(cli: PortAPI, app: tauri::AppHandle) { } }; - _ = icon.set_icon(Some(Image::from_bytes(BLUE_ICON).unwrap())); + _ = icon.set_icon(Some(Image::from_bytes(get_blue_icon()).unwrap())); let mut subsystems: HashMap = HashMap::new(); let mut spn_status: String = "".to_string(); @@ -407,7 +451,7 @@ pub async fn tray_handler(cli: PortAPI, app: tauri::AppHandle) { } update_spn_ui_state(false); - _ = icon.set_icon(Some(Image::from_bytes(RED_ICON).unwrap())); + _ = icon.set_icon(Some(Image::from_bytes(get_red_icon()).unwrap())); } fn update_spn_ui_state(enabled: bool) { diff --git a/desktop/tauri/src-tauri/src/window.rs b/desktop/tauri/src-tauri/src/window.rs index 2aa58344..6e078d63 100644 --- a/desktop/tauri/src-tauri/src/window.rs +++ b/desktop/tauri/src-tauri/src/window.rs @@ -1,11 +1,15 @@ use log::{debug, error}; use tauri::{ - AppHandle, Listener, Manager, Result, Theme, UserAttentionType, WebviewUrl, WebviewWindow, - WebviewWindowBuilder, + image::Image, AppHandle, Listener, Manager, Result, Theme, UserAttentionType, WebviewUrl, + WebviewWindow, WebviewWindowBuilder, }; use crate::portmaster::PortmasterExt; +const LIGHT_PM_ICON: &'static [u8] = + include_bytes!("../../../../assets/data/icons/pm_light_512.png"); +const DARK_PM_ICON: &'static [u8] = include_bytes!("../../../../assets/data/icons/pm_dark_512.png"); + /// Either returns the existing "main" window or creates a new one. /// /// The window is not automatically shown (i.e it starts hidden). @@ -47,6 +51,11 @@ pub fn create_main_window(app: &AppHandle) -> Result { // If the window is not yet navigated to the Portmaster UI, do it now. may_navigate_to_ui(&mut window, false); + let _ = match dark_light::detect() { + dark_light::Mode::Light => window.set_icon(Image::from_bytes(DARK_PM_ICON).unwrap()), + _ => window.set_icon(Image::from_bytes(LIGHT_PM_ICON).unwrap()), + }; + #[cfg(debug_assertions)] if let Ok(_) = std::env::var("TAURI_SHOW_IMMEDIATELY") { debug!("[tauri] TAURI_SHOW_IMMEDIATELY is set, opening window");