Skip to content

Commit c4698d3

Browse files
authored
fix: hidden tabbar view delay (#4507)
1 parent e014402 commit c4698d3

2 files changed

Lines changed: 66 additions & 36 deletions

File tree

packages/main-layout/src/browser/tabbar/bar.view.tsx

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import cls from 'classnames';
2-
import React, { useEffect } from 'react';
2+
import React, { CSSProperties, FC, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react';
33

44
import { Badge, Icon } from '@opensumi/ide-components';
55
import {
@@ -47,13 +47,13 @@ function getBadgeValue(badge: string | ViewBadge) {
4747
}
4848

4949
export interface ITabbarViewProps {
50-
TabView: React.FC<{ component: ComponentRegistryInfo }>;
50+
TabView: FC<{ component: ComponentRegistryInfo }>;
5151
forbidCollapse?: boolean;
5252
// tabbar的尺寸(横向为宽,纵向高),tab折叠后为改尺寸加上panelBorderSize
5353
barSize?: number;
5454
// 包含tab的内外边距的总尺寸,用于控制溢出隐藏逻辑
5555
tabSize: number;
56-
MoreTabView: React.FC;
56+
MoreTabView: FC;
5757
/**
5858
* 禁用自动检测高度或者宽度变化后自动调整显示 tab 的数量
5959
*/
@@ -64,7 +64,7 @@ export interface ITabbarViewProps {
6464
// tab上预留的位置,用来控制tab过多的显示效果
6565
margin?: number;
6666
canHideTabbar?: boolean;
67-
renderOtherVisibleContainers?: React.FC<{
67+
renderOtherVisibleContainers?: FC<{
6868
props: ITabbarViewProps;
6969
renderContainers: (
7070
component: ComponentRegistryInfo,
@@ -74,7 +74,7 @@ export interface ITabbarViewProps {
7474
}>;
7575
}
7676

77-
export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
77+
export const TabbarViewBase: FC<ITabbarViewProps> = (props) => {
7878
const {
7979
TabView,
8080
MoreTabView,
@@ -89,18 +89,47 @@ export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
8989
renderOtherVisibleContainers = () => null,
9090
disableAutoAdjust,
9191
} = props;
92-
const { side, direction, fullSize } = React.useContext(TabbarConfig);
92+
const { side, direction, fullSize } = useContext(TabbarConfig);
9393
const tabbarService: TabbarService = useInjectable(TabbarServiceFactory)(side);
9494
const styles_tab_bar = useDesignStyles(styles.tab_bar, 'tab_bar');
9595
const styles_bar_content = useDesignStyles(styles.bar_content, 'bar_content');
96+
const visibleCount = useMemo(
97+
() => (disableAutoAdjust ? Number.MAX_SAFE_INTEGER : Math.floor(fullSize - (margin || 0) / tabSize)),
98+
[disableAutoAdjust, fullSize, margin, tabSize],
99+
);
100+
const [containers, setContainers] = useState<ComponentRegistryInfo[][]>(
101+
splitVisibleTabs(
102+
tabbarService.visibleContainers.filter((container) => !container.options?.hideTab),
103+
visibleCount,
104+
),
105+
);
96106

97-
React.useEffect(() => {
107+
useEffect(() => {
98108
// 内部只关注总的宽度
99109
tabbarService.updateBarSize(barSize + panelBorderSize);
100110
}, []);
101111

102-
const currentContainerId = useAutorun(tabbarService.currentContainerId);
112+
useEffect(() => {
113+
setContainers(
114+
splitVisibleTabs(
115+
tabbarService.visibleContainers.filter((container) => !container.options?.hideTab),
116+
visibleCount,
117+
),
118+
);
119+
const disposable = tabbarService.onStateChange(() => {
120+
setContainers(
121+
splitVisibleTabs(
122+
tabbarService.visibleContainers.filter((container) => !container.options?.hideTab),
123+
visibleCount,
124+
),
125+
);
126+
});
127+
return () => {
128+
disposable.dispose();
129+
};
130+
}, [visibleCount]);
103131

132+
const currentContainerId = useAutorun(tabbarService.currentContainerId);
104133
const hideTabBarWhenHidePanel = usePreference<boolean>('workbench.hideSlotTabBarWhenHidePanel', false);
105134

106135
const willHideTabbar = canHideTabbar && hideTabBarWhenHidePanel;
@@ -113,18 +142,13 @@ export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
113142
tabbarService.resizeHandle?.setSize(0);
114143
}
115144

116-
const visibleCount = disableAutoAdjust ? Number.MAX_SAFE_INTEGER : Math.floor(fullSize - (margin || 0) / tabSize);
117-
118-
const [visibleContainers, hideContainers] = splitVisibleTabs(
119-
tabbarService.visibleContainers.filter((container) => !container.options?.hideTab),
120-
visibleCount,
121-
);
145+
const [visibleContainers, hideContainers] = containers;
122146

123147
hideContainers.forEach((componentInfo) => {
124148
tabbarService.updateTabInMoreKey(componentInfo.options!.containerId, true);
125149
});
126150

127-
const renderContainers = React.useCallback(
151+
const renderContainers = useCallback(
128152
(component: ComponentRegistryInfo, tabbarService: TabbarService, currentContainerId?: string, side?: string) => {
129153
const containerId = component.options?.containerId;
130154
if (!containerId) {
@@ -215,16 +239,16 @@ export const TabbarViewBase: React.FC<ITabbarViewProps> = (props) => {
215239
);
216240
};
217241

218-
export const IconTabView: React.FC<{ component: ComponentRegistryProvider }> = ({ component: defaultComponent }) => {
242+
export const IconTabView: FC<{ component: ComponentRegistryProvider }> = ({ component: defaultComponent }) => {
219243
const progressService: IProgressService = useInjectable(IProgressService);
220244
const keybindingRegistry: KeybindingRegistry = useInjectable(KeybindingRegistry);
221245
const styles_icon_tab = useDesignStyles(styles.icon_tab, 'icon_tab');
222-
const [component, setComponent] = React.useState<ComponentRegistryProvider>(defaultComponent);
246+
const [component, setComponent] = useState<ComponentRegistryProvider>(defaultComponent);
223247
const indicator = progressService.getIndicator(component.options?.containerId || '');
224248

225249
const inProgress = useAutorun(indicator!.progressModel.show);
226250

227-
const title = React.useMemo(() => {
251+
const title = useMemo(() => {
228252
const options = component.options;
229253
if (options?.activateKeyBinding) {
230254
return `${options?.title} (${keybindingRegistry.acceleratorForKeyString(options.activateKeyBinding, '+')})`;
@@ -258,8 +282,8 @@ export const IconTabView: React.FC<{ component: ComponentRegistryProvider }> = (
258282
);
259283
};
260284

261-
export const TextTabView: React.FC<{ component: ComponentRegistryProvider }> = ({ component: defaultComponent }) => {
262-
const [component, setComponent] = React.useState<ComponentRegistryProvider>(defaultComponent);
285+
export const TextTabView: FC<{ component: ComponentRegistryProvider }> = ({ component: defaultComponent }) => {
286+
const [component, setComponent] = useState<ComponentRegistryProvider>(defaultComponent);
263287
useEffect(() => {
264288
const dispose = component.onChange((newComponent) => {
265289
// Immediately update with current component to handle initial badge value
@@ -277,7 +301,7 @@ export const TextTabView: React.FC<{ component: ComponentRegistryProvider }> = (
277301
);
278302
};
279303

280-
export const IconElipses: React.FC = () => {
304+
export const IconElipses: FC = () => {
281305
const styles_icon_tab = useDesignStyles(styles.icon_tab, 'icon_tab');
282306
return (
283307
<div className={styles_icon_tab}>
@@ -287,17 +311,17 @@ export const IconElipses: React.FC = () => {
287311
);
288312
};
289313

290-
export const TextElipses: React.FC = () => (
314+
export const TextElipses: FC = () => (
291315
<div className={styles.text_tab}>
292316
<div className={styles.bottom_tab_title}>
293317
<i className={getIcon('doubleright')}></i>
294318
</div>
295319
</div>
296320
);
297321

298-
export const RightTabbarRenderer: React.FC<{ barSize?: number; style?: React.CSSProperties }> = (props) => {
322+
export const RightTabbarRenderer: FC<{ barSize?: number; style?: CSSProperties }> = (props) => {
299323
const { barSize = 48, style } = props;
300-
const { side } = React.useContext(TabbarConfig);
324+
const { side } = useContext(TabbarConfig);
301325
const tabbarService: TabbarService = useInjectable(TabbarServiceFactory)(side);
302326

303327
const styles_right_tab_bar = useDesignStyles(styles.right_tab_bar, 'right_tab_bar');
@@ -322,8 +346,8 @@ export const RightTabbarRenderer: React.FC<{ barSize?: number; style?: React.CSS
322346
);
323347
};
324348

325-
export const LeftTabbarRenderer: React.FC<{
326-
renderOtherVisibleContainers?: React.FC<{
349+
export const LeftTabbarRenderer: FC<{
350+
renderOtherVisibleContainers?: FC<{
327351
props: ITabbarViewProps;
328352
renderContainers: (
329353
component: ComponentRegistryInfo,
@@ -332,15 +356,15 @@ export const LeftTabbarRenderer: React.FC<{
332356
) => JSX.Element | null;
333357
}>;
334358
isRenderExtraTopMenus?: boolean;
335-
renderExtraMenus?: React.ReactNode;
359+
renderExtraMenus?: ReactNode;
336360
tabbarViewProps?: Partial<ITabbarViewProps>;
337361
}> = ({ renderOtherVisibleContainers, isRenderExtraTopMenus = true, renderExtraMenus, tabbarViewProps }) => {
338-
const { side } = React.useContext(TabbarConfig);
362+
const { side } = useContext(TabbarConfig);
339363
const layoutService = useInjectable<IMainLayoutService>(IMainLayoutService);
340364
const tabbarService: TabbarService = useInjectable(TabbarServiceFactory)(side);
341365

342-
const extraTopMenus = React.useMemo(() => layoutService.getExtraTopMenu(), [layoutService]);
343-
const extraMenus = React.useMemo(() => layoutService.getExtraMenu(), [layoutService]);
366+
const extraTopMenus = useMemo(() => layoutService.getExtraTopMenu(), [layoutService]);
367+
const extraMenus = useMemo(() => layoutService.getExtraMenu(), [layoutService]);
344368

345369
const styles_left_tab_bar = useDesignStyles(styles.left_tab_bar, 'left_tab_bar');
346370
const styles_left_tab = useDesignStyles(styles.left_tab, 'left_tab');
@@ -371,8 +395,8 @@ export const LeftTabbarRenderer: React.FC<{
371395
);
372396
};
373397

374-
export const BottomTabbarRenderer: React.FC = () => {
375-
const { side } = React.useContext(TabbarConfig);
398+
export const BottomTabbarRenderer: FC = () => {
399+
const { side } = useContext(TabbarConfig);
376400
const tabbarService: TabbarService = useInjectable(TabbarServiceFactory)(side);
377401
const styles_bottom_bar_container = useDesignStyles(styles.bottom_bar_container, 'bottom_bar_container');
378402
const styles_bottom_tab = useDesignStyles(styles.bottom_tab, 'bottom_tab');
@@ -396,9 +420,9 @@ export const BottomTabbarRenderer: React.FC = () => {
396420
);
397421
};
398422

399-
export const ChatTabbarRenderer2: React.FC<{ barSize?: number; style?: React.CSSProperties }> = (props) => {
423+
export const ChatTabbarRenderer2: FC<{ barSize?: number; style?: CSSProperties }> = (props) => {
400424
const { barSize = 32, style } = props;
401-
const { side } = React.useContext(TabbarConfig);
425+
const { side } = useContext(TabbarConfig);
402426
const tabbarService: TabbarService = useInjectable(TabbarServiceFactory)(side);
403427
useEffect(() => {
404428
tabbarService.setIsLatter(true);

packages/main-layout/src/browser/tabbar/tabbar.service.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ const NONE_CONTAINER_ID = undefined;
7676
@Injectable({ multiple: true })
7777
export class TabbarService extends WithEventBus {
7878
private readonly doChangeViewEmitter = new Emitter<void>();
79+
private readonly onStateChangeEmitter = new Emitter<void>();
80+
readonly onStateChange = this.onStateChangeEmitter.event;
81+
7982
private readonly shouldChangeView = observableFromEventOpts<void>(
8083
{ owner: this, equalsFn: () => false },
8184
this.doChangeViewEmitter.event,
@@ -254,13 +257,15 @@ export class TabbarService extends WithEventBus {
254257
const viewState = this.state.get(containerId);
255258
if (viewState) {
256259
viewState.hidden = true;
260+
this.onStateChangeEmitter.fire();
257261
}
258262
}
259263

260264
public showContainer(containerId: string) {
261265
const viewState = this.state.get(containerId);
262266
if (viewState) {
263267
viewState.hidden = false;
268+
this.onStateChangeEmitter.fire();
264269
}
265270
}
266271

@@ -632,7 +637,7 @@ export class TabbarService extends WithEventBus {
632637
}
633638
}
634639

635-
handleContextMenu(event: React.MouseEvent, containerId?: string) {
640+
handleContextMenu = (event: React.MouseEvent, containerId?: string) => {
636641
event.preventDefault();
637642
event.stopPropagation();
638643
const menus = this.menuService.createMenu(
@@ -647,7 +652,7 @@ export class TabbarService extends WithEventBus {
647652
y: event.clientY,
648653
},
649654
});
650-
}
655+
};
651656

652657
showMoreMenu(event: React.MouseEvent, lastContainerId?: string) {
653658
const menus = this.menuService.createMenu(this.moreMenuId, this.scopedCtxKeyService);
@@ -738,6 +743,7 @@ export class TabbarService extends WithEventBus {
738743
stateObj[key] = value;
739744
});
740745
this.layoutState.setState(LAYOUT_STATE.getTabbarSpace(this.location), stateObj);
746+
this.onStateChangeEmitter.fire();
741747
}
742748

743749
// 注册Tab的激活快捷键,对于底部panel,为切换快捷键

0 commit comments

Comments
 (0)