agent2: Fix some UI glitches (#36067)

Release Notes:

- N/A
This commit is contained in:
Danilo Leal 2025-08-12 16:31:54 -03:00 committed by GitHub
parent 7167f193c0
commit 628b1058be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 58 additions and 35 deletions

View file

@ -1278,8 +1278,6 @@ impl AcpThreadView {
.pr_1() .pr_1()
.py_1() .py_1()
.rounded_t_md() .rounded_t_md()
.border_b_1()
.border_color(self.tool_card_border_color(cx))
.bg(self.tool_card_header_bg(cx)) .bg(self.tool_card_header_bg(cx))
} else { } else {
this.opacity(0.8).hover(|style| style.opacity(1.)) this.opacity(0.8).hover(|style| style.opacity(1.))
@ -1387,7 +1385,9 @@ impl AcpThreadView {
Empty.into_any_element() Empty.into_any_element()
} }
} }
ToolCallContent::Diff(diff) => self.render_diff_editor(&diff.read(cx).multibuffer()), ToolCallContent::Diff(diff) => {
self.render_diff_editor(&diff.read(cx).multibuffer(), cx)
}
ToolCallContent::Terminal(terminal) => { ToolCallContent::Terminal(terminal) => {
self.render_terminal_tool_call(terminal, tool_call, window, cx) self.render_terminal_tool_call(terminal, tool_call, window, cx)
} }
@ -1531,9 +1531,15 @@ impl AcpThreadView {
}))) })))
} }
fn render_diff_editor(&self, multibuffer: &Entity<MultiBuffer>) -> AnyElement { fn render_diff_editor(
&self,
multibuffer: &Entity<MultiBuffer>,
cx: &Context<Self>,
) -> AnyElement {
v_flex() v_flex()
.h_full() .h_full()
.border_t_1()
.border_color(self.tool_card_border_color(cx))
.child( .child(
if let Some(editor) = self.diff_editors.get(&multibuffer.entity_id()) { if let Some(editor) = self.diff_editors.get(&multibuffer.entity_id()) {
editor.clone().into_any_element() editor.clone().into_any_element()
@ -1746,9 +1752,9 @@ impl AcpThreadView {
.overflow_hidden() .overflow_hidden()
.child( .child(
v_flex() v_flex()
.pt_1() .py_1p5()
.pb_2() .pl_2()
.px_2() .pr_1p5()
.gap_0p5() .gap_0p5()
.bg(header_bg) .bg(header_bg)
.text_xs() .text_xs()
@ -2004,24 +2010,26 @@ impl AcpThreadView {
parent.child(self.render_plan_entries(plan, window, cx)) parent.child(self.render_plan_entries(plan, window, cx))
}) })
}) })
.when(!changed_buffers.is_empty(), |this| { .when(!plan.is_empty() && !changed_buffers.is_empty(), |this| {
this.child(Divider::horizontal().color(DividerColor::Border)) this.child(Divider::horizontal().color(DividerColor::Border))
.child(self.render_edits_summary( })
.when(!changed_buffers.is_empty(), |this| {
this.child(self.render_edits_summary(
action_log,
&changed_buffers,
self.edits_expanded,
pending_edits,
window,
cx,
))
.when(self.edits_expanded, |parent| {
parent.child(self.render_edited_files(
action_log, action_log,
&changed_buffers, &changed_buffers,
self.edits_expanded,
pending_edits, pending_edits,
window,
cx, cx,
)) ))
.when(self.edits_expanded, |parent| { })
parent.child(self.render_edited_files(
action_log,
&changed_buffers,
pending_edits,
cx,
))
})
}) })
.into_any() .into_any()
.into() .into()
@ -2940,7 +2948,8 @@ impl AcpThreadView {
fn render_thread_controls(&self, cx: &Context<Self>) -> impl IntoElement { fn render_thread_controls(&self, cx: &Context<Self>) -> impl IntoElement {
let open_as_markdown = IconButton::new("open-as-markdown", IconName::FileMarkdown) let open_as_markdown = IconButton::new("open-as-markdown", IconName::FileMarkdown)
.icon_size(IconSize::XSmall) .shape(ui::IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Ignored) .icon_color(Color::Ignored)
.tooltip(Tooltip::text("Open Thread as Markdown")) .tooltip(Tooltip::text("Open Thread as Markdown"))
.on_click(cx.listener(move |this, _, window, cx| { .on_click(cx.listener(move |this, _, window, cx| {
@ -2951,7 +2960,8 @@ impl AcpThreadView {
})); }));
let scroll_to_top = IconButton::new("scroll_to_top", IconName::ArrowUp) let scroll_to_top = IconButton::new("scroll_to_top", IconName::ArrowUp)
.icon_size(IconSize::XSmall) .shape(ui::IconButtonShape::Square)
.icon_size(IconSize::Small)
.icon_color(Color::Ignored) .icon_color(Color::Ignored)
.tooltip(Tooltip::text("Scroll To Top")) .tooltip(Tooltip::text("Scroll To Top"))
.on_click(cx.listener(move |this, _, _, cx| { .on_click(cx.listener(move |this, _, _, cx| {
@ -2962,7 +2972,6 @@ impl AcpThreadView {
.w_full() .w_full()
.mr_1() .mr_1()
.pb_2() .pb_2()
.gap_1()
.px(RESPONSE_PADDING_X) .px(RESPONSE_PADDING_X)
.opacity(0.4) .opacity(0.4)
.hover(|style| style.opacity(1.)) .hover(|style| style.opacity(1.))
@ -3079,6 +3088,8 @@ impl Focusable for AcpThreadView {
impl Render for AcpThreadView { impl Render for AcpThreadView {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement { fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let has_messages = self.list_state.item_count() > 0;
v_flex() v_flex()
.size_full() .size_full()
.key_context("AcpThread") .key_context("AcpThread")
@ -3125,7 +3136,7 @@ impl Render for AcpThreadView {
let thread_clone = thread.clone(); let thread_clone = thread.clone();
v_flex().flex_1().map(|this| { v_flex().flex_1().map(|this| {
if self.list_state.item_count() > 0 { if has_messages {
this.child( this.child(
list( list(
self.list_state.clone(), self.list_state.clone(),
@ -3144,23 +3155,32 @@ impl Render for AcpThreadView {
.into_any(), .into_any(),
) )
.child(self.render_vertical_scrollbar(cx)) .child(self.render_vertical_scrollbar(cx))
.children(match thread_clone.read(cx).status() { .children(
ThreadStatus::Idle | ThreadStatus::WaitingForToolConfirmation => { match thread_clone.read(cx).status() {
None ThreadStatus::Idle
} | ThreadStatus::WaitingForToolConfirmation => None,
ThreadStatus::Generating => div() ThreadStatus::Generating => div()
.px_5() .px_5()
.py_2() .py_2()
.child(LoadingLabel::new("").size(LabelSize::Small)) .child(LoadingLabel::new("").size(LabelSize::Small))
.into(), .into(),
}) },
.children(self.render_activity_bar(&thread_clone, window, cx)) )
} else { } else {
this.child(self.render_empty_state(cx)) this.child(self.render_empty_state(cx))
} }
}) })
} }
}) })
// The activity bar is intentionally rendered outside of the ThreadState::Ready match
// above so that the scrollbar doesn't render behind it. The current setup allows
// the scrollbar to stop exactly at the activity bar start.
.when(has_messages, |this| match &self.thread_state {
ThreadState::Ready { thread, .. } => {
this.children(self.render_activity_bar(thread, window, cx))
}
_ => this,
})
.when_some(self.last_error.clone(), |el, error| { .when_some(self.last_error.clone(), |el, error| {
el.child( el.child(
div() div()

View file

@ -1084,7 +1084,9 @@ impl Element for MarkdownElement {
self.markdown.clone(), self.markdown.clone(),
cx, cx,
); );
el.child(div().absolute().top_1().right_1().w_5().child(codeblock)) el.child(
div().absolute().top_1().right_0p5().w_5().child(codeblock),
)
}); });
} }
@ -1312,6 +1314,7 @@ fn render_copy_code_block_button(
}, },
) )
.icon_color(Color::Muted) .icon_color(Color::Muted)
.icon_size(IconSize::Small)
.shape(ui::IconButtonShape::Square) .shape(ui::IconButtonShape::Square)
.tooltip(Tooltip::text("Copy Code")) .tooltip(Tooltip::text("Copy Code"))
.on_click({ .on_click({