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