From f4c7b133974b4b219ddfd8fb850c1ef05402b64d Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Wed, 6 Dec 2023 16:15:44 -0500 Subject: [PATCH] temp --- .../feedback2/src/deploy_feedback_button.rs | 42 ++- crates/feedback2/src/feedback2.rs | 6 +- crates/feedback2/src/feedback_modal.rs | 243 +++++++++++------- crates/zed2/src/zed2.rs | 7 +- 4 files changed, 177 insertions(+), 121 deletions(-) diff --git a/crates/feedback2/src/deploy_feedback_button.rs b/crates/feedback2/src/deploy_feedback_button.rs index f0f06f5bd0..c4ab36005a 100644 --- a/crates/feedback2/src/deploy_feedback_button.rs +++ b/crates/feedback2/src/deploy_feedback_button.rs @@ -2,7 +2,7 @@ use gpui::{AnyElement, Render, ViewContext, WeakView}; use ui::{prelude::*, ButtonCommon, Icon, IconButton, Tooltip}; use workspace::{item::ItemHandle, StatusItemView, Workspace}; -use crate::feedback_editor::FeedbackEditor; +use crate::{feedback_editor::GiveFeedback, feedback_modal::FeedbackModal}; pub struct DeployFeedbackButton { active: bool, @@ -22,34 +22,32 @@ impl Render for DeployFeedbackButton { type Element = AnyElement; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - let active = self.active; - + let is_open = self + .workspace + .upgrade() + .and_then(|workspace| { + workspace.update(cx, |workspace, cx| { + workspace.active_modal::(cx) + }) + }) + .is_some(); IconButton::new("give-feedback", Icon::Envelope) .style(ui::ButtonStyle::Subtle) + .selected(is_open) .tooltip(|cx| Tooltip::text("Give Feedback", cx)) - .on_click(cx.listener(move |this, _, cx| { - let Some(workspace) = this.workspace.upgrade() else { - return; - }; - - if !active { - workspace.update(cx, |workspace, cx| FeedbackEditor::deploy(workspace, cx)) - } - })) + .on_click(|_, cx| { + cx.dispatch_action(Box::new(GiveFeedback)); + }) .into_any_element() } } impl StatusItemView for DeployFeedbackButton { - fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext) { - if let Some(item) = item { - if let Some(_) = item.downcast::() { - self.active = true; - cx.notify(); - return; - } - } - self.active = false; - cx.notify(); + fn set_active_pane_item( + &mut self, + _item: Option<&dyn ItemHandle>, + _cx: &mut ViewContext, + ) { + // no-op } } diff --git a/crates/feedback2/src/feedback2.rs b/crates/feedback2/src/feedback2.rs index 30caa1aa0e..19c26e4f1c 100644 --- a/crates/feedback2/src/feedback2.rs +++ b/crates/feedback2/src/feedback2.rs @@ -5,7 +5,7 @@ use workspace::Workspace; pub mod deploy_feedback_button; pub mod feedback_editor; pub mod feedback_info_text; -// pub mod feedback_modal; +pub mod feedback_modal; pub mod submit_feedback_button; mod system_specs; @@ -18,7 +18,9 @@ actions!( ); pub fn init(cx: &mut AppContext) { - feedback_editor::init(cx); + // TODO - a way to combine these two into one? + cx.observe_new_views(feedback_modal::FeedbackModal::register) + .detach(); cx.observe_new_views(|workspace: &mut Workspace, _cx| { workspace diff --git a/crates/feedback2/src/feedback_modal.rs b/crates/feedback2/src/feedback_modal.rs index 1676f350f0..3694a25710 100644 --- a/crates/feedback2/src/feedback_modal.rs +++ b/crates/feedback2/src/feedback_modal.rs @@ -1,20 +1,34 @@ -use gpui::{ - div, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Render, - ViewContext, -}; -use ui::{prelude::*, Button, ButtonStyle, Label, Tooltip}; -use workspace::Workspace; +use std::ops::RangeInclusive; -use crate::feedback_editor::GiveFeedback; +use editor::{Editor, EditorEvent}; +use gpui::{ + div, red, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Model, + Render, View, ViewContext, +}; +use language::Buffer; +use project::Project; +use ui::{prelude::*, Button, ButtonStyle, Label, Tooltip}; +use util::ResultExt; +use workspace::{item::Item, Workspace}; + +use crate::{feedback_editor::GiveFeedback, system_specs::SystemSpecs, OpenZedCommunityRepo}; + +const FEEDBACK_CHAR_LIMIT: RangeInclusive = 10..=5000; +const FEEDBACK_SUBMISSION_ERROR_TEXT: &str = + "Feedback failed to submit, see error log for details."; pub struct FeedbackModal { - // editor: View, - tmp_focus_handle: FocusHandle, // TODO: should be editor.focus_handle(cx) + system_specs: SystemSpecs, + feedback_editor: View, + email_address_editor: View, + project: Model, + pub allow_submission: bool, + character_count: usize, } impl FocusableView for FeedbackModal { - fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { - self.tmp_focus_handle.clone() + fn focus_handle(&self, cx: &AppContext) -> FocusHandle { + self.feedback_editor.focus_handle(cx) } } impl EventEmitter for FeedbackModal {} @@ -23,28 +37,78 @@ impl FeedbackModal { pub fn register(workspace: &mut Workspace, cx: &mut ViewContext) { let _handle = cx.view().downgrade(); workspace.register_action(move |workspace, _: &GiveFeedback, cx| { - workspace.toggle_modal(cx, move |cx| FeedbackModal::new(cx)); + let markdown = workspace + .app_state() + .languages + .language_for_name("Markdown"); + + let project = workspace.project().clone(); + + cx.spawn(|workspace, mut cx| async move { + let markdown = markdown.await.log_err(); + let buffer = project + .update(&mut cx, |project, cx| { + project.create_buffer("", markdown, cx) + })? + .expect("creating buffers on a local workspace always succeeds"); + + workspace.update(&mut cx, |workspace, cx| { + let system_specs = SystemSpecs::new(cx); + + workspace.toggle_modal(cx, move |cx| { + FeedbackModal::new(system_specs, project, buffer, cx) + }); + })?; + + anyhow::Ok(()) + }) + .detach_and_log_err(cx); }); } - pub fn new(cx: &mut ViewContext) -> Self { - // let line_editor = cx.build_view(|cx| Editor::single_line(cx)); - // let line_editor_change = cx.subscribe(&line_editor, Self::on_line_editor_event); + pub fn new( + system_specs: SystemSpecs, + project: Model, + buffer: Model, + cx: &mut ViewContext, + ) -> Self { + let email_address_editor = cx.build_view(|cx| { + let mut editor = Editor::single_line(cx); + editor.set_placeholder_text("Email address (optional)", cx); + editor + }); + let feedback_editor = cx.build_view(|cx| { + let mut editor = Editor::for_buffer(buffer, Some(project.clone()), cx); + editor.set_vertical_scroll_margin(5, cx); + editor + }); - // let editor = active_editor.read(cx); - // let cursor = editor.selections.last::(cx).head(); - // let last_line = editor.buffer().read(cx).snapshot(cx).max_point().row; - // let scroll_position = active_editor.update(cx, |editor, cx| editor.scroll_position(cx)); + cx.subscribe( + &feedback_editor, + |this, editor, event: &EditorEvent, cx| match event { + EditorEvent::Edited => { + this.character_count = editor + .read(cx) + .buffer() + .read(cx) + .as_singleton() + .expect("Feedback editor is never a multi-buffer") + .read(cx) + .len(); + cx.notify(); + } + _ => {} + }, + ) + .detach(); - // let current_text = format!( - // "line {} of {} (column {})", - // cursor.row + 1, - // last_line + 1, - // cursor.column + 1, - // ); Self { - // editor: line_editor, - tmp_focus_handle: cx.focus_handle(), + system_specs: system_specs.clone(), + feedback_editor, + email_address_editor, + project, + allow_submission: true, + character_count: 0, } } @@ -127,7 +191,13 @@ impl Render for FeedbackModal { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + let character_count_error = (self.character_count < *FEEDBACK_CHAR_LIMIT.start()) + || (self.character_count > *FEEDBACK_CHAR_LIMIT.end()); + let dismiss = cx.listener(|_, _, cx| cx.emit(DismissEvent)); + // let open_community_issues = + // cx.listener(|_, _, cx| cx.dispatch_action(Box::new(OpenZedCommunityRepo))); + // let open_community_discussions = cx.listener(|_, _, cx| cx.emit(DismissEvent)); v_stack() .elevation_3(cx) @@ -136,81 +206,72 @@ impl Render for FeedbackModal { .h(rems(40.)) .p_2() .gap_2() - .child(h_stack().child(Label::new("Give Feedback").color(Color::Default))) + .child( + v_stack().child( + div() + .size_full() + .border() + .border_color(red()) + .child(Label::new("Give Feedback").color(Color::Default)) + .child(Label::new("This editor supports markdown").color(Color::Muted)), + ), + ) .child( div() .flex_1() .bg(cx.theme().colors().editor_background) .border() .border_color(cx.theme().colors().border) - .child("editor"), + .child(self.feedback_editor.clone()), + ) + .child( + div().border().border_color(red()).child( + Label::new(format!( + "{} / {} Characters", + self.character_count, + FEEDBACK_CHAR_LIMIT.end() + )) + .color(Color::Default), + ), + ) + .child( div() + .bg(cx.theme().colors().editor_background) + .border() + .border_color(cx.theme().colors().border) + .child(self.email_address_editor.clone()) ) .child( h_stack() - .justify_end() + .justify_between() .gap_1() - .child( - Button::new("cancel_feedback", "Cancel") - .style(ButtonStyle::Subtle) - .color(Color::Muted) - .on_click(dismiss), + .child(Button::new("community_repo", "Community Repo") + .style(ButtonStyle::Filled) + .color(Color::Muted) + // .on_click(cx.dispatch_action(Box::new(OpenZedCommunityRepo))) ) - .child( - Button::new("send_feedback", "Send Feedback") - .color(Color::Accent) - .style(ButtonStyle::Filled) - .tooltip(|cx| { - Tooltip::with_meta( - "Submit feedback to the Zed team.", - None, - "Provide an email address if you want us to be able to reply.", - cx, - ) - }), - ), + .child(h_stack().justify_between().gap_1() + .child( + Button::new("cancel_feedback", "Cancel") + .style(ButtonStyle::Subtle) + .color(Color::Muted) + .on_click(dismiss), + ) + .child( + Button::new("send_feedback", "Send Feedback") + .color(Color::Accent) + .style(ButtonStyle::Filled) + .tooltip(|cx| { + Tooltip::with_meta( + "Submit feedback to the Zed team.", + None, + "Provide an email address if you want us to be able to reply.", + cx, + ) + }) + .when(character_count_error, |this| this.disabled(true)), + ), + ) + ) - - // Header - // - has some info, maybe some links - // Body - // - Markdown Editor - // - Email address - // Footer - // - CTA buttons (Send, Cancel) - - // div() - // .elevation_2(cx) - // .key_context( - // "FeedbackModal - // ", - // ) - // .on_action(cx.listener(Self::cancel)) - // .on_action(cx.listener(Self::confirm)) - // .w_96() - // .child( - // v_stack() - // .px_1() - // .pt_0p5() - // .gap_px() - // .child( - // v_stack() - // .py_0p5() - // .px_1() - // .child(div().px_1().py_0p5().child(self.line_editor.clone())), - // ) - // .child( - // div() - // .h_px() - // .w_full() - // .bg(cx.theme().colors().element_background), - // ) - // .child( - // h_stack() - // .justify_between() - // .px_2() - // .py_1() - // .child(Label::new(self.current_text.clone()).color(Color::Muted)), - // ), - // ) } } diff --git a/crates/zed2/src/zed2.rs b/crates/zed2/src/zed2.rs index c4d5831589..f3f8d3b9f4 100644 --- a/crates/zed2/src/zed2.rs +++ b/crates/zed2/src/zed2.rs @@ -10,9 +10,7 @@ pub use assets::*; use breadcrumbs::Breadcrumbs; use collections::VecDeque; use editor::{Editor, MultiBuffer}; -use feedback::{ - feedback_info_text::FeedbackInfoText, submit_feedback_button::SubmitFeedbackButton, -}; +use feedback::submit_feedback_button::SubmitFeedbackButton; use gpui::{ actions, point, px, AppContext, Context, FocusableView, PromptLevel, TitlebarOptions, ViewContext, VisualContext, WindowBounds, WindowKind, WindowOptions, @@ -115,10 +113,7 @@ pub fn initialize_workspace(app_state: Arc, cx: &mut AppContext) { // toolbar.add_item(project_search_bar, cx); let submit_feedback_button = cx.build_view(|_| SubmitFeedbackButton::new()); - // todo!(tool bar does not display or fire correctly right now, this is only stubbed in) toolbar.add_item(submit_feedback_button, cx); - let feedback_info_text = cx.build_view(|_| FeedbackInfoText::new()); - toolbar.add_item(feedback_info_text, cx); // let lsp_log_item = // cx.add_view(|_| language_tools::LspLogToolbarItemView::new()); // toolbar.add_item(lsp_log_item, cx);