Add delete all history with confirm dialog.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -15,7 +15,6 @@ import androidx.compose.ui.graphics.vector.ImageVector
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.window.Dialog
|
|
||||||
import androidx.navigation.NavDestination.Companion.hierarchy
|
import androidx.navigation.NavDestination.Companion.hierarchy
|
||||||
import androidx.navigation.NavGraph.Companion.findStartDestination
|
import androidx.navigation.NavGraph.Companion.findStartDestination
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
@@ -115,8 +114,23 @@ class MainActivity : BaseActivity() {
|
|||||||
NavigationAction { scope.launch { drawerState.open() } }
|
NavigationAction { scope.launch { drawerState.open() } }
|
||||||
}
|
}
|
||||||
composable("history") {
|
composable("history") {
|
||||||
HistoryList(historyViewModel) { navController.navigate("counter") }
|
|
||||||
mainViewModel.topBarActions = emptyList()
|
var openDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
HistoryList(historyViewModel, openDialog, { deleteAll ->
|
||||||
|
if (deleteAll) {
|
||||||
|
mainViewModel.deleteAllInactiveGames()
|
||||||
|
}
|
||||||
|
openDialog = false
|
||||||
|
}) { navController.navigate("counter") }
|
||||||
|
mainViewModel.topBarActions = listOf(
|
||||||
|
TopBarAction(
|
||||||
|
Icons.Outlined.DeleteForever,
|
||||||
|
true
|
||||||
|
) {
|
||||||
|
openDialog = true
|
||||||
|
}
|
||||||
|
)
|
||||||
mainViewModel.topBarIcon = Icons.Outlined.ArrowBack
|
mainViewModel.topBarIcon = Icons.Outlined.ArrowBack
|
||||||
mainViewModel.topBarTitle = stringResource(R.string.menu_history)
|
mainViewModel.topBarTitle = stringResource(R.string.menu_history)
|
||||||
mainViewModel.topBarNavigationAction =
|
mainViewModel.topBarNavigationAction =
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
@Dao
|
@Dao
|
||||||
interface RoundDao : DaoBase<Round> {
|
interface RoundDao : DaoBase<Round> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM round")
|
||||||
|
fun getAll(): List<Round>
|
||||||
|
|
||||||
@Query("SELECT * FROM round WHERE gameId is :gameId")
|
@Query("SELECT * FROM round WHERE gameId is :gameId")
|
||||||
fun getAllForGame(gameId: Long?): List<Round>
|
fun getAllForGame(gameId: Long?): List<Round>
|
||||||
|
|
||||||
|
|||||||
@@ -99,4 +99,21 @@ class GameRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun deleteAllInactive() {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
gameDao.getAll().take(1).collect() { games ->
|
||||||
|
|
||||||
|
val activeId = games.first { it.active }.uid
|
||||||
|
val gamesToDelete = games.filter { !it.active }
|
||||||
|
val roundsToDelete = roundDao.getAll().filter { it.gameId != activeId }
|
||||||
|
|
||||||
|
gameDao.delete(gamesToDelete)
|
||||||
|
roundDao.delete(roundsToDelete)
|
||||||
|
}
|
||||||
|
} catch (_: NullPointerException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -83,4 +83,10 @@ class MainViewModel @Inject constructor(
|
|||||||
gameRepository.newGame()
|
gameRepository.newGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun deleteAllInactiveGames() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
gameRepository.deleteAllInactive()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -170,10 +170,9 @@ fun KeyboardTextButton(text: String, onClicked: () -> Unit) {
|
|||||||
|
|
||||||
val screenWidth = configuration.screenWidthDp.dp
|
val screenWidth = configuration.screenWidthDp.dp
|
||||||
|
|
||||||
val style = if(screenWidth < 350.dp)
|
val style = if (screenWidth < 350.dp) {
|
||||||
{
|
MaterialTheme.typography.labelSmall
|
||||||
MaterialTheme.typography.labelSmall
|
} else {
|
||||||
}else {
|
|
||||||
MaterialTheme.typography.labelLarge
|
MaterialTheme.typography.labelLarge
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ fun TeamNamesView(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
val color = TextFieldDefaults.textFieldColors(
|
val color = TextFieldDefaults.textFieldColors(
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp))
|
containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)
|
||||||
|
)
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
TextField(
|
TextField(
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.Delete
|
import androidx.compose.material.icons.outlined.Delete
|
||||||
import androidx.compose.material.icons.outlined.DeleteForever
|
|
||||||
import androidx.compose.material.icons.outlined.OpenInFull
|
import androidx.compose.material.icons.outlined.OpenInFull
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -22,19 +21,54 @@ import java.util.*
|
|||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryList(viewModel: HistoryViewModel, navigateToCalculator: () -> Unit) {
|
fun HistoryList(
|
||||||
|
viewModel: HistoryViewModel,
|
||||||
|
showDeleteDialog: Boolean,
|
||||||
|
onDialogExecuted: (Boolean) -> Unit,
|
||||||
|
navigateToCalculator: () -> Unit
|
||||||
|
) {
|
||||||
|
|
||||||
|
DeleteConfirmDialog(showDeleteDialog, onDialogExecuted)
|
||||||
|
|
||||||
HistoryList(viewModel.gameAndHistory,
|
HistoryList(viewModel.gameAndHistory,
|
||||||
{
|
{
|
||||||
viewModel.activateGame(it)
|
viewModel.activateGame(it)
|
||||||
navigateToCalculator()
|
navigateToCalculator()
|
||||||
},
|
},
|
||||||
{viewModel.deleteGame(it)})
|
{ viewModel.deleteGame(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun DeleteConfirmDialog(show: Boolean = true, onExecuted: (Boolean) -> Unit = {}) {
|
||||||
|
if (show) {
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = { onExecuted(false) },
|
||||||
|
dismissButton = {
|
||||||
|
TextButton({ onExecuted(false) })
|
||||||
|
{
|
||||||
|
Text(stringResource(R.string.cancel))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
TextButton({ onExecuted(true) })
|
||||||
|
{
|
||||||
|
Text(stringResource(R.string.ok))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = { Text(stringResource(R.string.delete_inactive_title)) },
|
||||||
|
text = { Text(stringResource(R.string.delete_inactive_text)) },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HistoryList(games: List<GameAndScore>,
|
fun HistoryList(
|
||||||
onOpenClicked: (GameId: Long) -> Unit,
|
games: List<GameAndScore>,
|
||||||
onDeleteClicked: (GameId: Long) -> Unit) {
|
onOpenClicked: (GameId: Long) -> Unit,
|
||||||
|
onDeleteClicked: (GameId: Long) -> Unit
|
||||||
|
) {
|
||||||
Row {
|
Row {
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
items(games) {
|
items(games) {
|
||||||
@@ -48,17 +82,16 @@ fun HistoryList(games: List<GameAndScore>,
|
|||||||
fun HistoryListItem(
|
fun HistoryListItem(
|
||||||
game: GameAndScore,
|
game: GameAndScore,
|
||||||
onOpenClicked: (GameId: Long) -> Unit,
|
onOpenClicked: (GameId: Long) -> Unit,
|
||||||
onDeleteClicked: (GameId: Long) -> Unit) {
|
onDeleteClicked: (GameId: Long) -> Unit
|
||||||
|
) {
|
||||||
val format =
|
val format =
|
||||||
DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault())
|
DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault())
|
||||||
|
|
||||||
|
|
||||||
val cardColor = if(game.active)
|
val cardColor = if (game.active) {
|
||||||
{
|
|
||||||
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer)
|
CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer)
|
||||||
|
|
||||||
} else
|
} else {
|
||||||
{
|
|
||||||
CardDefaults.cardColors()
|
CardDefaults.cardColors()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,8 +103,9 @@ fun HistoryListItem(
|
|||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
Modifier
|
Modifier
|
||||||
.padding(all = 12.dp)){
|
.padding(all = 12.dp)
|
||||||
Column(Modifier.weight(4f)){
|
) {
|
||||||
|
Column(Modifier.weight(4f)) {
|
||||||
Text(
|
Text(
|
||||||
text = game.nameA + " vs " + game.nameB,
|
text = game.nameA + " vs " + game.nameB,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
@@ -91,13 +125,15 @@ fun HistoryListItem(
|
|||||||
Column(
|
Column(
|
||||||
Modifier
|
Modifier
|
||||||
.wrapContentSize()
|
.wrapContentSize()
|
||||||
.width(70.dp)){
|
.width(70.dp)
|
||||||
|
) {
|
||||||
|
|
||||||
ElevatedButton(onClick = { onOpenClicked(game.gameId) }, enabled = true) {
|
ElevatedButton(onClick = { onOpenClicked(game.gameId) }, enabled = true) {
|
||||||
Icon(Icons.Outlined.OpenInFull, null)
|
Icon(Icons.Outlined.OpenInFull, null)
|
||||||
}
|
}
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onClick = { onDeleteClicked(game.gameId) }, enabled = !game.active ) {
|
onClick = { onDeleteClicked(game.gameId) }, enabled = !game.active
|
||||||
|
) {
|
||||||
Icon(Icons.Outlined.Delete, null)
|
Icon(Icons.Outlined.Delete, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,15 +30,13 @@ class HistoryViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteGame(gameId: Long)
|
fun deleteGame(gameId: Long) {
|
||||||
{
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
gameRepository.deleteGame(gameId)
|
gameRepository.deleteGame(gameId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun activateGame(gameId: Long)
|
fun activateGame(gameId: Long) {
|
||||||
{
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
gameRepository.setActive(gameId)
|
gameRepository.setActive(gameId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
<string name="newGame">Neues Spiel</string>
|
<string name="newGame">Neues Spiel</string>
|
||||||
<string name="created">"Erstellt: %s "</string>
|
<string name="created">"Erstellt: %s "</string>
|
||||||
<string name="modified">Bearbeitet: %s</string>
|
<string name="modified">Bearbeitet: %s</string>
|
||||||
<string name="delete_all">Alle löschen</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>
|
||||||
|
<string name="ok">Ok</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
@@ -18,5 +18,8 @@
|
|||||||
<string name="newGame">New Game</string>
|
<string name="newGame">New Game</string>
|
||||||
<string name="created">Created: %s</string>
|
<string name="created">Created: %s</string>
|
||||||
<string name="modified">Modified: %s</string>
|
<string name="modified">Modified: %s</string>
|
||||||
<string name="delete_all">Delete all</string>
|
<string name="delete_inactive_title">Delete history</string>
|
||||||
|
<string name="delete_inactive_text">You really want to delete the the history? This action can\'t be undone.</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
<string name="ok">Ok</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user