@theia/preferences 1.75.0 → 1.76.0-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,320 @@
1
+ "use strict";
2
+ // *****************************************************************************
3
+ // Copyright (C) 2026 Safi Seid-Ahmad, K2view and others.
4
+ //
5
+ // This program and the accompanying materials are made available under the
6
+ // terms of the Eclipse Public License v. 2.0 which is available at
7
+ // http://www.eclipse.org/legal/epl-2.0.
8
+ //
9
+ // This Source Code may also be made available under the following Secondary
10
+ // Licenses when the conditions for such availability set forth in the Eclipse
11
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
12
+ // with the GNU Classpath Exception which is available at
13
+ // https://www.gnu.org/software/classpath/license.html.
14
+ //
15
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16
+ // *****************************************************************************
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ /* eslint-disable @typescript-eslint/no-explicit-any */
19
+ const jsdom_1 = require("@theia/core/lib/browser/test/jsdom");
20
+ const disableJSDOM = (0, jsdom_1.enableJSDOM)();
21
+ const frontend_application_config_provider_1 = require("@theia/core/lib/browser/frontend-application-config-provider");
22
+ frontend_application_config_provider_1.FrontendApplicationConfigProvider.set({});
23
+ const chai_1 = require("chai");
24
+ const inversify_1 = require("@theia/core/shared/inversify");
25
+ const core_1 = require("@theia/core");
26
+ const mock_logger_1 = require("@theia/core/lib/common/test/mock-logger");
27
+ const browser_1 = require("@theia/core/lib/browser");
28
+ const preference_tree_model_1 = require("./preference-tree-model");
29
+ const preference_searchbar_widget_1 = require("./views/preference-searchbar-widget");
30
+ const preference_tree_generator_1 = require("./util/preference-tree-generator");
31
+ const preference_scope_tabbar_widget_1 = require("./views/preference-scope-tabbar-widget");
32
+ const preference_types_1 = require("./util/preference-types");
33
+ const preference_layout_1 = require("./util/preference-layout");
34
+ disableJSDOM();
35
+ describe('PreferenceTreeModel', () => {
36
+ let searchbarEmitter;
37
+ let schemaEmitter;
38
+ let scopeEmitter;
39
+ let isValidInScope;
40
+ function createComposite(group, id, parent, depth, expandable) {
41
+ const node = {
42
+ id: `${group}@${id}`,
43
+ visible: true,
44
+ parent,
45
+ children: [],
46
+ expanded: false,
47
+ selected: false,
48
+ depth,
49
+ label: id,
50
+ };
51
+ if (!expandable) {
52
+ delete node.expanded;
53
+ }
54
+ browser_1.CompositeTreeNode.addChild(parent, node);
55
+ return node;
56
+ }
57
+ function createLeaf(group, preferenceId, parent, depth) {
58
+ const node = {
59
+ id: `${group}@${preferenceId}`,
60
+ preferenceId,
61
+ parent,
62
+ preference: { data: {} },
63
+ depth,
64
+ };
65
+ browser_1.CompositeTreeNode.addChild(parent, node);
66
+ return node;
67
+ }
68
+ function createFixture(withCommonlyUsed = true) {
69
+ const root = {
70
+ id: 'root-node-id',
71
+ name: '',
72
+ parent: undefined,
73
+ visible: true,
74
+ children: [],
75
+ };
76
+ let commonlyUsed;
77
+ if (withCommonlyUsed) {
78
+ commonlyUsed = createComposite(preference_layout_1.COMMONLY_USED_SECTION_PREFIX, preference_layout_1.COMMONLY_USED_SECTION_PREFIX, root, 0, true);
79
+ createLeaf(preference_layout_1.COMMONLY_USED_SECTION_PREFIX, 'files.autoSave', commonlyUsed, 1);
80
+ }
81
+ const editor = createComposite('editor', 'editor', root, 0, true);
82
+ createLeaf('editor', 'editor.fontSize', editor, 1);
83
+ const editorCursor = createComposite('editor', 'editor.cursor', editor, 1, false);
84
+ createLeaf('editor', 'editor.cursorStyle', editorCursor, 2);
85
+ const extensions = createComposite('extensions', 'extensions', root, 0, true);
86
+ createLeaf('extensions', 'extensions.autoUpdate', extensions, 1);
87
+ return { root, commonlyUsed, editor, editorCursor, extensions };
88
+ }
89
+ /**
90
+ * Creates the model. The `onCreated` callback runs after the tree model's listeners are
91
+ * registered but before the (async) initial schema is applied, which simulates state that
92
+ * is restored before initialization completes, e.g. a restored search term.
93
+ */
94
+ async function createModel(fixture, onCreated) {
95
+ const parent = new inversify_1.Container();
96
+ searchbarEmitter = new core_1.Emitter();
97
+ schemaEmitter = new core_1.Emitter();
98
+ scopeEmitter = new core_1.Emitter();
99
+ isValidInScope = () => true;
100
+ parent.bind(core_1.ILogger).to(mock_logger_1.MockLogger).inSingletonScope();
101
+ parent.bind(browser_1.LabelProvider).toConstantValue({
102
+ getName: () => '',
103
+ getIcon: () => '',
104
+ getLongName: () => '',
105
+ });
106
+ parent.bind(core_1.PreferenceSchemaService).toConstantValue({
107
+ getSchemaProperties: () => new Map(),
108
+ isValidInScope: (preferenceId, scope) => isValidInScope(preferenceId, scope),
109
+ });
110
+ parent.bind(core_1.PreferenceService).toConstantValue({
111
+ ready: Promise.resolve(),
112
+ });
113
+ parent.bind(preference_searchbar_widget_1.PreferencesSearchbarWidget).toConstantValue({
114
+ onFilterChanged: searchbarEmitter.event,
115
+ updateResultsCount: () => { },
116
+ });
117
+ parent.bind(preference_tree_generator_1.PreferenceTreeGenerator).toConstantValue({
118
+ onSchemaChanged: schemaEmitter.event,
119
+ root: fixture.root,
120
+ getNodeId: () => '',
121
+ });
122
+ parent.bind(preference_scope_tabbar_widget_1.PreferencesScopeTabBar).toConstantValue({
123
+ onScopeChanged: scopeEmitter.event,
124
+ currentScope: preference_types_1.Preference.DEFAULT_SCOPE,
125
+ });
126
+ const child = (0, browser_1.createTreeContainer)(parent, { model: preference_tree_model_1.PreferenceTreeModel });
127
+ const model = child.get(preference_tree_model_1.PreferenceTreeModel);
128
+ onCreated?.(model);
129
+ await new Promise(resolve => setTimeout(resolve));
130
+ return model;
131
+ }
132
+ describe('category filter', () => {
133
+ it('selects the Commonly Used category by default', async () => {
134
+ const fixture = createFixture();
135
+ const model = await createModel(fixture);
136
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.commonlyUsed.id);
137
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.commonlyUsed.id);
138
+ });
139
+ it('applies the category filter when a category is selected', async () => {
140
+ const fixture = createFixture();
141
+ const model = await createModel(fixture);
142
+ model.selectNode(fixture.extensions);
143
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.extensions.id);
144
+ });
145
+ it('keeps the user selection across schema reloads', async () => {
146
+ const fixture = createFixture();
147
+ const model = await createModel(fixture);
148
+ model.selectNode(fixture.extensions);
149
+ schemaEmitter.fire(fixture.root);
150
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.extensions.id);
151
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.extensions.id);
152
+ });
153
+ it('restores the user selection when the schema is rebuilt with new nodes', async () => {
154
+ const fixture = createFixture();
155
+ const model = await createModel(fixture);
156
+ model.selectNode(fixture.extensions);
157
+ const rebuilt = createFixture();
158
+ schemaEmitter.fire(rebuilt.root);
159
+ (0, chai_1.expect)(model.selectedNodes[0]).to.equal(model.getNode(rebuilt.extensions.id));
160
+ (0, chai_1.expect)(model.selectedNodes[0]?.selected).to.be.true;
161
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(rebuilt.extensions.id);
162
+ });
163
+ it('keeps the default selection highlighted when the schema is rebuilt with new nodes', async () => {
164
+ const fixture = createFixture();
165
+ const model = await createModel(fixture);
166
+ const rebuilt = createFixture();
167
+ schemaEmitter.fire(rebuilt.root);
168
+ (0, chai_1.expect)(model.selectedNodes[0]).to.equal(model.getNode(rebuilt.commonlyUsed.id));
169
+ (0, chai_1.expect)(model.selectedNodes[0]?.selected).to.be.true;
170
+ });
171
+ it('preserves the category filter when restoring a synced selection after a schema rebuild', async () => {
172
+ const fixture = createFixture();
173
+ const model = await createModel(fixture);
174
+ model.selectNode(fixture.editor);
175
+ model.selectIfNotSelected(fixture.editorCursor);
176
+ const rebuilt = createFixture();
177
+ schemaEmitter.fire(rebuilt.root);
178
+ (0, chai_1.expect)(model.selectedNodes[0]).to.equal(model.getNode(rebuilt.editorCursor.id));
179
+ (0, chai_1.expect)(model.selectedNodes[0]?.selected).to.be.true;
180
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(rebuilt.editor.id);
181
+ });
182
+ it('falls back to the default category when the selected category disappears from the schema', async () => {
183
+ const fixture = createFixture();
184
+ const model = await createModel(fixture);
185
+ model.selectNode(fixture.extensions);
186
+ const newFixture = createFixture();
187
+ newFixture.root.children = newFixture.root.children.filter(child => child !== newFixture.extensions);
188
+ schemaEmitter.fire(newFixture.root);
189
+ (0, chai_1.expect)(model.selectedNodes[0]).to.equal(model.getNode(newFixture.commonlyUsed.id));
190
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(newFixture.commonlyUsed.id);
191
+ });
192
+ it('falls back to the default category when the selected category has no settings left after a schema change', async () => {
193
+ const fixture = createFixture();
194
+ const model = await createModel(fixture);
195
+ model.selectNode(fixture.extensions);
196
+ const rebuilt = createFixture();
197
+ rebuilt.extensions.children = [];
198
+ schemaEmitter.fire(rebuilt.root);
199
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(rebuilt.commonlyUsed.id);
200
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(rebuilt.commonlyUsed.id);
201
+ });
202
+ it('selects the Commonly Used category by its exact id', async () => {
203
+ const fixture = createFixture(false);
204
+ // A group whose id merely starts with the Commonly Used prefix must not be mistaken for it.
205
+ const lookalikeGroup = `${preference_layout_1.COMMONLY_USED_SECTION_PREFIX}-lookalike`;
206
+ const lookalike = createComposite(lookalikeGroup, lookalikeGroup, fixture.root, 0, true);
207
+ createLeaf(lookalikeGroup, 'lookalike.setting', lookalike, 1);
208
+ fixture.commonlyUsed = createComposite(preference_layout_1.COMMONLY_USED_SECTION_PREFIX, preference_layout_1.COMMONLY_USED_SECTION_PREFIX, fixture.root, 0, true);
209
+ createLeaf(preference_layout_1.COMMONLY_USED_SECTION_PREFIX, 'files.autoSave', fixture.commonlyUsed, 1);
210
+ const model = await createModel(fixture);
211
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.commonlyUsed.id);
212
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.commonlyUsed.id);
213
+ });
214
+ });
215
+ describe('scope change', () => {
216
+ function fireScopeChange(scope) {
217
+ scopeEmitter.fire({ scope, uri: undefined, activeScopeIsFolder: false });
218
+ }
219
+ it('keeps the selected category when it still has settings in the new scope', async () => {
220
+ const fixture = createFixture();
221
+ const model = await createModel(fixture);
222
+ model.selectNode(fixture.extensions);
223
+ fireScopeChange(core_1.PreferenceScope.Workspace);
224
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.extensions.id);
225
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.extensions.id);
226
+ });
227
+ it('falls back to the default category when the selected category has no settings in the new scope', async () => {
228
+ const fixture = createFixture();
229
+ const model = await createModel(fixture);
230
+ model.selectNode(fixture.extensions);
231
+ isValidInScope = (preferenceId, scope) => scope !== core_1.PreferenceScope.Workspace || !preferenceId.startsWith('extensions.');
232
+ fireScopeChange(core_1.PreferenceScope.Workspace);
233
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.commonlyUsed.id);
234
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.commonlyUsed.id);
235
+ });
236
+ it('clears the selection when neither the selected nor the default category has settings in the new scope', async () => {
237
+ const fixture = createFixture();
238
+ const model = await createModel(fixture);
239
+ model.selectNode(fixture.extensions);
240
+ isValidInScope = (preferenceId, scope) => scope !== core_1.PreferenceScope.Workspace || preferenceId.startsWith('editor.');
241
+ fireScopeChange(core_1.PreferenceScope.Workspace);
242
+ (0, chai_1.expect)(model.selectedNodes).to.have.lengthOf(0);
243
+ (0, chai_1.expect)(model.categoryFilterId).to.be.undefined;
244
+ });
245
+ });
246
+ describe('editor scroll sync', () => {
247
+ it('does not change the category filter when the selection syncs to the editor scroll position', async () => {
248
+ const fixture = createFixture();
249
+ const model = await createModel(fixture);
250
+ model.selectNode(fixture.editor);
251
+ model.selectIfNotSelected(fixture.editorCursor);
252
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.editorCursor.id);
253
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.editor.id);
254
+ });
255
+ it('does not narrow active search results when the selection syncs to the editor scroll position', async () => {
256
+ const fixture = createFixture();
257
+ const model = await createModel(fixture);
258
+ searchbarEmitter.fire('font');
259
+ model.selectIfNotSelected(fixture.editor);
260
+ (0, chai_1.expect)(model.categoryFilterId).to.be.undefined;
261
+ });
262
+ });
263
+ describe('search interaction', () => {
264
+ it('clears the category filter and the selection when a search starts', async () => {
265
+ const fixture = createFixture();
266
+ const model = await createModel(fixture);
267
+ model.selectNode(fixture.editor);
268
+ searchbarEmitter.fire('font');
269
+ (0, chai_1.expect)(model.isFiltered).to.be.true;
270
+ (0, chai_1.expect)(model.categoryFilterId).to.be.undefined;
271
+ (0, chai_1.expect)(model.selectedNodes).to.have.lengthOf(0);
272
+ });
273
+ it('applies the category filter when a category is explicitly selected during a search', async () => {
274
+ const fixture = createFixture();
275
+ const model = await createModel(fixture);
276
+ searchbarEmitter.fire('font');
277
+ model.selectNode(fixture.editor);
278
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.editor.id);
279
+ });
280
+ it('resets to all results when the search term changes after a category was selected', async () => {
281
+ const fixture = createFixture();
282
+ const model = await createModel(fixture);
283
+ searchbarEmitter.fire('font');
284
+ model.selectNode(fixture.editor);
285
+ searchbarEmitter.fire('fonts');
286
+ (0, chai_1.expect)(model.categoryFilterId).to.be.undefined;
287
+ (0, chai_1.expect)(model.selectedNodes).to.have.lengthOf(0);
288
+ });
289
+ it('returns to the Commonly Used category when the search is cleared', async () => {
290
+ const fixture = createFixture();
291
+ const model = await createModel(fixture);
292
+ searchbarEmitter.fire('font');
293
+ model.selectNode(fixture.editor);
294
+ searchbarEmitter.fire('');
295
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.commonlyUsed.id);
296
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.commonlyUsed.id);
297
+ });
298
+ });
299
+ describe('initial selection', () => {
300
+ it('does not apply the default selection while a restored search is active', async () => {
301
+ const fixture = createFixture();
302
+ const model = await createModel(fixture, () => searchbarEmitter.fire('font'));
303
+ (0, chai_1.expect)(model.selectedNodes).to.have.lengthOf(0);
304
+ (0, chai_1.expect)(model.categoryFilterId).to.be.undefined;
305
+ searchbarEmitter.fire('');
306
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(fixture.commonlyUsed.id);
307
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(fixture.commonlyUsed.id);
308
+ });
309
+ it('applies the default selection on a later schema change if Commonly Used is not present initially', async () => {
310
+ const withoutCommonlyUsed = createFixture(false);
311
+ const model = await createModel(withoutCommonlyUsed);
312
+ (0, chai_1.expect)(model.selectedNodes).to.have.lengthOf(0);
313
+ const withCommonlyUsed = createFixture();
314
+ schemaEmitter.fire(withCommonlyUsed.root);
315
+ (0, chai_1.expect)(model.selectedNodes[0]?.id).to.equal(withCommonlyUsed.commonlyUsed.id);
316
+ (0, chai_1.expect)(model.categoryFilterId).to.equal(withCommonlyUsed.commonlyUsed.id);
317
+ });
318
+ });
319
+ });
320
+ //# sourceMappingURL=preference-tree-model.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preference-tree-model.spec.js","sourceRoot":"","sources":["../../src/browser/preference-tree-model.spec.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { SelectableTreeNode, StatefulWidget } from '@theia/core/lib/browser';
1
+ import { SelectableTreeNode } from '@theia/core/lib/browser';
2
2
  import { Disposable, PreferenceProviderDataChanges, PreferenceProviderProvider, PreferenceSchemaService, PreferenceService } from '@theia/core';
