Implement feedback actions

Joseph T. Lyons created

CopySystemSpecsIntoClipboard
RequestFeature
FileBugReport

Change summary

crates/feedback2/src/deploy_feedback_button.rs |   8 
crates/feedback2/src/feedback2.rs              | 105 +++++++-------
crates/feedback2/src/feedback_editor.rs        |  20 +-
crates/feedback2/src/feedback_modal.rs         |   9 
crates/feedback2/src/system_specs.rs           | 139 +++++++++----------
crates/gpui2/src/platform.rs                   |   2 
crates/workspace2/src/workspace2.rs            |   2 
crates/zed2/src/main.rs                        |   2 
8 files changed, 140 insertions(+), 147 deletions(-)

Detailed changes

crates/feedback2/src/deploy_feedback_button.rs 🔗

@@ -1,18 +1,18 @@
-use gpui::{Action, AnyElement, Render, ViewContext, WeakView};
+use gpui::{AnyElement, Render, ViewContext, WeakView};
 use ui::{prelude::*, ButtonCommon, Icon, IconButton, Tooltip};
 use workspace::{StatusItemView, Workspace};
 
-use crate::{feedback_editor::GiveFeedback, feedback_modal::FeedbackModal};
+use crate::feedback_modal::FeedbackModal;
 
 pub struct DeployFeedbackButton {
-    active: bool,
+    _active: bool,
     workspace: WeakView<Workspace>,
 }
 
 impl DeployFeedbackButton {
     pub fn new(workspace: &Workspace) -> Self {
         DeployFeedbackButton {
-            active: false,
+            _active: false,
             workspace: workspace.weak_handle(),
         }
     }

crates/feedback2/src/feedback2.rs 🔗

@@ -1,4 +1,7 @@
-use gpui::AppContext;
+use gpui::{actions, AppContext, ClipboardItem, PromptLevel};
+use system_specs::SystemSpecs;
+// use system_specs::SystemSpecs;
+use workspace::Workspace;
 
 pub mod deploy_feedback_button;
 pub mod feedback_editor;
@@ -8,60 +11,52 @@ pub mod submit_feedback_button;
 
 mod system_specs;
 
+actions!(
+    CopySystemSpecsIntoClipboard,
+    FileBugReport,
+    RequestFeature,
+    OpenZedCommunityRepo
+);
+
 pub fn init(cx: &mut AppContext) {
-    cx.observe_new_views(feedback_modal::FeedbackModal::register)
-        .detach();
+    // feedback_editor::init(cx);
+
+    cx.observe_new_views(|workspace: &mut Workspace, _cx| {
+        workspace
+            .register_action(|_, _: &CopySystemSpecsIntoClipboard, cx| {
+                    let specs = SystemSpecs::new(&cx).to_string();
+
+                    let prompt = cx.prompt(
+                        PromptLevel::Info,
+                        &format!("Copied into clipboard:\n\n{specs}"),
+                        &["OK"],
+                    );
+                    cx.spawn(|_, _cx| async move {
+                        prompt.await.ok();
+                    })
+                    .detach();
+                    let item = ClipboardItem::new(specs.clone());
+                    cx.write_to_clipboard(item);
+                })
+            .register_action(|_, _: &RequestFeature, cx| {
+                let url = "https://github.com/zed-industries/community/issues/new?assignees=&labels=enhancement%2Ctriage&template=0_feature_request.yml";
+                cx.open_url(url);
+            })
+            .register_action(move |_, _: &FileBugReport, cx| {
+                let url = format!(
+                    "https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml&environment={}",
+                    urlencoding::encode(&SystemSpecs::new(&cx).to_string())
+                );
+                cx.open_url(&url);
+            });
+    })
+    .detach();
+
+    // TODO
+    // cx.add_global_action(open_zed_community_repo);
 }
 
-// actions!(
-//     zed,
-//     [
-//         CopySystemSpecsIntoClipboard,
-//         FileBugReport,
-//         RequestFeature,
-//         OpenZedCommunityRepo
-//     ]
-// );
-
-// pub fn init(cx: &mut AppContext) {
-//     feedback_editor::init(cx);
-
-//     cx.add_action(
-//         move |_: &mut Workspace,
-//               _: &CopySystemSpecsIntoClipboard,
-//               cx: &mut ViewContext<Workspace>| {
-//             let specs = SystemSpecs::new(&cx).to_string();
-//             cx.prompt(
-//                 PromptLevel::Info,
-//                 &format!("Copied into clipboard:\n\n{specs}"),
-//                 &["OK"],
-//             );
-//             let item = ClipboardItem::new(specs.clone());
-//             cx.write_to_clipboard(item);
-//         },
-//     );
-
-//     cx.add_action(
-//         |_: &mut Workspace, _: &RequestFeature, cx: &mut ViewContext<Workspace>| {
-//             let url = "https://github.com/zed-industries/community/issues/new?assignees=&labels=enhancement%2Ctriage&template=0_feature_request.yml";
-//             cx.platform().open_url(url);
-//         },
-//     );
-
-//     cx.add_action(
-//         move |_: &mut Workspace, _: &FileBugReport, cx: &mut ViewContext<Workspace>| {
-//             let url = format!(
-//                 "https://github.com/zed-industries/community/issues/new?assignees=&labels=defect%2Ctriage&template=2_bug_report.yml&environment={}",
-//                 urlencoding::encode(&SystemSpecs::new(&cx).to_string())
-//             );
-//             cx.platform().open_url(&url);
-//         },
-//     );
-
-//     cx.add_global_action(open_zed_community_repo);
-// }
-
-// pub fn open_zed_community_repo(_: &OpenZedCommunityRepo, cx: &mut AppContext) {
-//     let url = "https://github.com/zed-industries/community";
-//     cx.platform().open_url(&url);
-// }
+pub fn open_zed_community_repo(_: &OpenZedCommunityRepo, cx: &mut AppContext) {
+    let url = "https://github.com/zed-industries/community";
+    cx.open_url(&url);
+}

crates/feedback2/src/feedback_editor.rs 🔗

@@ -33,16 +33,16 @@ actions!(GiveFeedback, SubmitFeedback);
 //     });
 // }
 
-#[derive(Serialize)]
-struct FeedbackRequestBody<'a> {
-    feedback_text: &'a str,
-    email: Option<String>,
-    metrics_id: Option<Arc<str>>,
-    installation_id: Option<Arc<str>>,
-    system_specs: SystemSpecs,
-    is_staff: bool,
-    token: &'a str,
-}
+// #[derive(Serialize)]
+// struct FeedbackRequestBody<'a> {
+//     feedback_text: &'a str,
+//     email: Option<String>,
+//     metrics_id: Option<Arc<str>>,
+//     installation_id: Option<Arc<str>>,
+//     system_specs: SystemSpecs,
+//     is_staff: bool,
+//     token: &'a str,
+// }
 
 // #[derive(Clone)]
 // pub(crate) struct FeedbackEditor {

