feedback.rs

  1use gpui::{App, ClipboardItem, PromptLevel, actions};
  2use system_specs::{CopySystemSpecsIntoClipboard, SystemSpecs};
  3use util::ResultExt;
  4use workspace::Workspace;
  5use zed_actions::feedback::FileBugReport;
  6
  7pub mod feedback_modal;
  8
  9actions!(
 10    zed,
 11    [
 12        /// Opens email client to send feedback to Zed support.
 13        EmailZed,
 14        /// Opens the Zed repository on GitHub.
 15        OpenZedRepo,
 16        /// Opens the feature request form.
 17        RequestFeature,
 18    ]
 19);
 20
 21const ZED_REPO_URL: &str = "https://github.com/zed-industries/zed";
 22
 23const REQUEST_FEATURE_URL: &str = "https://github.com/zed-industries/zed/discussions/new/choose";
 24
 25fn file_bug_report_url(specs: &SystemSpecs) -> String {
 26    format!(
 27        concat!(
 28            "https://github.com/zed-industries/zed/issues/new",
 29            "?",
 30            "template=10_bug_report.yml",
 31            "&",
 32            "environment={}"
 33        ),
 34        urlencoding::encode(&specs.to_string())
 35    )
 36}
 37
 38fn email_zed_url(specs: &SystemSpecs) -> String {
 39    format!(
 40        concat!("mailto:hi@zed.dev", "?", "body={}"),
 41        email_body(specs)
 42    )
 43}
 44
 45fn email_body(specs: &SystemSpecs) -> String {
 46    let body = format!("\n\nSystem Information:\n\n{}", specs);
 47    urlencoding::encode(&body).to_string()
 48}
 49
 50pub fn init(cx: &mut App) {
 51    cx.observe_new(|workspace: &mut Workspace, window, cx| {
 52        let Some(window) = window else {
 53            return;
 54        };
 55        feedback_modal::FeedbackModal::register(workspace, window, cx);
 56        workspace
 57            .register_action(|_, _: &CopySystemSpecsIntoClipboard, window, cx| {
 58                let specs = SystemSpecs::new(window, cx);
 59
 60                cx.spawn_in(window, async move |_, cx| {
 61                    let specs = specs.await.to_string();
 62
 63                    cx.update(|_, cx| {
 64                        cx.write_to_clipboard(ClipboardItem::new_string(specs.clone()))
 65                    })
 66                    .log_err();
 67
 68                    cx.prompt(
 69                        PromptLevel::Info,
 70                        "Copied into clipboard",
 71                        Some(&specs),
 72                        &["OK"],
 73                    )
 74                    .await
 75                })
 76                .detach();
 77            })
 78            .register_action(|_, _: &RequestFeature, _, cx| {
 79                cx.open_url(REQUEST_FEATURE_URL);
 80            })
 81            .register_action(move |_, _: &FileBugReport, window, cx| {
 82                let specs = SystemSpecs::new(window, cx);
 83                cx.spawn_in(window, async move |_, cx| {
 84                    let specs = specs.await;
 85                    cx.update(|_, cx| {
 86                        cx.open_url(&file_bug_report_url(&specs));
 87                    })
 88                    .log_err();
 89                })
 90                .detach();
 91            })
 92            .register_action(move |_, _: &EmailZed, window, cx| {
 93                let specs = SystemSpecs::new(window, cx);
 94                cx.spawn_in(window, async move |_, cx| {
 95                    let specs = specs.await;
 96                    cx.update(|_, cx| {
 97                        cx.open_url(&email_zed_url(&specs));
 98                    })
 99                    .log_err();
100                })
101                .detach();
102            })
103            .register_action(move |_, _: &OpenZedRepo, _, cx| {
104                cx.open_url(ZED_REPO_URL);
105            });
106    })
107    .detach();
108}