redo undo 작업중

This commit is contained in:
hyojun.choi 2026-04-01 15:54:55 +09:00
parent c7238b2e27
commit d68f92c5d5
8 changed files with 37 additions and 30 deletions

View File

@ -36,7 +36,12 @@ import {
import { sessionStore } from '@/store/commonAtom'
import { outerLinePointsState } from '@/store/outerLineAtom'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import { addedRoofsState, basicSettingState, selectedRoofMaterialSelector, settingModalFirstOptionsState } from '@/store/settingAtom'
import {
addedRoofsState,
basicSettingState,
selectedRoofMaterialSelector,
settingModalFirstOptionsState,
} from '@/store/settingAtom'
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
import { commonUtilsState } from '@/store/commonUtilsAtom'
import { menusState } from '@/store/menuAtom'
@ -572,23 +577,13 @@ export default function CanvasMenu(props) {
{!['estimate', 'simulation'].some((num) => num === selectedMenu) && (
<>
<div className="undo-redo-wrap">
<button
className={`undo-btn ${!canUndo ? 'disabled' : ''}`}
onClick={undo}
disabled={!canUndo}
title="Undo (Ctrl+Z)"
>
<button className={`undo-btn ${!canUndo ? 'disabled' : ''}`} onClick={undo} disabled={!canUndo} title="Undo">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M3 10h10c4.42 0 8 3.58 8 8v1" />
<polyline points="7 14 3 10 7 6" />
</svg>
</button>
<button
className={`redo-btn ${!canRedo ? 'disabled' : ''}`}
onClick={redo}
disabled={!canRedo}
title="Redo (Ctrl+Shift+Z)"
>
<button className={`redo-btn ${!canRedo ? 'disabled' : ''}`} onClick={redo} disabled={!canRedo} title="Redo">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M21 10H11C6.58 10 3 13.58 3 18v1" />
<polyline points="17 14 21 10 17 6" />

View File

@ -11,6 +11,7 @@ import { useModuleSelection } from '@/hooks/module/useModuleSelection'
import { useOrientation } from '@/hooks/module/useOrientation'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import { useUndoRedo } from '@/hooks/useUndoRedo'
import {
canvasState,
checkedModuleState,
@ -32,6 +33,7 @@ import Trestle from './step/Trestle'
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const { clearStacks } = useUndoRedo()
const [tabNum, setTabNum] = useState(1)
const orientationRef = useRef(null)
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
@ -84,6 +86,11 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
useModuleBasicSetting(tabNum)
const { updateObjectDate } = useMasterController()
// / undo/redo
useEffect(() => {
clearStacks()
}, [])
useEffect(() => {
const moduleTabNum = basicSetting.roofSizeSet != 3 ? 3 : 2

View File

@ -18,6 +18,7 @@ import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedM
import { v4 as uuidv4 } from 'uuid'
import { useEstimate } from '@/hooks/useEstimate'
import { useUndoRedo } from '@/hooks/useUndoRedo'
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
import { useImgLoader } from '@/hooks/floorPlan/useImgLoader'
import { QcastContext } from '@/app/QcastProvider'
@ -34,6 +35,7 @@ export default function CircuitTrestleSetting({ id }) {
const { apply, setViewCircuitNumberTexts, getEstimateData, clear: clearTrestle, setAllModuleSurfaceIsComplete } = useTrestle()
const { swalFire } = useSwal()
const { saveEstimate } = useEstimate()
const { clearStacks } = useUndoRedo()
const canvas = useRecoilValue(canvasState)
const setCurrentMenu = useSetRecoilState(currentMenuState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
@ -711,6 +713,7 @@ export default function CircuitTrestleSetting({ id }) {
setIsGlobalLoading(false)
}
clearStacks()
// removeNotAllocationModules()
}

View File

@ -106,7 +106,6 @@ export function useModuleBasicSetting(tabNum) {
}
} else {
//육지붕 일경우에는 바로 배치면 설치LL
saveSnapshot()
canvas
.getObjects()
.filter((roof) => roof.name === POLYGON_TYPE.ROOF)
@ -120,7 +119,6 @@ export function useModuleBasicSetting(tabNum) {
//가대 상세 데이터 들어오면 실행
useEffect(() => {
if (trestleDetailList.length > 0) {
saveSnapshot()
let rowColArray = []
//지붕을 가져옴
canvas

View File

@ -13,7 +13,6 @@ import { usePopup } from '@/hooks/usePopup'
import { calculateAngle, isSamePoint } from '@/util/qpolygon-utils'
import { POLYGON_TYPE } from '@/common/common'
import { useMessage } from '../useMessage'
import { useUndoRedo } from '@/hooks/useUndoRedo'
import {
auxiliaryLineAngle1State,
auxiliaryLineAngle2State,
@ -37,7 +36,6 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
const { getAdsorptionPoints } = useAdsorptionPoint()
const { closePopup } = usePopup()
const { getMessage } = useMessage()
const { saveSnapshot } = useUndoRedo()
const adsorptionRange = useRecoilValue(adsorptionRangeState)
@ -654,8 +652,6 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
return
}
saveSnapshot()
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
/*const allLines = [...auxiliaryLines]
@ -917,7 +913,6 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
if (!confirm(getMessage('want.to.complete.auxiliary.creation'))) {
return
}
saveSnapshot()
// cutAuxiliary()

View File

@ -26,7 +26,6 @@ import { useSurfaceShapeBatch } from './useSurfaceShapeBatch'
import { roofDisplaySelector } from '@/store/settingAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
import { useObject } from '@/hooks/useObject'
import { useUndoRedo } from '@/hooks/useUndoRedo'
// 배치면 그리기
export function usePlacementShapeDrawing(id) {
@ -75,7 +74,6 @@ export function usePlacementShapeDrawing(id) {
const isFix = useRef(false)
const { closePopup, addPopup } = usePopup()
const { saveSnapshot } = useUndoRedo()
const globalPitch = useRecoilValue(globalPitchState)
@ -132,7 +130,6 @@ export function usePlacementShapeDrawing(id) {
let pointer = getIntersectMousePoint(e)
if (points.length === 0) {
saveSnapshot()
setPoints((prev) => [...prev, pointer])
} else {
const lastPoint = points[points.length - 1]

View File

@ -304,7 +304,7 @@ export function useCanvasEvent() {
case 'Escape':
break
case 'z':
/*case 'z':
if (!e.ctrlKey && !e.metaKey) {
return
}
@ -313,7 +313,7 @@ export function useCanvasEvent() {
} else {
undo()
}
break
break*/
default:
return // 키 이벤트를 처리하지 않는다면 종료합니다.

View File

@ -18,7 +18,7 @@ import { selectedMenuState } from '@/store/menuAtom'
import { popupState } from '@/store/popupAtom'
import { POLYGON_TYPE, SAVE_KEY } from '@/common/common'
const MAX_HISTORY = 20
const MAX_HISTORY = 3
// 모든 useUndoRedo 인스턴스가 공유하는 복원 플래그
// useRef는 인스턴스마다 독립적이므로, 모듈 레벨 변수로 전환
@ -318,7 +318,6 @@ export function useUndoRedo() {
if (!canvas || currentUndoStack.length === 0 || _isRestoring) return
_isRestoring = true
closeAllPopups()
const currentCanvasJSON = getCanvasSnapshot()
const currentAtomSnapshot = getAtomSnapshot()
@ -330,18 +329,21 @@ export function useUndoRedo() {
const newUndoStack = [...currentUndoStack]
const snapshot = newUndoStack.pop()
if (snapshot.atomSnapshot?.currentMenu !== currentMenu) {
closeAllPopups()
}
setUndoStack(newUndoStack)
setRedoStack((prev) => [...prev, currentSnapshot])
_restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom)
}, [canvas, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups])
}, [canvas, currentMenu, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups])
const redo = useCallback(() => {
const currentRedoStack = redoStackRef.current
if (!canvas || currentRedoStack.length === 0 || _isRestoring) return
_isRestoring = true
closeAllPopups()
const currentCanvasJSON = getCanvasSnapshot()
const currentAtomSnapshot = getAtomSnapshot()
@ -353,16 +355,26 @@ export function useUndoRedo() {
const newRedoStack = [...currentRedoStack]
const snapshot = newRedoStack.pop()
if (snapshot.atomSnapshot?.currentMenu !== currentMenu) {
closeAllPopups()
}
setRedoStack(newRedoStack)
setUndoStack((prev) => [...prev, currentSnapshot])
_restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAtoms, setCanvasZoom)
}, [canvas, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups])
}, [canvas, currentMenu, getCanvasSnapshot, getAtomSnapshot, restoreAtomSnapshot, rebuildCanvasAtoms, closeAllPopups])
const clearStacks = useCallback(() => {
setUndoStack([])
setRedoStack([])
}, [])
return {
saveSnapshot,
undo,
redo,
clearStacks,
canUndo: undoStack.length > 0,
canRedo: redoStack.length > 0,
}