@workbench-kit/shell-react 0.0.2-prototype.0.2.32 → 0.0.2-prototype.0.2.34
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.
- package/README.md +32 -0
- package/package.json +9 -9
- package/src/commands/use-command-descriptors.ts +7 -3
- package/src/commands/use-extension-registry-command-descriptors.ts +23 -6
- package/src/devtools/use-workbench-devtools-snapshot.ts +39 -14
- package/src/devtools/workbench-devtools-snapshot.ts +32 -13
- package/src/editor/area.tsx +3 -2
- package/src/editor/state-storage.ts +31 -0
- package/src/editor/tab-context-menu.ts +8 -8
- package/src/editor/use-editor.ts +6 -6
- package/src/explorer/context-menu.ts +8 -4
- package/src/explorer/view.tsx +4 -3
- package/src/extensions/canonical-extension-descriptions.ts +58 -0
- package/src/extensions/context-menu.ts +9 -6
- package/src/extensions/extension-enablement-context.ts +15 -0
- package/src/extensions/extension-enablement-controller.ts +453 -0
- package/src/extensions/management-model.ts +111 -47
- package/src/extensions/theme-selection-protection.ts +98 -0
- package/src/extensions/uninstall-eligibility.ts +103 -0
- package/src/extensions/use-extension-management.ts +151 -67
- package/src/extensions/view.tsx +4 -0
- package/src/field-remap/chrome-labels.ts +87 -2
- package/src/field-remap/convert-palette.tsx +164 -18
- package/src/field-remap/demo.tsx +48 -3
- package/src/field-remap/detail-panel.tsx +6 -5
- package/src/field-remap/flow.tsx +341 -155
- package/src/field-remap/history.ts +99 -0
- package/src/field-remap/index.ts +9 -1
- package/src/field-remap/panel.tsx +388 -97
- package/src/field-remap/preview-controller.ts +122 -0
- package/src/field-remap/preview.tsx +171 -0
- package/src/field-remap/view.css +154 -2
- package/src/index.ts +16 -1
- package/src/management/keybinding-overrides-storage.ts +28 -0
- package/src/management/preference-settings-storage.ts +28 -0
- package/src/management/settings.tsx +2 -0
- package/src/management/use-command-management.ts +31 -26
- package/src/management/use-keybinding-management.ts +25 -12
- package/src/shell/focused-extension-services.ts +138 -0
- package/src/shell/host-shell.tsx +13 -10
- package/src/shell/persistence-diagnostic-context.ts +11 -0
- package/src/shell/provider.tsx +373 -69
- package/src/shell/settings.tsx +25 -16
- package/src/shell/shell.tsx +119 -78
- package/src/shell/view-host.tsx +23 -22
- package/src/storage/local-json-storage.ts +43 -29
- package/src/storage/persistence-diagnostics.ts +72 -0
- package/src/workbench/appearance-storage.ts +28 -0
- package/src/workbench/command-host.tsx +19 -22
- package/src/workbench/command-palette.ts +14 -13
- package/src/workbench/layout-storage.ts +52 -5
- package/src/workbench/use-persisted-appearance.ts +38 -12
package/src/shell/settings.tsx
CHANGED
|
@@ -18,13 +18,15 @@ import {
|
|
|
18
18
|
} from '@workbench-kit/react/workbench/settings';
|
|
19
19
|
import {
|
|
20
20
|
applyThemeTokenOverrides,
|
|
21
|
-
type
|
|
21
|
+
type ConfigurationRegistry,
|
|
22
|
+
type LocalizationRegistry,
|
|
22
23
|
type PreferenceService,
|
|
24
|
+
type ThemeRegistry,
|
|
23
25
|
} from '@workbench-kit/workbench-core';
|
|
24
26
|
import type { PreferenceScope } from '@workbench-kit/workbench-config';
|
|
25
27
|
|
|
26
28
|
import { isRecord } from '../is-record.js';
|
|
27
|
-
import { useWorkbench } from './provider.js';
|
|
29
|
+
import { useWorkbench, type WorkbenchExtensionCatalogReader } from './provider.js';
|
|
28
30
|
import { WORKBENCH_PREFERENCE_SCOPES } from './settings-constants.js';
|
|
29
31
|
|
|
30
32
|
const APPEARANCE_SETTINGS_CATEGORY_ID = 'workbench.appearance';
|
|
@@ -60,8 +62,15 @@ export interface WorkbenchSettingsCategoryInput extends WorkbenchAppearanceSetti
|
|
|
60
62
|
preferenceService: PreferenceService;
|
|
61
63
|
}
|
|
62
64
|
|
|
65
|
+
export interface WorkbenchSettingsContributionAccess {
|
|
66
|
+
readonly configurations: ConfigurationRegistry;
|
|
67
|
+
readonly extensionCatalog: WorkbenchExtensionCatalogReader;
|
|
68
|
+
readonly localizations: LocalizationRegistry;
|
|
69
|
+
readonly themes: ThemeRegistry;
|
|
70
|
+
}
|
|
71
|
+
|
|
63
72
|
export function createSettingsCategories(
|
|
64
|
-
|
|
73
|
+
contributions: WorkbenchSettingsContributionAccess,
|
|
65
74
|
{
|
|
66
75
|
activeScope,
|
|
67
76
|
darkPreset,
|
|
@@ -78,9 +87,9 @@ export function createSettingsCategories(
|
|
|
78
87
|
themeOptions,
|
|
79
88
|
}: WorkbenchSettingsCategoryInput,
|
|
80
89
|
): WorkbenchSettingsCategory[] {
|
|
81
|
-
const configurations =
|
|
82
|
-
const mergedThemeOptions = mergeThemeOptions(themeOptions,
|
|
83
|
-
const localeOptions = buildLocaleOptions(
|
|
90
|
+
const configurations = contributions.configurations.getConfigurations();
|
|
91
|
+
const mergedThemeOptions = mergeThemeOptions(themeOptions, contributions.themes.getThemes());
|
|
92
|
+
const localeOptions = buildLocaleOptions(contributions.localizations.getLocalizations());
|
|
84
93
|
const appearanceCategory = createAppearanceSettingsCategory({
|
|
85
94
|
darkPreset,
|
|
86
95
|
lightPreset,
|
|
@@ -115,7 +124,7 @@ export function createSettingsCategories(
|
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
const contributedCategories = configurations.map(({ extensionId, configuration }) => {
|
|
118
|
-
const extension =
|
|
127
|
+
const extension = contributions.extensionCatalog.getExtension(extensionId);
|
|
119
128
|
const displayName = extension?.manifest.displayName ?? titleFromExtensionId(extensionId);
|
|
120
129
|
const properties = Object.entries(configuration.properties ?? {});
|
|
121
130
|
|
|
@@ -263,29 +272,30 @@ function AppearanceSettingsSection({
|
|
|
263
272
|
localeOptions: readonly WorkbenchLocaleOption[];
|
|
264
273
|
themeOptions: readonly WorkbenchThemeOption[];
|
|
265
274
|
}) {
|
|
266
|
-
const {
|
|
275
|
+
const { themes } = useWorkbench();
|
|
276
|
+
const themeRevision = themes.getRevision();
|
|
267
277
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
268
278
|
const previousThemeOverridesRef = useRef<Readonly<Record<string, string>> | undefined>(undefined);
|
|
269
279
|
const usesAppearancePresets = lightPreset !== undefined && darkPreset !== undefined;
|
|
270
280
|
const lightPresetOptions = useMemo<readonly WorkbenchThemePresetOption[]>(
|
|
271
281
|
() => [
|
|
272
282
|
...LIGHT_THEME_PRESET_OPTIONS,
|
|
273
|
-
...
|
|
283
|
+
...themes
|
|
274
284
|
.getThemes()
|
|
275
285
|
.filter((contributedTheme) => contributedTheme.mode === 'light')
|
|
276
286
|
.map((contributedTheme) => ({ id: contributedTheme.id, label: contributedTheme.label })),
|
|
277
287
|
],
|
|
278
|
-
[
|
|
288
|
+
[themeRevision, themes],
|
|
279
289
|
);
|
|
280
290
|
const darkPresetOptions = useMemo<readonly WorkbenchThemePresetOption[]>(
|
|
281
291
|
() => [
|
|
282
292
|
...DARK_THEME_PRESET_OPTIONS,
|
|
283
|
-
...
|
|
293
|
+
...themes
|
|
284
294
|
.getThemes()
|
|
285
295
|
.filter((contributedTheme) => contributedTheme.mode === 'dark')
|
|
286
296
|
.map((contributedTheme) => ({ id: contributedTheme.id, label: contributedTheme.label })),
|
|
287
297
|
],
|
|
288
|
-
[
|
|
298
|
+
[themeRevision, themes],
|
|
289
299
|
);
|
|
290
300
|
const selectedTheme = themeOptions.find((option) => option.id === theme) ?? themeOptions[0];
|
|
291
301
|
const selectedThemeId = selectedTheme?.id ?? '';
|
|
@@ -333,9 +343,7 @@ function AppearanceSettingsSection({
|
|
|
333
343
|
activeThemeId = selectedThemeId;
|
|
334
344
|
}
|
|
335
345
|
|
|
336
|
-
const contributedTheme = activeThemeId
|
|
337
|
-
? extensionRegistry.themes.getTheme(activeThemeId)
|
|
338
|
-
: undefined;
|
|
346
|
+
const contributedTheme = activeThemeId ? themes.getTheme(activeThemeId) : undefined;
|
|
339
347
|
|
|
340
348
|
// The actual workbench root (e.g. `.ide-root`) re-declares `data-theme-preset` locally,
|
|
341
349
|
// which shadows inheritance from `documentElement` for everything rendered inside it.
|
|
@@ -357,7 +365,8 @@ function AppearanceSettingsSection({
|
|
|
357
365
|
}
|
|
358
366
|
previousThemeOverridesRef.current = contributedTheme?.tokenOverrides;
|
|
359
367
|
}, [
|
|
360
|
-
|
|
368
|
+
themeRevision,
|
|
369
|
+
themes,
|
|
361
370
|
selectedColorSchemeId,
|
|
362
371
|
selectedDarkPreset.id,
|
|
363
372
|
selectedLightPreset.id,
|
package/src/shell/shell.tsx
CHANGED
|
@@ -10,10 +10,7 @@ import {
|
|
|
10
10
|
type StatusBarItemModel,
|
|
11
11
|
type StatusBarSectionModel,
|
|
12
12
|
} from '@workbench-kit/react/workbench/shell';
|
|
13
|
-
import {
|
|
14
|
-
WORKBENCH_SETTINGS_CAPABILITY_ID,
|
|
15
|
-
filterActivitiesByWhenClause,
|
|
16
|
-
} from '@workbench-kit/workbench-core';
|
|
13
|
+
import { filterActivitiesByWhenClause } from '@workbench-kit/workbench-core';
|
|
17
14
|
import type {
|
|
18
15
|
ExtensionCatalogTrustPolicy,
|
|
19
16
|
WorkbenchSettingsCapability,
|
|
@@ -24,9 +21,13 @@ import {
|
|
|
24
21
|
resolveActiveThemePreset,
|
|
25
22
|
DEFAULT_SHELL_PRESET,
|
|
26
23
|
useResolvedWorkbenchTheme,
|
|
24
|
+
type WorkbenchCommandDescriptor,
|
|
25
|
+
type WorkbenchCommandRunContext,
|
|
27
26
|
} from '@workbench-kit/react/workbench';
|
|
28
27
|
|
|
29
28
|
import { BUILTIN_COMMANDS_VIEW_CONTAINER_ID } from '../commands/view-data.js';
|
|
29
|
+
import { useExtensionEnablementController } from '../extensions/extension-enablement-context.js';
|
|
30
|
+
import { createThemeSelectionProtectionSnapshot } from '../extensions/theme-selection-protection.js';
|
|
30
31
|
import { BUILTIN_EXTENSIONS_VIEW_CONTAINER_ID } from '../extensions/view-data.js';
|
|
31
32
|
import {
|
|
32
33
|
filterActivityBarItems,
|
|
@@ -85,6 +86,20 @@ import {
|
|
|
85
86
|
} from './layout-metrics.js';
|
|
86
87
|
export type { WorkbenchLocaleOption, WorkbenchThemeOption } from './settings.js';
|
|
87
88
|
|
|
89
|
+
export interface WorkbenchShellCommandRunContext extends WorkbenchCommandRunContext {
|
|
90
|
+
openSettings(categoryId?: string): void;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface WorkbenchShellCommandHostProps extends Omit<
|
|
94
|
+
WorkbenchCommandHostProps,
|
|
95
|
+
'onOpenSettings' | 'onRunCommand'
|
|
96
|
+
> {
|
|
97
|
+
onRunCommand?: (
|
|
98
|
+
command: WorkbenchCommandDescriptor,
|
|
99
|
+
context: WorkbenchShellCommandRunContext,
|
|
100
|
+
) => boolean | void;
|
|
101
|
+
}
|
|
102
|
+
|
|
88
103
|
export interface WorkbenchShellProps {
|
|
89
104
|
accountManagement?: WorkbenchAccountManagementInput | undefined;
|
|
90
105
|
additionalSettingsCategories?: readonly WorkbenchSettingsCategory[] | undefined;
|
|
@@ -92,7 +107,7 @@ export interface WorkbenchShellProps {
|
|
|
92
107
|
appIcon?: ReactNode;
|
|
93
108
|
catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
|
|
94
109
|
catalogUrl?: string | undefined;
|
|
95
|
-
commandHost?: false |
|
|
110
|
+
commandHost?: false | WorkbenchShellCommandHostProps;
|
|
96
111
|
compactStatus?: boolean;
|
|
97
112
|
darkPreset?: string | undefined;
|
|
98
113
|
editorArea?: ReactNode;
|
|
@@ -190,19 +205,42 @@ export function WorkbenchShell({
|
|
|
190
205
|
? resolveActiveThemePreset(resolvedWorkbenchTheme, { darkPreset, lightPreset })
|
|
191
206
|
: undefined;
|
|
192
207
|
const {
|
|
208
|
+
activities,
|
|
209
|
+
commands,
|
|
210
|
+
configurations,
|
|
193
211
|
contextKeyService,
|
|
194
212
|
executeCommand,
|
|
195
|
-
|
|
213
|
+
extensionActivation,
|
|
214
|
+
extensionCatalog,
|
|
196
215
|
layoutService,
|
|
216
|
+
localizations,
|
|
197
217
|
missingExtensionIds,
|
|
198
218
|
preferenceService,
|
|
219
|
+
settingsCapabilityPublisher,
|
|
220
|
+
statusBar,
|
|
221
|
+
themes,
|
|
222
|
+
viewHostFactories,
|
|
223
|
+
views,
|
|
199
224
|
} = useWorkbench();
|
|
225
|
+
const extensionEnablement = useExtensionEnablementController();
|
|
200
226
|
const contextKeyRevision = useContextKeyRevision(contextKeyService);
|
|
201
227
|
const contextKeySnapshot = useMemo(
|
|
202
228
|
() => contextKeyService.createSnapshot(),
|
|
203
229
|
[contextKeyRevision, contextKeyService],
|
|
204
230
|
);
|
|
205
231
|
const forceRender = useForceRender();
|
|
232
|
+
const themeRevision = themes.getRevision();
|
|
233
|
+
const themeSelectionProtection = useMemo(
|
|
234
|
+
() =>
|
|
235
|
+
createThemeSelectionProtectionSnapshot({
|
|
236
|
+
darkPreset,
|
|
237
|
+
lightPreset,
|
|
238
|
+
theme,
|
|
239
|
+
themeOptions,
|
|
240
|
+
themes,
|
|
241
|
+
}),
|
|
242
|
+
[darkPreset, lightPreset, theme, themeOptions, themeRevision, themes],
|
|
243
|
+
);
|
|
206
244
|
const [preferenceRevision, bumpPreferenceRevision] = useReducer((count: number) => count + 1, 0);
|
|
207
245
|
const [isHelpOpen, setHelpOpen] = useState(false);
|
|
208
246
|
const [isProfileOpen, setProfileOpen] = useState(false);
|
|
@@ -228,32 +266,28 @@ export function WorkbenchShell({
|
|
|
228
266
|
statusSections ??
|
|
229
267
|
mergeWorkbenchStatusSections(
|
|
230
268
|
createDefaultWorkbenchStatusSections({
|
|
231
|
-
dependencyDiagnostics:
|
|
232
|
-
extensionCount:
|
|
269
|
+
dependencyDiagnostics: extensionCatalog.getDependencyDiagnostics(),
|
|
270
|
+
extensionCount: extensionCatalog.getExtensions().length,
|
|
233
271
|
missingExtensionIds,
|
|
234
272
|
profile,
|
|
235
273
|
}),
|
|
236
|
-
createContributedWorkbenchStatusSections(
|
|
274
|
+
createContributedWorkbenchStatusSections(statusBar.getStatusBarItems()),
|
|
237
275
|
),
|
|
238
|
-
[
|
|
276
|
+
[extensionCatalog, missingExtensionIds, profile, statusBar, statusSections],
|
|
239
277
|
);
|
|
240
278
|
const activeViewContainerId = layout.sideBar.activeViewContainer;
|
|
241
279
|
const activePanelViewContainerId = layout.panel.activeViewContainer;
|
|
242
|
-
const panelViewContainers =
|
|
280
|
+
const panelViewContainers = views.getViewContainers('panel');
|
|
243
281
|
const visibleActivities = useMemo(
|
|
244
|
-
() =>
|
|
245
|
-
|
|
246
|
-
extensionRegistry.activities.getActivities(),
|
|
247
|
-
contextKeySnapshot,
|
|
248
|
-
),
|
|
249
|
-
[contextKeySnapshot, extensionRegistry],
|
|
282
|
+
() => filterActivitiesByWhenClause(activities.getActivities(), contextKeySnapshot),
|
|
283
|
+
[activities, contextKeySnapshot],
|
|
250
284
|
);
|
|
251
285
|
const activityItems = sortActivityBarItems(
|
|
252
286
|
createWorkbenchShellActivityItems({
|
|
253
287
|
activeViewContainerId,
|
|
254
288
|
activities: visibleActivities,
|
|
255
|
-
viewContainers:
|
|
256
|
-
views:
|
|
289
|
+
viewContainers: views.getViewContainers('activitybar'),
|
|
290
|
+
views: views.getViews(),
|
|
257
291
|
}),
|
|
258
292
|
layout.activityBar.itemOrder,
|
|
259
293
|
);
|
|
@@ -278,6 +312,13 @@ export function WorkbenchShell({
|
|
|
278
312
|
settingsLabel: chromeLabels.settingsLabel,
|
|
279
313
|
});
|
|
280
314
|
|
|
315
|
+
useEffect(() => {
|
|
316
|
+
extensionEnablement.setThemeSelectionProtection(themeSelectionProtection);
|
|
317
|
+
return () => {
|
|
318
|
+
extensionEnablement.setThemeSelectionProtection(undefined);
|
|
319
|
+
};
|
|
320
|
+
}, [extensionEnablement, themeSelectionProtection]);
|
|
321
|
+
|
|
281
322
|
useEffect(() => {
|
|
282
323
|
if (visibleActivityItems.length === 0) {
|
|
283
324
|
return;
|
|
@@ -332,30 +373,35 @@ export function WorkbenchShell({
|
|
|
332
373
|
return [
|
|
333
374
|
...managementCategories,
|
|
334
375
|
...(additionalSettingsCategories ?? []),
|
|
335
|
-
...createSettingsCategories(
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
376
|
+
...createSettingsCategories(
|
|
377
|
+
{ configurations, extensionCatalog, localizations, themes },
|
|
378
|
+
{
|
|
379
|
+
activeScope: settingsScopeId,
|
|
380
|
+
darkPreset,
|
|
381
|
+
lightPreset,
|
|
382
|
+
locale,
|
|
383
|
+
onDarkPresetChange,
|
|
384
|
+
onLightPresetChange,
|
|
385
|
+
onLocaleChange,
|
|
386
|
+
onShellPresetChange,
|
|
387
|
+
onThemeChange,
|
|
388
|
+
preferenceService,
|
|
389
|
+
shellPreset,
|
|
390
|
+
theme,
|
|
391
|
+
themeOptions,
|
|
392
|
+
},
|
|
393
|
+
),
|
|
350
394
|
];
|
|
351
395
|
}, [
|
|
352
396
|
accountManagement,
|
|
353
397
|
additionalSettingsCategories,
|
|
354
398
|
commandHost,
|
|
355
399
|
darkPreset,
|
|
356
|
-
|
|
400
|
+
configurations,
|
|
401
|
+
extensionCatalog,
|
|
357
402
|
lightPreset,
|
|
358
403
|
locale,
|
|
404
|
+
localizations,
|
|
359
405
|
onDarkPresetChange,
|
|
360
406
|
onLightPresetChange,
|
|
361
407
|
onLocaleChange,
|
|
@@ -366,12 +412,14 @@ export function WorkbenchShell({
|
|
|
366
412
|
settingsScopeId,
|
|
367
413
|
shellPreset,
|
|
368
414
|
theme,
|
|
415
|
+
themeRevision,
|
|
416
|
+
themes,
|
|
369
417
|
themeOptions,
|
|
370
418
|
]);
|
|
371
419
|
const defaultSettingsCategoryId =
|
|
372
420
|
settingsCategories.find((category) => category.id === SETTINGS_EXTENSION_ID)?.id ??
|
|
373
421
|
settingsCategories[0]?.id;
|
|
374
|
-
const settingsContributionCount =
|
|
422
|
+
const settingsContributionCount = configurations.getConfigurations().length;
|
|
375
423
|
const showHelpModal = useCallback(() => {
|
|
376
424
|
setSettingsOpen(false);
|
|
377
425
|
setProfileOpen(false);
|
|
@@ -412,15 +460,17 @@ export function WorkbenchShell({
|
|
|
412
460
|
|
|
413
461
|
useEffect(() => {
|
|
414
462
|
const layoutDisposable = layoutService.onDidChangeLayout(forceRender);
|
|
415
|
-
const viewProviderDisposable =
|
|
463
|
+
const viewProviderDisposable = views.onDidRegisterViewProvider(forceRender);
|
|
416
464
|
const preferenceDisposable = preferenceService.onDidChangePreference(bumpPreferenceRevision);
|
|
465
|
+
const themeDisposable = themes.onDidChangeThemes(forceRender);
|
|
417
466
|
|
|
418
467
|
return () => {
|
|
419
468
|
layoutDisposable.dispose();
|
|
420
469
|
viewProviderDisposable.dispose();
|
|
421
470
|
preferenceDisposable.dispose();
|
|
471
|
+
themeDisposable.dispose();
|
|
422
472
|
};
|
|
423
|
-
}, [
|
|
473
|
+
}, [forceRender, layoutService, preferenceService, themes, views]);
|
|
424
474
|
|
|
425
475
|
useEffect(() => {
|
|
426
476
|
if (!activeViewContainerId) {
|
|
@@ -428,13 +478,13 @@ export function WorkbenchShell({
|
|
|
428
478
|
}
|
|
429
479
|
|
|
430
480
|
for (const view of getVisibleWorkbenchViews(
|
|
431
|
-
|
|
481
|
+
{ views },
|
|
432
482
|
activeViewContainerId,
|
|
433
483
|
contextKeySnapshot,
|
|
434
484
|
)) {
|
|
435
|
-
void
|
|
485
|
+
void extensionActivation.activateView(view.id).then(forceRender);
|
|
436
486
|
}
|
|
437
|
-
}, [activeViewContainerId, contextKeySnapshot,
|
|
487
|
+
}, [activeViewContainerId, contextKeySnapshot, extensionActivation, forceRender, views]);
|
|
438
488
|
|
|
439
489
|
useEffect(() => {
|
|
440
490
|
if (!activePanelViewContainerId) {
|
|
@@ -442,54 +492,44 @@ export function WorkbenchShell({
|
|
|
442
492
|
}
|
|
443
493
|
|
|
444
494
|
for (const view of getVisibleWorkbenchViews(
|
|
445
|
-
|
|
495
|
+
{ views },
|
|
446
496
|
activePanelViewContainerId,
|
|
447
497
|
contextKeySnapshot,
|
|
448
498
|
)) {
|
|
449
|
-
void
|
|
499
|
+
void extensionActivation.activateView(view.id).then(forceRender);
|
|
450
500
|
}
|
|
451
|
-
}, [activePanelViewContainerId, contextKeySnapshot,
|
|
501
|
+
}, [activePanelViewContainerId, contextKeySnapshot, extensionActivation, forceRender, views]);
|
|
452
502
|
|
|
453
503
|
useEffect(() => {
|
|
454
504
|
if (!layout.auxiliaryBar.visible) {
|
|
455
505
|
return;
|
|
456
506
|
}
|
|
457
507
|
|
|
458
|
-
for (const container of
|
|
459
|
-
for (const view of getVisibleWorkbenchViews(
|
|
460
|
-
|
|
461
|
-
container.id,
|
|
462
|
-
contextKeySnapshot,
|
|
463
|
-
)) {
|
|
464
|
-
void extensionRegistry.activateView(view.id).then(forceRender);
|
|
508
|
+
for (const container of views.getViewContainers('auxiliarybar')) {
|
|
509
|
+
for (const view of getVisibleWorkbenchViews({ views }, container.id, contextKeySnapshot)) {
|
|
510
|
+
void extensionActivation.activateView(view.id).then(forceRender);
|
|
465
511
|
}
|
|
466
512
|
}
|
|
467
|
-
}, [contextKeySnapshot,
|
|
513
|
+
}, [contextKeySnapshot, extensionActivation, forceRender, layout.auxiliaryBar.visible, views]);
|
|
468
514
|
|
|
469
515
|
useEffect(() => {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
const disposable = extensionRegistry.capabilityRegistry.register({
|
|
475
|
-
id: WORKBENCH_SETTINGS_CAPABILITY_ID,
|
|
476
|
-
get: () => settingsCapability,
|
|
477
|
-
});
|
|
516
|
+
const publication = settingsCapabilityPublisher.publishSettingsCapability(settingsCapability);
|
|
517
|
+
if (publication.kind === 'already-registered') return undefined;
|
|
478
518
|
|
|
479
519
|
return () => {
|
|
480
|
-
disposable.dispose();
|
|
520
|
+
publication.disposable.dispose();
|
|
481
521
|
};
|
|
482
|
-
}, [
|
|
522
|
+
}, [settingsCapability, settingsCapabilityPublisher]);
|
|
483
523
|
|
|
484
|
-
const openSettings = (
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
categoryId === undefined &&
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
524
|
+
const openSettings = useCallback(
|
|
525
|
+
(categoryId?: string) => {
|
|
526
|
+
showSettingsModal(categoryId);
|
|
527
|
+
if (categoryId === undefined && commands.hasCommand(OPEN_SETTINGS_COMMAND_ID)) {
|
|
528
|
+
void executeCommand(OPEN_SETTINGS_COMMAND_ID).catch(() => undefined);
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
[commands, executeCommand, showSettingsModal],
|
|
532
|
+
);
|
|
493
533
|
|
|
494
534
|
const resolvedCommandHost = useMemo(():
|
|
495
535
|
false | Omit<WorkbenchCommandHostProps, 'onOpenSettings'> => {
|
|
@@ -540,10 +580,10 @@ export function WorkbenchShell({
|
|
|
540
580
|
return true;
|
|
541
581
|
}
|
|
542
582
|
|
|
543
|
-
return hostProps.onRunCommand?.(command, context) ?? false;
|
|
583
|
+
return hostProps.onRunCommand?.(command, { ...context, openSettings }) ?? false;
|
|
544
584
|
},
|
|
545
585
|
};
|
|
546
|
-
}, [chromeLabels, commandHost, layoutService]);
|
|
586
|
+
}, [chromeLabels, commandHost, layoutService, openSettings]);
|
|
547
587
|
|
|
548
588
|
const handleStatusItemActivate = useCallback(
|
|
549
589
|
(item: StatusBarItemModel) => {
|
|
@@ -561,7 +601,7 @@ export function WorkbenchShell({
|
|
|
561
601
|
return;
|
|
562
602
|
}
|
|
563
603
|
|
|
564
|
-
const contributed =
|
|
604
|
+
const contributed = statusBar.getStatusBarItem(item.id);
|
|
565
605
|
if (contributed?.command) {
|
|
566
606
|
void executeCommand(contributed.command).catch(() => undefined);
|
|
567
607
|
return;
|
|
@@ -572,10 +612,11 @@ export function WorkbenchShell({
|
|
|
572
612
|
[
|
|
573
613
|
accountManagement,
|
|
574
614
|
executeCommand,
|
|
575
|
-
extensionRegistry,
|
|
576
615
|
onStatusItemActivate,
|
|
616
|
+
openSettings,
|
|
577
617
|
profile,
|
|
578
618
|
showProfileModal,
|
|
619
|
+
statusBar,
|
|
579
620
|
],
|
|
580
621
|
);
|
|
581
622
|
|
|
@@ -619,7 +660,7 @@ export function WorkbenchShell({
|
|
|
619
660
|
node:
|
|
620
661
|
primarySidebar ??
|
|
621
662
|
renderDefaultPrimarySidebar(
|
|
622
|
-
|
|
663
|
+
{ viewHostFactories, views },
|
|
623
664
|
activeViewContainerId,
|
|
624
665
|
catalogUrl,
|
|
625
666
|
catalogTrustPolicy,
|
|
@@ -633,7 +674,7 @@ export function WorkbenchShell({
|
|
|
633
674
|
auxiliarySidebar={{
|
|
634
675
|
isVisible: layout.auxiliaryBar.visible,
|
|
635
676
|
node: renderDefaultAuxiliarySidebar(
|
|
636
|
-
|
|
677
|
+
{ viewHostFactories, views },
|
|
637
678
|
contextKeySnapshot,
|
|
638
679
|
catalogUrl,
|
|
639
680
|
catalogTrustPolicy,
|
|
@@ -641,7 +682,7 @@ export function WorkbenchShell({
|
|
|
641
682
|
}}
|
|
642
683
|
bottomPanel={{
|
|
643
684
|
isVisible: layout.panel.visible,
|
|
644
|
-
node: renderDefaultBottomPanel(
|
|
685
|
+
node: renderDefaultBottomPanel({ viewHostFactories, views }, activePanelViewContainerId, {
|
|
645
686
|
catalogTrustPolicy,
|
|
646
687
|
catalogUrl,
|
|
647
688
|
contextKeys: contextKeySnapshot,
|
package/src/shell/view-host.tsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isValidElement, useEffect, useMemo, useRef, type FocusEvent, type ReactNode } from 'react';
|
|
2
2
|
import type {
|
|
3
3
|
ExtensionCatalogTrustPolicy,
|
|
4
|
-
ExtensionRegistry,
|
|
5
4
|
ViewHost,
|
|
6
5
|
ViewHostFactoryRegistry,
|
|
6
|
+
ViewRegistry,
|
|
7
7
|
ViewProvider,
|
|
8
8
|
WorkbenchViewContribution,
|
|
9
9
|
} from '@workbench-kit/workbench-core';
|
|
@@ -12,6 +12,11 @@ import {
|
|
|
12
12
|
type WorkbenchContextKeySnapshot,
|
|
13
13
|
} from '@workbench-kit/platform';
|
|
14
14
|
|
|
15
|
+
export interface WorkbenchViewContributionAccess {
|
|
16
|
+
readonly viewHostFactories: ViewHostFactoryRegistry;
|
|
17
|
+
readonly views: ViewRegistry;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
import { BuiltinChatView } from '../chat/view.js';
|
|
16
21
|
import { isBuiltinChatViewRenderData } from '../chat/view-data.js';
|
|
17
22
|
import { BuiltinCommandsView } from '../commands/view.js';
|
|
@@ -24,15 +29,15 @@ import { BuiltinSearchView } from '../explorer/search-view.js';
|
|
|
24
29
|
import { isBuiltinSearchViewRenderData } from '../explorer/search-view-data.js';
|
|
25
30
|
|
|
26
31
|
export function renderDefaultPrimarySidebar(
|
|
27
|
-
|
|
32
|
+
access: WorkbenchViewContributionAccess,
|
|
28
33
|
activeViewContainerId: string | undefined,
|
|
29
34
|
catalogUrl?: string | undefined,
|
|
30
35
|
catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined,
|
|
31
36
|
contextKeys: WorkbenchContextKeySnapshot = {},
|
|
32
37
|
) {
|
|
33
38
|
const views = activeViewContainerId
|
|
34
|
-
? getVisibleWorkbenchViews(
|
|
35
|
-
: filterWorkbenchContributionsByWhenClause(
|
|
39
|
+
? getVisibleWorkbenchViews(access, activeViewContainerId, contextKeys)
|
|
40
|
+
: filterWorkbenchContributionsByWhenClause(access.views.getViews(), contextKeys);
|
|
36
41
|
if (views.length === 0) {
|
|
37
42
|
return <aside aria-label="Primary sidebar" />;
|
|
38
43
|
}
|
|
@@ -42,33 +47,33 @@ export function renderDefaultPrimarySidebar(
|
|
|
42
47
|
aria-label="Primary sidebar"
|
|
43
48
|
className="workbench-primary-side-bar shell-react-sidebar-host"
|
|
44
49
|
>
|
|
45
|
-
{renderWorkbenchViews(
|
|
50
|
+
{renderWorkbenchViews(access, views, { catalogTrustPolicy, catalogUrl })}
|
|
46
51
|
</aside>
|
|
47
52
|
);
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
export function renderDefaultAuxiliarySidebar(
|
|
51
|
-
|
|
56
|
+
access: WorkbenchViewContributionAccess,
|
|
52
57
|
contextKeys: WorkbenchContextKeySnapshot,
|
|
53
58
|
catalogUrl?: string | undefined,
|
|
54
59
|
catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined,
|
|
55
60
|
) {
|
|
56
|
-
const views =
|
|
61
|
+
const views = access.views
|
|
57
62
|
.getViewContainers('auxiliarybar')
|
|
58
|
-
.flatMap((container) => getVisibleWorkbenchViews(
|
|
63
|
+
.flatMap((container) => getVisibleWorkbenchViews(access, container.id, contextKeys));
|
|
59
64
|
|
|
60
65
|
return (
|
|
61
66
|
<aside
|
|
62
67
|
aria-label="Secondary Side Bar"
|
|
63
68
|
className="workbench-auxiliary-side-bar shell-react-sidebar-host"
|
|
64
69
|
>
|
|
65
|
-
{renderWorkbenchViews(
|
|
70
|
+
{renderWorkbenchViews(access, views, { catalogTrustPolicy, catalogUrl })}
|
|
66
71
|
</aside>
|
|
67
72
|
);
|
|
68
73
|
}
|
|
69
74
|
|
|
70
75
|
export function renderDefaultBottomPanel(
|
|
71
|
-
|
|
76
|
+
access: WorkbenchViewContributionAccess,
|
|
72
77
|
activeViewContainerId: string | undefined,
|
|
73
78
|
options: {
|
|
74
79
|
catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
|
|
@@ -77,7 +82,7 @@ export function renderDefaultBottomPanel(
|
|
|
77
82
|
onActiveViewContainerChange?: ((viewContainerId: string) => void) | undefined;
|
|
78
83
|
} = {},
|
|
79
84
|
) {
|
|
80
|
-
const containers =
|
|
85
|
+
const containers = access.views.getViewContainers('panel');
|
|
81
86
|
if (containers.length === 0) {
|
|
82
87
|
return (
|
|
83
88
|
<section aria-label="Panel" className="workbench-bottom-panel">
|
|
@@ -92,11 +97,7 @@ export function renderDefaultBottomPanel(
|
|
|
92
97
|
? activeViewContainerId
|
|
93
98
|
: containers[0]?.id;
|
|
94
99
|
const views = resolvedActiveViewContainerId
|
|
95
|
-
? getVisibleWorkbenchViews(
|
|
96
|
-
extensionRegistry,
|
|
97
|
-
resolvedActiveViewContainerId,
|
|
98
|
-
options.contextKeys ?? {},
|
|
99
|
-
)
|
|
100
|
+
? getVisibleWorkbenchViews(access, resolvedActiveViewContainerId, options.contextKeys ?? {})
|
|
100
101
|
: [];
|
|
101
102
|
|
|
102
103
|
return (
|
|
@@ -127,7 +128,7 @@ export function renderDefaultBottomPanel(
|
|
|
127
128
|
{views.length === 0 ? (
|
|
128
129
|
<div className="workbench-bottom-panel__empty">No views in this panel container.</div>
|
|
129
130
|
) : (
|
|
130
|
-
renderWorkbenchViews(
|
|
131
|
+
renderWorkbenchViews(access, views, {
|
|
131
132
|
catalogTrustPolicy: options.catalogTrustPolicy,
|
|
132
133
|
catalogUrl: options.catalogUrl,
|
|
133
134
|
sectionClassName: 'workbench-bottom-panel__view',
|
|
@@ -139,18 +140,18 @@ export function renderDefaultBottomPanel(
|
|
|
139
140
|
}
|
|
140
141
|
|
|
141
142
|
export function getVisibleWorkbenchViews(
|
|
142
|
-
|
|
143
|
+
access: Pick<WorkbenchViewContributionAccess, 'views'>,
|
|
143
144
|
viewContainerId: string,
|
|
144
145
|
contextKeys: WorkbenchContextKeySnapshot,
|
|
145
146
|
): WorkbenchViewContribution[] {
|
|
146
147
|
return filterWorkbenchContributionsByWhenClause(
|
|
147
|
-
|
|
148
|
+
access.views.getViews(viewContainerId),
|
|
148
149
|
contextKeys,
|
|
149
150
|
);
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
function renderWorkbenchViews(
|
|
153
|
-
|
|
154
|
+
access: WorkbenchViewContributionAccess,
|
|
154
155
|
views: readonly WorkbenchViewContribution[],
|
|
155
156
|
options: {
|
|
156
157
|
catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
|
|
@@ -169,8 +170,8 @@ function renderWorkbenchViews(
|
|
|
169
170
|
catalogTrustPolicy={options.catalogTrustPolicy}
|
|
170
171
|
catalogUrl={options.catalogUrl}
|
|
171
172
|
fallback={view.name}
|
|
172
|
-
provider={
|
|
173
|
-
viewHostFactories={
|
|
173
|
+
provider={access.views.getViewProvider(view.id)}
|
|
174
|
+
viewHostFactories={access.viewHostFactories}
|
|
174
175
|
viewId={view.id}
|
|
175
176
|
/>
|
|
176
177
|
</section>
|