opti: 1.adjust eventlistener;
This commit is contained in:
@@ -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(() => {
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
|||||||
Reference in New Issue
Block a user