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