First draft
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-03-10 13:19:09 +01:00
parent 343d1d8e75
commit 3ec8c27b96
6 changed files with 133 additions and 14 deletions

View File

@@ -35,4 +35,7 @@ interface GameDao : DaoBase<Game> {
@Query("UPDATE game SET active = 0 WHERE uid is not :gameId;")
fun setOthersInactive(gameId: Long)
@Query("SELECT names FROM (SELECT nameA AS names FROM game UNION ALL SELECT nameB AS names FROM game) GROUP BY names")
fun getDistinctTeamNames(): Flow<List<String>>
}

View File

@@ -2,10 +2,7 @@ package me.zobrist.tichucounter.repository
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.flow.*
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.zobrist.tichucounter.data.GameDao
@@ -23,6 +20,8 @@ class GameRepository @Inject constructor(
private var activeGame: Game = Game(true, "TeamA", "TeamB", Date(), Date())
private var distinctTeamNames: List<String> = listOf()
init {
CoroutineScope(Dispatchers.IO).launch {
gameDao.getActiveAsFlow().collect {
@@ -130,4 +129,8 @@ class GameRepository @Inject constructor(
fun getAllWithRoundFlow(): Flow<List<GameWithScores>> {
return gameDao.getGamesWithRounds()
}
fun getDistinctTeamNames(): Flow<List<String>> {
return gameDao.getDistinctTeamNames()
}
}

View File

@@ -0,0 +1,90 @@
package me.zobrist.tichucounter.ui.composables
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
@Composable
fun TypeaheadTextField(
value: String,
items: List<String>,
onValueChange: (String) -> Unit,
modifier: Modifier,
colors: TextFieldColors,
textStyle: TextStyle
) {
var isFocused by remember { mutableStateOf(false) }
val focusManager = LocalFocusManager.current
ExposedDropdownMenuBox(
expanded = isFocused,
modifier = modifier,
onExpandedChange = {}
) {
var dropDownWidth by remember { mutableStateOf(0) }
TextField(
value = value,
textStyle = textStyle,
onValueChange = {
onValueChange(it)
},
singleLine = true,
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = {
focusManager.clearFocus()
}
),
modifier = Modifier
.menuAnchor()
.onFocusChanged {
isFocused = it.isFocused
}
.onSizeChanged { dropDownWidth = it.width }
.onKeyEvent { event ->
if (event.key == Key.Back || event.key == Key.Enter) {
focusManager.clearFocus()
true
}
false
},
colors = colors
)
ExposedDropdownMenu(
expanded = isFocused,
modifier = Modifier
.width(with(LocalDensity.current){dropDownWidth.toDp()}),
onDismissRequest = { }
) {
val filtered = items.filter { it.contains(value) && it.isNotBlank() }
filtered.forEach {
DropdownMenuItem(
onClick = {
onValueChange(it)
focusManager.clearFocus()
},
text = { Text(it) },
)
}
}
}
}

View File

@@ -35,6 +35,7 @@ fun Landscape(viewModel: ICounterViewModel) {
TeamNamesView(
viewModel.teamNameA,
viewModel.teamNameB,
viewModel.distinctTeamNames,
{ viewModel.updateNameA(it) },
{ viewModel.updateNameB(it) }
)
@@ -64,6 +65,7 @@ fun Portrait(viewModel: ICounterViewModel) {
TeamNamesView(
viewModel.teamNameA,
viewModel.teamNameB,
viewModel.distinctTeamNames,
{ viewModel.updateNameA(it) },
{ viewModel.updateNameB(it) }
)
@@ -111,6 +113,7 @@ internal class PreviewViewModel : ICounterViewModel {
override var activeValue: String = currentScoreA
override var inactiveValue: String = currentScoreB
override var keyboardHidden: Boolean = false
override val distinctTeamNames: List<String> = listOf("TeamA", "asdffd", "TeamB", "really really long Team Name that is way too long")
override fun focusLastInput() {
}

View File

@@ -1,6 +1,7 @@
package me.zobrist.tichucounter.ui.counter
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.focus.FocusRequester
@@ -9,6 +10,8 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.entity.Round
import me.zobrist.tichucounter.domain.Tichu
@@ -31,6 +34,7 @@ interface IKeyBoardViewModel {
val activeValue: String
val inactiveValue: String
val keyboardHidden: Boolean
val distinctTeamNames: List<String>
fun focusLastInput()
fun updateOtherScore()
@@ -105,6 +109,9 @@ class CounterViewModel @Inject constructor(
override var keyboardHidden by mutableStateOf(false)
private set
override var distinctTeamNames by mutableStateOf(listOf<String>())
private set
override var activeValue: String
get() {
return if (isBFocused) {
@@ -160,6 +167,12 @@ class CounterViewModel @Inject constructor(
}
}
}
viewModelScope.launch {
gameRepository.getDistinctTeamNames().collect() {
distinctTeamNames = it
}
}
}
override fun focusLastInput() {

View File

@@ -4,18 +4,22 @@ import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import me.zobrist.tichucounter.ui.AppTheme
import me.zobrist.tichucounter.ui.composables.TypeaheadTextField
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TeamNamesView(
nameA: String,
nameB: String,
nameSuggestions: List<String>,
updateA: (String) -> Unit,
updateB: (String) -> Unit
) {
@@ -25,23 +29,26 @@ fun TeamNamesView(
)
Row {
TextField(
TypeaheadTextField(
value = nameA,
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
items = nameSuggestions,
onValueChange = { updateA(it) },
singleLine = true,
modifier = Modifier.weight(1f),
colors = color
colors = color,
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center)
)
TextField(
TypeaheadTextField(
value = nameB,
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center),
items = nameSuggestions,
onValueChange = { updateB(it) },
singleLine = true,
modifier = Modifier.weight(1f),
colors = color
colors = color,
textStyle = LocalTextStyle.current.copy(textAlign = TextAlign.Center)
)
}
}
@@ -50,6 +57,6 @@ fun TeamNamesView(
@Composable
private fun TeamNamesViewPreview() {
AppTheme {
TeamNamesView("TeamA", "TeamB", {}, {})
TeamNamesView("TeamA", "TeamB", listOf("Test1", "Test3"), {}, {})
}
}