diff --git a/crates/story/src/settings_story.rs b/crates/story/src/settings_story.rs index f8b21a90..2be02603 100644 --- a/crates/story/src/settings_story.rs +++ b/crates/story/src/settings_story.rs @@ -22,6 +22,7 @@ struct AppSettings { cli_path: SharedString, font_family: SharedString, font_size: f64, + line_height: f64, notifications_enabled: bool, auto_update: bool, resettable: bool, @@ -34,6 +35,7 @@ impl Default for AppSettings { cli_path: "/usr/local/bin/bash".into(), font_family: "Arial".into(), font_size: 14.0, + line_height: 12.0, notifications_enabled: true, auto_update: true, resettable: true, @@ -265,6 +267,24 @@ impl SettingsStory { .default_value(default_settings.font_size), ) .description("Adjust the font size for better readability."), + ) + .item( + SettingItem::new( + "Line Height", + SettingField::number_input( + NumberFieldOptions { + min: 8.0, + max: 32.0, + ..Default::default() + }, + |cx: &App| AppSettings::global(cx).line_height, + |val: f64, cx: &mut App| { + AppSettings::global_mut(cx).line_height = val; + }, + ) + .default_value(default_settings.line_height), + ) + .description("Adjust the line height for better readability."), ), SettingGroup::new().title("Other").items(vec![ SettingItem::render(|options, _, _| { diff --git a/crates/ui/src/setting/fields/number.rs b/crates/ui/src/setting/fields/number.rs index 1e419b27..382807d5 100644 --- a/crates/ui/src/setting/fields/number.rs +++ b/crates/ui/src/setting/fields/number.rs @@ -1,17 +1,17 @@ use std::rc::Rc; use gpui::{ - prelude::FluentBuilder as _, AnyElement, App, AppContext as _, Entity, IntoElement, - SharedString, StyleRefinement, Styled, Window, + AnyElement, App, AppContext as _, Entity, IntoElement, SharedString, StyleRefinement, Styled, + Window, prelude::FluentBuilder as _, }; use crate::{ + AxisExt, Sizable, StyledExt, input::{InputState, NumberInput, NumberInputEvent}, setting::{ - fields::{get_value, set_value, SettingFieldRender}, AnySettingField, RenderOptions, + fields::{SettingFieldRender, get_value, set_value}, }, - AxisExt, Sizable, StyledExt, }; #[derive(Clone, Debug)] @@ -65,35 +65,43 @@ impl SettingFieldRender for NumberField { let num_options = self.options.clone(); let state = window - .use_keyed_state("number-state", cx, |window, cx| { - let input = - cx.new(|cx| InputState::new(window, cx).default_value(value.to_string())); - let _subscription = cx.subscribe_in(&input, window, { - move |_, input, event: &NumberInputEvent, window, cx| match event { - NumberInputEvent::Step(action) => input.update(cx, |input, cx| { - let value = input.value(); - if let Ok(value) = value.parse::() { - let new_value = if *action == crate::input::StepAction::Increment { - (value + num_options.step).min(num_options.max) - } else { - (value - num_options.step).max(num_options.min) - }; - set_value(new_value, cx); - input.set_value( - SharedString::from(new_value.to_string()), - window, - cx, - ); - } - }), - } - }); + .use_keyed_state( + SharedString::from(format!( + "number-state-{}-{}-{}", + options.page_ix, options.group_ix, options.item_ix + )), + cx, + |window, cx| { + let input = + cx.new(|cx| InputState::new(window, cx).default_value(value.to_string())); + let _subscription = cx.subscribe_in(&input, window, { + move |_, input, event: &NumberInputEvent, window, cx| match event { + NumberInputEvent::Step(action) => input.update(cx, |input, cx| { + let value = input.value(); + if let Ok(value) = value.parse::() { + let new_value = + if *action == crate::input::StepAction::Increment { + (value + num_options.step).min(num_options.max) + } else { + (value - num_options.step).max(num_options.min) + }; + set_value(new_value, cx); + input.set_value( + SharedString::from(new_value.to_string()), + window, + cx, + ); + } + }), + } + }); - State { - input, - _subscription, - } - }) + State { + input, + _subscription, + } + }, + ) .read(cx); NumberInput::new(&state.input) diff --git a/crates/ui/src/setting/fields/string.rs b/crates/ui/src/setting/fields/string.rs index d7a222b5..dd96805f 100644 --- a/crates/ui/src/setting/fields/string.rs +++ b/crates/ui/src/setting/fields/string.rs @@ -1,17 +1,17 @@ use std::rc::Rc; use gpui::{ - prelude::FluentBuilder as _, AnyElement, App, AppContext as _, Entity, IntoElement, - SharedString, StyleRefinement, Styled, Window, + AnyElement, App, AppContext as _, Entity, IntoElement, SharedString, StyleRefinement, Styled, + Window, prelude::FluentBuilder as _, }; use crate::{ + AxisExt as _, Sizable, StyledExt, input::{Input, InputEvent, InputState}, setting::{ - fields::{get_value, set_value, SettingFieldRender}, AnySettingField, RenderOptions, + fields::{SettingFieldRender, get_value, set_value}, }, - AxisExt as _, Sizable, StyledExt, }; pub(crate) struct StringField { @@ -47,23 +47,30 @@ where let set_value = set_value::(&field, cx); let state = window - .use_keyed_state("string-state", cx, |window, cx| { - let input = cx.new(|cx| InputState::new(window, cx).default_value(value)); - let _subscription = cx.subscribe(&input, { - move |_, input, event: &InputEvent, cx| match event { - InputEvent::Change => { - let value = input.read(cx).value(); - set_value(value.into(), cx); + .use_keyed_state( + SharedString::from(format!( + "string-state-{}-{}-{}", + options.page_ix, options.group_ix, options.item_ix + )), + cx, + |window, cx| { + let input = cx.new(|cx| InputState::new(window, cx).default_value(value)); + let _subscription = cx.subscribe(&input, { + move |_, input, event: &InputEvent, cx| match event { + InputEvent::Change => { + let value = input.read(cx).value(); + set_value(value.into(), cx); + } + _ => {} } - _ => {} - } - }); + }); - State { - input, - _subscription, - } - }) + State { + input, + _subscription, + } + }, + ) .read(cx); Input::new(&state.input) diff --git a/crates/ui/src/setting/group.rs b/crates/ui/src/setting/group.rs index a2511058..36ebf187 100644 --- a/crates/ui/src/setting/group.rs +++ b/crates/ui/src/setting/group.rs @@ -1,13 +1,14 @@ use gpui::{ - prelude::FluentBuilder as _, App, IntoElement, ParentElement as _, SharedString, - StyleRefinement, Styled, Window, + App, IntoElement, ParentElement as _, SharedString, StyleRefinement, Styled, Window, + prelude::FluentBuilder as _, }; use crate::{ + ActiveTheme, StyledExt, group_box::{GroupBox, GroupBoxVariants}, label::Label, setting::{RenderOptions, SettingItem}, - v_flex, ActiveTheme, StyledExt, + v_flex, }; /// A setting group that can contain multiple setting items. @@ -75,14 +76,13 @@ impl SettingGroup { pub(crate) fn render( self, - group_ix: usize, query: &str, options: &RenderOptions, window: &mut Window, cx: &mut App, ) -> impl IntoElement { GroupBox::new() - .id(SharedString::from(format!("group-{}", group_ix))) + .id(SharedString::from(format!("group-{}", options.group_ix))) .with_variant(options.group_variant) .when_some(self.title.clone(), |this, title| { this.title(v_flex().gap_1().child(title).when_some( @@ -99,7 +99,14 @@ impl SettingGroup { .gap_4() .children(self.items.iter().enumerate().filter_map(|(item_ix, item)| { if item.is_match(&query) { - Some(item.clone().render_item(item_ix, options, window, cx)) + Some(item.clone().render_item( + &RenderOptions { + item_ix, + ..*options + }, + window, + cx, + )) } else { None } diff --git a/crates/ui/src/setting/item.rs b/crates/ui/src/setting/item.rs index 5ab04f01..c466937f 100644 --- a/crates/ui/src/setting/item.rs +++ b/crates/ui/src/setting/item.rs @@ -150,13 +150,12 @@ impl SettingItem { pub(super) fn render_item( self, - ix: usize, options: &RenderOptions, window: &mut Window, cx: &mut App, ) -> Stateful
{ div() - .id(SharedString::from(format!("item-{}", ix))) + .id(SharedString::from(format!("item-{}", options.item_ix))) .w_full() .child(match self { SettingItem::Item { diff --git a/crates/ui/src/setting/page.rs b/crates/ui/src/setting/page.rs index 34a10ddf..13805871 100644 --- a/crates/ui/src/setting/page.rs +++ b/crates/ui/src/setting/page.rs @@ -167,11 +167,20 @@ impl SettingPage { list(list_state.clone(), { let query = query.clone(); let options = *options; - move |ix, window, cx| { - let group = groups[ix].clone(); + move |group_ix, window, cx| { + let group = groups[group_ix].clone(); group .py_4() - .render(ix, &query, &options, window, cx) + .render( + &query, + &RenderOptions { + page_ix: ix, + group_ix, + ..options + }, + window, + cx, + ) .into_any_element() } }) diff --git a/crates/ui/src/setting/settings.rs b/crates/ui/src/setting/settings.rs index d039bff4..0f4052d0 100644 --- a/crates/ui/src/setting/settings.rs +++ b/crates/ui/src/setting/settings.rs @@ -1,14 +1,14 @@ use crate::{ + IconName, Sizable, Size, StyledExt, group_box::GroupBoxVariant, input::{Input, InputState}, resizable::{h_resizable, resizable_panel}, setting::{SettingGroup, SettingPage}, sidebar::{Sidebar, SidebarMenu, SidebarMenuItem}, - IconName, Sizable, Size, StyledExt, }; use gpui::{ - div, prelude::FluentBuilder as _, px, relative, App, AppContext as _, Axis, ElementId, Entity, - IntoElement, ParentElement as _, Pixels, RenderOnce, StyleRefinement, Styled, Window, + App, AppContext as _, Axis, ElementId, Entity, IntoElement, ParentElement as _, Pixels, + RenderOnce, StyleRefinement, Styled, Window, div, prelude::FluentBuilder as _, px, relative, }; use rust_i18n::t; @@ -221,6 +221,9 @@ pub(super) struct SettingsState { /// Options for rendering setting item. #[derive(Clone, Copy)] pub struct RenderOptions { + pub page_ix: usize, + pub group_ix: usize, + pub item_ix: usize, pub size: Size, pub group_variant: GroupBoxVariant, pub layout: Axis, @@ -251,6 +254,9 @@ impl RenderOnce for Settings { let query = state.read(cx).search_input.read(cx).value(); let filtered_pages = self.filtered_pages(&query); let options = RenderOptions { + page_ix: 0, + group_ix: 0, + item_ix: 0, size: self.size, group_variant: self.group_variant, layout: Axis::Horizontal,