welcome.rs

  1mod base_keymap_picker;
  2mod base_keymap_setting;
  3
  4use crate::base_keymap_picker::ToggleBaseKeymapSelector;
  5use client::TelemetrySettings;
  6use db::kvp::KEY_VALUE_STORE;
  7use gpui::{
  8    elements::{Flex, Label, ParentElement},
  9    AnyElement, AppContext, Element, Entity, Subscription, View, ViewContext, WeakViewHandle,
 10};
 11use settings::{update_settings_file, SettingsStore};
 12use std::{borrow::Cow, sync::Arc};
 13use workspace::{
 14    dock::DockPosition, item::Item, open_new, AppState, PaneBackdrop, Welcome, Workspace,
 15    WorkspaceId,
 16};
 17
 18pub use base_keymap_setting::BaseKeymap;
 19
 20pub const FIRST_OPEN: &str = "first_open";
 21
 22pub fn init(cx: &mut AppContext) {
 23    settings::register::<BaseKeymap>(cx);
 24
 25    cx.add_action(|workspace: &mut Workspace, _: &Welcome, cx| {
 26        let welcome_page = cx.add_view(|cx| WelcomePage::new(workspace, cx));
 27        workspace.add_item(Box::new(welcome_page), cx)
 28    });
 29
 30    base_keymap_picker::init(cx);
 31}
 32
 33pub fn show_welcome_experience(app_state: &Arc<AppState>, cx: &mut AppContext) {
 34    open_new(&app_state, cx, |workspace, cx| {
 35        workspace.toggle_dock(DockPosition::Left, cx);
 36        let welcome_page = cx.add_view(|cx| WelcomePage::new(workspace, cx));
 37        workspace.add_item_to_center(Box::new(welcome_page.clone()), cx);
 38        cx.focus(&welcome_page);
 39        cx.notify();
 40    })
 41    .detach();
 42
 43    db::write_and_log(cx, || {
 44        KEY_VALUE_STORE.write_kvp(FIRST_OPEN.to_string(), "false".to_string())
 45    });
 46}
 47
 48pub struct WelcomePage {
 49    workspace: WeakViewHandle<Workspace>,
 50    _settings_subscription: Subscription,
 51}
 52
 53impl Entity for WelcomePage {
 54    type Event = ();
 55}
 56
 57impl View for WelcomePage {
 58    fn ui_name() -> &'static str {
 59        "WelcomePage"
 60    }
 61
 62    fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> AnyElement<Self> {
 63        let self_handle = cx.handle();
 64        let theme = theme::current(cx);
 65        let width = theme.welcome.page_width;
 66
 67        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
 68
 69        enum Metrics {}
 70        enum Diagnostics {}
 71
 72        PaneBackdrop::new(
 73            self_handle.id(),
 74            Flex::column()
 75                .with_child(
 76                    Flex::column()
 77                        .with_child(
 78                            theme::ui::svg(&theme.welcome.logo)
 79                                .aligned()
 80                                .contained()
 81                                .aligned(),
 82                        )
 83                        .with_child(
 84                            Label::new(
 85                                "Code at the speed of thought",
 86                                theme.welcome.logo_subheading.text.clone(),
 87                            )
 88                            .aligned()
 89                            .contained()
 90                            .with_style(theme.welcome.logo_subheading.container),
 91                        )
 92                        .contained()
 93                        .with_style(theme.welcome.heading_group)
 94                        .constrained()
 95                        .with_width(width),
 96                )
 97                .with_child(
 98                    Flex::column()
 99                        .with_child(theme::ui::cta_button::<theme_selector::Toggle, _, _, _>(
100                            "Choose a theme",
101                            width,
102                            &theme.welcome.button,
103                            cx,
104                            |_, this, cx| {
105                                if let Some(workspace) = this.workspace.upgrade(cx) {
106                                    workspace.update(cx, |workspace, cx| {
107                                        theme_selector::toggle(workspace, &Default::default(), cx)
108                                    })
109                                }
110                            },
111                        ))
112                        .with_child(theme::ui::cta_button::<ToggleBaseKeymapSelector, _, _, _>(
113                            "Choose a keymap",
114                            width,
115                            &theme.welcome.button,
116                            cx,
117                            |_, this, cx| {
118                                if let Some(workspace) = this.workspace.upgrade(cx) {
119                                    workspace.update(cx, |workspace, cx| {
120                                        base_keymap_picker::toggle(
121                                            workspace,
122                                            &Default::default(),
123                                            cx,
124                                        )
125                                    })
126                                }
127                            },
128                        ))
129                        .with_child(theme::ui::cta_button::<install_cli::Install, _, _, _>(
130                            "Install the CLI",
131                            width,
132                            &theme.welcome.button,
133                            cx,
134                            |_, _, cx| {
135                                cx.app_context()
136                                    .spawn(|cx| async move { install_cli::install_cli(&cx).await })
137                                    .detach_and_log_err(cx);
138                            },
139                        ))
140                        .contained()
141                        .with_style(theme.welcome.button_group)
142                        .constrained()
143                        .with_width(width),
144                )
145                .with_child(
146                    Flex::column()
147                        .with_child(
148                            theme::ui::checkbox_with_label::<Metrics, _, Self, _>(
149                                Flex::column()
150                                    .with_child(
151                                        Label::new(
152                                            "Send anonymous usage data",
153                                            theme.welcome.checkbox.label.text.clone(),
154                                        )
155                                        .contained()
156                                        .with_style(theme.welcome.checkbox.label.container),
157                                    )
158                                    .with_child(
159                                        Label::new(
160                                            "Help > View Telemetry",
161                                            theme.welcome.usage_note.text.clone(),
162                                        )
163                                        .contained()
164                                        .with_style(theme.welcome.usage_note.container),
165                                    ),
166                                &theme.welcome.checkbox,
167                                telemetry_settings.metrics,
168                                0,
169                                cx,
170                                |this, checked, cx| {
171                                    if let Some(workspace) = this.workspace.upgrade(cx) {
172                                        let fs = workspace.read(cx).app_state().fs.clone();
173                                        update_settings_file::<TelemetrySettings>(
174                                            fs,
175                                            cx,
176                                            move |setting| setting.metrics = Some(checked),
177                                        )
178                                    }
179                                },
180                            )
181                            .contained()
182                            .with_style(theme.welcome.checkbox_container),
183                        )
184                        .with_child(
185                            theme::ui::checkbox::<Diagnostics, Self, _>(
186                                "Send crash reports",
187                                &theme.welcome.checkbox,
188                                telemetry_settings.diagnostics,
189                                0,
190                                cx,
191                                |this, checked, cx| {
192                                    if let Some(workspace) = this.workspace.upgrade(cx) {
193                                        let fs = workspace.read(cx).app_state().fs.clone();
194                                        update_settings_file::<TelemetrySettings>(
195                                            fs,
196                                            cx,
197                                            move |setting| setting.diagnostics = Some(checked),
198                                        )
199                                    }
200                                },
201                            )
202                            .contained()
203                            .with_style(theme.welcome.checkbox_container),
204                        )
205                        .contained()
206                        .with_style(theme.welcome.checkbox_group)
207                        .constrained()
208                        .with_width(width),
209                )
210                .constrained()
211                .with_max_width(width)
212                .contained()
213                .with_uniform_padding(10.)
214                .aligned()
215                .into_any(),
216        )
217        .into_any_named("welcome page")
218    }
219}
220
221impl WelcomePage {
222    pub fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
223        WelcomePage {
224            workspace: workspace.weak_handle(),
225            _settings_subscription: cx.observe_global::<SettingsStore, _>(move |_, cx| cx.notify()),
226        }
227    }
228}
229
230impl Item for WelcomePage {
231    fn tab_tooltip_text(&self, _: &AppContext) -> Option<Cow<str>> {
232        Some("Welcome to Zed!".into())
233    }
234
235    fn tab_content<T: 'static>(
236        &self,
237        _detail: Option<usize>,
238        style: &theme::Tab,
239        _cx: &gpui::AppContext,
240    ) -> AnyElement<T> {
241        Flex::row()
242            .with_child(
243                Label::new("Welcome to Zed!", style.label.clone())
244                    .aligned()
245                    .contained(),
246            )
247            .into_any()
248    }
249
250    fn show_toolbar(&self) -> bool {
251        false
252    }
253
254    fn clone_on_split(
255        &self,
256        _workspace_id: WorkspaceId,
257        cx: &mut ViewContext<Self>,
258    ) -> Option<Self> {
259        Some(WelcomePage {
260            workspace: self.workspace.clone(),
261            _settings_subscription: cx.observe_global::<SettingsStore, _>(move |_, cx| cx.notify()),
262        })
263    }
264}