From bd3f64c5a148b67bcbd833b5ec98c79f740ce838 Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Wed, 15 Jan 2025 12:10:46 +0100 Subject: [PATCH] zeta: Allow viewing prompt details in rate completion modal (#23142) Co-Authored-by: Danilo Release Notes: - N/A --------- Co-authored-by: Danilo Co-authored-by: Danilo Leal Co-authored-by: Thorsten Ball --- crates/zeta/src/rate_completion_modal.rs | 142 +++++++++++++++++++---- 1 file changed, 120 insertions(+), 22 deletions(-) diff --git a/crates/zeta/src/rate_completion_modal.rs b/crates/zeta/src/rate_completion_modal.rs index cf7d3f34e9..ecdfc17823 100644 --- a/crates/zeta/src/rate_completion_modal.rs +++ b/crates/zeta/src/rate_completion_modal.rs @@ -37,6 +37,7 @@ pub struct RateCompletionModal { selected_index: usize, focus_handle: FocusHandle, _subscription: gpui::Subscription, + current_view: RateCompletionView, } struct ActiveCompletion { @@ -44,6 +45,21 @@ struct ActiveCompletion { feedback_editor: View, } +#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +enum RateCompletionView { + SuggestedEdits, + RawInput, +} + +impl RateCompletionView { + pub fn name(&self) -> &'static str { + match self { + Self::SuggestedEdits => "Suggested Edits", + Self::RawInput => "Recorded Events & Input", + } + } +} + impl RateCompletionModal { pub fn toggle(workspace: &mut Workspace, cx: &mut ViewContext) { if let Some(zeta) = Zeta::global(cx) { @@ -60,6 +76,7 @@ impl RateCompletionModal { focus_handle: cx.focus_handle(), active_completion: None, _subscription: subscription, + current_view: RateCompletionView::SuggestedEdits, } } @@ -266,6 +283,87 @@ impl RateCompletionModal { cx.notify(); } + fn render_view_nav(&self, cx: &ViewContext) -> impl IntoElement { + h_flex() + .h_8() + .px_1() + .border_b_1() + .border_color(cx.theme().colors().border) + .bg(cx.theme().colors().elevated_surface_background) + .gap_1() + .child( + Button::new( + ElementId::Name("suggested-edits".into()), + RateCompletionView::SuggestedEdits.name(), + ) + .label_size(LabelSize::Small) + .on_click(cx.listener(move |this, _, cx| { + this.current_view = RateCompletionView::SuggestedEdits; + cx.notify(); + })) + .toggle_state(self.current_view == RateCompletionView::SuggestedEdits), + ) + .child( + Button::new( + ElementId::Name("raw-input".into()), + RateCompletionView::RawInput.name(), + ) + .label_size(LabelSize::Small) + .on_click(cx.listener(move |this, _, cx| { + this.current_view = RateCompletionView::RawInput; + cx.notify(); + })) + .toggle_state(self.current_view == RateCompletionView::RawInput), + ) + } + + fn render_suggested_edits(&self, cx: &mut ViewContext) -> Option> { + let active_completion = self.active_completion.as_ref()?; + let bg_color = cx.theme().colors().editor_background; + + Some( + div() + .id("diff") + .p_4() + .size_full() + .bg(bg_color) + .overflow_scroll() + .whitespace_nowrap() + .child(CompletionDiffElement::new( + &active_completion.completion, + cx, + )), + ) + } + + fn render_raw_input(&self, cx: &mut ViewContext) -> Option> { + Some( + v_flex() + .size_full() + .overflow_hidden() + .relative() + .child( + div() + .id("raw-input") + .py_4() + .px_6() + .size_full() + .bg(cx.theme().colors().editor_background) + .overflow_scroll() + .child(if let Some(active_completion) = &self.active_completion { + format!( + "{}\n{}", + active_completion.completion.input_events, + active_completion.completion.input_excerpt + ) + } else { + "No active completion".to_string() + }), + ) + .id("raw-input-view"), + ) + } + fn render_active_completion(&mut self, cx: &mut ViewContext) -> Option { let active_completion = self.active_completion.as_ref()?; let completion_id = active_completion.completion.id; @@ -281,31 +379,31 @@ impl RateCompletionModal { .text(cx) .is_empty(); - let label_container = || h_flex().pl_1().gap_1p5(); + let label_container = h_flex().pl_1().gap_1p5(); Some( v_flex() .size_full() .overflow_hidden() + .relative() .child( - div() - .id("diff") - .py_4() - .px_6() + v_flex() .size_full() - .bg(bg_color) - .overflow_scroll() - .whitespace_nowrap() - .child(CompletionDiffElement::new(&active_completion.completion, cx)), + .overflow_hidden() + .relative() + .child(self.render_view_nav(cx)) + .when_some(match self.current_view { + RateCompletionView::SuggestedEdits => self.render_suggested_edits(cx), + RateCompletionView::RawInput => self.render_raw_input(cx), + }, |this, element| this.child(element)) ) - .when_some((!rated).then(|| ()), |this, _| { + .when(!rated, |this| { this.child( h_flex() .p_2() .gap_2() .border_y_1() .border_color(border_color) - .child( Icon::new(IconName::Info) .size(IconSize::XSmall) @@ -317,14 +415,14 @@ impl RateCompletionModal { .pr_2() .flex_wrap() .child( - Label::new("Ensure you explain why this completion is negative or positive. In case it's negative, report what you expected instead.") + Label::new("Explain why this completion is good or bad. If it's negative, describe what you expected instead.") .size(LabelSize::Small) .color(Color::Muted) ) ) ) }) - .when_some((!rated).then(|| ()), |this, _| { + .when(!rated, |this| { this.child( div() .h_40() @@ -344,7 +442,7 @@ impl RateCompletionModal { .justify_between() .children(if rated { Some( - label_container() + label_container .child( Icon::new(IconName::Check) .size(IconSize::Small) @@ -354,7 +452,7 @@ impl RateCompletionModal { ) } else if active_completion.completion.edits.is_empty() { Some( - label_container() + label_container .child( Icon::new(IconName::Warning) .size(IconSize::Small) @@ -363,7 +461,7 @@ impl RateCompletionModal { .child(Label::new("No edits produced.").color(Color::Muted)), ) } else { - Some(label_container()) + Some(label_container) }) .child( h_flex() @@ -440,16 +538,16 @@ impl Render for RateCompletionModal { .shadow_lg() .child( v_flex() - .border_r_1() - .border_color(border_color) .w_72() .h_full() + .border_r_1() + .border_color(border_color) .flex_shrink_0() .overflow_hidden() .child( h_flex() + .h_8() .px_2() - .py_1() .justify_between() .border_b_1() .border_color(border_color) @@ -475,7 +573,7 @@ impl Render for RateCompletionModal { div() .p_2() .child( - Label::new("No completions yet. Use the editor to generate some and rate them!") + Label::new("No completions yet. Use the editor to generate some, and make sure to rate them!") .color(Color::Muted), ) .into_any_element(), @@ -506,7 +604,7 @@ impl Render for RateCompletionModal { .child( h_flex() .id("completion-content") - .gap_2p5() + .gap_3() .child( Icon::new(icon_name) .color(icon_color) @@ -515,7 +613,7 @@ impl Render for RateCompletionModal { .child( v_flex() .child( - h_flex().gap_2() + h_flex().gap_1() .child(Label::new(file_name).size(LabelSize::Small)) .when_some(file_path, |this, p| this.child(Label::new(p).size(LabelSize::Small).color(Color::Muted))) )