From 3d567d1bed82b473c31df7734d330f3a05ee3c10 Mon Sep 17 00:00:00 2001 From: "zed-zippy[bot]" <234243425+zed-zippy[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 09:24:41 +0000 Subject: [PATCH] agent_ui: Fix panic in load/copy thread to/from clipboard (#49694) (cherry-pick to stable) (#49696) Cherry-pick of #49694 to stable ---- Fixes ZED-4VW Release Notes: - N/A *or* Added/Fixed/Improved ... Co-authored-by: Lukas Wirth --- crates/agent_ui/src/agent_panel.rs | 88 ++++++++++-------------------- 1 file changed, 29 insertions(+), 59 deletions(-) diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index 0ce6bd16a8fff708e594417f8dbd0bff45b8b0f7..972b8abf271ed72393498e5740bc47ff4d63b08c 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -1209,19 +1209,7 @@ impl AgentPanel { fn copy_thread_to_clipboard(&mut self, window: &mut Window, cx: &mut Context) { let Some(thread) = self.active_native_agent_thread(cx) else { - if let Some(workspace) = self.workspace.upgrade() { - workspace.update(cx, |workspace, cx| { - struct NoThreadToast; - workspace.show_toast( - workspace::Toast::new( - workspace::notifications::NotificationId::unique::(), - "No active native thread to copy", - ) - .autohide(), - cx, - ); - }); - } + Self::show_deferred_toast(&self.workspace, "No active native thread to copy", cx); return; }; @@ -1256,38 +1244,37 @@ impl AgentPanel { .detach_and_log_err(cx); } - fn load_thread_from_clipboard(&mut self, window: &mut Window, cx: &mut Context) { - let Some(clipboard) = cx.read_from_clipboard() else { - if let Some(workspace) = self.workspace.upgrade() { + fn show_deferred_toast( + workspace: &WeakEntity, + message: &'static str, + cx: &mut App, + ) { + let workspace = workspace.clone(); + cx.defer(move |cx| { + if let Some(workspace) = workspace.upgrade() { workspace.update(cx, |workspace, cx| { - struct NoClipboardToast; + struct ClipboardToast; workspace.show_toast( workspace::Toast::new( - workspace::notifications::NotificationId::unique::(), - "No clipboard content available", + workspace::notifications::NotificationId::unique::(), + message, ) .autohide(), cx, ); }); } + }); + } + + fn load_thread_from_clipboard(&mut self, window: &mut Window, cx: &mut Context) { + let Some(clipboard) = cx.read_from_clipboard() else { + Self::show_deferred_toast(&self.workspace, "No clipboard content available", cx); return; }; let Some(encoded) = clipboard.text() else { - if let Some(workspace) = self.workspace.upgrade() { - workspace.update(cx, |workspace, cx| { - struct InvalidClipboardToast; - workspace.show_toast( - workspace::Toast::new( - workspace::notifications::NotificationId::unique::(), - "Clipboard does not contain text", - ) - .autohide(), - cx, - ); - }); - } + Self::show_deferred_toast(&self.workspace, "Clipboard does not contain text", cx); return; }; @@ -1295,19 +1282,11 @@ impl AgentPanel { { Ok(data) => data, Err(_) => { - if let Some(workspace) = self.workspace.upgrade() { - workspace.update(cx, |workspace, cx| { - struct DecodeErrorToast; - workspace.show_toast( - workspace::Toast::new( - workspace::notifications::NotificationId::unique::(), - "Failed to decode clipboard content (expected base64)", - ) - .autohide(), - cx, - ); - }); - } + Self::show_deferred_toast( + &self.workspace, + "Failed to decode clipboard content (expected base64)", + cx, + ); return; } }; @@ -1315,20 +1294,11 @@ impl AgentPanel { let shared_thread = match SharedThread::from_bytes(&thread_data) { Ok(thread) => thread, Err(_) => { - if let Some(workspace) = self.workspace.upgrade() { - workspace.update(cx, |workspace, cx| { - struct ParseErrorToast; - workspace.show_toast( - workspace::Toast::new( - workspace::notifications::NotificationId::unique::( - ), - "Failed to parse thread data from clipboard", - ) - .autohide(), - cx, - ); - }); - } + Self::show_deferred_toast( + &self.workspace, + "Failed to parse thread data from clipboard", + cx, + ); return; } };