Implement Phase 6: undo/redo with command pattern
- UndoableAction interface with AddStrokeAction and DeleteStrokeAction - UndoManager: undo/redo stacks (depth 50), canUndo/canRedo StateFlows - EditorViewModel: stroke operations routed through UndoManager, visual callbacks sync canvas view without full DB reload - Toolbar: undo/redo buttons with enabled state - 9 unit tests for UndoManager Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package net.metacircular.engpad.undo
|
||||
|
||||
import net.metacircular.engpad.data.model.Stroke
|
||||
import net.metacircular.engpad.data.repository.PageRepository
|
||||
|
||||
class AddStrokeAction(
|
||||
private val stroke: Stroke,
|
||||
private val repository: PageRepository,
|
||||
private val onExecute: (Stroke) -> Unit,
|
||||
private val onUndo: (Long) -> Unit,
|
||||
) : UndoableAction {
|
||||
override val description = "Add stroke"
|
||||
private var insertedId: Long = 0
|
||||
|
||||
override suspend fun execute() {
|
||||
insertedId = repository.addStroke(stroke)
|
||||
onExecute(stroke.copy(id = insertedId))
|
||||
}
|
||||
|
||||
override suspend fun undo() {
|
||||
repository.deleteStroke(insertedId)
|
||||
onUndo(insertedId)
|
||||
}
|
||||
}
|
||||
|
||||
class DeleteStrokeAction(
|
||||
private val stroke: Stroke,
|
||||
private val repository: PageRepository,
|
||||
private val onExecute: (Long) -> Unit,
|
||||
private val onUndo: (Stroke) -> Unit,
|
||||
) : UndoableAction {
|
||||
override val description = "Delete stroke"
|
||||
|
||||
override suspend fun execute() {
|
||||
repository.deleteStroke(stroke.id)
|
||||
onExecute(stroke.id)
|
||||
}
|
||||
|
||||
override suspend fun undo() {
|
||||
val id = repository.addStroke(stroke)
|
||||
onUndo(stroke.copy(id = id))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user