crates/feedback2/src/feedback_modal.rs 🔗

@@ -1,4 +1,3 @@
-use editor::Editor;
 use gpui::{
     div, rems, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Render,
     ViewContext,
@@ -9,7 +8,7 @@ use workspace::Workspace;
 use crate::feedback_editor::GiveFeedback;
 
 pub struct FeedbackModal {
-    editor: View<Editor>,
+    // editor: View<Editor>,
     tmp_focus_handle: FocusHandle, // TODO: should be editor.focus_handle(cx)
 }
 
@@ -29,8 +28,8 @@ impl FeedbackModal {
     }
 
     pub fn new(cx: &mut ViewContext<Self>) -> 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);
+        // let line_editor = cx.build_view(|cx| Editor::single_line(cx));
+        // let line_editor_change = cx.subscribe(&line_editor, Self::on_line_editor_event);
 
         // let editor = active_editor.read(cx);
         // let cursor = editor.selections.last::<Point>(cx).head();
@@ -44,7 +43,7 @@ impl FeedbackModal {
         //     cursor.column + 1,
         // );
         Self {
-            editor: line_editor,
+            // editor: line_editor,
             tmp_focus_handle: cx.focus_handle(),
         }
     }

crates/feedback2/src/system_specs.rs 🔗

@@ -1,76 +1,75 @@
-// // use client::ZED_APP_VERSION;
-// use gpui::AppContext;
-// use human_bytes::human_bytes;
-// use serde::Serialize;
-// use std::{env, fmt::Display};
-// use sysinfo::{System, SystemExt};
-// use util::channel::ReleaseChannel;
+use client::ZED_APP_VERSION;
+use gpui::AppContext;
+use human_bytes::human_bytes;
+use serde::Serialize;
+use std::{env, fmt::Display};
+use sysinfo::{System, SystemExt};
+use util::channel::ReleaseChannel;
 
-// #[derive(Clone, Debug, Serialize)]
-// pub struct SystemSpecs {
-//     // todo!()
-//     // #[serde(serialize_with = "serialize_app_version")]
-//     // app_version: Option<AppVersion>,
-//     release_channel: &'static str,
-//     os_name: &'static str,
-//     os_version: Option<String>,
-//     memory: u64,
-//     architecture: &'static str,
-// }
+#[derive(Clone, Debug, Serialize)]
+pub struct SystemSpecs {
+    app_version: Option<String>,
+    release_channel: &'static str,
+    os_name: &'static str,
+    os_version: Option<String>,
+    memory: u64,
+    architecture: &'static str,
+}
 
