From 8f9e83c231262e185a01c10bcde4e10cf3211fea Mon Sep 17 00:00:00 2001 From: Uriel Date: Mon, 14 Oct 2024 18:22:08 +0200 Subject: [PATCH] add runtime check for appindicator on linux (#1193) --- .gitignore | 2 + Cargo.lock | 199 +++++++++++++----- gui/src-tauri/Cargo.toml | 3 + gui/src-tauri/src/main.rs | 6 +- gui/src-tauri/src/tray.rs | 36 +++- gui/src/components/TopBar.tsx | 5 +- .../settings/pages/InterfaceSettings.tsx | 47 +++-- gui/src/i18n/config.tsx | 3 +- gui/src/utils/tauri.ts | 5 +- 9 files changed, 227 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index aaa77a2856..d869932661 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,8 @@ /node_modules .husky +# kotlin stuff +/.kotlin # ignore gradle build folder build/ diff --git a/Cargo.lock b/Cargo.lock index 02f2168e0a..2c3cd46f2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -412,9 +412,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "byteorder" @@ -506,9 +506,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "jobserver", "libc", @@ -1239,12 +1239,11 @@ dependencies = [ [[package]] name = "flexi_logger" -version = "0.29.2" +version = "0.29.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c6e500462d7c5ee8b974423b55bd47f3e09c8306050e5bbeaccaf2b17992f70" +checksum = "719236bdbcf6033a3395165f797076b31056018e6723ccff616eb25fc9c99de1" dependencies = [ "chrono", - "glob", "log", "nu-ansi-term", "regex", @@ -2069,9 +2068,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -2467,7 +2466,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ "malloc_buf", - "objc_exception", ] [[package]] @@ -2475,6 +2473,9 @@ name = "objc-sys" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" +dependencies = [ + "cc", +] [[package]] name = "objc2" @@ -2502,6 +2503,30 @@ dependencies = [ "objc2-quartz-core", ] +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + [[package]] name = "objc2-core-data" version = "0.2.2" @@ -2526,6 +2551,18 @@ dependencies = [ "objc2-metal", ] +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + [[package]] name = "objc2-encode" version = "4.0.3" @@ -2545,6 +2582,18 @@ dependencies = [ "objc2", ] +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + [[package]] name = "objc2-metal" version = "0.2.2" @@ -2571,21 +2620,71 @@ dependencies = [ ] [[package]] -name = "objc_exception" -version = "0.1.2" +name = "objc2-symbols" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "cc", + "objc2", + "objc2-foundation", ] [[package]] -name = "objc_id" -version = "0.1.1" +name = "objc2-ui-kit" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "objc", + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-web-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bc69301064cebefc6c4c90ce9cba69225239e4b8ff99d445a2b5563797da65" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", ] [[package]] @@ -2713,9 +2812,9 @@ dependencies = [ [[package]] name = "pathdiff" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" [[package]] name = "percent-encoding" @@ -3593,6 +3692,7 @@ dependencies = [ "discord-sdk", "flexi_logger", "glob", + "libloading 0.8.5", "log", "log-panics", "open", @@ -3846,9 +3946,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tauri" -version = "2.0.2" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5920aad0804ea5e86808d4b6e8753d3bcbae7efc8f4e41a4da00b45427559868" +checksum = "fd96d46534b10765ce0c6208f9451d98ea38636364a41b272d3610c70dd0e4c3" dependencies = [ "anyhow", "bytes", @@ -4071,9 +4171,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af12ad1af974b274ef1d32a94e6eba27a312b429ef28fcb98abc710df7f9151d" +checksum = "c8f437293d6f5e5dce829250f4dbdce4e0b52905e297a6689cc2963eb53ac728" dependencies = [ "dpi", "gtk", @@ -4090,9 +4190,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45e88aa0b11b302d836e6ea3e507a6359044c4a8bc86b865ba99868c695753d" +checksum = "aaac63b65df8e85570993eaf93ae1dd73a6fb66d8bd99674ce65f41dc3c63e7d" dependencies = [ "gtk", "http", @@ -4430,9 +4530,9 @@ dependencies = [ [[package]] name = "tray-icon" -version = "0.19.0" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533fc2d4105e0e3d96ce1c71f2d308c9fbbe2ef9c587cab63dd627ab5bde218f" +checksum = "7c92af36a182b46206723bdf8a7942e20838cde1cf062e5b97854d57eb01763b" dependencies = [ "core-graphics", "crossbeam-channel", @@ -4704,9 +4804,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -4715,9 +4815,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -4730,9 +4830,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.43" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -4742,9 +4842,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4752,9 +4852,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -4765,9 +4865,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" @@ -4844,9 +4944,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -5333,14 +5433,12 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "wry" -version = "0.44.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "440600584cfbd8b0d28eace95c1f2c253db05dae43780b79380aa1e868f04c73" +checksum = "469a3765ecc3e8aa9ccdf3c5a52c82697ec03037cd60494488763880d31a1b3a" dependencies = [ "base64 0.22.1", - "block", - "cocoa", - "core-graphics", + "block2", "crossbeam-channel", "dpi", "dunce", @@ -5353,8 +5451,11 @@ dependencies = [ "kuchikiki", "libc", "ndk", - "objc", - "objc_id", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", "once_cell", "percent-encoding", "raw-window-handle", diff --git a/gui/src-tauri/Cargo.toml b/gui/src-tauri/Cargo.toml index 693c8824ca..b42e91bffb 100644 --- a/gui/src-tauri/Cargo.toml +++ b/gui/src-tauri/Cargo.toml @@ -57,3 +57,6 @@ tokio = { version = "1.37.0", features = ["time"] } [target.'cfg(windows)'.dependencies] win32job = "1" winreg = "0.52" + +[target.'cfg(target_os = "linux")'.dependencies] +libloading = "0.8" diff --git a/gui/src-tauri/src/main.rs b/gui/src-tauri/src/main.rs index 982695ad2b..d319286f95 100644 --- a/gui/src-tauri/src/main.rs +++ b/gui/src-tauri/src/main.rs @@ -180,6 +180,7 @@ fn main() -> Result<()> { warning, tray::update_translations, tray::update_tray_text, + tray::is_tray_available, presence::discord_client_exists, presence::update_presence, presence::clear_presence, @@ -209,11 +210,12 @@ fn main() -> Result<()> { window_state.update_window(&window.as_ref().window(), false)?; } - #[cfg(desktop)] - { + if cfg!(desktop) { let handle = app.handle(); tray::create_tray(handle)?; presence::create_presence(handle)?; + } else { + app.manage(tray::TrayAvailable(false)); } app.manage(Mutex::new(window_state)); diff --git a/gui/src-tauri/src/tray.rs b/gui/src-tauri/src/tray.rs index 0b9d67adf6..0f741e1275 100644 --- a/gui/src-tauri/src/tray.rs +++ b/gui/src-tauri/src/tray.rs @@ -8,6 +8,7 @@ use tauri::{ }; pub struct TrayMenu(Menu); +pub struct TrayAvailable(pub bool); pub struct TrayTranslations { store: Mutex>, @@ -21,11 +22,16 @@ impl TrayTranslations { } } +#[tauri::command] +pub fn is_tray_available(tray_available: State) -> bool { + tray_available.0 +} + #[tauri::command] pub fn update_translations( app: AppHandle, i18n: State, - menu: State>, + menu: State>>, new_i18n: HashMap, ) -> color_eyre::Result<(), String> { { @@ -44,8 +50,11 @@ pub fn update_translations( pub fn update_tray_text( app: AppHandle, i18n: State, - menu: State>, + menu: State>>, ) -> color_eyre::Result<(), String> { + let Some(menu) = menu.as_ref() else { + return Ok(()); + }; if let Some((window, MenuItemKind::MenuItem(toggle_i))) = app.get_webview_window("main").zip(menu.0.get("toggle")) { @@ -67,6 +76,26 @@ pub fn update_tray_text( } pub fn create_tray(app: &tauri::AppHandle) -> tauri::Result<()> { + #[cfg(target_os = "linux")] + unsafe { + const LIBS_TO_CHECK: &[&str] = &[ + "libayatana-appindicator3.so.1", + "libappindicator3.so.1", + "libayatana-appindicator3.so", + "libappindicator3.so", + ]; + let found = LIBS_TO_CHECK + .iter() + .any(|lib| libloading::Library::new(lib).is_ok()); + if !found { + log::warn!( + "libappindicator couldn't be found so tray support has been disabled!" + ); + app.manage(TrayAvailable(false)); + return Ok(()); + } + } + let toggle_i = MenuItemBuilder::with_id("toggle", "Hide").build(app)?; let quit_i = MenuItemBuilder::with_id("quit", "Quit").build(app)?; let menu1 = MenuBuilder::new(app).items(&[&toggle_i, &quit_i]).build()?; @@ -120,7 +149,8 @@ pub fn create_tray(app: &tauri::AppHandle) -> tauri::Result<()> { .menu_on_left_click(false) .build(app)?; - app.manage(TrayMenu(menu1)); + app.manage(TrayAvailable(true)); + app.manage(Some(TrayMenu(menu1))); app.manage(TrayTranslations { store: Default::default(), }); diff --git a/gui/src/components/TopBar.tsx b/gui/src/components/TopBar.tsx index 056dbdc247..2a6684d0c5 100644 --- a/gui/src/components/TopBar.tsx +++ b/gui/src/components/TopBar.tsx @@ -29,6 +29,7 @@ import { listen } from '@tauri-apps/api/event'; import { TrayOrExitModal } from './TrayOrExitModal'; import { error } from '@/utils/logging'; import { useDoubleTap } from 'use-double-tap'; +import { isTrayAvailable } from '@/utils/tauri'; export function VersionTag() { return ( @@ -74,7 +75,7 @@ export function TopBar({ await getCurrentWebviewWindow().close(); }; const tryCloseApp = async (dontTray = false) => { - if (isTauri && config?.useTray === null) { + if (isTrayAvailable && config?.useTray === null) { setShowTrayOrExitModal(true); return; } @@ -101,7 +102,7 @@ export function TopBar({ const window = getCurrentWebviewWindow(); await window.show(); await window.setFocus(); - await invoke('update_tray_text'); + if (isTrayAvailable) await invoke('update_tray_text'); await tryCloseApp(true); }); return () => { diff --git a/gui/src/components/settings/pages/InterfaceSettings.tsx b/gui/src/components/settings/pages/InterfaceSettings.tsx index 58956b5ce9..5ce0fefbb9 100644 --- a/gui/src/components/settings/pages/InterfaceSettings.tsx +++ b/gui/src/components/settings/pages/InterfaceSettings.tsx @@ -16,6 +16,7 @@ import { LangSelector } from '@/components/commons/LangSelector'; import { BellIcon } from '@/components/commons/icon/BellIcon'; import { Range } from '@/components/commons/Range'; import { Dropdown } from '@/components/commons/Dropdown'; +import { isTrayAvailable } from '@/utils/tauri'; interface InterfaceSettingsForm { appearance: { @@ -195,27 +196,31 @@ export function InterfaceSettings() { /> - - {l10n.getString('settings-general-interface-use_tray')} - -
- - {l10n.getString( - 'settings-general-interface-use_tray-description' - )} - -
-
- -
+ {isTrayAvailable && ( + <> + + {l10n.getString('settings-general-interface-use_tray')} + +
+ + {l10n.getString( + 'settings-general-interface-use_tray-description' + )} + +
+
+ +
+ + )} {l10n.getString('settings-general-interface-discord_presence')} diff --git a/gui/src/i18n/config.tsx b/gui/src/i18n/config.tsx index 3c24c54c50..66baa1c516 100644 --- a/gui/src/i18n/config.tsx +++ b/gui/src/i18n/config.tsx @@ -12,6 +12,7 @@ import { import { exists, readTextFile, BaseDirectory } from '@tauri-apps/plugin-fs'; import { error } from '@/utils/logging'; import { invoke } from '@tauri-apps/api/core'; +import { isTrayAvailable } from '@/utils/tauri'; export const defaultNS = 'translation'; export const DEFAULT_LOCALE = 'en'; @@ -200,7 +201,7 @@ export function AppLocalizationProvider(props: AppLocalizationProviderProps) { }, []); useEffect(() => { - if (l10n === null) return; + if (l10n === null || !isTrayAvailable) return; const newI18n: Record = {}; TRAY_MENU_KEYS.forEach((key) => { diff --git a/gui/src/utils/tauri.ts b/gui/src/utils/tauri.ts index 2b3f71fc34..ab9905ed01 100644 --- a/gui/src/utils/tauri.ts +++ b/gui/src/utils/tauri.ts @@ -1,4 +1,4 @@ -import { isTauri } from '@tauri-apps/api/core'; +import { invoke, isTauri } from '@tauri-apps/api/core'; import { type } from '@tauri-apps/plugin-os'; /** @@ -14,3 +14,6 @@ export async function fetchResourceUrl(url: string) { // FIXME: For some fucking reason, you can't top-level await on a react component file // on Chromium on developments builds specifically -Uriel export const AUTOBONE_VIDEO = await fetchResourceUrl('/videos/autobone.webm'); + +export const isTrayAvailable = + isTauri() && (await invoke('is_tray_available'));