Simplify composables.
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-01-08 18:47:08 +01:00
parent 0f4d008104
commit 823d1a6ca4
6 changed files with 163 additions and 243 deletions

View File

@@ -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,
value = viewModel.scoreA,
onValueChange = { },
placeholder = { Text("0") },
singleLine = true,
readOnly = true,
modifier = Modifier
.onFocusChanged {
keyboardController?.hide()
viewModel.isAFocused.value = it.isFocused
viewModel.isAFocused = it.isFocused
}
.focusRequester(viewModel.requestFocusA.value)
.focusRequester(viewModel.requestFocusA)
.weight(1f),
colors = TextFieldDefaults.textFieldColors(
cursorColor = Color.Transparent,
errorCursorColor = Color.Transparent
)
)
TextField(
value = viewModel.scoreB.value,
value = viewModel.scoreB,
onValueChange = { },
placeholder = { Text("0") },
singleLine = true,
readOnly = true,
modifier = Modifier
.onFocusChanged {
keyboardController?.hide()
viewModel.isBFocused.value = it.isFocused
viewModel.isBFocused = it.isFocused
}
.weight(1f),
colors = TextFieldDefaults.textFieldColors(
cursorColor = Color.Transparent,
errorCursorColor = Color.Transparent
.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<String> = mutableStateOf("")
override var scoreB: MutableState<String> = 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")
}
}
}

View File

@@ -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<String>
var scoreB: MutableState<String>
var enableSubmit: MutableState<Boolean>
var isAFocused: MutableState<Boolean>
var isBFocused: MutableState<Boolean>
var requestFocusA: MutableState<FocusRequester>
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() {
viewModelScope.launch {
gameRepository.addRoundToActiveGame(scoreA.value.toInt(), scoreB.value.toInt())
}
scoreA.value = ""
scoreB.value = ""
enableSubmit.value = false
}
var scoreB by mutableStateOf("")
private set
override fun appendToFocusedScore(toAppend: String) {
val value = getActiveValue()
value.value += toAppend
updateOtherScore()
}
var enableSubmit by mutableStateOf(false)
private set
override fun negateActiveInput() {
val value = getActiveValue()
var isAFocused by mutableStateOf(false)
if (value.value.contains("-")) {
value.value = value.value.replace("-", "")
var isBFocused by mutableStateOf(false)
var requestFocusA by mutableStateOf(FocusRequester())
private set
private var activeValue: String
get() {
return if (isBFocused) {
scoreB
} else {
value.value = "-" + value.value
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.toInt(), scoreB.toInt())
}
scoreA = ""
scoreB = ""
enableSubmit = false
}
fun appendToFocusedScore(toAppend: String) {
activeValue += toAppend
updateOtherScore()
updateSubmitButton()
}
fun negateActiveInput() {
activeValue = if (activeValue.contains("-")) {
activeValue.replace("-", "")
} else {
"-$activeValue"
}
updateOtherScore()
updateSubmitButton()
}
fun addToActiveInput(toAdd: Int) {
activeValue = try {
val temp = activeValue.toInt() + toAdd
temp.toString()
} catch (e: Exception) {
toAdd.toString()
}
if(inactiveValue == "")
{
updateOtherScore()
}
override fun addToActiveInput(toAdd: Int) {
val value = getActiveValue()
try {
val temp = value.value.toInt() + toAdd
value.value = temp.toString()
} catch (e: Exception) {
value.value = toAdd.toString()
}
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<String> {
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()
}
}

View File

@@ -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<Round>) {
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<Round>
get() = TODO("Not yet implemented")
set(value) {}
@Composable
@Preview
fun RoundListViewPreview() {
val rounds = listOf<Round>(
Round(1, 10, 90),
Round(1, 5, 95),
Round(1, 100, 0),
Round(1, 125, -25),
Round(1, 50, 50)
)
RoundListView(rounds)
}
}

View File

@@ -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<Round>
}
@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<Round>())
var scores by mutableStateOf(emptyList<Round>())
init {
viewModelScope.launch {

View File

@@ -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<GameAndScore>) {
LazyColumn {
items(games) {
HistoryListItem(it)
@@ -111,41 +111,16 @@ class HistoryFragment : Fragment() {
}
}
internal class DefaultViewModel : IHistoryFragmentViewModel {
override val gameAndHistory: State<List<GameAndScore>>
get() {
val tempData = mutableListOf<GameAndScore>()
tempData.add(
GameAndScore(
false,
"TeamA1sdfdsf",
"TeamB1",
Date(),
Date(),
1,
10,
50
@Preview
@Composable
private fun HistoryListPreview() {
val tempData = listOf<GameAndScore>(
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)
)
)
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)
}
HistoryList(tempData)
}
}

View File

@@ -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<List<GameAndScore>>
}
@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<GameAndScore>())
override val gameAndHistory: State<List<GameAndScore>>
get() {
return _gameAndHistory
}
var gameAndHistory by mutableStateOf(emptyList<GameAndScore>())
private set
init {
viewModelScope.launch {
gameDao.getAllWithPoints().collect { games ->
_gameAndHistory.value = games
gameAndHistory = games
}
}
}