3
3
  import { BaseWidget } from '@theia/core/lib/browser/widgets/widget';
4
4
  import { PreferenceTreeModel, PreferenceFilterChangeEvent, PreferenceFilterChangeSource } from '../preference-tree-model';
@@ -6,10 +6,7 @@ import { PreferenceNodeRendererFactory, GeneralPreferenceNodeRenderer } from './
6
6
  import { Preference } from '../util/preference-types';
7
7
  import { PreferencesScopeTabBar } from './preference-scope-tabbar-widget';
8
8
  import { PreferenceNodeRendererCreatorRegistry } from './components/preference-node-renderer-creator';
9
- export interface PreferencesEditorState {
10
- firstVisibleChildID: string;
11
- }
12
- export declare class PreferencesEditorWidget extends BaseWidget implements StatefulWidget {
9
+ export declare class PreferencesEditorWidget extends BaseWidget {
13
10
  static readonly ID = "settings.editor";
14
11
  static readonly LABEL: string;
15
12
  scrollOptions: import("perfect-scrollbar").default.Options;
@@ -45,19 +42,46 @@ export declare class PreferencesEditorWidget extends BaseWidget implements State
45
42
  protected subscribeToPreferenceProviderChanges(): Disposable;
46
43
  protected handleDisplayChange(e: PreferenceFilterChangeEvent): void;
47
44
  protected getScrollTarget(source: PreferenceFilterChangeSource): string | undefined;
45
+ protected isRendererVisible(nodeId: string): boolean;
48
46
  protected isRendererInViewport(nodeId: string): boolean;
49
47
  protected handleRegistryChange(): void;
50
48
  protected handleSchemaChange(isFiltered: boolean): void;
51
49
  protected handleScopeChange(isFiltered?: boolean): void;
52
50
  protected hasSchemaChanged(renderer: GeneralPreferenceNodeRenderer, node: Preference.LeafNode): boolean;
53
51
  protected handleSearchChange(isFiltered: boolean, leavesAreVisible: boolean): void;
52
+ protected handleCategoryChange(isFiltered: boolean, leavesAreVisible: boolean): void;
54
53
  protected areLeavesVisible(): boolean;
55
54
  protected allRenderers(): IterableIterator<[string, GeneralPreferenceNodeRenderer, Map<string, GeneralPreferenceNodeRenderer>]>;
56
55
  protected handlePreferenceChanges(e: PreferenceProviderDataChanges): void;
56
+ /**
57
+ * Returns true if a category filter is active and `node` is outside the visible slice:
58
+ * not the selected category itself, not a descendant of it, and not one of its
59
+ * composite ancestors (whose headers we keep visible above the selected category).
60
+ * Keeps the left tree intact (filtering is applied here, not in the model).
61
+ */
62
+ protected isOutsideSelectedCategory(node: Preference.TreeNode): boolean;
57
63
  /**
58
64
  * @returns true if the renderer is hidden, false otherwise.
59
65
  */
60
66
  protected hideIfFailsFilters(renderer: GeneralPreferenceNodeRenderer, isFiltered: boolean): boolean;
67
+ /**
68
+ * Pins category header rows to the top of the scroll container via `position: sticky`.
69
+ * The headers of the selected category and its ancestors are stacked on top of each
70
+ * other; the headers of its subsections all share the single slot below that stack, so
71
+ * the subsection currently scrolled into view replaces the previous one instead of the
72
+ * headers piling up. Clears the styles when no category filter is active.
73
+ */
74
+ protected pinCategoryHeaders(): void;
75
+ /**
76
+ * @returns the visible header renderers of the selected category and its ancestors,
77
+ * outermost first, i.e. in document order. Empty if no category filter is active.
78
+ */
79
+ protected getStackedHeaderRenderers(): GeneralPreferenceNodeRenderer[];
80
+ /**
81
+ * @returns the total height of the pinned header stack, i.e. the space at the top of the
82
+ * scroll container that is covered by the headers of the selected category and its ancestors.
83
+ */
84
+ protected getStackedHeaderHeight(stackedHeaders?: GeneralPreferenceNodeRenderer[]): number;
61
85
  protected resetScroll(nodeIDToScrollTo?: string): void;
62
86
  protected doResetScroll(nodeIDToScrollTo?: string): void;
63
87
  protected doOnScroll(): void;
@@ -75,7 +99,5 @@ export declare class PreferencesEditorWidget extends BaseWidget implements State
75
99
  collection: Map<string, GeneralPreferenceNodeRenderer>;
76
100
  };
77
101
  protected getScrollContainer(): HTMLElement;
78
- storeState(): PreferencesEditorState;
79
- restoreState(oldState: PreferencesEditorState): void;
80
102
  }
