From 2bb11a0af2e8ee8041f3519ca6b7e9271dc4e186 Mon Sep 17 00:00:00 2001 From: Raymond Zhao <7199958+rzhao271@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:11:38 -0800 Subject: [PATCH] fix: filter interaction with settings search regressed (#293187) --- .../preferences/browser/settingsEditor2.ts | 16 ++++----- .../preferences/browser/settingsTree.ts | 33 +++++++++---------- .../preferences/browser/settingsTreeModels.ts | 2 +- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index d9e1f30bd11..5f8db4b627d 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -879,7 +879,7 @@ export class SettingsEditor2 extends EditorPane { // If the target display category is different than the source's, unfocus the category // so that we can render all found settings again. // Then, the reveal call will correctly find the target setting. - if (this.viewState.filterToCategory && evt.source.displayCategory !== targetElement.displayCategory) { + if (this.viewState.categoryFilter && evt.source.displayCategory !== targetElement.displayCategory) { this.tocTree.setFocus([]); } try { @@ -1054,8 +1054,8 @@ export class SettingsEditor2 extends EditorPane { const scrollBehavior = this.configurationService.getValue<'paginated' | 'continuous'>(SCROLL_BEHAVIOR_KEY); if (this.searchResultModel || scrollBehavior === 'paginated') { // In search mode or paginated mode, filter to show only the selected category - if (this.viewState.filterToCategory !== element) { - this.viewState.filterToCategory = element ?? undefined; + if (this.viewState.categoryFilter !== element) { + this.viewState.categoryFilter = element ?? undefined; // Force render in this case, because // onDidClickSetting relies on the updated view. this.renderTree(undefined, true); @@ -1063,8 +1063,8 @@ export class SettingsEditor2 extends EditorPane { } } else { // In continuous mode, clear any category filter that may have been set in paginated mode - if (this.viewState.filterToCategory) { - this.viewState.filterToCategory = undefined; + if (this.viewState.categoryFilter) { + this.viewState.categoryFilter = undefined; this.renderTree(undefined, true); } if (element && (!e.browserEvent || !(e.browserEvent).fromScroll)) { @@ -1709,7 +1709,7 @@ export class SettingsEditor2 extends EditorPane { if (Array.isArray(rootChildren) && rootChildren.length > 0) { const firstCategory = rootChildren[0]; if (firstCategory instanceof SettingsTreeGroupElement) { - this.viewState.filterToCategory = firstCategory; + this.viewState.categoryFilter = firstCategory; this.tocTree.setFocus([firstCategory]); this.tocTree.setSelection([firstCategory]); } @@ -1918,7 +1918,7 @@ export class SettingsEditor2 extends EditorPane { if (expandResults) { this.tocTree.setFocus([]); - this.viewState.filterToCategory = undefined; + this.viewState.categoryFilter = undefined; } this.tocTreeModel.currentSearchModel = this.searchResultModel; @@ -2040,7 +2040,7 @@ export class SettingsEditor2 extends EditorPane { this.tocTreeModel.currentSearchModel = this.searchResultModel; if (expandResults) { this.tocTree.setFocus([]); - this.viewState.filterToCategory = undefined; + this.viewState.categoryFilter = undefined; this.tocTree.expandAll(); this.settingsTree.scrollTop = 0; } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index ec2eb97a767..fbd06c80137 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -2419,14 +2419,14 @@ function escapeInvisibleChars(enumValue: string): string { export class SettingsTreeFilter implements ITreeFilter { constructor( private viewState: ISettingsEditorViewState, - private filterGroups: boolean, + private isFilteringGroups: boolean, @IWorkbenchEnvironmentService private environmentService: IWorkbenchEnvironmentService, ) { } filter(element: SettingsTreeElement, parentVisibility: TreeVisibility): TreeFilterResult { // Filter during search - if (this.viewState.filterToCategory && element instanceof SettingsTreeSettingElement) { - if (!this.settingBelongsToCategory(element, this.viewState.filterToCategory)) { + if (this.viewState.categoryFilter && element instanceof SettingsTreeSettingElement) { + if (!this.settingContainedInGroup(element.setting, this.viewState.categoryFilter)) { return false; } } @@ -2442,8 +2442,8 @@ export class SettingsTreeFilter implements ITreeFilter { // Group with no visible children if (element instanceof SettingsTreeGroupElement) { // When filtering to a specific category, only show that category and its descendants - if (this.filterGroups && this.viewState.filterToCategory) { - if (!this.groupIsRelatedToCategory(element, this.viewState.filterToCategory)) { + if (this.isFilteringGroups && this.viewState.categoryFilter) { + if (!this.groupIsRelatedToCategory(element, this.viewState.categoryFilter)) { return false; } // For groups related to the category, skip the count check and recurse @@ -2460,7 +2460,7 @@ export class SettingsTreeFilter implements ITreeFilter { // Filtered "new extensions" button if (element instanceof SettingsTreeNewExtensionsElement) { - if (this.viewState.tagFilters?.size || this.viewState.filterToCategory) { + if (this.viewState.tagFilters?.size || this.viewState.categoryFilter) { return false; } } @@ -2468,19 +2468,16 @@ export class SettingsTreeFilter implements ITreeFilter { return true; } - /** - * Checks if a setting element belongs to the category or any of its subcategories - * by traversing up the setting's parent chain using IDs. - */ - private settingBelongsToCategory(element: SettingsTreeSettingElement, category: SettingsTreeGroupElement): boolean { - let parent = element.parent; - while (parent) { - if (parent.id === category.id) { - return true; + private settingContainedInGroup(setting: ISetting, group: SettingsTreeGroupElement): boolean { + return group.children.some(child => { + if (child instanceof SettingsTreeGroupElement) { + return this.settingContainedInGroup(setting, child); + } else if (child instanceof SettingsTreeSettingElement) { + return child.setting.key === setting.key; + } else { + return false; } - parent = parent.parent; - } - return false; + }); } /** diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts index f85311aa7f6..186468f57ad 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTreeModels.ts @@ -34,7 +34,7 @@ export interface ISettingsEditorViewState { featureFilters?: Set; idFilters?: Set; languageFilter?: string; - filterToCategory?: SettingsTreeGroupElement; + categoryFilter?: SettingsTreeGroupElement; } export abstract class SettingsTreeElement extends Disposable {