@opensumi/ide-main-layout 3.9.1-next-1748404987.0 → 3.9.1-next-1748425167.0

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 (71) hide show
  1. package/README.md +30 -31
  2. package/lib/browser/accordion/accordion.service.d.ts +9 -1
  3. package/lib/browser/accordion/accordion.service.d.ts.map +1 -1
  4. package/lib/browser/accordion/accordion.service.js +120 -33
  5. package/lib/browser/accordion/accordion.service.js.map +1 -1
  6. package/lib/browser/accordion/accordion.view.d.ts.map +1 -1
  7. package/lib/browser/accordion/accordion.view.js +4 -1
  8. package/lib/browser/accordion/accordion.view.js.map +1 -1
  9. package/lib/browser/accordion/section.view.d.ts.map +1 -1
  10. package/lib/browser/accordion/section.view.js +1 -1
  11. package/lib/browser/accordion/section.view.js.map +1 -1
  12. package/lib/browser/accordion/styles.module.less +61 -0
  13. package/lib/browser/command.d.ts +29 -0
  14. package/lib/browser/command.d.ts.map +1 -0
  15. package/lib/browser/command.js +84 -0
  16. package/lib/browser/command.js.map +1 -0
  17. package/lib/browser/default-config.d.ts.map +1 -1
  18. package/lib/browser/default-config.js +7 -6
  19. package/lib/browser/default-config.js.map +1 -1
  20. package/lib/browser/drop-area/drop-area.d.ts +3 -2
  21. package/lib/browser/drop-area/drop-area.d.ts.map +1 -1
  22. package/lib/browser/drop-area/drop-area.js +8 -5
  23. package/lib/browser/drop-area/drop-area.js.map +1 -1
  24. package/lib/browser/index.d.ts.map +1 -1
  25. package/lib/browser/index.js.map +1 -1
  26. package/lib/browser/layout.service.d.ts +3 -0
  27. package/lib/browser/layout.service.d.ts.map +1 -1
  28. package/lib/browser/layout.service.js +120 -78
  29. package/lib/browser/layout.service.js.map +1 -1
  30. package/lib/browser/main-layout.contribution.d.ts +2 -18
  31. package/lib/browser/main-layout.contribution.d.ts.map +1 -1
  32. package/lib/browser/main-layout.contribution.js +75 -131
  33. package/lib/browser/main-layout.contribution.js.map +1 -1
  34. package/lib/browser/tabbar/TABBAR_CONFIG_USAGE.md +141 -0
  35. package/lib/browser/tabbar/bar.view.d.ts.map +1 -1
  36. package/lib/browser/tabbar/bar.view.js +5 -10
  37. package/lib/browser/tabbar/bar.view.js.map +1 -1
  38. package/lib/browser/tabbar/panel.view.js +1 -1
  39. package/lib/browser/tabbar/panel.view.js.map +1 -1
  40. package/lib/browser/tabbar/renderer.view.js +4 -4
  41. package/lib/browser/tabbar/renderer.view.js.map +1 -1
  42. package/lib/browser/tabbar/tabbar-behavior-handler.d.ts +71 -0
  43. package/lib/browser/tabbar/tabbar-behavior-handler.d.ts.map +1 -0
  44. package/lib/browser/tabbar/tabbar-behavior-handler.js +210 -0
  45. package/lib/browser/tabbar/tabbar-behavior-handler.js.map +1 -0
  46. package/lib/browser/tabbar/tabbar.service.d.ts +8 -19
  47. package/lib/browser/tabbar/tabbar.service.d.ts.map +1 -1
  48. package/lib/browser/tabbar/tabbar.service.js +37 -146
  49. package/lib/browser/tabbar/tabbar.service.js.map +1 -1
  50. package/lib/common/main-layout.definition.d.ts +4 -3
  51. package/lib/common/main-layout.definition.d.ts.map +1 -1
  52. package/lib/common/main-layout.definition.js +5 -4
  53. package/lib/common/main-layout.definition.js.map +1 -1
  54. package/package.json +8 -8
  55. package/src/browser/accordion/accordion.service.ts +152 -35
  56. package/src/browser/accordion/accordion.view.tsx +4 -2
  57. package/src/browser/accordion/section.view.tsx +5 -1
  58. package/src/browser/accordion/styles.module.less +61 -0
  59. package/src/browser/command.ts +99 -0
  60. package/src/browser/default-config.ts +8 -7
  61. package/src/browser/drop-area/drop-area.tsx +6 -3
  62. package/src/browser/index.ts +1 -0
  63. package/src/browser/layout.service.ts +134 -66
  64. package/src/browser/main-layout.contribution.ts +93 -138
  65. package/src/browser/tabbar/TABBAR_CONFIG_USAGE.md +141 -0
  66. package/src/browser/tabbar/bar.view.tsx +9 -15
  67. package/src/browser/tabbar/panel.view.tsx +2 -2
  68. package/src/browser/tabbar/renderer.view.tsx +4 -4
  69. package/src/browser/tabbar/tabbar-behavior-handler.ts +260 -0
  70. package/src/browser/tabbar/tabbar.service.ts +52 -161
  71. package/src/common/main-layout.definition.ts +6 -4