81
103
  //# sourceMappingURL=preference-editor-widget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preference-editor-widget.d.ts","sourceRoot":"","sources":["../../../src/browser/views/preference-editor-widget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"preference-editor-widget.d.ts","sourceRoot":"","sources":["../../../src/browser/views/preference-editor-widget.ts"],"names":[],"mappings":"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"}
@@ -117,6 +117,9 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
117
117
  if (e.source === preference_tree_model_1.PreferenceFilterChangeSource.Search) {
118
118
  this.handleSearchChange(isFiltered, leavesAreVisible);
119
119
  }
120
+ else if (e.source === preference_tree_model_1.PreferenceFilterChangeSource.Category) {
121
+ this.handleCategoryChange(isFiltered, leavesAreVisible);
122
+ }
120
123
  else if (e.source === preference_tree_model_1.PreferenceFilterChangeSource.Scope) {
121
124
  this.handleScopeChange(isFiltered);
122
125
  }
@@ -126,16 +129,25 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
126
129
  else {
127
130
  (0, core_1.unreachable)(e.source, 'Not all PreferenceFilterChangeSource enum variants handled.');
128
131
  }
129
- if (scrollTarget) {
132
+ // Only sync the tree to a row that is still shown. A row hidden by the change, e.g. because
133
+ // it is not valid in the new scope or lies outside the selected category, must not pull the
134
+ // tree selection away from the page that is shown.
135
+ if (scrollTarget && this.isRendererVisible(scrollTarget)) {
130
136
  this.showInTree(scrollTarget);
131
137
  }
132
138
  this.resetScroll(scrollTarget);
139
+ this.pinCategoryHeaders();
133
140
  if (e.source === preference_tree_model_1.PreferenceFilterChangeSource.Search) {
134
141
  // Reset focus if search context changes.
135
142
  this.lastFocusedRendererNodeId = '';
136
143
  }
137
144
  }
