pipe window through to update settings file
This commit is contained in:
@@ -17,7 +17,7 @@ where
|
||||
labels: &'static [&'static str],
|
||||
should_do_title_case: bool,
|
||||
tab_index: Option<isize>,
|
||||
on_change: Rc<dyn Fn(T, &mut App) + 'static>,
|
||||
on_change: Rc<dyn Fn(T, &mut ui::Window, &mut App) + 'static>,
|
||||
}
|
||||
|
||||
impl<T> EnumVariantDropdown<T>
|
||||
@@ -29,7 +29,7 @@ where
|
||||
current_value: T,
|
||||
variants: &'static [T],
|
||||
labels: &'static [&'static str],
|
||||
on_change: impl Fn(T, &mut App) + 'static,
|
||||
on_change: impl Fn(T, &mut ui::Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
@@ -78,8 +78,8 @@ where
|
||||
value == current_value,
|
||||
IconPosition::End,
|
||||
None,
|
||||
move |_, cx| {
|
||||
on_change(value, cx);
|
||||
move |window, cx| {
|
||||
on_change(value, window, cx);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ pub struct FontPickerDelegate {
|
||||
filtered_fonts: Vec<StringMatch>,
|
||||
selected_index: usize,
|
||||
current_font: SharedString,
|
||||
on_font_changed: Arc<dyn Fn(SharedString, &mut App) + 'static>,
|
||||
on_font_changed: Arc<dyn Fn(SharedString, &mut Window, &mut App) + 'static>,
|
||||
}
|
||||
|
||||
impl FontPickerDelegate {
|
||||
fn new(
|
||||
current_font: SharedString,
|
||||
on_font_changed: impl Fn(SharedString, &mut App) + 'static,
|
||||
on_font_changed: impl Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||
cx: &mut Context<FontPicker>,
|
||||
) -> Self {
|
||||
let font_family_cache = FontFamilyCache::global(cx);
|
||||
@@ -132,10 +132,10 @@ impl PickerDelegate for FontPickerDelegate {
|
||||
Task::ready(())
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _secondary: bool, _window: &mut Window, cx: &mut Context<FontPicker>) {
|
||||
fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<FontPicker>) {
|
||||
if let Some(font_match) = self.filtered_fonts.get(self.selected_index) {
|
||||
let font = font_match.string.clone();
|
||||
(self.on_font_changed)(font.into(), cx);
|
||||
(self.on_font_changed)(font.into(), window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ impl PickerDelegate for FontPickerDelegate {
|
||||
|
||||
pub fn font_picker(
|
||||
current_font: SharedString,
|
||||
on_font_changed: impl Fn(SharedString, &mut App) + 'static,
|
||||
on_font_changed: impl Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<FontPicker>,
|
||||
) -> FontPicker {
|
||||
|
||||
@@ -13,13 +13,13 @@ pub struct IconThemePickerDelegate {
|
||||
filtered_themes: Vec<StringMatch>,
|
||||
selected_index: usize,
|
||||
current_theme: SharedString,
|
||||
on_theme_changed: Arc<dyn Fn(SharedString, &mut App) + 'static>,
|
||||
on_theme_changed: Arc<dyn Fn(SharedString, &mut Window, &mut App) + 'static>,
|
||||
}
|
||||
|
||||
impl IconThemePickerDelegate {
|
||||
fn new(
|
||||
current_theme: SharedString,
|
||||
on_theme_changed: impl Fn(SharedString, &mut App) + 'static,
|
||||
on_theme_changed: impl Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||
cx: &mut Context<IconThemePicker>,
|
||||
) -> Self {
|
||||
let theme_registry = ThemeRegistry::global(cx);
|
||||
@@ -32,15 +32,15 @@ impl IconThemePickerDelegate {
|
||||
|
||||
let selected_index = icon_themes
|
||||
.iter()
|
||||
.position(|icon_themes| *icon_themes == current_theme)
|
||||
.position(|icon_theme| *icon_theme == current_theme)
|
||||
.unwrap_or(0);
|
||||
|
||||
let filtered_themes = icon_themes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, icon_themes)| StringMatch {
|
||||
.map(|(index, theme)| StringMatch {
|
||||
candidate_id: index,
|
||||
string: icon_themes.to_string(),
|
||||
string: theme.to_string(),
|
||||
positions: Vec::new(),
|
||||
score: 0.0,
|
||||
})
|
||||
@@ -67,13 +67,18 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
self.selected_index
|
||||
}
|
||||
|
||||
fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<IconThemePicker>) {
|
||||
self.selected_index = ix.min(self.filtered_themes.len().saturating_sub(1));
|
||||
fn set_selected_index(
|
||||
&mut self,
|
||||
index: usize,
|
||||
_window: &mut Window,
|
||||
cx: &mut Context<IconThemePicker>,
|
||||
) {
|
||||
self.selected_index = index.min(self.filtered_themes.len().saturating_sub(1));
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
|
||||
"Search icon theme…".into()
|
||||
"Search icon themes…".into()
|
||||
}
|
||||
|
||||
fn update_matches(
|
||||
@@ -89,9 +94,9 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
icon_themes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, icon_theme)| StringMatch {
|
||||
.map(|(index, theme)| StringMatch {
|
||||
candidate_id: index,
|
||||
string: icon_theme.to_string(),
|
||||
string: theme.to_string(),
|
||||
positions: Vec::new(),
|
||||
score: 0.0,
|
||||
})
|
||||
@@ -100,16 +105,16 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
let _candidates: Vec<StringMatchCandidate> = icon_themes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(id, icon_theme)| StringMatchCandidate::new(id, icon_theme.as_ref()))
|
||||
.map(|(id, theme)| StringMatchCandidate::new(id, theme.as_ref()))
|
||||
.collect();
|
||||
|
||||
icon_themes
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, icon_theme)| icon_theme.to_lowercase().contains(&query.to_lowercase()))
|
||||
.map(|(index, icon_theme)| StringMatch {
|
||||
.filter(|(_, theme)| theme.to_lowercase().contains(&query.to_lowercase()))
|
||||
.map(|(index, theme)| StringMatch {
|
||||
candidate_id: index,
|
||||
string: icon_theme.to_string(),
|
||||
string: theme.to_string(),
|
||||
positions: Vec::new(),
|
||||
score: 0.0,
|
||||
})
|
||||
@@ -119,7 +124,7 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
let selected_index = if query.is_empty() {
|
||||
icon_themes
|
||||
.iter()
|
||||
.position(|icon_theme| *icon_theme == current_theme)
|
||||
.position(|theme| *theme == current_theme)
|
||||
.unwrap_or(0)
|
||||
} else {
|
||||
matches
|
||||
@@ -138,12 +143,12 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
fn confirm(
|
||||
&mut self,
|
||||
_secondary: bool,
|
||||
_window: &mut Window,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<IconThemePicker>,
|
||||
) {
|
||||
if let Some(theme_match) = self.filtered_themes.get(self.selected_index) {
|
||||
let theme = theme_match.string.clone();
|
||||
(self.on_theme_changed)(theme.into(), cx);
|
||||
(self.on_theme_changed)(theme.into(), window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,15 +161,15 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
|
||||
fn render_match(
|
||||
&self,
|
||||
ix: usize,
|
||||
index: usize,
|
||||
selected: bool,
|
||||
_window: &mut Window,
|
||||
_cx: &mut Context<IconThemePicker>,
|
||||
) -> Option<Self::ListItem> {
|
||||
let theme_match = self.filtered_themes.get(ix)?;
|
||||
let theme_match = self.filtered_themes.get(index)?;
|
||||
|
||||
Some(
|
||||
ListItem::new(ix)
|
||||
ListItem::new(index)
|
||||
.inset(true)
|
||||
.spacing(ListItemSpacing::Sparse)
|
||||
.toggle_state(selected)
|
||||
@@ -176,7 +181,7 @@ impl PickerDelegate for IconThemePickerDelegate {
|
||||
|
||||
pub fn icon_theme_picker(
|
||||
current_theme: SharedString,
|
||||
on_theme_changed: impl Fn(SharedString, &mut App) + 'static,
|
||||
on_theme_changed: impl Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<IconThemePicker>,
|
||||
) -> IconThemePicker {
|
||||
|
||||
@@ -9,7 +9,7 @@ use ui::{
|
||||
pub struct SettingsInputField {
|
||||
initial_text: Option<String>,
|
||||
placeholder: Option<&'static str>,
|
||||
confirm: Option<Box<dyn Fn(Option<String>, &mut App)>>,
|
||||
confirm: Option<Box<dyn Fn(Option<String>, &mut Window, &mut App)>>,
|
||||
tab_index: Option<isize>,
|
||||
}
|
||||
|
||||
@@ -34,7 +34,10 @@ impl SettingsInputField {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_confirm(mut self, confirm: impl Fn(Option<String>, &mut App) + 'static) -> Self {
|
||||
pub fn on_confirm(
|
||||
mut self,
|
||||
confirm: impl Fn(Option<String>, &mut Window, &mut App) + 'static,
|
||||
) -> Self {
|
||||
self.confirm = Some(Box::new(confirm));
|
||||
self
|
||||
}
|
||||
@@ -83,13 +86,13 @@ impl RenderOnce for SettingsInputField {
|
||||
.child(editor)
|
||||
.when_some(self.confirm, |this, confirm| {
|
||||
this.on_action::<menu::Confirm>({
|
||||
move |_, _, cx| {
|
||||
move |_, window, 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);
|
||||
confirm(new_value, cx);
|
||||
confirm(new_value, window, cx);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,13 +13,13 @@ pub struct ThemePickerDelegate {
|
||||
filtered_themes: Vec<StringMatch>,
|
||||
selected_index: usize,
|
||||
current_theme: SharedString,
|
||||
on_theme_changed: Arc<dyn Fn(SharedString, &mut App) + 'static>,
|
||||
on_theme_changed: Arc<dyn Fn(SharedString, &mut Window, &mut App) + 'static>,
|
||||
}
|
||||
|
||||
impl ThemePickerDelegate {
|
||||
fn new(
|
||||
current_theme: SharedString,
|
||||
on_theme_changed: impl Fn(SharedString, &mut App) + 'static,
|
||||
on_theme_changed: impl Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||
cx: &mut Context<ThemePicker>,
|
||||
) -> Self {
|
||||
let theme_registry = ThemeRegistry::global(cx);
|
||||
@@ -130,10 +130,10 @@ impl PickerDelegate for ThemePickerDelegate {
|
||||
Task::ready(())
|
||||
}
|
||||
|
||||
fn confirm(&mut self, _secondary: bool, _window: &mut Window, cx: &mut Context<ThemePicker>) {
|
||||
fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context<ThemePicker>) {
|
||||
if let Some(theme_match) = self.filtered_themes.get(self.selected_index) {
|
||||
let theme = theme_match.string.clone();
|
||||
(self.on_theme_changed)(theme.into(), cx);
|
||||
(self.on_theme_changed)(theme.into(), window, cx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ impl PickerDelegate for ThemePickerDelegate {
|
||||
|
||||
pub fn theme_picker(
|
||||
current_theme: SharedString,
|
||||
on_theme_changed: impl Fn(SharedString, &mut App) + 'static,
|
||||
on_theme_changed: impl Fn(SharedString, &mut Window, &mut App) + 'static,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<ThemePicker>,
|
||||
) -> ThemePicker {
|
||||
|
||||
@@ -217,7 +217,7 @@ fn render_api_key_provider(
|
||||
SettingsInputField::new()
|
||||
.tab_index(0)
|
||||
.with_placeholder("xxxxxxxxxxxxxxxxxxxx")
|
||||
.on_confirm(move |api_key, cx| {
|
||||
.on_confirm(move |api_key, _window, cx| {
|
||||
write_key(api_key.filter(|key| !key.is_empty()), cx);
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -154,7 +154,7 @@ trait AnySettingField {
|
||||
current_file: &SettingsUiFile,
|
||||
file_set_in: &settings::SettingsFile,
|
||||
cx: &App,
|
||||
) -> Option<Box<dyn Fn(&mut App)>>;
|
||||
) -> Option<Box<dyn Fn(&mut Window, &mut App)>>;
|
||||
|
||||
fn json_path(&self) -> Option<&'static str>;
|
||||
}
|
||||
@@ -184,7 +184,7 @@ impl<T: PartialEq + Clone + Send + Sync + 'static> AnySettingField for SettingFi
|
||||
current_file: &SettingsUiFile,
|
||||
file_set_in: &settings::SettingsFile,
|
||||
cx: &App,
|
||||
) -> Option<Box<dyn Fn(&mut App)>> {
|
||||
) -> Option<Box<dyn Fn(&mut Window, &mut App)>> {
|
||||
if file_set_in == &settings::SettingsFile::Default {
|
||||
return None;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ impl<T: PartialEq + Clone + Send + Sync + 'static> AnySettingField for SettingFi
|
||||
}
|
||||
let current_file = current_file.clone();
|
||||
|
||||
return Some(Box::new(move |cx| {
|
||||
return Some(Box::new(move |window, cx| {
|
||||
let store = SettingsStore::global(cx);
|
||||
let default_value = (this.pick)(store.raw_default_settings());
|
||||
let is_set_somewhere_other_than_default = store
|
||||
@@ -215,9 +215,15 @@ impl<T: PartialEq + Clone + Send + Sync + 'static> AnySettingField for SettingFi
|
||||
} else {
|
||||
None
|
||||
};
|
||||
update_settings_file(current_file.clone(), None, cx, move |settings, _| {
|
||||
(this.write)(settings, value_to_set);
|
||||
})
|
||||
update_settings_file(
|
||||
current_file.clone(),
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _| {
|
||||
(this.write)(settings, value_to_set);
|
||||
},
|
||||
)
|
||||
// todo(settings_ui): Don't log err
|
||||
.log_err();
|
||||
}));
|
||||
@@ -1068,8 +1074,8 @@ fn render_settings_item(
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(Tooltip::text("Reset to Default"))
|
||||
.on_click({
|
||||
move |_, _, cx| {
|
||||
reset_to_default(cx);
|
||||
move |_, window, cx| {
|
||||
reset_to_default(window, cx);
|
||||
}
|
||||
}),
|
||||
)
|
||||
@@ -3544,20 +3550,33 @@ fn all_projects(
|
||||
fn update_settings_file(
|
||||
file: SettingsUiFile,
|
||||
file_name: Option<&'static str>,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
update: impl 'static + Send + FnOnce(&mut SettingsContent, &App),
|
||||
) -> Result<()> {
|
||||
telemetry::event!("Settings Change", setting = file_name, type = file.setting_type());
|
||||
|
||||
let original_workspace_window =
|
||||
window
|
||||
.root::<SettingsWindow>()
|
||||
.flatten()
|
||||
.and_then(|settings_window| {
|
||||
settings_window.read_with(cx, |settings_window, _cx| {
|
||||
settings_window.original_window.clone()
|
||||
})
|
||||
});
|
||||
|
||||
match file {
|
||||
SettingsUiFile::Project((worktree_id, rel_path)) => {
|
||||
let rel_path = rel_path.join(paths::local_settings_file_relative_path());
|
||||
let Some((worktree, project)) = all_projects(None, cx).find_map(|project| {
|
||||
project
|
||||
.read(cx)
|
||||
.worktree_for_id(worktree_id, cx)
|
||||
.zip(Some(project))
|
||||
}) else {
|
||||
let Some((worktree, project)) = all_projects(original_workspace_window.as_ref(), cx)
|
||||
.find_map(|project| {
|
||||
project
|
||||
.read(cx)
|
||||
.worktree_for_id(worktree_id, cx)
|
||||
.zip(Some(project))
|
||||
})
|
||||
else {
|
||||
anyhow::bail!("Could not find project with worktree id: {}", worktree_id);
|
||||
};
|
||||
|
||||
@@ -3618,10 +3637,16 @@ fn render_text_field<T: From<String> + Into<String> + AsRef<str> + Clone>(
|
||||
|editor, placeholder| editor.with_placeholder(placeholder),
|
||||
)
|
||||
.on_confirm({
|
||||
move |new_text, cx| {
|
||||
update_settings_file(file.clone(), field.json_path, cx, move |settings, _cx| {
|
||||
(field.write)(settings, new_text.map(Into::into));
|
||||
})
|
||||
move |new_text, window, cx| {
|
||||
update_settings_file(
|
||||
file.clone(),
|
||||
field.json_path,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _cx| {
|
||||
(field.write)(settings, new_text.map(Into::into));
|
||||
},
|
||||
)
|
||||
.log_err(); // todo(settings_ui) don't log err
|
||||
}
|
||||
})
|
||||
@@ -3646,11 +3671,11 @@ fn render_toggle_button<B: Into<bool> + From<bool> + Copy>(
|
||||
Switch::new("toggle_button", toggle_state)
|
||||
.tab_index(0_isize)
|
||||
.on_click({
|
||||
move |state, _window, cx| {
|
||||
move |state, window, cx| {
|
||||
telemetry::event!("Settings Change", setting = field.json_path, type = file.setting_type());
|
||||
|
||||
let state = *state == ui::ToggleState::Selected;
|
||||
update_settings_file(file.clone(), field.json_path, cx, move |settings, _cx| {
|
||||
update_settings_file(file.clone(), field.json_path, window, cx, move |settings, _cx| {
|
||||
(field.write)(settings, Some(state.into()));
|
||||
})
|
||||
.log_err(); // todo(settings_ui) don't log err
|
||||
@@ -3670,11 +3695,17 @@ fn render_number_field<T: NumberFieldType + Send + Sync>(
|
||||
let value = value.copied().unwrap_or_else(T::min_value);
|
||||
NumberField::new("numeric_stepper", value, window, cx)
|
||||
.on_change({
|
||||
move |value, _window, cx| {
|
||||
move |value, window, cx| {
|
||||
let value = *value;
|
||||
update_settings_file(file.clone(), field.json_path, cx, move |settings, _cx| {
|
||||
(field.write)(settings, Some(value));
|
||||
})
|
||||
update_settings_file(
|
||||
file.clone(),
|
||||
field.json_path,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _cx| {
|
||||
(field.write)(settings, Some(value));
|
||||
},
|
||||
)
|
||||
.log_err(); // todo(settings_ui) don't log err
|
||||
}
|
||||
})
|
||||
@@ -3702,13 +3733,19 @@ where
|
||||
let current_value = current_value.copied().unwrap_or(variants()[0]);
|
||||
|
||||
EnumVariantDropdown::new("dropdown", current_value, variants(), labels(), {
|
||||
move |value, cx| {
|
||||
move |value, window, cx| {
|
||||
if value == current_value {
|
||||
return;
|
||||
}
|
||||
update_settings_file(file.clone(), field.json_path, cx, move |settings, _cx| {
|
||||
(field.write)(settings, Some(value));
|
||||
})
|
||||
update_settings_file(
|
||||
file.clone(),
|
||||
field.json_path,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _cx| {
|
||||
(field.write)(settings, Some(value));
|
||||
},
|
||||
)
|
||||
.log_err(); // todo(settings_ui) don't log err
|
||||
}
|
||||
})
|
||||
@@ -3753,10 +3790,11 @@ fn render_font_picker(
|
||||
Some(cx.new(move |cx| {
|
||||
font_picker(
|
||||
current_value.clone().into(),
|
||||
move |font_name, cx| {
|
||||
move |font_name, window, cx| {
|
||||
update_settings_file(
|
||||
file.clone(),
|
||||
field.json_path,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _cx| {
|
||||
(field.write)(settings, Some(font_name.into()));
|
||||
@@ -3802,10 +3840,11 @@ fn render_theme_picker(
|
||||
let current_value = current_value.clone();
|
||||
theme_picker(
|
||||
current_value,
|
||||
move |theme_name, cx| {
|
||||
move |theme_name, window, cx| {
|
||||
update_settings_file(
|
||||
file.clone(),
|
||||
field.json_path,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _cx| {
|
||||
(field.write)(
|
||||
@@ -3854,10 +3893,11 @@ fn render_icon_theme_picker(
|
||||
let current_value = current_value.clone();
|
||||
icon_theme_picker(
|
||||
current_value,
|
||||
move |theme_name, cx| {
|
||||
move |theme_name, window, cx| {
|
||||
update_settings_file(
|
||||
file.clone(),
|
||||
field.json_path,
|
||||
window,
|
||||
cx,
|
||||
move |settings, _cx| {
|
||||
(field.write)(
|
||||
|
||||
Reference in New Issue
Block a user