Add alerts for winning and draw.
All checks were successful
Build Android / build (push) Successful in 8m35s
Build Android / build (pull_request) Successful in 8m23s

This commit is contained in:
2023-08-26 15:20:43 +02:00
parent c97d98704b
commit 2599e3320a
8 changed files with 127 additions and 37 deletions

View File

@@ -40,7 +40,6 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.google.android.play.core.review.ReviewManager
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -230,7 +229,7 @@ class MainActivity : AppCompatActivity(), ISystemSettingsChangeListener {
mainViewModel.activeGameHasRounds,
{ expanded = true }
) {
val newGameTranslated = stringResource(R.string.newGame)
val newGameTranslated = stringResource(R.string.new_game)
DropDownMenu(
listOf(newGameTranslated),
"",

View File

@@ -2,27 +2,17 @@ package me.zobrist.tichucounter.domain
import android.app.Activity
import android.content.Context
import androidx.fragment.app.FragmentActivity
import androidx.preference.PreferenceManager
import com.google.android.play.core.review.ReviewManagerFactory
import com.google.android.play.core.review.testing.FakeReviewManager
import dagger.hilt.android.internal.Contexts
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ActivityScoped
import dagger.hilt.android.scopes.FragmentScoped
import dagger.hilt.android.scopes.ViewScoped
import java.time.Duration
import java.time.Period
import java.util.Date
import javax.inject.Inject
import javax.inject.Singleton
class ReviewService @Inject constructor(@ActivityContext private val appContext: Context) {
private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext)
private val THREE_MONTHS : Long = 7776000000
private val THREE_MONTHS: Long = 7776000000
private var requestCalled: Int
get() = sharedPreferences.getInt("requestCalled", 0)
@@ -43,10 +33,8 @@ class ReviewService @Inject constructor(@ActivityContext private val appContext:
fun request() {
requestCalled += 1
if(requestCalled >= 3)
{
if(nextReviewedDate.time < System.currentTimeMillis())
{
if (requestCalled >= 3) {
if (nextReviewedDate.time < System.currentTimeMillis()) {
requestCalled = 0
nextReviewedDate = Date(System.currentTimeMillis() + THREE_MONTHS)

View File

@@ -4,7 +4,6 @@ import android.content.Context
import androidx.core.os.LocaleListCompat
import androidx.preference.PreferenceManager
import dagger.hilt.android.qualifiers.ApplicationContext
import java.util.Date
import javax.inject.Inject
import javax.inject.Singleton

View File

@@ -7,10 +7,8 @@ import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.scopes.ActivityScoped
import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.entity.Round
import me.zobrist.tichucounter.domain.ReviewService
import me.zobrist.tichucounter.repository.GameRepository
import javax.inject.Inject

View File

@@ -3,7 +3,13 @@ package me.zobrist.tichucounter.ui.counter
import android.content.res.Configuration
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.EmojiEvents
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -12,7 +18,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import me.zobrist.tichucounter.R
import me.zobrist.tichucounter.data.entity.Round
import me.zobrist.tichucounter.ui.AppTheme
@@ -23,6 +31,18 @@ fun Counter(viewModel: ICounterViewModel = PreviewViewModel()) {
var orientation by remember { mutableStateOf(Configuration.ORIENTATION_PORTRAIT) }
orientation = LocalConfiguration.current.orientation
if (viewModel.showVictoryDialog) {
GameVictoryDialog(
viewModel.totalScoreA,
viewModel.totalScoreB,
viewModel.teamNameA,
viewModel.teamNameB,
{ viewModel.victoryDialogExecuted(false) })
{
viewModel.victoryDialogExecuted(true)
}
}
Surface {
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
Landscape(viewModel)
@@ -102,6 +122,54 @@ fun CounterViewPreview() {
}
}
@Preview()
@Composable
fun GameVictoryDialog(
pointsA: Int = 2000,
pointsB: Int = 50,
nameA: String = "nameA",
nameB: String = "nameB",
onDismiss: () -> Unit = {},
onNewGame: () -> Unit = {},
) {
val winner = if (pointsA > pointsB) {
nameA
} else {
nameB
}
val message = if (pointsA == pointsB) {
stringResource(R.string.draw_message, winner, 100)
} else {
stringResource(R.string.victory_message)
}
val title = if (pointsA == pointsB) {
stringResource(R.string.draw_title)
} else {
stringResource(R.string.victory_title, winner)
}
AlertDialog(
onDismissRequest = { onDismiss() },
dismissButton = {
TextButton({ onDismiss() }) {
Text(stringResource(R.string.continue_play))
}
},
confirmButton = {
TextButton({ onNewGame() }) {
Text(stringResource(R.string.new_game))
}
},
icon = { Icon(Icons.Outlined.EmojiEvents, null) },
title = { Text(title) },
text = { Text(message) }
)
}
internal class PreviewViewModel : ICounterViewModel {
override var roundScoreList: List<Round> =
listOf(Round(1, 10, 90), Round(1, 50, 50), Round(1, 70, 30))
@@ -123,7 +191,7 @@ internal class PreviewViewModel : ICounterViewModel {
listOf("TeamA", "asdffd", "TeamB", "really really long Team Name that is way too long")
override val teamNameSuggestionsB: List<String> =
listOf("TeamA", "asdffd", "TeamB", "really really long Team Name that is way too long")
override val victoryPoints: Int = 1000
override var showVictoryDialog: Boolean = false
override fun focusLastInput() {
}
@@ -156,6 +224,9 @@ internal class PreviewViewModel : ICounterViewModel {
override fun updateNameB(value: String) {
}
override fun victoryDialogExecuted(result: Boolean) {
}
override fun updateFocusStateA(state: Boolean) {
}

View File

@@ -11,8 +11,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import me.zobrist.tichucounter.data.entity.Game
import me.zobrist.tichucounter.data.entity.Round
import me.zobrist.tichucounter.domain.IGameSettingsChangeListener
import me.zobrist.tichucounter.domain.SettingsAdapter
import me.zobrist.tichucounter.domain.Tichu
import me.zobrist.tichucounter.domain.digitCount
import me.zobrist.tichucounter.domain.getTotalPoints
@@ -59,15 +61,17 @@ interface ICounterViewModel : IKeyBoardViewModel {
val teamNameB: String
val teamNameSuggestionsA: List<String>
val teamNameSuggestionsB: List<String>
val victoryPoints: Int
val showVictoryDialog: Boolean
fun updateNameA(value: String)
fun updateNameB(value: String)
fun victoryDialogExecuted(result: Boolean)
}
@HiltViewModel
class CounterViewModel @Inject constructor(
private val gameRepository: GameRepository
private val gameRepository: GameRepository,
private val settings: SettingsAdapter
) :
ViewModel(), ICounterViewModel, IGameSettingsChangeListener {
@@ -115,8 +119,7 @@ class CounterViewModel @Inject constructor(
override var teamNameSuggestionsB by mutableStateOf(listOf<String>())
private set
override var victoryPoints by mutableStateOf(0)
override var showVictoryDialog by mutableStateOf(false)
private set
override var activeValue: String
@@ -160,11 +163,14 @@ class CounterViewModel @Inject constructor(
private var distinctTeamNames = listOf<String>()
private var victoryDialogShown = false
private var lastGame: Game? = null
init {
viewModelScope.launch {
gameRepository.getActiveGameFlow().collect {
if (it != null) {
val score = it.getTotalPoints()
roundScoreList = it.rounds
@@ -176,12 +182,16 @@ class CounterViewModel @Inject constructor(
buildTeamNameSuggestions()
if (totalScoreA >= victoryPoints || totalScoreB >= victoryPoints) {
if (totalScoreA == totalScoreB) {
}
if (it.game.uid != lastGame?.uid) {
victoryDialogShown = false
lastGame = it.game
}
if (!victoryDialogShown) {
if (totalScoreA >= settings.victoryPoints || totalScoreB >= settings.victoryPoints) {
showVictoryDialog = true
}
}
}
}
}
@@ -193,6 +203,12 @@ class CounterViewModel @Inject constructor(
buildTeamNameSuggestions()
}
}
settings.registerOnChangeListener(this)
}
override fun onCleared() {
settings.unregisterOnChangeListener(this)
}
override fun focusLastInput() {
@@ -301,6 +317,17 @@ class CounterViewModel @Inject constructor(
}
}
override fun victoryDialogExecuted(result: Boolean) {
showVictoryDialog = false
victoryDialogShown = true
if (result) {
viewModelScope.launch {
gameRepository.newGame()
}
}
}
override fun updateFocusStateA(state: Boolean) {
isAFocused = state
if (state) {
@@ -341,10 +368,6 @@ class CounterViewModel @Inject constructor(
}
}
override fun onVictoryPointsChanged(victoryPoints: Int) {
this.victoryPoints = victoryPoints
}
private fun deleteLastDigitActive() {
if (activeValue != "") {
activeValue = activeValue.dropLast(1)
@@ -378,4 +401,8 @@ class CounterViewModel @Inject constructor(
return filtered.sorted().sortedBy { it.length }.take(10)
}
override fun onVictoryPointsChanged(victoryPoints: Int) {
victoryDialogShown = false
}
}

View File

@@ -12,7 +12,7 @@
<string name="menu_settings">Einstellungen</string>
<string name="on">Ein</string>
<string name="off">Aus</string>
<string name="newGame">Neues Spiel</string>
<string name="new_game">Neues Spiel</string>
<string name="delete_inactive_title">Verlauf löschen</string>
<string name="delete_inactive_text">Wirklich den gesamten Verlauf löschen? Diese Aktion kann nicht rückgängig gemacht werden.</string>
<string name="cancel">Abbrechen</string>
@@ -32,4 +32,8 @@
<string name="display">Anzeige</string>
<string name="game">Spiel</string>
<string name="victory_points">Siegespunkte</string>
<string name="victory_title">%1$s hat gewonnen</string>
<string name="draw_message">Sieht aus, als ob ihr ein neues Spiel starten solltet, um das endgültig zu klären.</string>
<string name="draw_title">Unentschieden</string>
<string name="victory_message">Herzliche Gratulation! Wie wäre es mit einer Revanche?</string>
</resources>

View File

@@ -15,7 +15,7 @@
<string name="menu_settings">Settings</string>
<string name="on">On</string>
<string name="off">Off</string>
<string name="newGame">New Game</string>
<string name="new_game">New Game</string>
<string name="delete_inactive_title">Delete history</string>
<string name="delete_inactive_text">You really want to delete the history? This action can\'t be undone.</string>
<string name="cancel">Cancel</string>
@@ -28,7 +28,7 @@
<string name="menu_about">About</string>
<string name="contact_us">Contact us</string>
<string name="play_store" translatable="false">Play Store</string>
<string name="continue_play">Continue</string>
<string name="continue_play">Continue game</string>
<string name="delete_success">Game deleted.</string>
<string name="undo_question">UNDO</string>
<string name="activated_success">Game activated.</string>
@@ -36,4 +36,8 @@
<string name="display">Display</string>
<string name="game">Game</string>
<string name="victory_points">Victory points</string>
<string name="victory_title">%1$s won the game</string>
<string name="draw_message">Looks like you should start a new game to settle this for good.</string>
<string name="draw_title">Draw</string>
<string name="victory_message">Congratulations! How about a rematch?</string>
</resources>