138
145
  getScrollTarget(source) {
146
+ if (source === preference_tree_model_1.PreferenceFilterChangeSource.Category) {
147
+ // A newly selected category always opens at its top. Scrolling back to the last focused
148
+ // control would re-select its (previous) category in the tree and desync tree and editor.
149
+ return undefined;
150
+ }
139
151
  if (source !== preference_tree_model_1.PreferenceFilterChangeSource.Search) {
140
152
  return this.firstVisibleChildID;
141
153
  }
@@ -144,6 +156,10 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
144
156
  }
145
157
  return undefined;
146
158
  }
159
+ isRendererVisible(nodeId) {
160
+ const { id, collection } = this.analyzeIDAndGetRendererGroup(nodeId);
161
+ return !!collection.get(id)?.visible;
162
+ }
147
163
  isRendererInViewport(nodeId) {
148
164
  const { id, collection } = this.analyzeIDAndGetRendererGroup(nodeId);
149
165
  const renderer = collection.get(id);
@@ -218,6 +234,13 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
218
234
  }
219
235
  }
220
236
  }
237
+ handleCategoryChange(isFiltered, leavesAreVisible) {
238
+ if (leavesAreVisible) {
239
+ for (const [, renderer] of this.allRenderers()) {
240
+ this.hideIfFailsFilters(renderer, isFiltered);
241
+ }
242
+ }
243
+ }
221
244
  areLeavesVisible() {
222
245
  const leavesAreVisible = this.model.totalVisibleLeaves > 0;
223
246
  this.node.classList.toggle('no-results', !leavesAreVisible);
@@ -238,12 +261,29 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
238
261
  this.renderers.get(id)?.handleValueChange?.();
239
262
  }
