mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
Start up settings UI 2 (#38673)
Release Notes: - N/A --------- Co-authored-by: Anthony <hello@anthonyeid.me> Co-authored-by: Ben Kunkle <ben@zed.dev> Co-authored-by: Anthony <anthony@zed.dev> Co-authored-by: Ben Kunkle <ben.kunkle@gmail.com>
This commit is contained in:
parent
6f3e66d027
commit
53885c00d3
11 changed files with 582 additions and 10 deletions
26
Cargo.lock
generated
26
Cargo.lock
generated
|
|
@ -14502,6 +14502,31 @@ dependencies = [
|
|||
"zed_actions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "settings_ui"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"assets",
|
||||
"command_palette_hooks",
|
||||
"editor",
|
||||
"feature_flags",
|
||||
"fs",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"language",
|
||||
"menu",
|
||||
"paths",
|
||||
"project",
|
||||
"serde",
|
||||
"settings",
|
||||
"theme",
|
||||
"ui",
|
||||
"workspace",
|
||||
"workspace-hack",
|
||||
"zlog",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
|
|
@ -20253,6 +20278,7 @@ dependencies = [
|
|||
"session",
|
||||
"settings",
|
||||
"settings_profile_selector",
|
||||
"settings_ui",
|
||||
"shellexpand 2.1.2",
|
||||
"smol",
|
||||
"snippet_provider",
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ members = [
|
|||
"crates/settings",
|
||||
"crates/settings_macros",
|
||||
"crates/settings_profile_selector",
|
||||
"crates/settings_ui",
|
||||
"crates/snippet",
|
||||
"crates/snippet_provider",
|
||||
"crates/snippets_ui",
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ zlog.workspace = true
|
|||
[dev-dependencies]
|
||||
fs = { workspace = true, features = ["test-support"] }
|
||||
gpui = { workspace = true, features = ["test-support"] }
|
||||
|
||||
indoc.workspace = true
|
||||
pretty_assertions.workspace = true
|
||||
unindent.workspace = true
|
||||
|
|
|
|||
|
|
@ -177,7 +177,6 @@ impl KeymapFile {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "test-support")]
|
||||
pub fn load_asset_allow_partial_failure(
|
||||
asset_path: &str,
|
||||
cx: &App,
|
||||
|
|
|
|||
|
|
@ -138,7 +138,6 @@ pub struct SettingsLocation<'a> {
|
|||
pub path: &'a Path,
|
||||
}
|
||||
|
||||
/// A set of strongly-typed setting values defined via multiple config files.
|
||||
pub struct SettingsStore {
|
||||
setting_values: HashMap<TypeId, Box<dyn AnySettingValue>>,
|
||||
default_settings: Rc<SettingsContent>,
|
||||
|
|
@ -318,7 +317,7 @@ impl SettingsStore {
|
|||
.set_global_value(Box::new(value))
|
||||
}
|
||||
|
||||
/// Get the user's settings as a raw JSON value.
|
||||
/// Get the user's settings content.
|
||||
///
|
||||
/// For user-facing functionality use the typed setting interface.
|
||||
/// (e.g. ProjectSettings::get_global(cx))
|
||||
|
|
@ -326,6 +325,11 @@ impl SettingsStore {
|
|||
self.user_settings.as_ref()
|
||||
}
|
||||
|
||||
/// Get the default settings content as a raw JSON value.
|
||||
pub fn raw_default_settings(&self) -> &SettingsContent {
|
||||
&self.default_settings
|
||||
}
|
||||
|
||||
/// Get the configured settings profile names.
|
||||
pub fn configured_settings_profiles(&self) -> impl Iterator<Item = &str> {
|
||||
self.user_settings
|
||||
|
|
|
|||
44
crates/settings_ui/Cargo.toml
Normal file
44
crates/settings_ui/Cargo.toml
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
[package]
|
||||
name = "settings_ui"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
publish.workspace = true
|
||||
license = "GPL-3.0-or-later"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[lib]
|
||||
path = "src/settings_ui.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
test-support = []
|
||||
|
||||
[dependencies]
|
||||
project.workspace = true
|
||||
fs.workspace = true
|
||||
anyhow.workspace = true
|
||||
command_palette_hooks.workspace = true
|
||||
editor.workspace = true
|
||||
feature_flags.workspace = true
|
||||
gpui.workspace = true
|
||||
menu.workspace = true
|
||||
serde.workspace = true
|
||||
settings.workspace = true
|
||||
theme.workspace = true
|
||||
ui.workspace = true
|
||||
workspace-hack.workspace = true
|
||||
workspace.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
settings = { workspace = true, features = ["test-support"] }
|
||||
futures.workspace = true
|
||||
language.workspace = true
|
||||
assets.workspace = true
|
||||
paths.workspace = true
|
||||
zlog.workspace = true
|
||||
|
||||
[[example]]
|
||||
name = "ui"
|
||||
path = "examples/ui.rs"
|
||||
1
crates/settings_ui/LICENSE-GPL
Symbolic link
1
crates/settings_ui/LICENSE-GPL
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../../LICENSE-GPL
|
||||
48
crates/settings_ui/examples/ui.rs
Normal file
48
crates/settings_ui/examples/ui.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use futures::StreamExt;
|
||||
use settings::{DEFAULT_KEYMAP_PATH, KeymapFile, SettingsStore, watch_config_file};
|
||||
use settings_ui::open_settings_editor;
|
||||
use ui::BorrowAppContext;
|
||||
|
||||
fn main() {
|
||||
let app = gpui::Application::new().with_assets(assets::Assets);
|
||||
|
||||
let fs = Arc::new(fs::RealFs::new(None, app.background_executor()));
|
||||
let mut user_settings_file_rx = watch_config_file(
|
||||
&app.background_executor(),
|
||||
fs.clone(),
|
||||
paths::settings_file().clone(),
|
||||
);
|
||||
zlog::init();
|
||||
zlog::init_output_stderr();
|
||||
|
||||
app.run(move |cx| {
|
||||
<dyn fs::Fs>::set_global(fs.clone(), cx);
|
||||
settings::init(cx);
|
||||
theme::init(theme::LoadThemes::JustBase, cx);
|
||||
workspace::init_settings(cx);
|
||||
project::Project::init_settings(cx);
|
||||
language::init(cx);
|
||||
editor::init(cx);
|
||||
menu::init();
|
||||
|
||||
let keybindings =
|
||||
KeymapFile::load_asset_allow_partial_failure(DEFAULT_KEYMAP_PATH, cx).unwrap();
|
||||
cx.bind_keys(keybindings);
|
||||
cx.spawn(async move |cx| {
|
||||
while let Some(content) = user_settings_file_rx.next().await {
|
||||
cx.update(|cx| {
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.set_user_settings(&content, cx).unwrap()
|
||||
})
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
||||
open_settings_editor(cx).unwrap();
|
||||
cx.activate(true);
|
||||
});
|
||||
}
|
||||
446
crates/settings_ui/src/settings_ui.rs
Normal file
446
crates/settings_ui/src/settings_ui.rs
Normal file
|
|
@ -0,0 +1,446 @@
|
|||
//! # settings_ui
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
|
||||
use editor::Editor;
|
||||
use feature_flags::{FeatureFlag, FeatureFlagAppExt as _};
|
||||
use gpui::{
|
||||
App, AppContext as _, Context, Div, Entity, IntoElement, ReadGlobal as _, Render, Window,
|
||||
WindowHandle, WindowOptions, actions, div, px, size,
|
||||
};
|
||||
use project::WorktreeId;
|
||||
use settings::{SettingsContent, SettingsStore};
|
||||
use std::path::Path;
|
||||
use ui::{
|
||||
ActiveTheme as _, AnyElement, BorrowAppContext as _, Button, Clickable as _, Color,
|
||||
FluentBuilder as _, Icon, IconName, InteractiveElement as _, Label, LabelCommon as _,
|
||||
LabelSize, ParentElement, SharedString, StatefulInteractiveElement as _, Styled, Switch,
|
||||
v_flex,
|
||||
};
|
||||
|
||||
fn user_settings_data() -> Vec<SettingsPage> {
|
||||
vec![
|
||||
SettingsPage {
|
||||
title: "General Page",
|
||||
items: vec![
|
||||
SettingsPageItem::SectionHeader("General Section"),
|
||||
SettingsPageItem::SettingItem(SettingItem {
|
||||
title: "Confirm Quit",
|
||||
description: "Whether to confirm before quitting Zed",
|
||||
render: Rc::new(|_, cx| {
|
||||
render_toggle_button(
|
||||
"confirm_quit",
|
||||
SettingsFile::User,
|
||||
cx,
|
||||
|settings_content| &mut settings_content.workspace.confirm_quit,
|
||||
)
|
||||
}),
|
||||
}),
|
||||
SettingsPageItem::SettingItem(SettingItem {
|
||||
title: "Auto Update",
|
||||
description: "Automatically update Zed (may be ignored on Linux if installed through a package manager)",
|
||||
render: Rc::new(|_, cx| {
|
||||
render_toggle_button(
|
||||
"Auto Update",
|
||||
SettingsFile::User,
|
||||
cx,
|
||||
|settings_content| &mut settings_content.auto_update,
|
||||
)
|
||||
}),
|
||||
}),
|
||||
],
|
||||
},
|
||||
SettingsPage {
|
||||
title: "Project",
|
||||
items: vec![
|
||||
SettingsPageItem::SectionHeader("Worktree Settings Content"),
|
||||
SettingsPageItem::SettingItem(SettingItem {
|
||||
title: "Project Name",
|
||||
description: "The displayed name of this project. If not set, the root directory name",
|
||||
render: Rc::new(|window, cx| {
|
||||
render_text_field(
|
||||
"project_name",
|
||||
SettingsFile::User,
|
||||
window,
|
||||
cx,
|
||||
|settings_content| &mut settings_content.project.worktree.project_name,
|
||||
)
|
||||
}),
|
||||
}),
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
fn project_settings_data() -> Vec<SettingsPage> {
|
||||
vec![SettingsPage {
|
||||
title: "Project",
|
||||
items: vec![
|
||||
SettingsPageItem::SectionHeader("Worktree Settings Content"),
|
||||
SettingsPageItem::SettingItem(SettingItem {
|
||||
title: "Project Name",
|
||||
description: " The displayed name of this project. If not set, the root directory name",
|
||||
render: Rc::new(|window, cx| {
|
||||
render_text_field(
|
||||
"project_name",
|
||||
SettingsFile::Local((
|
||||
WorktreeId::from_usize(0),
|
||||
Arc::from(Path::new("TODO: actually pass through file")),
|
||||
)),
|
||||
window,
|
||||
cx,
|
||||
|settings_content| &mut settings_content.project.worktree.project_name,
|
||||
)
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}]
|
||||
}
|
||||
|
||||
pub struct SettingsUiFeatureFlag;
|
||||
|
||||
impl FeatureFlag for SettingsUiFeatureFlag {
|
||||
const NAME: &'static str = "settings-ui";
|
||||
}
|
||||
|
||||
actions!(
|
||||
zed,
|
||||
[
|
||||
/// Opens Settings Editor.
|
||||
OpenSettingsEditor
|
||||
]
|
||||
);
|
||||
|
||||
pub fn init(cx: &mut App) {
|
||||
cx.observe_new(|workspace: &mut workspace::Workspace, _, _| {
|
||||
workspace.register_action_renderer(|div, _, _, cx| {
|
||||
let settings_ui_actions = [std::any::TypeId::of::<OpenSettingsEditor>()];
|
||||
let has_flag = cx.has_flag::<SettingsUiFeatureFlag>();
|
||||
command_palette_hooks::CommandPaletteFilter::update_global(cx, |filter, _| {
|
||||
if has_flag {
|
||||
filter.show_action_types(&settings_ui_actions);
|
||||
} else {
|
||||
filter.hide_action_types(&settings_ui_actions);
|
||||
}
|
||||
});
|
||||
if has_flag {
|
||||
div.on_action(cx.listener(|_, _: &OpenSettingsEditor, _, cx| {
|
||||
open_settings_editor(cx).ok();
|
||||
}))
|
||||
} else {
|
||||
div
|
||||
}
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn open_settings_editor(cx: &mut App) -> anyhow::Result<WindowHandle<SettingsWindow>> {
|
||||
cx.open_window(
|
||||
WindowOptions {
|
||||
titlebar: None,
|
||||
focus: true,
|
||||
show: true,
|
||||
kind: gpui::WindowKind::Normal,
|
||||
window_min_size: Some(size(px(300.), px(500.))), // todo(settings_ui): Does this min_size make sense?
|
||||
..Default::default()
|
||||
},
|
||||
|window, cx| cx.new(|cx| SettingsWindow::new(window, cx)),
|
||||
)
|
||||
}
|
||||
|
||||
pub struct SettingsWindow {
|
||||
files: Vec<SettingsFile>,
|
||||
current_file: SettingsFile,
|
||||
pages: Vec<SettingsPage>,
|
||||
search: Entity<Editor>,
|
||||
current_page: usize, // Index into pages - should probably be (usize, Option<usize>) for section + page
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct SettingsPage {
|
||||
title: &'static str,
|
||||
items: Vec<SettingsPageItem>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
enum SettingsPageItem {
|
||||
SectionHeader(&'static str),
|
||||
SettingItem(SettingItem),
|
||||
}
|
||||
|
||||
impl SettingsPageItem {
|
||||
fn render(&self, window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
match self {
|
||||
SettingsPageItem::SectionHeader(header) => Label::new(SharedString::new_static(header))
|
||||
.size(LabelSize::Large)
|
||||
.into_any_element(),
|
||||
SettingsPageItem::SettingItem(setting_item) => div()
|
||||
.child(setting_item.title)
|
||||
.child(setting_item.description)
|
||||
.child((setting_item.render)(window, cx))
|
||||
.into_any_element(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SettingsPageItem {
|
||||
fn _header(&self) -> Option<&'static str> {
|
||||
match self {
|
||||
SettingsPageItem::SectionHeader(header) => Some(header),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct SettingItem {
|
||||
title: &'static str,
|
||||
description: &'static str,
|
||||
render: std::rc::Rc<dyn Fn(&mut Window, &mut App) -> AnyElement>,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Clone)]
|
||||
enum SettingsFile {
|
||||
User, // Uses all settings.
|
||||
Local((WorktreeId, Arc<Path>)), // Has a special name, and special set of settings
|
||||
Server(&'static str), // Uses a special name, and the user settings
|
||||
}
|
||||
|
||||
impl SettingsFile {
|
||||
fn pages(&self) -> Vec<SettingsPage> {
|
||||
match self {
|
||||
SettingsFile::User => user_settings_data(),
|
||||
SettingsFile::Local(_) => project_settings_data(),
|
||||
SettingsFile::Server(_) => user_settings_data(),
|
||||
}
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
match self {
|
||||
SettingsFile::User => "User".to_string(),
|
||||
SettingsFile::Local((_, path)) => format!("Local ({})", path.display()),
|
||||
SettingsFile::Server(file) => format!("Server ({})", file),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SettingsWindow {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let current_file = SettingsFile::User;
|
||||
let search = cx.new(|cx| {
|
||||
let mut editor = Editor::single_line(window, cx);
|
||||
editor.set_placeholder_text("Search Settings", window, cx);
|
||||
editor
|
||||
});
|
||||
let mut this = Self {
|
||||
files: vec![
|
||||
SettingsFile::User,
|
||||
SettingsFile::Local((
|
||||
WorktreeId::from_usize(0),
|
||||
Arc::from(Path::new("/my-project/")),
|
||||
)),
|
||||
],
|
||||
current_file: current_file,
|
||||
pages: vec![],
|
||||
current_page: 0,
|
||||
search,
|
||||
};
|
||||
cx.observe_global_in::<SettingsStore>(window, move |_, _, cx| {
|
||||
cx.notify();
|
||||
})
|
||||
.detach();
|
||||
|
||||
this.build_ui();
|
||||
this
|
||||
}
|
||||
|
||||
fn build_ui(&mut self) {
|
||||
self.pages = self.current_file.pages();
|
||||
}
|
||||
|
||||
fn change_file(&mut self, ix: usize) {
|
||||
self.current_file = self.files[ix].clone();
|
||||
self.build_ui();
|
||||
}
|
||||
|
||||
fn render_files(&self, _window: &mut Window, cx: &mut Context<SettingsWindow>) -> Div {
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.gap_1()
|
||||
.children(self.files.iter().enumerate().map(|(ix, file)| {
|
||||
Button::new(ix, file.name())
|
||||
.on_click(cx.listener(move |this, _, _window, _cx| this.change_file(ix)))
|
||||
}))
|
||||
}
|
||||
|
||||
fn render_search(&self, _window: &mut Window, _cx: &mut App) -> Div {
|
||||
div()
|
||||
.child(Icon::new(IconName::MagnifyingGlass))
|
||||
.child(self.search.clone())
|
||||
}
|
||||
|
||||
fn render_nav(&self, window: &mut Window, cx: &mut Context<SettingsWindow>) -> Div {
|
||||
let mut nav = v_flex()
|
||||
.p_4()
|
||||
.gap_2()
|
||||
.child(div().h_10()) // Files spacer;
|
||||
.child(self.render_search(window, cx));
|
||||
|
||||
for (ix, page) in self.pages.iter().enumerate() {
|
||||
nav = nav.child(
|
||||
div()
|
||||
.id(page.title)
|
||||
.child(
|
||||
Label::new(page.title)
|
||||
.size(LabelSize::Large)
|
||||
.when(self.is_page_selected(ix), |this| {
|
||||
this.color(Color::Selected)
|
||||
}),
|
||||
)
|
||||
.on_click(cx.listener(move |this, _, _, cx| {
|
||||
this.current_page = ix;
|
||||
cx.notify();
|
||||
})),
|
||||
);
|
||||
}
|
||||
nav
|
||||
}
|
||||
|
||||
fn render_page(
|
||||
&self,
|
||||
page: &SettingsPage,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<SettingsWindow>,
|
||||
) -> Div {
|
||||
div()
|
||||
.child(self.render_files(window, cx))
|
||||
.child(Label::new(page.title))
|
||||
.children(page.items.iter().map(|item| item.render(window, cx)))
|
||||
}
|
||||
|
||||
fn current_page(&self) -> &SettingsPage {
|
||||
&self.pages[self.current_page]
|
||||
}
|
||||
|
||||
fn is_page_selected(&self, ix: usize) -> bool {
|
||||
ix == self.current_page
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for SettingsWindow {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.size_full()
|
||||
.bg(cx.theme().colors().background)
|
||||
.flex()
|
||||
.flex_row()
|
||||
.text_color(cx.theme().colors().text)
|
||||
.child(self.render_nav(window, cx).w(px(300.0)))
|
||||
.child(self.render_page(self.current_page(), window, cx).w_full())
|
||||
}
|
||||
}
|
||||
|
||||
fn write_setting_value<T: Send + 'static>(
|
||||
get_value: fn(&mut SettingsContent) -> &mut Option<T>,
|
||||
value: Option<T>,
|
||||
cx: &mut App,
|
||||
) {
|
||||
cx.update_global(|store: &mut SettingsStore, cx| {
|
||||
store.update_settings_file(<dyn fs::Fs>::global(cx), move |settings, _cx| {
|
||||
*get_value(settings) = value;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn render_text_field(
|
||||
id: &'static str,
|
||||
_file: SettingsFile,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
get_value: fn(&mut SettingsContent) -> &mut Option<String>,
|
||||
) -> AnyElement {
|
||||
// TODO: Updating file does not cause the editor text to reload, suspicious it may be a missing global update/notify in SettingsStore
|
||||
|
||||
// TODO: in settings window state
|
||||
let store = SettingsStore::global(cx);
|
||||
|
||||
// TODO: This clone needs to go!!
|
||||
let mut defaults = store.raw_default_settings().clone();
|
||||
let mut user_settings = store
|
||||
.raw_user_settings()
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.content;
|
||||
|
||||
// TODO: unwrap_or_default here because project name is null
|
||||
let initial_text = get_value(user_settings.as_mut())
|
||||
.clone()
|
||||
.unwrap_or_else(|| get_value(&mut defaults).clone().unwrap_or_default());
|
||||
|
||||
let editor = window.use_keyed_state((id.into(), initial_text.clone()), cx, {
|
||||
move |window, cx| {
|
||||
let mut editor = Editor::single_line(window, cx);
|
||||
editor.set_text(initial_text, window, cx);
|
||||
editor
|
||||
}
|
||||
});
|
||||
|
||||
let weak_editor = editor.downgrade();
|
||||
let theme_colors = cx.theme().colors();
|
||||
|
||||
div()
|
||||
.child(editor)
|
||||
.bg(theme_colors.editor_background)
|
||||
.border_1()
|
||||
.rounded_lg()
|
||||
.border_color(theme_colors.border)
|
||||
.on_action::<menu::Confirm>({
|
||||
move |_, _, cx| {
|
||||
let Some(editor) = weak_editor.upgrade() else {
|
||||
return;
|
||||
};
|
||||
let new_value = editor.read_with(cx, |editor, cx| editor.text(cx));
|
||||
let new_value = (!new_value.is_empty()).then_some(new_value);
|
||||
write_setting_value(get_value, new_value, cx);
|
||||
editor.update(cx, |_, cx| {
|
||||
cx.notify();
|
||||
});
|
||||
}
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn render_toggle_button(
|
||||
id: &'static str,
|
||||
_: SettingsFile,
|
||||
cx: &mut App,
|
||||
get_value: fn(&mut SettingsContent) -> &mut Option<bool>,
|
||||
) -> AnyElement {
|
||||
// TODO: in settings window state
|
||||
let store = SettingsStore::global(cx);
|
||||
|
||||
// TODO: This clone needs to go!!
|
||||
let mut defaults = store.raw_default_settings().clone();
|
||||
let mut user_settings = store
|
||||
.raw_user_settings()
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.content;
|
||||
|
||||
let toggle_state =
|
||||
if get_value(&mut user_settings).unwrap_or_else(|| get_value(&mut defaults).unwrap()) {
|
||||
ui::ToggleState::Selected
|
||||
} else {
|
||||
ui::ToggleState::Unselected
|
||||
};
|
||||
|
||||
Switch::new(id, toggle_state)
|
||||
.on_click({
|
||||
move |state, _window, cx| {
|
||||
write_setting_value(get_value, Some(*state == ui::ToggleState::Selected), cx);
|
||||
}
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
|
@ -19,11 +19,11 @@ name = "zed"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
activity_indicator.workspace = true
|
||||
acp_tools.workspace = true
|
||||
activity_indicator.workspace = true
|
||||
agent.workspace = true
|
||||
agent_ui.workspace = true
|
||||
agent_settings.workspace = true
|
||||
agent_ui.workspace = true
|
||||
anyhow.workspace = true
|
||||
askpass.workspace = true
|
||||
assets.workspace = true
|
||||
|
|
@ -60,13 +60,13 @@ extensions_ui.workspace = true
|
|||
feature_flags.workspace = true
|
||||
feedback.workspace = true
|
||||
file_finder.workspace = true
|
||||
system_specs.workspace = true
|
||||
fs.workspace = true
|
||||
futures.workspace = true
|
||||
git.workspace = true
|
||||
git_hosting_providers.workspace = true
|
||||
git_ui.workspace = true
|
||||
go_to_line.workspace = true
|
||||
system_specs.workspace = true
|
||||
gpui = { workspace = true, features = [
|
||||
"wayland",
|
||||
"x11",
|
||||
|
|
@ -75,12 +75,13 @@ gpui = { workspace = true, features = [
|
|||
] }
|
||||
gpui_tokio.workspace = true
|
||||
|
||||
edit_prediction_button.workspace = true
|
||||
http_client.workspace = true
|
||||
image_viewer.workspace = true
|
||||
edit_prediction_button.workspace = true
|
||||
inspector_ui.workspace = true
|
||||
install_cli.workspace = true
|
||||
journal.workspace = true
|
||||
keymap_editor.workspace = true
|
||||
language.workspace = true
|
||||
language_extension.workspace = true
|
||||
language_model.workspace = true
|
||||
|
|
@ -93,7 +94,6 @@ line_ending_selector.workspace = true
|
|||
log.workspace = true
|
||||
markdown.workspace = true
|
||||
markdown_preview.workspace = true
|
||||
svg_preview.workspace = true
|
||||
menu.workspace = true
|
||||
migrator.workspace = true
|
||||
mimalloc = { version = "0.1", optional = true }
|
||||
|
|
@ -107,7 +107,6 @@ outline_panel.workspace = true
|
|||
parking_lot.workspace = true
|
||||
paths.workspace = true
|
||||
picker.workspace = true
|
||||
settings_profile_selector.workspace = true
|
||||
profiling.workspace = true
|
||||
project.workspace = true
|
||||
project_panel.workspace = true
|
||||
|
|
@ -126,12 +125,14 @@ serde.workspace = true
|
|||
serde_json.workspace = true
|
||||
session.workspace = true
|
||||
settings.workspace = true
|
||||
keymap_editor.workspace = true
|
||||
settings_profile_selector.workspace = true
|
||||
settings_ui.workspace = true
|
||||
shellexpand.workspace = true
|
||||
smol.workspace = true
|
||||
snippet_provider.workspace = true
|
||||
snippets_ui.workspace = true
|
||||
supermaven.workspace = true
|
||||
svg_preview.workspace = true
|
||||
sysinfo.workspace = true
|
||||
tab_switcher.workspace = true
|
||||
task.workspace = true
|
||||
|
|
|
|||
|
|
@ -614,6 +614,7 @@ pub fn main() {
|
|||
markdown_preview::init(cx);
|
||||
svg_preview::init(cx);
|
||||
onboarding::init(cx);
|
||||
settings_ui::init(cx);
|
||||
keymap_editor::init(cx);
|
||||
extensions_ui::init(cx);
|
||||
zeta::init(cx);
|
||||
|
|
|
|||
Loading…
Reference in a new issue