From 0dbecee03f5dcbf50e4d170ae474efb2884ee9cb Mon Sep 17 00:00:00 2001 From: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:08:55 +0200 Subject: [PATCH] assistant: Refine workflow step labels (#16161) https://github.com/user-attachments/assets/f6325507-091a-482e-ac28-dd09877ebaa2 Release Notes: - N/A --------- Co-authored-by: Danilo --- assets/icons/text-search.svg | 1 - crates/assistant/src/assistant_panel.rs | 145 +++++++++++++--------- crates/assistant/src/context.rs | 17 +-- crates/assistant/src/context_inspector.rs | 9 +- crates/ui/src/components/icon.rs | 2 - 5 files changed, 101 insertions(+), 73 deletions(-) delete mode 100644 assets/icons/text-search.svg diff --git a/assets/icons/text-search.svg b/assets/icons/text-search.svg deleted file mode 100644 index 379284cdea..0000000000 --- a/assets/icons/text-search.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index ce40a93839..b904e102e3 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -365,7 +365,8 @@ impl AssistantPanel { pane.set_should_display_tab_bar(|_| true); pane.set_render_tab_bar_buttons(cx, move |pane, cx| { let focus_handle = pane.focus_handle(cx); - let left_children = IconButton::new("history", IconName::TextSearch) + let left_children = IconButton::new("history", IconName::HistoryRerun) + .icon_size(IconSize::Small) .on_click(cx.listener({ let focus_handle = focus_handle.clone(); move |_, _, cx| { @@ -377,7 +378,7 @@ impl AssistantPanel { cx.new_view(|cx| { let keybind = KeyBinding::for_action_in(&DeployHistory, &focus_handle, cx); - Tooltip::new("History").key_binding(keybind) + Tooltip::new("Open History").key_binding(keybind) }) .into() }) @@ -1458,12 +1459,14 @@ impl WorkflowStepStatus { .unwrap_or_default() } match self { - WorkflowStepStatus::Resolving => Icon::new(IconName::ArrowCircle) - .size(IconSize::Small) + WorkflowStepStatus::Resolving => Label::new("Resolving") + .size(LabelSize::Small) .with_animation( - ("resolving-suggestion-label", id), - Animation::new(Duration::from_secs(2)).repeat(), - |icon, delta| icon.transform(Transformation::rotate(percentage(delta))), + ("resolving-suggestion-animation", id), + Animation::new(Duration::from_secs(2)) + .repeat() + .with_easing(pulsating_between(0.2, 1.0)), + |label, delta| label.alpha(delta), ) .into_any_element(), @@ -1539,51 +1542,61 @@ impl WorkflowStepStatus { } }) .into_any_element(), - WorkflowStepStatus::Pending => Button::new(("stop-transformation", id), "Stop") - .icon(IconName::Stop) - .icon_position(IconPosition::Start) - .icon_size(IconSize::Small) - .label_size(LabelSize::Small) - .style(ButtonStyle::Tinted(TintColor::Negative)) - .tooltip({ - let step_range = step_range.clone(); - let editor = editor.clone(); - move |cx| { - cx.new_view(|cx| { - let tooltip = Tooltip::new("Stop Transformation"); - if display_keybind_in_tooltip(&step_range, &editor, cx) { - tooltip.key_binding(KeyBinding::for_action_in( - &editor::actions::Cancel, - &focus_handle, - cx, - )) - } else { - tooltip + WorkflowStepStatus::Pending => h_flex() + .items_center() + .gap_2() + .child( + Label::new("Applying...") + .size(LabelSize::Small) + .with_animation( + ("applying-step-transformation-label", id), + Animation::new(Duration::from_secs(2)) + .repeat() + .with_easing(pulsating_between(0.2, 1.0)), + |label, delta| label.alpha(delta), + ), + ) + .child( + IconButton::new(("stop-transformation", id), IconName::Stop) + .icon_size(IconSize::Small) + .style(ButtonStyle::Tinted(TintColor::Negative)) + .tooltip({ + let step_range = step_range.clone(); + let editor = editor.clone(); + move |cx| { + cx.new_view(|cx| { + let tooltip = Tooltip::new("Stop Transformation"); + if display_keybind_in_tooltip(&step_range, &editor, cx) { + tooltip.key_binding(KeyBinding::for_action_in( + &editor::actions::Cancel, + &focus_handle, + cx, + )) + } else { + tooltip + } + }) + .into() } }) - .into() - } - }) - .on_click({ - let editor = editor.clone(); - let step_range = step_range.clone(); - move |_, cx| { - editor - .update(cx, |this, cx| { - this.stop_workflow_step(step_range.clone(), cx) - }) - .ok(); - } - }) + .on_click({ + let editor = editor.clone(); + let step_range = step_range.clone(); + move |_, cx| { + editor + .update(cx, |this, cx| { + this.stop_workflow_step(step_range.clone(), cx) + }) + .ok(); + } + }), + ) .into_any_element(), WorkflowStepStatus::Done => h_flex() .gap_1() .child( - Button::new(("stop-transformation", id), "Reject") - .icon(IconName::Close) - .icon_position(IconPosition::Start) + IconButton::new(("stop-transformation", id), IconName::Close) .icon_size(IconSize::Small) - .label_size(LabelSize::Small) .style(ButtonStyle::Tinted(TintColor::Negative)) .tooltip({ let focus_handle = focus_handle.clone(); @@ -1664,7 +1677,6 @@ impl WorkflowStepStatus { .icon_position(IconPosition::Start) .icon_size(IconSize::Small) .label_size(LabelSize::Small) - .tooltip(|cx| Tooltip::text("Undo Transformation", cx)) .on_click({ let editor = editor.clone(); let step_range = step_range.clone(); @@ -2519,6 +2531,17 @@ impl ContextEditor { } else { theme.info_border }; + let step_index = weak_self.update(&mut **cx, |this, cx| { + let snapshot = this.editor.read(cx).buffer().read(cx).as_singleton()?.read(cx).text_snapshot(); + let start_offset = step_range.start.to_offset(&snapshot); + let parent_message = this.context.read(cx).messages_for_offsets([start_offset], cx); + debug_assert_eq!(parent_message.len(), 1); + let parent_message = parent_message.first()?; + + let index_of_current_step = this.workflow_steps.keys().filter(|workflow_step_range| workflow_step_range.start.cmp(&parent_message.anchor, &snapshot).is_ge() && workflow_step_range.end.cmp(&step_range.end, &snapshot).is_le()).count(); + Some(index_of_current_step) + }).ok().flatten(); + let debug_header = weak_self .update(&mut **cx, |this, _| { if let Some(inspector) = this.debug_inspector.as_mut() { @@ -2528,6 +2551,17 @@ impl ContextEditor { } }) .unwrap_or_default(); + let step_label = if let Some(index) = step_index { + + Label::new(format!("Step {index}")).size(LabelSize::Small) + } else { + Label::new("Step").size(LabelSize::Small) + }; + let step_label = if current_status.as_ref().is_some_and(|status| status.is_confirmed()) { + h_flex().items_center().gap_2().child(step_label.strikethrough(true).color(Color::Muted)).child(Icon::new(IconName::Check).size(IconSize::Small).color(Color::Created)) + } else { + div().child(step_label) + }; div() .w_full() .px(cx.gutter_dimensions.full_width()) @@ -2536,11 +2570,12 @@ impl ContextEditor { .w_full() .border_b_1() .border_color(border_color) - .pb_1() + .pb_1p5() .justify_between() .gap_2() - .children(debug_header.map(|is_active| { - h_flex().justify_start().child( + .child(h_flex().justify_start().gap_2().child(step_label).children( + debug_header.map(|is_active| { + Button::new("debug-workflows-toggle", "Debug") .icon_color(Color::Hidden) .color(Color::Hidden) @@ -2571,10 +2606,10 @@ impl ContextEditor { }) .ok(); } - }), - ) - // .child(h_flex().w_full()) - })) + }) + }) + + )) .children(current_status.as_ref().map(|status| { h_flex().w_full().justify_end().child( status.into_element( @@ -2618,9 +2653,7 @@ impl ContextEditor { div() .w_full() .px(cx.gutter_dimensions.full_width()) - .child( - h_flex().w_full().border_t_1().border_color(border_color), - ) + .child(h_flex().h(px(1.)).bg(border_color)) .into_any() }), disposition: BlockDisposition::Below, diff --git a/crates/assistant/src/context.rs b/crates/assistant/src/context.rs index 66c56fed50..97eba5993a 100644 --- a/crates/assistant/src/context.rs +++ b/crates/assistant/src/context.rs @@ -1252,7 +1252,10 @@ impl Context { if let Some(step_end_index) = line.find("") { if in_step { - let step_open_tag_end_ix = step_open_tag_start_ix + "".len(); + let mut step_open_tag_end_ix = step_open_tag_start_ix + "".len(); + if buffer.chars_at(step_open_tag_end_ix).next() == Some('\n') { + step_open_tag_end_ix += 1; + } let mut step_end_tag_start_ix = line_start_offset + step_end_index; let step_end_tag_end_ix = step_end_tag_start_ix + "".len(); if buffer.reversed_chars_at(step_end_tag_start_ix).next() == Some('\n') { @@ -3098,12 +3101,12 @@ mod tests { vec![ ( Point::new(response_start_row + 2, 0) - ..Point::new(response_start_row + 13, 3), + ..Point::new(response_start_row + 12, 3), WorkflowStepTestStatus::Pending ), ( - Point::new(response_start_row + 15, 0) - ..Point::new(response_start_row + 26, 3), + Point::new(response_start_row + 14, 0) + ..Point::new(response_start_row + 24, 3), WorkflowStepTestStatus::Pending ), ] @@ -3135,12 +3138,12 @@ mod tests { vec![ ( Point::new(response_start_row + 2, 0) - ..Point::new(response_start_row + 13, 3), + ..Point::new(response_start_row + 12, 3), WorkflowStepTestStatus::Resolved ), ( - Point::new(response_start_row + 15, 0) - ..Point::new(response_start_row + 26, 3), + Point::new(response_start_row + 14, 0) + ..Point::new(response_start_row + 24, 3), WorkflowStepTestStatus::Pending ), ] diff --git a/crates/assistant/src/context_inspector.rs b/crates/assistant/src/context_inspector.rs index 1fde35fdf0..16e6da1a29 100644 --- a/crates/assistant/src/context_inspector.rs +++ b/crates/assistant/src/context_inspector.rs @@ -8,7 +8,7 @@ use editor::{ use gpui::{AppContext, Model, View}; use text::{ToOffset, ToPoint}; use ui::{ - div, h_flex, Color, Element as _, ParentElement as _, Styled, ViewContext, WindowContext, + div, h_flex, px, Color, Element as _, ParentElement as _, Styled, ViewContext, WindowContext, }; use crate::{Context, ResolvedWorkflowStep, WorkflowSuggestion}; @@ -109,12 +109,7 @@ impl ContextInspector { div() .w_full() .px(cx.gutter_dimensions.full_width()) - .child( - h_flex() - .w_full() - .border_t_1() - .border_color(Color::Warning.color(cx)), - ) + .child(h_flex().h(px(1.)).bg(Color::Warning.color(cx))) .into_any() }), disposition: BlockDisposition::Below, diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs index 9e3a0290bd..9091b7b00b 100644 --- a/crates/ui/src/components/icon.rs +++ b/crates/ui/src/components/icon.rs @@ -254,7 +254,6 @@ pub enum IconName { Tab, Terminal, TextCursor, - TextSearch, Trash, TriangleRight, Undo, @@ -418,7 +417,6 @@ impl IconName { IconName::Tab => "icons/tab.svg", IconName::Terminal => "icons/terminal.svg", IconName::TextCursor => "icons/text-cursor.svg", - IconName::TextSearch => "icons/text-search.svg", IconName::Trash => "icons/trash.svg", IconName::TriangleRight => "icons/triangle_right.svg", IconName::Update => "icons/update.svg",