240
263
  }
264
+ /**
265
+ * Returns true if a category filter is active and `node` is outside the visible slice:
266
+ * not the selected category itself, not a descendant of it, and not one of its
267
+ * composite ancestors (whose headers we keep visible above the selected category).
268
+ * Keeps the left tree intact (filtering is applied here, not in the model).
269
+ */
270
+ isOutsideSelectedCategory(node) {
271
+ const categoryId = this.model.categoryFilterId;
272
+ if (!categoryId || node.id === categoryId) {
273
+ return false;
274
+ }
275
+ const category = this.model.getNode(categoryId);
276
+ if (!browser_1.CompositeTreeNode.is(category) || browser_1.CompositeTreeNode.isAncestor(category, node)) {
277
+ return false;
278
+ }
279
+ return !(browser_1.CompositeTreeNode.is(node) && browser_1.CompositeTreeNode.isAncestor(node, category));
280
+ }
241
281
  /**
242
282
  * @returns true if the renderer is hidden, false otherwise.
243
283
  */
244
284
  hideIfFailsFilters(renderer, isFiltered) {
245
285
  const row = this.model.currentRows.get(renderer.nodeId);
246
- if (!row || (browser_1.CompositeTreeNode.is(row.node) && (isFiltered || row.visibleChildren === 0))) {
286
+ if (!row || (browser_1.CompositeTreeNode.is(row.node) && (isFiltered || row.visibleChildren === 0)) || this.isOutsideSelectedCategory(row.node)) {
247
287
  renderer.hide();
248
288
  return true;
249
289
  }
@@ -252,6 +292,67 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
252
292
  return false;
253
293
  }
254
294
  }
