Replace RoundList with compose.
Some checks are pending
continuous-integration/drone/push Build is running

This commit is contained in:
2023-01-07 22:42:21 +01:00
parent 5f6da1d7d4
commit 2ed221a99f
8 changed files with 107 additions and 345 deletions

View File

@@ -11,7 +11,7 @@ data class GameAndScore(
override val created: Date,
override var modified: Date,
override var gameId: Long,
override var scoreA: Int?,
override var scoreB: Int?,
override var scoreA: Int,
override var scoreB: Int,
) : IGame, IRound {
}

View File

@@ -2,6 +2,6 @@ package me.zobrist.tichucounter.data
interface IRound {
var gameId: Long
var scoreA: Int?
var scoreB: Int?
var scoreA: Int
var scoreB: Int
}

View File

@@ -6,7 +6,7 @@ import androidx.room.PrimaryKey
@Entity
data class Round(
override var gameId: Long,
override var scoreA: Int?,
override var scoreB: Int?,
override var scoreA: Int,
override var scoreB: Int,
@PrimaryKey(autoGenerate = true) override val uid: Long? = null
) : IRound, IEntity

View File

@@ -5,13 +5,11 @@ import android.view.*
import androidx.appcompat.app.AlertDialog
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import me.zobrist.tichucounter.R
import me.zobrist.tichucounter.data.Round
import me.zobrist.tichucounter.databinding.FragmentCounterBinding
import me.zobrist.tichucounter.repository.GameRepository
import me.zobrist.tichucounter.ui.FragmentBase
@@ -26,12 +24,6 @@ class CounterFragment : FragmentBase<FragmentCounterBinding>(), MenuProvider {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentCounterBinding
get() = FragmentCounterBinding::inflate
private var currentRound: Round = Round(0, 0, null, null)
private var ignoreNextUpdate: Boolean = false
private val keyboardViewModel: KeyboardViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

View File

@@ -4,32 +4,103 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
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.compose.ui.unit.dp
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import dagger.hilt.android.AndroidEntryPoint
import me.zobrist.tichucounter.databinding.FragmentRoundListBinding
import me.zobrist.tichucounter.ui.FragmentBase
import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.Round
@AndroidEntryPoint
class RoundList : FragmentBase<FragmentRoundListBinding>() {
override val bindingInflater: (LayoutInflater, ViewGroup?, Boolean) -> FragmentRoundListBinding
get() = FragmentRoundListBinding::inflate
class RoundList : Fragment() {
private val viewModel: RoundListViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
viewModel.historyA.observe(viewLifecycleOwner) { text ->
binding.historyA.text = text
return ComposeView(requireContext()).apply {
// Dispose of the Composition when the view's LifecycleOwner
// is destroyed
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
RoundListView(viewModel)
}
viewModel.historyB.observe(viewLifecycleOwner) { text ->
binding.historyB.text = text
}
viewModel.scrollDown.observe(viewLifecycleOwner) {
binding.scrollViewHistory.smoothScrollTo(0, binding.scrollViewHistory.height)
}
}
@Preview
@Composable
fun RoundListView(viewModel: IRoundListViewModel = DefaultViewModel()) {
val lazyListState = rememberLazyListState()
val scope = rememberCoroutineScope()
LazyColumn(state = lazyListState) {
itemsIndexed(viewModel.scores) { index, item ->
RoundListItem(item, index, lazyListState)
}
scope.launch {
lazyListState.animateScrollToItem(viewModel.scores.size)
}
}
}
@Composable
fun RoundListItem(round: Round, index: Int, lazyListState: LazyListState) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(all = 4.dp)
) {
Text(
text = round.scoreA.toString(),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(5f),
textAlign = TextAlign.Center
)
Text(
text = index.toString(),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(1f),
textAlign = TextAlign.Center
)
Text(
text = round.scoreB.toString(),
style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(5f),
textAlign = TextAlign.Center
)
}
}
internal class DefaultViewModel() : IRoundListViewModel {
override var scores: List<Round>
get() = TODO("Not yet implemented")
set(value) {}
}
}

