From 7a1eb541061ec99de9804cd3d5dc0502d21dc6b4 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 7 Dec 2023 00:33:24 -0500 Subject: [PATCH 01/15] checkpoint --- crates/feedback2/src/feedback_modal.rs | 152 +++++++++++++----------- crates/ui2/src/components/keybinding.rs | 12 +- 2 files changed, 87 insertions(+), 77 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 68fbcfb3a30f69e462bf98b323d189a3b8a9675d..b4d4b08d54aa19027d8f26cf767a4070e1355a51 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -292,91 +292,99 @@ impl Render for FeedbackModal { .on_action(cx.listener(Self::cancel)) .min_w(rems(40.)) .max_w(rems(96.)) - .border() - .border_color(red()) - .h(rems(40.)) - .p_2() + .min_h(rems(24.)) + .max_h(rems(42.)) .gap_2() .child( - v_stack().child( + v_stack() + .p_4() + .child( div() .size_full() .child(Label::new("Give Feedback").color(Color::Default)) .child(Label::new("This editor supports markdown").color(Color::Muted)), ), ) - .child( - div() - .flex_1() + .child(v_stack() + .p_4() + .child( + div() + .flex_1() + .bg(cx.theme().colors().editor_background) + .border() + .border_color(cx.theme().colors().border) + .child(self.feedback_editor.clone()), + ) + .child( + div().child( + Label::new(format!( + "Characters: {}", + characters_remaining + )) + .map(|this| + if valid_character_count { + this.color(Color::Success) + } else { + this.color(Color::Error) + + } + ) + ), + ) + .child( + div() .bg(cx.theme().colors().editor_background) .border() .border_color(cx.theme().colors().border) - .child(self.feedback_editor.clone()), - ) - .child( - div().child( - Label::new(format!( - "Characters: {}", - characters_remaining - )) - .when_else( - valid_character_count, - |this| this.color(Color::Success), - |this| this.color(Color::Error) - ) - ), - ) - .child( - div() - .bg(cx.theme().colors().editor_background) - .border() - .border_color(cx.theme().colors().border) - .child(self.email_address_editor.clone()) - ) - .child( - h_stack() - .justify_between() - .gap_1() - .child(Button::new("community_repo", "Community Repo") - .style(ButtonStyle::Filled) - .color(Color::Muted) - .on_click(open_community_repo) - ) - .child(h_stack().justify_between().gap_1() - .child( - Button::new("cancel_feedback", "Cancel") - .style(ButtonStyle::Subtle) - .color(Color::Muted) - // 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(self.email_address_editor.clone()) + ) + .child( + h_stack() + .justify_between() + .gap_1() + .child(Button::new("community_repo", "Community Repo") + .style(ButtonStyle::Filled) + .color(Color::Muted) + .on_click(open_community_repo) + ) + .child(h_stack().justify_between().gap_1() + .child( + Button::new("cancel_feedback", "Cancel") + .style(ButtonStyle::Subtle) + .color(Color::Muted) + // TODO: replicate this logic when clicking outside the modal + // TODO: Will require somehow overriding the modal dismal default behavior + .map(|this| { + if has_feedback { + this.on_click(dismiss_prompt) + } else { + this.on_click(dismiss) + } + }) + ) + .child( + Button::new("send_feedback", submit_button_text) + .color(Color::Accent) + .style(ButtonStyle::Filled) + // 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.", + None, + "Provide an email address if you want us to be able to reply.", + cx, + ) + }) + .when(!allow_submission, |this| this.disabled(true)) + ), ) - .child( - Button::new("send_feedback", submit_button_text) - .color(Color::Accent) - .style(ButtonStyle::Filled) - // 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.", - None, - "Provide an email address if you want us to be able to reply.", - cx, - ) - }) - .when(!allow_submission, |this| this.disabled(true)) - ), - ) + ) ) } } diff --git a/crates/ui2/src/components/keybinding.rs b/crates/ui2/src/components/keybinding.rs index 29586fd1941ba1fe69608e14d6f7fb01e053d56c..25a77f59e191f74ab445d564613f8ebe0859b7e2 100644 --- a/crates/ui2/src/components/keybinding.rs +++ b/crates/ui2/src/components/keybinding.rs @@ -98,11 +98,13 @@ impl RenderOnce for Key { div() .py_0() - .when_else( - single_char, - |el| el.w(rems(14. / 16.)).flex().flex_none().justify_center(), - |el| el.px_0p5(), - ) + .map(|el| { + if single_char { + el.w(rems(14. / 16.)).flex().flex_none().justify_center() + } else { + el.px_0p5() + } + }) .h(rems(14. / 16.)) .text_ui() .line_height(relative(1.)) From 197f355729e804ed2b9ced4bcf40d86f775924d2 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 7 Dec 2023 01:17:18 -0500 Subject: [PATCH 02/15] Add `row-reverse` and `col-reverse` to styled --- crates/gpui2/src/styled.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/gpui2/src/styled.rs b/crates/gpui2/src/styled.rs index 346c1a760d6a56105440bfd2a3a788497d103a66..209169a9a6ecf0d4b70c8c40af3e59b6722ff9de 100644 --- a/crates/gpui2/src/styled.rs +++ b/crates/gpui2/src/styled.rs @@ -245,6 +245,13 @@ pub trait Styled: Sized { self } + /// Sets the flex direction of the element to `column-reverse`. + /// [Docs](https://tailwindcss.com/docs/flex-direction#column-reverse) + fn flex_col_reverse(mut self) -> Self { + self.style().flex_direction = Some(FlexDirection::ColumnReverse); + self + } + /// Sets the flex direction of the element to `row`. /// [Docs](https://tailwindcss.com/docs/flex-direction#row) fn flex_row(mut self) -> Self { @@ -252,6 +259,13 @@ pub trait Styled: Sized { self } + /// Sets the flex direction of the element to `row-reverse`. + /// [Docs](https://tailwindcss.com/docs/flex-direction#row-reverse) + fn flex_row_reverse(mut self) -> Self { + self.style().flex_direction = Some(FlexDirection::RowReverse); + self + } + /// Sets the element to allow a flex item to grow and shrink as needed, ignoring its initial size. /// [Docs](https://tailwindcss.com/docs/flex#flex-1) fn flex_1(mut self) -> Self { From f798b193d0d40c91abcc67a57e571ae744a33e15 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 7 Dec 2023 01:46:28 -0500 Subject: [PATCH 03/15] WIP --- crates/feedback2/src/feedback_modal.rs | 65 ++++++++++--------- crates/ui2/src/components/button/button.rs | 48 +++++++++----- .../ui2/src/components/button/button_like.rs | 8 +++ crates/ui2/src/components/icon.rs | 3 +- crates/ui2/src/prelude.rs | 2 +- 5 files changed, 79 insertions(+), 47 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index b4d4b08d54aa19027d8f26cf767a4070e1355a51..aa6f3910a1bec92ac60562c5e45aea7c2391a34b 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -6,15 +6,15 @@ use db::kvp::KEY_VALUE_STORE; use editor::{Editor, EditorEvent}; use futures::AsyncReadExt; use gpui::{ - div, red, rems, serde_json, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, - FocusableView, Model, PromptLevel, Render, Task, View, ViewContext, + div, rems, serde_json, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, + Model, PromptLevel, Render, Task, View, ViewContext, }; use isahc::Request; use language::Buffer; use project::Project; use regex::Regex; use serde_derive::Serialize; -use ui::{prelude::*, Button, ButtonStyle, Label, Tooltip}; +use ui::{prelude::*, Button, ButtonStyle, IconPosition, Label, Tooltip}; use util::ResultExt; use workspace::Workspace; @@ -285,29 +285,22 @@ impl Render for FeedbackModal { 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.)) - .min_h(rems(24.)) - .max_h(rems(42.)) - .gap_2() + .h(rems(32.)) .child( v_stack() - .p_4() - .child( - div() - .size_full() - .child(Label::new("Give Feedback").color(Color::Default)) - .child(Label::new("This editor supports markdown").color(Color::Muted)), - ), + .px_4() + .pt_4() + .pb_2() + .child(Label::new("Give Feedback").color(Color::Default)) + .child(Label::new("This editor supports markdown").color(Color::Muted)), ) - .child(v_stack() - .p_4() - .child( + .child( div() .flex_1() .bg(cx.theme().colors().editor_background) @@ -317,37 +310,49 @@ impl Render for FeedbackModal { ) .child( div().child( - Label::new(format!( - "Characters: {}", - characters_remaining - )) + Label::new( + if !valid_character_count && characters_remaining < 0 { + "Feedback must be at least 10 characters.".to_string() + } else if !valid_character_count && characters_remaining > 5000 { + "Feedback must be less than 5000 characters.".to_string() + } else { + format!( + "Characters: {}", + characters_remaining + ) + } + ) .map(|this| if valid_character_count { this.color(Color::Success) } else { this.color(Color::Error) - } ) - ), - ) - .child( - div() + ) + .child( + v_stack() + .p_4() + .child( + h_stack() .bg(cx.theme().colors().editor_background) .border() .border_color(cx.theme().colors().border) - .child(self.email_address_editor.clone()) + .child(self.email_address_editor.clone())) ) .child( h_stack() + .p_4() .justify_between() .gap_1() .child(Button::new("community_repo", "Community Repo") - .style(ButtonStyle::Filled) - .color(Color::Muted) + .style(ButtonStyle::Transparent) + .icon(Icon::ExternalLink) + .icon_position(IconPosition::End) + .icon_size(IconSize::Small) .on_click(open_community_repo) ) - .child(h_stack().justify_between().gap_1() + .child(h_stack().gap_1() .child( Button::new("cancel_feedback", "Cancel") .style(ButtonStyle::Subtle) diff --git a/crates/ui2/src/components/button/button.rs b/crates/ui2/src/components/button/button.rs index c1262321cede804c65199ae9e206138796e9024f..607b6c8a61df5cc6e8ccf4dc3adebc1addb886d4 100644 --- a/crates/ui2/src/components/button/button.rs +++ b/crates/ui2/src/components/button/button.rs @@ -1,6 +1,6 @@ use gpui::{AnyView, DefiniteLength}; -use crate::prelude::*; +use crate::{prelude::*, IconPosition}; use crate::{ ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize, Label, LineHeightStyle, }; @@ -14,6 +14,7 @@ pub struct Button { label_color: Option, selected_label: Option, icon: Option, + icon_position: Option, icon_size: Option, icon_color: Option, selected_icon: Option, @@ -27,6 +28,7 @@ impl Button { label_color: None, selected_label: None, icon: None, + icon_position: None, icon_size: None, icon_color: None, selected_icon: None, @@ -48,6 +50,11 @@ impl Button { self } + pub fn icon_position(mut self, icon_position: impl Into>) -> Self { + self.icon_position = icon_position.into(); + self + } + pub fn icon_size(mut self, icon_size: impl Into>) -> Self { self.icon_size = icon_size.into(); self @@ -141,19 +148,30 @@ impl RenderOnce for Button { self.label_color.unwrap_or_default() }; - self.base - .children(self.icon.map(|icon| { - ButtonIcon::new(icon) - .disabled(is_disabled) - .selected(is_selected) - .selected_icon(self.selected_icon) - .size(self.icon_size) - .color(self.icon_color) - })) - .child( - Label::new(label) - .color(label_color) - .line_height_style(LineHeightStyle::UILabel), - ) + self.base.child( + h_stack() + .gap_1() + .map(|this| { + if self.icon_position == Some(IconPosition::End) { + this.flex_row_reverse() + } else { + this + } + }) + .flex_row_reverse() + .child( + Label::new(label) + .color(label_color) + .line_height_style(LineHeightStyle::UILabel), + ) + .children(self.icon.map(|icon| { + ButtonIcon::new(icon) + .disabled(is_disabled) + .selected(is_selected) + .selected_icon(self.selected_icon) + .size(self.icon_size) + .color(self.icon_color) + })), + ) } } diff --git a/crates/ui2/src/components/button/button_like.rs b/crates/ui2/src/components/button/button_like.rs index 1a33eb2845eef9e767181bb2cc5f65ba7eb8957f..9f42c95e7e76b2f0878f30f07d9726f7356aeb6c 100644 --- a/crates/ui2/src/components/button/button_like.rs +++ b/crates/ui2/src/components/button/button_like.rs @@ -30,6 +30,13 @@ pub trait ButtonCommon: Clickable + Disableable { fn tooltip(self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self; } +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] +pub enum IconPosition { + #[default] + Start, + End, +} + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] pub enum ButtonStyle { /// A filled button with a solid background color. Provides emphasis versus @@ -344,6 +351,7 @@ impl RenderOnce for ButtonLike { .gap_1() .px_1() .bg(self.style.enabled(cx).background) + .when(self.disabled, |this| this.cursor_not_allowed()) .when(!self.disabled, |this| { this.cursor_pointer() .hover(|hover| hover.bg(self.style.hovered(cx).background)) diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index a5b09782f569c46b1b7d26c61fe09deef4d7e90e..88af3847f55a8ad4b5dddf9effdffa11a7204a73 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -51,6 +51,7 @@ pub enum Icon { CopilotDisabled, Dash, Envelope, + ExternalLink, ExclamationTriangle, Exit, File, @@ -122,13 +123,13 @@ impl Icon { Icon::Close => "icons/x.svg", Icon::Collab => "icons/user_group_16.svg", Icon::Copilot => "icons/copilot.svg", - Icon::CopilotInit => "icons/copilot_init.svg", Icon::CopilotError => "icons/copilot_error.svg", Icon::CopilotDisabled => "icons/copilot_disabled.svg", Icon::Dash => "icons/dash.svg", Icon::Envelope => "icons/feedback.svg", Icon::ExclamationTriangle => "icons/warning.svg", + Icon::ExternalLink => "icons/external_link.svg", Icon::Exit => "icons/exit.svg", Icon::File => "icons/file.svg", Icon::FileDoc => "icons/file_icons/book.svg", diff --git a/crates/ui2/src/prelude.rs b/crates/ui2/src/prelude.rs index 42fb44ed4dda4f60b7623e3985d4b7cc5482e1aa..076d34644c931a0a930efd51d1ff88d01d7af4d7 100644 --- a/crates/ui2/src/prelude.rs +++ b/crates/ui2/src/prelude.rs @@ -12,6 +12,6 @@ pub use crate::selectable::*; pub use crate::{h_stack, v_stack}; pub use crate::{Button, ButtonSize, ButtonStyle, IconButton}; pub use crate::{ButtonCommon, Color, StyledExt}; -pub use crate::{Icon, IconElement, IconSize}; +pub use crate::{Icon, IconElement, IconPosition, IconSize}; pub use crate::{Label, LabelCommon, LabelSize, LineHeightStyle}; pub use theme::ActiveTheme; From 5e5eb25aab7e4cf3aa157af47e726d11ca11a364 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 7 Dec 2023 10:50:07 -0500 Subject: [PATCH 04/15] WIP [no-ci] --- crates/feedback2/src/feedback_modal.rs | 26 +++++++++++++--------- crates/ui2/src/components/button/button.rs | 1 - 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index aa6f3910a1bec92ac60562c5e45aea7c2391a34b..32619578ed3866b0928a027260100bf75ec1e22f 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -104,6 +104,11 @@ impl FeedbackModal { let feedback_editor = cx.build_view(|cx| { let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx); + editor.set_placeholder_text( + "You can use markdown to add links or organize feedback.", + cx, + ); + // editor.set_show_gutter(false, cx); editor.set_vertical_scroll_margin(5, cx); editor }); @@ -292,19 +297,21 @@ impl Render for FeedbackModal { .min_w(rems(40.)) .max_w(rems(96.)) .h(rems(32.)) + .p_4() + .gap_4() .child( v_stack() - .px_4() - .pt_4() - .pb_2() - .child(Label::new("Give Feedback").color(Color::Default)) - .child(Label::new("This editor supports markdown").color(Color::Muted)), + .child( + // TODO: Add Headline component to `ui2` + div().text_xl().child("Share Feedback")) ) .child( div() .flex_1() .bg(cx.theme().colors().editor_background) + .p_2() .border() + .rounded_md() .border_color(cx.theme().colors().border) .child(self.feedback_editor.clone()), ) @@ -330,19 +337,18 @@ impl Render for FeedbackModal { } ) ) - .child( - v_stack() - .p_4() + .child( h_stack() .bg(cx.theme().colors().editor_background) + .p_2() .border() + .rounded_md() .border_color(cx.theme().colors().border) .child(self.email_address_editor.clone())) - ) + .child( h_stack() - .p_4() .justify_between() .gap_1() .child(Button::new("community_repo", "Community Repo") diff --git a/crates/ui2/src/components/button/button.rs b/crates/ui2/src/components/button/button.rs index 607b6c8a61df5cc6e8ccf4dc3adebc1addb886d4..fc7ca2c12872142e5e41a8a2a96e6c8fe764697a 100644 --- a/crates/ui2/src/components/button/button.rs +++ b/crates/ui2/src/components/button/button.rs @@ -158,7 +158,6 @@ impl RenderOnce for Button { this } }) - .flex_row_reverse() .child( Label::new(label) .color(label_color) From 794b79580010e115aa23e16331bfb7d863837506 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 7 Dec 2023 12:04:04 -0500 Subject: [PATCH 05/15] Add TODO --- crates/feedback2/src/feedback_modal.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 32619578ed3866b0928a027260100bf75ec1e22f..148772c296039272ef30deaf93ca9edd181d1fbe 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -399,3 +399,5 @@ impl Render for FeedbackModal { ) } } + +// TODO: Add compilation flags to enable debug mode, where we can simulate sending feedback that both succeeds and fails, so we can test the UI From ef4bc5e20b6839dbad93e52c9aec5a6036d7ba08 Mon Sep 17 00:00:00 2001 From: Nate Butler Date: Thu, 7 Dec 2023 12:59:51 -0500 Subject: [PATCH 06/15] Remove static status bar icons --- crates/workspace2/src/status_bar.rs | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index 07c48293b5ca720dbc295003e2a3b578f999655c..22e2fa128d24697782a92c6ccfdde3d08bba7fc4 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -48,30 +48,7 @@ impl Render for StatusBar { .h_8() .bg(cx.theme().colors().status_bar_background) .child(h_stack().gap_1().child(self.render_left_tools(cx))) - .child( - h_stack() - .gap_4() - .child( - h_stack().gap_1().child( - // Feedback Tool - div() - .border() - .border_color(gpui::red()) - .child(IconButton::new("status-feedback", Icon::Envelope)), - ), - ) - .child( - // Right Dock - h_stack().gap_1().child( - // Terminal - div() - .border() - .border_color(gpui::red()) - .child(IconButton::new("status-chat", Icon::MessageBubbles)), - ), - ) - .child(self.render_right_tools(cx)), - ) + .child(h_stack().gap_4().child(self.render_right_tools(cx))) } } From 0ee4ad6ba0c4dcaf48a5a568f0e1c3593b7e6aa6 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 7 Dec 2023 13:00:49 -0500 Subject: [PATCH 07/15] Skip using map --- crates/feedback2/src/feedback_modal.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 148772c296039272ef30deaf93ca9edd181d1fbe..c61d17d63c256f270578234f76acfdfdaac1d3cd 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -329,11 +329,11 @@ impl Render for FeedbackModal { ) } ) - .map(|this| + .color( if valid_character_count { - this.color(Color::Success) + Color::Success } else { - this.color(Color::Error) + Color::Error } ) ) From 8b9b19195d02f104b9fc51805d07ea6ca2c83503 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 7 Dec 2023 13:19:03 -0500 Subject: [PATCH 08/15] Fix bug with how characters limits are being displayed --- crates/feedback2/src/feedback_modal.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index c61d17d63c256f270578234f76acfdfdaac1d3cd..1b746e1f1f2abd06644e003562b3188b40238aff 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -256,12 +256,6 @@ impl Render for FeedbackModal { }; let valid_character_count = FEEDBACK_CHAR_LIMIT.contains(&self.character_count); - let characters_remaining = - if valid_character_count || self.character_count > *FEEDBACK_CHAR_LIMIT.end() { - *FEEDBACK_CHAR_LIMIT.end() as i32 - self.character_count as i32 - } else { - self.character_count as i32 - *FEEDBACK_CHAR_LIMIT.start() as i32 - }; let allow_submission = valid_character_count && valid_email_address && !self.pending_submission; @@ -318,14 +312,14 @@ impl Render for FeedbackModal { .child( div().child( Label::new( - if !valid_character_count && characters_remaining < 0 { - "Feedback must be at least 10 characters.".to_string() - } else if !valid_character_count && characters_remaining > 5000 { - "Feedback must be less than 5000 characters.".to_string() + if self.character_count < *FEEDBACK_CHAR_LIMIT.start() { + format!("Feedback must be at least {} characters.", FEEDBACK_CHAR_LIMIT.start()) + } else if self.character_count > *FEEDBACK_CHAR_LIMIT.end() { + format!("Feedback must be less than {} characters.", FEEDBACK_CHAR_LIMIT.end()) } else { format!( "Characters: {}", - characters_remaining + *FEEDBACK_CHAR_LIMIT.end() - self.character_count ) } ) From 1f51f74670c78134ae22c14476e10532cc58bafe Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Thu, 7 Dec 2023 22:24:32 -0500 Subject: [PATCH 09/15] Add TODO --- crates/feedback2/src/feedback_modal.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 1b746e1f1f2abd06644e003562b3188b40238aff..6de05b6496d32bd5032682847fac2381bdad3cd3 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -395,3 +395,4 @@ impl Render for FeedbackModal { } // TODO: Add compilation flags to enable debug mode, where we can simulate sending feedback that both succeeds and fails, so we can test the UI +// TODO: Maybe store email address whenever the modal is closed, versus just on submit, so users can remove it if they want without submitting From 260a75300525e796cec0f9fe9f3782819af1bd9f Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 8 Dec 2023 11:33:18 -0500 Subject: [PATCH 10/15] Fix rustfmt --- crates/feedback2/src/feedback_modal.rs | 180 +++++++++++++------------ 1 file changed, 93 insertions(+), 87 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 6de05b6496d32bd5032682847fac2381bdad3cd3..865cbcc4de4a79d2e2a61ce6fc76532471b6df3c 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -284,6 +284,10 @@ impl Render for FeedbackModal { let open_community_repo = cx.listener(|_, _, cx| cx.dispatch_action(Box::new(OpenZedCommunityRepo))); + // Moved this here because providing it inline breaks rustfmt + let provide_an_email_address = + "Provide an email address if you want us to be able to reply."; + v_stack() .elevation_3(cx) .key_context("GiveFeedback") @@ -293,103 +297,105 @@ impl Render for FeedbackModal { .h(rems(32.)) .p_4() .gap_4() + .child(v_stack().child( + // TODO: Add Headline component to `ui2` + div().text_xl().child("Share Feedback"), + )) .child( - v_stack() - .child( - // TODO: Add Headline component to `ui2` - div().text_xl().child("Share Feedback")) - ) - .child( - div() - .flex_1() - .bg(cx.theme().colors().editor_background) - .p_2() - .border() - .rounded_md() - .border_color(cx.theme().colors().border) - .child(self.feedback_editor.clone()), - ) - .child( - div().child( - Label::new( - if self.character_count < *FEEDBACK_CHAR_LIMIT.start() { - format!("Feedback must be at least {} characters.", FEEDBACK_CHAR_LIMIT.start()) - } else if self.character_count > *FEEDBACK_CHAR_LIMIT.end() { - format!("Feedback must be less than {} characters.", FEEDBACK_CHAR_LIMIT.end()) - } else { - format!( - "Characters: {}", - *FEEDBACK_CHAR_LIMIT.end() - self.character_count - ) - } - ) - .color( - if valid_character_count { - Color::Success - } else { - Color::Error - } - ) - ) - - .child( - h_stack() + div() + .flex_1() .bg(cx.theme().colors().editor_background) .p_2() .border() .rounded_md() .border_color(cx.theme().colors().border) - .child(self.email_address_editor.clone())) - - .child( - h_stack() - .justify_between() - .gap_1() - .child(Button::new("community_repo", "Community Repo") - .style(ButtonStyle::Transparent) - .icon(Icon::ExternalLink) - .icon_position(IconPosition::End) - .icon_size(IconSize::Small) - .on_click(open_community_repo) - ) - .child(h_stack().gap_1() + .child(self.feedback_editor.clone()), + ) + .child( + div() + .child( + Label::new(if self.character_count < *FEEDBACK_CHAR_LIMIT.start() { + format!( + "Feedback must be at least {} characters.", + FEEDBACK_CHAR_LIMIT.start() + ) + } else if self.character_count > *FEEDBACK_CHAR_LIMIT.end() { + format!( + "Feedback must be less than {} characters.", + FEEDBACK_CHAR_LIMIT.end() + ) + } else { + format!( + "Characters: {}", + *FEEDBACK_CHAR_LIMIT.end() - self.character_count + ) + }) + .color(if valid_character_count { + Color::Success + } else { + Color::Error + }), + ) + .child( + h_stack() + .bg(cx.theme().colors().editor_background) + .p_2() + .border() + .rounded_md() + .border_color(cx.theme().colors().border) + .child(self.email_address_editor.clone()), + ) + .child( + h_stack() + .justify_between() + .gap_1() .child( - Button::new("cancel_feedback", "Cancel") - .style(ButtonStyle::Subtle) - .color(Color::Muted) - // TODO: replicate this logic when clicking outside the modal - // TODO: Will require somehow overriding the modal dismal default behavior - .map(|this| { - if has_feedback { - this.on_click(dismiss_prompt) - } else { - this.on_click(dismiss) - } - }) + Button::new("community_repo", "Community Repo") + .style(ButtonStyle::Transparent) + .icon(Icon::ExternalLink) + .icon_position(IconPosition::End) + .icon_size(IconSize::Small) + .on_click(open_community_repo), ) .child( - Button::new("send_feedback", submit_button_text) - .color(Color::Accent) - .style(ButtonStyle::Filled) - // 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.", - None, - "Provide an email address if you want us to be able to reply.", - cx, - ) - }) - .when(!allow_submission, |this| this.disabled(true)) + h_stack() + .gap_1() + .child( + Button::new("cancel_feedback", "Cancel") + .style(ButtonStyle::Subtle) + .color(Color::Muted) + // TODO: replicate this logic when clicking outside the modal + // TODO: Will require somehow overriding the modal dismal default behavior + .map(|this| { + if has_feedback { + this.on_click(dismiss_prompt) + } else { + this.on_click(dismiss) + } + }), + ) + .child( + Button::new("send_feedback", submit_button_text) + .color(Color::Accent) + .style(ButtonStyle::Filled) + // 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.", + None, + provide_an_email_address, + cx, + ) + }) + .when(!allow_submission, |this| this.disabled(true)), + ), ), - ) - - ) + ), ) } } From b66e1d2d58b562bb30a6ee5c2ef7c0d48bb87e38 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 8 Dec 2023 11:35:49 -0500 Subject: [PATCH 11/15] Fix compiler error --- crates/feedback2/src/feedback_modal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 865cbcc4de4a79d2e2a61ce6fc76532471b6df3c..0cee05c8f8af22943b5313f75ed4fd34187b2563 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -384,7 +384,7 @@ impl Render for FeedbackModal { .on_click(cx.listener(|this, _, cx| { let _ = this.submit(cx); })) - .tooltip(|cx| { + .tooltip(move |cx| { Tooltip::with_meta( "Submit feedback to the Zed team.", None, From 4596e7a68a6bc5729787f91ba2d9404397f0ede0 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 8 Dec 2023 11:39:10 -0500 Subject: [PATCH 12/15] Use consistent text --- crates/feedback2/src/deploy_feedback_button.rs | 2 +- crates/feedback2/src/feedback_modal.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/feedback2/src/deploy_feedback_button.rs b/crates/feedback2/src/deploy_feedback_button.rs index e5884cf9b185528b741cfa3b8dde4e8fe55b7812..3b28c64dc3a57c51937f636c1693ea779aa1bf0d 100644 --- a/crates/feedback2/src/deploy_feedback_button.rs +++ b/crates/feedback2/src/deploy_feedback_button.rs @@ -32,7 +32,7 @@ impl Render for DeployFeedbackButton { IconButton::new("give-feedback", Icon::Envelope) .style(ui::ButtonStyle::Subtle) .selected(is_open) - .tooltip(|cx| Tooltip::text("Give Feedback", cx)) + .tooltip(|cx| Tooltip::text("Share Feedback", cx)) .on_click(|_, cx| { cx.dispatch_action(Box::new(GiveFeedback)); }) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 0cee05c8f8af22943b5313f75ed4fd34187b2563..5ac2197609e3e2811678ccc9a50825badc27240e 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -263,9 +263,9 @@ impl Render for FeedbackModal { let has_feedback = self.feedback_editor.read(cx).text_option(cx).is_some(); let submit_button_text = if self.pending_submission { - "Sending..." + "Submitting..." } else { - "Send Feedback" + "Submit" }; let dismiss = cx.listener(|_, _, cx| { cx.emit(DismissEvent); @@ -379,7 +379,7 @@ impl Render for FeedbackModal { .color(Color::Accent) .style(ButtonStyle::Filled) // 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 errors: show popup with error, don't close modal, set text back to "Submit", and re-enable button // TODO: If submit is successful, close the modal .on_click(cx.listener(|this, _, cx| { let _ = this.submit(cx); From 63cc9e506801694f3413f6155834751652811833 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 8 Dec 2023 13:07:16 -0500 Subject: [PATCH 13/15] Move character counter up above editor in feedback modal --- crates/feedback2/src/feedback_modal.rs | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 5ac2197609e3e2811678ccc9a50825badc27240e..ada844ecdac11bc971b9edb894b3718ede8be69f 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -301,6 +301,29 @@ impl Render for FeedbackModal { // TODO: Add Headline component to `ui2` div().text_xl().child("Share Feedback"), )) + .child( + Label::new(if self.character_count < *FEEDBACK_CHAR_LIMIT.start() { + format!( + "Feedback must be at least {} characters.", + FEEDBACK_CHAR_LIMIT.start() + ) + } else if self.character_count > *FEEDBACK_CHAR_LIMIT.end() { + format!( + "Feedback must be less than {} characters.", + FEEDBACK_CHAR_LIMIT.end() + ) + } else { + format!( + "Characters: {}", + *FEEDBACK_CHAR_LIMIT.end() - self.character_count + ) + }) + .color(if valid_character_count { + Color::Success + } else { + Color::Error + }), + ) .child( div() .flex_1() @@ -313,29 +336,6 @@ impl Render for FeedbackModal { ) .child( div() - .child( - Label::new(if self.character_count < *FEEDBACK_CHAR_LIMIT.start() { - format!( - "Feedback must be at least {} characters.", - FEEDBACK_CHAR_LIMIT.start() - ) - } else if self.character_count > *FEEDBACK_CHAR_LIMIT.end() { - format!( - "Feedback must be less than {} characters.", - FEEDBACK_CHAR_LIMIT.end() - ) - } else { - format!( - "Characters: {}", - *FEEDBACK_CHAR_LIMIT.end() - self.character_count - ) - }) - .color(if valid_character_count { - Color::Success - } else { - Color::Error - }), - ) .child( h_stack() .bg(cx.theme().colors().editor_background) From be6c909587c5c3d852288f7cb03e86f7e0875b1a Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 8 Dec 2023 13:13:40 -0500 Subject: [PATCH 14/15] Remove some unused imports --- crates/feedback2/src/feedback_modal.rs | 2 +- crates/workspace2/src/status_bar.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index ada844ecdac11bc971b9edb894b3718ede8be69f..23d8c38626e5bd076a57ff3d32d6f238d9333e60 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -14,7 +14,7 @@ use language::Buffer; use project::Project; use regex::Regex; use serde_derive::Serialize; -use ui::{prelude::*, Button, ButtonStyle, IconPosition, Label, Tooltip}; +use ui::{prelude::*, Button, ButtonStyle, IconPosition, Tooltip}; use util::ResultExt; use workspace::Workspace; diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index 22e2fa128d24697782a92c6ccfdde3d08bba7fc4..c095fd03b06f3d329e6bbbabf1f94252853d763d 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -6,7 +6,7 @@ use gpui::{ WindowContext, }; use ui::prelude::*; -use ui::{h_stack, Icon, IconButton}; +use ui::{h_stack}; use util::ResultExt; pub trait StatusItemView: Render { From fdde76c1a5465fda848d0e5107d902c81302fd31 Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Fri, 8 Dec 2023 13:15:12 -0500 Subject: [PATCH 15/15] Cargo fmt --- crates/workspace2/src/status_bar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index c095fd03b06f3d329e6bbbabf1f94252853d763d..d198b0485e26aed6660b9e8e6bb320daf7d16617 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -5,8 +5,8 @@ use gpui::{ div, AnyView, Div, IntoElement, ParentElement, Render, Styled, Subscription, View, ViewContext, WindowContext, }; +use ui::h_stack; use ui::prelude::*; -use ui::{h_stack}; use util::ResultExt; pub trait StatusItemView: Render {