Files
eng-pad/app/src/main/kotlin/net/metacircular/engpad/undo/StrokeActions.kt
Kyle Isom 5eeedff464 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>
2026-03-24 14:40:24 -07:00

44 lines
1.2 KiB
Kotlin

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))
}
}