From b21727533646909b76901dd2c30151d240ee49eb Mon Sep 17 00:00:00 2001 From: ZLATAN628 <107628611+ZLATAN628@users.noreply.github.com> Date: Fri, 10 Jan 2025 10:48:41 +0800 Subject: [PATCH 1/2] fix issue #1625 --- frontend/layout/lib/layoutModelHooks.ts | 49 ++++++++++++++----------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/frontend/layout/lib/layoutModelHooks.ts b/frontend/layout/lib/layoutModelHooks.ts index 582957b50..1a4e94a2b 100644 --- a/frontend/layout/lib/layoutModelHooks.ts +++ b/frontend/layout/lib/layoutModelHooks.ts @@ -11,22 +11,18 @@ import { LayoutModel } from "./layoutModel"; import { LayoutNode, NodeModel, TileLayoutContents } from "./types"; const layoutModelMap: Map = new Map(); +const timeoutMap: Map = new Map(); export function getLayoutModelForTab(tabAtom: Atom): LayoutModel { const tabData = globalStore.get(tabAtom); if (!tabData) return; const tabId = tabData.oid; - if (layoutModelMap.has(tabId)) { - const layoutModel = layoutModelMap.get(tabData.oid); - if (layoutModel) { - return layoutModel; - } - } - const layoutTreeStateAtom = withLayoutTreeStateAtomFromTab(tabAtom); - const layoutModel = new LayoutModel(layoutTreeStateAtom, globalStore.get, globalStore.set); - globalStore.sub(layoutTreeStateAtom, () => fireAndForget(layoutModel.onTreeStateAtomUpdated.bind(layoutModel))); - layoutModelMap.set(tabId, layoutModel); - return layoutModel; + return computeIfAbsent(layoutModelMap, tabId, (_) => { + const layoutTreeStateAtom = withLayoutTreeStateAtomFromTab(tabAtom); + const layoutModel = new LayoutModel(layoutTreeStateAtom, globalStore.get, globalStore.set); + globalStore.sub(layoutTreeStateAtom, () => fireAndForget(layoutModel.onTreeStateAtomUpdated.bind(layoutModel))); + return layoutModel; + }) } export function getLayoutModelForTabById(tabId: string) { @@ -73,25 +69,26 @@ export function useDebouncedNodeInnerRect(nodeModel: NodeModel): CSSProperties { const isResizing = useAtomValue(nodeModel.isResizing); const prefersReducedMotion = useAtomValue(atoms.prefersReducedMotionAtom); const [innerRect, setInnerRect] = useState(); - const [innerRectDebounceTimeout, setInnerRectDebounceTimeout] = useState(); const setInnerRectDebounced = useCallback( (nodeInnerRect: CSSProperties) => { clearInnerRectDebounce(); - setInnerRectDebounceTimeout( - setTimeout(() => { - setInnerRect(nodeInnerRect); - }, animationTimeS * 1000) - ); + const timeout = setTimeout(() => { + setInnerRect(nodeInnerRect); + }, animationTimeS * 1000); + computeIfAbsent(timeoutMap, nodeModel.blockId, (_) => timeout) }, [animationTimeS] ); - const clearInnerRectDebounce = useCallback(() => { - if (innerRectDebounceTimeout) { - clearTimeout(innerRectDebounceTimeout); - setInnerRectDebounceTimeout(undefined); + const clearInnerRectDebounce = function () { + if (timeoutMap.has(nodeModel.blockId)) { + const innerRectDebounceTimeout = timeoutMap.get(nodeModel.blockId); + if (innerRectDebounceTimeout) { + clearTimeout(innerRectDebounceTimeout); + } + timeoutMap.delete(nodeModel.blockId); } - }, [innerRectDebounceTimeout]); + }; useEffect(() => { if (prefersReducedMotion || isMagnified || isResizing) { @@ -104,3 +101,11 @@ export function useDebouncedNodeInnerRect(nodeModel: NodeModel): CSSProperties { return innerRect; } + +function computeIfAbsent(map: Map, key: V, mappingFunction: (a: V) => F): F { + if (!map.has(key)) { + const newValue = mappingFunction(key); + map.set(key, newValue); + } + return map.get(key); +} From 9c454a016fdfa29b6a1ea23ec9848c35e44541a0 Mon Sep 17 00:00:00 2001 From: ZLATAN628 <107628611+ZLATAN628@users.noreply.github.com> Date: Fri, 10 Jan 2025 11:12:50 +0800 Subject: [PATCH 2/2] Fix code issues --- frontend/layout/lib/layoutModelHooks.ts | 29 +++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/frontend/layout/lib/layoutModelHooks.ts b/frontend/layout/lib/layoutModelHooks.ts index 1a4e94a2b..e791dc65f 100644 --- a/frontend/layout/lib/layoutModelHooks.ts +++ b/frontend/layout/lib/layoutModelHooks.ts @@ -11,18 +11,23 @@ import { LayoutModel } from "./layoutModel"; import { LayoutNode, NodeModel, TileLayoutContents } from "./types"; const layoutModelMap: Map = new Map(); -const timeoutMap: Map = new Map(); +const timeoutMap: Map = new Map(); export function getLayoutModelForTab(tabAtom: Atom): LayoutModel { const tabData = globalStore.get(tabAtom); if (!tabData) return; const tabId = tabData.oid; - return computeIfAbsent(layoutModelMap, tabId, (_) => { - const layoutTreeStateAtom = withLayoutTreeStateAtomFromTab(tabAtom); - const layoutModel = new LayoutModel(layoutTreeStateAtom, globalStore.get, globalStore.set); - globalStore.sub(layoutTreeStateAtom, () => fireAndForget(layoutModel.onTreeStateAtomUpdated.bind(layoutModel))); - return layoutModel; - }) + if (layoutModelMap.has(tabId)) { + const layoutModel = layoutModelMap.get(tabData.oid); + if (layoutModel) { + return layoutModel; + } + } + const layoutTreeStateAtom = withLayoutTreeStateAtomFromTab(tabAtom); + const layoutModel = new LayoutModel(layoutTreeStateAtom, globalStore.get, globalStore.set); + globalStore.sub(layoutTreeStateAtom, () => fireAndForget(layoutModel.onTreeStateAtomUpdated.bind(layoutModel))); + layoutModelMap.set(tabId, layoutModel); + return layoutModel; } export function getLayoutModelForTabById(tabId: string) { @@ -76,7 +81,7 @@ export function useDebouncedNodeInnerRect(nodeModel: NodeModel): CSSProperties { const timeout = setTimeout(() => { setInnerRect(nodeInnerRect); }, animationTimeS * 1000); - computeIfAbsent(timeoutMap, nodeModel.blockId, (_) => timeout) + timeoutMap.set(nodeModel.blockId, timeout); }, [animationTimeS] ); @@ -101,11 +106,3 @@ export function useDebouncedNodeInnerRect(nodeModel: NodeModel): CSSProperties { return innerRect; } - -function computeIfAbsent(map: Map, key: V, mappingFunction: (a: V) => F): F { - if (!map.has(key)) { - const newValue = mappingFunction(key); - map.set(key, newValue); - } - return map.get(key); -}