diff --git a/lib/tray.ts b/lib/tray.ts index b755a1d..969d8b4 100644 --- a/lib/tray.ts +++ b/lib/tray.ts @@ -1,4 +1,5 @@ import * as Sentry from '@sentry/browser' +import { invoke } from '@tauri-apps/api/core' import { Menu } from '@tauri-apps/api/menu' import { MenuItem } from '@tauri-apps/api/menu' import { resolveResource } from '@tauri-apps/api/path' @@ -22,6 +23,21 @@ async function getTray() { return await TrayIcon.getById('main-tray') } +async function resolveTrayIconForTheme() { + let theme: 'light' | 'dark' = 'dark' + try { + const t = (await invoke('get_system_theme')) || 'dark' + theme = t === 'dark' ? 'dark' : 'light' + } catch {} + + console.log('[resolveTrayIconForTheme] theme', theme) + + const pickedPath = theme === 'dark' ? 'icons/favicon/icon.png' : 'icons/favicon/icon-light.png' + console.log('[resolveTrayIconForTheme] pickedPath', pickedPath) + + return await resolveResource(pickedPath) +} + export async function showLoadingTray() { console.log('[showLoadingTray]') @@ -88,7 +104,9 @@ export async function showDefaultTray() { const newMenu = await buildMenu() await tray.setMenu(newMenu) - await tray.setIcon(await resolveResource('icons/favicon/icon.png')) + + const iconPath = await resolveTrayIconForTheme() + await tray.setIcon(iconPath) await tray.setTooltip('Rclone') console.log('[showDefaultTray] tray menu rebuilt') @@ -98,9 +116,10 @@ export async function initTray() { try { console.log('[initTray]') + const initialIcon = await resolveTrayIconForTheme() await TrayIcon.new({ id: 'main-tray', - icon: (await resolveResource('icons/favicon/icon.png'))!, + icon: initialIcon!, tooltip: 'Rclone', menuOnLeftClick: true, action: async (event: TrayIconEvent) => { diff --git a/src-tauri/icons/favicon/icon-light.png b/src-tauri/icons/favicon/icon-light.png new file mode 100644 index 0000000..ad31977 Binary files /dev/null and b/src-tauri/icons/favicon/icon-light.png differ diff --git a/src-tauri/icons/favicon/icon.png b/src-tauri/icons/favicon/icon.png index d93c321..5bed538 100644 Binary files a/src-tauri/icons/favicon/icon.png and b/src-tauri/icons/favicon/icon.png differ diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index a344e30..0c8c703 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -248,6 +248,98 @@ fn get_uid() -> String { return machine_uid::get().unwrap(); } +#[tauri::command] +fn get_system_theme() -> String { + #[cfg(target_os = "macos")] + { + use std::process::Command; + if let Ok(output) = Command::new("defaults") + .args(&["read", "-g", "AppleInterfaceStyle"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + return "light".to_string(); + } + + #[cfg(target_os = "windows")] + { + use std::process::Command; + if let Ok(output) = Command::new("reg").args(&[ + "query", + r"HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", + "/v", + "AppsUseLightTheme", + ]).output() { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("0x0") || out.contains("0x00000000") { + return "dark".to_string(); + } + if out.contains("0x1") || out.contains("0x00000001") { + return "light".to_string(); + } + } + } + return "light".to_string(); + } + + #[cfg(target_os = "linux")] + { + use std::process::Command; + + // GNOME color-scheme (prefer-dark) + if let Ok(output) = Command::new("gsettings") + .args(&["get", "org.gnome.desktop.interface", "color-scheme"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + + // GNOME gtk-theme name contains "dark" + if let Ok(output) = Command::new("gsettings") + .args(&["get", "org.gnome.desktop.interface", "gtk-theme"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + + // KDE color scheme via kreadconfig5 + if let Ok(output) = Command::new("kreadconfig5") + .args(&["--group", "General", "--key", "ColorScheme"]) + .output() + { + if output.status.success() { + let out = String::from_utf8_lossy(&output.stdout).to_ascii_lowercase(); + if out.contains("dark") { + return "dark".to_string(); + } + } + } + + return "light".to_string(); + } + + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))] + { + "dark".to_string() + } +} #[tauri::command] fn is_rclone_running(port: Option) -> bool { @@ -710,7 +802,7 @@ pub fn run() { .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_prevent_default::debug()) - .invoke_handler(tauri::generate_handler![unzip_file, get_arch, get_uid, is_rclone_running, stop_rclone_processes, prompt_password, prompt_text, stop_pid, update_system_rclone, test_proxy_connection, is_tray_supported]) + .invoke_handler(tauri::generate_handler![unzip_file, get_arch, get_uid, is_rclone_running, stop_rclone_processes, prompt_password, prompt_text, stop_pid, update_system_rclone, test_proxy_connection, is_tray_supported, get_system_theme]) .setup(|_app| Ok(())) // .setup(|app| { // if cfg!(debug_assertions) {