1 Commits

Author SHA1 Message Date
d1b4ab1e8c WIP: Add setting for counter mode.
All checks were successful
Build Android / build (push) Successful in 7m57s
2023-07-01 11:37:10 +02:00
8 changed files with 120 additions and 27 deletions

View File

@@ -37,7 +37,7 @@ import me.zobrist.tichucounter.ui.settings.SettingsViewModel
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity(), ISettingsChangeListener { class MainActivity : AppCompatActivity(), ISystemSettingsChangeListener {
@Inject @Inject
lateinit var settingsAdapter: SettingsAdapter lateinit var settingsAdapter: SettingsAdapter

View File

@@ -16,17 +16,26 @@ enum class Language(val value: LocaleListCompat) {
enum class KeepScreenOn(val value: Boolean) { ON(true), OFF(false) } enum class KeepScreenOn(val value: Boolean) { ON(true), OFF(false) }
interface ISettingsChangeListener { enum class CounterListView { BY_ROUND, CONTINUOUS }
interface ISystemSettingsChangeListener {
fun onLanguageChanged(language: Language) fun onLanguageChanged(language: Language)
fun onThemeChanged(theme: Theme) fun onThemeChanged(theme: Theme)
fun onScreenOnChanged(keepOn: KeepScreenOn) fun onScreenOnChanged(keepOn: KeepScreenOn)
} }
interface IDisplaySettingsChangeListener {
fun onCounterListViewChanged(listView: CounterListView)
}
@Singleton @Singleton
class SettingsAdapter @Inject constructor(@ApplicationContext private val context: Context) { class SettingsAdapter @Inject constructor(@ApplicationContext private val context: Context) {
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
private var listenerList = mutableListOf<ISettingsChangeListener>() private var systemListenerList = mutableListOf<ISystemSettingsChangeListener>()
private var displayListenerList = mutableListOf<IDisplaySettingsChangeListener>()
var language: Language var language: Language
private set private set
@@ -37,6 +46,9 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
var keepScreenOn: KeepScreenOn var keepScreenOn: KeepScreenOn
private set private set
var counterListView: CounterListView
private set
init { init {
language = try { language = try {
enumValueOf(sharedPreferences.getString(Language::class.simpleName, null)!!) enumValueOf(sharedPreferences.getString(Language::class.simpleName, null)!!)
@@ -55,19 +67,37 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
} catch (_: java.lang.Exception) { } catch (_: java.lang.Exception) {
KeepScreenOn.OFF KeepScreenOn.OFF
} }
counterListView = try {
enumValueOf(sharedPreferences.getString(CounterListView::class.simpleName, null)!!)
} catch (_: java.lang.Exception) {
CounterListView.BY_ROUND
}
} }
fun registerOnChangeListener(listener: ISettingsChangeListener) { fun registerOnChangeListener(listener: ISystemSettingsChangeListener) {
listenerList.add(listener) systemListenerList.add(listener)
listener.onThemeChanged(theme) listener.onThemeChanged(theme)
listener.onLanguageChanged(language) listener.onLanguageChanged(language)
listener.onScreenOnChanged(keepScreenOn) listener.onScreenOnChanged(keepScreenOn)
} }
fun unregisterOnChangeListener(listener: ISettingsChangeListener?) { fun registerOnChangeListener(listener: IDisplaySettingsChangeListener) {
displayListenerList.add(listener)
listener.onCounterListViewChanged(counterListView)
}
fun unregisterOnChangeListener(listener: ISystemSettingsChangeListener?) {
if (listener != null) { if (listener != null) {
listenerList.remove(listener) systemListenerList.remove(listener)
}
}
fun unregisterOnChangeListener(listener: IDisplaySettingsChangeListener?) {
if (listener != null) {
displayListenerList.remove(listener)
} }
} }
@@ -89,6 +119,12 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
notifyListeners(setting) notifyListeners(setting)
} }
fun setCounterViewList(setting: CounterListView) {
this.counterListView = setting
updatePreference(CounterListView::class.simpleName, setting.name)
notifyListeners(setting)
}
private fun updatePreference(name: String?, value: String) { private fun updatePreference(name: String?, value: String) {
val editor = sharedPreferences.edit() val editor = sharedPreferences.edit()
editor.putString(name, value) editor.putString(name, value)
@@ -96,21 +132,27 @@ class SettingsAdapter @Inject constructor(@ApplicationContext private val contex
} }
private fun notifyListeners(language: Language) { private fun notifyListeners(language: Language) {
listenerList.forEach { systemListenerList.forEach {
it.onLanguageChanged(language) it.onLanguageChanged(language)
} }
} }
private fun notifyListeners(theme: Theme) { private fun notifyListeners(theme: Theme) {
listenerList.forEach { systemListenerList.forEach {
it.onThemeChanged(theme) it.onThemeChanged(theme)
} }
} }
private fun notifyListeners(keepScreenOn: KeepScreenOn) { private fun notifyListeners(keepScreenOn: KeepScreenOn) {
listenerList.forEach { systemListenerList.forEach {
it.onScreenOnChanged(keepScreenOn) it.onScreenOnChanged(keepScreenOn)
} }
} }
private fun notifyListeners(counterListView: CounterListView) {
displayListenerList.forEach {
it.onCounterListViewChanged(counterListView)
}
}
} }

View File

@@ -52,6 +52,7 @@ fun Landscape(viewModel: ICounterViewModel) {
RoundListView( RoundListView(
viewModel.roundScoreList, viewModel.roundScoreList,
viewModel.sumUpScores,
Modifier.weight(1f) Modifier.weight(1f)
) )
} }
@@ -83,6 +84,7 @@ fun Portrait(viewModel: ICounterViewModel) {
RoundListView( RoundListView(
viewModel.roundScoreList, viewModel.roundScoreList,
viewModel.sumUpScores,
Modifier.weight(1f) Modifier.weight(1f)
) )
@@ -109,6 +111,7 @@ internal class PreviewViewModel : ICounterViewModel {
override var totalScoreB: Int = 750 override var totalScoreB: Int = 750
override var teamNameA: String = "Team A" override var teamNameA: String = "Team A"
override var teamNameB: String = "Team B" override var teamNameB: String = "Team B"
override val sumUpScores: Boolean = false
override var currentScoreA: String = "" override var currentScoreA: String = ""
override var currentScoreB: String = "45" override var currentScoreB: String = "45"
override var isValidRound: Boolean = false override var isValidRound: Boolean = false

View File

@@ -11,9 +11,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.entity.Round import me.zobrist.tichucounter.data.entity.Round
import me.zobrist.tichucounter.domain.Tichu import me.zobrist.tichucounter.domain.*
import me.zobrist.tichucounter.domain.digitCount
import me.zobrist.tichucounter.domain.getTotalPoints
import me.zobrist.tichucounter.repository.GameRepository import me.zobrist.tichucounter.repository.GameRepository
import javax.inject.Inject import javax.inject.Inject
@@ -53,6 +51,7 @@ interface ICounterViewModel : IKeyBoardViewModel {
val roundScoreList: List<Round> val roundScoreList: List<Round>
val totalScoreA: Int val totalScoreA: Int
val totalScoreB: Int val totalScoreB: Int
val sumUpScores: Boolean
val teamNameA: String val teamNameA: String
val teamNameB: String val teamNameB: String
val teamNameSuggestionsA: List<String> val teamNameSuggestionsA: List<String>
@@ -64,9 +63,10 @@ interface ICounterViewModel : IKeyBoardViewModel {
@HiltViewModel @HiltViewModel
class CounterViewModel @Inject constructor( class CounterViewModel @Inject constructor(
private val gameRepository: GameRepository private val gameRepository: GameRepository,
private val settingsAdapter: SettingsAdapter
) : ) :
ViewModel(), ICounterViewModel { ViewModel(), ICounterViewModel, IDisplaySettingsChangeListener {
override var roundScoreList by mutableStateOf(emptyList<Round>()) override var roundScoreList by mutableStateOf(emptyList<Round>())
private set private set
@@ -80,6 +80,9 @@ class CounterViewModel @Inject constructor(
override var teamNameA by mutableStateOf("") override var teamNameA by mutableStateOf("")
private set private set
override var sumUpScores by mutableStateOf(false)
private set
override var teamNameB by mutableStateOf("") override var teamNameB by mutableStateOf("")
private set private set
@@ -181,6 +184,12 @@ class CounterViewModel @Inject constructor(
buildTeamNameSuggestions() buildTeamNameSuggestions()
} }
} }
settingsAdapter.registerOnChangeListener(this)
}
override fun onCleared() {
settingsAdapter.unregisterOnChangeListener(this)
} }
override fun focusLastInput() { override fun focusLastInput() {
@@ -362,4 +371,8 @@ class CounterViewModel @Inject constructor(
return filtered.sorted().sortedBy { it.length }.take(10) return filtered.sorted().sortedBy { it.length }.take(10)
} }
override fun onCounterListViewChanged(listView: CounterListView) {
sumUpScores = listView == CounterListView.CONTINUOUS
}
} }

View File

@@ -21,13 +21,22 @@ import me.zobrist.tichucounter.data.entity.Round
import me.zobrist.tichucounter.ui.AppTheme import me.zobrist.tichucounter.ui.AppTheme
@Composable @Composable
fun RoundListView(rounds: List<Round>, modifier: Modifier) { fun RoundListView(rounds: List<Round>, sumUpRounds: Boolean = false, modifier: Modifier) {
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
var sumA = 0
var sumB = 0
LazyColumn(state = lazyListState, modifier = modifier) { LazyColumn(state = lazyListState, modifier = modifier) {
itemsIndexed(rounds) { index, item -> itemsIndexed(rounds) { index, item ->
RoundListItem(item, index) if (sumUpRounds) {
sumA += item.scoreA
sumB += item.scoreB
RoundListItem(sumA, sumB, index)
} else {
RoundListItem(item.scoreA, item.scoreB, index)
}
} }
scope.launch { scope.launch {
@@ -37,14 +46,14 @@ fun RoundListView(rounds: List<Round>, modifier: Modifier) {
} }
@Composable @Composable
private fun RoundListItem(round: Round, index: Int) { private fun RoundListItem(scoreA: Int, scoreB: Int, index: Int) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(all = 4.dp) .padding(all = 4.dp)
) { ) {
Text( Text(
text = round.scoreA.toString(), text = scoreA.toString(),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(5f), modifier = Modifier.weight(5f),
textAlign = TextAlign.Center textAlign = TextAlign.Center
@@ -56,7 +65,7 @@ private fun RoundListItem(round: Round, index: Int) {
textAlign = TextAlign.Center textAlign = TextAlign.Center
) )
Text( Text(
text = round.scoreB.toString(), text = scoreB.toString(),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
modifier = Modifier.weight(5f), modifier = Modifier.weight(5f),
textAlign = TextAlign.Center textAlign = TextAlign.Center
@@ -78,7 +87,7 @@ fun RoundListViewPreview() {
AppTheme { AppTheme {
Surface { Surface {
RoundListView(rounds, Modifier) RoundListView(rounds, true, Modifier)
} }
} }
} }

View File

@@ -25,6 +25,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import me.zobrist.tichucounter.R import me.zobrist.tichucounter.R
import me.zobrist.tichucounter.domain.CounterListView
import me.zobrist.tichucounter.domain.KeepScreenOn import me.zobrist.tichucounter.domain.KeepScreenOn
import me.zobrist.tichucounter.domain.Language import me.zobrist.tichucounter.domain.Language
import me.zobrist.tichucounter.domain.Theme import me.zobrist.tichucounter.domain.Theme
@@ -44,6 +45,11 @@ val themeMap = mapOf(
Theme.LIGHT to R.string.light Theme.LIGHT to R.string.light
) )
val counterListViewMap = mapOf(
CounterListView.BY_ROUND to R.string.by_round,
CounterListView.CONTINUOUS to R.string.continuous,
)
@Composable @Composable
fun SettingsView(viewModel: SettingsViewModel) { fun SettingsView(viewModel: SettingsViewModel) {
@@ -51,9 +57,11 @@ fun SettingsView(viewModel: SettingsViewModel) {
viewModel.screenOn.value, viewModel.screenOn.value,
viewModel.language, viewModel.language,
viewModel.theme, viewModel.theme,
viewModel.counterListView,
{ viewModel.updateScreenOn(it) }, { viewModel.updateScreenOn(it) },
{ viewModel.updateLanguage(it) }, { viewModel.updateLanguage(it) },
{ viewModel.updateTheme(it) }) { viewModel.updateTheme(it) },
{ viewModel.updateCounterListView(it) })
} }
@Composable @Composable
@@ -61,9 +69,11 @@ fun SettingsView(
valueScreenOn: Boolean = true, valueScreenOn: Boolean = true,
valueLanguage: Language = Language.ENGLISH, valueLanguage: Language = Language.ENGLISH,
valueTheme: Theme = Theme.DARK, valueTheme: Theme = Theme.DARK,
valueCounterListView: CounterListView = CounterListView.BY_ROUND,
updateScreenOn: (KeepScreenOn) -> Unit = {}, updateScreenOn: (KeepScreenOn) -> Unit = {},
updateLanguage: (Language) -> Unit = {}, updateLanguage: (Language) -> Unit = {},
updateTheme: (Theme) -> Unit = {} updateTheme: (Theme) -> Unit = {},
updateCounterListView: (CounterListView) -> Unit = {}
) { ) {
Column { Column {
BooleanSetting( BooleanSetting(
@@ -82,6 +92,14 @@ fun SettingsView(
themeMap, themeMap,
valueTheme, valueTheme,
) { updateTheme(it) } ) { updateTheme(it) }
StringSetting(
stringResource(R.string.counter_mode),
counterListViewMap,
valueCounterListView,
) { updateCounterListView(it) }
} }
} }

View File

@@ -5,10 +5,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import me.zobrist.tichucounter.domain.KeepScreenOn import me.zobrist.tichucounter.domain.*
import me.zobrist.tichucounter.domain.Language
import me.zobrist.tichucounter.domain.SettingsAdapter
import me.zobrist.tichucounter.domain.Theme
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@@ -24,6 +21,9 @@ class SettingsViewModel @Inject constructor(private val settings: SettingsAdapte
var screenOn by mutableStateOf(settings.keepScreenOn) var screenOn by mutableStateOf(settings.keepScreenOn)
private set private set
var counterListView by mutableStateOf(settings.counterListView)
private set
fun updateLanguage(language: Language) { fun updateLanguage(language: Language) {
settings.setLanguage(language) settings.setLanguage(language)
this.language = settings.language this.language = settings.language
@@ -39,4 +39,9 @@ class SettingsViewModel @Inject constructor(private val settings: SettingsAdapte
screenOn = settings.keepScreenOn screenOn = settings.keepScreenOn
} }
fun updateCounterListView(value: CounterListView) {
settings.setCounterViewList(value)
counterListView = settings.counterListView
}
} }

View File

@@ -26,6 +26,9 @@
<string name="inactive">Old Games</string> <string name="inactive">Old Games</string>
<string name="menu_counter">Counter</string> <string name="menu_counter">Counter</string>
<string name="menu_about">About</string> <string name="menu_about">About</string>
<string name="by_round">Display Single Round</string>
<string name="continuous">Sum up rounds</string>
<string name="counter_mode">Counter Mode</string>
<string name="contact_us">Contact us</string> <string name="contact_us">Contact us</string>
<string name="play_store" translatable="false">Play Store</string> <string name="play_store" translatable="false">Play Store</string>
</resources> </resources>