295
+ /**
296
+ * Pins category header rows to the top of the scroll container via `position: sticky`.
297
+ * The headers of the selected category and its ancestors are stacked on top of each
298
+ * other; the headers of its subsections all share the single slot below that stack, so
299
+ * the subsection currently scrolled into view replaces the previous one instead of the
300
+ * headers piling up. Clears the styles when no category filter is active.
301
+ */
302
+ pinCategoryHeaders() {
303
+ requestAnimationFrame(() => {
304
+ const categoryId = this.model.categoryFilterId;
305
+ const stackedHeaders = this.getStackedHeaderRenderers();
306
+ // Read all heights before writing any styles, so that the layout is computed only once.
307
+ const heights = stackedHeaders.map(renderer => renderer.node.offsetHeight);
308
+ const stackedTops = new Map();
309
+ let stackHeight = 0;
310
+ stackedHeaders.forEach((renderer, index) => {
311
+ stackedTops.set(renderer.nodeId, stackHeight);
312
+ stackHeight += heights[index];
313
+ });
314
+ for (const [, renderer] of this.allRenderers()) {
315
+ if (!browser_1.CompositeTreeNode.is(this.model.getNode(renderer.nodeId))) {
316
+ continue;
317
+ }
318
+ const wrapper = renderer.node;
319
+ if (categoryId && renderer.visible) {
320
+ wrapper.classList.add('theia-settings-pinned-category-header');
321
+ wrapper.style.top = `${stackedTops.get(renderer.nodeId) ?? stackHeight}px`;
322
+ }
323
+ else {
324
+ wrapper.classList.remove('theia-settings-pinned-category-header');
325
+ wrapper.style.top = '';
326
+ }
327
+ }
328
+ });
329
+ }
330
+ /**
331
+ * @returns the visible header renderers of the selected category and its ancestors,
332
+ * outermost first, i.e. in document order. Empty if no category filter is active.
333
+ */
334
+ getStackedHeaderRenderers() {
335
+ const renderers = [];
336
+ const categoryId = this.model.categoryFilterId;
337
+ if (!categoryId) {
338
+ return renderers;
339
+ }
340
+ for (let node = this.model.getNode(categoryId); node && preference_types_1.Preference.TreeNode.is(node); node = node.parent) {
341
+ const { id, collection } = this.analyzeIDAndGetRendererGroup(node.id);
342
+ const renderer = collection.get(id);
343
+ if (renderer?.visible) {
344
+ renderers.unshift(renderer);
345
+ }
346
+ }
347
+ return renderers;
348
+ }
349
+ /**
350
+ * @returns the total height of the pinned header stack, i.e. the space at the top of the
351
+ * scroll container that is covered by the headers of the selected category and its ancestors.
352
+ */
353
+ getStackedHeaderHeight(stackedHeaders = this.getStackedHeaderRenderers()) {
354
+ return stackedHeaders.reduce((height, renderer) => height + renderer.node.offsetHeight, 0);
355
+ }
255
356
  resetScroll(nodeIDToScrollTo) {
256
357
  if (this.scrollBar) { // Absent on widget creation
257
358
  this.doResetScroll(nodeIDToScrollTo);
@@ -272,7 +373,8 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
272
373
  const { id, collection } = this.analyzeIDAndGetRendererGroup(nodeIDToScrollTo);
273
374
  const renderer = collection.get(id);
274
375
  if (renderer?.visible) {
275
- this.scrollContainer.scrollTo(0, renderer.node.offsetTop);
376
+ // Place the target right below the pinned category headers, not behind them.
377
+ this.scrollContainer.scrollTo(0, renderer.node.offsetTop - this.getStackedHeaderHeight());
276
378
  return;
277
379
  }
278
380
  }
@@ -295,10 +397,21 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
295
397
  }
