From 79e0d8ce3bb032cdca6a1ab28276d5480ceca5d7 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 6 Dec 2023 23:15:04 -0500 Subject: [PATCH] WIP --- Cargo.lock | 1 + crates/feedback2/Cargo.toml | 5 +- crates/feedback2/src/feedback2.rs | 4 +- crates/feedback2/src/feedback_modal.rs | 71 ++++++++++++++++++-------- 4 files changed, 57 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b156b29145384a9b349c5f07f549d839e67649a5..4e59f245ddae3fc96aa406caea5729a02ef7b9b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3195,6 +3195,7 @@ dependencies = [ "language2", "lazy_static", "log", + "menu2", "postage", "project2", "regex", diff --git a/crates/feedback2/Cargo.toml b/crates/feedback2/Cargo.toml index 6360bd193f4fe2f62b4b2caf4f20d80e704367e9..560c5a307f9b103c0a65aed5fee73f48f55ee738 100644 --- a/crates/feedback2/Cargo.toml +++ b/crates/feedback2/Cargo.toml @@ -14,16 +14,17 @@ test-support = [] client = { package = "client2", path = "../client2" } db = { package = "db2", path = "../db2" } editor = { package = "editor2", path = "../editor2" } -language = { package = "language2", path = "../language2" } gpui = { package = "gpui2", path = "../gpui2" } +language = { package = "language2", path = "../language2" } +menu = { package = "menu2", path = "../menu2" } project = { package = "project2", path = "../project2" } regex.workspace = true search = { package = "search2", path = "../search2" } settings = { package = "settings2", path = "../settings2" } theme = { package = "theme2", path = "../theme2" } +ui = { package = "ui2", path = "../ui2" } util = { path = "../util" } workspace = { package = "workspace2", path = "../workspace2"} -ui = { package = "ui2", path = "../ui2" } log.workspace = true futures.workspace = true diff --git a/crates/feedback2/src/feedback2.rs b/crates/feedback2/src/feedback2.rs index 63a1e86211215a4d078cb96098dc4d044cd750bf..1a1bd935267ce2509aa0b004a6040a962901361e 100644 --- a/crates/feedback2/src/feedback2.rs +++ b/crates/feedback2/src/feedback2.rs @@ -17,11 +17,11 @@ actions!( ); pub fn init(cx: &mut AppContext) { - // TODO - a way to combine these two into one? + // TODO: a way to combine these two into one? cx.observe_new_views(feedback_modal::FeedbackModal::register) .detach(); - cx.observe_new_views(|workspace: &mut Workspace, _cx| { + cx.observe_new_views(|workspace: &mut Workspace, _| { workspace .register_action(|_, _: &CopySystemSpecsIntoClipboard, cx| { let specs = SystemSpecs::new(&cx).to_string(); diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 72c16319bf57e28dd83ccef63c3182fe4e583f97..68fbcfb3a30f69e462bf98b323d189a3b8a9675d 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -231,6 +231,14 @@ impl FeedbackModal { } Ok(()) } + + // TODO: Escape button calls dismiss + // TODO: Should do same as hitting cancel / clicking outside of modal + // Close immediately if no text in field + // Ask to close if text in the field + fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { + cx.emit(DismissEvent); + } } impl Render for FeedbackModal { @@ -253,26 +261,35 @@ impl Render for FeedbackModal { let allow_submission = valid_character_count && valid_email_address && !self.pending_submission; - let dismiss = cx.listener(|_, _, cx| { - // TODO - // if self.feedback_editor.read(cx).text_option(cx).is_some() { - // let answer = cx.prompt(PromptLevel::Info, "Exit feedback?", &["Yes", "No"]); - // cx.spawn(|_, cx| async move { - // let answer = answer.await.ok(); - // if answer == Some(0) { - // cx.emit(DismissEvent); - // } - // }) - // .detach(); - // } + let has_feedback = self.feedback_editor.read(cx).text_option(cx).is_some(); + let submit_button_text = if self.pending_submission { + "Sending..." + } else { + "Send Feedback" + }; + let dismiss = cx.listener(|_, _, cx| { cx.emit(DismissEvent); }); + // TODO: get the "are you sure you want to dismiss?" prompt here working + let dismiss_prompt = cx.listener(|_, _, _| { + // let answer = cx.prompt(PromptLevel::Info, "Exit feedback?", &["Yes", "No"]); + // cx.spawn(|_, _| async move { + // let answer = answer.await.ok(); + // if answer == Some(0) { + // cx.emit(DismissEvent); + // } + // }) + // .detach(); + }); let open_community_repo = cx.listener(|_, _, cx| cx.dispatch_action(Box::new(OpenZedCommunityRepo))); + // TODO: Nate UI pass v_stack() .elevation_3(cx) + .key_context("GiveFeedback") + .on_action(cx.listener(Self::cancel)) .min_w(rems(40.)) .max_w(rems(96.)) .border() @@ -302,11 +319,15 @@ impl Render for FeedbackModal { "Characters: {}", characters_remaining )) - .when(valid_character_count, |this| this.color(Color::Success)) - .when(!valid_character_count, |this| this.color(Color::Error)) + .when_else( + valid_character_count, + |this| this.color(Color::Success), + |this| this.color(Color::Error) + ) ), ) - .child( div() + .child( + div() .bg(cx.theme().colors().editor_background) .border() .border_color(cx.theme().colors().border) @@ -326,14 +347,24 @@ impl Render for FeedbackModal { Button::new("cancel_feedback", "Cancel") .style(ButtonStyle::Subtle) .color(Color::Muted) - .on_click(dismiss), + // TODO: replicate this logic when clicking outside the modal + // TODO: Will require somehow overriding the modal dismal default behavior + .when_else( + has_feedback, + |this| this.on_click(dismiss_prompt), + |this| this.on_click(dismiss) + ) ) .child( - Button::new("send_feedback", "Send Feedback") + Button::new("send_feedback", submit_button_text) .color(Color::Accent) .style(ButtonStyle::Filled) - // TODO - error handling - show modal on error - .on_click(cx.listener(|this, _, cx| {let _ = this.submit(cx);})) + // TODO: Ensure that while submitting, "Sending..." is shown and disable the button + // TODO: If submit errors: show popup with error, don't close modal, set text back to "Send Feedback", and re-enable button + // TODO: If submit is successful, close the modal + .on_click(cx.listener(|this, _, cx| { + let _ = this.submit(cx); + })) .tooltip(|cx| { Tooltip::with_meta( "Submit feedback to the Zed team.", @@ -342,7 +373,7 @@ impl Render for FeedbackModal { cx, ) }) - .when(!allow_submission, |this| this.disabled(true)), + .when(!allow_submission, |this| this.disabled(true)) ), )