From 56ed5dcc89dfe80349bd265b649a1f252065425f Mon Sep 17 00:00:00 2001 From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com> Date: Mon, 7 Apr 2025 18:58:49 -0300 Subject: [PATCH] agent: Add the history button back in the toolbar and make it a toggle (#28275) Release Notes: - agent: The history view is now more easily accessible via the icon button in the Agent Panel toolbar. --------- Co-authored-by: Bennet Bo Fenner --- crates/agent/src/assistant_panel.rs | 82 +++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 17 deletions(-) diff --git a/crates/agent/src/assistant_panel.rs b/crates/agent/src/assistant_panel.rs index 150cc5b34b..f269d1ca2e 100644 --- a/crates/agent/src/assistant_panel.rs +++ b/crates/agent/src/assistant_panel.rs @@ -178,6 +178,7 @@ pub struct AssistantPanel { configuration_subscription: Option, local_timezone: UtcOffset, active_view: ActiveView, + previous_view: Option, history_store: Entity, history: Entity, assistant_dropdown_menu_handle: PopoverMenuHandle, @@ -292,6 +293,7 @@ impl AssistantPanel { chrono::Local::now().offset().local_minus_utc(), ) .unwrap(), + previous_view: None, history_store: history_store.clone(), history: cx.new(|cx| ThreadHistory::new(weak_self, history_store, window, cx)), assistant_dropdown_menu_handle: PopoverMenuHandle::default(), @@ -337,7 +339,8 @@ impl AssistantPanel { .thread_store .update(cx, |this, cx| this.create_thread(cx)); - self.active_view = ActiveView::thread(thread.clone(), window, cx); + let thread_view = ActiveView::thread(thread.clone(), window, cx); + self.set_active_view(thread_view, window, cx); let message_editor_context_store = cx.new(|_cx| { crate::context_store::ContextStore::new( @@ -400,7 +403,7 @@ impl AssistantPanel { } fn new_prompt_editor(&mut self, window: &mut Window, cx: &mut Context) { - self.active_view = ActiveView::PromptEditor; + self.set_active_view(ActiveView::PromptEditor, window, cx); let context = self .context_store @@ -450,11 +453,16 @@ impl AssistantPanel { } fn open_history(&mut self, window: &mut Window, cx: &mut Context) { - self.thread_store - .update(cx, |thread_store, cx| thread_store.reload(cx)) - .detach_and_log_err(cx); - self.active_view = ActiveView::History; - self.history.focus_handle(cx).focus(window); + if matches!(self.active_view, ActiveView::History) { + if let Some(previous_view) = self.previous_view.take() { + self.set_active_view(previous_view, window, cx); + } + } else { + self.thread_store + .update(cx, |thread_store, cx| thread_store.reload(cx)) + .detach_and_log_err(cx); + self.set_active_view(ActiveView::History, window, cx); + } cx.notify(); } @@ -487,7 +495,7 @@ impl AssistantPanel { cx, ) }); - this.active_view = ActiveView::PromptEditor; + this.set_active_view(ActiveView::PromptEditor, window, cx); this.context_editor = Some(editor); anyhow::Ok(()) @@ -509,7 +517,8 @@ impl AssistantPanel { cx.spawn_in(window, async move |this, cx| { let thread = open_thread_task.await?; this.update_in(cx, |this, window, cx| { - this.active_view = ActiveView::thread(thread.clone(), window, cx); + let thread_view = ActiveView::thread(thread.clone(), window, cx); + this.set_active_view(thread_view, window, cx); let message_editor_context_store = cx.new(|_cx| { crate::context_store::ContextStore::new( this.workspace.clone(), @@ -573,7 +582,7 @@ impl AssistantPanel { let tools = self.thread_store.read(cx).tools(); let fs = self.fs.clone(); - self.active_view = ActiveView::Configuration; + self.set_active_view(ActiveView::Configuration, window, cx); self.configuration = Some(cx.new(|cx| { AssistantConfiguration::new(fs, context_server_manager, tools, window, cx) @@ -701,6 +710,29 @@ impl AssistantPanel { self.context_store .update(cx, |this, cx| this.delete_local_context(path, cx)) } + + fn set_active_view( + &mut self, + new_view: ActiveView, + window: &mut Window, + cx: &mut Context, + ) { + let current_is_history = matches!(self.active_view, ActiveView::History); + let new_is_history = matches!(new_view, ActiveView::History); + + if current_is_history && !new_is_history { + self.active_view = new_view; + } else if !current_is_history && new_is_history { + self.previous_view = Some(std::mem::replace(&mut self.active_view, new_view)); + } else { + if !new_is_history { + self.previous_view = None; + } + self.active_view = new_view; + } + + self.focus_handle(cx).focus(window); + } } impl Focusable for AssistantPanel { @@ -868,6 +900,8 @@ impl AssistantPanel { let is_empty = active_thread.is_empty(); let focus_handle = self.focus_handle(cx); + let is_history = matches!(self.active_view, ActiveView::History); + let show_token_count = match &self.active_view { ActiveView::Thread { .. } => !is_empty, ActiveView::PromptEditor => self.context_editor.is_some(), @@ -1009,6 +1043,27 @@ impl AssistantPanel { ); }), ) + .child( + IconButton::new("open-history", IconName::HistoryRerun) + .icon_size(IconSize::Small) + .toggle_state(is_history) + .selected_icon_color(Color::Accent) + .tooltip({ + let focus_handle = self.focus_handle(cx); + move |window, cx| { + Tooltip::for_action_in( + "History", + &OpenHistory, + &focus_handle, + window, + cx, + ) + } + }) + .on_click(move |_event, window, cx| { + window.dispatch_action(OpenHistory.boxed_clone(), cx); + }), + ) .child( PopoverMenu::new("assistant-menu") .trigger_with_tooltip( @@ -1025,12 +1080,6 @@ impl AssistantPanel { cx, |menu, _window, _cx| { menu.action( - "New Thread", - Box::new(NewThread { - from_thread_id: None, - }), - ) - .action( "New Prompt Editor", NewPromptEditor.boxed_clone(), ) @@ -1043,7 +1092,6 @@ impl AssistantPanel { ) }) .separator() - .action("History", OpenHistory.boxed_clone()) .action("Settings", OpenConfiguration.boxed_clone()) }, ))