From 473f563b6be2dc6dd7b36732f9268fed9cc63db6 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 16:45:07 +0000 Subject: [PATCH] Add setting to always show advanced settings (#283592) * Initial plan * Add workbench.settings.alwaysShowAdvancedSettings setting with insiders default Co-authored-by: sandy081 <10746682+sandy081@users.noreply.github.com> * Add configuration change handler to refresh view when alwaysShowAdvancedSettings changes Co-authored-by: sandy081 <10746682+sandy081@users.noreply.github.com> * polish * polish --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: sandy081 <10746682+sandy081@users.noreply.github.com> Co-authored-by: Sandeep Somavarapu --- .../browser/workbench.contribution.ts | 6 +++ .../preferences/browser/settingsEditor2.ts | 12 ++++-- .../settingsEditorSettingIndicators.ts | 38 +++++++++++++++++-- .../preferences/browser/settingsTree.ts | 1 + .../preferences/common/preferences.ts | 1 + 5 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index bd30b27298d9..03a1995b73e0 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -7,6 +7,7 @@ import { isStandalone } from '../../base/browser/browser.js'; import { isLinux, isMacintosh, isNative, isWeb, isWindows } from '../../base/common/platform.js'; import { localize } from '../../nls.js'; import { Extensions as ConfigurationExtensions, ConfigurationScope, IConfigurationRegistry } from '../../platform/configuration/common/configurationRegistry.js'; +import product from '../../platform/product/common/product.js'; import { Registry } from '../../platform/registry/common/platform.js'; import { ConfigurationKeyValuePairs, ConfigurationMigrationWorkbenchContribution, DynamicWindowConfiguration, DynamicWorkbenchSecurityConfiguration, Extensions, IConfigurationMigrationRegistry, problemsConfigurationNodeBase, windowConfigurationNodeBase, workbenchConfigurationNodeBase } from '../common/configuration.js'; import { WorkbenchPhase, registerWorkbenchContribution2 } from '../common/contributions.js'; @@ -533,6 +534,11 @@ const registry = Registry.as(ConfigurationExtensions.Con 'description': localize('openDefaultKeybindings', "Controls whether opening keybinding settings also opens an editor showing all default keybindings."), 'default': false }, + 'workbench.settings.alwaysShowAdvancedSettings': { + 'type': 'boolean', + 'description': localize('alwaysShowAdvancedSettings', "Controls whether advanced settings are always shown in the settings editor without requiring the `@tag:advanced` filter."), + 'default': product.quality !== 'stable' + }, 'workbench.sideBar.location': { 'type': 'string', 'enum': ['left', 'right'], diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 5c66a52ef9a4..a3011857a264 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -55,7 +55,7 @@ import { IChatEntitlementService } from '../../../services/chat/common/chatEntit import { APPLICATION_SCOPES, IWorkbenchConfigurationService } from '../../../services/configuration/common/configuration.js'; import { IEditorGroup, IEditorGroupsService } from '../../../services/editor/common/editorGroupsService.js'; import { IExtensionService } from '../../../services/extensions/common/extensions.js'; -import { IOpenSettingsOptions, IPreferencesService, ISearchResult, ISetting, ISettingsEditorModel, ISettingsEditorOptions, ISettingsGroup, SettingMatchType, SettingValueType, validateSettingsEditorOptions } from '../../../services/preferences/common/preferences.js'; +import { ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING, IOpenSettingsOptions, IPreferencesService, ISearchResult, ISetting, ISettingsEditorModel, ISettingsEditorOptions, ISettingsGroup, SettingMatchType, SettingValueType, validateSettingsEditorOptions } from '../../../services/preferences/common/preferences.js'; import { SettingsEditor2Input } from '../../../services/preferences/common/preferencesEditorInput.js'; import { nullRange, Settings2EditorModel } from '../../../services/preferences/common/preferencesModels.js'; import { IUserDataProfileService } from '../../../services/userDataProfile/common/userDataProfile.js'; @@ -299,6 +299,9 @@ export class SettingsEditor2 extends EditorPane { || e.affectedKeys.has(WorkbenchSettingsEditorSettings.EnableNaturalLanguageSearch)) { this.updateAiSearchToggleVisibility(); } + if (e.affectsConfiguration(ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING)) { + this.onConfigUpdate(undefined, true, true); + } if (e.source !== ConfigurationTarget.DEFAULT) { this.onConfigUpdate(e.affectedKeys); } @@ -352,6 +355,9 @@ export class SettingsEditor2 extends EditorPane { } private canShowAdvancedSettings(): boolean { + if (this.configurationService.getValue(ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING) ?? false) { + return true; + } return this.viewState.tagFilters?.has(ADVANCED_SETTING_TAG) ?? false; } @@ -1420,7 +1426,7 @@ export class SettingsEditor2 extends EditorPane { this.settingsOrderByTocIndex = this.createSettingsOrderByTocIndex(resolvedSettingsRoot); } - private async onConfigUpdate(keys?: ReadonlySet, forceRefresh = false, schemaChange = false): Promise { + private async onConfigUpdate(keys?: ReadonlySet, forceRefresh = false, triggerSearch = false): Promise { if (keys && this.settingsTreeModel) { return this.updateElementsByKey(keys); } @@ -1576,7 +1582,7 @@ export class SettingsEditor2 extends EditorPane { if (this.settingsTreeModel.value) { this.refreshModels(resolvedSettingsRoot); - if (schemaChange && this.searchResultModel) { + if (triggerSearch && this.searchResultModel) { // If an extension's settings were just loaded and a search is active, retrigger the search so it shows up return await this.onSearchInputChanged(false); } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditorSettingIndicators.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditorSettingIndicators.ts index 1d437f92635b..e5de36909fb8 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditorSettingIndicators.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditorSettingIndicators.ts @@ -67,6 +67,7 @@ export class SettingsTreeIndicatorsLabel implements IDisposable { private readonly indicatorsContainerElement: HTMLElement; private readonly previewIndicator: SettingIndicator; + private readonly advancedIndicator: SettingIndicator; private readonly workspaceTrustIndicator: SettingIndicator; private readonly scopeOverridesIndicator: SettingIndicator; private readonly syncIgnoredIndicator: SettingIndicator; @@ -91,7 +92,8 @@ export class SettingsTreeIndicatorsLabel implements IDisposable { this.indicatorsContainerElement.style.display = 'inline'; this.previewIndicator = this.createPreviewIndicator(); - this.isolatedIndicators = [this.previewIndicator]; + this.advancedIndicator = this.createAdvancedIndicator(); + this.isolatedIndicators = [this.previewIndicator, this.advancedIndicator]; this.workspaceTrustIndicator = this.createWorkspaceTrustIndicator(); this.scopeOverridesIndicator = this.createScopeOverridesIndicator(); @@ -225,6 +227,28 @@ export class SettingsTreeIndicatorsLabel implements IDisposable { }; } + private createAdvancedIndicator(): SettingIndicator { + const disposables = new DisposableStore(); + const advancedIndicator = $('span.setting-indicator.setting-item-preview'); + const advancedLabel = disposables.add(new SimpleIconLabel(advancedIndicator)); + advancedLabel.text = localize('advancedLabel', "Advanced"); + + const showHover = (focus: boolean) => { + return this.hoverService.showInstantHover({ + ...this.defaultHoverOptions, + content: ADVANCED_INDICATOR_DESCRIPTION, + target: advancedIndicator + }, focus); + }; + this.addHoverDisposables(disposables, advancedIndicator, showHover); + + return { + element: advancedIndicator, + label: advancedLabel, + disposables + }; + } + private render() { this.indicatorsContainerElement.innerText = ''; this.indicatorsContainerElement.style.display = 'none'; @@ -342,6 +366,12 @@ export class SettingsTreeIndicatorsLabel implements IDisposable { this.render(); } + updateAdvancedIndicator(element: SettingsTreeSettingElement) { + const isAdvancedSetting = element.tags?.has('advanced'); + this.advancedIndicator.element.style.display = isAdvancedSetting ? 'inline' : 'none'; + this.render(); + } + private getInlineScopeDisplayText(completeScope: string): string { const [scope, language] = completeScope.split(':'); const localizedScope = scope === 'user' ? @@ -575,12 +605,14 @@ function getAccessibleScopeDisplayMidSentenceText(completeScope: string, languag export function getIndicatorsLabelAriaLabel(element: SettingsTreeSettingElement, configurationService: IWorkbenchConfigurationService, userDataProfilesService: IUserDataProfilesService, languageService: ILanguageService): string { const ariaLabelSections: string[] = []; - // Add preview or experimental or advanced indicator text + // Add preview or experimental indicator text if (element.tags?.has('preview')) { ariaLabelSections.push(localize('previewLabel', "Preview")); } else if (element.tags?.has('experimental')) { ariaLabelSections.push(localize('experimentalLabel', "Experimental")); - } else if (element.tags?.has('advanced')) { + } + + if (element.tags?.has('advanced')) { ariaLabelSections.push(localize('advancedLabel', "Advanced")); } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts index c9a9c687001a..6e680158a18d 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsTree.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsTree.ts @@ -1041,6 +1041,7 @@ export abstract class AbstractSettingRenderer extends Disposable implements ITre template.indicatorsLabel.updateSyncIgnored(element, this.ignoredSettings); template.indicatorsLabel.updateDefaultOverrideIndicator(element); template.indicatorsLabel.updatePreviewIndicator(element); + template.indicatorsLabel.updateAdvancedIndicator(element); template.elementDisposables.add(this.onDidChangeIgnoredSettings(() => { template.indicatorsLabel.updateSyncIgnored(element, this.ignoredSettings); })); diff --git a/src/vs/workbench/services/preferences/common/preferences.ts b/src/vs/workbench/services/preferences/common/preferences.ts index 2547976da464..d0e12602e254 100644 --- a/src/vs/workbench/services/preferences/common/preferences.ts +++ b/src/vs/workbench/services/preferences/common/preferences.ts @@ -348,5 +348,6 @@ export interface IDefineKeybindingEditorContribution extends IEditorContribution export const FOLDER_SETTINGS_PATH = '.vscode/settings.json'; export const DEFAULT_SETTINGS_EDITOR_SETTING = 'workbench.settings.openDefaultSettings'; export const USE_SPLIT_JSON_SETTING = 'workbench.settings.useSplitJSON'; +export const ALWAYS_SHOW_ADVANCED_SETTINGS_SETTING = 'workbench.settings.alwaysShowAdvancedSettings'; export const SETTINGS_AUTHORITY = 'settings';