[go: nahoru, domu]

Skip to content

Commit

Permalink
fix(ui): fix flickering on register ui parts (#2430)
Browse files Browse the repository at this point in the history
* fix(ui): fix flickering on register ui parts

* chore: fix unintended bug

* chore: update pnpm lock

* fix: fix type
  • Loading branch information
wzhudev committed Jun 5, 2024
1 parent e8afcfd commit 2d036a3
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 48 deletions.
13 changes: 7 additions & 6 deletions packages/ui/src/services/parts/parts.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ export enum BuiltInUIPart {
export interface IUIPartsService {
componentRegistered$: Observable<ComponentPartKey>;

registerComponent(part: ComponentPartKey, component: () => ComponentType): IDisposable;
registerComponent(part: ComponentPartKey, componentFactory: () => ComponentType): IDisposable;
getComponents(part: ComponentPartKey): Set<ComponentRenderer>;
}

export const IUIPartsService = createIdentifier<IUIPartsService>('ui.parts.service');

export class UIPartsService extends Disposable implements IUIPartsService {
private _componentsByPart: Map<ComponentPartKey, Set<ComponentRenderer>> = new Map();
private _componentsByPart: Map<ComponentPartKey, Set<ComponentType>> = new Map();

private readonly _componentRegistered$ = new Subject<ComponentPartKey>();
readonly componentRegistered$ = this._componentRegistered$.asObservable();
Expand All @@ -54,24 +54,25 @@ export class UIPartsService extends Disposable implements IUIPartsService {
this._componentRegistered$.complete();
}

registerComponent(part: ComponentPartKey, component: () => React.ComponentType): IDisposable {
registerComponent(part: ComponentPartKey, componentFactory: () => React.ComponentType): IDisposable {
const componentType = componentFactory();
const components = (
this._componentsByPart.get(part)
|| this._componentsByPart.set(part, new Set()).get(part)!
).add(component);
).add(componentType);

this._componentRegistered$.next(part);

return toDisposable(() => {
components.delete(component);
components.delete(componentType);
if (components.size === 0) {
this._componentsByPart.delete(part);
}
this._componentRegistered$.next(part);
});
}

getComponents(part: ComponentPartKey): Set<ComponentRenderer> {
getComponents(part: ComponentPartKey): Set<ComponentType> {
return new Set([...(this._componentsByPart.get(part) || new Set())]);
}
}
46 changes: 14 additions & 32 deletions packages/ui/src/views/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import { useDependency } from '@wendellhu/redi/react-bindings';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import type { IWorkbenchOptions } from '../controllers/ui/ui.controller';
import { IMessageService } from '../services/message/message.service';
import { BuiltInUIPart, IUIPartsService } from '../services/parts/parts.service';
import { BuiltInUIPart } from '../services/parts/parts.service';
import styles from './app.module.less';
import { ComponentContainer } from './components/ComponentContainer';
import { ComponentContainer, useComponentsOfPart } from './components/ComponentContainer';
import { Toolbar } from './components/doc-bars/Toolbar';
import { Sidebar } from './components/sidebar/Sidebar';
import { ZenZone } from './components/zen-zone/ZenZone';
Expand All @@ -50,30 +50,12 @@ export function App(props: IUniverAppProps) {
const messageService = useDependency(IMessageService);
const contentRef = useRef<HTMLDivElement>(null);

const uiPartsService = useDependency(IUIPartsService);

const [updateTrigger, setUpdateTrigger] = useState({});

useEffect(() => {
const updateSubscription = uiPartsService.componentRegistered$.subscribe(() => {
setUpdateTrigger({});
});

return () => {
updateSubscription.unsubscribe();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const { headerComponents, contentComponents, footerComponents, headerMenuComponents, leftSidebarComponents, globalComponents } = useMemo(() => ({
headerComponents: uiPartsService.getComponents(BuiltInUIPart.HEADER),
contentComponents: uiPartsService.getComponents(BuiltInUIPart.CONTENT),
footerComponents: uiPartsService.getComponents(BuiltInUIPart.FOOTER),
headerMenuComponents: uiPartsService.getComponents(BuiltInUIPart.HEADER_MENU),
leftSidebarComponents: uiPartsService.getComponents(BuiltInUIPart.LEFT_SIDEBAR),
globalComponents: uiPartsService.getComponents(BuiltInUIPart.GLOBAL),
// eslint-disable-next-line react-hooks/exhaustive-deps
}), [updateTrigger]);
const footerComponents = useComponentsOfPart(BuiltInUIPart.FOOTER);
const headerComponents = useComponentsOfPart(BuiltInUIPart.HEADER);
const headerMenuComponents = useComponentsOfPart(BuiltInUIPart.HEADER_MENU);
const contentComponents = useComponentsOfPart(BuiltInUIPart.CONTENT);
const leftSidebarComponents = useComponentsOfPart(BuiltInUIPart.LEFT_SIDEBAR);
const globalComponents = useComponentsOfPart(BuiltInUIPart.GLOBAL);

useEffect(() => {
if (!themeService.getCurrentTheme()) {
Expand Down Expand Up @@ -135,12 +117,12 @@ export function App(props: IUniverAppProps) {
<section className={styles.appContainer}>
<div className={styles.appContainerWrapper}>
<aside className={styles.appContainerLeftSidebar}>
<ComponentContainer components={leftSidebarComponents} />
<ComponentContainer key="left-sidebar" components={leftSidebarComponents} />
</aside>

<section className={styles.appContainerContent}>
<header>
{header && <ComponentContainer components={headerComponents} />}
{header && <ComponentContainer key="header" components={headerComponents} />}
</header>

<section
Expand All @@ -149,7 +131,7 @@ export function App(props: IUniverAppProps) {
data-range-selector
onContextMenu={(e) => e.preventDefault()}
>
<ComponentContainer components={contentComponents} />
<ComponentContainer key="content" components={contentComponents} />
</section>
</section>

Expand All @@ -161,15 +143,15 @@ export function App(props: IUniverAppProps) {
{/* footer */}
{footer && (
<footer className={styles.appFooter}>
<ComponentContainer components={footerComponents} />
<ComponentContainer key="footer" components={footerComponents} />
</footer>
)}

<ZenZone />
</section>
</div>
<ComponentContainer components={globalComponents} />
<ComponentContainer components={builtInGlobalComponents} />
<ComponentContainer key="global" components={globalComponents} />
<ComponentContainer key="built-in-global" components={builtInGlobalComponents} />
{contextMenu && <ContextMenu />}
</ConfigProvider>
);
Expand Down
12 changes: 6 additions & 6 deletions packages/ui/src/views/components/ComponentContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { useObservable } from '../../components/hooks/observable';
import { IUIPartsService } from '../../services/parts/parts.service';

export interface IComponentContainerProps {
components?: Set<() => ComponentType>;
components?: Set<ComponentType>;
fallback?: React.ReactNode;
sharedProps?: Record<string, unknown>;
}
Expand All @@ -32,9 +32,9 @@ export function ComponentContainer(props: IComponentContainerProps) {
const { components, fallback, sharedProps } = props;
if (!components || components.size === 0) return fallback ?? null;

return Array.from(components.values()).map((component, index) =>
React.createElement(component(), { key: `${index}`, ...sharedProps })
);
return Array.from(components.values()).map((component, index) => {
return React.createElement(component, { key: `${component.displayName ?? index}`, ...sharedProps });
});
}

/**
Expand All @@ -55,9 +55,9 @@ export function useComponentsOfPart(part: string, injector?: Injector) {
),
undefined,
undefined,
[uiPartsService]
[uiPartsService, part]
);

// eslint-disable-next-line react-hooks/exhaustive-deps
// eslint-disable-next-line react-hooks/exhaustive-deps
return useMemo(() => uiPartsService.getComponents(part), [componentPartUpdateCount]);
}
2 changes: 1 addition & 1 deletion packages/ui/src/views/components/doc-bars/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const MENU_POSITIONS = [
];

export interface IToolbarProps {
headerMenuComponents?: Set<() => ComponentType>;
headerMenuComponents?: Set<ComponentType>;
}

/**
Expand Down
4 changes: 1 addition & 3 deletions packages/ui/src/views/parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,4 @@ import type { ComponentType } from 'react';

import { GlobalZone } from './components/global-zone/GlobalZone';

export const builtInGlobalComponents: Set<() => ComponentType> = new Set([
() => GlobalZone,
]);
export const builtInGlobalComponents: Set<ComponentType> = new Set([GlobalZone]);

0 comments on commit 2d036a3

Please sign in to comment.