settings_ui: Filter to get project settings (#39730)

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Ben Kunkle
2025-10-07 21:36:40 -04:00
committed by GitHub
co-authored by Danilo Leal Mikayla Maki
parent 69ac003bc9
commit f652c3a14d
2 changed files with 1354 additions and 1660 deletions
File diff suppressed because it is too large Load Diff
+104 -12
View File
@@ -673,6 +673,55 @@ struct SettingItem {
description: &'static str,
field: Box<dyn AnySettingField>,
metadata: Option<Box<SettingsFieldMetadata>>,
files: FileMask,
}
#[derive(PartialEq, Eq, Clone, Copy)]
struct FileMask(u8);
impl std::fmt::Debug for FileMask {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "FileMask(")?;
let mut items = vec![];
if self.contains(USER) {
items.push("USER");
}
if self.contains(LOCAL) {
items.push("LOCAL");
}
if self.contains(SERVER) {
items.push("SERVER");
}
write!(f, "{})", items.join(" | "))
}
}
const USER: FileMask = FileMask(1 << 0);
const LOCAL: FileMask = FileMask(1 << 2);
const SERVER: FileMask = FileMask(1 << 3);
impl std::ops::BitAnd for FileMask {
type Output = Self;
fn bitand(self, other: Self) -> Self {
Self(self.0 & other.0)
}
}
impl std::ops::BitOr for FileMask {
type Output = Self;
fn bitor(self, other: Self) -> Self {
Self(self.0 | other.0)
}
}
impl FileMask {
fn contains(&self, other: FileMask) -> bool {
self.0 & other.0 != 0
}
}
impl PartialEq for SettingItem {
@@ -690,6 +739,7 @@ impl PartialEq for SettingItem {
#[derive(Clone)]
struct SubPageLink {
title: &'static str,
files: FileMask,
render: Arc<
dyn Fn(&mut SettingsWindow, &mut Window, &mut Context<SettingsWindow>) -> AnyElement
+ 'static
@@ -713,14 +763,6 @@ enum SettingsUiFile {
}
impl SettingsUiFile {
fn pages(&self) -> Vec<SettingsPage> {
match self {
SettingsUiFile::User => page_data::user_settings_data(),
SettingsUiFile::Local(_) => page_data::project_settings_data(),
SettingsUiFile::Server(_) => page_data::user_settings_data(),
}
}
fn name(&self) -> SharedString {
match self {
SettingsUiFile::User => SharedString::new_static("User"),
@@ -748,6 +790,14 @@ impl SettingsUiFile {
SettingsUiFile::Server(_) => settings::SettingsFile::Server,
}
}
fn mask(&self) -> FileMask {
match self {
SettingsUiFile::User => USER,
SettingsUiFile::Local(_) => LOCAL,
SettingsUiFile::Server(_) => SERVER,
}
}
}
impl SettingsWindow {
@@ -939,6 +989,45 @@ impl SettingsWindow {
})
}
fn filter_matches_to_file(&mut self) {
let current_file = self.current_file.mask();
for (page, page_filter) in std::iter::zip(&self.pages, &mut self.search_matches) {
let mut header_index = 0;
let mut any_found_since_last_header = true;
for (index, item) in page.items.iter().enumerate() {
match item {
SettingsPageItem::SectionHeader(_) => {
if !any_found_since_last_header {
page_filter[header_index] = false;
}
header_index = index;
any_found_since_last_header = false;
}
SettingsPageItem::SettingItem(setting_item) => {
if !setting_item.files.contains(current_file) {
page_filter[index] = false;
} else {
any_found_since_last_header = true;
}
}
SettingsPageItem::SubPageLink(sub_page_link) => {
if !sub_page_link.files.contains(current_file) {
page_filter[index] = false;
} else {
any_found_since_last_header = true;
}
}
}
}
if let Some(last_header) = page_filter.get_mut(header_index)
&& !any_found_since_last_header
{
*last_header = false;
}
}
}
fn update_matches(&mut self, cx: &mut Context<SettingsWindow>) {
self.search_task.take();
let query = self.search_bar.read(cx).text(cx);
@@ -946,6 +1035,7 @@ impl SettingsWindow {
for page in &mut self.search_matches {
page.fill(true);
}
self.filter_matches_to_file();
cx.notify();
return;
}
@@ -1011,6 +1101,7 @@ impl SettingsWindow {
page[header_index] = true;
page[item_index] = true;
}
this.filter_matches_to_file();
let first_navbar_entry_index = this
.visible_navbar_entries()
.next()
@@ -1032,13 +1123,13 @@ impl SettingsWindow {
}
fn build_ui(&mut self, cx: &mut Context<SettingsWindow>) {
self.pages = self.current_file.pages();
if self.pages.is_empty() {
self.pages = page_data::settings_data();
}
self.build_search_matches();
self.build_navbar();
if !self.search_bar.read(cx).is_empty(cx) {
self.update_matches(cx);
}
self.update_matches(cx);
cx.notify();
}
@@ -1878,6 +1969,7 @@ mod test {
impl SettingsPageItem {
fn basic_item(title: &'static str, description: &'static str) -> Self {
SettingsPageItem::SettingItem(SettingItem {
files: USER,
title,
description,
field: Box::new(SettingField {