[#24] Add long press to delete functionality.
Some checks are pending
continuous-integration/drone/push Build is running
Some checks are pending
continuous-integration/drone/push Build is running
Reformat code. closes #24
This commit is contained in:
@@ -1,18 +1,13 @@
|
||||
package me.zobrist.tichucounter
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.room.Room
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.withContext
|
||||
import me.zobrist.tichucounter.data.AppDatabase
|
||||
import me.zobrist.tichucounter.data.GameDao
|
||||
import me.zobrist.tichucounter.data.GameWithScores
|
||||
import me.zobrist.tichucounter.data.RoundDao
|
||||
import me.zobrist.tichucounter.repository.GameRepository
|
||||
import org.junit.After
|
||||
@@ -39,7 +34,8 @@ class RepositoryInstrumentedTest {
|
||||
fun createDb() {
|
||||
val context = ApplicationProvider.getApplicationContext<Context>()
|
||||
db = Room.inMemoryDatabaseBuilder(
|
||||
context, AppDatabase::class.java).build()
|
||||
context, AppDatabase::class.java
|
||||
).build()
|
||||
roundDao = db.roundDao()
|
||||
gameDao = db.gameDao()
|
||||
|
||||
@@ -70,14 +66,14 @@ class RepositoryInstrumentedTest {
|
||||
repository.getActiveGameFlow().take(1).collect {
|
||||
}
|
||||
|
||||
repository.updateActiveTeamName(nameA ="aaa")
|
||||
repository.updateActiveTeamName(nameA = "aaa")
|
||||
|
||||
repository.getActiveGameFlow().take(1).collect {
|
||||
assertEquals("aaa", it.game.nameA)
|
||||
assertEquals("TeamB", it.game.nameB)
|
||||
}
|
||||
|
||||
repository.updateActiveTeamName(nameB ="bbb")
|
||||
repository.updateActiveTeamName(nameB = "bbb")
|
||||
|
||||
repository.getActiveGameFlow().take(1).collect {
|
||||
assertEquals("aaa", it.game.nameA)
|
||||
@@ -88,7 +84,6 @@ class RepositoryInstrumentedTest {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Throws(Exception::class)
|
||||
fun newGame() = runTest {
|
||||
@@ -107,7 +102,7 @@ class RepositoryInstrumentedTest {
|
||||
assertEquals(6, it.count())
|
||||
|
||||
var uid: Long = 1
|
||||
it.forEach {game ->
|
||||
it.forEach { game ->
|
||||
assertEquals(uid++, game.game.uid)
|
||||
assertEquals(0, game.rounds.count())
|
||||
}
|
||||
@@ -157,12 +152,12 @@ class RepositoryInstrumentedTest {
|
||||
repository.newGame()
|
||||
|
||||
|
||||
repository.addRoundToActiveGame(1,1)
|
||||
repository.addRoundToActiveGame(2,2)
|
||||
repository.addRoundToActiveGame(3,3)
|
||||
repository.addRoundToActiveGame(4,4)
|
||||
repository.addRoundToActiveGame(5,5)
|
||||
repository.addRoundToActiveGame(6,6)
|
||||
repository.addRoundToActiveGame(1, 1)
|
||||
repository.addRoundToActiveGame(2, 2)
|
||||
repository.addRoundToActiveGame(3, 3)
|
||||
repository.addRoundToActiveGame(4, 4)
|
||||
repository.addRoundToActiveGame(5, 5)
|
||||
repository.addRoundToActiveGame(6, 6)
|
||||
|
||||
|
||||
repository.getAllWithRoundFlow().take(1).collect() { it ->
|
||||
@@ -187,12 +182,12 @@ class RepositoryInstrumentedTest {
|
||||
|
||||
assertNull(repository.getLastRound())
|
||||
|
||||
repository.addRoundToActiveGame(1,1)
|
||||
repository.addRoundToActiveGame(2,2)
|
||||
repository.addRoundToActiveGame(3,3)
|
||||
repository.addRoundToActiveGame(4,4)
|
||||
repository.addRoundToActiveGame(5,5)
|
||||
repository.addRoundToActiveGame(6,6)
|
||||
repository.addRoundToActiveGame(1, 1)
|
||||
repository.addRoundToActiveGame(2, 2)
|
||||
repository.addRoundToActiveGame(3, 3)
|
||||
repository.addRoundToActiveGame(4, 4)
|
||||
repository.addRoundToActiveGame(5, 5)
|
||||
repository.addRoundToActiveGame(6, 6)
|
||||
|
||||
var lastRound = repository.getLastRound()
|
||||
assertEquals(6, lastRound?.scoreA)
|
||||
@@ -225,12 +220,12 @@ class RepositoryInstrumentedTest {
|
||||
|
||||
for (i in 1..6) {
|
||||
repository.newGame()
|
||||
repository.addRoundToActiveGame(1,1)
|
||||
repository.addRoundToActiveGame(2,2)
|
||||
repository.addRoundToActiveGame(3,3)
|
||||
repository.addRoundToActiveGame(4,4)
|
||||
repository.addRoundToActiveGame(5,5)
|
||||
repository.addRoundToActiveGame(6,6)
|
||||
repository.addRoundToActiveGame(1, 1)
|
||||
repository.addRoundToActiveGame(2, 2)
|
||||
repository.addRoundToActiveGame(3, 3)
|
||||
repository.addRoundToActiveGame(4, 4)
|
||||
repository.addRoundToActiveGame(5, 5)
|
||||
repository.addRoundToActiveGame(6, 6)
|
||||
}
|
||||
assertEquals(6 * 6, roundDao.getAll().count())
|
||||
|
||||
@@ -253,12 +248,12 @@ class RepositoryInstrumentedTest {
|
||||
|
||||
for (i in 1..6) {
|
||||
repository.newGame()
|
||||
repository.addRoundToActiveGame(1,1)
|
||||
repository.addRoundToActiveGame(2,2)
|
||||
repository.addRoundToActiveGame(3,3)
|
||||
repository.addRoundToActiveGame(4,4)
|
||||
repository.addRoundToActiveGame(5,5)
|
||||
repository.addRoundToActiveGame(6,6)
|
||||
repository.addRoundToActiveGame(1, 1)
|
||||
repository.addRoundToActiveGame(2, 2)
|
||||
repository.addRoundToActiveGame(3, 3)
|
||||
repository.addRoundToActiveGame(4, 4)
|
||||
repository.addRoundToActiveGame(5, 5)
|
||||
repository.addRoundToActiveGame(6, 6)
|
||||
}
|
||||
|
||||
// Non existing Id
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package me.zobrist.tichucounter.data
|
||||
|
||||
import androidx.room.*
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Update
|
||||
|
||||
@Dao
|
||||
interface DaoBase<T> {
|
||||
|
||||
@@ -5,7 +5,6 @@ import androidx.room.Entity
|
||||
import androidx.room.Relation
|
||||
import me.zobrist.tichucounter.data.entity.Game
|
||||
import me.zobrist.tichucounter.data.entity.Round
|
||||
import java.util.*
|
||||
|
||||
@Entity
|
||||
data class GameWithScores(
|
||||
|
||||
@@ -5,7 +5,7 @@ import androidx.navigation.*
|
||||
import androidx.navigation.compose.composable
|
||||
|
||||
fun NavController.navigate(route: Route) {
|
||||
this.navigate(route.name){
|
||||
this.navigate(route.name) {
|
||||
// Pop up to the start destination of the graph to
|
||||
// avoid building up a large stack of destinations
|
||||
// on the back stack as users select items
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
package me.zobrist.tichucounter.repository
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import me.zobrist.tichucounter.data.GameDao
|
||||
import me.zobrist.tichucounter.data.GameWithScores
|
||||
import me.zobrist.tichucounter.data.RoundDao
|
||||
@@ -41,7 +47,7 @@ class GameRepository @Inject constructor(
|
||||
val newA = nameA ?: activeGame.nameA
|
||||
val newB = nameB ?: activeGame.nameB
|
||||
|
||||
if(newA == activeGame.nameA && newB == activeGame.nameB) {
|
||||
if (newA == activeGame.nameA && newB == activeGame.nameB) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -137,9 +137,6 @@ internal class PreviewViewModel : ICounterViewModel {
|
||||
override fun addSub100Clicked(toAdd: Int) {
|
||||
}
|
||||
|
||||
override fun deleteClicked() {
|
||||
}
|
||||
|
||||
override fun updateNameA(value: String) {
|
||||
}
|
||||
|
||||
@@ -161,4 +158,7 @@ internal class PreviewViewModel : ICounterViewModel {
|
||||
override fun showKeyboard() {
|
||||
}
|
||||
|
||||
override fun deleteState(pressed: Boolean) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import me.zobrist.tichucounter.data.entity.Round
|
||||
import me.zobrist.tichucounter.domain.Tichu
|
||||
@@ -38,12 +40,12 @@ interface IKeyBoardViewModel {
|
||||
fun digitClicked(digit: String)
|
||||
fun negateClicked()
|
||||
fun addSub100Clicked(toAdd: Int)
|
||||
fun deleteClicked()
|
||||
fun updateFocusStateA(state: Boolean)
|
||||
fun updateFocusStateB(state: Boolean)
|
||||
fun swapInputScores()
|
||||
fun hideKeyboard()
|
||||
fun showKeyboard()
|
||||
fun deleteState(pressed: Boolean)
|
||||
|
||||
}
|
||||
|
||||
@@ -138,6 +140,10 @@ class CounterViewModel @Inject constructor(
|
||||
|
||||
private var lastFocused = Focused.TEAM_A
|
||||
|
||||
private var deletePressed = false
|
||||
|
||||
private var deleteJob: Job? = null
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
gameRepository.getActiveGameFlow().collect {
|
||||
@@ -204,8 +210,7 @@ class CounterViewModel @Inject constructor(
|
||||
focusLastInput()
|
||||
|
||||
|
||||
if(activeValue.digitCount() >= 5)
|
||||
{
|
||||
if (activeValue.digitCount() >= 5) {
|
||||
// 5 digits is enough
|
||||
return
|
||||
}
|
||||
@@ -214,8 +219,7 @@ class CounterViewModel @Inject constructor(
|
||||
|
||||
try {
|
||||
activeValue = newValue.toInt().toString()
|
||||
} catch (_: NumberFormatException)
|
||||
{
|
||||
} catch (_: NumberFormatException) {
|
||||
}
|
||||
|
||||
updateOtherScore()
|
||||
@@ -250,14 +254,6 @@ class CounterViewModel @Inject constructor(
|
||||
updateSubmitButton()
|
||||
}
|
||||
|
||||
override fun deleteClicked() {
|
||||
if (activeValue != "") {
|
||||
activeValue = activeValue.dropLast(1)
|
||||
}
|
||||
updateOtherScore()
|
||||
updateSubmitButton()
|
||||
}
|
||||
|
||||
override fun updateNameA(value: String) {
|
||||
viewModelScope.launch {
|
||||
gameRepository.updateActiveTeamName(nameA = value)
|
||||
@@ -297,4 +293,35 @@ class CounterViewModel @Inject constructor(
|
||||
override fun showKeyboard() {
|
||||
keyboardHidden = false
|
||||
}
|
||||
|
||||
override fun deleteState(pressed: Boolean) {
|
||||
deletePressed = pressed
|
||||
|
||||
if (deletePressed) {
|
||||
if (deleteJob?.isActive != true) {
|
||||
deleteJob = deleteRepeatedlyUntilRelease()
|
||||
}
|
||||
} else {
|
||||
deleteJob?.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private fun deleteLastDigitActive() {
|
||||
if (activeValue != "") {
|
||||
activeValue = activeValue.dropLast(1)
|
||||
}
|
||||
updateOtherScore()
|
||||
updateSubmitButton()
|
||||
}
|
||||
|
||||
private fun deleteRepeatedlyUntilRelease(): Job {
|
||||
return viewModelScope.launch {
|
||||
deleteLastDigitActive()
|
||||
delay(500)
|
||||
while (deletePressed) {
|
||||
deleteLastDigitActive()
|
||||
delay(100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package me.zobrist.tichucounter.ui.counter
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.collectIsPressedAsState
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Backspace
|
||||
@@ -37,11 +39,11 @@ fun KeyBoardView(viewModel: IKeyBoardViewModel) {
|
||||
{ viewModel.updateFocusStateB(it) },
|
||||
{ viewModel.digitClicked(it) },
|
||||
{ viewModel.addSub100Clicked(it) },
|
||||
{ viewModel.deleteClicked() },
|
||||
{ viewModel.negateClicked() },
|
||||
{ viewModel.submitClicked() },
|
||||
{ viewModel.hideKeyboard() },
|
||||
{ viewModel.swapInputScores() }
|
||||
{ viewModel.swapInputScores() },
|
||||
{ viewModel.deleteState(it) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,11 +60,11 @@ fun KeyboardView(
|
||||
updateFocusStateB: (Boolean) -> Unit,
|
||||
digitClicked: (String) -> Unit,
|
||||
addSub100Clicked: (Int) -> Unit,
|
||||
deleteClicked: () -> Unit,
|
||||
negateClicked: () -> Unit,
|
||||
submitClicked: () -> Unit,
|
||||
hideKeyboardClicked: () -> Unit,
|
||||
onSwapClicked: () -> Unit
|
||||
onSwapClicked: () -> Unit,
|
||||
deleteButtonPressedState: (Boolean) -> Unit
|
||||
) {
|
||||
Column {
|
||||
Row(Modifier.height(IntrinsicSize.Max)) {
|
||||
@@ -164,9 +166,16 @@ fun KeyboardView(
|
||||
}
|
||||
}
|
||||
Column(Modifier.weight(1f)) {
|
||||
KeyboardIconButton(Icons.Outlined.Backspace) {
|
||||
deleteClicked()
|
||||
}
|
||||
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val deletePressed by interactionSource.collectIsPressedAsState()
|
||||
|
||||
deleteButtonPressedState(deletePressed)
|
||||
|
||||
KeyboardIconButton(
|
||||
icon = Icons.Outlined.Backspace,
|
||||
interactionSource = interactionSource
|
||||
) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +228,12 @@ fun KeyboardTextButton(text: String, onClicked: () -> Unit) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun KeyboardIconButton(icon: ImageVector, enabled: Boolean = true, onClicked: () -> Unit) {
|
||||
fun KeyboardIconButton(
|
||||
icon: ImageVector,
|
||||
enabled: Boolean = true,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
onClicked: () -> Unit
|
||||
) {
|
||||
|
||||
ElevatedButton(
|
||||
onClick = { onClicked() },
|
||||
@@ -228,6 +242,7 @@ fun KeyboardIconButton(icon: ImageVector, enabled: Boolean = true, onClicked: ()
|
||||
.height(50.dp)
|
||||
.padding(2.dp),
|
||||
enabled = enabled,
|
||||
interactionSource = interactionSource
|
||||
) {
|
||||
Icon(
|
||||
icon,
|
||||
@@ -319,11 +334,11 @@ fun KeyboardViewPreview() {
|
||||
updateFocusStateB = {},
|
||||
digitClicked = {},
|
||||
addSub100Clicked = {},
|
||||
deleteClicked = {},
|
||||
negateClicked = {},
|
||||
submitClicked = {},
|
||||
hideKeyboardClicked = {},
|
||||
onSwapClicked = {})
|
||||
onSwapClicked = {},
|
||||
deleteButtonPressedState = {})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package me.zobrist.tichucounter
|
||||
|
||||
import me.zobrist.tichucounter.domain.digitCount
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user