import { Shape, Point } from 'remixed/model/l33t'; import { Command, CommandContext } from '.'; interface DraggedPoint { shapeId: string; pointIndex: number; oldPosition: Point; newPosition: Point; } export class DragPointCommand implements Command { private draggedPoints: DraggedPoint[] = []; constructor( private context: CommandContext, private selectedPoint: { shapeId: string; pointIndex: number }, private currentShape: Shape, private dx: number, private dy: number, ) {} execute() { const { shapes, setShapes, setCurrentShape } = this.context; const newPoints = this.currentShape.points.map((p, index) => { if (index === this.selectedPoint.pointIndex || (this.currentShape.type === 'polygon' && this.currentShape.isClosed && ((index === 0 && this.selectedPoint.pointIndex === this.currentShape.points.length - 1) || (index === this.currentShape.points.length - 1 && this.selectedPoint.pointIndex === 0)))) { this.draggedPoints.push({ shapeId: this.currentShape.id, pointIndex: index, oldPosition: { ...p }, newPosition: { x: p.x + this.dx, y: p.y + this.dy } }); return { x: p.x + this.dx, y: p.y + this.dy }; } return p; }); const updatedShape = { ...this.currentShape, points: newPoints }; setShapes(prevShapes => ({ ...prevShapes, [this.currentShape.id]: updatedShape })); setCurrentShape(prevShape => prevShape && prevShape.id === this.currentShape.id ? updatedShape : prevShape ); } undo() { const { shapes, setShapes, setCurrentShape } = this.context; const updatedShapes = { ...shapes }; this.draggedPoints.forEach(dp => { if (updatedShapes[dp.shapeId]) { updatedShapes[dp.shapeId] = { ...updatedShapes[dp.shapeId], points: updatedShapes[dp.shapeId].points.map((p, index) => index === dp.pointIndex ? dp.oldPosition : p ) }; } }); setShapes(updatedShapes); setCurrentShape(prevShape => { if (!prevShape) return null; const draggedPointsForShape = this.draggedPoints.filter(dp => dp.shapeId === prevShape.id); if (draggedPointsForShape.length > 0) { return { ...prevShape, points: prevShape.points.map((p, index) => { const draggedPoint = draggedPointsForShape.find(dp => dp.pointIndex === index); return draggedPoint ? draggedPoint.oldPosition : p; }) }; } return prevShape; }); } }