Composify more fragments.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2023-01-09 20:08:13 +01:00
parent 823d1a6ca4
commit a4ccd62d72
7 changed files with 155 additions and 154 deletions

View File

@@ -74,12 +74,16 @@ class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepo
} }
fun appendToFocusedScore(toAppend: String) { fun appendToFocusedScore(toAppend: String) {
giveFocusToAIfNone()
activeValue += toAppend activeValue += toAppend
updateOtherScore() updateOtherScore()
updateSubmitButton() updateSubmitButton()
} }
fun negateActiveInput() { fun negateActiveInput() {
giveFocusToAIfNone()
activeValue = if (activeValue.contains("-")) { activeValue = if (activeValue.contains("-")) {
activeValue.replace("-", "") activeValue.replace("-", "")
} else { } else {
@@ -90,6 +94,8 @@ class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepo
} }
fun addToActiveInput(toAdd: Int) { fun addToActiveInput(toAdd: Int) {
giveFocusToAIfNone()
activeValue = try { activeValue = try {
val temp = activeValue.toInt() + toAdd val temp = activeValue.toInt() + toAdd
temp.toString() temp.toString()
@@ -119,17 +125,17 @@ class KeyboardViewModel @Inject constructor(private val gameRepository: GameRepo
} }
private fun updateOtherScore() { private fun updateOtherScore() {
try { inactiveValue = try {
val tichu = Tichu() val tichu = Tichu()
val myScore = activeValue.toInt() val myScore = activeValue.toInt()
val hisScore = tichu.calculateOtherScore(myScore) val hisScore = tichu.calculateOtherScore(myScore)
if (tichu.isValidRound(myScore, hisScore)) { if (tichu.isValidRound(myScore, hisScore)) {
inactiveValue = hisScore?.toString() ?: "" hisScore?.toString() ?: ""
} else { } else {
inactiveValue = "" ""
} }
} catch (_: Exception) { } catch (_: Exception) {
inactiveValue = "" ""
} }
} }

View File

@@ -4,41 +4,81 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.widget.doAfterTextChanged import android.widget.EditText
import androidx.fragment.app.activityViewModels import androidx.compose.foundation.layout.Row
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.tooling.preview.Preview
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import me.zobrist.tichucounter.databinding.FragmentTeamNamesBinding
import me.zobrist.tichucounter.ui.FragmentBase
@AndroidEntryPoint @AndroidEntryPoint
class TeamNames : FragmentBase<FragmentTeamNamesBinding>() { class TeamNames : Fragment() {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentTeamNamesBinding private val viewModel: TeamNamesViewModel by viewModels()
get() = FragmentTeamNamesBinding::inflate
private val viewModel: TeamNamesViewModel by activityViewModels() override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { return ComposeView(requireContext()).apply {
// Dispose of the Composition when the view's LifecycleOwner
binding.nameTeamA.doAfterTextChanged { // is destroyed
viewModel.setNameA(binding.nameTeamA.text.toString()) setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
TeamNamesView(viewModel)
} }
binding.nameTeamB.doAfterTextChanged {
viewModel.setNameB(binding.nameTeamB.text.toString())
} }
viewModel.nameA.observe(viewLifecycleOwner) { value ->
if (value != binding.nameTeamA.text.toString()) {
binding.nameTeamA.setText(value)
} }
} }
viewModel.nameB.observe(viewLifecycleOwner) { value -> @Composable
if (value != binding.nameTeamB.text.toString()) { private fun TeamNamesView(viewModel: TeamNamesViewModel) {
binding.nameTeamB.setText(value)
TeamNamesView(
viewModel.nameA,
viewModel.nameB,
{ viewModel.updateNameA(it)},
{ viewModel.updateNameB(it)})
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TeamNamesView(
nameA: String,
nameB: String,
updateA: (String) -> Unit,
updateB: (String) -> Unit
){
Row() {
TextField(
value = nameA,
onValueChange = { updateA(it) },
singleLine = true,
modifier = Modifier.weight(1f))
TextField(
value = nameB,
onValueChange = { updateB(it) },
singleLine = true,
modifier = Modifier.weight(1f))
} }
} }
@Preview
@Composable
private fun TeamNamesView() {
TeamNamesView("TeamA", "TeamB", {}, {})
} }
} }

View File

@@ -1,11 +1,15 @@
package me.zobrist.tichucounter.ui.counter package me.zobrist.tichucounter.ui.counter
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.Game
import me.zobrist.tichucounter.data.GameDao import me.zobrist.tichucounter.data.GameDao
import me.zobrist.tichucounter.repository.GameRepository import me.zobrist.tichucounter.repository.GameRepository
import javax.inject.Inject import javax.inject.Inject
@@ -17,40 +21,35 @@ class TeamNamesViewModel @Inject constructor(
) : ) :
ViewModel() { ViewModel() {
private val _nameA: MutableLiveData<String> = MutableLiveData() var nameA by mutableStateOf("")
private val _nameB: MutableLiveData<String> = MutableLiveData() private set
val nameA: LiveData<String> var nameB by mutableStateOf("")
get() { private set
return _nameA
}
val nameB: LiveData<String>
get() {
return _nameB
}
init { init {
viewModelScope.launch { viewModelScope.launch {
gameDao.getActive().collect { gameDao.getActive().collect {
_nameA.value = it?.nameA if (it != null) {
_nameB.value = it?.nameB nameA = it.nameA
nameB = it.nameB
}
} }
} }
} }
fun setNameA(name: String) { fun updateNameA(value: String) {
viewModelScope.launch { viewModelScope.launch {
val game = gameRepository.activeGame val game = gameRepository.activeGame
game.nameA = name game.nameA = value
gameRepository.updateGame(game) gameRepository.updateGame(game)
} }
} }
fun setNameB(name: String) { fun updateNameB(value: String) {
viewModelScope.launch { viewModelScope.launch {
val game = gameRepository.activeGame val game = gameRepository.activeGame
game.nameB = name game.nameB = value
gameRepository.updateGame(game) gameRepository.updateGame(game)
} }
} }

View File

@@ -4,27 +4,70 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import me.zobrist.tichucounter.databinding.FragmentTeamScoresBinding import me.zobrist.tichucounter.databinding.FragmentTeamScoresBinding
import me.zobrist.tichucounter.ui.FragmentBase import me.zobrist.tichucounter.ui.FragmentBase
@AndroidEntryPoint @AndroidEntryPoint
class TeamScores : FragmentBase<FragmentTeamScoresBinding>() { class TeamScores : Fragment() {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentTeamScoresBinding
get() = FragmentTeamScoresBinding::inflate
private val viewModel: TeamScoresViewModel by activityViewModels() private val viewModel: TeamScoresViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel.scoreA.observe(viewLifecycleOwner) { return ComposeView(requireContext()).apply {
binding.scoreA.text = it?.toString() ?: "" // Dispose of the Composition when the view's LifecycleOwner
// is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
TeamScoresView(viewModel)
}
}
}
} }
viewModel.scoreB.observe(viewLifecycleOwner) { @Composable
binding.scoreB.text = it?.toString() ?: "" private fun TeamScoresView(viewModel: TeamScoresViewModel) {
TeamScoresView(viewModel.scoreA, viewModel.scoreB)
}
@Composable
private fun TeamScoresView(scoreA: Int, scoreB: Int,){
Row() {
Text(
text = scoreA.toString(),
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center)
Text(
text = scoreB.toString(),
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center)
} }
} }
@Preview
@Composable
private fun TeamNamesView() {
TeamScoresView(10, 90)
}
} }

