From eb02834582964b00429a2a2f6c789df67272457d Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 5 Jan 2023 17:58:52 -0500 Subject: [PATCH 1/5] In-app feedback WIP --- crates/editor/src/editor.rs | 9 + crates/theme/src/theme.rs | 17 ++ crates/workspace/src/pane.rs | 6 + crates/zed/src/feedback.rs | 50 ----- crates/zed/src/feedback_popover.rs | 326 +++++++++++++++++++++++++++++ crates/zed/src/main.rs | 5 +- crates/zed/src/system_specs.rs | 2 + crates/zed/src/zed.rs | 4 +- 8 files changed, 366 insertions(+), 53 deletions(-) delete mode 100644 crates/zed/src/feedback.rs create mode 100644 crates/zed/src/feedback_popover.rs diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index d8ee49866b..f63d44ee67 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -990,6 +990,15 @@ impl Editor { Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx) } + pub fn multi_line( + field_editor_style: Option>, + cx: &mut ViewContext, + ) -> Self { + let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); + let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx)); + Self::new(EditorMode::Full, buffer, None, field_editor_style, cx) + } + pub fn auto_height( max_lines: usize, field_editor_style: Option>, diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index bf6cb57adb..3ce8894238 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -25,6 +25,7 @@ pub struct Theme { pub command_palette: CommandPalette, pub picker: Picker, pub editor: Editor, + // pub feedback_box: Editor, pub search: Search, pub project_diagnostics: ProjectDiagnostics, pub breadcrumbs: ContainedText, @@ -119,6 +120,22 @@ pub struct ContactList { pub calling_indicator: ContainedText, } +// TODO FEEDBACK: Remove or use this +// #[derive(Deserialize, Default)] +// pub struct FeedbackPopover { +// #[serde(flatten)] +// pub container: ContainerStyle, +// pub height: f32, +// pub width: f32, +// pub invite_row_height: f32, +// pub invite_row: Interactive, +// } + +// #[derive(Deserialize, Default)] +// pub struct FeedbackBox { +// pub feedback_editor: FieldEditor, +// } + #[derive(Deserialize, Default)] pub struct ProjectRow { #[serde(flatten)] diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 618c650e02..5456ecaf60 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -95,6 +95,11 @@ pub struct DeployNewMenu { position: Vector2F, } +#[derive(Clone, PartialEq)] +pub struct DeployFeedbackModal { + position: Vector2F, +} + impl_actions!(pane, [GoBack, GoForward, ActivateItem]); impl_internal_actions!( pane, @@ -104,6 +109,7 @@ impl_internal_actions!( DeployNewMenu, DeployDockMenu, MoveItem, + DeployFeedbackModal ] ); diff --git a/crates/zed/src/feedback.rs b/crates/zed/src/feedback.rs deleted file mode 100644 index 55597312ae..0000000000 --- a/crates/zed/src/feedback.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::OpenBrowser; -use gpui::{ - elements::{MouseEventHandler, Text}, - platform::CursorStyle, - Element, Entity, MouseButton, RenderContext, View, -}; -use settings::Settings; -use workspace::{item::ItemHandle, StatusItemView}; - -pub const NEW_ISSUE_URL: &str = "https://github.com/zed-industries/feedback/issues/new/choose"; - -pub struct FeedbackLink; - -impl Entity for FeedbackLink { - type Event = (); -} - -impl View for FeedbackLink { - fn ui_name() -> &'static str { - "FeedbackLink" - } - - fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> gpui::ElementBox { - MouseEventHandler::::new(0, cx, |state, cx| { - let theme = &cx.global::().theme; - let theme = &theme.workspace.status_bar.feedback; - Text::new( - "Give Feedback".to_string(), - theme.style_for(state, false).clone(), - ) - .boxed() - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { - cx.dispatch_action(OpenBrowser { - url: NEW_ISSUE_URL.into(), - }) - }) - .boxed() - } -} - -impl StatusItemView for FeedbackLink { - fn set_active_pane_item( - &mut self, - _: Option<&dyn ItemHandle>, - _: &mut gpui::ViewContext, - ) { - } -} diff --git a/crates/zed/src/feedback_popover.rs b/crates/zed/src/feedback_popover.rs new file mode 100644 index 0000000000..52397562f9 --- /dev/null +++ b/crates/zed/src/feedback_popover.rs @@ -0,0 +1,326 @@ +use std::{ops::Range, sync::Arc}; + +use anyhow::bail; +use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN}; +use editor::Editor; +use futures::AsyncReadExt; +use gpui::{ + actions, + elements::{ + AnchorCorner, ChildView, Flex, MouseEventHandler, Overlay, OverlayFitMode, ParentElement, + Stack, Text, + }, + serde_json, CursorStyle, Element, ElementBox, Entity, MouseButton, MutableAppContext, + RenderContext, View, ViewContext, ViewHandle, +}; +use isahc::Request; +use lazy_static::lazy_static; +use serde::Serialize; +use settings::Settings; +use workspace::{item::ItemHandle, StatusItemView}; + +use crate::{feedback_popover, system_specs::SystemSpecs}; + +/* + TODO FEEDBACK + + Next steps from Mikayla: + 1: Find the bottom bar height and maybe guess some feedback button widths? + Basically, just use to position the modal + 2: Look at ContactList::render() and ContactPopover::render() for clues on how + to make the modal look nice. Copy the theme values from the contact list styles + + Now + Fix all layout issues, theming, buttons, etc + Make multi-line editor without line numbers + Some sort of feedback when something fails or succeeds + Naming of all UI stuff and separation out into files (follow a convention already in place) + Disable submit button when text length is 0 + Should we store staff boolean? + Put behind experiments flag + Move to separate crate + Render a character counter + All warnings + Remove all comments + Later + If a character limit is imposed, switch submit button over to a "GitHub Issue" button + Should editor by treated as a markdown file + Limit characters? + Disable submit button when text length is GTE to character limit + + Pay for AirTable + Add AirTable to system architecture diagram in Figma +*/ + +lazy_static! { + pub static ref ZED_SERVER_URL: String = + std::env::var("ZED_SERVER_URL").unwrap_or_else(|_| "https://zed.dev".to_string()); +} + +const FEEDBACK_CHAR_COUNT_RANGE: Range = Range { + start: 5, + end: 1000, +}; + +actions!(feedback, [ToggleFeedbackPopover, SubmitFeedback]); + +pub fn init(cx: &mut MutableAppContext) { + cx.add_action(FeedbackButton::toggle_feedback); + cx.add_action(FeedbackPopover::submit_feedback); +} + +pub struct FeedbackButton { + feedback_popover: Option>, +} + +impl FeedbackButton { + pub fn new() -> Self { + Self { + feedback_popover: None, + } + } + + pub fn toggle_feedback(&mut self, _: &ToggleFeedbackPopover, cx: &mut ViewContext) { + match self.feedback_popover.take() { + Some(_) => {} + None => { + let popover_view = cx.add_view(|_cx| FeedbackPopover::new(_cx)); + self.feedback_popover = Some(popover_view.clone()); + } + } + + cx.notify(); + } +} + +impl Entity for FeedbackButton { + type Event = (); +} + +impl View for FeedbackButton { + fn ui_name() -> &'static str { + "FeedbackButton" + } + + fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox { + Stack::new() + .with_child( + MouseEventHandler::::new(0, cx, |state, cx| { + let theme = &cx.global::().theme; + let theme = &theme.workspace.status_bar.feedback; + + Text::new( + "Give Feedback".to_string(), + theme + .style_for(state, self.feedback_popover.is_some()) + .clone(), + ) + .boxed() + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, |_, cx| { + cx.dispatch_action(ToggleFeedbackPopover) + }) + .boxed(), + ) + .with_children(self.feedback_popover.as_ref().map(|popover| { + Overlay::new( + ChildView::new(popover, cx) + .contained() + // .with_height(theme.contact_list.user_query_editor_height) + // .with_margin_top(-50.0) + // .with_margin_left(titlebar.toggle_contacts_button.default.button_width) + // .with_margin_right(-titlebar.toggle_contacts_button.default.button_width) + .boxed(), + ) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .boxed() + })) + .boxed() + } +} + +impl StatusItemView for FeedbackButton { + fn set_active_pane_item( + &mut self, + _: Option<&dyn ItemHandle>, + _: &mut gpui::ViewContext, + ) { + // N/A + } +} + +pub struct FeedbackPopover { + feedback_editor: ViewHandle, + // _subscriptions: Vec, +} + +impl Entity for FeedbackPopover { + type Event = (); +} + +#[derive(Serialize)] +struct FeedbackRequestBody<'a> { + feedback_text: &'a str, + metrics_id: Option>, + system_specs: SystemSpecs, + token: &'a str, +} + +impl FeedbackPopover { + pub fn new(cx: &mut ViewContext) -> Self { + let feedback_editor = cx.add_view(|cx| { + let editor = Editor::multi_line( + Some(Arc::new(|theme| { + theme.contact_list.user_query_editor.clone() + })), + cx, + ); + editor + }); + + cx.focus(&feedback_editor); + + cx.subscribe(&feedback_editor, |this, _, event, cx| { + if let editor::Event::BufferEdited = event { + let buffer_len = this.feedback_editor.read(cx).buffer().read(cx).len(cx); + let feedback_chars_remaining = FEEDBACK_CHAR_COUNT_RANGE.end - buffer_len; + dbg!(feedback_chars_remaining); + } + }) + .detach(); + + // let active_call = ActiveCall::global(cx); + // let mut subscriptions = Vec::new(); + // subscriptions.push(cx.observe(&user_store, |this, _, cx| this.update_entries(cx))); + // subscriptions.push(cx.observe(&active_call, |this, _, cx| this.update_entries(cx))); + let this = Self { + feedback_editor, // _subscriptions: subscriptions, + }; + // this.update_entries(cx); + this + } + + fn submit_feedback(&mut self, _: &SubmitFeedback, cx: &mut ViewContext<'_, Self>) { + let feedback_text = self.feedback_editor.read(cx).text(cx); + let http_client = cx.global::>().clone(); + let system_specs = SystemSpecs::new(cx); + let feedback_endpoint = format!("{}/api/feedback", *ZED_SERVER_URL); + + cx.spawn(|this, async_cx| { + async move { + // TODO FEEDBACK: Use or remove + // this.read_with(&async_cx, |this, cx| { + // // Now we have a &self and a &AppContext + // }); + + let metrics_id = None; + + let request = FeedbackRequestBody { + feedback_text: &feedback_text, + metrics_id, + system_specs, + token: ZED_SECRET_CLIENT_TOKEN, + }; + + let json_bytes = serde_json::to_vec(&request)?; + + let request = Request::post(feedback_endpoint) + .header("content-type", "application/json") + .body(json_bytes.into())?; + + let mut response = http_client.send(request).await?; + let mut body = String::new(); + response.body_mut().read_to_string(&mut body).await?; + + let response_status = response.status(); + + dbg!(response_status); + + if !response_status.is_success() { + // TODO FEEDBACK: Do some sort of error reporting here for if store fails + bail!("Error") + } + + // TODO FEEDBACK: Use or remove + // Will need to handle error cases + // async_cx.update(|cx| { + // this.update(cx, |this, cx| { + // this.handle_error(error); + // cx.notify(); + // cx.dispatch_action(ShowErrorPopover); + // this.error_text = "Embedding failed" + // }) + // }); + + Ok(()) + } + }) + .detach(); + } +} + +impl View for FeedbackPopover { + fn ui_name() -> &'static str { + "FeedbackPopover" + } + + fn render(&mut self, cx: &mut RenderContext) -> ElementBox { + enum SubmitFeedback {} + + let theme = cx.global::().theme.clone(); + let status_bar_height = theme.workspace.status_bar.height; + let submit_feedback_text_button_height = 20.0; + + // I'd like to just define: + + // 1. Overall popover width x height dimensions + // 2. Submit Feedback button height dimensions + // 3. Allow editor to dynamically fill in the remaining space + + Flex::column() + .with_child( + Flex::row() + .with_child( + ChildView::new(self.feedback_editor.clone(), cx) + .contained() + .with_style(theme.contact_list.user_query_editor.container) + .flex(1., true) + .boxed(), + ) + .constrained() + .with_width(theme.contacts_popover.width) + .with_height(theme.contacts_popover.height - submit_feedback_text_button_height) + .boxed(), + ) + .with_child( + MouseEventHandler::::new(0, cx, |state, _| { + let theme = &theme.workspace.status_bar.feedback; + + Text::new( + "Submit Feedback".to_string(), + theme.style_for(state, true).clone(), + ) + .constrained() + .with_height(submit_feedback_text_button_height) + .boxed() + }) + .with_cursor_style(CursorStyle::PointingHand) + .on_click(MouseButton::Left, |_, cx| { + cx.dispatch_action(feedback_popover::SubmitFeedback) + }) + .on_click(MouseButton::Left, |_, cx| { + cx.dispatch_action(feedback_popover::ToggleFeedbackPopover) + }) + .boxed(), + ) + .contained() + .with_style(theme.contacts_popover.container) + .constrained() + .with_width(theme.contacts_popover.width + 200.0) + .with_height(theme.contacts_popover.height) + .boxed() + } +} diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 5ac7cb36b6..90527af555 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -41,7 +41,7 @@ use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt}; use workspace::{ self, item::ItemHandle, notifications::NotifyResultExt, AppState, NewFile, OpenPaths, Workspace, }; -use zed::{self, build_window_options, initialize_workspace, languages, menus}; +use zed::{self, build_window_options, feedback_popover, initialize_workspace, languages, menus}; fn main() { let http = http::client(); @@ -108,6 +108,9 @@ fn main() { watch_settings_file(default_settings, settings_file_content, themes.clone(), cx); watch_keymap_file(keymap_file, cx); + cx.set_global(http.clone()); + + feedback_popover::init(cx); context_menu::init(cx); project::Project::init(&client); client::init(client.clone(), cx); diff --git a/crates/zed/src/system_specs.rs b/crates/zed/src/system_specs.rs index b6c2c0fcba..fc55f76f35 100644 --- a/crates/zed/src/system_specs.rs +++ b/crates/zed/src/system_specs.rs @@ -2,9 +2,11 @@ use std::{env, fmt::Display}; use gpui::AppContext; use human_bytes::human_bytes; +use serde::Serialize; use sysinfo::{System, SystemExt}; use util::channel::ReleaseChannel; +#[derive(Debug, Serialize)] pub struct SystemSpecs { app_version: &'static str, release_channel: &'static str, diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index e6d50f43af..527da286d2 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,4 +1,4 @@ -mod feedback; +pub mod feedback_popover; pub mod languages; pub mod menus; pub mod system_specs; @@ -369,7 +369,7 @@ pub fn initialize_workspace( let activity_indicator = activity_indicator::ActivityIndicator::new(workspace, app_state.languages.clone(), cx); let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new()); - let feedback_link = cx.add_view(|_| feedback::FeedbackLink); + let feedback_link = cx.add_view(|_| feedback_popover::FeedbackButton::new()); workspace.status_bar().update(cx, |status_bar, cx| { status_bar.add_left_item(diagnostic_summary, cx); status_bar.add_left_item(activity_indicator, cx); From 404f59090cfd387cb33b11ad5e80336cd4bcb2c4 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 5 Jan 2023 18:14:28 -0500 Subject: [PATCH 2/5] Update TODO --- crates/zed/src/feedback_popover.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/zed/src/feedback_popover.rs b/crates/zed/src/feedback_popover.rs index 52397562f9..e0721078a0 100644 --- a/crates/zed/src/feedback_popover.rs +++ b/crates/zed/src/feedback_popover.rs @@ -31,6 +31,7 @@ use crate::{feedback_popover, system_specs::SystemSpecs}; to make the modal look nice. Copy the theme values from the contact list styles Now + Obtain metrics_id Fix all layout issues, theming, buttons, etc Make multi-line editor without line numbers Some sort of feedback when something fails or succeeds From 658541ec9f1e133e56a7a8ac8eca6a41633ae017 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 6 Jan 2023 15:32:28 -0500 Subject: [PATCH 3/5] Add to TODO --- crates/zed/src/feedback_popover.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/zed/src/feedback_popover.rs b/crates/zed/src/feedback_popover.rs index e0721078a0..556fb5922c 100644 --- a/crates/zed/src/feedback_popover.rs +++ b/crates/zed/src/feedback_popover.rs @@ -31,6 +31,7 @@ use crate::{feedback_popover, system_specs::SystemSpecs}; to make the modal look nice. Copy the theme values from the contact list styles Now + Rework all code relying on contacts list (search out "contacts") Obtain metrics_id Fix all layout issues, theming, buttons, etc Make multi-line editor without line numbers From 9d4cf2ff62247c0ef07fb580b640817aa2d0641f Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 6 Jan 2023 15:41:31 -0500 Subject: [PATCH 4/5] Move notes into PR --- crates/zed/src/feedback_popover.rs | 33 ------------------------------ 1 file changed, 33 deletions(-) diff --git a/crates/zed/src/feedback_popover.rs b/crates/zed/src/feedback_popover.rs index 556fb5922c..46e7116e39 100644 --- a/crates/zed/src/feedback_popover.rs +++ b/crates/zed/src/feedback_popover.rs @@ -21,39 +21,6 @@ use workspace::{item::ItemHandle, StatusItemView}; use crate::{feedback_popover, system_specs::SystemSpecs}; -/* - TODO FEEDBACK - - Next steps from Mikayla: - 1: Find the bottom bar height and maybe guess some feedback button widths? - Basically, just use to position the modal - 2: Look at ContactList::render() and ContactPopover::render() for clues on how - to make the modal look nice. Copy the theme values from the contact list styles - - Now - Rework all code relying on contacts list (search out "contacts") - Obtain metrics_id - Fix all layout issues, theming, buttons, etc - Make multi-line editor without line numbers - Some sort of feedback when something fails or succeeds - Naming of all UI stuff and separation out into files (follow a convention already in place) - Disable submit button when text length is 0 - Should we store staff boolean? - Put behind experiments flag - Move to separate crate - Render a character counter - All warnings - Remove all comments - Later - If a character limit is imposed, switch submit button over to a "GitHub Issue" button - Should editor by treated as a markdown file - Limit characters? - Disable submit button when text length is GTE to character limit - - Pay for AirTable - Add AirTable to system architecture diagram in Figma -*/ - lazy_static! { pub static ref ZED_SERVER_URL: String = std::env::var("ZED_SERVER_URL").unwrap_or_else(|_| "https://zed.dev".to_string()); From 5387695ee0ae283d0795229596c5cdf6b17ff7f7 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 6 Jan 2023 17:40:30 -0500 Subject: [PATCH 5/5] WIP Don't rely on contacts popover or contacts list for theming Add metrics id to request body Clean up some code and comments Co-Authored-By: Mikayla Maki --- crates/client/src/client.rs | 4 +++ crates/client/src/telemetry.rs | 4 +++ crates/theme/src/theme.rs | 28 +++++++--------- crates/zed/src/feedback_popover.rs | 54 +++++++++++------------------- crates/zed/src/main.rs | 2 +- styles/src/styleTree/app.ts | 2 ++ styles/src/styleTree/feedback.ts | 35 +++++++++++++++++++ 7 files changed, 79 insertions(+), 50 deletions(-) create mode 100644 styles/src/styleTree/feedback.ts diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs index 6d9ec305b6..49ac0062f8 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -1292,6 +1292,10 @@ impl Client { pub fn telemetry_log_file_path(&self) -> Option { self.telemetry.log_file_path() } + + pub fn metrics_id(&self) -> Option> { + self.telemetry.metrics_id() + } } impl WeakSubscriber { diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index ce8b713996..4e32e020eb 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -261,6 +261,10 @@ impl Telemetry { } } + pub fn metrics_id(self: &Arc) -> Option> { + self.state.lock().metrics_id.clone() + } + fn flush(self: &Arc) { let mut state = self.state.lock(); let mut events = mem::take(&mut state.queue); diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 3ce8894238..d3f0b03245 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -25,7 +25,7 @@ pub struct Theme { pub command_palette: CommandPalette, pub picker: Picker, pub editor: Editor, - // pub feedback_box: Editor, + pub feedback: Feedback, pub search: Search, pub project_diagnostics: ProjectDiagnostics, pub breadcrumbs: ContainedText, @@ -120,21 +120,19 @@ pub struct ContactList { pub calling_indicator: ContainedText, } -// TODO FEEDBACK: Remove or use this -// #[derive(Deserialize, Default)] -// pub struct FeedbackPopover { -// #[serde(flatten)] -// pub container: ContainerStyle, -// pub height: f32, -// pub width: f32, -// pub invite_row_height: f32, -// pub invite_row: Interactive, -// } +#[derive(Deserialize, Default)] +pub struct Feedback { + pub feedback_popover: FeedbackPopover, + pub feedback_editor: FieldEditor, +} -// #[derive(Deserialize, Default)] -// pub struct FeedbackBox { -// pub feedback_editor: FieldEditor, -// } +#[derive(Deserialize, Default)] +pub struct FeedbackPopover { + #[serde(flatten)] + pub container: ContainerStyle, + pub height: f32, + pub width: f32, +} #[derive(Deserialize, Default)] pub struct ProjectRow { diff --git a/crates/zed/src/feedback_popover.rs b/crates/zed/src/feedback_popover.rs index 46e7116e39..b11ab1f4ac 100644 --- a/crates/zed/src/feedback_popover.rs +++ b/crates/zed/src/feedback_popover.rs @@ -1,7 +1,7 @@ use std::{ops::Range, sync::Arc}; use anyhow::bail; -use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN}; +use client::{Client, ZED_SECRET_CLIENT_TOKEN}; use editor::Editor; use futures::AsyncReadExt; use gpui::{ @@ -93,19 +93,11 @@ impl View for FeedbackButton { .boxed(), ) .with_children(self.feedback_popover.as_ref().map(|popover| { - Overlay::new( - ChildView::new(popover, cx) - .contained() - // .with_height(theme.contact_list.user_query_editor_height) - // .with_margin_top(-50.0) - // .with_margin_left(titlebar.toggle_contacts_button.default.button_width) - // .with_margin_right(-titlebar.toggle_contacts_button.default.button_width) - .boxed(), - ) - .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopLeft) - .with_z_index(999) - .boxed() + Overlay::new(ChildView::new(popover, cx).contained().boxed()) + .with_fit_mode(OverlayFitMode::SwitchAnchor) + .with_anchor_corner(AnchorCorner::TopLeft) + .with_z_index(999) + .boxed() })) .boxed() } @@ -142,9 +134,7 @@ impl FeedbackPopover { pub fn new(cx: &mut ViewContext) -> Self { let feedback_editor = cx.add_view(|cx| { let editor = Editor::multi_line( - Some(Arc::new(|theme| { - theme.contact_list.user_query_editor.clone() - })), + Some(Arc::new(|theme| theme.feedback.feedback_editor.clone())), cx, ); editor @@ -174,19 +164,20 @@ impl FeedbackPopover { fn submit_feedback(&mut self, _: &SubmitFeedback, cx: &mut ViewContext<'_, Self>) { let feedback_text = self.feedback_editor.read(cx).text(cx); - let http_client = cx.global::>().clone(); + let zed_client = cx.global::>(); let system_specs = SystemSpecs::new(cx); let feedback_endpoint = format!("{}/api/feedback", *ZED_SERVER_URL); - cx.spawn(|this, async_cx| { + let metrics_id = zed_client.metrics_id(); + let http_client = zed_client.http_client(); + + cx.spawn(|_, _| { async move { // TODO FEEDBACK: Use or remove // this.read_with(&async_cx, |this, cx| { // // Now we have a &self and a &AppContext // }); - let metrics_id = None; - let request = FeedbackRequestBody { feedback_text: &feedback_text, metrics_id, @@ -240,28 +231,23 @@ impl View for FeedbackPopover { enum SubmitFeedback {} let theme = cx.global::().theme.clone(); - let status_bar_height = theme.workspace.status_bar.height; let submit_feedback_text_button_height = 20.0; - // I'd like to just define: - - // 1. Overall popover width x height dimensions - // 2. Submit Feedback button height dimensions - // 3. Allow editor to dynamically fill in the remaining space - Flex::column() .with_child( Flex::row() .with_child( ChildView::new(self.feedback_editor.clone(), cx) .contained() - .with_style(theme.contact_list.user_query_editor.container) + .with_style(theme.feedback.feedback_editor.container) .flex(1., true) .boxed(), ) .constrained() - .with_width(theme.contacts_popover.width) - .with_height(theme.contacts_popover.height - submit_feedback_text_button_height) + .with_width(theme.feedback.feedback_popover.width) + .with_height( + theme.feedback.feedback_popover.height - submit_feedback_text_button_height, + ) .boxed(), ) .with_child( @@ -286,10 +272,10 @@ impl View for FeedbackPopover { .boxed(), ) .contained() - .with_style(theme.contacts_popover.container) + .with_style(theme.feedback.feedback_popover.container) .constrained() - .with_width(theme.contacts_popover.width + 200.0) - .with_height(theme.contacts_popover.height) + .with_width(theme.feedback.feedback_popover.width) + .with_height(theme.feedback.feedback_popover.height) .boxed() } } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 90527af555..ce68895768 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -108,7 +108,7 @@ fn main() { watch_settings_file(default_settings, settings_file_content, themes.clone(), cx); watch_keymap_file(keymap_file, cx); - cx.set_global(http.clone()); + cx.set_global(client.clone()); feedback_popover::init(cx); context_menu::init(cx); diff --git a/styles/src/styleTree/app.ts b/styles/src/styleTree/app.ts index 267d830506..a51426b6f6 100644 --- a/styles/src/styleTree/app.ts +++ b/styles/src/styleTree/app.ts @@ -19,6 +19,7 @@ import terminal from "./terminal"; import contactList from "./contactList"; import incomingCallNotification from "./incomingCallNotification"; import { ColorScheme } from "../themes/common/colorScheme"; +import feedback from "./feedback"; export default function app(colorScheme: ColorScheme): Object { return { @@ -37,6 +38,7 @@ export default function app(colorScheme: ColorScheme): Object { projectDiagnostics: projectDiagnostics(colorScheme), projectPanel: projectPanel(colorScheme), contactsPopover: contactsPopover(colorScheme), + feedback: feedback(colorScheme), contactFinder: contactFinder(colorScheme), contactList: contactList(colorScheme), search: search(colorScheme), diff --git a/styles/src/styleTree/feedback.ts b/styles/src/styleTree/feedback.ts new file mode 100644 index 0000000000..0521949871 --- /dev/null +++ b/styles/src/styleTree/feedback.ts @@ -0,0 +1,35 @@ +import { ColorScheme } from "../themes/common/colorScheme"; +import { background, border, text } from "./components"; + +export default function feedback(colorScheme: ColorScheme) { + let layer = colorScheme.middle; + return { + feedbackEditor: { + background: background(layer, "on"), + cornerRadius: 6, + text: text(layer, "mono", "on"), + placeholderText: text(layer, "mono", "on", "disabled", { size: "xs" }), + selection: colorScheme.players[0], + border: border(layer, "on"), + padding: { + bottom: 4, + left: 8, + right: 8, + top: 4, + }, + margin: { + left: 6, + } + }, + feedbackPopover: { + background: background(layer), + cornerRadius: 6, + padding: { top: 6 }, + margin: { top: -6 }, + shadow: colorScheme.popoverShadow, + border: border(layer), + width: 500, + height: 400 + } + } +}