- 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>
44 lines
1.2 KiB
Kotlin
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))
|
|
}
|
|
}
|