View File

@@ -1,5 +1,8 @@
package me.zobrist.tichucounter.ui.counter package me.zobrist.tichucounter.ui.counter
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@@ -12,26 +15,20 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class TeamScoresViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel() { class TeamScoresViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel() {
private var _scoreA: MutableLiveData<Int> = MutableLiveData() var scoreA by mutableStateOf(0)
private var _scoreB: MutableLiveData<Int> = MutableLiveData() private set
var scoreB by mutableStateOf(0)
private set
init { init {
viewModelScope.launch { viewModelScope.launch {
roundDao.getRoundSumForActiveGame().collect { score -> roundDao.getRoundSumForActiveGame().collect { score ->
_scoreA.value = if (score?.scoreA != null) score.scoreA else 0 scoreA = score.scoreA
_scoreB.value = if (score?.scoreB != null) score.scoreB else 0 scoreB = score.scoreB
} }
} }
} }
val scoreA: LiveData<Int>
get() {
return _scoreA
}
val scoreB: LiveData<Int>
get() {
return _scoreB
}
} }

View File

@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.counter.TeamNames">
<LinearLayout
android:id="@+id/viewNames"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="@+id/nameTeamA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:autofillHints=""
android:gravity="center"
android:imeOptions="actionDone"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true"
android:text="@string/team_a"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<EditText
android:id="@+id/nameTeamB"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:autofillHints=""
android:gravity="center"
android:imeOptions="actionDone"
android:inputType="text"
android:selectAllOnFocus="true"
android:singleLine="true"
android:text="@string/team_b"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</LinearLayout>
</FrameLayout>

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.counter.TeamScores">
<LinearLayout
android:id="@+id/viewScore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/scoreA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="0"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="18sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/scoreB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="0"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
android:textSize="18sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</LinearLayout>
</FrameLayout>