Skip to content

Commit

Permalink
fix: multiple undo tap for drawing, unnecessary recompositions (WPB-8…
Browse files Browse the repository at this point in the history
…810) (#3032)
  • Loading branch information
yamilmedina authored and github-actions[bot] committed May 24, 2024
1 parent 522d1cb commit 2d56c11
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import androidx.lifecycle.viewModelScope
import com.wire.android.feature.sketch.model.DrawingMotionEvent
import com.wire.android.feature.sketch.model.DrawingPathProperties
import com.wire.android.feature.sketch.model.DrawingState
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand Down Expand Up @@ -89,7 +91,7 @@ class DrawingCanvasViewModel : ViewModel() {
* Stores the initial point of the drawing.
*/
fun onStartDrawingEvent() {
state = state.copy(paths = state.paths + state.currentPath).apply {
state = state.copy(paths = (state.paths + state.currentPath).toPersistentList()).apply {
currentPath.path.moveTo(state.currentPosition.x, state.currentPosition.y)
}
}
Expand All @@ -111,7 +113,8 @@ class DrawingCanvasViewModel : ViewModel() {
strokeWidth = state.currentPath.strokeWidth
color = state.currentPath.color
drawMode = state.currentPath.drawMode
}, pathsUndone = emptyList(),
},
pathsUndone = persistentListOf(),
currentPosition = Offset.Unspecified,
drawingMotionEvent = DrawingMotionEvent.Idle
)
Expand All @@ -130,8 +133,8 @@ class DrawingCanvasViewModel : ViewModel() {
fun onUndoLastStroke() {
if (state.paths.isNotEmpty()) {
state = state.copy(
paths = state.paths.dropLast(1),
pathsUndone = state.pathsUndone + state.paths.last()
paths = state.paths.distinct().dropLast(1).toPersistentList(),
pathsUndone = (state.pathsUndone + state.paths.last()).toPersistentList()
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import androidx.compose.ui.graphics.toArgb
* Represents the current path properties [DrawingState.currentPath]
* This can be extended in the future to [strokeWidth], [drawMode] ,etc.
*/
internal class DrawingPathProperties(
internal data class DrawingPathProperties(
var path: Path = Path(),
var strokeWidth: Float = 10f,
var color: Color = Color.Black,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
*/
package com.wire.android.feature.sketch.model

import androidx.compose.runtime.Stable
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf

@Stable
internal data class DrawingState(
val paths: List<DrawingPathProperties> = listOf(),
val pathsUndone: List<DrawingPathProperties> = listOf(),
val paths: ImmutableList<DrawingPathProperties> = persistentListOf(),
val pathsUndone: ImmutableList<DrawingPathProperties> = persistentListOf(),
val drawingMotionEvent: DrawingMotionEvent = DrawingMotionEvent.Idle,
val currentPath: DrawingPathProperties = DrawingPathProperties(),
val currentPosition: Offset = Offset.Unspecified,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class DrawingCanvasViewModelTest {
assertEquals(viewModel.state.currentPosition, Offset.Unspecified)

// when
draw(viewModel)
draw(viewModel, MOVED_OFFSET)

// then
with(viewModel.state) {
Expand All @@ -79,6 +79,28 @@ class DrawingCanvasViewModelTest {
}
}

@Test
fun givenDrawingEventPersisted_WhenCallingTheUndoAction_ThenUpdateShouldNotHaveDuplicatedPathAndRemoveLast() = runTest {
// given
val (_, viewModel) = Arrangement().arrange()
assertEquals(viewModel.state.currentPosition, Offset.Unspecified)

// when - then
draw(viewModel, MOVED_OFFSET)
assertEquals(1, viewModel.state.paths.size)
assertEquals(0, viewModel.state.pathsUndone.size)

// repeated path
draw(viewModel, MOVED_OFFSET)
assertEquals(2, viewModel.state.paths.size)
assertEquals(0, viewModel.state.pathsUndone.size)

// then
viewModel.onUndoLastStroke()
assertEquals(0, viewModel.state.paths.size)
assertEquals(1, viewModel.state.pathsUndone.size)
}

@Test
fun givenStopDrawingEvent_WhenCallingTheAction_ThenUpdateTheStateWithTheFinalPathPosition() = runTest {
// given
Expand Down Expand Up @@ -139,16 +161,16 @@ class DrawingCanvasViewModelTest {
}
}

private fun stopDrawing(viewModel: DrawingCanvasViewModel) = with(viewModel) {
draw(viewModel)
private fun stopDrawing(viewModel: DrawingCanvasViewModel, movedOffset: Offset = MOVED_OFFSET) = with(viewModel) {
draw(viewModel, movedOffset)
onStopDrawing()
onStopDrawingEvent()
}

// simulates the drawing of strokes
private fun draw(viewModel: DrawingCanvasViewModel) = with(viewModel) {
private fun draw(viewModel: DrawingCanvasViewModel, movedOffset: Offset = MOVED_OFFSET) = with(viewModel) {
startDrawing(viewModel)
onDraw(MOVED_OFFSET)
onDraw(movedOffset)
onDrawEvent()
}

Expand Down

0 comments on commit 2d56c11

Please sign in to comment.