View File

@@ -1,61 +1,33 @@
package me.zobrist.tichucounter.ui.counter
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
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.Round
import me.zobrist.tichucounter.data.RoundDao
import me.zobrist.tichucounter.framework.SingleLiveEvent
import javax.inject.Inject
@HiltViewModel
class RoundListViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel() {
interface IRoundListViewModel {
var scores: List<Round>
}
private val _historyA: MutableLiveData<String> = MutableLiveData<String>()
private val _historyB: MutableLiveData<String> = MutableLiveData<String>()
private val _scrollDown: SingleLiveEvent<Boolean> = SingleLiveEvent()
@HiltViewModel
class RoundListViewModel @Inject constructor(private val roundDao: RoundDao) : ViewModel(),
IRoundListViewModel {
override var scores by mutableStateOf(emptyList<Round>())
init {
viewModelScope.launch {
roundDao.getForActiveGame().collect { scores ->
update(scores)
roundDao.getForActiveGame().collect {
scores = it
}
}
}
val historyA: LiveData<String>
get() {
return _historyA
}
val historyB: LiveData<String>
get() {
return _historyB
}
val scrollDown: LiveData<Boolean>
get() {
return _scrollDown
}
private fun update(scores: List<Round>) {
var historyA = String()
var historyB = String()
scores.forEach {
historyA += it.scoreA.toString() + "\n"
historyB += it.scoreB.toString() + "\n"
}
_historyA.value = historyA
_historyB.value = historyB
scrollDown()
}
private fun scrollDown() {
_scrollDown.value = true
}
}

View File

@@ -1,228 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".ui.counter.Keyboard">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/viewInput"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/keyboard"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<EditText
android:id="@+id/inputTeamA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:gravity="center"
android:hint="0"
android:importantForAutofill="no"
android:inputType="numberSigned"
tools:ignore="HardcodedText" />
<EditText
android:id="@+id/inputTeamB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:gravity="center"
android:hint="0"
android:importantForAutofill="no"
android:inputType="numberSigned"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ButtonRow1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<Button
android:id="@+id/button1"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="1"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/button2"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/button3"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="3"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/buttonAdd100"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="+100"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ButtonRow2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button4"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="4"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/button5"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="5"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/button6"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="6"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/buttonSub100"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="-100"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ButtonRow3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/button7"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="7"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/button8"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="8"
tools:ignore="HardcodedText" />
<Button
android:id="@+id/button9"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="9"
tools:ignore="HardcodedText" />
<ImageButton
android:id="@+id/buttonBack"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="@string/back"
android:cropToPadding="false"
android:paddingTop="15dp"
android:paddingBottom="15dp"
android:scaleType="fitCenter"
app:srcCompat="@drawable/back" />
</LinearLayout>
<LinearLayout
android:id="@+id/ButtonRow4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
tools:layout_editor_absoluteX="1dp">
<Button
android:id="@+id/buttonInv"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="+/-" />
<Button
android:id="@+id/button0"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:text="0" />
<Space
style='?android:attr/buttonBarButtonStyle'
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1.0" />
<ImageButton
android:id="@+id/submit"
style='?android:attr/buttonStyle'
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:contentDescription="@string/submit"
android:cropToPadding="false"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:scaleType="fitCenter"
app:srcCompat="@drawable/checkmark" />
</LinearLayout>
</LinearLayout>
</FrameLayout>

View File

@@ -1,45 +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.RoundList">
<ScrollView
android:id="@+id/scrollViewHistory"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/historyA"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:gravity="center"
tools:text="@tools:sample/cities" />
<TextView
android:id="@+id/historyB"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:gravity="center"
tools:text="@tools:sample/date/hhmmss" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</FrameLayout>