assistant: Remove "Resolving" text for step resolution and use Transform instead (#16461)

That way, user can click on "Transform" straight away and get it applied
immediately when it's resolved.



https://github.com/user-attachments/assets/08c99804-3841-4eba-a5eb-7066a9f45b47


TODO:
- [x] Tie "Send" button at the bottom into the same behavior

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2024-08-19 15:17:04 +02:00 committed by GitHub
parent 911112d94a
commit 56f1ab9459
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 108 additions and 53 deletions

View file

@ -1355,6 +1355,7 @@ struct WorkflowStep {
footer_block_id: CustomBlockId, footer_block_id: CustomBlockId,
resolved_step: Option<Result<WorkflowStepResolution, Arc<anyhow::Error>>>, resolved_step: Option<Result<WorkflowStepResolution, Arc<anyhow::Error>>>,
assist: Option<WorkflowAssist>, assist: Option<WorkflowAssist>,
auto_apply: bool,
} }
impl WorkflowStep { impl WorkflowStep {
@ -1391,13 +1392,16 @@ impl WorkflowStep {
} }
} }
Some(Err(error)) => WorkflowStepStatus::Error(error.clone()), Some(Err(error)) => WorkflowStepStatus::Error(error.clone()),
None => WorkflowStepStatus::Resolving, None => WorkflowStepStatus::Resolving {
auto_apply: self.auto_apply,
},
} }
} }
} }
#[derive(Clone)]
enum WorkflowStepStatus { enum WorkflowStepStatus {
Resolving, Resolving { auto_apply: bool },
Error(Arc<anyhow::Error>), Error(Arc<anyhow::Error>),
Empty, Empty,
Idle, Idle,
@ -1474,16 +1478,6 @@ impl WorkflowStepStatus {
.unwrap_or_default() .unwrap_or_default()
} }
match self { match self {
WorkflowStepStatus::Resolving => Label::new("Resolving")
.size(LabelSize::Small)
.with_animation(
("resolving-suggestion-animation", id),
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.4, 0.8)),
|label, delta| label.alpha(delta),
)
.into_any_element(),
WorkflowStepStatus::Error(error) => Self::render_workflow_step_error( WorkflowStepStatus::Error(error) => Self::render_workflow_step_error(
id, id,
editor.clone(), editor.clone(),
@ -1496,43 +1490,72 @@ impl WorkflowStepStatus {
step_range.clone(), step_range.clone(),
"Model was unable to locate the code to edit".to_string(), "Model was unable to locate the code to edit".to_string(),
), ),
WorkflowStepStatus::Idle => Button::new(("transform", id), "Transform") WorkflowStepStatus::Idle | WorkflowStepStatus::Resolving { .. } => {
.icon(IconName::SparkleAlt) let status = self.clone();
.icon_position(IconPosition::Start) Button::new(("transform", id), "Transform")
.icon_size(IconSize::Small) .icon(IconName::SparkleAlt)
.label_size(LabelSize::Small) .icon_position(IconPosition::Start)
.style(ButtonStyle::Tinted(TintColor::Accent)) .icon_size(IconSize::Small)
.tooltip({ .label_size(LabelSize::Small)
let step_range = step_range.clone(); .style(ButtonStyle::Tinted(TintColor::Accent))
let editor = editor.clone(); .tooltip({
move |cx| { let step_range = step_range.clone();
cx.new_view(|cx| { let editor = editor.clone();
let tooltip = Tooltip::new("Transform"); move |cx| {
if display_keybind_in_tooltip(&step_range, &editor, cx) { cx.new_view(|cx| {
tooltip.key_binding(KeyBinding::for_action_in( let tooltip = Tooltip::new("Transform");
&Assist, if display_keybind_in_tooltip(&step_range, &editor, cx) {
&focus_handle, tooltip.key_binding(KeyBinding::for_action_in(
cx, &Assist,
)) &focus_handle,
} else { cx,
tooltip ))
} } else {
}) tooltip
.into() }
}
})
.on_click({
let editor = editor.clone();
let step_range = step_range.clone();
move |_, cx| {
editor
.update(cx, |this, cx| {
this.apply_workflow_step(step_range.clone(), cx)
}) })
.ok(); .into()
} }
}) })
.into_any_element(), .on_click({
let editor = editor.clone();
let step_range = step_range.clone();
move |_, cx| {
if let WorkflowStepStatus::Idle = &status {
editor
.update(cx, |this, cx| {
this.apply_workflow_step(step_range.clone(), cx)
})
.ok();
} else if let WorkflowStepStatus::Resolving { auto_apply: false } =
&status
{
editor
.update(cx, |this, _| {
if let Some(step) = this.workflow_steps.get_mut(&step_range)
{
step.auto_apply = true;
}
})
.ok();
}
}
})
.map(|this| {
if let WorkflowStepStatus::Resolving { auto_apply: true } = &self {
this.with_animation(
("resolving-suggestion-animation", id),
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.4, 0.8)),
|label, delta| label.alpha(delta),
)
.into_any_element()
} else {
this.into_any_element()
}
})
}
WorkflowStepStatus::Pending => h_flex() WorkflowStepStatus::Pending => h_flex()
.items_center() .items_center()
.gap_2() .gap_2()
@ -1856,7 +1879,7 @@ impl ContextEditor {
let range = step.range.clone(); let range = step.range.clone();
match step.status(cx) { match step.status(cx) {
WorkflowStepStatus::Resolving | WorkflowStepStatus::Pending => true, WorkflowStepStatus::Resolving { .. } | WorkflowStepStatus::Pending => true,
WorkflowStepStatus::Idle => { WorkflowStepStatus::Idle => {
self.apply_workflow_step(range, cx); self.apply_workflow_step(range, cx);
true true
@ -2650,11 +2673,17 @@ impl ContextEditor {
footer_block_id: block_ids[1], footer_block_id: block_ids[1],
resolved_step, resolved_step,
assist: None, assist: None,
auto_apply: false,
}, },
); );
} }
self.update_active_workflow_step(cx); self.update_active_workflow_step(cx);
if let Some(step) = self.workflow_steps.get_mut(&step_range) {
if step.auto_apply && matches!(step.status(cx), WorkflowStepStatus::Idle) {
self.apply_workflow_step(step_range, cx);
}
}
} }
fn open_workflow_step( fn open_workflow_step(
@ -3586,13 +3615,17 @@ impl ContextEditor {
fn render_send_button(&self, cx: &mut ViewContext<Self>) -> impl IntoElement { fn render_send_button(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let focus_handle = self.focus_handle(cx).clone(); let focus_handle = self.focus_handle(cx).clone();
let mut should_pulsate = false;
let button_text = match self.active_workflow_step() { let button_text = match self.active_workflow_step() {
Some(step) => match step.status(cx) { Some(step) => match step.status(cx) {
WorkflowStepStatus::Resolving => "Resolving Step...",
WorkflowStepStatus::Empty | WorkflowStepStatus::Error(_) => "Retry Step Resolution", WorkflowStepStatus::Empty | WorkflowStepStatus::Error(_) => "Retry Step Resolution",
WorkflowStepStatus::Resolving { auto_apply } => {
should_pulsate = auto_apply;
"Transform"
}
WorkflowStepStatus::Idle => "Transform", WorkflowStepStatus::Idle => "Transform",
WorkflowStepStatus::Pending => "Transforming...", WorkflowStepStatus::Pending => "Applying...",
WorkflowStepStatus::Done => "Accept Transformation", WorkflowStepStatus::Done => "Accept",
WorkflowStepStatus::Confirmed => "Send", WorkflowStepStatus::Confirmed => "Send",
}, },
None => "Send", None => "Send",
@ -3636,7 +3669,20 @@ impl ContextEditor {
button.tooltip(move |_| tooltip.clone()) button.tooltip(move |_| tooltip.clone())
}) })
.layer(ElevationIndex::ModalSurface) .layer(ElevationIndex::ModalSurface)
.child(Label::new(button_text)) .child(Label::new(button_text).map(|this| {
if should_pulsate {
this.with_animation(
"resolving-suggestion-send-button-animation",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.4, 0.8)),
|label, delta| label.alpha(delta),
)
.into_any_element()
} else {
this.into_any_element()
}
}))
.children( .children(
KeyBinding::for_action_in(&Assist, &focus_handle, cx) KeyBinding::for_action_in(&Assist, &focus_handle, cx)
.map(|binding| binding.into_any_element()), .map(|binding| binding.into_any_element()),

View file

@ -89,6 +89,7 @@ pub struct Button {
selected_icon: Option<IconName>, selected_icon: Option<IconName>,
selected_icon_color: Option<Color>, selected_icon_color: Option<Color>,
key_binding: Option<KeyBinding>, key_binding: Option<KeyBinding>,
alpha: Option<f32>,
} }
impl Button { impl Button {
@ -113,6 +114,7 @@ impl Button {
selected_icon: None, selected_icon: None,
selected_icon_color: None, selected_icon_color: None,
key_binding: None, key_binding: None,
alpha: None,
} }
} }
@ -181,6 +183,12 @@ impl Button {
self.key_binding = key_binding.into(); self.key_binding = key_binding.into();
self self
} }
/// Sets the alpha property of the color of label.
pub fn alpha(mut self, alpha: f32) -> Self {
self.alpha = Some(alpha);
self
}
} }
impl Selectable for Button { impl Selectable for Button {
@ -409,6 +417,7 @@ impl RenderOnce for Button {
Label::new(label) Label::new(label)
.color(label_color) .color(label_color)
.size(self.label_size.unwrap_or_default()) .size(self.label_size.unwrap_or_default())
.when_some(self.alpha, |this, alpha| this.alpha(alpha))
.line_height_style(LineHeightStyle::UiLabel), .line_height_style(LineHeightStyle::UiLabel),
) )
.children(self.key_binding), .children(self.key_binding),