mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-13 16:16:46 +08:00
opti: 1.adjust eventlistener;
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
destroyEventList,
|
||||
getContentByAsyncBlocks,
|
||||
getPageTOC,
|
||||
listenerMap,
|
||||
type TocType,
|
||||
} from '../../utils/toc';
|
||||
|
||||
@@ -123,24 +124,35 @@ export const Toc = (props: Props) => {
|
||||
const { page_id } = useParams();
|
||||
const [tocDataSource, setTocDataSource] = useState<TocType[]>([]);
|
||||
const [activeBlockId, setActiveBlockId] = useState('');
|
||||
const [blockEventListeners, setBlockEventListeners] = useState([]);
|
||||
|
||||
const updateTocDataSource = useCallback(async () => {
|
||||
destroyEventList(blockEventListeners);
|
||||
/* page listener: trigger update-notice when add new group */
|
||||
const pageAsyncBlock = (await editor.getBlockByIds([page_id]))?.[0];
|
||||
if (!listenerMap.has(pageAsyncBlock.id)) {
|
||||
listenerMap.set(
|
||||
pageAsyncBlock.id,
|
||||
pageAsyncBlock.onUpdate(updateTocDataSource)
|
||||
);
|
||||
}
|
||||
|
||||
/* block listener: trigger update-notice when change block content */
|
||||
const { children = [] } =
|
||||
(await editor.queryByPageId(page_id))?.[0] || {};
|
||||
const asyncBlocks = (await editor.getBlockByIds(children)) || [];
|
||||
const { tocContents, eventListeners } = await getContentByAsyncBlocks(
|
||||
const { tocContents } = await getContentByAsyncBlocks(
|
||||
asyncBlocks,
|
||||
updateTocDataSource
|
||||
);
|
||||
|
||||
/* toc: flat content */
|
||||
const tocDataSource = getPageTOC(asyncBlocks, tocContents);
|
||||
setTocDataSource(tocDataSource);
|
||||
setBlockEventListeners(eventListeners);
|
||||
|
||||
/* remove listener when unmount component */
|
||||
return destroyEventList;
|
||||
}, [editor, page_id]);
|
||||
|
||||
/* init toc and add page/block update-listener & unmount-listener */
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
await updateTocDataSource();
|
||||
|
||||
@@ -13,16 +13,16 @@ export const BLOCK_TYPES = {
|
||||
HEADING3: 'heading3',
|
||||
};
|
||||
|
||||
/* store page/block unmount-listener */
|
||||
export const listenerMap = new Map<string, () => void>();
|
||||
|
||||
/* 😞😞sorry, I don't know how to define unlimited dimensions array */
|
||||
const getContentByAsyncBlocks = async (
|
||||
asyncBlocks: AsyncBlock[] = [],
|
||||
callback: () => void
|
||||
): Promise<{
|
||||
tocContents: any[];
|
||||
eventListeners: (() => void | undefined)[];
|
||||
}> => {
|
||||
const eventListeners = [];
|
||||
|
||||
const collect = async (asyncBlocks): Promise<any[]> => {
|
||||
/* maybe should recast it to tail recursion */
|
||||
return await Promise.all(
|
||||
@@ -33,11 +33,14 @@ const getContentByAsyncBlocks = async (
|
||||
return collect(asyncBlocks);
|
||||
}
|
||||
|
||||
/* get update notice */
|
||||
const destroyHandler = asyncBlock.onUpdate(callback);
|
||||
/* add only once event listener for every block */
|
||||
if (!listenerMap.has(asyncBlock.id)) {
|
||||
/* get update notice */
|
||||
const destroyHandler = asyncBlock.onUpdate(callback);
|
||||
|
||||
/* collect destroy handlers */
|
||||
eventListeners.push(destroyHandler);
|
||||
/* collect destroy handlers */
|
||||
listenerMap.set(asyncBlock.id, destroyHandler);
|
||||
}
|
||||
|
||||
const { id, type } = asyncBlock;
|
||||
if (Object.values(BLOCK_TYPES).includes(type)) {
|
||||
@@ -57,10 +60,14 @@ const getContentByAsyncBlocks = async (
|
||||
|
||||
return {
|
||||
tocContents: await collect(asyncBlocks),
|
||||
eventListeners,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* get flat toc
|
||||
* @param asyncBlocks
|
||||
* @param tocContents
|
||||
*/
|
||||
const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents): TocType[] => {
|
||||
return tocContents
|
||||
.reduce((tocGroupContent, tocContent, index) => {
|
||||
@@ -83,9 +90,10 @@ const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents): TocType[] => {
|
||||
.filter(Boolean);
|
||||
};
|
||||
|
||||
const destroyEventList = (
|
||||
eventListeners: (() => void | undefined)[] = []
|
||||
): boolean => {
|
||||
/* destroy page/block update-listener */
|
||||
const destroyEventList = (): boolean => {
|
||||
const eventListeners = listenerMap.values();
|
||||
|
||||
for (const eventListener of eventListeners) {
|
||||
eventListener?.();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user