@workbench-kit/shell-react 0.0.2-prototype.0.2.41 → 0.0.2-prototype.0.2.44

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.
Files changed (39) hide show
  1. package/README.md +81 -2
  2. package/package.json +14 -10
  3. package/src/editor/workspace-reconcile.tsx +12 -7
  4. package/src/extensions/extension-enablement-controller.ts +40 -9
  5. package/src/extensions/theme-selection-protection.ts +80 -55
  6. package/src/field-remap/chrome-labels.ts +117 -0
  7. package/src/field-remap/convert-note-editor.tsx +119 -104
  8. package/src/field-remap/convert-palette.tsx +6 -0
  9. package/src/field-remap/demo.tsx +8 -2
  10. package/src/field-remap/detail-panel.tsx +535 -434
  11. package/src/field-remap/document-io.tsx +299 -0
  12. package/src/field-remap/drag-payload.ts +48 -0
  13. package/src/field-remap/flow-adapter.ts +216 -88
  14. package/src/field-remap/flow-ops.ts +150 -0
  15. package/src/field-remap/flow.tsx +1227 -272
  16. package/src/field-remap/index.ts +2 -0
  17. package/src/field-remap/io-class-browse.tsx +34 -22
  18. package/src/field-remap/keyboard.ts +16 -0
  19. package/src/field-remap/modal-detail.tsx +34 -0
  20. package/src/field-remap/panel.tsx +110 -14
  21. package/src/field-remap/transform-options-editor.tsx +68 -48
  22. package/src/field-remap/view.css +107 -189
  23. package/src/index.ts +7 -0
  24. package/src/keybinding-management-settings.ts +4 -0
  25. package/src/management/keybinding-overrides-storage.ts +48 -23
  26. package/src/management/keybinding-settings-view.tsx +31 -0
  27. package/src/management/keybinding-settings.tsx +4 -12
  28. package/src/management/use-keybinding-management.ts +72 -22
  29. package/src/shell/appearance-catalog.ts +453 -0
  30. package/src/shell/appearance-controller.ts +331 -0
  31. package/src/shell/appearance-presentation.ts +269 -0
  32. package/src/shell/provider.tsx +157 -19
  33. package/src/shell/settings.tsx +282 -153
  34. package/src/shell/shell.tsx +88 -18
  35. package/src/workbench/appearance-storage.ts +2 -2
  36. package/src/workbench/command-host-controller.tsx +223 -0
  37. package/src/workbench/command-host.tsx +100 -150
  38. package/src/workbench/keybinding-bridge.ts +84 -38
  39. package/src/workbench/shell-command-registration.ts +27 -2
@@ -3,11 +3,14 @@ import {
3
3
  useCallback,
4
4
  useContext,
5
5
  useEffect,
6
+ useLayoutEffect,
6
7
  useMemo,
7
8
  useRef,
8
9
  useState,
9
10
  type ReactNode,
10
11
  } from 'react';
