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"