From f8d7702fcadfdafea24944ca4f5bfe86cb4fec11 Mon Sep 17 00:00:00 2001 From: Christian Basler Date: Tue, 29 Apr 2025 06:00:34 +0200 Subject: [PATCH] Add restart option --- .../drawable/action-restart.xml | 10 +++++++ .../kotlin/ch/dissem/yaep/ui/common/App.kt | 13 ++++---- .../dissem/yaep/ui/desktop/desktop window.kt | 30 +++++++++++++++++++ .../kotlin/ch/dissem/yaep/ui/desktop/main.kt | 20 +++++++++++-- .../kotlin/ch/dissem/yaep/domain/Game.kt | 1 + gradle/libs.versions.toml | 2 +- 6 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 commonUI/src/commonMain/composeResources/drawable/action-restart.xml diff --git a/commonUI/src/commonMain/composeResources/drawable/action-restart.xml b/commonUI/src/commonMain/composeResources/drawable/action-restart.xml new file mode 100644 index 0000000..0eb92ea --- /dev/null +++ b/commonUI/src/commonMain/composeResources/drawable/action-restart.xml @@ -0,0 +1,10 @@ + + + diff --git a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/App.kt b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/App.kt index 9ab4c0f..83033d9 100644 --- a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/App.kt +++ b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/App.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.TextUnitType import androidx.compose.ui.unit.dp import ch.dissem.yaep.domain.Clue +import ch.dissem.yaep.domain.Game import ch.dissem.yaep.domain.Grid import ch.dissem.yaep.domain.HorizontalClue import ch.dissem.yaep.domain.ItemClass @@ -39,7 +40,6 @@ import ch.dissem.yaep.domain.NeighbourClue import ch.dissem.yaep.domain.OrderClue import ch.dissem.yaep.domain.SameColumnClue import ch.dissem.yaep.domain.TripletClue -import ch.dissem.yaep.domain.generateGame import org.jetbrains.compose.resources.painterResource import yaep.commonui.generated.resources.Res import yaep.commonui.generated.resources.neighbour @@ -59,10 +59,9 @@ class DisplayClue(val clue: C) { } @Composable -fun App(modifier: Modifier = Modifier) { - var game by remember { mutableStateOf(generateGame()) } - val horizontalClues = remember(game) { game.horizontalClues.map { DisplayClue(it) } } - val verticalClues = remember(game) { game.verticalClues.map { DisplayClue(it) } } +fun App(modifier: Modifier = Modifier, game: Game, onNewGame: () -> Unit, resetCluesBeacon: Any = Any()) { + val horizontalClues = remember(game, resetCluesBeacon) { game.horizontalClues.map { DisplayClue(it) } } + val verticalClues = remember(game, resetCluesBeacon) { game.verticalClues.map { DisplayClue(it) } } val timer = remember(game) { GameTimer() } val time by timer.elapsedTime.collectAsState("00:00") var isSolved by remember(game) { mutableStateOf(false) } @@ -104,9 +103,7 @@ fun App(modifier: Modifier = Modifier) { Text(time, fontSize = TextUnit(4f, TextUnitType.Em)) } } - EndOfGame(isSolved = isSolved, time = time) { - game = generateGame() - } + EndOfGame(isSolved = isSolved, time = time, onRestart = onNewGame) } } diff --git a/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/desktop window.kt b/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/desktop window.kt index 08cce0a..4125aac 100644 --- a/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/desktop window.kt +++ b/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/desktop window.kt @@ -1,3 +1,5 @@ +package ch.dissem.yaep.ui.desktop + import androidx.compose.foundation.Image import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Spacer @@ -14,17 +16,25 @@ import androidx.compose.material3.SwitchDefaults import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.unit.dp import androidx.compose.ui.window.WindowPlacement import androidx.compose.ui.window.WindowScope import androidx.compose.ui.window.WindowState +import ch.dissem.yaep.domain.Game import ch.dissem.yaep.ui.common.theme.AppTheme import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource +import yaep.commonui.generated.resources.action_restart import yaep.commonui.generated.resources.app_name_full import yaep.commonui.generated.resources.moon +import yaep.commonui.generated.resources.restart import yaep.commonui.generated.resources.sun import yaep.commonui.generated.resources.window_close import yaep.commonui.generated.resources.window_maximize @@ -58,8 +68,17 @@ fun AppBar( useDarkMode: Boolean, setDarkMode: (Boolean) -> Unit, onCloseRequest: () -> Unit, + onRestart: () -> Unit, windowState: WindowState, + game: Game, ) { + var gameSolved by remember { mutableStateOf(false) } + LaunchedEffect(game) { + game.onSolved { + gameSolved = true + } + } + TopAppBar( navigationIcon = { Image( @@ -70,6 +89,16 @@ fun AppBar( }, title = { Text(text = stringResource(CRes.string.app_name_full)) }, actions = { + IconButton( + onClick = onRestart + ) { + Icon( + painter = painterResource(CRes.drawable.action_restart), + contentDescription = stringResource(CRes.string.restart), + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } + Spacer(Modifier.width(8.dp)) Switch( checked = useDarkMode, onCheckedChange = setDarkMode, @@ -98,6 +127,7 @@ fun AppBar( ) } IconButton( + enabled = !gameSolved, onClick = { windowState.placement = if (windowState.placement == WindowPlacement.Maximized) diff --git a/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/main.kt b/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/main.kt index d0e63c9..16aa1e3 100644 --- a/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/main.kt +++ b/desktop/src/main/kotlin/ch/dissem/yaep/ui/desktop/main.kt @@ -14,8 +14,12 @@ import androidx.compose.ui.window.Window import androidx.compose.ui.window.WindowPlacement import androidx.compose.ui.window.application import androidx.compose.ui.window.rememberWindowState +import ch.dissem.yaep.domain.Game +import ch.dissem.yaep.domain.generateGame import ch.dissem.yaep.ui.common.App import ch.dissem.yaep.ui.common.theme.emojiFontFamily +import ch.dissem.yaep.ui.desktop.AppBar +import ch.dissem.yaep.ui.desktop.DesktopWindow import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import yaep.commonui.generated.resources.app_name @@ -35,6 +39,7 @@ fun main() = application { placement = WindowPlacement.Floating, size = DpSize(1200.dp, 800.dp) ) + var game by remember { mutableStateOf(generateGame()) } Window( onCloseRequest = ::exitApplication, @@ -44,6 +49,7 @@ fun main() = application { icon = painterResource(DRes.drawable.ic_launcher) ) { var useDarkMode by remember { mutableStateOf(true) } + var resetCluesBeacon by remember { mutableStateOf(Any()) } DesktopWindow( useDarkMode = useDarkMode, topBar = { @@ -51,11 +57,21 @@ fun main() = application { useDarkMode = useDarkMode, setDarkMode = { useDarkMode = it }, onCloseRequest = ::exitApplication, - windowState = windowState + onRestart = { + do while (game.grid.undo()); + resetCluesBeacon = Any() + }, + windowState = windowState, + game = game, ) } ) { - App(modifier = Modifier.padding(it)) + App( + modifier = Modifier.padding(it), + game = game, + onNewGame = { game = generateGame() }, + resetCluesBeacon = resetCluesBeacon + ) } } } \ No newline at end of file diff --git a/domain/src/commonMain/kotlin/ch/dissem/yaep/domain/Game.kt b/domain/src/commonMain/kotlin/ch/dissem/yaep/domain/Game.kt index f309ca1..a7f4047 100644 --- a/domain/src/commonMain/kotlin/ch/dissem/yaep/domain/Game.kt +++ b/domain/src/commonMain/kotlin/ch/dissem/yaep/domain/Game.kt @@ -37,6 +37,7 @@ class Game( } } } + grid.snapshot() } fun onStart(listener: () -> Unit) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8099cf5..0b60412 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.9.0" +agp = "8.9.2" jdk = "21" android-compileSdk = "35" android-minSdk = "24"