diff --git a/libs/components/editor-core/src/editor/block/async-block.ts b/libs/components/editor-core/src/editor/block/async-block.ts index 73db5de087..1bdc7ef086 100644 --- a/libs/components/editor-core/src/editor/block/async-block.ts +++ b/libs/components/editor-core/src/editor/block/async-block.ts @@ -180,9 +180,49 @@ export class AsyncBlock { return this.event_emitter.emit(eventName, eventData); } - onUpdate(callback: (event: EventData) => void) { - this.on('update', callback); + /** + * @param deep observe deep + * + * NOTICE: the observe of children is async, + * so there maybe have some delay before observe done. + */ + onUpdate(callback: (event: EventData) => void, deep = 0) { + let expired = false; + const unobserveMap: Record void> = {}; + const observeChildren = () => { + if (deep <= 0) { + return; + } + this.children().then(children => { + // Check current event listeners is not expired + if (expired) { + return; + } + children.forEach(child => { + if (unobserveMap[child.id]) return; + const unobserve = child.onUpdate(callback, deep - 1); + unobserveMap[child.id] = unobserve; + }); + }); + }; + + const unobserveChildren = () => { + Object.values(unobserveMap).forEach(unobserve => { + unobserve(); + }); + }; + + this.on('update', e => { + callback(e); + // Update children observe + observeChildren(); + }); + + observeChildren(); + return () => { + expired = true; + unobserveChildren(); this.off('update', callback); }; } diff --git a/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx b/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx index f9b532f6b3..0044a4e6aa 100644 --- a/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx +++ b/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx @@ -40,6 +40,8 @@ export const KanbanParentBlockRender = ({ }; const useBlockProgress = (block?: AsyncBlock) => { + // Progress of the progress bar. The range is between 0 and 1. + // Default progress is 1, that is 100%. const [progress, setProgress] = useState(1); useEffect(() => { @@ -57,36 +59,13 @@ const useBlockProgress = (block?: AsyncBlock) => { setProgress(checkedTodoChildren.length / todoChildren.length); }; - let childrenQueue: (() => void)[] = []; - const childrenUnobserve = () => { - childrenQueue.forEach(fn => fn()); - childrenQueue = []; - }; - - const observeChildren = async () => { - const children = await block.children(); - - childrenUnobserve(); - children.forEach(child => { - const unobserve = child.onUpdate(() => { - updateProgress(); - }); - childrenQueue.push(unobserve); - }); - }; - - observeChildren(); updateProgress(); const unobserve = block.onUpdate(() => { - observeChildren(); updateProgress(); - }); + }, 1); - return () => { - unobserve(); - childrenUnobserve(); - }; + return unobserve; }, [block]); return progress; diff --git a/libs/datasource/db-service/src/services/database/index.ts b/libs/datasource/db-service/src/services/database/index.ts index d6d013a3d3..3d70345f0f 100644 --- a/libs/datasource/db-service/src/services/database/index.ts +++ b/libs/datasource/db-service/src/services/database/index.ts @@ -168,7 +168,7 @@ export class Database { block.on('children', observer_name, listener); block.on('content', observer_name, listener); block.on('parent', observer_name, listener); - block.on('cascade', observer_name, listener); + // block.on('cascade', observer_name, listener); } this.#observers.setStatus(observer_name, 'observing'); @@ -189,7 +189,7 @@ export class Database { block.off('children', observer_name); block.off('content', observer_name); block.off('parent', observer_name); - block.off('cascade', observer_name); + // block.off('cascade', observer_name); } } }