From dccdfdd1752ba7aeb5d02f01d8398ebe9e9a259b Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Fri, 5 Jun 2026 16:02:21 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AA=A8=EB=93=88=20undo=20redo=EC=8B=9C=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useUndoRedo.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/hooks/useUndoRedo.js b/src/hooks/useUndoRedo.js index 0472ba1d..478a483e 100644 --- a/src/hooks/useUndoRedo.js +++ b/src/hooks/useUndoRedo.js @@ -18,6 +18,7 @@ import { outerLinePointsState } from '@/store/outerLineAtom' import { selectedMenuState } from '@/store/menuAtom' import { pendingPopupState, popupState } from '@/store/popupAtom' import { POLYGON_TYPE, SAVE_KEY } from '@/common/common' +import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' const MAX_HISTORY = 3 @@ -53,7 +54,7 @@ export function isUndoRedoDrawing() { } // loadFromJSON 공통 처리 - 이벤트 일시 중단 후 복원 -function _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom) { +function _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom, setModuleStatisticsData) { // 진행 중인 복원 타이머가 있으면 취소 if (_restoreTimer) { clearTimeout(_restoreTimer) @@ -80,6 +81,10 @@ function _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAt canvas.renderAll() restoreAtomSnapshot(snapshot.atomSnapshot) + // [undo 집계 fix] 캔버스/surface.modules 복원 후 패널 배치 집계를 재계산한다. + // 집계 atom(moduleStatisticsState)은 스냅샷 대상이 아니라, 복원 시점에 다시 계산해야 한다. + if (typeof setModuleStatisticsData === 'function') setModuleStatisticsData() + if (canvas.viewportTransform) { setCanvasZoom(Number((canvas.viewportTransform[0] * 100).toFixed(0))) } @@ -141,6 +146,7 @@ export function useUndoRedo() { const [, setCanvasZoom] = useRecoilState(canvasZoomState) const setPopup = useSetRecoilState(popupState) const [pendingPopup, setPendingPopup] = useRecoilState(pendingPopupState) + const { setModuleStatisticsData } = useCircuitTrestle() // 최신 스택 값을 ref로 유지하여 클로저 stale 문제 방지 const undoStackRef = useRef(undoStack) @@ -485,8 +491,8 @@ export function useUndoRedo() { setUndoStack(newUndoStack) setRedoStack((prev) => [...prev, currentSnapshot]) - _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom) - }, [canvas, currentMenu, isDrawing, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups]) + _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom, setModuleStatisticsData) + }, [canvas, currentMenu, isDrawing, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups, setModuleStatisticsData]) const redo = useCallback(() => { // 외벽선/배치면/지붕형상 수동설정 등 그리기 진행 중에는 redo 차단 @@ -513,8 +519,8 @@ export function useUndoRedo() { setRedoStack(newRedoStack) setUndoStack((prev) => [...prev, currentSnapshot]) - _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom) - }, [canvas, currentMenu, isDrawing, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups]) + _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom, setModuleStatisticsData) + }, [canvas, currentMenu, isDrawing, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups, setModuleStatisticsData]) const clearStacks = useCallback(() => { setUndoStack([])