-// impl SystemSpecs {
-//     pub fn new(cx: &AppContext) -> Self {
-//         let platform = cx.platform();
-//         // let app_version = ZED_APP_VERSION.or_else(|| platform.app_version().ok());
-//         let release_channel = cx.global::<ReleaseChannel>().dev_name();
-//         let os_name = platform.os_name();
-//         let system = System::new_all();
-//         let memory = system.total_memory();
-//         let architecture = env::consts::ARCH;
-//         let os_version = platform
-//             .os_version()
-//             .ok()
-//             .map(|os_version| os_version.to_string());
+impl SystemSpecs {
+    pub fn new(cx: &AppContext) -> Self {
+        let app_version = ZED_APP_VERSION
+            .or_else(|| cx.app_metadata().app_version)
+            .map(|v| v.to_string());
+        let release_channel = cx.global::<ReleaseChannel>().dev_name();
+        let os_name = cx.app_metadata().os_name;
+        let system = System::new_all();
+        let memory = system.total_memory();
+        let architecture = env::consts::ARCH;
+        let os_version = cx
+            .app_metadata()
+            .os_version
+            .map(|os_version| os_version.to_string());
 
-//         SystemSpecs {
-//             //   app_version,
-//             release_channel,
-//             os_name,
-//             os_version,
-//             memory,
-//             architecture,
-//         }
-//     }
-// }
+        SystemSpecs {
+            app_version,
+            release_channel,
+            os_name,
+            os_version,
+            memory,
+            architecture,
+        }
+    }
+}
 
-// impl Display for SystemSpecs {
-//     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-//         let os_information = match &self.os_version {
-//             Some(os_version) => format!("OS: {} {}", self.os_name, os_version),
-//             None => format!("OS: {}", self.os_name),
-//         };
-//         let app_version_information = self
-//             .app_version
-//             .as_ref()
-//             .map(|app_version| format!("Zed: v{} ({})", app_version, self.release_channel));
-//         let system_specs = [
-//             app_version_information,
-//             Some(os_information),
-//             Some(format!("Memory: {}", human_bytes(self.memory as f64))),
-//             Some(format!("Architecture: {}", self.architecture)),
-//         ]
-//         .into_iter()
-//         .flatten()
-//         .collect::<Vec<String>>()
-//         .join("\n");
+impl Display for SystemSpecs {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let os_information = match &self.os_version {
+            Some(os_version) => format!("OS: {} {}", self.os_name, os_version),
+            None => format!("OS: {}", self.os_name),
+        };
+        let app_version_information = self
+            .app_version
+            .as_ref()
+            .map(|app_version| format!("Zed: v{} ({})", app_version, self.release_channel));
+        let system_specs = [
+            app_version_information,
+            Some(os_information),
+            Some(format!("Memory: {}", human_bytes(self.memory as f64))),
+            Some(format!("Architecture: {}", self.architecture)),
+        ]
+        .into_iter()
+        .flatten()
+        .collect::<Vec<String>>()
+        .join("\n");
 
-//         write!(f, "{system_specs}")
-//     }
-// }
+        write!(f, "{system_specs}")
+    }
+}
 
-// // fn serialize_app_version<S>(version: &Option<AppVersion>, serializer: S) -> Result<S::Ok, S::Error>
-// // where
-// //     S: serde::Serializer,
-// // {
-// //     version.map(|v| v.to_string()).serialize(serializer)
-// // }
+// fn serialize_app_version<S>(version: ZED_APP_VERSION, serializer: S) -> Result<S::Ok, S::Error>
+// where
+//     S: serde::Serializer,
+// {
+//     version.map(|v| v.to_string()).serialize(serializer)
+// }

crates/gpui2/src/platform.rs 🔗

@@ -501,7 +501,7 @@ impl Default for CursorStyle {
     }
 }
 
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize)]
 pub struct SemanticVersion {
     major: usize,
     minor: usize,

crates/workspace2/src/workspace2.rs 🔗

@@ -67,7 +67,7 @@ use std::{
 use theme::{ActiveTheme, ThemeSettings};
 pub use toolbar::{ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
 pub use ui;
-use ui::{h_stack, v_stack, StyledExt};
+// use ui::{h_stack, v_stack, StyledExt};
 use util::ResultExt;
 use uuid::Uuid;
 pub use workspace_settings::{AutosaveSetting, WorkspaceSettings};

crates/zed2/src/main.rs 🔗

@@ -221,7 +221,7 @@ fn main() {
         // language_tools::init(cx);
         call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
         collab_ui::init(&app_state, cx);
-        // feedback::init(cx);
+        feedback::init(cx);
         welcome::init(cx);
 
         // cx.set_menus(menus::menus());