@opensumi/ide-main-layout 3.7.1 → 3.7.2-next-1739859371.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.
- package/lib/browser/accordion/titlebar.view.d.ts +3 -0
- package/lib/browser/accordion/titlebar.view.d.ts.map +1 -1
- package/lib/browser/accordion/titlebar.view.js +12 -1
- package/lib/browser/accordion/titlebar.view.js.map +1 -1
- package/lib/browser/default-config.d.ts.map +1 -1
- package/lib/browser/default-config.js +9 -2
- package/lib/browser/default-config.js.map +1 -1
- package/lib/browser/drop-area/drop-area.d.ts +4 -0
- package/lib/browser/drop-area/drop-area.d.ts.map +1 -0
- package/lib/browser/drop-area/drop-area.js +25 -0
- package/lib/browser/drop-area/drop-area.js.map +1 -0
- package/lib/browser/drop-area/styles.module.less +7 -0
- package/lib/browser/layout.service.d.ts +6 -0
- package/lib/browser/layout.service.d.ts.map +1 -1
- package/lib/browser/layout.service.js +94 -12
- package/lib/browser/layout.service.js.map +1 -1
- package/lib/browser/main-layout.contribution.d.ts +2 -1
- package/lib/browser/main-layout.contribution.d.ts.map +1 -1
- package/lib/browser/main-layout.contribution.js +14 -1
- package/lib/browser/main-layout.contribution.js.map +1 -1
- package/lib/browser/tabbar/bar.view.d.ts.map +1 -1
- package/lib/browser/tabbar/bar.view.js +8 -3
- package/lib/browser/tabbar/bar.view.js.map +1 -1
- package/lib/browser/tabbar/panel.view.d.ts +1 -0
- package/lib/browser/tabbar/panel.view.d.ts.map +1 -1
- package/lib/browser/tabbar/panel.view.js +4 -3
- package/lib/browser/tabbar/panel.view.js.map +1 -1
- package/lib/browser/tabbar/tabbar.service.d.ts +3 -0
- package/lib/browser/tabbar/tabbar.service.d.ts.map +1 -1
- package/lib/browser/tabbar/tabbar.service.js +15 -0
- package/lib/browser/tabbar/tabbar.service.js.map +1 -1
- package/lib/common/main-layout.definition.d.ts +6 -0
- package/lib/common/main-layout.definition.d.ts.map +1 -1
- package/lib/common/main-layout.definition.js +3 -1
- package/lib/common/main-layout.definition.js.map +1 -1
- package/package.json +8 -8
- package/src/browser/accordion/titlebar.view.tsx +30 -2
- package/src/browser/default-config.ts +10 -2
- package/src/browser/drop-area/drop-area.tsx +40 -0
- package/src/browser/drop-area/styles.module.less +7 -0
- package/src/browser/layout.service.ts +107 -14
- package/src/browser/main-layout.contribution.ts +24 -2
- package/src/browser/tabbar/bar.view.tsx +9 -2
- package/src/browser/tabbar/panel.view.tsx +7 -2
- package/src/browser/tabbar/tabbar.service.ts +18 -0
- package/src/common/main-layout.definition.ts +7 -0
|
@@ -32,6 +32,8 @@ import { Deferred, getDebugLogger, isUndefined } from '@opensumi/ide-core-common
|
|
|
32
32
|
import { ThemeChangedEvent } from '@opensumi/ide-theme';
|
|
33
33
|
|
|
34
34
|
import {
|
|
35
|
+
DROP_BOTTOM_CONTAINER,
|
|
36
|
+
DROP_RIGHT_CONTAINER,
|
|
35
37
|
IMainLayoutService,
|
|
36
38
|
MainLayoutContribution,
|
|
37
39
|
SUPPORT_ACCORDION_LOCATION,
|
|
@@ -201,7 +203,7 @@ export class LayoutService extends WithEventBus implements IMainLayoutService {
|
|
|
201
203
|
/**
|
|
202
204
|
* ContainerId 存在三种值类型,对应的处理模式如下:
|
|
203
205
|
* 1. undefined: 采用首个注册的容器作为当前 containerId
|
|
204
|
-
* 2. string: 直接使用该 containerId 作为当前 containerId
|
|
206
|
+
* 2. string: 非 drop container 直接使用该 containerId 作为当前 containerId
|
|
205
207
|
* 3. '': 直接清空当前 containerId,不展开相应的 viewContainer
|
|
206
208
|
*/
|
|
207
209
|
if (isUndefined(currentId)) {
|
|
@@ -211,19 +213,93 @@ export class LayoutService extends WithEventBus implements IMainLayoutService {
|
|
|
211
213
|
} else {
|
|
212
214
|
service.updateCurrentContainerId(defaultContainer);
|
|
213
215
|
}
|
|
214
|
-
} else if (currentId) {
|
|
216
|
+
} else if (currentId && !this.isDropContainer(currentId)) {
|
|
215
217
|
if (service.containersMap.has(currentId)) {
|
|
216
218
|
service.updateCurrentContainerId(currentId);
|
|
217
219
|
} else {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
220
|
+
// 如果在别的 tabbar 中存在该 containerId,则将其移动到当前 tabbar
|
|
221
|
+
if (this.findTabbarServiceByContainerId(currentId)) {
|
|
222
|
+
this.moveContainerTo(currentId, service.location);
|
|
223
|
+
service.updateCurrentContainerId(currentId);
|
|
224
|
+
} else {
|
|
225
|
+
service.updateCurrentContainerId(defaultContainer);
|
|
226
|
+
// 等待后续新容器注册时,更新当前的 containerId
|
|
227
|
+
service.updateNextContainerId(currentId);
|
|
228
|
+
}
|
|
221
229
|
}
|
|
222
|
-
} else if (currentId === '') {
|
|
230
|
+
} else if (currentId === '' || this.isDropContainer(currentId)) {
|
|
223
231
|
service.updateCurrentContainerId('');
|
|
224
232
|
}
|
|
225
233
|
};
|
|
226
234
|
|
|
235
|
+
findTabbarServiceByContainerId(containerId: string): TabbarService | undefined {
|
|
236
|
+
let tabbarService: undefined | TabbarService;
|
|
237
|
+
for (const value of this.tabbarServices.values()) {
|
|
238
|
+
if (value.containersMap.has(containerId)) {
|
|
239
|
+
tabbarService = value;
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return tabbarService;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
moveContainerTo(containerId: string, to: string): void {
|
|
248
|
+
const fromTabbar = this.findTabbarServiceByContainerId(containerId);
|
|
249
|
+
|
|
250
|
+
if (!fromTabbar) {
|
|
251
|
+
this.logger.error(`cannot find container: ${containerId}`);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const container = fromTabbar.getContainer(containerId);
|
|
255
|
+
if (!container) {
|
|
256
|
+
this.logger.error(`cannot find container: ${containerId}`);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (!container.options?.draggable) {
|
|
260
|
+
this.logger.warn(`container: ${containerId} is not draggable`);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const toTabbar = this.getTabbarService(to);
|
|
265
|
+
|
|
266
|
+
fromTabbar.removeContainer(containerId);
|
|
267
|
+
|
|
268
|
+
if (!fromTabbar.visibleContainers.length || fromTabbar.currentContainerId.get() === containerId) {
|
|
269
|
+
this.toggleSlot(fromTabbar.location, false);
|
|
270
|
+
}
|
|
271
|
+
toTabbar.dynamicAddContainer(containerId, container);
|
|
272
|
+
const newHandler = this.injector.get(TabBarHandler, [containerId, this.getTabbarService(toTabbar.location)]);
|
|
273
|
+
this.handleMap.set(containerId, newHandler!);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
showDropAreaForContainer(containerId: string): void {
|
|
277
|
+
const tabbarService = this.findTabbarServiceByContainerId(containerId);
|
|
278
|
+
const bottomService = this.tabbarServices.get('bottom');
|
|
279
|
+
const rightService = this.tabbarServices.get('right');
|
|
280
|
+
if (!tabbarService) {
|
|
281
|
+
this.logger.error(`cannot find container: ${containerId}`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (tabbarService?.location === 'right') {
|
|
285
|
+
bottomService?.updateCurrentContainerId(DROP_BOTTOM_CONTAINER);
|
|
286
|
+
}
|
|
287
|
+
if (tabbarService?.location === 'bottom') {
|
|
288
|
+
rightService?.updateCurrentContainerId(DROP_RIGHT_CONTAINER);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
hideDropArea(): void {
|
|
293
|
+
const bottomService = this.tabbarServices.get('bottom');
|
|
294
|
+
const rightService = this.tabbarServices.get('right');
|
|
295
|
+
if (bottomService?.currentContainerId.get() === DROP_BOTTOM_CONTAINER) {
|
|
296
|
+
bottomService.updateCurrentContainerId(bottomService.previousContainerId || '');
|
|
297
|
+
}
|
|
298
|
+
if (rightService?.currentContainerId.get() === DROP_RIGHT_CONTAINER) {
|
|
299
|
+
rightService.updateCurrentContainerId(rightService.previousContainerId || '');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
227
303
|
isVisible(location: string) {
|
|
228
304
|
const tabbarService = this.getTabbarService(location);
|
|
229
305
|
return !!tabbarService.currentContainerId.get();
|
|
@@ -245,18 +321,13 @@ export class LayoutService extends WithEventBus implements IMainLayoutService {
|
|
|
245
321
|
return;
|
|
246
322
|
}
|
|
247
323
|
if (show === true) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
tabbarService.previousContainerId ||
|
|
251
|
-
tabbarService.containersMap.keys().next().value!,
|
|
252
|
-
);
|
|
324
|
+
// 不允许通过该api展示drop面板
|
|
325
|
+
tabbarService.updateCurrentContainerId(this.findNonDropContainerId(tabbarService));
|
|
253
326
|
} else if (show === false) {
|
|
254
327
|
tabbarService.updateCurrentContainerId('');
|
|
255
328
|
} else {
|
|
256
329
|
tabbarService.updateCurrentContainerId(
|
|
257
|
-
tabbarService.currentContainerId.get()
|
|
258
|
-
? ''
|
|
259
|
-
: tabbarService.previousContainerId || tabbarService.containersMap.keys().next().value!,
|
|
330
|
+
tabbarService.currentContainerId.get() ? '' : this.findNonDropContainerId(tabbarService),
|
|
260
331
|
);
|
|
261
332
|
}
|
|
262
333
|
if (tabbarService.currentContainerId.get() && size) {
|
|
@@ -264,6 +335,28 @@ export class LayoutService extends WithEventBus implements IMainLayoutService {
|
|
|
264
335
|
}
|
|
265
336
|
}
|
|
266
337
|
|
|
338
|
+
private isDropContainer(containerId: string): boolean {
|
|
339
|
+
return [DROP_BOTTOM_CONTAINER, DROP_RIGHT_CONTAINER].includes(containerId);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
private findNonDropContainerId(tabbarService: TabbarService): string {
|
|
343
|
+
const currentContainerId = tabbarService.currentContainerId.get();
|
|
344
|
+
if (currentContainerId && !this.isDropContainer(currentContainerId)) {
|
|
345
|
+
return currentContainerId;
|
|
346
|
+
}
|
|
347
|
+
if (tabbarService.previousContainerId && !this.isDropContainer(tabbarService.previousContainerId)) {
|
|
348
|
+
return tabbarService.previousContainerId;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for (const key of tabbarService.containersMap.keys()) {
|
|
352
|
+
if (!this.isDropContainer(key)) {
|
|
353
|
+
return key;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return '';
|
|
358
|
+
}
|
|
359
|
+
|
|
267
360
|
getTabbarService(location: string) {
|
|
268
361
|
const service = this.tabbarServices.get(location) || this.injector.get(TabbarService, [location]);
|
|
269
362
|
if (!this.tabbarServices.get(location)) {
|
|
@@ -41,8 +41,9 @@ import {
|
|
|
41
41
|
import { ContributionProvider, Domain, IEventBus, WithEventBus, localize } from '@opensumi/ide-core-common';
|
|
42
42
|
import { Command, CommandContribution, CommandRegistry, CommandService } from '@opensumi/ide-core-common/lib/command';
|
|
43
43
|
|
|
44
|
-
import { IMainLayoutService } from '../common';
|
|
44
|
+
import { DROP_BOTTOM_CONTAINER, DROP_RIGHT_CONTAINER, IMainLayoutService } from '../common';
|
|
45
45
|
|
|
46
|
+
import { BottomDropArea, RightDropArea } from './drop-area/drop-area';
|
|
46
47
|
import { ViewQuickOpenHandler } from './quick-open-view';
|
|
47
48
|
import { BottomTabRenderer, LeftTabRenderer, RightTabRenderer } from './tabbar/renderer.view';
|
|
48
49
|
|
|
@@ -117,7 +118,14 @@ export const RETRACT_BOTTOM_PANEL: Command = {
|
|
|
117
118
|
iconClass: getIcon('shrink'),
|
|
118
119
|
};
|
|
119
120
|
|
|
120
|
-
@Domain(
|
|
121
|
+
@Domain(
|
|
122
|
+
CommandContribution,
|
|
123
|
+
ClientAppContribution,
|
|
124
|
+
SlotRendererContribution,
|
|
125
|
+
MenuContribution,
|
|
126
|
+
QuickOpenContribution,
|
|
127
|
+
ComponentContribution,
|
|
128
|
+
)
|
|
121
129
|
export class MainLayoutModuleContribution
|
|
122
130
|
extends WithEventBus
|
|
123
131
|
implements
|
|
@@ -125,6 +133,7 @@ export class MainLayoutModuleContribution
|
|
|
125
133
|
ClientAppContribution,
|
|
126
134
|
SlotRendererContribution,
|
|
127
135
|
MenuContribution,
|
|
136
|
+
ComponentContribution,
|
|
128
137
|
QuickOpenContribution
|
|
129
138
|
{
|
|
130
139
|
@Autowired(IMainLayoutService)
|
|
@@ -186,6 +195,19 @@ export class MainLayoutModuleContribution
|
|
|
186
195
|
}
|
|
187
196
|
}
|
|
188
197
|
|
|
198
|
+
registerComponent(registry: ComponentRegistry): void {
|
|
199
|
+
registry.register(DROP_RIGHT_CONTAINER, [], {
|
|
200
|
+
component: RightDropArea,
|
|
201
|
+
hideTab: true,
|
|
202
|
+
containerId: DROP_RIGHT_CONTAINER,
|
|
203
|
+
});
|
|
204
|
+
registry.register(DROP_BOTTOM_CONTAINER, [], {
|
|
205
|
+
component: BottomDropArea,
|
|
206
|
+
hideTab: true,
|
|
207
|
+
containerId: DROP_BOTTOM_CONTAINER,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
189
211
|
async onStart() {
|
|
190
212
|
this.registerSideToggleKey();
|
|
191
213
|
}
|
|
@@ -125,11 +125,15 @@ export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
|
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
const renderContainers = React.useCallback(
|
|
128
|
-
(component: ComponentRegistryInfo, tabbarService: TabbarService, currentContainerId?: string) => {
|
|
128
|
+
(component: ComponentRegistryInfo, tabbarService: TabbarService, currentContainerId?: string, side?: string) => {
|
|
129
129
|
const containerId = component.options?.containerId;
|
|
130
130
|
if (!containerId) {
|
|
131
131
|
return null;
|
|
132
132
|
}
|
|
133
|
+
if (side && component.options?.hideLocationTab?.includes(side)) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
133
137
|
tabbarService.updateTabInMoreKey(containerId, false);
|
|
134
138
|
let ref: HTMLLIElement | null;
|
|
135
139
|
return (
|
|
@@ -168,6 +172,9 @@ export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
|
|
|
168
172
|
}
|
|
169
173
|
tabbarService.handleDrop(e, containerId);
|
|
170
174
|
}}
|
|
175
|
+
onDragEnd={(e) => {
|
|
176
|
+
tabbarService.handleDragEnd(e);
|
|
177
|
+
}}
|
|
171
178
|
key={containerId}
|
|
172
179
|
id={containerId}
|
|
173
180
|
onContextMenu={(e) => tabbarService.handleContextMenu(e, containerId)}
|
|
@@ -186,7 +193,7 @@ export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
|
|
|
186
193
|
return (
|
|
187
194
|
<div className={cls([styles_tab_bar, className])}>
|
|
188
195
|
<div className={styles_bar_content} style={{ flexDirection: Layout.getTabbarDirection(direction) }}>
|
|
189
|
-
{visibleContainers.map((component) => renderContainers(component, tabbarService, currentContainerId))}
|
|
196
|
+
{visibleContainers.map((component) => renderContainers(component, tabbarService, currentContainerId, side))}
|
|
190
197
|
{renderOtherVisibleContainers({ props, renderContainers })}
|
|
191
198
|
{hideContainers.length ? (
|
|
192
199
|
<li
|
|
@@ -100,12 +100,13 @@ export const ContainerView: React.FC<{
|
|
|
100
100
|
renderContainerWrap?: React.FC<{
|
|
101
101
|
children: React.ReactNode;
|
|
102
102
|
}>;
|
|
103
|
+
customTitleBar?: React.ReactNode;
|
|
103
104
|
className?: string;
|
|
104
|
-
}> = ({ component, titleMenu, side, renderContainerWrap, className }) => {
|
|
105
|
+
}> = ({ component, titleMenu, side, renderContainerWrap, className, customTitleBar }) => {
|
|
105
106
|
const ref = React.useRef<HTMLElement | null>();
|
|
106
107
|
const containerRef = React.useRef<HTMLDivElement | null>(null);
|
|
107
108
|
const appConfig = useInjectable<AppConfig>(AppConfig);
|
|
108
|
-
const { title, titleComponent, component: CustomComponent, containerId } = component.options || {};
|
|
109
|
+
const { title, titleComponent, component: CustomComponent, containerId, draggable } = component.options || {};
|
|
109
110
|
const injector: Injector = useInjectable(INJECTOR_TOKEN);
|
|
110
111
|
const layoutViewSize = useInjectable<LayoutViewSizeConfig>(LayoutViewSizeConfig);
|
|
111
112
|
|
|
@@ -140,11 +141,15 @@ export const ContainerView: React.FC<{
|
|
|
140
141
|
|
|
141
142
|
return (
|
|
142
143
|
<div ref={containerRef} className={cls(styles.view_container, className)}>
|
|
144
|
+
{!!customTitleBar && customTitleBar}
|
|
143
145
|
{!CustomComponent && (
|
|
144
146
|
<div onContextMenu={handleContextMenu} className={styles.panel_titlebar}>
|
|
145
147
|
{!title ? null : (
|
|
146
148
|
<TitleBar
|
|
149
|
+
containerId={containerId}
|
|
150
|
+
side={side}
|
|
147
151
|
title={title}
|
|
152
|
+
draggable={draggable}
|
|
148
153
|
height={layoutViewSize.panelTitleBarHeight}
|
|
149
154
|
menubar={<InlineActionBar menus={titleMenu} />}
|
|
150
155
|
/>
|
|
@@ -664,6 +664,7 @@ export class TabbarService extends WithEventBus {
|
|
|
664
664
|
// drag & drop
|
|
665
665
|
handleDragStart(e: React.DragEvent, containerId: string) {
|
|
666
666
|
e.dataTransfer.setData('containerId', containerId);
|
|
667
|
+
this.layoutService.showDropAreaForContainer(containerId);
|
|
667
668
|
}
|
|
668
669
|
|
|
669
670
|
handleDrop(e: React.DragEvent, target: string) {
|
|
@@ -677,6 +678,10 @@ export class TabbarService extends WithEventBus {
|
|
|
677
678
|
}
|
|
678
679
|
}
|
|
679
680
|
|
|
681
|
+
handleDragEnd(e: React.DragEvent) {
|
|
682
|
+
this.layoutService.hideDropArea();
|
|
683
|
+
}
|
|
684
|
+
|
|
680
685
|
restoreState() {
|
|
681
686
|
this.storedState = this.layoutState.getState(LAYOUT_STATE.getTabbarSpace(this.location), {});
|
|
682
687
|
for (const containerId of this.state.keys()) {
|
|
@@ -691,6 +696,19 @@ export class TabbarService extends WithEventBus {
|
|
|
691
696
|
});
|
|
692
697
|
}
|
|
693
698
|
|
|
699
|
+
removeContainer(containerId: string) {
|
|
700
|
+
const disposable = this.disposableMap.get(containerId);
|
|
701
|
+
disposable?.dispose();
|
|
702
|
+
this.updateCurrentContainerId('');
|
|
703
|
+
this.doChangeViewEmitter.fire();
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
dynamicAddContainer(containerId: string, options: ComponentRegistryInfo) {
|
|
707
|
+
this.registerContainer(containerId, options);
|
|
708
|
+
this.updateCurrentContainerId(containerId);
|
|
709
|
+
this.doChangeViewEmitter.fire();
|
|
710
|
+
}
|
|
711
|
+
|
|
694
712
|
protected doInsertTab(containers: ComponentRegistryInfo[], sourceIndex: number, targetIndex: number) {
|
|
695
713
|
const targetPriority = this.getContainerState(containers[targetIndex].options!.containerId).priority;
|
|
696
714
|
const changePriority = (sourceIndex: number, targetIndex: number) => {
|
|
@@ -86,6 +86,10 @@ export interface IMainLayoutService {
|
|
|
86
86
|
getExtraTopMenu(): IContextMenu;
|
|
87
87
|
getExtraMenu(): IContextMenu;
|
|
88
88
|
getAllAccordionService(): Map<string, AccordionService>;
|
|
89
|
+
moveContainerTo(containerId: string, to: string): void;
|
|
90
|
+
showDropAreaForContainer(containerId: string): void;
|
|
91
|
+
hideDropArea(): void;
|
|
92
|
+
findTabbarServiceByContainerId(containerId: string): TabbarService | undefined;
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
export const MainLayoutContribution = Symbol('MainLayoutContribution');
|
|
@@ -128,3 +132,6 @@ export class ViewCollapseChangedEvent extends BasicEvent<{
|
|
|
128
132
|
}> {}
|
|
129
133
|
|
|
130
134
|
export const SUPPORT_ACCORDION_LOCATION = new Set([SlotLocation.left, SlotLocation.right]);
|
|
135
|
+
|
|
136
|
+
export const DROP_BOTTOM_CONTAINER = 'drop-bottom';
|
|
137
|
+
export const DROP_RIGHT_CONTAINER = 'drop-right';
|