setting: Use precise subscripts for use_keyed_state (#1735)
This commit is contained in:
parent
a50b1e9341
commit
514aea00be
7 changed files with 121 additions and 65 deletions
|
|
@ -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, _, _| {
|
||||
|
|
|
|||
|
|
@ -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::<f64>() {
|
||||
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::<f64>() {
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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<T> {
|
||||
|
|
@ -47,23 +47,30 @@ where
|
|||
let set_value = set_value::<T>(&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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,13 +150,12 @@ impl SettingItem {
|
|||
|
||||
pub(super) fn render_item(
|
||||
self,
|
||||
ix: usize,
|
||||
options: &RenderOptions,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Stateful<Div> {
|
||||
div()
|
||||
.id(SharedString::from(format!("item-{}", ix)))
|
||||
.id(SharedString::from(format!("item-{}", options.item_ix)))
|
||||
.w_full()
|
||||
.child(match self {
|
||||
SettingItem::Item {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue