From eb02834582964b00429a2a2f6c789df67272457d Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 5 Jan 2023 17:58:52 -0500 Subject: [PATCH 01/24] 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 02/24] 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 03/24] 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 04/24] 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 05/24] 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 + } + } +} From 318a0b7ed007923ee73c095deac6bc9e61943a73 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 5 Jan 2023 17:58:52 -0500 Subject: [PATCH 06/24] 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 76092bbecf..67f17bc8f9 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -991,6 +991,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 e463310b98..92dd68ac1b 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 f4fa919c48..99b4c5a1a3 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 c3af91306d..9fda149191 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 1545b2ac61a8a9ea526225d4370cd230603decd5 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Thu, 5 Jan 2023 18:14:28 -0500 Subject: [PATCH 07/24] 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 9fc7f546311ba087e95e575263b05ecadfd44298 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 6 Jan 2023 15:32:28 -0500 Subject: [PATCH 08/24] 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 969477175270ee7b1411a07961ec104ecd86effa Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 6 Jan 2023 15:41:31 -0500 Subject: [PATCH 09/24] 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 0200fc5542f4a835cf67f8eccd00124d5555bd9a Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 6 Jan 2023 17:40:30 -0500 Subject: [PATCH 10/24] 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 aa46d64fcb..69cdb16116 100644 --- a/crates/client/src/client.rs +++ b/crates/client/src/client.rs @@ -1294,6 +1294,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 92dd68ac1b..3b118bbef9 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 99b4c5a1a3..fe06ca2893 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 + } + } +} From c1e61b479cf87c1c5d0cee55322b1a53da1d564f Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 9 Jan 2023 13:54:37 -0500 Subject: [PATCH 11/24] Move feedback items into a feedback crate --- Cargo.lock | 28 +++++++-- Cargo.toml | 1 + crates/feedback/Cargo.toml | 26 ++++++++ crates/feedback/src/feedback.rs | 62 +++++++++++++++++++ .../{zed => feedback}/src/feedback_popover.rs | 6 ++ crates/{zed => feedback}/src/system_specs.rs | 0 crates/zed/Cargo.toml | 4 +- crates/zed/src/main.rs | 5 +- crates/zed/src/menus.rs | 6 +- crates/zed/src/zed.rs | 48 +------------- 10 files changed, 128 insertions(+), 58 deletions(-) create mode 100644 crates/feedback/Cargo.toml create mode 100644 crates/feedback/src/feedback.rs rename crates/{zed => feedback}/src/feedback_popover.rs (97%) rename crates/{zed => feedback}/src/system_specs.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 14574cc19a..b6bd88e507 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2022,6 +2022,26 @@ dependencies = [ "instant", ] +[[package]] +name = "feedback" +version = "0.1.0" +dependencies = [ + "anyhow", + "client", + "editor", + "futures 0.3.25", + "gpui", + "human_bytes", + "isahc", + "lazy_static", + "serde", + "settings", + "sysinfo", + "urlencoding", + "util", + "workspace", +] + [[package]] name = "file-per-thread-logger" version = "0.1.5" @@ -6239,9 +6259,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.27.1" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb297c0afb439440834b4bcf02c5c9da8ec2e808e70f36b0d8e815ff403bd24" +checksum = "1620f9573034c573376acc550f3b9a2be96daeb08abb3c12c8523e1cee06e80f" dependencies = [ "cfg-if 1.0.0", "core-foundation-sys", @@ -8212,6 +8232,7 @@ dependencies = [ "easy-parallel", "editor", "env_logger", + "feedback", "file_finder", "fs", "fsevent", @@ -8219,7 +8240,6 @@ dependencies = [ "fuzzy", "go_to_line", "gpui", - "human_bytes", "ignore", "image", "indexmap", @@ -8253,7 +8273,6 @@ dependencies = [ "smallvec", "smol", "sum_tree", - "sysinfo", "tempdir", "terminal_view", "text", @@ -8282,7 +8301,6 @@ dependencies = [ "tree-sitter-typescript", "unindent", "url", - "urlencoding", "util", "vim", "workspace", diff --git a/Cargo.toml b/Cargo.toml index 1ace51dbd5..77469c0623 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ members = [ "crates/diagnostics", "crates/drag_and_drop", "crates/editor", + "crates/feedback", "crates/file_finder", "crates/fs", "crates/fsevent", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml new file mode 100644 index 0000000000..afb43f501f --- /dev/null +++ b/crates/feedback/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "feedback" +version = "0.1.0" +edition = "2021" + +[lib] +path = "src/feedback.rs" + +[features] +test-support = [] + +[dependencies] +anyhow = "1.0.38" +client = { path = "../client" } +editor = { path = "../editor" } +futures = "0.3" +gpui = { path = "../gpui" } +human_bytes = "0.4.1" +isahc = "1.7" +lazy_static = "1.4.0" +serde = { version = "1.0", features = ["derive", "rc"] } +settings = { path = "../settings" } +sysinfo = "0.27.1" +urlencoding = "2.1.2" +util = { path = "../util" } +workspace = { path = "../workspace" } \ No newline at end of file diff --git a/crates/feedback/src/feedback.rs b/crates/feedback/src/feedback.rs new file mode 100644 index 0000000000..58cb682f3b --- /dev/null +++ b/crates/feedback/src/feedback.rs @@ -0,0 +1,62 @@ +use std::sync::Arc; + +pub mod feedback_popover; +mod system_specs; +use gpui::{actions, impl_actions, ClipboardItem, ViewContext}; +use serde::Deserialize; +use system_specs::SystemSpecs; +use workspace::Workspace; + +// TODO FEEDBACK: This open brownser code is duplicated from the zed crate, where should we refactor it to? +#[derive(Deserialize, Clone, PartialEq)] +struct OpenBrowser { + url: Arc, +} + +impl_actions!(zed, [OpenBrowser]); + +actions!( + zed, + [CopySystemSpecsIntoClipboard, FileBugReport, RequestFeature,] +); + +pub fn init(cx: &mut gpui::MutableAppContext) { + feedback_popover::init(cx); + + cx.add_global_action(move |action: &OpenBrowser, cx| cx.platform().open_url(&action.url)); + + cx.add_action( + |_: &mut Workspace, _: &CopySystemSpecsIntoClipboard, cx: &mut ViewContext| { + let system_specs = SystemSpecs::new(cx).to_string(); + let item = ClipboardItem::new(system_specs.clone()); + cx.prompt( + gpui::PromptLevel::Info, + &format!("Copied into clipboard:\n\n{system_specs}"), + &["OK"], + ); + cx.write_to_clipboard(item); + }, + ); + + cx.add_action( + |_: &mut Workspace, _: &RequestFeature, cx: &mut ViewContext| { + let url = "https://github.com/zed-industries/feedback/issues/new?assignees=&labels=enhancement%2Ctriage&template=0_feature_request.yml"; + cx.dispatch_action(OpenBrowser { + url: url.into(), + }); + }, + ); + + cx.add_action( + |_: &mut Workspace, _: &FileBugReport, cx: &mut ViewContext| { + let system_specs_text = SystemSpecs::new(cx).to_string(); + let url = format!( + "https://github.com/zed-industries/feedback/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml&environment={}", + urlencoding::encode(&system_specs_text) + ); + cx.dispatch_action(OpenBrowser { + url: url.into(), + }); + }, + ); +} diff --git a/crates/zed/src/feedback_popover.rs b/crates/feedback/src/feedback_popover.rs similarity index 97% rename from crates/zed/src/feedback_popover.rs rename to crates/feedback/src/feedback_popover.rs index b11ab1f4ac..b9a9312952 100644 --- a/crates/zed/src/feedback_popover.rs +++ b/crates/feedback/src/feedback_popover.rs @@ -230,6 +230,12 @@ impl View for FeedbackPopover { fn render(&mut self, cx: &mut RenderContext) -> ElementBox { enum SubmitFeedback {} + // I'd like to just define: + + // 1. Overall popover width x height dimensions (done) + // 2. Submit Feedback button height dimensions + // 3. Allow editor to dynamically fill in the remaining space + let theme = cx.global::().theme.clone(); let submit_feedback_text_button_height = 20.0; diff --git a/crates/zed/src/system_specs.rs b/crates/feedback/src/system_specs.rs similarity index 100% rename from crates/zed/src/system_specs.rs rename to crates/feedback/src/system_specs.rs diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index d295deea71..b4b4b2475f 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -29,8 +29,8 @@ client = { path = "../client" } clock = { path = "../clock" } diagnostics = { path = "../diagnostics" } editor = { path = "../editor" } +feedback = { path = "../feedback" } file_finder = { path = "../file_finder" } -human_bytes = "0.4.1" search = { path = "../search" } fs = { path = "../fs" } fsevent = { path = "../fsevent" } @@ -49,7 +49,6 @@ recent_projects = { path = "../recent_projects" } rpc = { path = "../rpc" } settings = { path = "../settings" } sum_tree = { path = "../sum_tree" } -sysinfo = "0.27.1" text = { path = "../text" } terminal_view = { path = "../terminal_view" } theme = { path = "../theme" } @@ -110,7 +109,6 @@ tree-sitter-html = "0.19.0" tree-sitter-scheme = { git = "https://github.com/6cdh/tree-sitter-scheme", rev = "af0fd1fa452cb2562dc7b5c8a8c55551c39273b9"} tree-sitter-racket = { git = "https://github.com/zed-industries/tree-sitter-racket", rev = "eb010cf2c674c6fd9a6316a84e28ef90190fe51a"} url = "2.2" -urlencoding = "2.1.2" [dev-dependencies] call = { path = "../call", features = ["test-support"] } diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index fe06ca2893..bd13088f7f 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -14,6 +14,7 @@ use client::{ http::{self, HttpClient}, UserStore, ZED_SECRET_CLIENT_TOKEN, }; + use futures::{ channel::{mpsc, oneshot}, FutureExt, SinkExt, StreamExt, @@ -41,7 +42,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, feedback_popover, initialize_workspace, languages, menus}; +use zed::{self, build_window_options, initialize_workspace, languages, menus}; fn main() { let http = http::client(); @@ -110,12 +111,12 @@ fn main() { cx.set_global(client.clone()); - feedback_popover::init(cx); context_menu::init(cx); project::Project::init(&client); client::init(client.clone(), cx); command_palette::init(cx); editor::init(cx); + feedback::init(cx); go_to_line::init(cx); file_finder::init(cx); outline::init(cx); diff --git a/crates/zed/src/menus.rs b/crates/zed/src/menus.rs index b46e8ad703..834eb751e1 100644 --- a/crates/zed/src/menus.rs +++ b/crates/zed/src/menus.rs @@ -340,15 +340,15 @@ pub fn menus() -> Vec> { MenuItem::Separator, MenuItem::Action { name: "Copy System Specs Into Clipboard", - action: Box::new(crate::CopySystemSpecsIntoClipboard), + action: Box::new(feedback::CopySystemSpecsIntoClipboard), }, MenuItem::Action { name: "File Bug Report", - action: Box::new(crate::FileBugReport), + action: Box::new(feedback::FileBugReport), }, MenuItem::Action { name: "Request Feature", - action: Box::new(crate::RequestFeature), + action: Box::new(feedback::RequestFeature), }, MenuItem::Separator, MenuItem::Action { diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 9fda149191..21f5b5d342 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -1,10 +1,7 @@ -pub mod feedback_popover; pub mod languages; pub mod menus; -pub mod system_specs; #[cfg(any(test, feature = "test-support"))] pub mod test; - use anyhow::{anyhow, Context, Result}; use assets::Assets; use breadcrumbs::Breadcrumbs; @@ -22,7 +19,7 @@ use gpui::{ }, impl_actions, platform::{WindowBounds, WindowOptions}, - AssetSource, AsyncAppContext, ClipboardItem, TitlebarOptions, ViewContext, WindowKind, + AssetSource, AsyncAppContext, TitlebarOptions, ViewContext, WindowKind, }; use language::Rope; use lazy_static::lazy_static; @@ -34,7 +31,6 @@ use serde::Deserialize; use serde_json::to_string_pretty; use settings::{keymap_file_json_schema, settings_file_json_schema, Settings}; use std::{env, path::Path, str, sync::Arc}; -use system_specs::SystemSpecs; use util::{channel::ReleaseChannel, paths, ResultExt}; pub use workspace; use workspace::{sidebar::SidebarSide, AppState, Workspace}; @@ -69,9 +65,6 @@ actions!( ResetBufferFontSize, InstallCommandLineInterface, ResetDatabase, - CopySystemSpecsIntoClipboard, - RequestFeature, - FileBugReport ] ); @@ -250,41 +243,6 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { }, ); - cx.add_action( - |_: &mut Workspace, _: &CopySystemSpecsIntoClipboard, cx: &mut ViewContext| { - let system_specs = SystemSpecs::new(cx).to_string(); - let item = ClipboardItem::new(system_specs.clone()); - cx.prompt( - gpui::PromptLevel::Info, - &format!("Copied into clipboard:\n\n{system_specs}"), - &["OK"], - ); - cx.write_to_clipboard(item); - }, - ); - - cx.add_action( - |_: &mut Workspace, _: &RequestFeature, cx: &mut ViewContext| { - let url = "https://github.com/zed-industries/feedback/issues/new?assignees=&labels=enhancement%2Ctriage&template=0_feature_request.yml"; - cx.dispatch_action(OpenBrowser { - url: url.into(), - }); - }, - ); - - cx.add_action( - |_: &mut Workspace, _: &FileBugReport, cx: &mut ViewContext| { - let system_specs_text = SystemSpecs::new(cx).to_string(); - let url = format!( - "https://github.com/zed-industries/feedback/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml&environment={}", - urlencoding::encode(&system_specs_text) - ); - cx.dispatch_action(OpenBrowser { - url: url.into(), - }); - }, - ); - activity_indicator::init(cx); call::init(app_state.client.clone(), app_state.user_store.clone(), cx); settings::KeymapFileContent::load_defaults(cx); @@ -369,12 +327,12 @@ 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_popover::FeedbackButton::new()); + let feedback_button = cx.add_view(|_| feedback::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); status_bar.add_right_item(cursor_position, cx); - status_bar.add_right_item(feedback_link, cx); + status_bar.add_right_item(feedback_button, cx); }); auto_update::notify_of_any_new_update(cx.weak_handle(), cx); From bec03dc882a734241f8091b0f1ce3cb0d388ad13 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Wed, 18 Jan 2023 00:12:52 -0500 Subject: [PATCH 12/24] WIP --- Cargo.lock | 3 + crates/feedback/Cargo.toml | 3 + crates/feedback/src/feedback.rs | 3 + crates/feedback/src/feedback_popover.rs | 370 +++++++++++++++--------- crates/feedback/src/system_specs.rs | 2 +- crates/theme/src/theme.rs | 16 +- crates/workspace/src/workspace.rs | 3 +- crates/zed/src/zed.rs | 2 +- 8 files changed, 251 insertions(+), 151 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6bd88e507..66a3e3ee72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2034,9 +2034,12 @@ dependencies = [ "human_bytes", "isahc", "lazy_static", + "project", "serde", "settings", + "smallvec", "sysinfo", + "theme", "urlencoding", "util", "workspace", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index afb43f501f..c6f139e36e 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -18,9 +18,12 @@ gpui = { path = "../gpui" } human_bytes = "0.4.1" isahc = "1.7" lazy_static = "1.4.0" +project = { path = "../project" } serde = { version = "1.0", features = ["derive", "rc"] } settings = { path = "../settings" } +smallvec = { version = "1.6", features = ["union"] } sysinfo = "0.27.1" +theme = { path = "../theme" } urlencoding = "2.1.2" util = { path = "../util" } workspace = { path = "../workspace" } \ No newline at end of file diff --git a/crates/feedback/src/feedback.rs b/crates/feedback/src/feedback.rs index 58cb682f3b..03379d655c 100644 --- a/crates/feedback/src/feedback.rs +++ b/crates/feedback/src/feedback.rs @@ -59,4 +59,7 @@ pub fn init(cx: &mut gpui::MutableAppContext) { }); }, ); + + // TODO FEEDBACK: Should I put Give Feedback action here? + // TODO FEEDBACK: Disble buffer search? } diff --git a/crates/feedback/src/feedback_popover.rs b/crates/feedback/src/feedback_popover.rs index b9a9312952..6beaea83f0 100644 --- a/crates/feedback/src/feedback_popover.rs +++ b/crates/feedback/src/feedback_popover.rs @@ -2,24 +2,30 @@ use std::{ops::Range, sync::Arc}; use anyhow::bail; use client::{Client, ZED_SECRET_CLIENT_TOKEN}; -use editor::Editor; +use editor::{Editor, MultiBuffer}; 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, + elements::{ChildView, Flex, Label, MouseEventHandler, ParentElement, Stack, Text}, + serde_json, CursorStyle, Element, ElementBox, Entity, ModelHandle, MouseButton, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use isahc::Request; + use lazy_static::lazy_static; +use project::{Project, ProjectEntryId, ProjectPath}; use serde::Serialize; use settings::Settings; -use workspace::{item::ItemHandle, StatusItemView}; +use smallvec::SmallVec; +use workspace::{ + item::{Item, ItemHandle}, + StatusItemView, Workspace, +}; -use crate::{feedback_popover, system_specs::SystemSpecs}; +use crate::system_specs::SystemSpecs; + +// TODO FEEDBACK: Rename this file to feedback editor? +// TODO FEEDBACK: Where is the backend code for air table? lazy_static! { pub static ref ZED_SERVER_URL: String = @@ -31,36 +37,14 @@ const FEEDBACK_CHAR_COUNT_RANGE: Range = Range { end: 1000, }; -actions!(feedback, [ToggleFeedbackPopover, SubmitFeedback]); +actions!(feedback, [SubmitFeedback, GiveFeedback, DeployFeedback]); pub fn init(cx: &mut MutableAppContext) { - cx.add_action(FeedbackButton::toggle_feedback); - cx.add_action(FeedbackPopover::submit_feedback); + // cx.add_action(FeedbackView::submit_feedback); + cx.add_action(FeedbackEditor::deploy); } -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(); - } -} +pub struct FeedbackButton; impl Entity for FeedbackButton { type Event = (); @@ -80,27 +64,81 @@ impl View for FeedbackButton { Text::new( "Give Feedback".to_string(), - theme - .style_for(state, self.feedback_popover.is_some()) - .clone(), + theme.style_for(state, true).clone(), ) .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, |_, cx| { - cx.dispatch_action(ToggleFeedbackPopover) - }) + .on_click(MouseButton::Left, |_, cx| cx.dispatch_action(GiveFeedback)) .boxed(), ) - .with_children(self.feedback_popover.as_ref().map(|popover| { - Overlay::new(ChildView::new(popover, cx).contained().boxed()) - .with_fit_mode(OverlayFitMode::SwitchAnchor) - .with_anchor_corner(AnchorCorner::TopLeft) - .with_z_index(999) - .boxed() - })) .boxed() } + + fn focus_in(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) {} + + fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) {} + + fn key_down(&mut self, _: &gpui::KeyDownEvent, _: &mut ViewContext) -> bool { + false + } + + fn key_up(&mut self, _: &gpui::KeyUpEvent, _: &mut ViewContext) -> bool { + false + } + + fn modifiers_changed( + &mut self, + _: &gpui::ModifiersChangedEvent, + _: &mut ViewContext, + ) -> bool { + false + } + + fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap_matcher::KeymapContext { + Self::default_keymap_context() + } + + fn default_keymap_context() -> gpui::keymap_matcher::KeymapContext { + let mut cx = gpui::keymap_matcher::KeymapContext::default(); + cx.set.insert(Self::ui_name().into()); + cx + } + + fn debug_json(&self, _: &gpui::AppContext) -> gpui::serde_json::Value { + gpui::serde_json::Value::Null + } + + fn text_for_range(&self, _: Range, _: &gpui::AppContext) -> Option { + None + } + + fn selected_text_range(&self, _: &gpui::AppContext) -> Option> { + None + } + + fn marked_text_range(&self, _: &gpui::AppContext) -> Option> { + None + } + + fn unmark_text(&mut self, _: &mut ViewContext) {} + + fn replace_text_in_range( + &mut self, + _: Option>, + _: &str, + _: &mut ViewContext, + ) { + } + + fn replace_and_mark_text_in_range( + &mut self, + _: Option>, + _: &str, + _: Option>, + _: &mut ViewContext, + ) { + } } impl StatusItemView for FeedbackButton { @@ -113,14 +151,9 @@ impl StatusItemView for FeedbackButton { } } -pub struct FeedbackPopover { - feedback_editor: ViewHandle, - // _subscriptions: Vec, -} - -impl Entity for FeedbackPopover { - type Event = (); -} +// impl Entity for FeedbackView { +// type Event = (); +// } #[derive(Serialize)] struct FeedbackRequestBody<'a> { @@ -130,40 +163,34 @@ struct FeedbackRequestBody<'a> { 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.feedback.feedback_editor.clone())), - cx, - ); +struct FeedbackEditor { + editor: ViewHandle, +} + +impl FeedbackEditor { + fn new( + project_handle: ModelHandle, + _: WeakViewHandle, + cx: &mut ViewContext, + ) -> Self { + // TODO FEEDBACK: Get rid of this expect + let buffer = project_handle + .update(cx, |project, cx| project.create_buffer("", None, cx)) + .expect("Could not open feedback window"); + + let editor = cx.add_view(|cx| { + let mut editor = Editor::for_buffer(buffer, Some(project_handle.clone()), cx); + editor.set_vertical_scroll_margin(5, cx); + editor.set_placeholder_text("Enter your feedback here, save to submit feedback", 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); + let this = Self { editor }; this } - fn submit_feedback(&mut self, _: &SubmitFeedback, cx: &mut ViewContext<'_, Self>) { - let feedback_text = self.feedback_editor.read(cx).text(cx); + fn submit_feedback(&mut self, cx: &mut ViewContext<'_, Self>) { + let feedback_text = self.editor.read(cx).text(cx); let zed_client = cx.global::>(); let system_specs = SystemSpecs::new(cx); let feedback_endpoint = format!("{}/api/feedback", *ZED_SERVER_URL); @@ -222,66 +249,129 @@ impl FeedbackPopover { } } -impl View for FeedbackPopover { +impl FeedbackEditor { + pub fn deploy(workspace: &mut Workspace, _: &GiveFeedback, cx: &mut ViewContext) { + // if let Some(existing) = workspace.item_of_type::(cx) { + // workspace.activate_item(&existing, cx); + // } else { + let workspace_handle = cx.weak_handle(); + let feedback_editor = cx + .add_view(|cx| FeedbackEditor::new(workspace.project().clone(), workspace_handle, cx)); + workspace.add_item(Box::new(feedback_editor), cx); + } + // } +} + +// struct FeedbackView { +// editor: Editor, +// } + +impl View for FeedbackEditor { fn ui_name() -> &'static str { - "FeedbackPopover" + "Feedback" } fn render(&mut self, cx: &mut RenderContext) -> ElementBox { - enum SubmitFeedback {} + // let theme = cx.global::().theme.clone(); + // let submit_feedback_text_button_height = 20.0; - // I'd like to just define: - - // 1. Overall popover width x height dimensions (done) - // 2. Submit Feedback button height dimensions - // 3. Allow editor to dynamically fill in the remaining space - - let theme = cx.global::().theme.clone(); - let submit_feedback_text_button_height = 20.0; - - Flex::column() - .with_child( - Flex::row() - .with_child( - ChildView::new(self.feedback_editor.clone(), cx) - .contained() - .with_style(theme.feedback.feedback_editor.container) - .flex(1., true) - .boxed(), - ) - .constrained() - .with_width(theme.feedback.feedback_popover.width) - .with_height( - theme.feedback.feedback_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.feedback.feedback_popover.container) - .constrained() - .with_width(theme.feedback.feedback_popover.width) - .with_height(theme.feedback.feedback_popover.height) - .boxed() + ChildView::new(&self.editor, cx).boxed() } } + +impl Entity for FeedbackEditor { + type Event = (); +} + +impl Item for FeedbackEditor { + fn tab_content( + &self, + _: Option, + style: &theme::Tab, + _: &gpui::AppContext, + ) -> ElementBox { + Flex::row() + .with_child( + Label::new("Feedback".to_string(), style.label.clone()) + .aligned() + .contained() + .boxed(), + ) + .boxed() + } + + fn to_item_events(_: &Self::Event) -> Vec { + Vec::new() + } + + fn project_path(&self, _: &gpui::AppContext) -> Option { + None + } + + fn project_entry_ids(&self, _: &gpui::AppContext) -> SmallVec<[ProjectEntryId; 3]> { + SmallVec::new() + } + + fn is_singleton(&self, _: &gpui::AppContext) -> bool { + true + } + + fn set_nav_history(&mut self, _: workspace::ItemNavHistory, _: &mut ViewContext) {} + + fn can_save(&self, _: &gpui::AppContext) -> bool { + true + } + + fn save( + &mut self, + _: gpui::ModelHandle, + cx: &mut ViewContext, + ) -> Task> { + cx.prompt( + gpui::PromptLevel::Info, + &format!("You are trying to to submit this feedbac"), + &["OK"], + ); + + self.submit_feedback(cx); + Task::ready(Ok(())) + } + + fn save_as( + &mut self, + _: gpui::ModelHandle, + _: std::path::PathBuf, + _: &mut ViewContext, + ) -> Task> { + unreachable!("save_as should not have been called"); + } + + fn reload( + &mut self, + _: gpui::ModelHandle, + _: &mut ViewContext, + ) -> Task> { + unreachable!("should not have been called") + } + + fn serialized_item_kind() -> Option<&'static str> { + None + } + + fn deserialize( + _: gpui::ModelHandle, + _: gpui::WeakViewHandle, + _: workspace::WorkspaceId, + _: workspace::ItemId, + _: &mut ViewContext, + ) -> Task>> { + unreachable!() + } +} + +// TODO FEEDBACK: Add placeholder text +// TODO FEEDBACK: act_as_type (max mentionedt this) +// TODO FEEDBACK: focus +// TODO FEEDBACK: markdown highlighting +// TODO FEEDBACK: save prompts and accepting closes +// TODO FEEDBACK: multiple tabs? diff --git a/crates/feedback/src/system_specs.rs b/crates/feedback/src/system_specs.rs index fc55f76f35..17e51a6815 100644 --- a/crates/feedback/src/system_specs.rs +++ b/crates/feedback/src/system_specs.rs @@ -42,7 +42,7 @@ impl Display for SystemSpecs { None => format!("OS: {}", self.os_name), }; let system_specs = [ - format!("Zed: {} ({})", self.app_version, self.release_channel), + format!("Zed: v{} ({})", self.app_version, self.release_channel), os_information, format!("Memory: {}", human_bytes(self.memory as f64)), format!("Architecture: {}", self.architecture), diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index 3b118bbef9..ed8fb1bb12 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -122,17 +122,17 @@ pub struct ContactList { #[derive(Deserialize, Default)] pub struct Feedback { - pub feedback_popover: FeedbackPopover, + // pub feedback_popover: FeedbackPopover, 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 FeedbackPopover { +// #[serde(flatten)] +// pub container: ContainerStyle, +// pub height: f32, +// pub width: f32, +// } #[derive(Deserialize, Default)] pub struct ProjectRow { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 8bf4cbce32..ff5748f240 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -96,7 +96,8 @@ actions!( ToggleLeftSidebar, ToggleRightSidebar, NewTerminal, - NewSearch + NewSearch, + Feedback ] ); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 21f5b5d342..8f597ebe79 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -327,7 +327,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_button = cx.add_view(|_| feedback::feedback_popover::FeedbackButton::new()); + let feedback_button = cx.add_view(|_| feedback::feedback_popover::FeedbackButton {}); 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 d30e129d63d7438e717fdc958dd2473dea05fd3b Mon Sep 17 00:00:00 2001 From: Petros Amoiridis Date: Thu, 19 Jan 2023 19:38:05 +0200 Subject: [PATCH 13/24] Create files passed as args to CLI Co-Authored-by: Mikayla --- crates/cli/src/main.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 4bc2d6e73d..a31e59587f 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -9,7 +9,13 @@ use core_foundation::{ use core_services::{kLSLaunchDefaults, LSLaunchURLSpec, LSOpenFromURLSpec, TCFType}; use ipc_channel::ipc::{IpcOneShotServer, IpcReceiver, IpcSender}; use serde::Deserialize; -use std::{ffi::OsStr, fs, path::PathBuf, ptr}; +use std::{ + ffi::OsStr, + fs::{self, OpenOptions}, + io, + path::{Path, PathBuf}, + ptr, +}; #[derive(Parser)] #[clap(name = "zed", global_setting(clap::AppSettings::NoAutoVersion))] @@ -54,6 +60,12 @@ fn main() -> Result<()> { return Ok(()); } + for path in args.paths.iter() { + if !path.exists() { + touch(path.as_path())?; + } + } + let (tx, rx) = launch_app(bundle_path)?; tx.send(CliRequest::Open { @@ -77,6 +89,13 @@ fn main() -> Result<()> { Ok(()) } +fn touch(path: &Path) -> io::Result<()> { + match OpenOptions::new().create(true).write(true).open(path) { + Ok(_) => Ok(()), + Err(e) => Err(e), + } +} + fn locate_bundle() -> Result { let cli_path = std::env::current_exe()?.canonicalize()?; let mut app_path = cli_path.clone(); From c1934d62328904f1f500e43477f8ce9996137132 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 20 Jan 2023 16:56:56 -0500 Subject: [PATCH 14/24] WIP --- Cargo.lock | 3 + crates/feedback/Cargo.toml | 3 + crates/feedback/src/feedback.rs | 7 +- ...feedback_popover.rs => feedback_editor.rs} | 183 ++++++++++++------ crates/zed/src/zed.rs | 2 +- 5 files changed, 137 insertions(+), 61 deletions(-) rename crates/feedback/src/{feedback_popover.rs => feedback_editor.rs} (66%) diff --git a/Cargo.lock b/Cargo.lock index 66a3e3ee72..10c67ee33b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2033,13 +2033,16 @@ dependencies = [ "gpui", "human_bytes", "isahc", + "language", "lazy_static", + "postage", "project", "serde", "settings", "smallvec", "sysinfo", "theme", + "tree-sitter-markdown", "urlencoding", "util", "workspace", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index c6f139e36e..3eaa9448f9 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -13,17 +13,20 @@ test-support = [] anyhow = "1.0.38" client = { path = "../client" } editor = { path = "../editor" } +language = { path = "../language" } futures = "0.3" gpui = { path = "../gpui" } human_bytes = "0.4.1" isahc = "1.7" lazy_static = "1.4.0" +postage = { version = "0.4", features = ["futures-traits"] } project = { path = "../project" } serde = { version = "1.0", features = ["derive", "rc"] } settings = { path = "../settings" } smallvec = { version = "1.6", features = ["union"] } sysinfo = "0.27.1" theme = { path = "../theme" } +tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" } urlencoding = "2.1.2" util = { path = "../util" } workspace = { path = "../workspace" } \ No newline at end of file diff --git a/crates/feedback/src/feedback.rs b/crates/feedback/src/feedback.rs index 03379d655c..46c9c2efc2 100644 --- a/crates/feedback/src/feedback.rs +++ b/crates/feedback/src/feedback.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -pub mod feedback_popover; +pub mod feedback_editor; mod system_specs; use gpui::{actions, impl_actions, ClipboardItem, ViewContext}; use serde::Deserialize; @@ -21,7 +21,7 @@ actions!( ); pub fn init(cx: &mut gpui::MutableAppContext) { - feedback_popover::init(cx); + feedback_editor::init(cx); cx.add_global_action(move |action: &OpenBrowser, cx| cx.platform().open_url(&action.url)); @@ -59,7 +59,4 @@ pub fn init(cx: &mut gpui::MutableAppContext) { }); }, ); - - // TODO FEEDBACK: Should I put Give Feedback action here? - // TODO FEEDBACK: Disble buffer search? } diff --git a/crates/feedback/src/feedback_popover.rs b/crates/feedback/src/feedback_editor.rs similarity index 66% rename from crates/feedback/src/feedback_popover.rs rename to crates/feedback/src/feedback_editor.rs index 6beaea83f0..120431ab22 100644 --- a/crates/feedback/src/feedback_popover.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -2,15 +2,18 @@ use std::{ops::Range, sync::Arc}; use anyhow::bail; use client::{Client, ZED_SECRET_CLIENT_TOKEN}; -use editor::{Editor, MultiBuffer}; +use editor::Editor; use futures::AsyncReadExt; use gpui::{ actions, elements::{ChildView, Flex, Label, MouseEventHandler, ParentElement, Stack, Text}, - serde_json, CursorStyle, Element, ElementBox, Entity, ModelHandle, MouseButton, - MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, WeakViewHandle, + serde_json, AnyViewHandle, CursorStyle, Element, ElementBox, Entity, ModelHandle, MouseButton, + MutableAppContext, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle, + WeakViewHandle, }; use isahc::Request; +use language::{Language, LanguageConfig}; +use postage::prelude::Stream; use lazy_static::lazy_static; use project::{Project, ProjectEntryId, ProjectPath}; @@ -24,14 +27,13 @@ use workspace::{ use crate::system_specs::SystemSpecs; -// TODO FEEDBACK: Rename this file to feedback editor? -// TODO FEEDBACK: Where is the backend code for air table? - lazy_static! { pub static ref ZED_SERVER_URL: String = std::env::var("ZED_SERVER_URL").unwrap_or_else(|_| "https://zed.dev".to_string()); } +// TODO FEEDBACK: In the future, it would be nice to use this is some sort of live-rendering character counter thing +// Currently, we are just checking on submit that the the text exceeds the `start` value in this range const FEEDBACK_CHAR_COUNT_RANGE: Range = Range { start: 5, end: 1000, @@ -40,7 +42,6 @@ const FEEDBACK_CHAR_COUNT_RANGE: Range = Range { actions!(feedback, [SubmitFeedback, GiveFeedback, DeployFeedback]); pub fn init(cx: &mut MutableAppContext) { - // cx.add_action(FeedbackView::submit_feedback); cx.add_action(FeedbackEditor::deploy); } @@ -147,14 +148,9 @@ impl StatusItemView for FeedbackButton { _: Option<&dyn ItemHandle>, _: &mut gpui::ViewContext, ) { - // N/A } } -// impl Entity for FeedbackView { -// type Event = (); -// } - #[derive(Serialize)] struct FeedbackRequestBody<'a> { feedback_text: &'a str, @@ -163,6 +159,7 @@ struct FeedbackRequestBody<'a> { token: &'a str, } +#[derive(Clone)] struct FeedbackEditor { editor: ViewHandle, } @@ -173,15 +170,30 @@ impl FeedbackEditor { _: WeakViewHandle, cx: &mut ViewContext, ) -> Self { - // TODO FEEDBACK: Get rid of this expect + // TODO FEEDBACK: This doesn't work like I expected it would + // let markdown_language = Arc::new(Language::new( + // LanguageConfig::default(), + // Some(tree_sitter_markdown::language()), + // )); + + let markdown_language = project_handle + .read(cx) + .languages() + .get_language("Markdown") + .unwrap(); + let buffer = project_handle - .update(cx, |project, cx| project.create_buffer("", None, cx)) - .expect("Could not open feedback window"); + .update(cx, |project, cx| { + project.create_buffer("", Some(markdown_language), cx) + }) + .expect("creating buffers on a local workspace always succeeds"); + + const FEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here in the form of Markdown. Save the tab to submit your feedback."; let editor = cx.add_view(|cx| { let mut editor = Editor::for_buffer(buffer, Some(project_handle.clone()), cx); editor.set_vertical_scroll_margin(5, cx); - editor.set_placeholder_text("Enter your feedback here, save to submit feedback", cx); + editor.set_placeholder_text(FEDBACK_PLACEHOLDER_TEXT, cx); editor }); @@ -189,7 +201,65 @@ impl FeedbackEditor { this } - fn submit_feedback(&mut self, cx: &mut ViewContext<'_, Self>) { + fn handle_save( + &mut self, + _: gpui::ModelHandle, + cx: &mut ViewContext, + ) -> Task> { + // TODO FEEDBACK: These don't look right + let feedback_text_length = self.editor.read(cx).buffer().read(cx).len(cx); + + if feedback_text_length <= FEEDBACK_CHAR_COUNT_RANGE.start { + cx.prompt( + PromptLevel::Critical, + &format!( + "Feedback must be longer than {} characters", + FEEDBACK_CHAR_COUNT_RANGE.start + ), + &["OK"], + ); + + return Task::ready(Ok(())); + } + + let mut answer = cx.prompt( + PromptLevel::Warning, + "Ready to submit your feedback?", + &["Yes, Submit!", "No"], + ); + + let this = cx.handle(); + cx.spawn(|_, mut cx| async move { + let answer = answer.recv().await; + + if answer == Some(0) { + cx.update(|cx| { + this.update(cx, |this, cx| match this.submit_feedback(cx) { + // TODO FEEDBACK + Ok(_) => { + // Close file after feedback sent successfully + // workspace + // .update(cx, |workspace, cx| { + // Pane::close_active_item(workspace, &Default::default(), cx) + // .unwrap() + // }) + // .await + // .unwrap(); + } + Err(error) => { + cx.prompt(PromptLevel::Critical, &error.to_string(), &["OK"]); + // Prompt that something failed (and to check the log for the exact error? and to try again?) + } + }) + }) + } + }) + .detach(); + + Task::ready(Ok(())) + } + + fn submit_feedback(&mut self, cx: &mut ViewContext<'_, Self>) -> anyhow::Result<()> { let feedback_text = self.editor.read(cx).text(cx); let zed_client = cx.global::>(); let system_specs = SystemSpecs::new(cx); @@ -198,13 +268,12 @@ impl FeedbackEditor { 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 - // }); + // TODO FEEDBACK: how to get error out of the thread + let this = cx.handle(); + + cx.spawn(|_, async_cx| { + async move { let request = FeedbackRequestBody { feedback_text: &feedback_text, metrics_id, @@ -224,13 +293,14 @@ impl FeedbackEditor { 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") + bail!("Feedback API failed with: {}", response_status) } + this.read_with(&async_cx, |this, cx| -> anyhow::Result<()> { + bail!("Error") + })?; + // TODO FEEDBACK: Use or remove // Will need to handle error cases // async_cx.update(|cx| { @@ -246,6 +316,8 @@ impl FeedbackEditor { } }) .detach(); + + Ok(()) } } @@ -258,25 +330,24 @@ impl FeedbackEditor { let feedback_editor = cx .add_view(|cx| FeedbackEditor::new(workspace.project().clone(), workspace_handle, cx)); workspace.add_item(Box::new(feedback_editor), cx); + // } } - // } } -// struct FeedbackView { -// editor: Editor, -// } - impl View for FeedbackEditor { fn ui_name() -> &'static str { - "Feedback" + "FeedbackEditor" } fn render(&mut self, cx: &mut RenderContext) -> ElementBox { - // let theme = cx.global::().theme.clone(); - // let submit_feedback_text_button_height = 20.0; - ChildView::new(&self.editor, cx).boxed() } + + fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { + if cx.is_self_focused() { + cx.focus(&self.editor); + } + } } impl Entity for FeedbackEditor { @@ -324,26 +395,19 @@ impl Item for FeedbackEditor { fn save( &mut self, - _: gpui::ModelHandle, + project_handle: gpui::ModelHandle, cx: &mut ViewContext, ) -> Task> { - cx.prompt( - gpui::PromptLevel::Info, - &format!("You are trying to to submit this feedbac"), - &["OK"], - ); - - self.submit_feedback(cx); - Task::ready(Ok(())) + self.handle_save(project_handle, cx) } fn save_as( &mut self, - _: gpui::ModelHandle, + project_handle: gpui::ModelHandle, _: std::path::PathBuf, - _: &mut ViewContext, + cx: &mut ViewContext, ) -> Task> { - unreachable!("save_as should not have been called"); + self.handle_save(project_handle, cx) } fn reload( @@ -351,7 +415,20 @@ impl Item for FeedbackEditor { _: gpui::ModelHandle, _: &mut ViewContext, ) -> Task> { - unreachable!("should not have been called") + unreachable!("reload should not have been called") + } + + fn clone_on_split( + &self, + _workspace_id: workspace::WorkspaceId, + cx: &mut ViewContext, + ) -> Option + where + Self: Sized, + { + // TODO FEEDBACK: split is busted + // Some(self.clone()) + None } fn serialized_item_kind() -> Option<&'static str> { @@ -369,9 +446,5 @@ impl Item for FeedbackEditor { } } -// TODO FEEDBACK: Add placeholder text -// TODO FEEDBACK: act_as_type (max mentionedt this) -// TODO FEEDBACK: focus -// TODO FEEDBACK: markdown highlighting -// TODO FEEDBACK: save prompts and accepting closes -// TODO FEEDBACK: multiple tabs? +// TODO FEEDBACK: search buffer? +// TODO FEEDBACK: warnings diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 8f597ebe79..167b57aaf2 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -327,7 +327,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_button = cx.add_view(|_| feedback::feedback_popover::FeedbackButton {}); + let feedback_button = cx.add_view(|_| feedback::feedback_editor::FeedbackButton {}); 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 083986dfae054237c2312135f4388364e6d1e031 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Fri, 20 Jan 2023 18:05:24 -0500 Subject: [PATCH 15/24] WIP Co-Authored-By: Mikayla Maki --- Cargo.lock | 1 + crates/feedback/Cargo.toml | 1 + crates/feedback/src/feedback_editor.rs | 122 ++++++++++++++++++------- 3 files changed, 90 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10c67ee33b..fad1906e05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2037,6 +2037,7 @@ dependencies = [ "lazy_static", "postage", "project", + "search", "serde", "settings", "smallvec", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index 3eaa9448f9..b623c9b68e 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -21,6 +21,7 @@ isahc = "1.7" lazy_static = "1.4.0" postage = { version = "0.4", features = ["futures-traits"] } project = { path = "../project" } +search = { path = "../search" } serde = { version = "1.0", features = ["derive", "rc"] } settings = { path = "../settings" } smallvec = { version = "1.6", features = ["union"] } diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index 120431ab22..c5e90b7216 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -9,10 +9,9 @@ use gpui::{ elements::{ChildView, Flex, Label, MouseEventHandler, ParentElement, Stack, Text}, serde_json, AnyViewHandle, CursorStyle, Element, ElementBox, Entity, ModelHandle, MouseButton, MutableAppContext, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle, - WeakViewHandle, }; use isahc::Request; -use language::{Language, LanguageConfig}; +use language::Buffer; use postage::prelude::Stream; use lazy_static::lazy_static; @@ -162,43 +161,44 @@ struct FeedbackRequestBody<'a> { #[derive(Clone)] struct FeedbackEditor { editor: ViewHandle, + project: ModelHandle, } impl FeedbackEditor { - fn new( - project_handle: ModelHandle, - _: WeakViewHandle, + fn new_with_buffer( + project: ModelHandle, + buffer: ModelHandle, cx: &mut ViewContext, ) -> Self { + const FEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here in the form of Markdown. Save the tab to submit your feedback."; + + let editor = cx.add_view(|cx| { + let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx); + editor.set_vertical_scroll_margin(5, cx); + editor.set_placeholder_text(FEDBACK_PLACEHOLDER_TEXT, cx); + editor + }); + + let this = Self { editor, project }; + this + } + + fn new(project: ModelHandle, cx: &mut ViewContext) -> Self { // TODO FEEDBACK: This doesn't work like I expected it would // let markdown_language = Arc::new(Language::new( // LanguageConfig::default(), // Some(tree_sitter_markdown::language()), // )); - let markdown_language = project_handle - .read(cx) - .languages() - .get_language("Markdown") - .unwrap(); + let markdown_language = project.read(cx).languages().get_language("Markdown"); - let buffer = project_handle + let buffer = project .update(cx, |project, cx| { - project.create_buffer("", Some(markdown_language), cx) + project.create_buffer("", markdown_language, cx) }) .expect("creating buffers on a local workspace always succeeds"); - const FEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here in the form of Markdown. Save the tab to submit your feedback."; - - let editor = cx.add_view(|cx| { - let mut editor = Editor::for_buffer(buffer, Some(project_handle.clone()), cx); - editor.set_vertical_scroll_margin(5, cx); - editor.set_placeholder_text(FEDBACK_PLACEHOLDER_TEXT, cx); - editor - }); - - let this = Self { editor }; - this + Self::new_with_buffer(project, buffer, cx) } fn handle_save( @@ -297,7 +297,7 @@ impl FeedbackEditor { bail!("Feedback API failed with: {}", response_status) } - this.read_with(&async_cx, |this, cx| -> anyhow::Result<()> { + this.read_with(&async_cx, |_this, _cx| -> anyhow::Result<()> { bail!("Error") })?; @@ -326,9 +326,8 @@ impl FeedbackEditor { // if let Some(existing) = workspace.item_of_type::(cx) { // workspace.activate_item(&existing, cx); // } else { - let workspace_handle = cx.weak_handle(); - let feedback_editor = cx - .add_view(|cx| FeedbackEditor::new(workspace.project().clone(), workspace_handle, cx)); + let feedback_editor = + cx.add_view(|cx| FeedbackEditor::new(workspace.project().clone(), cx)); workspace.add_item(Box::new(feedback_editor), cx); // } } @@ -395,19 +394,19 @@ impl Item for FeedbackEditor { fn save( &mut self, - project_handle: gpui::ModelHandle, + project: gpui::ModelHandle, cx: &mut ViewContext, ) -> Task> { - self.handle_save(project_handle, cx) + self.handle_save(project, cx) } fn save_as( &mut self, - project_handle: gpui::ModelHandle, + project: gpui::ModelHandle, _: std::path::PathBuf, cx: &mut ViewContext, ) -> Task> { - self.handle_save(project_handle, cx) + self.handle_save(project, cx) } fn reload( @@ -426,9 +425,19 @@ impl Item for FeedbackEditor { where Self: Sized, { - // TODO FEEDBACK: split is busted - // Some(self.clone()) - None + let buffer = self + .editor + .read(cx) + .buffer() + .read(cx) + .as_singleton() + .expect("Feedback buffer is only ever singleton"); + + Some(Self::new_with_buffer( + self.project.clone(), + buffer.clone(), + cx, + )) } fn serialized_item_kind() -> Option<&'static str> { @@ -446,5 +455,50 @@ impl Item for FeedbackEditor { } } +// impl SearchableItem for FeedbackEditor { +// type Match = ::Match; + +// fn to_search_event(event: &Self::Event) -> Option { +// Editor::to_search_event(event) +// } + +// fn clear_matches(&mut self, cx: &mut ViewContext) { +// self. +// } + +// fn update_matches(&mut self, matches: Vec, cx: &mut ViewContext) { +// todo!() +// } + +// fn query_suggestion(&mut self, cx: &mut ViewContext) -> String { +// todo!() +// } + +// fn activate_match( +// &mut self, +// index: usize, +// matches: Vec, +// cx: &mut ViewContext, +// ) { +// todo!() +// } + +// fn find_matches( +// &mut self, +// query: project::search::SearchQuery, +// cx: &mut ViewContext, +// ) -> Task> { +// todo!() +// } + +// fn active_match_index( +// &mut self, +// matches: Vec, +// cx: &mut ViewContext, +// ) -> Option { +// todo!() +// } +// } + // TODO FEEDBACK: search buffer? // TODO FEEDBACK: warnings From fb2278dc6d8c688a1e17d58d4fd46f81fc937081 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 23 Jan 2023 00:59:46 -0500 Subject: [PATCH 16/24] Complete first iteration of in-app feedback --- Cargo.lock | 1 + crates/feedback/Cargo.toml | 1 + crates/feedback/src/feedback.rs | 5 +- crates/feedback/src/feedback_editor.rs | 234 ++++++++++++------------- crates/zed/src/zed.rs | 2 +- 5 files changed, 113 insertions(+), 130 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fad1906e05..b503e1838a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2035,6 +2035,7 @@ dependencies = [ "isahc", "language", "lazy_static", + "log", "postage", "project", "search", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index b623c9b68e..ec5aa52a1a 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -14,6 +14,7 @@ anyhow = "1.0.38" client = { path = "../client" } editor = { path = "../editor" } language = { path = "../language" } +log = "0.4" futures = "0.3" gpui = { path = "../gpui" } human_bytes = "0.4.1" diff --git a/crates/feedback/src/feedback.rs b/crates/feedback/src/feedback.rs index 46c9c2efc2..4b0dfc4df9 100644 --- a/crates/feedback/src/feedback.rs +++ b/crates/feedback/src/feedback.rs @@ -7,10 +7,9 @@ use serde::Deserialize; use system_specs::SystemSpecs; use workspace::Workspace; -// TODO FEEDBACK: This open brownser code is duplicated from the zed crate, where should we refactor it to? #[derive(Deserialize, Clone, PartialEq)] -struct OpenBrowser { - url: Arc, +pub struct OpenBrowser { + pub url: Arc, } impl_actions!(zed, [OpenBrowser]); diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index c5e90b7216..564ac76203 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -2,7 +2,7 @@ use std::{ops::Range, sync::Arc}; use anyhow::bail; use client::{Client, ZED_SECRET_CLIENT_TOKEN}; -use editor::Editor; +use editor::{Anchor, Editor}; use futures::AsyncReadExt; use gpui::{ actions, @@ -21,6 +21,7 @@ use settings::Settings; use smallvec::SmallVec; use workspace::{ item::{Item, ItemHandle}, + searchable::{SearchableItem, SearchableItemHandle}, StatusItemView, Workspace, }; @@ -31,13 +32,15 @@ lazy_static! { std::env::var("ZED_SERVER_URL").unwrap_or_else(|_| "https://zed.dev".to_string()); } -// TODO FEEDBACK: In the future, it would be nice to use this is some sort of live-rendering character counter thing -// Currently, we are just checking on submit that the the text exceeds the `start` value in this range const FEEDBACK_CHAR_COUNT_RANGE: Range = Range { - start: 5, + start: 10, end: 1000, }; +const FEEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here in the form of Markdown. Save the tab to submit your feedback."; +const FEEDBACK_SUBMISSION_ERROR_TEXT: &str = + "Feedback failed to submit, see error log for details."; + actions!(feedback, [SubmitFeedback, GiveFeedback, DeployFeedback]); pub fn init(cx: &mut MutableAppContext) { @@ -170,26 +173,21 @@ impl FeedbackEditor { buffer: ModelHandle, cx: &mut ViewContext, ) -> Self { - const FEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here in the form of Markdown. Save the tab to submit your feedback."; - let editor = cx.add_view(|cx| { let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx); editor.set_vertical_scroll_margin(5, cx); - editor.set_placeholder_text(FEDBACK_PLACEHOLDER_TEXT, cx); + editor.set_placeholder_text(FEEDBACK_PLACEHOLDER_TEXT, cx); editor }); + cx.subscribe(&editor, |_, _, e, cx| cx.emit(e.clone())) + .detach(); + let this = Self { editor, project }; this } fn new(project: ModelHandle, cx: &mut ViewContext) -> Self { - // TODO FEEDBACK: This doesn't work like I expected it would - // let markdown_language = Arc::new(Language::new( - // LanguageConfig::default(), - // Some(tree_sitter_markdown::language()), - // )); - let markdown_language = project.read(cx).languages().get_language("Markdown"); let buffer = project @@ -206,7 +204,6 @@ impl FeedbackEditor { _: gpui::ModelHandle, cx: &mut ViewContext, ) -> Task> { - // TODO FEEDBACK: These don't look right let feedback_text_length = self.editor.read(cx).buffer().read(cx).len(cx); if feedback_text_length <= FEEDBACK_CHAR_COUNT_RANGE.start { @@ -223,35 +220,42 @@ impl FeedbackEditor { } let mut answer = cx.prompt( - PromptLevel::Warning, + PromptLevel::Info, "Ready to submit your feedback?", &["Yes, Submit!", "No"], ); let this = cx.handle(); + let client = cx.global::>().clone(); + let feedback_text = self.editor.read(cx).text(cx); + let specs = SystemSpecs::new(cx); + cx.spawn(|_, mut cx| async move { let answer = answer.recv().await; if answer == Some(0) { - cx.update(|cx| { - this.update(cx, |this, cx| match this.submit_feedback(cx) { - // TODO FEEDBACK - Ok(_) => { - // Close file after feedback sent successfully - // workspace - // .update(cx, |workspace, cx| { - // Pane::close_active_item(workspace, &Default::default(), cx) - // .unwrap() - // }) - // .await - // .unwrap(); - } - Err(error) => { - cx.prompt(PromptLevel::Critical, &error.to_string(), &["OK"]); - // Prompt that something failed (and to check the log for the exact error? and to try again?) - } - }) - }) + match FeedbackEditor::submit_feedback(&feedback_text, client, specs).await { + Ok(_) => { + cx.update(|cx| { + this.update(cx, |_, cx| { + cx.dispatch_action(workspace::CloseActiveItem); + }) + }); + } + Err(error) => { + log::error!("{}", error); + + cx.update(|cx| { + this.update(cx, |_, cx| { + cx.prompt( + PromptLevel::Critical, + FEEDBACK_SUBMISSION_ERROR_TEXT, + &["OK"], + ); + }) + }); + } + } } }) .detach(); @@ -259,63 +263,38 @@ impl FeedbackEditor { Task::ready(Ok(())) } - fn submit_feedback(&mut self, cx: &mut ViewContext<'_, Self>) -> anyhow::Result<()> { - let feedback_text = self.editor.read(cx).text(cx); - let zed_client = cx.global::>(); - let system_specs = SystemSpecs::new(cx); + async fn submit_feedback( + feedback_text: &str, + zed_client: Arc, + system_specs: SystemSpecs, + ) -> anyhow::Result<()> { let feedback_endpoint = format!("{}/api/feedback", *ZED_SERVER_URL); let metrics_id = zed_client.metrics_id(); let http_client = zed_client.http_client(); - // TODO FEEDBACK: how to get error out of the thread + let request = FeedbackRequestBody { + feedback_text: &feedback_text, + metrics_id, + system_specs, + token: ZED_SECRET_CLIENT_TOKEN, + }; - let this = cx.handle(); + let json_bytes = serde_json::to_vec(&request)?; - cx.spawn(|_, async_cx| { - async move { - let request = FeedbackRequestBody { - feedback_text: &feedback_text, - metrics_id, - system_specs, - token: ZED_SECRET_CLIENT_TOKEN, - }; + let request = Request::post(feedback_endpoint) + .header("content-type", "application/json") + .body(json_bytes.into())?; - let json_bytes = serde_json::to_vec(&request)?; + let mut response = http_client.send(request).await?; + let mut body = String::new(); + response.body_mut().read_to_string(&mut body).await?; - let request = Request::post(feedback_endpoint) - .header("content-type", "application/json") - .body(json_bytes.into())?; + let response_status = response.status(); - 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(); - - if !response_status.is_success() { - bail!("Feedback API failed with: {}", response_status) - } - - this.read_with(&async_cx, |_this, _cx| -> anyhow::Result<()> { - 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(); + if !response_status.is_success() { + bail!("Feedback API failed with error: {}", response_status) + } Ok(()) } @@ -323,13 +302,9 @@ impl FeedbackEditor { impl FeedbackEditor { pub fn deploy(workspace: &mut Workspace, _: &GiveFeedback, cx: &mut ViewContext) { - // if let Some(existing) = workspace.item_of_type::(cx) { - // workspace.activate_item(&existing, cx); - // } else { let feedback_editor = cx.add_view(|cx| FeedbackEditor::new(workspace.project().clone(), cx)); workspace.add_item(Box::new(feedback_editor), cx); - // } } } @@ -350,7 +325,7 @@ impl View for FeedbackEditor { } impl Entity for FeedbackEditor { - type Event = (); + type Event = editor::Event; } impl Item for FeedbackEditor { @@ -453,52 +428,59 @@ impl Item for FeedbackEditor { ) -> Task>> { unreachable!() } + + fn as_searchable(&self, handle: &ViewHandle) -> Option> { + Some(Box::new(handle.clone())) + } } -// impl SearchableItem for FeedbackEditor { -// type Match = ::Match; +impl SearchableItem for FeedbackEditor { + type Match = Range; -// fn to_search_event(event: &Self::Event) -> Option { -// Editor::to_search_event(event) -// } + fn to_search_event(event: &Self::Event) -> Option { + Editor::to_search_event(event) + } -// fn clear_matches(&mut self, cx: &mut ViewContext) { -// self. -// } + fn clear_matches(&mut self, cx: &mut ViewContext) { + self.editor + .update(cx, |editor, cx| editor.clear_matches(cx)) + } -// fn update_matches(&mut self, matches: Vec, cx: &mut ViewContext) { -// todo!() -// } + fn update_matches(&mut self, matches: Vec, cx: &mut ViewContext) { + self.editor + .update(cx, |editor, cx| editor.update_matches(matches, cx)) + } -// fn query_suggestion(&mut self, cx: &mut ViewContext) -> String { -// todo!() -// } + fn query_suggestion(&mut self, cx: &mut ViewContext) -> String { + self.editor + .update(cx, |editor, cx| editor.query_suggestion(cx)) + } -// fn activate_match( -// &mut self, -// index: usize, -// matches: Vec, -// cx: &mut ViewContext, -// ) { -// todo!() -// } + fn activate_match( + &mut self, + index: usize, + matches: Vec, + cx: &mut ViewContext, + ) { + self.editor + .update(cx, |editor, cx| editor.activate_match(index, matches, cx)) + } -// fn find_matches( -// &mut self, -// query: project::search::SearchQuery, -// cx: &mut ViewContext, -// ) -> Task> { -// todo!() -// } + fn find_matches( + &mut self, + query: project::search::SearchQuery, + cx: &mut ViewContext, + ) -> Task> { + self.editor + .update(cx, |editor, cx| editor.find_matches(query, cx)) + } -// fn active_match_index( -// &mut self, -// matches: Vec, -// cx: &mut ViewContext, -// ) -> Option { -// todo!() -// } -// } - -// TODO FEEDBACK: search buffer? -// TODO FEEDBACK: warnings + fn active_match_index( + &mut self, + matches: Vec, + cx: &mut ViewContext, + ) -> Option { + self.editor + .update(cx, |editor, cx| editor.active_match_index(matches, cx)) + } +} diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 167b57aaf2..4dca6e0de8 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -36,7 +36,7 @@ pub use workspace; use workspace::{sidebar::SidebarSide, AppState, Workspace}; #[derive(Deserialize, Clone, PartialEq)] -struct OpenBrowser { +pub struct OpenBrowser { url: Arc, } From c118f9aabd6b226f9373232fcecea130ec6fdeb3 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 23 Jan 2023 01:31:02 -0500 Subject: [PATCH 17/24] Fix new errors after merge --- Cargo.lock | 1 - crates/feedback/Cargo.toml | 1 - crates/feedback/src/feedback_editor.rs | 20 ++++++++------------ crates/workspace/src/workspace.rs | 2 +- crates/zed/src/zed.rs | 3 +-- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be257b2425..f08a13902e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2040,7 +2040,6 @@ dependencies = [ "search", "serde", "settings", - "smallvec", "sysinfo", "theme", "tree-sitter-markdown", diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index ec5aa52a1a..ee6ec2f6ed 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -25,7 +25,6 @@ project = { path = "../project" } search = { path = "../search" } serde = { version = "1.0", features = ["derive", "rc"] } settings = { path = "../settings" } -smallvec = { version = "1.6", features = ["union"] } sysinfo = "0.27.1" theme = { path = "../theme" } tree-sitter-markdown = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "330ecab87a3e3a7211ac69bbadc19eabecdb1cca" } diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index 564ac76203..ca960a7c10 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -7,18 +7,18 @@ use futures::AsyncReadExt; use gpui::{ actions, elements::{ChildView, Flex, Label, MouseEventHandler, ParentElement, Stack, Text}, - serde_json, AnyViewHandle, CursorStyle, Element, ElementBox, Entity, ModelHandle, MouseButton, - MutableAppContext, PromptLevel, RenderContext, Task, View, ViewContext, ViewHandle, + serde_json, AnyViewHandle, AppContext, CursorStyle, Element, ElementBox, Entity, ModelHandle, + MouseButton, MutableAppContext, PromptLevel, RenderContext, Task, View, ViewContext, + ViewHandle, }; use isahc::Request; use language::Buffer; use postage::prelude::Stream; use lazy_static::lazy_static; -use project::{Project, ProjectEntryId, ProjectPath}; +use project::Project; use serde::Serialize; use settings::Settings; -use smallvec::SmallVec; use workspace::{ item::{Item, ItemHandle}, searchable::{SearchableItem, SearchableItemHandle}, @@ -345,18 +345,14 @@ impl Item for FeedbackEditor { .boxed() } + fn for_each_project_item(&self, cx: &AppContext, f: &mut dyn FnMut(usize, &dyn project::Item)) { + self.editor.for_each_project_item(cx, f) + } + fn to_item_events(_: &Self::Event) -> Vec { Vec::new() } - fn project_path(&self, _: &gpui::AppContext) -> Option { - None - } - - fn project_entry_ids(&self, _: &gpui::AppContext) -> SmallVec<[ProjectEntryId; 3]> { - SmallVec::new() - } - fn is_singleton(&self, _: &gpui::AppContext) -> bool { true } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index c1c90f2560..a212949511 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -99,7 +99,7 @@ actions!( ToggleRightSidebar, NewTerminal, NewSearch, - Feedback + Feedback, ShowNotif, ] ); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 3b1d65c349..57219cf7aa 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -20,8 +20,7 @@ use gpui::{ }, impl_actions, platform::{WindowBounds, WindowOptions}, - AssetSource, AsyncAppContext, ClipboardItem, PromptLevel, TitlebarOptions, ViewContext, - WindowKind, + AssetSource, AsyncAppContext, PromptLevel, TitlebarOptions, ViewContext, WindowKind, }; use language::Rope; use lazy_static::lazy_static; From 95b259b841898caf5f720b10e34115bb5b489bc8 Mon Sep 17 00:00:00 2001 From: Julia Date: Mon, 23 Jan 2023 11:43:50 -0500 Subject: [PATCH 18/24] Avoid stomping on tab close icon's cursor style --- crates/workspace/src/pane.rs | 87 ++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 8d0d731551..f9124bfd83 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1150,7 +1150,7 @@ impl Pane { row.add_child({ enum Tab {} - dragged_item_receiver::(ix, ix, true, None, cx, { + let mut receiver = dragged_item_receiver::(ix, ix, true, None, cx, { let item = item.clone(); let pane = pane.clone(); let detail = detail.clone(); @@ -1162,50 +1162,51 @@ impl Pane { let hovered = mouse_state.hovered(); Self::render_tab(&item, pane, ix == 0, detail, hovered, tab_style, cx) } - }) - .with_cursor_style(if pane_active && tab_active { - CursorStyle::Arrow - } else { - CursorStyle::PointingHand - }) - .on_down(MouseButton::Left, move |_, cx| { - cx.dispatch_action(ActivateItem(ix)); - cx.propagate_event(); - }) - .on_click(MouseButton::Middle, { - let item = item.clone(); - let pane = pane.clone(); - move |_, cx: &mut EventContext| { - cx.dispatch_action(CloseItem { - item_id: item.id(), - pane: pane.clone(), - }) - } - }) - .as_draggable( - DraggedItem { - item, - pane: pane.clone(), - }, - { - let theme = cx.global::().theme.clone(); + }); - let detail = detail.clone(); - move |dragged_item, cx: &mut RenderContext| { - let tab_style = &theme.workspace.tab_bar.dragged_tab; - Self::render_tab( - &dragged_item.item, - dragged_item.pane.clone(), - false, - detail, - false, - &tab_style, - cx, - ) + if !pane_active || !tab_active { + receiver = receiver.with_cursor_style(CursorStyle::PointingHand); + } + + receiver + .on_down(MouseButton::Left, move |_, cx| { + cx.dispatch_action(ActivateItem(ix)); + cx.propagate_event(); + }) + .on_click(MouseButton::Middle, { + let item = item.clone(); + let pane = pane.clone(); + move |_, cx: &mut EventContext| { + cx.dispatch_action(CloseItem { + item_id: item.id(), + pane: pane.clone(), + }) } - }, - ) - .boxed() + }) + .as_draggable( + DraggedItem { + item, + pane: pane.clone(), + }, + { + let theme = cx.global::().theme.clone(); + + let detail = detail.clone(); + move |dragged_item, cx: &mut RenderContext| { + let tab_style = &theme.workspace.tab_bar.dragged_tab; + Self::render_tab( + &dragged_item.item, + dragged_item.pane.clone(), + false, + detail, + false, + &tab_style, + cx, + ) + } + }, + ) + .boxed() }) } From 4609be20deee44f61692dddd9900f3c05423a675 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 11 Jan 2023 17:52:18 -0800 Subject: [PATCH 19/24] WIP: Adding license compliance to CI --- licenses/test.tx | 1 + licenses/test.txt | 1 + script/collect-licenses.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 licenses/test.tx create mode 100644 licenses/test.txt create mode 100755 script/collect-licenses.js diff --git a/licenses/test.tx b/licenses/test.tx new file mode 100644 index 0000000000..9f27c62f59 --- /dev/null +++ b/licenses/test.tx @@ -0,0 +1 @@ +DATA DATA DATA \ No newline at end of file diff --git a/licenses/test.txt b/licenses/test.txt new file mode 100644 index 0000000000..b18c75c886 --- /dev/null +++ b/licenses/test.txt @@ -0,0 +1 @@ +Test test \ No newline at end of file diff --git a/script/collect-licenses.js b/script/collect-licenses.js new file mode 100755 index 0000000000..a0193a4899 --- /dev/null +++ b/script/collect-licenses.js @@ -0,0 +1,29 @@ +#!/usr/bin/env node + +const fs = require('fs'); + +const file_name = (path) => "./licenses/".concat(path); + +const writeFile = (path, data) => { + fs.writeFile(file_name(path), data, (err) => { + if (err) throw err; + console.log("Saved file") + }); +} + +main(); + +async function main() { + console.log("Here!"); + + writeFile("test.tx", "DATA DATA DATA") + + // Next steps: + // 1a. Add wiring in Zed to check for a licenses markdown file + // 1b. Add wiring in Zed.dev for builds to publish licenses alongside releases as well as licenses for Zed.dev itself + // 2. Figure out how to run those commands and get the license text for each MIT and Apache licensed software + // 3. Add in the configuration file: + // a. and refactor this script to have types of licenses + // b. add callback handlers for each type, + // c. check if the handler succeeds +} \ No newline at end of file From 9d5803206456f76abde64eb6d05ce3ac28202eda Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 13 Jan 2023 14:53:44 -0800 Subject: [PATCH 20/24] Add action to open licenses file --- assets/licenses.md | 1 + crates/workspace/src/workspace.rs | 1 + crates/zed/src/zed.rs | 25 +++++++++++++++++++++---- licenses/test.tx | 1 - licenses/test.txt | 1 - script/collect-licenses.js | 29 ----------------------------- script/collect-licenses.rs | 17 +++++++++++++++++ 7 files changed, 40 insertions(+), 35 deletions(-) create mode 100644 assets/licenses.md delete mode 100644 licenses/test.tx delete mode 100644 licenses/test.txt delete mode 100755 script/collect-licenses.js create mode 100755 script/collect-licenses.rs diff --git a/assets/licenses.md b/assets/licenses.md new file mode 100644 index 0000000000..b4c705632b --- /dev/null +++ b/assets/licenses.md @@ -0,0 +1 @@ +TWSTS \ No newline at end of file diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 8735f33fbe..e8af0d62fc 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -233,6 +233,7 @@ pub fn init(app_state: Arc, cx: &mut MutableAppContext) { workspace.toggle_sidebar(SidebarSide::Right, cx); }); cx.add_action(Workspace::activate_pane_at_index); + cx.add_action(Workspace::split_pane_with_item); cx.add_action(Workspace::split_pane_with_project_entry); diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index b6b00e7869..30f5bef53b 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -62,6 +62,7 @@ actions!( DebugElements, OpenSettings, OpenLog, + OpenLicenses, OpenTelemetryLog, OpenKeymap, OpenDefaultSettings, @@ -184,6 +185,19 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { open_log_file(workspace, app_state.clone(), cx); } }); + cx.add_action({ + let app_state = app_state.clone(); + move |workspace: &mut Workspace, _: &OpenLicenses, cx: &mut ViewContext| { + open_bundled_file( + workspace, + app_state.clone(), + "licenses.md", + "Open Source License Attribution", + "Markdown", + cx, + ); + } + }); cx.add_action({ let app_state = app_state.clone(); move |workspace: &mut Workspace, _: &OpenTelemetryLog, cx: &mut ViewContext| { @@ -199,11 +213,12 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { cx.add_action({ let app_state = app_state.clone(); move |workspace: &mut Workspace, _: &OpenDefaultKeymap, cx: &mut ViewContext| { - open_bundled_config_file( + open_bundled_file( workspace, app_state.clone(), "keymaps/default.json", "Default Key Bindings", + "JSON", cx, ); } @@ -213,11 +228,12 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { move |workspace: &mut Workspace, _: &OpenDefaultSettings, cx: &mut ViewContext| { - open_bundled_config_file( + open_bundled_file( workspace, app_state.clone(), "settings/default.json", "Default Settings", + "JSON", cx, ); } @@ -656,11 +672,12 @@ fn open_telemetry_log_file( }).detach(); } -fn open_bundled_config_file( +fn open_bundled_file( workspace: &mut Workspace, app_state: Arc, asset_path: &'static str, title: &'static str, + language: &'static str, cx: &mut ViewContext, ) { workspace @@ -670,7 +687,7 @@ fn open_bundled_config_file( let text = Assets::get(asset_path).unwrap().data; let text = str::from_utf8(text.as_ref()).unwrap(); project - .create_buffer(text, project.languages().get_language("JSON"), cx) + .create_buffer(text, project.languages().get_language(language), cx) .expect("creating buffers on a local workspace always succeeds") }); let buffer = diff --git a/licenses/test.tx b/licenses/test.tx deleted file mode 100644 index 9f27c62f59..0000000000 --- a/licenses/test.tx +++ /dev/null @@ -1 +0,0 @@ -DATA DATA DATA \ No newline at end of file diff --git a/licenses/test.txt b/licenses/test.txt deleted file mode 100644 index b18c75c886..0000000000 --- a/licenses/test.txt +++ /dev/null @@ -1 +0,0 @@ -Test test \ No newline at end of file diff --git a/script/collect-licenses.js b/script/collect-licenses.js deleted file mode 100755 index a0193a4899..0000000000 --- a/script/collect-licenses.js +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs'); - -const file_name = (path) => "./licenses/".concat(path); - -const writeFile = (path, data) => { - fs.writeFile(file_name(path), data, (err) => { - if (err) throw err; - console.log("Saved file") - }); -} - -main(); - -async function main() { - console.log("Here!"); - - writeFile("test.tx", "DATA DATA DATA") - - // Next steps: - // 1a. Add wiring in Zed to check for a licenses markdown file - // 1b. Add wiring in Zed.dev for builds to publish licenses alongside releases as well as licenses for Zed.dev itself - // 2. Figure out how to run those commands and get the license text for each MIT and Apache licensed software - // 3. Add in the configuration file: - // a. and refactor this script to have types of licenses - // b. add callback handlers for each type, - // c. check if the handler succeeds -} \ No newline at end of file diff --git a/script/collect-licenses.rs b/script/collect-licenses.rs new file mode 100755 index 0000000000..2814feaa08 --- /dev/null +++ b/script/collect-licenses.rs @@ -0,0 +1,17 @@ +//usr/bin/env rustc $0 -o a.out && ./a.out ; rm -f ./a.out ; exit + +fn main() { + println!("Hello world"); + + +} + +// Next steps: +// 1a. Add wiring in Zed to check for a licenses markdown file +// 1b. Add wiring in Zed.dev for builds to publish licenses alongside releases as well as licenses for Zed.dev itself +// (e.g. https://github.com/zed-industries/zed.dev/tree/main/content/licenses) +// 2. Figure out how to run those commands and get the license text for each MIT and Apache licensed software +// 3. Add in the configuration file: +// a. and refactor this script to have types of licenses +// b. add callback handlers for each type, +// c. check if the handler succeeds From d060114f00c198f72f0e571464893cf55c100545 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Wed, 18 Jan 2023 12:28:02 -0800 Subject: [PATCH 21/24] Added complete scripts for generating third party license files --- assets/licenses.md | 2 +- crates/activity_indicator/Cargo.toml | 1 + crates/assets/Cargo.toml | 1 + crates/auto_update/Cargo.toml | 1 + crates/breadcrumbs/Cargo.toml | 1 + crates/call/Cargo.toml | 1 + crates/cli/Cargo.toml | 1 + crates/client/Cargo.toml | 1 + crates/clock/Cargo.toml | 1 + crates/collab/Cargo.toml | 1 + crates/collab_ui/Cargo.toml | 1 + crates/collections/Cargo.toml | 1 + crates/command_palette/Cargo.toml | 1 + crates/context_menu/Cargo.toml | 1 + crates/db/Cargo.toml | 1 + crates/diagnostics/Cargo.toml | 1 + crates/drag_and_drop/Cargo.toml | 1 + crates/editor/Cargo.toml | 1 + crates/file_finder/Cargo.toml | 1 + crates/fs/Cargo.toml | 1 + crates/fsevent/Cargo.toml | 1 + crates/fuzzy/Cargo.toml | 1 + crates/git/Cargo.toml | 1 + crates/go_to_line/Cargo.toml | 1 + crates/gpui/Cargo.toml | 1 + crates/gpui_macros/Cargo.toml | 1 + crates/journal/Cargo.toml | 1 + crates/language/Cargo.toml | 1 + crates/live_kit_client/Cargo.toml | 1 + crates/live_kit_server/Cargo.toml | 1 + crates/lsp/Cargo.toml | 1 + crates/media/Cargo.toml | 1 + crates/menu/Cargo.toml | 1 + crates/outline/Cargo.toml | 1 + crates/picker/Cargo.toml | 1 + crates/plugin/Cargo.toml | 1 + crates/plugin_macros/Cargo.toml | 1 + crates/plugin_runtime/Cargo.toml | 1 + crates/project/Cargo.toml | 1 + crates/project_panel/Cargo.toml | 1 + crates/project_symbols/Cargo.toml | 1 + crates/recent_projects/Cargo.toml | 1 + crates/rope/Cargo.toml | 1 + crates/rpc/Cargo.toml | 1 + crates/search/Cargo.toml | 1 + crates/settings/Cargo.toml | 1 + crates/snippet/Cargo.toml | 1 + crates/sqlez/Cargo.toml | 1 + crates/sqlez_macros/Cargo.toml | 1 + crates/sum_tree/Cargo.toml | 1 + crates/terminal/Cargo.toml | 1 + crates/terminal_view/Cargo.toml | 1 + crates/text/Cargo.toml | 1 + crates/theme/Cargo.toml | 1 + crates/theme_selector/Cargo.toml | 1 + crates/theme_testbench/Cargo.toml | 1 + crates/util/Cargo.toml | 1 + crates/vim/Cargo.toml | 1 + crates/workspace/Cargo.toml | 1 + crates/zed/Cargo.toml | 1 + script/collect-licenses.rs | 17 ------------- script/generate-licenses | 10 ++++++++ script/licenses/template.hbs.md | 27 ++++++++++++++++++++ script/licenses/zed-licenses.toml | 37 ++++++++++++++++++++++++++++ styles/src/themes/one-light.ts | 18 +++++++------- 65 files changed, 143 insertions(+), 27 deletions(-) delete mode 100755 script/collect-licenses.rs create mode 100755 script/generate-licenses create mode 100644 script/licenses/template.hbs.md create mode 100644 script/licenses/zed-licenses.toml diff --git a/assets/licenses.md b/assets/licenses.md index b4c705632b..5d70eab88b 100644 --- a/assets/licenses.md +++ b/assets/licenses.md @@ -1 +1 @@ -TWSTS \ No newline at end of file +Place holder \ No newline at end of file diff --git a/crates/activity_indicator/Cargo.toml b/crates/activity_indicator/Cargo.toml index 63998fa47b..78a4e752b2 100644 --- a/crates/activity_indicator/Cargo.toml +++ b/crates/activity_indicator/Cargo.toml @@ -2,6 +2,7 @@ name = "activity_indicator" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/activity_indicator.rs" diff --git a/crates/assets/Cargo.toml b/crates/assets/Cargo.toml index 71db57f320..ca96c92602 100644 --- a/crates/assets/Cargo.toml +++ b/crates/assets/Cargo.toml @@ -2,6 +2,7 @@ name = "assets" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/assets.rs" diff --git a/crates/auto_update/Cargo.toml b/crates/auto_update/Cargo.toml index b1ca061614..5f672e759f 100644 --- a/crates/auto_update/Cargo.toml +++ b/crates/auto_update/Cargo.toml @@ -2,6 +2,7 @@ name = "auto_update" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/auto_update.rs" diff --git a/crates/breadcrumbs/Cargo.toml b/crates/breadcrumbs/Cargo.toml index e5cae74e8f..99476fdc0a 100644 --- a/crates/breadcrumbs/Cargo.toml +++ b/crates/breadcrumbs/Cargo.toml @@ -2,6 +2,7 @@ name = "breadcrumbs" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/breadcrumbs.rs" diff --git a/crates/call/Cargo.toml b/crates/call/Cargo.toml index e6aa357bef..156925fb72 100644 --- a/crates/call/Cargo.toml +++ b/crates/call/Cargo.toml @@ -2,6 +2,7 @@ name = "call" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/call.rs" diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index fafcc5ab68..f2bab22ea7 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -2,6 +2,7 @@ name = "cli" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/cli.rs" diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index 74533fbc3b..347424d34e 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -2,6 +2,7 @@ name = "client" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/client.rs" diff --git a/crates/clock/Cargo.toml b/crates/clock/Cargo.toml index 8e17e15e5e..1705fdc6d5 100644 --- a/crates/clock/Cargo.toml +++ b/crates/clock/Cargo.toml @@ -2,6 +2,7 @@ name = "clock" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/clock.rs" diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 8c21af7273..456bcf6531 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -4,6 +4,7 @@ default-run = "collab" edition = "2021" name = "collab" version = "0.5.3" +publish = false [[bin]] name = "collab" diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index 20db066ce7..ac13e361fd 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -2,6 +2,7 @@ name = "collab_ui" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/collab_ui.rs" diff --git a/crates/collections/Cargo.toml b/crates/collections/Cargo.toml index 8e18cbd11d..dcbc642c4c 100644 --- a/crates/collections/Cargo.toml +++ b/crates/collections/Cargo.toml @@ -2,6 +2,7 @@ name = "collections" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/collections.rs" diff --git a/crates/command_palette/Cargo.toml b/crates/command_palette/Cargo.toml index 85f5b36ed6..555deff1ce 100644 --- a/crates/command_palette/Cargo.toml +++ b/crates/command_palette/Cargo.toml @@ -2,6 +2,7 @@ name = "command_palette" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/command_palette.rs" diff --git a/crates/context_menu/Cargo.toml b/crates/context_menu/Cargo.toml index 817893f43e..d764d4ddb8 100644 --- a/crates/context_menu/Cargo.toml +++ b/crates/context_menu/Cargo.toml @@ -2,6 +2,7 @@ name = "context_menu" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/context_menu.rs" diff --git a/crates/db/Cargo.toml b/crates/db/Cargo.toml index 8e12b06027..496e61b811 100644 --- a/crates/db/Cargo.toml +++ b/crates/db/Cargo.toml @@ -2,6 +2,7 @@ name = "db" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/db.rs" diff --git a/crates/diagnostics/Cargo.toml b/crates/diagnostics/Cargo.toml index 616f69117f..ebb57e0636 100644 --- a/crates/diagnostics/Cargo.toml +++ b/crates/diagnostics/Cargo.toml @@ -2,6 +2,7 @@ name = "diagnostics" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/diagnostics.rs" diff --git a/crates/drag_and_drop/Cargo.toml b/crates/drag_and_drop/Cargo.toml index 4ab54ad8e6..e378a5bc31 100644 --- a/crates/drag_and_drop/Cargo.toml +++ b/crates/drag_and_drop/Cargo.toml @@ -2,6 +2,7 @@ name = "drag_and_drop" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/drag_and_drop.rs" diff --git a/crates/editor/Cargo.toml b/crates/editor/Cargo.toml index f992ed5116..26dd371041 100644 --- a/crates/editor/Cargo.toml +++ b/crates/editor/Cargo.toml @@ -2,6 +2,7 @@ name = "editor" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/editor.rs" diff --git a/crates/file_finder/Cargo.toml b/crates/file_finder/Cargo.toml index 6fd792940d..1d1a4dfb1b 100644 --- a/crates/file_finder/Cargo.toml +++ b/crates/file_finder/Cargo.toml @@ -2,6 +2,7 @@ name = "file_finder" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/file_finder.rs" diff --git a/crates/fs/Cargo.toml b/crates/fs/Cargo.toml index 5b9082d114..cd6c8f969c 100644 --- a/crates/fs/Cargo.toml +++ b/crates/fs/Cargo.toml @@ -2,6 +2,7 @@ name = "fs" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/fs.rs" diff --git a/crates/fsevent/Cargo.toml b/crates/fsevent/Cargo.toml index 3bf7ae885b..e71e247bf2 100644 --- a/crates/fsevent/Cargo.toml +++ b/crates/fsevent/Cargo.toml @@ -3,6 +3,7 @@ name = "fsevent" version = "2.0.2" license = "MIT" edition = "2021" +publish = false [lib] path = "src/fsevent.rs" diff --git a/crates/fuzzy/Cargo.toml b/crates/fuzzy/Cargo.toml index e36c22055a..553c0497a5 100644 --- a/crates/fuzzy/Cargo.toml +++ b/crates/fuzzy/Cargo.toml @@ -2,6 +2,7 @@ name = "fuzzy" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/fuzzy.rs" diff --git a/crates/git/Cargo.toml b/crates/git/Cargo.toml index 66202a489a..3e88d72313 100644 --- a/crates/git/Cargo.toml +++ b/crates/git/Cargo.toml @@ -2,6 +2,7 @@ name = "git" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/git.rs" diff --git a/crates/go_to_line/Cargo.toml b/crates/go_to_line/Cargo.toml index 93ae96f93e..def6361dc2 100644 --- a/crates/go_to_line/Cargo.toml +++ b/crates/go_to_line/Cargo.toml @@ -2,6 +2,7 @@ name = "go_to_line" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/go_to_line.rs" diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 5153c1f7c1..e1b6e11b46 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -4,6 +4,7 @@ edition = "2021" name = "gpui" version = "0.1.0" description = "A GPU-accelerated UI framework" +publish = false [lib] path = "src/gpui.rs" diff --git a/crates/gpui_macros/Cargo.toml b/crates/gpui_macros/Cargo.toml index e35e0b1d2b..76daeae2a8 100644 --- a/crates/gpui_macros/Cargo.toml +++ b/crates/gpui_macros/Cargo.toml @@ -2,6 +2,7 @@ name = "gpui_macros" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/gpui_macros.rs" diff --git a/crates/journal/Cargo.toml b/crates/journal/Cargo.toml index 9622049a9c..b532397dd1 100644 --- a/crates/journal/Cargo.toml +++ b/crates/journal/Cargo.toml @@ -2,6 +2,7 @@ name = "journal" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/journal.rs" diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index 6c074a2d75..ab6c687b7a 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -2,6 +2,7 @@ name = "language" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/language.rs" diff --git a/crates/live_kit_client/Cargo.toml b/crates/live_kit_client/Cargo.toml index d0f54782b9..0145737508 100644 --- a/crates/live_kit_client/Cargo.toml +++ b/crates/live_kit_client/Cargo.toml @@ -3,6 +3,7 @@ name = "live_kit_client" version = "0.1.0" edition = "2021" description = "Bindings to LiveKit Swift client SDK" +publish = false [lib] path = "src/live_kit_client.rs" diff --git a/crates/live_kit_server/Cargo.toml b/crates/live_kit_server/Cargo.toml index 64267f62d1..17ee3cd62e 100644 --- a/crates/live_kit_server/Cargo.toml +++ b/crates/live_kit_server/Cargo.toml @@ -3,6 +3,7 @@ name = "live_kit_server" version = "0.1.0" edition = "2021" description = "SDK for the LiveKit server API" +publish = false [lib] path = "src/live_kit_server.rs" diff --git a/crates/lsp/Cargo.toml b/crates/lsp/Cargo.toml index 94780a9472..eb6e02aac9 100644 --- a/crates/lsp/Cargo.toml +++ b/crates/lsp/Cargo.toml @@ -2,6 +2,7 @@ name = "lsp" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/lsp.rs" diff --git a/crates/media/Cargo.toml b/crates/media/Cargo.toml index aad2b74c02..4c230819e2 100644 --- a/crates/media/Cargo.toml +++ b/crates/media/Cargo.toml @@ -2,6 +2,7 @@ name = "media" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/media.rs" diff --git a/crates/menu/Cargo.toml b/crates/menu/Cargo.toml index cdcacd4416..c473df7ef0 100644 --- a/crates/menu/Cargo.toml +++ b/crates/menu/Cargo.toml @@ -2,6 +2,7 @@ name = "menu" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/menu.rs" diff --git a/crates/outline/Cargo.toml b/crates/outline/Cargo.toml index 5b4751e620..661c84c8cd 100644 --- a/crates/outline/Cargo.toml +++ b/crates/outline/Cargo.toml @@ -2,6 +2,7 @@ name = "outline" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/outline.rs" diff --git a/crates/picker/Cargo.toml b/crates/picker/Cargo.toml index 6438697910..e7a8079caa 100644 --- a/crates/picker/Cargo.toml +++ b/crates/picker/Cargo.toml @@ -2,6 +2,7 @@ name = "picker" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/picker.rs" diff --git a/crates/plugin/Cargo.toml b/crates/plugin/Cargo.toml index 6f37c458d9..7bf5510465 100644 --- a/crates/plugin/Cargo.toml +++ b/crates/plugin/Cargo.toml @@ -2,6 +2,7 @@ name = "plugin" version = "0.1.0" edition = "2021" +publish = false [dependencies] serde = "1.0" diff --git a/crates/plugin_macros/Cargo.toml b/crates/plugin_macros/Cargo.toml index b0a2c4e09b..32bfc6a01a 100644 --- a/crates/plugin_macros/Cargo.toml +++ b/crates/plugin_macros/Cargo.toml @@ -2,6 +2,7 @@ name = "plugin_macros" version = "0.1.0" edition = "2021" +publish = false [lib] proc-macro = true diff --git a/crates/plugin_runtime/Cargo.toml b/crates/plugin_runtime/Cargo.toml index a8c0a063a8..b5cfb9514f 100644 --- a/crates/plugin_runtime/Cargo.toml +++ b/crates/plugin_runtime/Cargo.toml @@ -2,6 +2,7 @@ name = "plugin_runtime" version = "0.1.0" edition = "2021" +publish = false [dependencies] wasmtime = "0.38" diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index 6d6560ea38..949dbdf916 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -2,6 +2,7 @@ name = "project" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/project.rs" diff --git a/crates/project_panel/Cargo.toml b/crates/project_panel/Cargo.toml index 8704f57c8c..cc27f40954 100644 --- a/crates/project_panel/Cargo.toml +++ b/crates/project_panel/Cargo.toml @@ -2,6 +2,7 @@ name = "project_panel" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/project_panel.rs" diff --git a/crates/project_symbols/Cargo.toml b/crates/project_symbols/Cargo.toml index a426e2e0d4..e9283b14c9 100644 --- a/crates/project_symbols/Cargo.toml +++ b/crates/project_symbols/Cargo.toml @@ -2,6 +2,7 @@ name = "project_symbols" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/project_symbols.rs" diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index d633381365..037c6fd4fb 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -2,6 +2,7 @@ name = "recent_projects" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/recent_projects.rs" diff --git a/crates/rope/Cargo.toml b/crates/rope/Cargo.toml index e9ddcc8195..8257ef4a6e 100644 --- a/crates/rope/Cargo.toml +++ b/crates/rope/Cargo.toml @@ -2,6 +2,7 @@ name = "rope" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/rope.rs" diff --git a/crates/rpc/Cargo.toml b/crates/rpc/Cargo.toml index cd959e75a1..25c2ce1ca7 100644 --- a/crates/rpc/Cargo.toml +++ b/crates/rpc/Cargo.toml @@ -3,6 +3,7 @@ description = "Shared logic for communication between the Zed app and the zed.de edition = "2021" name = "rpc" version = "0.1.0" +publish = false [lib] path = "src/rpc.rs" diff --git a/crates/search/Cargo.toml b/crates/search/Cargo.toml index 3a5d9468fc..f36865a89b 100644 --- a/crates/search/Cargo.toml +++ b/crates/search/Cargo.toml @@ -2,6 +2,7 @@ name = "search" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/search.rs" diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index a292358e75..c1ec2a6210 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -2,6 +2,7 @@ name = "settings" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/settings.rs" diff --git a/crates/snippet/Cargo.toml b/crates/snippet/Cargo.toml index 03a0f8314a..429f5d416e 100644 --- a/crates/snippet/Cargo.toml +++ b/crates/snippet/Cargo.toml @@ -2,6 +2,7 @@ name = "snippet" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/snippet.rs" diff --git a/crates/sqlez/Cargo.toml b/crates/sqlez/Cargo.toml index 78bf83dc30..8409a1dff5 100644 --- a/crates/sqlez/Cargo.toml +++ b/crates/sqlez/Cargo.toml @@ -2,6 +2,7 @@ name = "sqlez" version = "0.1.0" edition = "2021" +publish = false # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/sqlez_macros/Cargo.toml b/crates/sqlez_macros/Cargo.toml index 423b494500..8d650074c3 100644 --- a/crates/sqlez_macros/Cargo.toml +++ b/crates/sqlez_macros/Cargo.toml @@ -2,6 +2,7 @@ name = "sqlez_macros" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/sqlez_macros.rs" diff --git a/crates/sum_tree/Cargo.toml b/crates/sum_tree/Cargo.toml index 02cad4fb9d..3aab16cc3e 100644 --- a/crates/sum_tree/Cargo.toml +++ b/crates/sum_tree/Cargo.toml @@ -2,6 +2,7 @@ name = "sum_tree" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/sum_tree.rs" diff --git a/crates/terminal/Cargo.toml b/crates/terminal/Cargo.toml index 0dea7bfbcf..c6f33a0fc7 100644 --- a/crates/terminal/Cargo.toml +++ b/crates/terminal/Cargo.toml @@ -2,6 +2,7 @@ name = "terminal" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/terminal.rs" diff --git a/crates/terminal_view/Cargo.toml b/crates/terminal_view/Cargo.toml index 05fda2c75f..f12e4be03b 100644 --- a/crates/terminal_view/Cargo.toml +++ b/crates/terminal_view/Cargo.toml @@ -2,6 +2,7 @@ name = "terminal_view" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/terminal_view.rs" diff --git a/crates/text/Cargo.toml b/crates/text/Cargo.toml index ad960ec93e..5fda4b613c 100644 --- a/crates/text/Cargo.toml +++ b/crates/text/Cargo.toml @@ -2,6 +2,7 @@ name = "text" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/text.rs" diff --git a/crates/theme/Cargo.toml b/crates/theme/Cargo.toml index 36de158afe..1e9883860f 100644 --- a/crates/theme/Cargo.toml +++ b/crates/theme/Cargo.toml @@ -2,6 +2,7 @@ name = "theme" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/theme.rs" diff --git a/crates/theme_selector/Cargo.toml b/crates/theme_selector/Cargo.toml index 59cb5fbc2c..8f6fc74600 100644 --- a/crates/theme_selector/Cargo.toml +++ b/crates/theme_selector/Cargo.toml @@ -2,6 +2,7 @@ name = "theme_selector" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/theme_selector.rs" diff --git a/crates/theme_testbench/Cargo.toml b/crates/theme_testbench/Cargo.toml index 5fb263501f..763727fc68 100644 --- a/crates/theme_testbench/Cargo.toml +++ b/crates/theme_testbench/Cargo.toml @@ -2,6 +2,7 @@ name = "theme_testbench" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/theme_testbench.rs" diff --git a/crates/util/Cargo.toml b/crates/util/Cargo.toml index 0a0bacf53c..4cbaa382e8 100644 --- a/crates/util/Cargo.toml +++ b/crates/util/Cargo.toml @@ -2,6 +2,7 @@ name = "util" version = "0.1.0" edition = "2021" +publish = false [lib] doctest = false diff --git a/crates/vim/Cargo.toml b/crates/vim/Cargo.toml index daefebdbdd..bd94e48b9e 100644 --- a/crates/vim/Cargo.toml +++ b/crates/vim/Cargo.toml @@ -2,6 +2,7 @@ name = "vim" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/vim.rs" diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 5894a2a44e..60680f82a2 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -2,6 +2,7 @@ name = "workspace" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/workspace.rs" diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 63719b7003..f2e82bd63f 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -4,6 +4,7 @@ description = "The fast, collaborative code editor." edition = "2021" name = "zed" version = "0.71.0" +publish = false [lib] name = "zed" diff --git a/script/collect-licenses.rs b/script/collect-licenses.rs deleted file mode 100755 index 2814feaa08..0000000000 --- a/script/collect-licenses.rs +++ /dev/null @@ -1,17 +0,0 @@ -//usr/bin/env rustc $0 -o a.out && ./a.out ; rm -f ./a.out ; exit - -fn main() { - println!("Hello world"); - - -} - -// Next steps: -// 1a. Add wiring in Zed to check for a licenses markdown file -// 1b. Add wiring in Zed.dev for builds to publish licenses alongside releases as well as licenses for Zed.dev itself -// (e.g. https://github.com/zed-industries/zed.dev/tree/main/content/licenses) -// 2. Figure out how to run those commands and get the license text for each MIT and Apache licensed software -// 3. Add in the configuration file: -// a. and refactor this script to have types of licenses -// b. add callback handlers for each type, -// c. check if the handler succeeds diff --git a/script/generate-licenses b/script/generate-licenses new file mode 100755 index 0000000000..31febf263f --- /dev/null +++ b/script/generate-licenses @@ -0,0 +1,10 @@ +#!/bin/bash +cargo about generate --workspace -o assets/licenses.md -c script/licenses/zed-licenses.toml script/licenses/template.hbs.md + +# cargo about automatically html-escapes all output, so we need to undo it here: +sed -i '' 's/"/"/g' assets/licenses.md +sed -i '' 's/'/'\''/g' assets/licenses.md # `'\''` ends the string, appends a single quote, and re-opens the string +sed -i '' 's/=/=/g' assets/licenses.md +sed -i '' 's/`/`/g' assets/licenses.md +sed -i '' 's/<//g' assets/licenses.md diff --git a/script/licenses/template.hbs.md b/script/licenses/template.hbs.md new file mode 100644 index 0000000000..a51b714dae --- /dev/null +++ b/script/licenses/template.hbs.md @@ -0,0 +1,27 @@ +# Third Party Licenses + +This page lists the licenses of the projects used in Zed. + +## Overview of licenses: + +{{#each overview}} +* {{name}} ({{count}}) +{{/each}} + +## All license texts: + +{{#each licenses}} + +### {{name}} + +#### Used by: + +{{#each used_by}} +* [{{crate.name}} {{crate.version}}]({{#if crate.repository}} {{crate.repository}} {{else}} https://crates.io/crates/{{crate.name}} {{/if}}) +{{/each}} + +{{text}} + +-------------------------------------------------------------------------------- + +{{/each}} \ No newline at end of file diff --git a/script/licenses/zed-licenses.toml b/script/licenses/zed-licenses.toml new file mode 100644 index 0000000000..2e294878d7 --- /dev/null +++ b/script/licenses/zed-licenses.toml @@ -0,0 +1,37 @@ +no-clearly-defined = true +private = { ignore = true } +accepted = [ + "Apache-2.0", + "MIT", + "Apache-2.0 WITH LLVM-exception", + "MPL-2.0", + "BSD-3-Clause", + "BSD-2-Clause", + "ISC", + "CC0-1.0", + "Unicode-DFS-2016", + "OpenSSL", + "Zlib", +] +workarounds = [ + "ring", + "wasmtime", +] + +[procinfo.clarify] +license = "MIT" +[[procinfo.clarify.git]] +path = 'LICENSE.md' +checksum = '37db33bbbd7348969eda397b89a16f252d56c1ca7481b6ccaf56ccdcbab5dcca' + +[webpki.clarify] +license = "ISC" # It actually says 'ISC-style' but I don't know the SPDX expression for that. +[[webpki.clarify.files]] +path = 'LICENSE' +checksum = '5b698ca13897be3afdb7174256fa1574f8c6892b8bea1a66dd6469d3fe27885a' + +[fuchsia-cprng.clarify] +license = "BSD-3-Clause" +[[fuchsia-cprng.clarify.files]] +path = 'LICENSE' +checksum = '03b114f53e6587a398931762ee11e2395bfdba252a329940e2c8c9e81813845b' \ No newline at end of file diff --git a/styles/src/themes/one-light.ts b/styles/src/themes/one-light.ts index d8c8e5272c..a5ac1f7158 100644 --- a/styles/src/themes/one-light.ts +++ b/styles/src/themes/one-light.ts @@ -11,15 +11,15 @@ const license = { export const light = createColorScheme(`${name}`, true, { neutral: chroma.scale([ - "#090a0b", - "#202227", - "#383a42", - "#696c77", - "#a0a1a7", - "#e5e5e6", - "#f0f0f1", - "#fafafa", - ]) + "#090a0b", + "#202227", + "#383a42", + "#696c77", + "#a0a1a7", + "#e5e5e6", + "#f0f0f1", + "#fafafa", + ]) .domain([0.05, 0.22, 0.25, 0.45, 0.62, 0.8, 0.9, 1]), red: colorRamp(chroma("#ca1243")), From 0f0d5d5726cae330238a545e26c7910f470373a0 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Mon, 23 Jan 2023 12:43:19 -0800 Subject: [PATCH 22/24] Added cargo-about auto-install and CI steps --- .github/workflows/ci.yml | 10 ++++++++-- .gitignore | 1 + assets/licenses.md | 1 - crates/zed/src/zed.rs | 6 ++++-- script/generate-licenses | 9 +++++++-- script/licenses/zed-licenses.toml | 2 +- 6 files changed, 21 insertions(+), 8 deletions(-) delete mode 100644 assets/licenses.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7072a3fe94..fce5717ca9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,16 +41,19 @@ jobs: with: clean: false submodules: 'recursive' - + - name: Run tests run: cargo test --workspace --no-fail-fast - + - name: Build collab run: cargo build -p collab - name: Build other binaries run: cargo build --workspace --bins --all-features + - name: Generate license file + run: script/generate-licenses + bundle: name: Bundle app runs-on: @@ -109,6 +112,9 @@ jobs: exit 1 fi + - name: Generate license file + run: script/generate-licenses + - name: Create app bundle run: script/bundle diff --git a/.gitignore b/.gitignore index 356f4d97cd..8bca2eafac 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /assets/themes/*.json /assets/themes/Internal/*.json /assets/themes/Experiments/*.json +/assets/licenses.md **/venv .build Packages diff --git a/assets/licenses.md b/assets/licenses.md deleted file mode 100644 index 5d70eab88b..0000000000 --- a/assets/licenses.md +++ /dev/null @@ -1 +0,0 @@ -Place holder \ No newline at end of file diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 30f5bef53b..53bc9d5abc 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -35,7 +35,7 @@ use search::{BufferSearchBar, ProjectSearchBar}; use serde::Deserialize; use serde_json::to_string_pretty; use settings::{keymap_file_json_schema, settings_file_json_schema, Settings}; -use std::{env, path::Path, str, sync::Arc}; +use std::{borrow::Cow, env, path::Path, str, sync::Arc}; use system_specs::SystemSpecs; use util::{channel::ReleaseChannel, paths, ResultExt}; pub use workspace; @@ -684,7 +684,9 @@ fn open_bundled_file( .with_local_workspace(&app_state, cx, |workspace, cx| { let project = workspace.project().clone(); let buffer = project.update(cx, |project, cx| { - let text = Assets::get(asset_path).unwrap().data; + let text = Assets::get(asset_path) + .map(|f| f.data) + .unwrap_or_else(|| Cow::Borrowed(b"File not found")); let text = str::from_utf8(text.as_ref()).unwrap(); project .create_buffer(text, project.languages().get_language(language), cx) diff --git a/script/generate-licenses b/script/generate-licenses index 31febf263f..e1a917292c 100755 --- a/script/generate-licenses +++ b/script/generate-licenses @@ -1,5 +1,10 @@ #!/bin/bash -cargo about generate --workspace -o assets/licenses.md -c script/licenses/zed-licenses.toml script/licenses/template.hbs.md + +set -e + +[[ "$(cargo about --version)" == "cargo-about 0.5.2" ]] || cargo install cargo-about --locked --git https://github.com/zed-industries/cargo-about --branch error-code-on-warn + +cargo about generate --fail-on-missing-license -o assets/licenses.md -c script/licenses/zed-licenses.toml script/licenses/template.hbs.md # cargo about automatically html-escapes all output, so we need to undo it here: sed -i '' 's/"/"/g' assets/licenses.md @@ -7,4 +12,4 @@ sed -i '' 's/'/'\''/g' assets/licenses.md # `'\''` ends the string, appends sed -i '' 's/=/=/g' assets/licenses.md sed -i '' 's/`/`/g' assets/licenses.md sed -i '' 's/<//g' assets/licenses.md +sed -i '' 's/>/>/g' assets/licenses.md \ No newline at end of file diff --git a/script/licenses/zed-licenses.toml b/script/licenses/zed-licenses.toml index 2e294878d7..d338e7ab0b 100644 --- a/script/licenses/zed-licenses.toml +++ b/script/licenses/zed-licenses.toml @@ -34,4 +34,4 @@ checksum = '5b698ca13897be3afdb7174256fa1574f8c6892b8bea1a66dd6469d3fe27885a' license = "BSD-3-Clause" [[fuchsia-cprng.clarify.files]] path = 'LICENSE' -checksum = '03b114f53e6587a398931762ee11e2395bfdba252a329940e2c8c9e81813845b' \ No newline at end of file +checksum = '03b114f53e6587a398931762ee11e2395bfdba252a329940e2c8c9e81813845b' From c9299a49e16d904cb268f7b154c82d7346b6f9e0 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 23 Jan 2023 18:19:10 -0500 Subject: [PATCH 23/24] Clean out unused code --- crates/feedback/src/feedback_editor.rs | 67 +------------------------- crates/theme/src/theme.rs | 15 ------ crates/workspace/src/pane.rs | 8 +-- styles/src/styleTree/app.ts | 2 - styles/src/styleTree/feedback.ts | 35 -------------- 5 files changed, 2 insertions(+), 125 deletions(-) delete mode 100644 styles/src/styleTree/feedback.ts diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index ca960a7c10..8185fbad9a 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -37,7 +37,7 @@ const FEEDBACK_CHAR_COUNT_RANGE: Range = Range { end: 1000, }; -const FEEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here in the form of Markdown. Save the tab to submit your feedback."; +const FEEDBACK_PLACEHOLDER_TEXT: &str = "Thanks for spending time with Zed. Enter your feedback here as Markdown. Save the tab to submit your feedback."; const FEEDBACK_SUBMISSION_ERROR_TEXT: &str = "Feedback failed to submit, see error log for details."; @@ -77,71 +77,6 @@ impl View for FeedbackButton { ) .boxed() } - - fn focus_in(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) {} - - fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext) {} - - fn key_down(&mut self, _: &gpui::KeyDownEvent, _: &mut ViewContext) -> bool { - false - } - - fn key_up(&mut self, _: &gpui::KeyUpEvent, _: &mut ViewContext) -> bool { - false - } - - fn modifiers_changed( - &mut self, - _: &gpui::ModifiersChangedEvent, - _: &mut ViewContext, - ) -> bool { - false - } - - fn keymap_context(&self, _: &gpui::AppContext) -> gpui::keymap_matcher::KeymapContext { - Self::default_keymap_context() - } - - fn default_keymap_context() -> gpui::keymap_matcher::KeymapContext { - let mut cx = gpui::keymap_matcher::KeymapContext::default(); - cx.set.insert(Self::ui_name().into()); - cx - } - - fn debug_json(&self, _: &gpui::AppContext) -> gpui::serde_json::Value { - gpui::serde_json::Value::Null - } - - fn text_for_range(&self, _: Range, _: &gpui::AppContext) -> Option { - None - } - - fn selected_text_range(&self, _: &gpui::AppContext) -> Option> { - None - } - - fn marked_text_range(&self, _: &gpui::AppContext) -> Option> { - None - } - - fn unmark_text(&mut self, _: &mut ViewContext) {} - - fn replace_text_in_range( - &mut self, - _: Option>, - _: &str, - _: &mut ViewContext, - ) { - } - - fn replace_and_mark_text_in_range( - &mut self, - _: Option>, - _: &str, - _: Option>, - _: &mut ViewContext, - ) { - } } impl StatusItemView for FeedbackButton { diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index ed8fb1bb12..e463310b98 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -25,7 +25,6 @@ pub struct Theme { pub command_palette: CommandPalette, pub picker: Picker, pub editor: Editor, - pub feedback: Feedback, pub search: Search, pub project_diagnostics: ProjectDiagnostics, pub breadcrumbs: ContainedText, @@ -120,20 +119,6 @@ pub struct ContactList { pub calling_indicator: ContainedText, } -#[derive(Deserialize, Default)] -pub struct Feedback { - // pub feedback_popover: FeedbackPopover, - 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 { #[serde(flatten)] diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 863a036e8e..2d0222ef3a 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -95,11 +95,6 @@ pub struct DeployNewMenu { position: Vector2F, } -#[derive(Clone, PartialEq)] -pub struct DeployFeedbackModal { - position: Vector2F, -} - impl_actions!(pane, [GoBack, GoForward, ActivateItem]); impl_internal_actions!( pane, @@ -108,8 +103,7 @@ impl_internal_actions!( DeploySplitMenu, DeployNewMenu, DeployDockMenu, - MoveItem, - DeployFeedbackModal + MoveItem ] ); diff --git a/styles/src/styleTree/app.ts b/styles/src/styleTree/app.ts index a51426b6f6..267d830506 100644 --- a/styles/src/styleTree/app.ts +++ b/styles/src/styleTree/app.ts @@ -19,7 +19,6 @@ 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 { @@ -38,7 +37,6 @@ 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 deleted file mode 100644 index 0521949871..0000000000 --- a/styles/src/styleTree/feedback.ts +++ /dev/null @@ -1,35 +0,0 @@ -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 - } - } -} From 2b3d09f70af6e7b1161276ea77d32f1e8fd3b9c0 Mon Sep 17 00:00:00 2001 From: Joseph Lyons Date: Mon, 23 Jan 2023 18:34:10 -0500 Subject: [PATCH 24/24] Fix CI missing license check --- crates/feedback/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/feedback/Cargo.toml b/crates/feedback/Cargo.toml index ee6ec2f6ed..b224f91a2f 100644 --- a/crates/feedback/Cargo.toml +++ b/crates/feedback/Cargo.toml @@ -2,6 +2,7 @@ name = "feedback" version = "0.1.0" edition = "2021" +publish = false [lib] path = "src/feedback.rs"