mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-02 06:39:46 +08:00
feat: init new plugin system (#3323)
This commit is contained in:
@@ -7,20 +7,18 @@ import { SidebarSwitch } from '@affine/component/app-sidebar/sidebar-header';
|
||||
import { isDesktop } from '@affine/env/constant';
|
||||
import { CloseIcon, MinusIcon, RoundedRectangleIcon } from '@blocksuite/icons';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
|
||||
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
|
||||
import { headerItemsAtom } from '@toeverything/plugin-infra/manager';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import type { FC, HTMLAttributes, PropsWithChildren, ReactNode } from 'react';
|
||||
import {
|
||||
forwardRef,
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { contentLayoutAtom } from '../../../atoms/layout';
|
||||
import { currentModeAtom } from '../../../atoms/mode';
|
||||
import type { AffineOfficialWorkspace } from '../../../shared';
|
||||
import DownloadClientTip from './download-tips';
|
||||
@@ -124,41 +122,37 @@ const HeaderRightItems: Record<HeaderRightItemName, HeaderItem> = {
|
||||
|
||||
export type HeaderProps = BaseHeaderProps;
|
||||
|
||||
const PluginHeaderItemAdapter = memo<{
|
||||
headerItem: PluginUIAdapter['headerItem'];
|
||||
}>(function PluginHeaderItemAdapter({ headerItem }) {
|
||||
return (
|
||||
<div>
|
||||
{headerItem({
|
||||
contentLayoutAtom,
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const PluginHeader = () => {
|
||||
const affinePluginsMap = useAtomValue(affinePluginsAtom);
|
||||
const plugins = useMemo(
|
||||
() => Object.values(affinePluginsMap),
|
||||
[affinePluginsMap]
|
||||
);
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
const headerItems = useAtomValue(headerItemsAtom);
|
||||
useEffect(() => {
|
||||
const root = rootRef.current;
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
let disposes: (() => void)[] = [];
|
||||
const renderTimeout = setTimeout(() => {
|
||||
disposes = Object.entries(headerItems).map(([id, headerItem]) => {
|
||||
const div = document.createElement('div');
|
||||
div.setAttribute('plugin-id', id);
|
||||
const cleanup = headerItem(div);
|
||||
root.appendChild(div);
|
||||
return () => {
|
||||
cleanup();
|
||||
root.removeChild(div);
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{plugins
|
||||
.filter(plugin => plugin.uiAdapter.headerItem != null)
|
||||
.map(plugin => {
|
||||
const headerItem = plugin.uiAdapter
|
||||
.headerItem as PluginUIAdapter['headerItem'];
|
||||
return (
|
||||
<PluginHeaderItemAdapter
|
||||
key={plugin.definition.id}
|
||||
headerItem={headerItem}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
return () => {
|
||||
clearTimeout(renderTimeout);
|
||||
setTimeout(() => {
|
||||
disposes.forEach(dispose => dispose());
|
||||
});
|
||||
};
|
||||
}, [headerItems]);
|
||||
|
||||
return <div className={styles.pluginHeaderItems} ref={rootRef} />;
|
||||
};
|
||||
|
||||
export const Header = forwardRef<
|
||||
|
||||
@@ -238,3 +238,10 @@ export const windowAppControl = style({
|
||||
},
|
||||
},
|
||||
} as ComplexStyleRule);
|
||||
|
||||
export const pluginHeaderItems = style({
|
||||
display: 'flex',
|
||||
gap: '12px',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user