@@ -14,7 +14,6 @@ import {
14
14
  IScopedContextKeyService,
15
15
  KeybindingRegistry,
16
16
  ResizeEvent,
17
- SlotLocation,
18
17
  ViewContextKeyRegistry,
19
18
  WithEventBus,
20
19
  createFormatLocalizedStr,
@@ -26,7 +25,6 @@ import {
26
25
  localize,
27
26
  toDisposable,
28
27
  } from '@opensumi/ide-core-browser';
29
- import { SCM_CONTAINER_ID } from '@opensumi/ide-core-browser/lib/common/container-id';
30
28
  import { ResizeHandle } from '@opensumi/ide-core-browser/lib/components';
31
29
  import { LAYOUT_STATE, LayoutState } from '@opensumi/ide-core-browser/lib/layout/layout-state';
32
30
  import {
@@ -38,10 +36,11 @@ import {
38
36
  IMenuRegistry,
39
37
  MenuId,
40
38
  generateCtxMenu,
41
- getTabbarCommonMenuId,
42
39
  } from '@opensumi/ide-core-browser/lib/menu/next';
43
40
  import { IProgressService } from '@opensumi/ide-core-browser/lib/progress';
41
+ import { slotRendererRegistry } from '@opensumi/ide-core-browser/lib/react-providers';
44
42
  import {
43
+ ITransaction,
45
44
  autorunDelta,
46
45
  derivedOpts,
47
46
  observableFromEventOpts,
@@ -49,8 +48,9 @@ import {
49
48
  transaction,
50
49
  } from '@opensumi/ide-monaco/lib/common/observable';
51
50
 
52
- import { IMainLayoutService, SUPPORT_ACCORDION_LOCATION, TabBarRegistrationEvent } from '../../common';
53
- import { EXPAND_BOTTOM_PANEL, RETRACT_BOTTOM_PANEL, TOGGLE_BOTTOM_PANEL_COMMAND } from '../main-layout.contribution';
51
+ import { IMainLayoutService, TabBarRegistrationEvent } from '../../common';
52
+
53
+ import { ITabbarResizeOptions, TabbarBehaviorHandler } from './tabbar-behavior-handler';
54
54
 
55
55
  import type { ViewBadge } from 'vscode';
56
56
 
@@ -65,11 +65,6 @@ export interface TabState {
65
65
  // 排序位置,数字越小优先级越高
66
66
  priority: number;
67
67
  }
68
- const CONTAINER_NAME_MAP = {
69
- left: 'view',
70
- right: 'extendView',
71
- bottom: 'panel',
72
- };
73
68
 
74
69
  const NONE_CONTAINER_ID = undefined;
75
70
 
@@ -104,21 +99,15 @@ export class TabbarService extends WithEventBus {
104
99
  public previousContainerId: string | undefined = undefined;
105
100
  public containersMap: Map<string, ComponentRegistryProvider> = new Map();
106
101
  public prevSize?: number;
107
- public commonTitleMenu: IContextMenu;
102
+ public commonTitleMenu?: IContextMenu;
108
103
  public viewReady = new Deferred<void>();
109
104
 
110
105
  private state: Map<string, TabState> = new Map();
111
106
  private storedState: { [containerId: string]: TabState } = {};
112
107
 
113
- resizeHandle?: {
114
- setSize: (targetSize?: number) => void;
115
- setRelativeSize: (prev: number, next: number) => void;
116
- getSize: () => number;
117
- getRelativeSize: () => number[];
118
- lockSize: (lock: boolean | undefined) => void;
119
- setMaxSize: (lock: boolean | undefined) => void;
120
- hidePanel: (show?: boolean) => void;
121
- };
108
+ private behaviorHandler: TabbarBehaviorHandler;
109
+
110
+ public resizeHandle?: ITabbarResizeOptions;
122
111
 
123
112
  @Autowired(AbstractMenuService)
124
113
  protected menuService: AbstractMenuService;
@@ -153,8 +142,6 @@ export class TabbarService extends WithEventBus {
153
142
  @Autowired(IProgressService)
154
143
  private progressService: IProgressService;
155
144
 
156
- private accordionRestored: Set<string> = new Set();
157
-
158
145
  private readonly onCurrentChangeEmitter = new Emitter<{ previousId: string; currentId: string }>();
159
146
  readonly onCurrentChange: Event<{ previousId: string; currentId: string }> = this.onCurrentChangeEmitter.event;
160
147
 
@@ -170,7 +157,6 @@ export class TabbarService extends WithEventBus {
170
157
  private disposableMap: Map<string, DisposableCollection> = new Map();
171
158
  private tabInMoreKeyMap: Map<string, IContextKey<boolean>> = new Map();
172
159
  private shouldWaitForViewRender = false;
173
- private isLatter: boolean;
174
160
 
175
161
  private scopedCtxKeyService: IScopedContextKeyService;
176
162
  private onDidRegisterContainerEmitter = new Emitter<string>();
@@ -178,7 +164,10 @@ export class TabbarService extends WithEventBus {
178
164
 
179
165
  constructor(public location: string) {
180
166
  super();
181
- this.setIsLatter(location === SlotLocation.right || location === SlotLocation.bottom);
167
+ // 从插槽渲染器注册表获取配置,创建行为处理器
168
+ const tabbarConfig = slotRendererRegistry.getTabbarConfig(location);
169
+ this.behaviorHandler = new TabbarBehaviorHandler(location, tabbarConfig);
170
+
182
171
  this.scopedCtxKeyService = this.contextKeyService.createScoped();
183
172
  this.scopedCtxKeyService.createKey('triggerWithTab', true);
184
173
  this.menuRegistry.registerMenuItem(this.menuId, {
@@ -190,10 +179,17 @@ export class TabbarService extends WithEventBus {
190
179
  when: 'triggerWithTab == true',
191
180
  });
192
181
  this.activatedKey = this.contextKeyService.createKey(getTabbarCtxKey(this.location), '');
193
- if (this.location === 'bottom') {
194
- this.registerPanelCommands();
195
- this.registerPanelMenus();
196
- }
182
+
183
+ // 使用行为处理器注册特定位置的命令和菜单
184
+ this.behaviorHandler.registerLocationSpecificCommands({
185
+ commandRegistry: this.commandRegistry,
186
+ layoutService: this.layoutService,
187
+ });
188
+
189
+ this.commonTitleMenu = this.behaviorHandler.registerLocationSpecificMenus({
190
+ menuRegistry: this.menuRegistry,
191
+ ctxMenuService: this.ctxMenuService,
192
+ });
197
193
 
198
194
  this.eventBus.onDirective(ResizeEvent.createDirective(this.location), () => {
199
195
  this.onResize();
@@ -204,10 +200,6 @@ export class TabbarService extends WithEventBus {
204
200
  return this.onDidRegisterContainerEmitter.event;
205
201
  }
206
202
 
207
- public setIsLatter(v: boolean) {
208
- this.isLatter = v;
209
- }
210
-
211
203
  updateNextContainerId(nextContainerId?: string) {
212
204
  if (isUndefined(nextContainerId)) {
213
205
  this.useFirstContainerId = true;
@@ -216,10 +208,14 @@ export class TabbarService extends WithEventBus {
216
208
  }
217
209
  }
218
210
 
219
- updateCurrentContainerId(containerId: string) {
220
- transaction((tx) => {
211
+ updateCurrentContainerId(containerId: string, tx?: ITransaction) {
212
+ if (tx) {
221
213
  this.containerIdObs.set(containerId, tx);
222
- });
214
+ } else {
215
+ transaction((tx) => {
216
+ this.containerIdObs.set(containerId, tx);
217
+ });
218
+ }
223
219
  }
224
220
 
225
221
  updateBadge(containerId: string, value?: ViewBadge | string) {
@@ -230,24 +226,6 @@ export class TabbarService extends WithEventBus {
230
226
  component?.fireChange(component);
231
227
  }
232
228
 
233
- registerPanelCommands(): void {
234
- this.commandRegistry.registerCommand(EXPAND_BOTTOM_PANEL, {
235
- execute: () => {
236
- this.layoutService.expandBottom(true);
237
- },
238
- });
239
- this.commandRegistry.registerCommand(RETRACT_BOTTOM_PANEL, {
240
- execute: () => {
241
- this.layoutService.expandBottom(false);
242
- },
243
- });
244
- this.commandRegistry.registerCommand(TOGGLE_BOTTOM_PANEL_COMMAND, {
245
- execute: (show?: boolean, size?: number) => {
246
- this.layoutService.toggleSlot(SlotLocation.bottom, show, size);
247
- },
248
- });
249
- }
250
-
251
229
  public getContainerState(containerId: string) {
252
230
  const viewState = this.state.get(containerId);
253
231
  return viewState!;
@@ -345,16 +323,7 @@ export class TabbarService extends WithEventBus {
345
323
  }
346
324
 
347
325
  registerResizeHandle(resizeHandle: ResizeHandle) {
348
- const { setSize, setRelativeSize, getSize, getRelativeSize, lockSize, setMaxSize, hidePanel } = resizeHandle;
349
- this.resizeHandle = {
350
- setSize: (size) => setSize(size, this.isLatter),
351
- setRelativeSize: (prev: number, next: number) => setRelativeSize(prev, next, this.isLatter),
352
- getSize: () => getSize(this.isLatter),
353
- getRelativeSize: () => getRelativeSize(this.isLatter),
354
- setMaxSize: (lock: boolean | undefined) => setMaxSize(lock, this.isLatter),
355
- lockSize: (lock: boolean | undefined) => lockSize(lock, this.isLatter),
356
- hidePanel: (show) => hidePanel(show),
357
- };
326
+ this.resizeHandle = this.behaviorHandler.wrapResizeHandle(resizeHandle);
358
327
  return this.listenCurrentChange();
359
328
  }
360
329
 
@@ -441,7 +410,7 @@ export class TabbarService extends WithEventBus {
441
410
  disposables.push(this.registerActivateKeyBinding(componentInfo, componentInfo.options!.fromExtension));
442
411
  // 注册视图是否存在的contextKey
443
412
  const containerExistKey = this.contextKeyService.createKey<boolean>(
444
- `workbench.${CONTAINER_NAME_MAP[this.location] || 'view'}.${componentInfo.options!.containerId}`,
413
+ `workbench.${this.location}.${componentInfo.options!.containerId}`,
445
414
  true,
446
415
  );
447
416
  disposables.push({
@@ -603,28 +572,11 @@ export class TabbarService extends WithEventBus {
603
572
  }
604
573
 
605
574
  doExpand(expand: boolean) {
606
- if (this.resizeHandle) {
607
- const { setRelativeSize } = this.resizeHandle;
608
- if (expand) {
609
- if (!this.isLatter) {
610
- setRelativeSize(1, 0);
611
- } else {
612
- setRelativeSize(0, 1);
613
- }
614
- } else {
615
- // FIXME 底部需要额外的字段记录展开前的尺寸
616
- setRelativeSize(2, 1);
617
- }
618
- }
575
+ this.behaviorHandler.doExpand(expand, this.resizeHandle);
619
576
  }
620
577
 
621
578
  get isExpanded(): boolean {
622
- if (this.resizeHandle) {
623
- const { getRelativeSize } = this.resizeHandle;
624
- const relativeSizes = getRelativeSize().join(',');
625
- return this.isLatter ? relativeSizes === '0,1' : relativeSizes === '1,0';
626
- }
627
- return false;
579
+ return this.behaviorHandler.isExpanded(this.resizeHandle);
628
580
  }
629
581
 
630
582
  handleTabClick(e: React.MouseEvent, forbidCollapse?: boolean) {
@@ -695,23 +647,19 @@ export class TabbarService extends WithEventBus {
695
647
  }
696
648
  }
697
649
  this.visibleContainers.forEach((container) => {
698
- if (SUPPORT_ACCORDION_LOCATION.has(this.location)) {
699
- this.tryRestoreAccordionSize(container.options!.containerId);
700
- }
650
+ this.tryRestoreAccordionSize(container);
701
651
  });
702
652
  }
703
653
 
704
654
  removeContainer(containerId: string) {
705
655
  const disposable = this.disposableMap.get(containerId);
706
656
  disposable?.dispose();
707
- this.updateCurrentContainerId('');
708
- this.doChangeViewEmitter.fire();
657
+ this.onStateChangeEmitter.fire();
709
658
  }
710
659
 
711
660
  dynamicAddContainer(containerId: string, options: ComponentRegistryInfo) {
712
661
  this.registerContainer(containerId, options);
713
662
  this.updateCurrentContainerId(containerId);
714
- this.doChangeViewEmitter.fire();
715
663
  }
716
664
 
717
665
  protected doInsertTab(containers: ComponentRegistryInfo[], sourceIndex: number, targetIndex: number) {
@@ -762,12 +710,12 @@ export class TabbarService extends WithEventBus {
762
710
  },
763
711
  {
764
712
  execute: ({ forceShow }: { forceShow?: boolean } = {}) => {
765
- // 支持toggle
766
- if (this.location === 'bottom' && !forceShow) {
767
- this.updateCurrentContainerId(this.currentContainerId.get() === containerId ? '' : containerId);
768
- } else {
769
- this.updateCurrentContainerId(containerId);
770
- }
713
+ this.behaviorHandler.handleActivateKeyBinding(
714
+ containerId,
715
+ this.currentContainerId.get() || '',
716
+ (id: string) => this.updateCurrentContainerId(id),
717
+ forceShow,
718
+ );
771
719
  },
772
720
  },
773
721
  ),
@@ -858,31 +806,6 @@ export class TabbarService extends WithEventBus {
858
806
  return `${containerId}.isInMore`;
859
807
  }
860
808
 
861
- protected registerPanelMenus() {
862
- this.menuRegistry.registerMenuItems(getTabbarCommonMenuId('bottom'), [
863
- {
864
- command: EXPAND_BOTTOM_PANEL.id,
865
- group: 'navigation',
866
- when: '!bottomFullExpanded',
867
- order: 1,
868
- },
869
- {
870
- command: RETRACT_BOTTOM_PANEL.id,
871
- group: 'navigation',
872
- when: 'bottomFullExpanded',
873
- order: 1,
874
- },
875
- {
876
- command: TOGGLE_BOTTOM_PANEL_COMMAND.id,
877
- group: 'navigation',
878
- order: 2,
879
- },
880
- ]);
881
- this.commonTitleMenu = this.ctxMenuService.createMenu({
882
- id: 'tabbar/bottom/common',
883
- });
884
- }
885
-
886
809
  protected doToggleTab(containerId: string, forceShow?: boolean) {
887
810
  const state = this.getContainerState(containerId);
888
811
  if (forceShow === undefined) {
@@ -898,9 +821,9 @@ export class TabbarService extends WithEventBus {
898
821
  this.storeState();
899
822
  }
900
823
 
901
- protected shouldExpand(containerId: string | undefined) {
824
+ protected shouldExpand(containerId: string | undefined): boolean {
902
825
  const info = this.getContainer(containerId);
903
- return info && info.options && info.options.expanded;
826
+ return !!(info && info.options && info.options.expanded);
904
827
  }
905
828
 
906
829
  protected onResize() {
@@ -934,7 +857,11 @@ export class TabbarService extends WithEventBus {
934
857
  this.onCurrentChangeEmitter.fire({ previousId, currentId });
935
858
  const isCurrentExpanded = this.shouldExpand(currentId);
936
859
  if (this.shouldExpand(this.previousContainerId) || isCurrentExpanded) {
937
- this.handleFullExpanded(currentId, isCurrentExpanded);
860
+ this.behaviorHandler.handleFullExpanded(currentId, isCurrentExpanded, this.resizeHandle, {
861
+ barSize: this.barSize,
862
+ panelSize: this.panelSize,
863
+ prevSize: this.prevSize,
864
+ });
938
865
  } else {
939
866
  if (currentId) {
940
867
  if (previousId && currentId !== previousId) {
@@ -953,43 +880,7 @@ export class TabbarService extends WithEventBus {
953
880
  }
954
881
  }
955
882
 
956
- protected tryRestoreAccordionSize(containerId: string) {
957
- if (this.accordionRestored.has(containerId)) {
958
- return;
959
- }
960
- const containerInfo = this.containersMap.get(containerId);
961
- // 使用自定义视图取代手风琴的面板不需要 restore
962
- // scm 视图例外,因为在新版本 Gitlens 中可以将自己注册到 scm 中
963
- // 暂时用这种方式使 scm 面板状态可以被持久化
964
- if (
965
- (!containerInfo || containerInfo.options?.component) &&
966
- containerInfo?.options?.containerId !== SCM_CONTAINER_ID
967
- ) {
968
- return;
969
- }
970
- const accordionService = this.layoutService.getAccordionService(containerId);
971
- // 需要保证此时tab切换已完成dom渲染
972
- accordionService.restoreState();
973
- this.accordionRestored.add(containerId);
974
- }
975
-
976
- protected handleFullExpanded(currentId: string, isCurrentExpanded?: boolean) {
977
- if (!this.resizeHandle) {
978
- return;
979
- }
980
- const { setRelativeSize, setSize } = this.resizeHandle;
981
- if (currentId) {
982
- if (isCurrentExpanded) {
983
- if (!this.isLatter) {
984
- setRelativeSize(1, 0);
985
- } else {
986
- setRelativeSize(0, 1);
987
- }
988
- } else {
989
- setSize(this.prevSize || this.panelSize + this.barSize);
990
- }
991
- } else {
992
- setSize(this.barSize);
993
- }
883
+ protected tryRestoreAccordionSize(containerInfo: ComponentRegistryProvider) {
884
+ this.behaviorHandler.tryRestoreAccordionSize(containerInfo, this.layoutService);
994
885
  }
995
886
  }
@@ -1,4 +1,5 @@
1
1
  import { BasicEvent, IDisposable, SlotLocation } from '@opensumi/ide-core-browser';
2
+ import { Layout } from '@opensumi/ide-core-browser/lib/components';
2
3
  import { SideStateManager, View, ViewContainerOptions } from '@opensumi/ide-core-browser/lib/layout';
3
4
  import { ComponentRegistryInfo } from '@opensumi/ide-core-browser/lib/layout/layout.interface';
4
5
  import { IContextMenu } from '@opensumi/ide-core-browser/lib/menu/next';
@@ -41,7 +42,7 @@ export interface IMainLayoutService {
41
42
  * 注册单个或多个视图到tabbar位置
42
43
  * @param views 使用手风琴能力时传入的多个子视图
43
44
  * @param options container相关选项
44
- * @param side 注册的位置,支持left、right、bottom
45
+ * @param side 注册的位置,支持 view、extendView、panel,对应之前的 left、right、bottom
45
46
  */
46
47
  collectTabbarComponent(views: View[], options: ViewContainerOptions, side: string): string;
47
48
 
@@ -131,7 +132,8 @@ export class ViewCollapseChangedEvent extends BasicEvent<{
131
132
  collapsed: boolean;
132
133
  }> {}
133
134
 
134
- export const SUPPORT_ACCORDION_LOCATION = new Set([SlotLocation.left, SlotLocation.right]);
135
+ export const SUPPORT_ACCORDION_LOCATION = new Set([SlotLocation.view, SlotLocation.extendView]);
135
136
 
136
- export const DROP_BOTTOM_CONTAINER = 'drop-bottom';
137
- export const DROP_RIGHT_CONTAINER = 'drop-right';
137
+ export const DROP_PANEL_CONTAINER = 'drop-panel';
138
+ export const DROP_EXTEND_VIEW_CONTAINER = 'drop-extend-view';
139
+ export const DROP_VIEW_CONTAINER = 'drop-view';