opti: 1.adjust eventlistener;

This commit is contained in:
mitsuha
2022-08-23 21:25:38 +08:00
parent b96d6c37f7
commit 85838c77a1
2 changed files with 66 additions and 28 deletions

View File

@@ -11,8 +11,10 @@ import {
import { useParams } from 'react-router'; import { useParams } from 'react-router';
import { import {
BLOCK_TYPES, BLOCK_TYPES,
destroyEventList,
getContentByAsyncBlocks, getContentByAsyncBlocks,
getPageTOC, getPageTOC,
type TocType,
} from '../../utils/toc'; } from '../../utils/toc';
const StyledTOCItem = styled('a')<{ type?: string; isActive?: boolean }>( const StyledTOCItem = styled('a')<{ type?: string; isActive?: boolean }>(
@@ -119,19 +121,24 @@ const renderTOCContent = tocDataSource => {
export const Toc = (props: Props) => { export const Toc = (props: Props) => {
const { editor } = props; const { editor } = props;
const { page_id } = useParams(); const { page_id } = useParams();
const [tocDataSource, setTocDataSource] = useState([]); const [tocDataSource, setTocDataSource] = useState<TocType[]>([]);
const [activeBlockId, setActiveBlockId] = useState('blockId'); const [activeBlockId, setActiveBlockId] = useState('');
const [blockEventListeners, setBlockEventListeners] = useState([]);
const updateTocDataSource = useCallback(async () => { const updateTocDataSource = useCallback(async () => {
destroyEventList(blockEventListeners);
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 tocDataSource = getPageTOC( const { tocContents, eventListeners } = await getContentByAsyncBlocks(
asyncBlocks, asyncBlocks,
await getContentByAsyncBlocks(asyncBlocks, updateTocDataSource) updateTocDataSource
); );
const tocDataSource = getPageTOC(asyncBlocks, tocContents);
setTocDataSource(tocDataSource); setTocDataSource(tocDataSource);
setBlockEventListeners(eventListeners);
}, [editor, page_id]); }, [editor, page_id]);
useEffect(() => { useEffect(() => {

View File

@@ -1,5 +1,11 @@
import { AsyncBlock } from '@toeverything/components/editor-core'; import { AsyncBlock } from '@toeverything/components/editor-core';
export type TocType = {
id: string;
type: string;
text: string;
};
export const BLOCK_TYPES = { export const BLOCK_TYPES = {
GROUP: 'group', GROUP: 'group',
HEADING1: 'heading1', HEADING1: 'heading1',
@@ -11,36 +17,51 @@ export const BLOCK_TYPES = {
const getContentByAsyncBlocks = async ( const getContentByAsyncBlocks = async (
asyncBlocks: AsyncBlock[] = [], asyncBlocks: AsyncBlock[] = [],
callback: () => void callback: () => void
): Promise<any[]> => { ): Promise<{
/* maybe should recast it to tail recursion */ tocContents: any[];
return await Promise.all( eventListeners: (() => void | undefined)[];
asyncBlocks.map(async (asyncBlock: AsyncBlock) => { }> => {
const asyncBlocks = await asyncBlock.children(); const eventListeners = [];
if (asyncBlocks?.length) { const collect = async (asyncBlocks): Promise<any[]> => {
return getContentByAsyncBlocks(asyncBlocks, callback); /* maybe should recast it to tail recursion */
} return await Promise.all(
asyncBlocks.map(async (asyncBlock: AsyncBlock) => {
const asyncBlocks = await asyncBlock.children();
/* get update notice */ if (asyncBlocks?.length) {
asyncBlock.onUpdate(callback); return collect(asyncBlocks);
}
const { id, type } = asyncBlock; /* get update notice */
if (Object.values(BLOCK_TYPES).includes(type)) { const destroyHandler = asyncBlock.onUpdate(callback);
const properties = await asyncBlock.getProperties();
return { /* collect destroy handlers */
id, eventListeners.push(destroyHandler);
type,
text: properties?.text?.value?.[0]?.text || '',
};
}
return null; const { id, type } = asyncBlock;
}) if (Object.values(BLOCK_TYPES).includes(type)) {
); const properties = await asyncBlock.getProperties();
return {
id,
type,
text: properties?.text?.value?.[0]?.text || '',
};
}
return null;
})
);
};
return {
tocContents: await collect(asyncBlocks),
eventListeners,
};
}; };
const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents) => { const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents): TocType[] => {
return tocContents return tocContents
.reduce((tocGroupContent, tocContent, index) => { .reduce((tocGroupContent, tocContent, index) => {
const { id, type } = asyncBlocks[index]; const { id, type } = asyncBlocks[index];
@@ -62,4 +83,14 @@ const getPageTOC = (asyncBlocks: AsyncBlock[], tocContents) => {
.filter(Boolean); .filter(Boolean);
}; };
export { getPageTOC, getContentByAsyncBlocks }; const destroyEventList = (
eventListeners: (() => void | undefined)[] = []
): boolean => {
for (const eventListener of eventListeners) {
eventListener?.();
}
return true;
};
export { getPageTOC, getContentByAsyncBlocks, destroyEventList };