diff --git a/crates/settings_ui/src/components/dropdown.rs b/crates/settings_ui/src/components/dropdown.rs index ec9ecb4eaf..010a8ec0c0 100644 --- a/crates/settings_ui/src/components/dropdown.rs +++ b/crates/settings_ui/src/components/dropdown.rs @@ -17,7 +17,7 @@ where labels: &'static [&'static str], should_do_title_case: bool, tab_index: Option, - on_change: Rc, + on_change: Rc, } impl EnumVariantDropdown @@ -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); }, ); } diff --git a/crates/settings_ui/src/components/font_picker.rs b/crates/settings_ui/src/components/font_picker.rs index 7a79009efd..564d98c6d2 100644 --- a/crates/settings_ui/src/components/font_picker.rs +++ b/crates/settings_ui/src/components/font_picker.rs @@ -13,13 +13,13 @@ pub struct FontPickerDelegate { filtered_fonts: Vec, selected_index: usize, current_font: SharedString, - on_font_changed: Arc, + on_font_changed: Arc, } 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, ) -> 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) { + fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context) { 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 { diff --git a/crates/settings_ui/src/components/icon_theme_picker.rs b/crates/settings_ui/src/components/icon_theme_picker.rs index 33a648f81b..f369a8207d 100644 --- a/crates/settings_ui/src/components/icon_theme_picker.rs +++ b/crates/settings_ui/src/components/icon_theme_picker.rs @@ -13,13 +13,13 @@ pub struct IconThemePickerDelegate { filtered_themes: Vec, selected_index: usize, current_theme: SharedString, - on_theme_changed: Arc, + on_theme_changed: Arc, } 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, ) -> 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) { - 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, + ) { + 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 { - "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 = 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, ) { 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, ) -> Option { - 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 { diff --git a/crates/settings_ui/src/components/input_field.rs b/crates/settings_ui/src/components/input_field.rs index 575da7f7ae..17afe89029 100644 --- a/crates/settings_ui/src/components/input_field.rs +++ b/crates/settings_ui/src/components/input_field.rs @@ -9,7 +9,7 @@ use ui::{ pub struct SettingsInputField { initial_text: Option, placeholder: Option<&'static str>, - confirm: Option, &mut App)>>, + confirm: Option, &mut Window, &mut App)>>, tab_index: Option, } @@ -34,7 +34,10 @@ impl SettingsInputField { self } - pub fn on_confirm(mut self, confirm: impl Fn(Option, &mut App) + 'static) -> Self { + pub fn on_confirm( + mut self, + confirm: impl Fn(Option, &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::({ - 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); } }) }) diff --git a/crates/settings_ui/src/components/theme_picker.rs b/crates/settings_ui/src/components/theme_picker.rs index 2146ab314f..a1f1339a7a 100644 --- a/crates/settings_ui/src/components/theme_picker.rs +++ b/crates/settings_ui/src/components/theme_picker.rs @@ -13,13 +13,13 @@ pub struct ThemePickerDelegate { filtered_themes: Vec, selected_index: usize, current_theme: SharedString, - on_theme_changed: Arc, + on_theme_changed: Arc, } 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, ) -> 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) { + fn confirm(&mut self, _secondary: bool, window: &mut Window, cx: &mut Context) { 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 { diff --git a/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs b/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs index fb8f967613..f560e29b2f 100644 --- a/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs +++ b/crates/settings_ui/src/pages/edit_prediction_provider_setup.rs @@ -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); }), ), diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 319da85fcd..f1b82a9102 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -154,7 +154,7 @@ trait AnySettingField { current_file: &SettingsUiFile, file_set_in: &settings::SettingsFile, cx: &App, - ) -> Option>; + ) -> Option>; fn json_path(&self) -> Option<&'static str>; } @@ -184,7 +184,7 @@ impl AnySettingField for SettingFi current_file: &SettingsUiFile, file_set_in: &settings::SettingsFile, cx: &App, - ) -> Option> { + ) -> Option> { if file_set_in == &settings::SettingsFile::Default { return None; } @@ -203,7 +203,7 @@ impl 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 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::() + .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 + Into + AsRef + 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 + From + 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( 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)(