feat: implement MoveCommand for undoable layer movement
Critical Fix - Move Tool Undo/Redo: - Create MoveCommand class to track layer position changes - Capture initial and final positions during move operation - Only add to history if position actually changed - Real-time visual feedback during drag (via updateLayer) - Single undo point per move operation (not per pixel) Command Pattern: - MoveCommand extends BaseCommand - Implements execute() and undo() methods - captureAfterPosition() called on pointer up - hasChanged() prevents no-op entries in history Files: - core/commands/move-command.ts - New command class - tools/move-tool.ts - Updated to use MoveCommand - core/commands/index.ts - Export MoveCommand This fixes the critical issue where moving layers had no undo support. Users can now undo/redo layer movements as expected. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
export * from './base-command';
|
||||
export * from './layer-commands';
|
||||
export * from './draw-command';
|
||||
export * from './move-command';
|
||||
|
||||
60
core/commands/move-command.ts
Normal file
60
core/commands/move-command.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { BaseCommand } from './base-command';
|
||||
import { useLayerStore } from '@/store/layer-store';
|
||||
|
||||
/**
|
||||
* Command for moving a layer
|
||||
* Captures start and end positions for undo/redo
|
||||
*/
|
||||
export class MoveCommand extends BaseCommand {
|
||||
private layerId: string;
|
||||
private beforePosition: { x: number; y: number };
|
||||
private afterPosition: { x: number; y: number } | null = null;
|
||||
|
||||
constructor(layerId: string, beforePosition: { x: number; y: number }) {
|
||||
super('Move Layer');
|
||||
this.layerId = layerId;
|
||||
this.beforePosition = beforePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture the final position after the move is complete
|
||||
*/
|
||||
captureAfterPosition(x: number, y: number): void {
|
||||
this.afterPosition = { x, y };
|
||||
}
|
||||
|
||||
execute(): void {
|
||||
if (!this.afterPosition) {
|
||||
// No-op on first execute (position already set during drag)
|
||||
return;
|
||||
}
|
||||
|
||||
// Restore after position (for redo)
|
||||
const { updateLayer } = useLayerStore.getState();
|
||||
updateLayer(this.layerId, {
|
||||
x: this.afterPosition.x,
|
||||
y: this.afterPosition.y,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
const { updateLayer } = useLayerStore.getState();
|
||||
updateLayer(this.layerId, {
|
||||
x: this.beforePosition.x,
|
||||
y: this.beforePosition.y,
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this move actually changed position
|
||||
*/
|
||||
hasChanged(): boolean {
|
||||
if (!this.afterPosition) return false;
|
||||
return (
|
||||
this.beforePosition.x !== this.afterPosition.x ||
|
||||
this.beforePosition.y !== this.afterPosition.y
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user