Skip to content

Commit

Permalink
feat: added history and revert action
Browse files Browse the repository at this point in the history
  • Loading branch information
Gimbergsson committed Feb 25, 2025
1 parent caec6ee commit 28a3a3d
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ object Constants {

object Keys{
const val SCOREBOARD = "scoreboard"
const val SCOREBOARD_HISTORY = "scoreboard_history"
const val SCOREBOARD_UPDATE = "scoreboard_update"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package se.dennisgimbergsson.tennisscoreboard.repositories
import android.content.SharedPreferences
import com.google.gson.Gson
import kotlinx.coroutines.withContext
import se.dennisgimbergsson.shared.utils.Constants
import se.dennisgimbergsson.shared.utils.DispatcherProvider
import se.dennisgimbergsson.shared.data.models.Scoreboard
import se.dennisgimbergsson.shared.utils.Constants.Keys
import se.dennisgimbergsson.shared.utils.DispatcherProvider
import javax.inject.Inject

interface SharedPreferencesDataSource {
suspend fun putScoreboardData(scoreboard: Scoreboard): Boolean
suspend fun getScoreboardData(): Scoreboard

suspend fun putScoreboardHistoryData(scoreboardHistory: List<Scoreboard>): Boolean
suspend fun getScoreboardHistoryData(): List<Scoreboard>
}

class SharedPreferencesRepository @Inject constructor(
Expand All @@ -23,12 +26,30 @@ class SharedPreferencesRepository @Inject constructor(
scoreboard: Scoreboard,
) = withContext(dispatcherProvider.io()) {
sharedPreferences.edit()
.putString(Constants.Keys.SCOREBOARD, gson.toJson(scoreboard))
.putString(Keys.SCOREBOARD, gson.toJson(scoreboard))
.commit()
}

override suspend fun getScoreboardData() = withContext(dispatcherProvider.io()) {
val json = sharedPreferences.getString(Constants.Keys.SCOREBOARD, "") ?: ""
val json = sharedPreferences.getString(Keys.SCOREBOARD, "") ?: ""
gson.fromJson(json, Scoreboard::class.java) ?: Scoreboard()
}

override suspend fun putScoreboardHistoryData(scoreboardHistory: List<Scoreboard>) =
withContext(dispatcherProvider.io()) {
sharedPreferences.edit()
.putString(Keys.SCOREBOARD_HISTORY, gson.toJson(scoreboardHistory))
.commit()
}

override suspend fun getScoreboardHistoryData() = withContext(dispatcherProvider.io()) {
val json = sharedPreferences.getString(Keys.SCOREBOARD_HISTORY, DEFAULT_SCOREBOARD_HISTORY)
?: DEFAULT_SCOREBOARD_HISTORY
gson.fromJson(json, Array<Scoreboard>::class.java)?.toList() ?: emptyList()
}

companion object {
private const val DEFAULT_SCOREBOARD_HISTORY =
"[{\"awayScore\":{\"gameScore\":\"ZERO\",\"wonGames\":0,\"wonSets\":0},\"homeScore\":{\"gameScore\":\"ZERO\",\"wonGames\":0,\"wonSets\":0},\"peekDrawer\":false}]"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import dagger.hilt.android.AndroidEntryPoint
import se.dennisgimbergsson.shared.extensions.logWearMessage
import se.dennisgimbergsson.shared.utils.Constants
import se.dennisgimbergsson.tennisscoreboard.ui.theme.TennisScoreboardTheme
import se.dennisgimbergsson.tennisscoreboard.ui.views.ScoreboardView
import javax.inject.Inject
import se.dennisgimbergsson.tennisscoreboard.ui.views.MainView

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
Expand Down Expand Up @@ -51,7 +51,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
ScoreboardView(
MainView(
state = viewModel.stateFlow.collectAsStateWithLifecycle(
initialValue = MainViewState()
).value,
Expand All @@ -63,7 +63,8 @@ class MainActivity : ComponentActivity() {
viewModel.incrementAway()
increaseCounter()
},
clearAll = viewModel::clear,
revertLastScore = viewModel::popScoreboardHistory,
clearAll = viewModel::clearScoreboard,
decrementHome = viewModel::decrementHome,
decrementAway = viewModel::decrementAway,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import se.dennisgimbergsson.shared.data.models.Score
import se.dennisgimbergsson.shared.data.models.Scoreboard
import se.dennisgimbergsson.shared.enums.GameScores.ADVANTAGE
import se.dennisgimbergsson.shared.enums.GameScores.FIFTEEN
import se.dennisgimbergsson.shared.enums.GameScores.FORTY
Expand All @@ -28,11 +29,19 @@ class MainViewModel @Inject constructor(
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
saveScoreboard()
saveScoreboardHistory()
}

override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
loadScoreboard()
loadScoreboardHistory()
}

private fun saveScoreboard() = viewModelScope.launch {
sharedPreferencesRepository.putScoreboardData(
scoreboard = currentState().scoreboard
)
}

private fun loadScoreboard() = viewModelScope.launch {
Expand All @@ -42,15 +51,19 @@ class MainViewModel @Inject constructor(
}
}

private fun saveScoreboard() = viewModelScope.launch {
sharedPreferencesRepository.putScoreboardData(
scoreboard = currentState().scoreboard
)
}
private fun saveScoreboardHistory() =
viewModelScope.launch {
sharedPreferencesRepository.putScoreboardHistoryData(
scoreboardHistory = currentState().scoreboardHistory
)
}

)
}
private fun loadScoreboardHistory() = viewModelScope.launch {
val scoreboardHistory = sharedPreferencesRepository.getScoreboardHistoryData()
setState {
copy(scoreboardHistory = scoreboardHistory)
}
}

private fun calculateIncrementedScore(
team: Teams,
Expand Down Expand Up @@ -234,11 +247,15 @@ class MainViewModel @Inject constructor(
private fun incrementScore(team: Teams) =
calculateIncrementedScore(team = team) { homeScore, awayScore ->
viewModelScope.launchSetState {
val scoreboard = scoreboard.copy(
homeScore = homeScore,
awayScore = awayScore,
)
val scoreboardHistory = scoreboardHistory.toMutableList()
scoreboardHistory.add(scoreboard)
copy(
scoreboard = scoreboard.copy(
homeScore = homeScore,
awayScore = awayScore,
)
scoreboard = scoreboard,
scoreboardHistory = scoreboardHistory,
)
}
}
Expand All @@ -250,11 +267,15 @@ class MainViewModel @Inject constructor(
private fun decrementScore(team: Teams) =
calculateDecrementedScore(team = team) { homeScore, awayScore ->
viewModelScope.launchSetState {
val scoreboard = scoreboard.copy(
homeScore = homeScore,
awayScore = awayScore,
)
val scoreboardHistory = scoreboardHistory.toMutableList()
scoreboardHistory.add(scoreboard)
copy(
scoreboard = scoreboard.copy(
homeScore = homeScore,
awayScore = awayScore,
)
scoreboard = scoreboard,
scoreboardHistory = scoreboardHistory,
)
}
}
Expand Down Expand Up @@ -332,10 +353,25 @@ class MainViewModel @Inject constructor(
scoreboard = scoreboard.copy(
homeScore = Score(),
awayScore = Score(),
)
),
scoreboardHistory = listOf(Scoreboard()),
)
}

fun popScoreboardHistory() = viewModelScope.launch {
val scoreboardHistory = currentState().scoreboardHistory
if (scoreboardHistory.isEmpty() || scoreboardHistory.size == 1) return@launch

val newScoreboardHistory = scoreboardHistory.dropLast(1)

setState {
copy(
scoreboard = newScoreboardHistory.last(),
scoreboardHistory = newScoreboardHistory,
)
}
}

companion object {
private const val TAG = "MainViewModel"
const val MOCK_ARG = "mock_arg"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ import se.dennisgimbergsson.shared.data.models.Scoreboard
@Immutable
data class MainViewState(
val scoreboard: Scoreboard = Scoreboard(),
val scoreboardHistory: List<Scoreboard> = listOf(Scoreboard()),
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.content.res.Configuration
import androidx.compose.foundation.focusable
import androidx.compose.foundation.gestures.scrollBy
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
Expand Down Expand Up @@ -43,11 +42,12 @@ import se.dennisgimbergsson.tennisscoreboard.ui.screens.MainViewState
import se.dennisgimbergsson.tennisscoreboard.ui.theme.TennisScoreboardTheme

@Composable
fun ScoreboardView(
fun MainView(
modifier: Modifier = Modifier,
state: MainViewState,
incrementHomeScore: () -> Unit = {},
incrementAwayScore: () -> Unit = {},
revertLastScore: () -> Unit = {},
clearAll: () -> Unit = {},
decrementHome: () -> Unit = {},
decrementAway: () -> Unit = {},
Expand Down Expand Up @@ -91,45 +91,57 @@ fun ScoreboardView(
)
}
item {
Column(
modifier = Modifier
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.SpaceBetween
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { revertLastScore() }
) {
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { decrementHome() }
) {
Text(
modifier = Modifier.padding(0.dp),
text = stringResource(id = R.string.decrement_home_score),
textAlign = TextAlign.Center,
)
}
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { decrementAway() }
) {
Text(
text = stringResource(id = R.string.decrement_away_score),
textAlign = TextAlign.Center,
)
}
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { clearAll() }
) {
Text(
text = stringResource(id = R.string.clear_all_score),
textAlign = TextAlign.Center,
)
}
Text(
modifier = Modifier.padding(0.dp),
text = stringResource(id = R.string.revert_last_score),
textAlign = TextAlign.Center,
)
}
}
item {
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { decrementHome() }
) {
Text(
modifier = Modifier.padding(0.dp),
text = stringResource(id = R.string.decrement_home_score),
textAlign = TextAlign.Center,
)
}
}
item {
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { decrementAway() }
) {
Text(
text = stringResource(id = R.string.decrement_away_score),
textAlign = TextAlign.Center,
)
}
}
item {
Button(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(5.dp),
contentPadding = PaddingValues(0.dp),
onClick = { clearAll() }
) {
Text(
text = stringResource(id = R.string.clear_all_score),
textAlign = TextAlign.Center,
)
}
}
item {
Expand Down
2 changes: 1 addition & 1 deletion wearos/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<string name="score_30">30</string>
<string name="score_15">15</string>
<string name="score_advantage">Adv.</string>

<string name="revert_last_score">Revert last score</string>
<string name="decrement_home_score">Decrement home</string>
<string name="decrement_away_score">Decrement away</string>
<string name="clear_all_score">Clear all</string>
Expand Down

0 comments on commit 28a3a3d

Please sign in to comment.