From 097047a1ce2b43484a58a9db95498ee1c146db11 Mon Sep 17 00:00:00 2001 From: FTCHD <144691102+FTCHD@users.noreply.github.com> Date: Wed, 8 Oct 2025 13:07:50 +0200 Subject: [PATCH] check tray support on inux Signed-off-by: FTCHD <144691102+FTCHD@users.noreply.github.com> --- main.ts | 40 ++++++++++++++++++++++++++++++++++++++- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 3 +++ src-tauri/src/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/main.ts b/main.ts index 83d7012..3f21200 100644 --- a/main.ts +++ b/main.ts @@ -603,6 +603,43 @@ async function checkVersion() { } catch {} } +async function checkTraySupport() { + let traySupported = false + + try { + traySupported = await invoke('is_tray_supported') + } catch {} + + if (!traySupported) { + const msg = + 'Your desktop environment does not appear to support system tray icons.\n\nRclone UI requires a tray to run. The application will exit automatically in 10 seconds.' + + let alreadyExiting = false + const timer = setTimeout(async () => { + if (alreadyExiting) return + alreadyExiting = true + await exit(0) + }, 10_000) + + ask(msg, { + title: 'Tray Not Supported', + kind: 'error', + okLabel: 'Exit Now', + cancelLabel: 'Cancel', + }) + .then(async (confirmed) => { + if (!alreadyExiting && confirmed) { + alreadyExiting = true + clearTimeout(timer) + await exit(0) + } + }) + .catch() + + await new Promise(() => {}) + } +} + getCurrentWindow().listen('tauri://close-requested', async (e) => { console.log('(main) window close requested') await getCurrentWindow().destroy() @@ -617,7 +654,8 @@ getCurrentWindow().listen('rebuild-tray', async (e) => { await showDefaultTray() }) -initTray() +checkTraySupport() + .then(() => initTray()) .then(() => showLoadingTray()) .then(() => waitForHydration()) .then(() => checkVersion()) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ed1fea5..2445bfb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -284,6 +284,7 @@ dependencies = [ "tauri-plugin-single-instance", "tauri-plugin-store", "tauri-plugin-updater", + "zbus", "zip 0.6.6", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 725b799..f02a2af 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -48,3 +48,6 @@ sysinfo = "0.37" [target.'cfg(target_os = "macos")'.dependencies] cocoa = "0.26" + +[target.'cfg(target_os = "linux")'.dependencies] +zbus = { version = "5" } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 1575038..9762a19 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -14,6 +14,49 @@ use sysinfo::{System}; use tauri_plugin_sentry; use sentry; +#[tauri::command] +fn is_tray_supported() -> bool { + #[cfg(not(target_os = "linux"))] + { + return true; + } + + #[cfg(target_os = "linux")] + { + use zbus::blocking::fdo::DBusProxy; + use zbus::blocking::{Connection, Proxy}; + + let conn = match Connection::session() { + Ok(c) => c, + Err(_) => return false, + }; + + let dbus = match DBusProxy::new(&conn) { + Ok(p) => p, + Err(_) => return false, + }; + + let candidates = [ + "org.kde.StatusNotifierWatcher", + "org.freedesktop.StatusNotifierWatcher", + ]; + + for name in candidates { + if dbus.name_has_owner(name).unwrap_or(false) { + // Try to read the property; if it fails but watcher exists, assume true + if let Ok(proxy) = Proxy::new(&conn, name, "/StatusNotifierWatcher", "org.kde.StatusNotifierWatcher") { + if let Ok(registered) = proxy.get_property::("IsStatusNotifierHostRegistered") { + return registered; + } + } + return true; + } + } + + false + } +} + #[tauri::command] fn unzip_file(zip_path: &str, output_folder: &str) -> Result<(), String> { // Open the zip file @@ -644,7 +687,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]) + .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]) .setup(|_app| Ok(())) // .setup(|app| { // if cfg!(debug_assertions) {