From 039f44b7b1ecd411e3b3406aa28ccb8e8a0ec63a Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Fri, 25 Apr 2025 15:30:53 -0300 Subject: [PATCH] fix(core): fix TrayIcon.getById returning new resource IDs (#13307) * fix(core): fix TrayIcon.getById returning new resource IDs this prevents the close() from working properly if you somehow lose the new() resource ID (for instance when the app reloads) and need to pick it up again and close it. * cleanup on close --- .changes/fix-tray-get-by-id.md | 5 +++++ crates/tauri/src/tray/mod.rs | 7 +++++++ crates/tauri/src/tray/plugin.rs | 30 ++++++++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 .changes/fix-tray-get-by-id.md diff --git a/.changes/fix-tray-get-by-id.md b/.changes/fix-tray-get-by-id.md new file mode 100644 index 000000000..13474ce8f --- /dev/null +++ b/.changes/fix-tray-get-by-id.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:bug +--- + +Fix `TrayIcon.getById` returning a new resource ID instead of reusing a previously created id from `TrayIcon.new`. diff --git a/crates/tauri/src/tray/mod.rs b/crates/tauri/src/tray/mod.rs index 8f900ab8e..472f42bfc 100644 --- a/crates/tauri/src/tray/mod.rs +++ b/crates/tauri/src/tray/mod.rs @@ -598,6 +598,13 @@ impl TrayIcon { impl Resource for TrayIcon { fn close(self: std::sync::Arc) { + self + .app_handle + .state::() + .icons + .lock() + .unwrap() + .remove(&self.id.0); self.app_handle.remove_tray_by_id(&self.id); } } diff --git a/crates/tauri/src/tray/plugin.rs b/crates/tauri/src/tray/plugin.rs index ff7686403..1e1a057f3 100644 --- a/crates/tauri/src/tray/plugin.rs +++ b/crates/tauri/src/tray/plugin.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT -use std::path::PathBuf; +use std::{collections::HashMap, path::PathBuf, sync::Mutex}; use serde::Deserialize; @@ -14,11 +14,15 @@ use crate::{ plugin::{Builder, TauriPlugin}, resources::ResourceId, tray::TrayIconBuilder, - AppHandle, Manager, Runtime, Webview, + AppHandle, Manager, Runtime, State, Webview, }; use super::{TrayIcon, TrayIconEvent}; +pub(crate) struct TrayIcons { + pub(crate) icons: Mutex>, +} + #[derive(Deserialize)] #[serde(rename_all = "camelCase")] struct TrayIconOptions { @@ -36,6 +40,7 @@ struct TrayIconOptions { #[command(root = "crate")] fn new( webview: Webview, + icons: State<'_, TrayIcons>, options: TrayIconOptions, handler: Channel, ) -> crate::Result<(ResourceId, String)> { @@ -91,6 +96,8 @@ fn new( let id = tray.id().as_ref().to_string(); let rid = resources_table.add(tray); + icons.icons.lock().unwrap().insert(id.clone(), rid); + Ok((rid, id)) } @@ -98,13 +105,26 @@ fn new( fn get_by_id( app: AppHandle, webview: Webview, + icons: State<'_, TrayIcons>, id: &str, ) -> crate::Result> { + // if the icon was created by this plugin, return the resource id + // this lets a getById call match the rid of a TrayIcon.new call + // which allows it to close a previously created icon + if let Some(rid) = icons.icons.lock().unwrap().get(id) { + return Ok(Some(*rid)); + } + let tray = app.tray_by_id(id); let maybe_rid = tray.map(|tray| { let mut resources_table = webview.resources_table(); resources_table.add(tray) }); + + if let Some(rid) = maybe_rid { + icons.icons.lock().unwrap().insert(id.to_string(), rid); + } + Ok(maybe_rid) } @@ -226,6 +246,12 @@ fn set_show_menu_on_left_click( pub(crate) fn init() -> TauriPlugin { Builder::new("tray") + .setup(|app, _api| { + app.manage(TrayIcons { + icons: Default::default(), + }); + Ok(()) + }) .invoke_handler(crate::generate_handler![ #![plugin(tray)] new,