basics_page.rs

  1use std::sync::Arc;
  2
  3use client::TelemetrySettings;
  4use fs::Fs;
  5use gpui::{App, IntoElement};
  6use settings::{BaseKeymap, Settings, update_settings_file};
  7use theme::{Appearance, SystemAppearance, ThemeMode, ThemeSettings};
  8use ui::{
  9    SwitchField, ThemePreviewTile, ToggleButtonGroup, ToggleButtonSimple, ToggleButtonWithIcon,
 10    prelude::*,
 11};
 12use vim_mode_setting::VimModeSetting;
 13
 14use crate::Onboarding;
 15
 16fn read_theme_selection(cx: &App) -> (ThemeMode, SharedString) {
 17    let settings = ThemeSettings::get_global(cx);
 18    (
 19        settings
 20            .theme_selection
 21            .as_ref()
 22            .and_then(|selection| selection.mode())
 23            .unwrap_or_default(),
 24        settings.active_theme.name.clone(),
 25    )
 26}
 27
 28fn write_theme_selection(theme_mode: ThemeMode, cx: &App) {
 29    let fs = <dyn Fs>::global(cx);
 30
 31    update_settings_file::<ThemeSettings>(fs, cx, move |settings, _| {
 32        settings.set_mode(theme_mode);
 33    });
 34}
 35
 36fn write_keymap_base(keymap_base: BaseKeymap, cx: &App) {
 37    let fs = <dyn Fs>::global(cx);
 38
 39    update_settings_file::<BaseKeymap>(fs, cx, move |setting, _| {
 40        *setting = Some(keymap_base);
 41    });
 42}
 43
 44fn render_theme_section(theme_mode: ThemeMode) -> impl IntoElement {
 45    h_flex().justify_between().child(Label::new("Theme")).child(
 46        ToggleButtonGroup::single_row(
 47            "theme-selector-onboarding",
 48            [
 49                ToggleButtonSimple::new("Light", |_, _, cx| {
 50                    write_theme_selection(ThemeMode::Light, cx)
 51                }),
 52                ToggleButtonSimple::new("Dark", |_, _, cx| {
 53                    write_theme_selection(ThemeMode::Dark, cx)
 54                }),
 55                ToggleButtonSimple::new("System", |_, _, cx| {
 56                    write_theme_selection(ThemeMode::System, cx)
 57                }),
 58            ],
 59        )
 60        .selected_index(match theme_mode {
 61            ThemeMode::Light => 0,
 62            ThemeMode::Dark => 1,
 63            ThemeMode::System => 2,
 64        })
 65        .style(ui::ToggleButtonGroupStyle::Outlined)
 66        .button_width(rems_from_px(64.)),
 67    )
 68}
 69
 70fn render_telemetry_section(fs: Arc<dyn Fs>, cx: &App) -> impl IntoElement {
 71    v_flex()
 72
 73        .gap_4()
 74        .child(Label::new("Telemetry").size(LabelSize::Large))
 75        .child(SwitchField::new(
 76            "onboarding-telemetry-metrics",
 77            "Help Improve Zed",
 78            "Sending anonymous usage data helps us build the right features and create the best experience.",
 79            if TelemetrySettings::get_global(cx).metrics {
 80                ui::ToggleState::Selected
 81            } else {
 82                ui::ToggleState::Unselected
 83            },
 84            {
 85            let fs = fs.clone();
 86            move |selection, _, cx| {
 87                let enabled = match selection {
 88                    ToggleState::Selected => true,
 89                    ToggleState::Unselected => false,
 90                    ToggleState::Indeterminate => { return; },
 91                };
 92
 93                update_settings_file::<TelemetrySettings>(
 94                    fs.clone(),
 95                    cx,
 96                    move |setting, _| setting.metrics = Some(enabled),
 97                );
 98            }},
 99        ))
100        .child(SwitchField::new(
101            "onboarding-telemetry-crash-reports",
102            "Help Fix Zed",
103            "Send crash reports so we can fix critical issues fast.",
104            if TelemetrySettings::get_global(cx).diagnostics {
105                ui::ToggleState::Selected
106            } else {
107                ui::ToggleState::Unselected
108            },
109            {
110                let fs = fs.clone();
111                move |selection, _, cx| {
112                    let enabled = match selection {
113                        ToggleState::Selected => true,
114                        ToggleState::Unselected => false,
115                        ToggleState::Indeterminate => { return; },
116                    };
117
118                    update_settings_file::<TelemetrySettings>(
119                        fs.clone(),
120                        cx,
121                        move |setting, _| setting.diagnostics = Some(enabled),
122                    );
123                }
124            }
125        ))
126}
127
128pub(crate) fn render_basics_page(onboarding: &Onboarding, cx: &mut App) -> impl IntoElement {
129    let (theme_mode, active_theme_name) = read_theme_selection(cx);
130    let themes = match theme_mode {
131        ThemeMode::Dark => &onboarding.dark_themes,
132        ThemeMode::Light => &onboarding.light_themes,
133        ThemeMode::System => match SystemAppearance::global(cx).0 {
134            Appearance::Light => &onboarding.light_themes,
135            Appearance::Dark => &onboarding.dark_themes,
136        },
137    };
138
139    let base_keymap = match BaseKeymap::get_global(cx) {
140        BaseKeymap::VSCode => Some(0),
141        BaseKeymap::JetBrains => Some(1),
142        BaseKeymap::SublimeText => Some(2),
143        BaseKeymap::Atom => Some(3),
144        BaseKeymap::Emacs => Some(4),
145        BaseKeymap::Cursor => Some(5),
146        BaseKeymap::TextMate | BaseKeymap::None => None,
147    };
148
149    v_flex()
150        .gap_6()
151        .child(render_theme_section(theme_mode))
152        .child(h_flex().children(
153            themes.iter().map(|theme| {
154                ThemePreviewTile::new(theme.clone(), active_theme_name == theme.name, 0.48)
155                .on_click({
156                    let theme_name = theme.name.clone();
157                    let fs = onboarding.fs.clone();
158                    move |_, _, cx| {
159                        let theme_name = theme_name.clone();
160                        update_settings_file::<ThemeSettings>(fs.clone(), cx, move |settings, cx| {
161                            settings.set_theme(theme_name.to_string(), SystemAppearance::global(cx).0);
162                        });
163                    }
164                })
165            })
166        ))
167        .child(
168            v_flex().gap_2().child(Label::new("Base Keymap")).child(
169                ToggleButtonGroup::two_rows(
170                    "multiple_row_test",
171                    [
172                        ToggleButtonWithIcon::new("VS Code", IconName::AiZed, |_, _, cx| {
173                            write_keymap_base(BaseKeymap::VSCode, cx);
174                        }),
175                        ToggleButtonWithIcon::new("Jetbrains", IconName::AiZed, |_, _, cx| {
176                            write_keymap_base(BaseKeymap::JetBrains, cx);
177                        }),
178                        ToggleButtonWithIcon::new("Sublime Text", IconName::AiZed, |_, _, cx| {
179                            write_keymap_base(BaseKeymap::SublimeText, cx);
180                        }),
181                    ],
182                    [
183                        ToggleButtonWithIcon::new("Atom", IconName::AiZed, |_, _, cx| {
184                            write_keymap_base(BaseKeymap::Atom, cx);
185                        }),
186                        ToggleButtonWithIcon::new("Emacs", IconName::AiZed, |_, _, cx| {
187                            write_keymap_base(BaseKeymap::Emacs, cx);
188                        }),
189                        ToggleButtonWithIcon::new("Cursor (Beta)", IconName::AiZed, |_, _, cx| {
190                            write_keymap_base(BaseKeymap::Cursor, cx);
191                        }),
192                    ],
193                )
194                .when_some(base_keymap, |this, base_keymap| this.selected_index(base_keymap))
195                .button_width(rems_from_px(230.))
196                .style(ui::ToggleButtonGroupStyle::Outlined)
197            ),
198        )
199        .child(v_flex().justify_center().child(div().h_0().child("hack").invisible()).child(SwitchField::new(
200            "onboarding-vim-mode",
201            "Vim Mode",
202            "Coming from Neovim? Zed's first-class implementation of Vim Mode has got your back.",
203            if VimModeSetting::get_global(cx).0 {
204                ui::ToggleState::Selected
205            } else {
206                ui::ToggleState::Unselected
207            },
208            {
209                let fs = onboarding.fs.clone();
210                move |selection, _, cx| {
211                    let enabled = match selection {
212                        ToggleState::Selected => true,
213                        ToggleState::Unselected => false,
214                        ToggleState::Indeterminate => { return; },
215                    };
216
217                    update_settings_file::<VimModeSetting>(
218                        fs.clone(),
219                        cx,
220                        move |setting, _| *setting = Some(enabled),
221                    );
222                }
223            },
224        )))
225        .child(render_telemetry_section(onboarding.fs.clone(), cx))
226}