Get `feedback2` compiling

Nate Butler , Joseph T. Lyons , and Conrad Irwin created

Co-Authored-By: Joseph T. Lyons <19867440+JosephTLyons@users.noreply.github.com>
Co-Authored-By: Conrad Irwin <conrad.irwin@gmail.com>

Change summary

crates/feedback2/src/deploy_feedback_button.rs | 149 +++++++-----------
crates/feedback2/src/feedback2.rs              |  11 
crates/feedback2/src/feedback_editor.rs        |  31 +--
crates/feedback2/src/feedback_modal.rs         | 164 ++++++++++++++++++++
crates/feedback2/src/submit_feedback_button.rs | 114 +++++++------
crates/feedback2/src/system_specs.rs           |  27 +-
crates/workspace2/src/workspace2.rs            |  20 --
crates/zed2/src/zed2.rs                        |  11 
8 files changed, 317 insertions(+), 210 deletions(-)

Detailed changes

crates/feedback2/src/deploy_feedback_button.rs 🔗

@@ -1,91 +1,58 @@
-// use gpui::{
-//     elements::*,
-//     platform::{CursorStyle, MouseButton},
-//     Entity, View, ViewContext, WeakViewHandle,
-// };
-// use workspace::{item::ItemHandle, StatusItemView, Workspace};
-
-// use crate::feedback_editor::{FeedbackEditor, GiveFeedback};
-
-// pub struct DeployFeedbackButton {
-//     active: bool,
-//     workspace: WeakViewHandle<Workspace>,
-// }
-
-// impl Entity for DeployFeedbackButton {
-//     type Event = ();
-// }
-
-// impl DeployFeedbackButton {
-//     pub fn new(workspace: &Workspace) -> Self {
-//         DeployFeedbackButton {
-//             active: false,
-//             workspace: workspace.weak_handle(),
-//         }
-//     }
-// }
-
-// impl View for DeployFeedbackButton {
-//     fn ui_name() -> &'static str {
-//         "DeployFeedbackButton"
-//     }
-
-//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
-//         let active = self.active;
-//         let theme = theme::current(cx).clone();
-//         Stack::new()
-//             .with_child(
-//                 MouseEventHandler::new::<Self, _>(0, cx, |state, _| {
-//                     let style = &theme
-//                         .workspace
-//                         .status_bar
-//                         .panel_buttons
-//                         .button
-//                         .in_state(active)
-//                         .style_for(state);
-
-//                     Svg::new("icons/feedback.svg")
-//                         .with_color(style.icon_color)
-//                         .constrained()
-//                         .with_width(style.icon_size)
-//                         .aligned()
-//                         .constrained()
-//                         .with_width(style.icon_size)
-//                         .with_height(style.icon_size)
-//                         .contained()
-//                         .with_style(style.container)
-//                 })
-//                 .with_cursor_style(CursorStyle::PointingHand)
-//                 .on_click(MouseButton::Left, move |_, this, cx| {
-//                     if !active {
-//                         if let Some(workspace) = this.workspace.upgrade(cx) {
-//                             workspace
-//                                 .update(cx, |workspace, cx| FeedbackEditor::deploy(workspace, cx))
-//                         }
-//                     }
-//                 })
-//                 .with_tooltip::<Self>(
-//                     0,
-//                     "Send Feedback",
-//                     Some(Box::new(GiveFeedback)),
-//                     theme.tooltip.clone(),
-//                     cx,
-//                 ),
-//             )
-//             .into_any()
-//     }
-// }
-
-// impl StatusItemView for DeployFeedbackButton {
-//     fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext<Self>) {
-//         if let Some(item) = item {
-//             if let Some(_) = item.downcast::<FeedbackEditor>() {
-//                 self.active = true;
-//                 cx.notify();
-//                 return;
-//             }
-//         }
-//         self.active = false;
-//         cx.notify();
-//     }
-// }
+use gpui::{Action, AnyElement, Render, ViewContext, WeakView};
+use ui::{prelude::*, ButtonCommon, Icon, IconButton, Tooltip};
+use workspace::{StatusItemView, Workspace};
+
+use crate::{feedback_editor::GiveFeedback, feedback_modal::FeedbackModal};
+
+pub struct DeployFeedbackButton {
+    active: bool,
+    workspace: WeakView<Workspace>,
+}
+
+impl DeployFeedbackButton {
+    pub fn new(workspace: &Workspace) -> Self {
+        DeployFeedbackButton {
+            active: false,
+            workspace: workspace.weak_handle(),
+        }
+    }
+}
+
+impl Render for DeployFeedbackButton {
+    type Element = AnyElement;
+
+    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+        let is_open = self
+            .workspace
+            .upgrade()
+            .and_then(|workspace| {
+                workspace.update(cx, |workspace, cx| {
+                    workspace.active_modal::<FeedbackModal>(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(|this, _, cx| {
+                let Some(workspace) = this.workspace.upgrade() else {
+                    return;
+                };
+                workspace.update(cx, |workspace, cx| {
+                    workspace.toggle_modal(cx, |cx| FeedbackModal::new(cx))
+                })
+            }))
+            .into_any_element()
+    }
+}
+impl StatusItemView for DeployFeedbackButton {
+    fn set_active_pane_item(
+        &mut self,
+        _active_pane_item: Option<&dyn workspace::item::ItemHandle>,
+        _cx: &mut ViewContext<Self>,
+    ) {
+        // no-op
+    }
+}

crates/feedback2/src/feedback2.rs 🔗

@@ -1,12 +1,17 @@
+use gpui::AppContext;
+
 pub mod deploy_feedback_button;
 pub mod feedback_editor;
 pub mod feedback_info_text;
+pub mod feedback_modal;
 pub mod submit_feedback_button;
 
 mod system_specs;
-use gpui::{actions, platform::PromptLevel, AppContext, ClipboardItem, ViewContext};
-use system_specs::SystemSpecs;
-use workspace::Workspace;
+
+pub fn init(cx: &mut AppContext) {
+    cx.observe_new_views(feedback_modal::FeedbackModal::register)
+        .detach();
+}
 
 // actions!(
 //     zed,

crates/feedback2/src/feedback_editor.rs 🔗

@@ -3,38 +3,27 @@
 // use client::{Client, ZED_SECRET_CLIENT_TOKEN, ZED_SERVER_URL};
 // use editor::{Anchor, Editor};
 // use futures::AsyncReadExt;
-// use gpui::{
-//     actions,
-//     elements::{ChildView, Flex, Label, ParentElement, Svg},
-//     platform::PromptLevel,
-//     serde_json, AnyElement, AnyViewHandle, AppContext, Element, Entity, ModelHandle, Task, View,
-//     ViewContext, ViewHandle,
-// };
+// use gpui::{actions, serde_json, AppContext, Model, PromptLevel, Task, View, ViewContext};
 // use isahc::Request;
 // use language::Buffer;
 // use postage::prelude::Stream;
 // use project::{search::SearchQuery, Project};
 // use regex::Regex;
 // use serde::Serialize;
-// use smallvec::SmallVec;
 // use std::{
-//     any::TypeId,
-//     borrow::Cow,
 //     ops::{Range, RangeInclusive},
 //     sync::Arc,
 // };
 // use util::ResultExt;
-// use workspace::{
-//     item::{Item, ItemEvent, ItemHandle},
-//     searchable::{SearchableItem, SearchableItemHandle},
-//     Workspace,
-// };
+// use workspace::{searchable::SearchableItem, Workspace};
 
 // const FEEDBACK_CHAR_LIMIT: RangeInclusive<usize> = 10..=5000;
 // const FEEDBACK_SUBMISSION_ERROR_TEXT: &str =
 //     "Feedback failed to submit, see error log for details.";
 
-// actions!(feedback, [GiveFeedback, SubmitFeedback]);
+use gpui::actions;
+
+actions!(GiveFeedback, SubmitFeedback);
 
 // pub fn init(cx: &mut AppContext) {
 //     cx.add_action({
@@ -58,16 +47,16 @@
 // #[derive(Clone)]
 // pub(crate) struct FeedbackEditor {
 //     system_specs: SystemSpecs,
-//     editor: ViewHandle<Editor>,
-//     project: ModelHandle<Project>,
+//     editor: View<Editor>,
+//     project: Model<Project>,
 //     pub allow_submission: bool,
 // }
 
 // impl FeedbackEditor {
 //     fn new(
 //         system_specs: SystemSpecs,
-//         project: ModelHandle<Project>,
-//         buffer: ModelHandle<Buffer>,
+//         project: Model<Project>,
+//         buffer: Model<Buffer>,
 //         cx: &mut ViewContext<Self>,
 //     ) -> Self {
 //         let editor = cx.add_view(|cx| {
@@ -135,7 +124,7 @@
 
 //                 match FeedbackEditor::submit_feedback(&feedback_text, client, specs).await {
 //                     Ok(_) => {
-//                         this.update(&mut cx, |_, cx| cx.emit(editor::Event::Closed))
+//                         this.update(&mut cx, |_, cx| cx.emit(editor::EditorEvent::Closed))
 //                             .log_err();
 //                     }
 

crates/feedback2/src/feedback_modal.rs 🔗

@@ -0,0 +1,164 @@
+use gpui::{
+    div, AppContext, DismissEvent, Div, EventEmitter, FocusHandle, FocusableView, Render,
+    ViewContext,
+};
+use ui::prelude::*;
+use workspace::Workspace;
+
+use crate::feedback_editor::GiveFeedback;
+
+pub struct FeedbackModal {
+    // editor: View<FeedbackEditor>,
+    tmp_focus_handle: FocusHandle, // TODO: should be editor.focus_handle(cx)
+}
+
+impl FocusableView for FeedbackModal {
+    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
+        self.tmp_focus_handle.clone()
+    }
+}
+impl EventEmitter<DismissEvent> for FeedbackModal {}
+
+impl FeedbackModal {
+    pub fn register(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
+        let _handle = cx.view().downgrade();
+        workspace.register_action(move |workspace, _: &GiveFeedback, cx| {
+            workspace.toggle_modal(cx, move |cx| FeedbackModal::new(cx));
+        });
+    }
+
+    pub fn new(cx: &mut ViewContext<Self>) -> Self {
+        Self {
+            tmp_focus_handle: cx.focus_handle(),
+        }
+    }
+
+    // fn release(&mut self, cx: &mut WindowContext) {
+    //     let scroll_position = self.prev_scroll_position.take();
+    //     self.active_editor.update(cx, |editor, cx| {
+    //         editor.highlight_rows(None);
+    //         if let Some(scroll_position) = scroll_position {
+    //             editor.set_scroll_position(scroll_position, cx);
+    //         }
+    //         cx.notify();
+    //     })
+    // }
+
+    // fn on_feedback_editor_event(
+    //     &mut self,
+    //     _: View<Editor>,
+    //     event: &editor::EditorEvent,
+    //     cx: &mut ViewContext<Self>,
+    // ) {
+    //     match event {
+    //         // todo!() this isn't working...
+    //         editor::EditorEvent::Blurred => cx.emit(DismissEvent),
+    //         editor::EditorEvent::BufferEdited { .. } => self.highlight_current_line(cx),
+    //         _ => {}
+    //     }
+    // }
+
+    // fn highlight_current_line(&mut self, cx: &mut ViewContext<Self>) {
+    //     if let Some(point) = self.point_from_query(cx) {
+    //         self.active_editor.update(cx, |active_editor, cx| {
+    //             let snapshot = active_editor.snapshot(cx).display_snapshot;
+    //             let point = snapshot.buffer_snapshot.clip_point(point, Bias::Left);
+    //             let display_point = point.to_display_point(&snapshot);
+    //             let row = display_point.row();
+    //             active_editor.highlight_rows(Some(row..row + 1));
+    //             active_editor.request_autoscroll(Autoscroll::center(), cx);
+    //         });
+    //         cx.notify();
+    //     }
+    // }
+
+    // fn point_from_query(&self, cx: &ViewContext<Self>) -> Option<Point> {
+    //     let line_editor = self.line_editor.read(cx).text(cx);
+    //     let mut components = line_editor
+    //         .splitn(2, FILE_ROW_COLUMN_DELIMITER)
+    //         .map(str::trim)
+    //         .fuse();
+    //     let row = components.next().and_then(|row| row.parse::<u32>().ok())?;
+    //     let column = components.next().and_then(|col| col.parse::<u32>().ok());
+    //     Some(Point::new(
+    //         row.saturating_sub(1),
+    //         column.unwrap_or(0).saturating_sub(1),
+    //     ))
+    // }
+
+    // fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
+    //     cx.emit(DismissEvent);
+    // }
+
+    // fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext<Self>) {
+    //     if let Some(point) = self.point_from_query(cx) {
+    //         self.active_editor.update(cx, |editor, cx| {
+    //             let snapshot = editor.snapshot(cx).display_snapshot;
+    //             let point = snapshot.buffer_snapshot.clip_point(point, Bias::Left);
+    //             editor.change_selections(Some(Autoscroll::center()), cx, |s| {
+    //                 s.select_ranges([point..point])
+    //             });
+    //             editor.focus(cx);
+    //             cx.notify();
+    //         });
+    //         self.prev_scroll_position.take();
+    //     }
+
+    //     cx.emit(DismissEvent);
+    // }
+}
+
+impl Render for FeedbackModal {
+    type Element = Div;
+
+    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+        div().elevation_3(cx).w_1_2().h_2_3().child(
+            v_stack()
+                .w_full()
+                .child(h_stack().child("header"))
+                .child("editor"),
+            // 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)),
+        //             ),
+        //     )
+    }
+}

crates/feedback2/src/submit_feedback_button.rs 🔗

@@ -1,10 +1,7 @@
-// use crate::feedback_editor::{FeedbackEditor, SubmitFeedback};
+// use crate::{feedback_editor::SubmitFeedback, feedback_modal::FeedbackModal};
 // use anyhow::Result;
-// use gpui::{
-//     elements::{Label, MouseEventHandler},
-//     platform::{CursorStyle, MouseButton},
-//     AnyElement, AppContext, Element, Entity, Task, View, ViewContext, ViewHandle,
-// };
+// use gpui::{AppContext, Render, Task, View, ViewContext};
+// use ui::IconButton;
 // use workspace::{item::ItemHandle, ToolbarItemLocation, ToolbarItemView};
 
 // pub fn init(cx: &mut AppContext) {
@@ -12,7 +9,7 @@
 // }
 
 // pub struct SubmitFeedbackButton {
-//     pub(crate) active_item: Option<ViewHandle<FeedbackEditor>>,
+//     pub(crate) active_item: Option<View<FeedbackModal>>,
 // }
 
 // impl SubmitFeedbackButton {
@@ -35,59 +32,66 @@
 //     }
 // }
 
-// impl Entity for SubmitFeedbackButton {
-//     type Event = ();
-// }
+// impl Render for SubmitFeedbackbutton {
+//     type Element;
 
-// impl View for SubmitFeedbackButton {
-//     fn ui_name() -> &'static str {
-//         "SubmitFeedbackButton"
+//     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+//         todo!();
+//         // IconButton::new("give-feedback", Icon::Envelope)
+//         //     .style(ui::ButtonStyle::Subtle)
+//         //     .on_click(|_, cx| cx.dispatch_action(GiveFeedback))
 //     }
+// }
 
-//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
-//         let theme = theme::current(cx).clone();
-//         let allow_submission = self
-//             .active_item
-//             .as_ref()
-//             .map_or(true, |i| i.read(cx).allow_submission);
+// // impl View for SubmitFeedbackButton {
+// //     fn ui_name() -> &'static str {
+// //         "SubmitFeedbackButton"
+// //     }
 
-//         enum SubmitFeedbackButton {}
-//         MouseEventHandler::new::<SubmitFeedbackButton, _>(0, cx, |state, _| {
-//             let text;
-//             let style = if allow_submission {
-//                 text = "Submit as Markdown";
-//                 theme.feedback.submit_button.style_for(state)
-//             } else {
-//                 text = "Submitting...";
-//                 theme
-//                     .feedback
-//                     .submit_button
-//                     .disabled
-//                     .as_ref()
-//                     .unwrap_or(&theme.feedback.submit_button.default)
-//             };
+// //     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
+// //         let theme = theme::current(cx).clone();
+// //         let allow_submission = self
+// //             .active_item
+// //             .as_ref()
+// //             .map_or(true, |i| i.read(cx).allow_submission);
 
-//             Label::new(text, style.text.clone())
-//                 .contained()
-//                 .with_style(style.container)
-//         })
-//         .with_cursor_style(CursorStyle::PointingHand)
-//         .on_click(MouseButton::Left, |_, this, cx| {
-//             this.submit(&Default::default(), cx);
-//         })
-//         .aligned()
-//         .contained()
-//         .with_margin_left(theme.feedback.button_margin)
-//         .with_tooltip::<Self>(
-//             0,
-//             "cmd-s",
-//             Some(Box::new(SubmitFeedback)),
-//             theme.tooltip.clone(),
-//             cx,
-//         )
-//         .into_any()
-//     }
-// }
+// //         enum SubmitFeedbackButton {}
+// //         MouseEventHandler::new::<SubmitFeedbackButton, _>(0, cx, |state, _| {
+// //             let text;
+// //             let style = if allow_submission {
+// //                 text = "Submit as Markdown";
+// //                 theme.feedback.submit_button.style_for(state)
+// //             } else {
+// //                 text = "Submitting...";
+// //                 theme
+// //                     .feedback
+// //                     .submit_button
+// //                     .disabled
+// //                     .as_ref()
+// //                     .unwrap_or(&theme.feedback.submit_button.default)
+// //             };
+
+// //             Label::new(text, style.text.clone())
+// //                 .contained()
+// //                 .with_style(style.container)
+// //         })
+// //         .with_cursor_style(CursorStyle::PointingHand)
+// //         .on_click(MouseButton::Left, |_, this, cx| {
+// //             this.submit(&Default::default(), cx);
+// //         })
+// //         .aligned()
+// //         .contained()
+// //         .with_margin_left(theme.feedback.button_margin)
+// //         .with_tooltip::<Self>(
+// //             0,
+// //             "cmd-s",
+// //             Some(Box::new(SubmitFeedback)),
+// //             theme.tooltip.clone(),
+// //             cx,
+// //         )
+// //         .into_any()
+// //     }
+// // }
 
 // impl ToolbarItemView for SubmitFeedbackButton {
 //     fn set_active_pane_item(

crates/feedback2/src/system_specs.rs 🔗

@@ -1,17 +1,16 @@
-// use client::ZED_APP_VERSION;
-// use gpui::{platform::AppVersion, AppContext};
+// // 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;
 
-// TODO: Move this file out of feedback and into a more general place
-
 // #[derive(Clone, Debug, Serialize)]
 // pub struct SystemSpecs {
-//     #[serde(serialize_with = "serialize_app_version")]
-//     app_version: Option<AppVersion>,
+//     // todo!()
+//     // #[serde(serialize_with = "serialize_app_version")]
+//     // app_version: Option<AppVersion>,
 //     release_channel: &'static str,
 //     os_name: &'static str,
 //     os_version: Option<String>,
@@ -22,7 +21,7 @@
 // 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 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();
@@ -34,7 +33,7 @@
 //             .map(|os_version| os_version.to_string());
 
 //         SystemSpecs {
-//             app_version,
+//             //   app_version,
 //             release_channel,
 //             os_name,
 //             os_version,
@@ -69,9 +68,9 @@
 //     }
 // }
 
-// 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: &Option<AppVersion>, serializer: S) -> Result<S::Ok, S::Error>
+// // where
+// //     S: serde::Serializer,
+// // {
+// //     version.map(|v| v.to_string()).serialize(serializer)
+// // }

crates/workspace2/src/workspace2.rs 🔗

@@ -3723,26 +3723,6 @@ impl Render for Workspace {
             .text_color(cx.theme().colors().text)
             .bg(cx.theme().colors().background)
             .children(self.titlebar_item.clone())
-            .child(
-                div()
-                    .absolute()
-                    .ml_1_4()
-                    .mt_20()
-                    .elevation_3(cx)
-                    .z_index(999)
-                    .w_1_2()
-                    .h_2_3()
-                    .child(
-                        v_stack().w_full().child(h_stack().child("header")),
-                        // Header
-                        // - has some info, maybe some links
-                        // Body
-                        // - Markdown Editor
-                        // - Email address
-                        // Footer
-                        // - CTA buttons (Send, Cancel)
-                    ),
-            )
             .child(
                 div()
                     .id("workspace")

crates/zed2/src/zed2.rs 🔗

@@ -109,8 +109,8 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
                             //     toolbar.add_item(diagnostic_editor_controls, cx);
                             //     let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
                             //     toolbar.add_item(project_search_bar, cx);
-                            //     let submit_feedback_button =
-                            //         cx.add_view(|_| SubmitFeedbackButton::new());
+                            // let submit_feedback_button =
+                            //     cx.build_view(|_| SubmitFeedbackButton::new());
                             //     toolbar.add_item(submit_feedback_button, cx);
                             //     let feedback_info_text = cx.add_view(|_| FeedbackInfoText::new());
                             //     toolbar.add_item(feedback_info_text, cx);
@@ -144,15 +144,14 @@ pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
         //     let active_buffer_language =
         //         cx.add_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
         //     let vim_mode_indicator = cx.add_view(|cx| vim::ModeIndicator::new(cx));
-        //     let feedback_button = cx.add_view(|_| {
-        //         feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace)
-        //     });
+        let feedback_button = cx
+            .build_view(|_| feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace));
         //     let cursor_position = cx.add_view(|_| editor::items::CursorPosition::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(feedback_button, cx);
+            status_bar.add_right_item(feedback_button, cx);
             // status_bar.add_right_item(copilot, cx);
             // status_bar.add_right_item(active_buffer_language, cx);
             // status_bar.add_right_item(vim_mode_indicator, cx);