diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/counter/Keyboard.kt b/app/src/main/java/me/zobrist/tichucounter/ui/counter/Keyboard.kt index 182917d..21eef59 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/counter/Keyboard.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/counter/Keyboard.kt @@ -13,18 +13,13 @@ import androidx.compose.material.icons.outlined.Check import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.* import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import dagger.hilt.android.AndroidEntryPoint @@ -55,50 +50,39 @@ class Keyboard : Fragment() { } @OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class) - @Preview @Composable - fun KeyboardView(viewModel: IKeyboardViewModel = DefaultViewModel()) { + fun KeyboardView(viewModel: KeyboardViewModel) { val keyboardController = LocalSoftwareKeyboardController.current Column { Row { - CompositionLocalProvider( - LocalTextToolbar provides EmptyTextToolbar - ) { - TextField( - value = viewModel.scoreA.value, - onValueChange = { }, - placeholder = { Text("0") }, - singleLine = true, - modifier = Modifier - .onFocusChanged { - keyboardController?.hide() - viewModel.isAFocused.value = it.isFocused - } - .focusRequester(viewModel.requestFocusA.value) - .weight(1f), - colors = TextFieldDefaults.textFieldColors( - cursorColor = Color.Transparent, - errorCursorColor = Color.Transparent - ) - ) - TextField( - value = viewModel.scoreB.value, - onValueChange = { }, - placeholder = { Text("0") }, - singleLine = true, - modifier = Modifier - .onFocusChanged { - keyboardController?.hide() - viewModel.isBFocused.value = it.isFocused - } - .weight(1f), - colors = TextFieldDefaults.textFieldColors( - cursorColor = Color.Transparent, - errorCursorColor = Color.Transparent - ) - ) - } + TextField( + value = viewModel.scoreA, + onValueChange = { }, + placeholder = { Text("0") }, + singleLine = true, + readOnly = true, + modifier = Modifier + .onFocusChanged { + keyboardController?.hide() + viewModel.isAFocused = it.isFocused + } + .focusRequester(viewModel.requestFocusA) + .weight(1f), + ) + TextField( + value = viewModel.scoreB, + onValueChange = { }, + placeholder = { Text("0") }, + singleLine = true, + readOnly = true, + modifier = Modifier + .onFocusChanged { + keyboardController?.hide() + viewModel.isBFocused = it.isFocused + } + .weight(1f) + ) } Row { @@ -169,54 +153,9 @@ class Keyboard : Fragment() { IconButton( onClick = { viewModel.submitScore() }, modifier = Modifier.weight(1F), - enabled = viewModel.enableSubmit.value + enabled = viewModel.enableSubmit ) { Icon(Icons.Outlined.Check, stringResource(R.string.submit)) } } } } - - object EmptyTextToolbar : TextToolbar { - override val status: TextToolbarStatus = TextToolbarStatus.Hidden - - override fun hide() {} - - override fun showMenu( - rect: Rect, - onCopyRequested: (() -> Unit)?, - onPasteRequested: (() -> Unit)?, - onCutRequested: (() -> Unit)?, - onSelectAllRequested: (() -> Unit)?, - ) { - } - } - - internal class DefaultViewModel : IKeyboardViewModel { - override var scoreA: MutableState = mutableStateOf("") - override var scoreB: MutableState = mutableStateOf("") - override var enableSubmit = mutableStateOf(false) - override var isAFocused = mutableStateOf(false) - override var isBFocused = mutableStateOf(false) - override var requestFocusA = mutableStateOf(FocusRequester()) - - override fun appendToFocusedScore(toAppend: String) { - TODO("Not yet implemented") - } - - override fun negateActiveInput() { - TODO("Not yet implemented") - } - - override fun addToActiveInput(toAdd: Int) { - TODO("Not yet implemented") - } - - override fun removeLastCharFromActive() { - TODO("Not yet implemented") - } - - override fun submitScore() { - TODO("Not yet implemented") - } - } - } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/counter/KeyboardViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/ui/counter/KeyboardViewModel.kt index 90ad766..59808a2 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/counter/KeyboardViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/counter/KeyboardViewModel.kt @@ -1,7 +1,8 @@ package me.zobrist.tichucounter.ui.counter -import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.compose.ui.focus.FocusRequester import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -11,127 +12,137 @@ import me.zobrist.tichucounter.domain.Tichu import me.zobrist.tichucounter.repository.GameRepository import javax.inject.Inject -interface IKeyboardViewModel { - var scoreA: MutableState - var scoreB: MutableState - var enableSubmit: MutableState - var isAFocused: MutableState - var isBFocused: MutableState - var requestFocusA: MutableState - - fun appendToFocusedScore(toAppend: String) - - fun negateActiveInput() - - fun addToActiveInput(toAdd: Int) - - fun removeLastCharFromActive() - - fun submitScore() -} - @HiltViewModel class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepository) : - ViewModel(), IKeyboardViewModel { - override var scoreA = mutableStateOf("") - override var scoreB = mutableStateOf("") - override var enableSubmit = mutableStateOf(false) - override var isAFocused = mutableStateOf(false) - override var isBFocused = mutableStateOf(false) - override var requestFocusA = mutableStateOf(FocusRequester()) + ViewModel() { + var scoreA by mutableStateOf("") + private set - override fun submitScore() { + var scoreB by mutableStateOf("") + private set + + var enableSubmit by mutableStateOf(false) + private set + + var isAFocused by mutableStateOf(false) + + var isBFocused by mutableStateOf(false) + + var requestFocusA by mutableStateOf(FocusRequester()) + private set + + private var activeValue: String + get() { + return if (isBFocused) { + scoreB + } else { + scoreA + } + } + set(value) { + if (isBFocused) { + scoreB = value + } else { + scoreA = value + } + } + + private var inactiveValue: String + get() { + return if (isAFocused) { + scoreB + } else { + scoreA + } + } + set(value) { + if (isAFocused) { + scoreB = value + } else { + scoreA = value + } + } + + + fun submitScore() { viewModelScope.launch { - gameRepository.addRoundToActiveGame(scoreA.value.toInt(), scoreB.value.toInt()) + gameRepository.addRoundToActiveGame(scoreA.toInt(), scoreB.toInt()) } - scoreA.value = "" - scoreB.value = "" - enableSubmit.value = false + scoreA = "" + scoreB = "" + enableSubmit = false } - override fun appendToFocusedScore(toAppend: String) { - val value = getActiveValue() - value.value += toAppend + fun appendToFocusedScore(toAppend: String) { + activeValue += toAppend updateOtherScore() + updateSubmitButton() } - override fun negateActiveInput() { - val value = getActiveValue() - - if (value.value.contains("-")) { - value.value = value.value.replace("-", "") + fun negateActiveInput() { + activeValue = if (activeValue.contains("-")) { + activeValue.replace("-", "") } else { - value.value = "-" + value.value + "-$activeValue" } - updateOtherScore() + updateSubmitButton() } - override fun addToActiveInput(toAdd: Int) { - val value = getActiveValue() - - try { - val temp = value.value.toInt() + toAdd - value.value = temp.toString() + fun addToActiveInput(toAdd: Int) { + activeValue = try { + val temp = activeValue.toInt() + toAdd + temp.toString() } catch (e: Exception) { - value.value = toAdd.toString() + toAdd.toString() } + if(inactiveValue == "") + { + updateOtherScore() + } + + updateSubmitButton() } - override fun removeLastCharFromActive() { - val value = getActiveValue() - if (value.value != "") { - value.value = value.value.dropLast(1) + fun removeLastCharFromActive() { + if (activeValue != "") { + activeValue = activeValue.dropLast(1) } updateOtherScore() } private fun giveFocusToAIfNone() { - if (!isAFocused.value && !isBFocused.value) { - requestFocusA.value.requestFocus() + if (!isAFocused && !isBFocused) { + requestFocusA.requestFocus() } } private fun updateOtherScore() { - val value = getActiveValue() - try { val tichu = Tichu() - val myScore = value.value.toInt() + val myScore = activeValue.toInt() val hisScore = tichu.calculateOtherScore(myScore) if (tichu.isValidRound(myScore, hisScore)) { - updateInactiveValue(hisScore?.toString() ?: "") + inactiveValue = hisScore?.toString() ?: "" } else { - updateInactiveValue("") + inactiveValue = "" } } catch (_: Exception) { - updateInactiveValue("") + inactiveValue = "" } } - private fun getActiveValue(): MutableState { - giveFocusToAIfNone() - if (isBFocused.value) { - return scoreB - } - return scoreA - } - - private fun updateInactiveValue(value: String) { - giveFocusToAIfNone() - if (isBFocused.value) { - scoreA.value = value - } else { - scoreB.value = value - } - - try { + private fun isValidTichuRound(): Boolean { + return try { val tichu = Tichu() - enableSubmit.value = tichu.isValidRound(scoreA.value.toInt(), scoreB.value.toInt()) + tichu.isValidRound(scoreA.toInt(), scoreB.toInt()) } catch (_: java.lang.NumberFormatException) { - enableSubmit.value = false + false } } + private fun updateSubmitButton() { + enableSubmit = isValidTichuRound() + } } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundList.kt b/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundList.kt index 47f7671..2272f99 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundList.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundList.kt @@ -50,15 +50,18 @@ class RoundList : Fragment() { } } - - @Preview @Composable - fun RoundListView(viewModel: IRoundListViewModel = DefaultViewModel()) { + fun RoundListView(viewModel: RoundListViewModel) { + RoundListView(viewModel.scores) + } + + @Composable + fun RoundListView(rounds: List) { val lazyListState = rememberLazyListState() val scope = rememberCoroutineScope() LazyColumn(state = lazyListState) { - itemsIndexed(viewModel.scores) { index, item -> + itemsIndexed(rounds) { index, item -> RoundListItem(item, index, lazyListState) } @@ -96,11 +99,16 @@ class RoundList : Fragment() { } } - internal class DefaultViewModel() : IRoundListViewModel { - override var scores: List - get() = TODO("Not yet implemented") - set(value) {} + @Composable + @Preview + fun RoundListViewPreview() { + val rounds = listOf( + Round(1, 10, 90), + Round(1, 5, 95), + Round(1, 100, 0), + Round(1, 125, -25), + Round(1, 50, 50) + ) + RoundListView(rounds) } - - } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundListViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundListViewModel.kt index 739441d..2189e75 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundListViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/counter/RoundListViewModel.kt @@ -11,15 +11,10 @@ import me.zobrist.tichucounter.data.Round import me.zobrist.tichucounter.data.RoundDao import javax.inject.Inject -interface IRoundListViewModel { - var scores: List -} - @HiltViewModel -class RoundListViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel(), - IRoundListViewModel { +class RoundListViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel(){ - override var scores by mutableStateOf(emptyList()) + var scores by mutableStateOf(emptyList()) init { viewModelScope.launch { diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt index 21452e2..d8821ec 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragment.kt @@ -15,8 +15,6 @@ import androidx.compose.material3.Card import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy @@ -55,11 +53,13 @@ class HistoryFragment : Fragment() { } } - @Preview @Composable - fun HistoryList(viewModel: IHistoryFragmentViewModel = DefaultViewModel()) { - val games = viewModel.gameAndHistory.value + fun HistoryList(viewModel: HistoryFragmentViewModel) { + HistoryList(viewModel.gameAndHistory) + } + @Composable + fun HistoryList(games: List) { LazyColumn { items(games) { HistoryListItem(it) @@ -111,41 +111,16 @@ class HistoryFragment : Fragment() { } } - internal class DefaultViewModel : IHistoryFragmentViewModel { - - override val gameAndHistory: State> - get() { - val tempData = mutableListOf() - tempData.add( - GameAndScore( - false, - "TeamA1sdfdsf", - "TeamB1", - Date(), - Date(), - 1, - 10, - 50 - ) - ) - tempData.add( - GameAndScore( - true, - "TeamA2", - "TeamB2sdfsdf", - Date(), - Date(), - 2, - 20, - 60 - ) - ) - tempData.add(GameAndScore(false, "TeamA3", "TeamB3", Date(), Date(), 3, 30, 70)) - tempData.add(GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80)) - tempData.add(GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90)) - - return mutableStateOf(tempData) - } - + @Preview + @Composable + private fun HistoryListPreview() { + val tempData = listOf( + GameAndScore(false, "abc", "def", Date(), Date(), 1, 10, 50), + GameAndScore(true, "ADTH", "dogfg", Date(), Date(), 2, 20, 60), + GameAndScore(false, "TeamA3", "TeamB3", Date(), Date(), 3, 30, 70), + GameAndScore(false, "TeamA4", "TeamB4", Date(), Date(), 4, 40, 80), + GameAndScore(false, "TeamA5", "TeamB5", Date(), Date(), 5, 50, 90) + ) + HistoryList(tempData) } } \ No newline at end of file diff --git a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt index 858190b..bece052 100644 --- a/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt +++ b/app/src/main/java/me/zobrist/tichucounter/ui/history/HistoryFragmentViewModel.kt @@ -1,37 +1,29 @@ package me.zobrist.tichucounter.ui.history -import androidx.compose.runtime.State +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import me.zobrist.tichucounter.data.GameAndScore import me.zobrist.tichucounter.data.GameDao -import me.zobrist.tichucounter.data.RoundDao import javax.inject.Inject -interface IHistoryFragmentViewModel { - val gameAndHistory: State> -} @HiltViewModel class HistoryFragmentViewModel @Inject constructor( - private val gameDao: GameDao, - private val roundDao: RoundDao -) : ViewModel(), IHistoryFragmentViewModel { + private val gameDao: GameDao +) : ViewModel() { - private val _gameAndHistory = mutableStateOf(emptyList()) - - override val gameAndHistory: State> - get() { - return _gameAndHistory - } + var gameAndHistory by mutableStateOf(emptyList()) + private set init { viewModelScope.launch { gameDao.getAllWithPoints().collect { games -> - _gameAndHistory.value = games + gameAndHistory = games } } }