opti: 1.adjust eventlistener;

This commit is contained in:
mitsuha
2022-08-24 01:54:10 +08:00
parent 85838c77a1
commit ab1fe668b4
2 changed files with 35 additions and 15 deletions

View File

@@ -14,6 +14,7 @@ import {
destroyEventList, destroyEventList,
getContentByAsyncBlocks, getContentByAsyncBlocks,
getPageTOC, getPageTOC,
listenerMap,
type TocType, type TocType,
} from '../../utils/toc'; } from '../../utils/toc';
@@ -123,24 +124,35 @@ export const Toc = (props: Props) => {
const { page_id } = useParams(); const { page_id } = useParams();
const [tocDataSource, setTocDataSource] = useState<TocType[]>([]); const [tocDataSource, setTocDataSource] = useState<TocType[]>([]);
const [activeBlockId, setActiveBlockId] = useState(''); const [activeBlockId, setActiveBlockId] = useState('');
const [blockEventListeners, setBlockEventListeners] = useState([]);
const updateTocDataSource = useCallback(async () => { 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 = [] } = const { children = [] } =
(await editor.queryByPageId(page_id))?.[0] || {}; (await editor.queryByPageId(page_id))?.[0] || {};
const asyncBlocks = (await editor.getBlockByIds(children)) || []; const asyncBlocks = (await editor.getBlockByIds(children)) || [];
const { tocContents, eventListeners } = await getContentByAsyncBlocks( const { tocContents } = await getContentByAsyncBlocks(
asyncBlocks, asyncBlocks,
updateTocDataSource updateTocDataSource
); );
/* toc: flat content */
const tocDataSource = getPageTOC(asyncBlocks, tocContents); const tocDataSource = getPageTOC(asyncBlocks, tocContents);
setTocDataSource(tocDataSource); setTocDataSource(tocDataSource);
setBlockEventListeners(eventListeners);
/* remove listener when unmount component */
return destroyEventList;
}, [editor, page_id]); }, [editor, page_id]);
/* init toc and add page/block update-listener & unmount-listener */
useEffect(() => { useEffect(() => {
(async () => { (async () => {
await updateTocDataSource(); await updateTocDataSource();

View File

@@ -13,16 +13,16 @@ export const BLOCK_TYPES = {
HEADING3: 'heading3', 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 */ /* 😞😞sorry, I don't know how to define unlimited dimensions array */
const getContentByAsyncBlocks = async ( const getContentByAsyncBlocks = async (
asyncBlocks: AsyncBlock[] = [], asyncBlocks: AsyncBlock[] = [],
callback: () => void callback: () => void
): Promise<{ ): Promise<{
tocContents: any[]; tocContents: any[];
eventListeners: (() => void | undefined)[];
}> => { }> => {
const eventListeners = [];
const collect = async (asyncBlocks): Promise<any[]> => { const collect = async (asyncBlocks): Promise<any[]> => {
/* maybe should recast it to tail recursion */ /* maybe should recast it to tail recursion */
return await Promise.all( return await Promise.all(
@@ -33,11 +33,14 @@ const getContentByAsyncBlocks = async (
return collect(asyncBlocks); return collect(asyncBlocks);
} }
/* get update notice */ /* add only once event listener for every block */
const destroyHandler = asyncBlock.onUpdate(callback); if (!listenerMap.has(asyncBlock.id)) {
/* get update notice */
const destroyHandler = asyncBlock.onUpdate(callback);
/* collect destroy handlers */ /* collect destroy handlers */
eventListeners.push(destroyHandler); listenerMap.set(asyncBlock.id, destroyHandler);
}
const { id, type } = asyncBlock; const { id, type } = asyncBlock;
if (Object.values(BLOCK_TYPES).includes(type)) { if (Object.values(BLOCK_TYPES).includes(type)) {
@@ -57,10 +60,14 @@ const getContentByAsyncBlocks = async (
return { return {
tocContents: await collect(asyncBlocks), tocContents: await collect(asyncBlocks),
eventListeners,
}; };
}; };
/**
* get flat toc
* @param asyncBlocks
* @param tocContents
*/
const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents): TocType[] => { const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents): TocType[] => {
return tocContents return tocContents
.reduce((tocGroupContent, tocContent, index) => { .reduce((tocGroupContent, tocContent, index) => {
@@ -83,9 +90,10 @@ const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents): TocType[] => {
.filter(Boolean); .filter(Boolean);
}; };
const destroyEventList = ( /* destroy page/block update-listener */
eventListeners: (() => void | undefined)[] = [] const destroyEventList = (): boolean => {
): boolean => { const eventListeners = listenerMap.values();
for (const eventListener of eventListeners) { for (const eventListener of eventListeners) {
eventListener?.(); eventListener?.();
} }