Add restart option

This commit is contained in:
Christian Basler
2025-04-29 06:00:34 +02:00
parent d02043bbdb
commit f8d7702fca
6 changed files with 65 additions and 11 deletions

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFFFFF"
android:pathData="M360,840L303,784L367,720L360,720Q243,720 161.5,638.5Q80,557 80,440Q80,323 161.5,241.5Q243,160 360,160L600,160Q717,160 798.5,241.5Q880,323 880,440Q880,557 798.5,638.5Q717,720 600,720L600,640Q683,640 741.5,581.5Q800,523 800,440Q800,357 741.5,298.5Q683,240 600,240L360,240Q277,240 218.5,298.5Q160,357 160,440Q160,523 218.5,582.5Q277,642 360,648L376,648L304,576L360,520L520,680L360,840Z"/>
</vector>

View File

@@ -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<C : Clue>(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)
}
}

View File

@@ -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)

View File

@@ -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<Game>(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
)
}
}
}

View File

@@ -37,6 +37,7 @@ class Game(
}
}
}
grid.snapshot()
}
fun onStart(listener: () -> Unit) {

View File

@@ -1,5 +1,5 @@
[versions]
agp = "8.9.0"
agp = "8.9.2"
jdk = "21"
android-compileSdk = "35"
android-minSdk = "24"