296
398
  ;
297
399
  findFirstVisibleChildID() {
298
- const { scrollTop } = this.scrollContainer;
400
+ // The pinned headers of the selected category and its ancestors always sit at the top of
401
+ // the scroll container. Skip them and look for the first row right below the stack,
402
+ // otherwise the outermost ancestor would always be reported and the tree selection would
403
+ // jump from the selected sub-category to its parent.
404
+ const stackedHeaders = this.getStackedHeaderRenderers();
405
+ const stackBottom = this.scrollContainer.scrollTop + this.getStackedHeaderHeight(stackedHeaders);
299
406
  for (const [, renderer] of this.allRenderers()) {
300
- const { offsetTop, offsetHeight } = renderer.node;
301
- if (Math.abs(offsetTop - scrollTop) <= offsetHeight / 2) {
407
+ const { offsetTop, offsetHeight, offsetParent } = renderer.node;
408
+ // Skip hidden renderers (display:none): they report offsetTop/offsetHeight 0
409
+ // and would otherwise match scrollTop===0, hijacking the selection back to
410
+ // the first hidden category.
411
+ if (!offsetParent || stackedHeaders.includes(renderer)) {
412
+ continue;
413
+ }
414
+ if (Math.abs(offsetTop - stackBottom) <= offsetHeight / 2) {
302
415
  return renderer.nodeId;
303
416
  }
304
417
  }
@@ -376,15 +489,6 @@ let PreferencesEditorWidget = class PreferencesEditorWidget extends widget_1.Bas
376
489
  getScrollContainer() {
377
490
  return this.scrollContainer;
378
491
  }
379
- storeState() {
380
- return {
381
- firstVisibleChildID: this.firstVisibleChildID,
382
- };
383
- }
384
- restoreState(oldState) {
385
- this.firstVisibleChildID = oldState.firstVisibleChildID;
386
- this.resetScroll(this.firstVisibleChildID);
387
- }
388
492
  };
389
493
  exports.PreferencesEditorWidget = PreferencesEditorWidget;
390
494
  tslib_1.__decorate([