12
+ import type { WorkbenchKeybindingManagementSettingsViewProps } from '../management/keybinding-settings-view.js';
13
+ import { useKeybindingManagementModel } from '../management/use-keybinding-management.js';
11
14
  import {
12
15
  collectConfigurationDefaults,
13
16
  createEditorService,
@@ -46,9 +49,15 @@ import {
46
49
  import {
47
50
  ContextKeyService,
48
51
  createWorkbenchPermissionContextKeys,
52
+ projectCommandRegistryKeybindings,
53
+ resetManagedKeybindingOverride,
54
+ resolveWorkbenchShortcutPlatform,
55
+ setManagedKeybindingOverride,
49
56
  type CommandRegistry,
57
+ type CommandRegistryKeybindingProjection,
50
58
  type ContextKeyValue,
51
59
  type KeybindingRegistry,
60
+ type WorkbenchShortcutPlatform,
52
61
  } from '@workbench-kit/platform';
53
62
  import type {
54
63
  WorkbenchExtensionsConfig,
@@ -74,6 +83,7 @@ import {
74
83
  isWorkbenchKeybindingPersistenceAvailable,
75
84
  readPersistedKeybindingOverridesResult,
76
85
  writePersistedKeybindingOverridesResult,
86
+ type PersistedKeybindingOverridesReadResult,
77
87
  } from '../management/keybinding-overrides-storage.js';
78
88
  import {
79
89
  BUILTIN_EXPLORER_VIEW_CONTAINER_ID,
@@ -199,7 +209,10 @@ export interface WorkbenchContextValue {
199
209
  installedExtensionsStorage?: WorkbenchStorageAdapter;
200
210
  installedExtensionsStorageKey: string;
201
211
  keybindings: KeybindingRegistry;
212
+ keybindingEditingDisabledReason?: string | undefined;
202
213
  keybindingOverrides: readonly WorkbenchKeybindingDefinition[];
214
+ keybindingPlatform: WorkbenchShortcutPlatform;
215
+ keybindingProjection: CommandRegistryKeybindingProjection;
203
216
  layoutService: LayoutService;
204
217
  localizations: LocalizationRegistry;
205
218
  menus: MenuRegistry;
@@ -237,8 +250,10 @@ interface DeferredProviderDispose {
237
250
  }
238
251
 
239
252
  interface KeybindingOverridesState {
253
+ readonly dirty: boolean;
240
254
  readonly initialOverrides: readonly WorkbenchKeybindingDefinition[] | undefined;
241
255
  readonly overrides: readonly WorkbenchKeybindingDefinition[];
256
+ readonly platform: WorkbenchShortcutPlatform;
242
257
  readonly shouldPersist: boolean;
243
258
  readonly storage: WorkbenchStorageAdapter | undefined;
244
259
  readonly storageKey: string;
@@ -253,9 +268,11 @@ function isKeybindingStateCurrent(
253
268
  shouldPersist: boolean,
254
269
  storage: WorkbenchStorageAdapter | undefined,
255
270
  storageKey: string,
271
+ platform: WorkbenchShortcutPlatform,
256
272
  ): boolean {
257
273
  return (
258
274
  state.initialOverrides === initialOverrides &&
275
+ state.platform === platform &&
259
276
  state.shouldPersist === shouldPersist &&
260
277
  state.storage === storage &&
261
278
  state.storageKey === storageKey
@@ -264,19 +281,21 @@ function isKeybindingStateCurrent(
264
281
 
265
282
  function createKeybindingOverridesState(
266
283
  initialOverrides: readonly WorkbenchKeybindingDefinition[] | undefined,
267
- resolvedOverrides: readonly WorkbenchKeybindingDefinition[],
268
- readFailed: boolean,
284
+ resolved: PersistedKeybindingOverridesReadResult,
269
285
  shouldPersist: boolean,
270
286
  storage: WorkbenchStorageAdapter | undefined,
271
287
  storageKey: string,
288
+ platform: WorkbenchShortcutPlatform,
272
289
  ): KeybindingOverridesState {
273
290
  return {
291
+ dirty: false,
274
292
  initialOverrides,
275
- overrides: resolvedOverrides,
293
+ overrides: resolved.value,
294
+ platform,
276
295
  shouldPersist,
277
296
  storage,
278
297
  storageKey,
279
- writeEligible: initialOverrides !== undefined || !readFailed,
298
+ writeEligible: resolved.writeEligible,
280
299
  };
281
300
  }
282
301
 
@@ -340,6 +359,7 @@ export function WorkbenchProvider({
340
359
  const shouldPersistKeybindingOverrides =
341
360
  persistKeybindingOverrides ??
342
361
  (keybindingOverridesStorage !== undefined || isWorkbenchKeybindingPersistenceAvailable());
362
+ const keybindingPlatform = resolveWorkbenchShortcutPlatform();
343
363
  const shouldPersistLayout =
344
364
  persistLayout ?? (layoutStorage !== undefined || isWorkbenchLayoutPersistenceAvailable());
345
365
  const shouldPersistLocalPreferences =
@@ -366,18 +386,25 @@ export function WorkbenchProvider({
366
386
  [editorStateStorage, editorStateStorageKey, initialEditorState, shouldPersistEditorState],
367
387
  );
368
388
  const resolvedInitialEditorState = resolvedInitialEditorStateResult.value;
369
- const resolvedInitialKeybindingOverridesResult = useMemo(
389
+ const resolvedInitialKeybindingOverridesResult = useMemo<PersistedKeybindingOverridesReadResult>(
370
390
  () =>
371
391
  initialKeybindingOverrides !== undefined
372
- ? { value: initialKeybindingOverrides }
392
+ ? {
393
+ entries: initialKeybindingOverrides,
394
+ format: 'v1',
395
+ value: initialKeybindingOverrides,
396
+ writeEligible: true,
397
+ }
373
398
  : shouldPersistKeybindingOverrides
374
399
  ? readPersistedKeybindingOverridesResult(
375
400
  keybindingOverridesStorageKey,
376
401
  keybindingOverridesStorage,
402
+ { platform: keybindingPlatform },
377
403
  )
378
- : { value: [] },
404
+ : { entries: [], format: 'missing', value: [], writeEligible: true },
379
405
  [
380
406
  initialKeybindingOverrides,
407
+ keybindingPlatform,
381
408
  keybindingOverridesStorage,
382
409
  keybindingOverridesStorageKey,
383
410
  shouldPersistKeybindingOverrides,
@@ -387,23 +414,32 @@ export function WorkbenchProvider({
387
414
  const [keybindingState, setKeybindingState] = useState<KeybindingOverridesState>(() =>
388
415
  createKeybindingOverridesState(
389
416
  initialKeybindingOverrides,
390
- resolvedInitialKeybindingOverrides,
391
- resolvedInitialKeybindingOverridesResult.diagnostic !== undefined,
417
+ resolvedInitialKeybindingOverridesResult,
392
418
  shouldPersistKeybindingOverrides,
393
419
  keybindingOverridesStorage,
394
420
  keybindingOverridesStorageKey,
421
+ keybindingPlatform,
395
422
  ),
396
423
  );
424
+ const handledKeybindingWriteRef = useRef<KeybindingOverridesState | undefined>(undefined);
397
425
  const keybindingStateIsCurrent = isKeybindingStateCurrent(
398
426
  keybindingState,
399
427
  initialKeybindingOverrides,
400
428
  shouldPersistKeybindingOverrides,
401
429
  keybindingOverridesStorage,
402
430
  keybindingOverridesStorageKey,
431
+ keybindingPlatform,
403
432
  );
404
433
  const keybindingOverrides = keybindingStateIsCurrent
405
434
  ? keybindingState.overrides
406
435
  : resolvedInitialKeybindingOverrides;
436
+ const keybindingWriteEligible = keybindingStateIsCurrent
437
+ ? keybindingState.writeEligible
438
+ : resolvedInitialKeybindingOverridesResult.writeEligible;
439
+ const keybindingEditingDisabledReason = keybindingWriteEligible
440
+ ? undefined
441
+ : (resolvedInitialKeybindingOverridesResult.diagnostic?.message ??
442
+ 'Stored keyboard shortcuts cannot be edited in this version.');
407
443
  const [contextKeyService] = useState(() => createInitialContextKeyService(contextKeyValues));
408
444
 
409
445
  useEffect(() => {
@@ -430,23 +466,25 @@ export function WorkbenchProvider({
430
466
  shouldPersistKeybindingOverrides,
431
467
  keybindingOverridesStorage,
432
468
  keybindingOverridesStorageKey,
469
+ keybindingPlatform,
433
470
  )
434
471
  ? current
435
472
  : createKeybindingOverridesState(
436
473
  initialKeybindingOverrides,
437
- resolvedInitialKeybindingOverrides,
438
- resolvedInitialKeybindingOverridesResult.diagnostic !== undefined,
474
+ resolvedInitialKeybindingOverridesResult,
439
475
  shouldPersistKeybindingOverrides,
440
476
  keybindingOverridesStorage,
441
477
  keybindingOverridesStorageKey,
478
+ keybindingPlatform,
442
479
  ),
443
480
  );
444
481
  }, [
445
482
  initialKeybindingOverrides,
446
483
  keybindingOverridesStorage,
447
484
  keybindingOverridesStorageKey,
485
+ keybindingPlatform,
448
486
  resolvedInitialKeybindingOverrides,
449
- resolvedInitialKeybindingOverridesResult.diagnostic,
487
+ resolvedInitialKeybindingOverridesResult,
450
488
  shouldPersistKeybindingOverrides,
451
489
  ]);
452
490
 
@@ -459,25 +497,53 @@ export function WorkbenchProvider({
459
497
  shouldPersistKeybindingOverrides,
460
498
  keybindingOverridesStorage,
461
499
  keybindingOverridesStorageKey,
500
+ keybindingPlatform,
462
501
  )
463
502
  ? current.overrides
464
503
  : resolvedInitialKeybindingOverrides;
465
- const without = currentOverrides.filter((binding) => binding.command !== commandId);
504
+ const currentWriteEligible = isKeybindingStateCurrent(
505
+ current,
506
+ initialKeybindingOverrides,
507
+ shouldPersistKeybindingOverrides,
508
+ keybindingOverridesStorage,
509
+ keybindingOverridesStorageKey,
510
+ keybindingPlatform,
511
+ )
512
+ ? current.writeEligible
513
+ : resolvedInitialKeybindingOverridesResult.writeEligible;
514
+ if (!currentWriteEligible) {
515
+ return current;
516
+ }
517
+
518
+ const result = setManagedKeybindingOverride({
519
+ commandId,
520
+ key,
521
+ overrides: currentOverrides,
522
+ platform: keybindingPlatform,
523
+ });
524
+ if (!result.changed) {
525
+ return current;
526
+ }
527
+
466
528
  return {
529
+ dirty: true,
467
530
  initialOverrides: initialKeybindingOverrides,
468
- overrides: [...without, { command: commandId, key }],
531
+ overrides: result.overrides,
532
+ platform: keybindingPlatform,
469
533
  shouldPersist: shouldPersistKeybindingOverrides,
470
534
  storage: keybindingOverridesStorage,
471
535
  storageKey: keybindingOverridesStorageKey,
472
- writeEligible: true,
536
+ writeEligible: currentWriteEligible,
473
537
  };
474
538
  });
475
539
  },
476
540
  [
477
541
  initialKeybindingOverrides,
542
+ keybindingPlatform,
478
543
  keybindingOverridesStorage,
479
544
  keybindingOverridesStorageKey,
480
545
  resolvedInitialKeybindingOverrides,
546
+ resolvedInitialKeybindingOverridesResult.writeEligible,
481
547
  shouldPersistKeybindingOverrides,
482
548
  ],
483
549
  );
@@ -491,33 +557,66 @@ export function WorkbenchProvider({
491
557
  shouldPersistKeybindingOverrides,
492
558
  keybindingOverridesStorage,
493
559
  keybindingOverridesStorageKey,
560
+ keybindingPlatform,
494
561
  )
495
562
  ? current.overrides
496
563
  : resolvedInitialKeybindingOverrides;
564
+ const currentWriteEligible = isKeybindingStateCurrent(
565
+ current,
566
+ initialKeybindingOverrides,
567
+ shouldPersistKeybindingOverrides,
568
+ keybindingOverridesStorage,
569
+ keybindingOverridesStorageKey,
570
+ keybindingPlatform,
571
+ )
572
+ ? current.writeEligible
573
+ : resolvedInitialKeybindingOverridesResult.writeEligible;
574
+ if (!currentWriteEligible) {
575
+ return current;
576
+ }
577
+
578
+ const result = resetManagedKeybindingOverride({
579
+ commandId,
580
+ overrides: currentOverrides,
581
+ platform: keybindingPlatform,
582
+ });
583
+ if (!result.changed) {
584
+ return current;
585
+ }
586
+
497
587
  return {
588
+ dirty: true,
498
589
  initialOverrides: initialKeybindingOverrides,
499
- overrides: currentOverrides.filter((binding) => binding.command !== commandId),
590
+ overrides: result.overrides,
591
+ platform: keybindingPlatform,
500
592
  shouldPersist: shouldPersistKeybindingOverrides,
501
593
  storage: keybindingOverridesStorage,
502
594
  storageKey: keybindingOverridesStorageKey,
503
- writeEligible: true,
595
+ writeEligible: currentWriteEligible,
504
596
  };
505
597
  });
506
598
  },
507
599
  [
508
600
  initialKeybindingOverrides,
601
+ keybindingPlatform,
509
602
  keybindingOverridesStorage,
510
603
  keybindingOverridesStorageKey,
511
604
  resolvedInitialKeybindingOverrides,
605
+ resolvedInitialKeybindingOverridesResult.writeEligible,
512
606
  shouldPersistKeybindingOverrides,
513
607
  ],
514
608
  );
515
609
 
516
610
  useEffect(() => {
517
- if (!keybindingStateIsCurrent) {
611
+ if (
612
+ !keybindingStateIsCurrent ||
613
+ !keybindingState.dirty ||
614
+ handledKeybindingWriteRef.current === keybindingState
615
+ ) {
518
616
  return;
519
617
  }
520
618
 
619
+ handledKeybindingWriteRef.current = keybindingState;
521
620
  onKeybindingOverridesChange?.(keybindingState.overrides);
522
621
  if (!shouldPersistKeybindingOverrides || !keybindingState.writeEligible) {
523
622
  return;
@@ -571,6 +670,7 @@ export function WorkbenchProvider({
571
670
  initialKeybindingOverrides,
572
671
  keybindingOverridesStorage,
573
672
  keybindingOverridesStorageKey,
673
+ keybindingPlatform,
574
674
  shouldPersistKeybindingOverrides,
575
675
  ],
576
676
  diagnosticHandlerRef,
@@ -748,6 +848,31 @@ export function WorkbenchProvider({
748
848
  diagnosticHandlerRef,
749
849
  ]);
750
850
 
851
+ const [commandKeybindingRevision, setCommandKeybindingRevision] = useState(
852
+ () => services.extensionRegistry.commands.revision,
853
+ );
854
+ useLayoutEffect(() => {
855
+ const updateRevision = () => {
856
+ setCommandKeybindingRevision(services.extensionRegistry.commands.revision);
857
+ };
858
+ const commandDisposable =
859
+ services.extensionRegistry.commands.onDidChangeCommands(updateRevision);
860
+ updateRevision();
861
+
862
+ return () => {
863
+ commandDisposable.dispose();
864
+ };
865
+ }, [services.extensionRegistry.commands]);
866
+ const keybindingProjection = useMemo(
867
+ () =>
868
+ projectCommandRegistryKeybindings({
869
+ context: undefined,
870
+ platform: keybindingPlatform,
871
+ registry: services.extensionRegistry.commands,
872
+ }),
873
+ [commandKeybindingRevision, keybindingPlatform, services.extensionRegistry.commands],
874
+ );
875
+
751
876
  useEffect(() => {
752
877
  if (!shouldPersistLayout) {
753
878
  return undefined;
@@ -886,7 +1011,10 @@ export function WorkbenchProvider({
886
1011
  installedExtensionsStorage,
887
1012
  installedExtensionsStorageKey,
888
1013
  keybindings: services.extensionRegistry.keybindings,
1014
+ keybindingEditingDisabledReason,
889
1015
  keybindingOverrides,
1016
+ keybindingPlatform,
1017
+ keybindingProjection,
890
1018
  layoutService: services.layoutService,
891
1019
  localizations: services.extensionRegistry.localizations,
892
1020
  menus: services.extensionRegistry.menus,
@@ -908,7 +1036,10 @@ export function WorkbenchProvider({
908
1036
  contextKeyService,
909
1037
  installedExtensionsStorage,
910
1038
  installedExtensionsStorageKey,
1039
+ keybindingEditingDisabledReason,
911
1040
  keybindingOverrides,
1041
+ keybindingPlatform,
1042
+ keybindingProjection,
912
1043
  resetCommandKeybindingOverride,
913
1044
  services,
914
1045
  setCommandKeybindingOverride,
@@ -919,7 +1050,10 @@ export function WorkbenchProvider({
919
1050
  <WorkbenchPersistenceDiagnosticContext.Provider value={onPersistenceDiagnostic}>
920
1051
  <WorkbenchContext.Provider value={value}>
921
1052
  <ExtensionEnablementContext.Provider value={services.extensionEnablement}>
922
- <EditorWorkspaceReconciler />
1053
+ <EditorWorkspaceReconciler
1054
+ editorService={services.editorService}
1055
+ workspaceHostService={services.workspaceHostPort?.service}
1056
+ />
923
1057
  {children}
924
1058
  </ExtensionEnablementContext.Provider>
925
1059
  </WorkbenchContext.Provider>
@@ -935,3 +1069,7 @@ export function useWorkbench(): WorkbenchContextValue {
935
1069
 
936
1070
  return value;
937
1071
  }
1072
+
1073
+ export function useWorkbenchKeybindingManagementBinding(): WorkbenchKeybindingManagementSettingsViewProps {
1074
+ return useKeybindingManagementModel(useWorkbench());
1075
+ }