From 63f6fca83f6cfe5d4c18667a430626b47e08f0be Mon Sep 17 00:00:00 2001 From: Christian Basler Date: Wed, 12 Mar 2025 07:52:02 +0100 Subject: [PATCH] Add restart --- .../kotlin/ch/dissem/yaep/ui/common/App.kt | 59 ++++++++++------- .../kotlin/ch/dissem/yaep/ui/common/end.kt | 65 +++++++++++++++++++ gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt 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 ec84291..99f245b 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 @@ -2,6 +2,7 @@ package ch.dissem.yaep.ui.common import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.aspectRatio @@ -30,7 +31,6 @@ 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 @@ -58,11 +58,13 @@ class DisplayClue(val clue: C) { } @Composable -fun App(modifier: Modifier = Modifier, game: Game = remember { generateGame() }) { +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) } } val timer = remember(game) { GameTimer() } val time by timer.elapsedTime.collectAsState("00:00") + var isSolved by remember(game) { mutableStateOf(false) } LaunchedEffect(game) { game.onStart { timer.start() @@ -70,31 +72,37 @@ fun App(modifier: Modifier = Modifier, game: Game = remember { generateGame() }) game.onSolved { timer.stop() + isSolved = true } } - Row(modifier = modifier) { - PuzzleGrid( - modifier = Modifier - .aspectRatio(1f) - .weight(0.6f) - .fillMaxHeight(), - grid = game.grid, - onUpdate = { - horizontalClues.forEach { it.update(game.grid) } - verticalClues.forEach { it.update(game.grid) } - } - ) - Column( - modifier = Modifier.padding(start = 16.dp).weight(0.4f).fillMaxHeight() - ) { - PuzzleClues( - modifier = Modifier, - horizontalClues, - verticalClues + Box(modifier = modifier) { + Row(modifier = Modifier.blurOnFinished(isSolved)) { + PuzzleGrid( + modifier = Modifier + .aspectRatio(1f) + .weight(0.6f) + .fillMaxHeight(), + grid = game.grid, + onUpdate = { + horizontalClues.forEach { it.update(game.grid) } + verticalClues.forEach { it.update(game.grid) } + } ) + Column( + modifier = Modifier.padding(start = 16.dp).weight(0.4f).fillMaxHeight() + ) { + PuzzleClues( + modifier = Modifier, + horizontalClues, + verticalClues + ) - Text(time, fontSize = TextUnit(4f, TextUnitType.Em)) + Text(time, fontSize = TextUnit(4f, TextUnitType.Em)) + } + } + EndOfGame(isSolved = isSolved) { + game = generateGame() } } } @@ -114,9 +122,10 @@ fun PuzzleGrid( ) { val allOptions = row.options for (item in row) { - var selection by remember { mutableStateOf(item.selection) } - val options = - remember { allOptions.map { Toggleable(it, item.options.contains(it)) } } + var selection by remember(item) { mutableStateOf(item.selection) } + val options = remember(item) { + allOptions.map { Toggleable(it, item.options.contains(it)) } + } LaunchedEffect(item) { item.optionsRemovedListeners.add { removed -> options diff --git a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt new file mode 100644 index 0000000..ed014d7 --- /dev/null +++ b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/end.kt @@ -0,0 +1,65 @@ +package ch.dissem.yaep.ui.common + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion.CenterHorizontally +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.graphics.BlurEffect +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.sp + +@Composable +fun EndOfGame( + modifier: Modifier = Modifier, + isSolved: Boolean, + onRestart: () -> Unit +) { + AnimatedVisibility( + visible = isSolved, + modifier = modifier, + enter = fadeIn(), + exit = fadeOut() + ) { + val background = MaterialTheme.colorScheme.background + Box(modifier = Modifier + .fillMaxSize() + .drawBehind { + drawRect(color = background.copy(alpha = 0.8f)) + } + ) { + Column( + modifier = Modifier + .align(Alignment.Center) + ) { + Text( + text = "You won", + fontSize = 128.sp, + textAlign = TextAlign.Center, + ) + Button( + modifier = Modifier.align(CenterHorizontally), + onClick = onRestart + ) { + Text("Restart") + } + } + } + } +} + +fun Modifier.blurOnFinished(isSolved: Boolean): Modifier = graphicsLayer { + if (isSolved) { + this.renderEffect = BlurEffect(8f, 8f) + } +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7fb09a0..8099cf5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.8.2" +agp = "8.9.0" jdk = "21" android-compileSdk = "35" android-minSdk = "24" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..e2847c8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME