diff --git a/android/gradle.properties b/android/gradle.properties index 5a0756cd02457428e3b8367e76eb2061b39f8a81..6da1d1a861ea19ee0ba4f1e97315cd050c8dae4f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.1.19 -app.versionCode=68 +app.versionName=0.1.20 +app.versionCode=69 diff --git a/assets/icons/button_delete_saved_game.png b/assets/icons/button_delete_saved_game.png new file mode 100644 index 0000000000000000000000000000000000000000..5e4f217689b11e444b7163557d7e5d68f3bbfe7d Binary files /dev/null and b/assets/icons/button_delete_saved_game.png differ diff --git a/assets/icons/button_resume_game.png b/assets/icons/button_resume_game.png new file mode 100644 index 0000000000000000000000000000000000000000..b2ea0a02d05e42377eb551a4b51428b511a32f5d Binary files /dev/null and b/assets/icons/button_resume_game.png differ diff --git a/fastlane/metadata/android/en-US/changelogs/69.txt b/fastlane/metadata/android/en-US/changelogs/69.txt new file mode 100644 index 0000000000000000000000000000000000000000..63b5271e68322c990d41af35e449e3990312eac0 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/69.txt @@ -0,0 +1 @@ +Restore delete/resume saved game. diff --git a/fastlane/metadata/android/fr-FR/changelogs/69.txt b/fastlane/metadata/android/fr-FR/changelogs/69.txt new file mode 100644 index 0000000000000000000000000000000000000000..72a200e97ec5a3573447cfd0bf4396c3cd5c063b --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/69.txt @@ -0,0 +1 @@ +Restauration de la suppression ou reprise de partie sauvegardée. diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh index 03cd74fc54841271f1cb1f54dfa5c00e75a2f8f6..e079a347ee2da4842772d4cb0d6f564cf98c191f 100755 --- a/icons/build_game_icons.sh +++ b/icons/build_game_icons.sh @@ -18,6 +18,8 @@ ICON_SIZE=192 AVAILABLE_GAME_IMAGES=" button_back button_start + button_resume_game + button_delete_saved_game button_help button_show_conflicts game_win diff --git a/icons/button_delete_saved_game.svg b/icons/button_delete_saved_game.svg new file mode 100644 index 0000000000000000000000000000000000000000..ac7eefef476f761903fe781b8c86d0c94323550a --- /dev/null +++ b/icons/button_delete_saved_game.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg> diff --git a/icons/button_resume_game.svg b/icons/button_resume_game.svg new file mode 100644 index 0000000000000000000000000000000000000000..6ad8b64202d0e70f898c16c520e756fe8a934add --- /dev/null +++ b/icons/button_resume_game.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m39.211 31.236c-0.84086-0.84489-2.9911-0.84489-2.9911 0v34.329c0 0.84594 2.1554 0.84594 2.9993 0l28.178-15.637c0.84392-0.84086 0.85812-2.2091 0.01623-3.053z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.1726"/><path d="m40.355 33.714c-0.71948-0.72294-2.5594-0.72294-2.5594 0v29.373c0 0.72383 1.8442 0.72383 2.5663 0l24.11-13.38c0.7221-0.71948 0.73426-1.8902 0.01389-2.6124z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.225"/><path d="m28.369 66.919v-37.591" fill="#105ca2" stroke="#105ca2" stroke-linecap="round" stroke-width="4.0337"/></svg> diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart index 3f29efd13c70c8999233870ff0f126f53f242461..bb663d00184762011ee4e39fe14579b9267aa461 100644 --- a/lib/cubit/game_cubit.dart +++ b/lib/cubit/game_cubit.dart @@ -34,6 +34,7 @@ class GameCubit extends HydratedCubit<GameState> { board: state.game.board, solvedBoard: state.game.solvedBoard, isRunning: state.game.isRunning, + isStarted: state.game.isStarted, isFinished: state.game.isFinished, blockSizeHorizontal: state.game.blockSizeHorizontal, blockSizeVertical: state.game.blockSizeVertical, @@ -86,6 +87,7 @@ class GameCubit extends HydratedCubit<GameState> { isFixed: false, ), ); + state.game.isStarted = true; refresh(); } @@ -125,6 +127,17 @@ class GameCubit extends HydratedCubit<GameState> { refresh(); } + void resumeSavedGame() { + state.game.isRunning = true; + refresh(); + } + + void deleteSavedGame() { + state.game.isRunning = false; + state.game.isFinished = true; + refresh(); + } + void updateAnimationInProgress(bool animationInProgress) { state.game.animationInProgress = animationInProgress; refresh(); diff --git a/lib/models/game.dart b/lib/models/game.dart index 3ae9cc9a96192c9e9d4b5d9444c7df3c434c5f5c..74bc3b486a2f34cf5a4ce781669bab65acf9583f 100644 --- a/lib/models/game.dart +++ b/lib/models/game.dart @@ -19,6 +19,7 @@ class Game { required this.board, required this.solvedBoard, required this.isRunning, + required this.isStarted, required this.isFinished, this.shuffledCellValues = const [], this.boardConflicts = const [], @@ -37,6 +38,7 @@ class Game { final GlobalSettings globalSettings; bool isRunning = false; + bool isStarted = false; bool isFinished = false; int blockSizeVertical = 0; @@ -65,6 +67,7 @@ class Game { solvedBoard: Board.createEmpty(), shuffledCellValues: [], isRunning: false, + isStarted: false, isFinished: false, givenTipsCount: 0, blockSizeHorizontal: 0, @@ -133,6 +136,7 @@ class Game { board: board, solvedBoard: solvedBoard, isRunning: true, + isStarted: false, isFinished: false, boardConflicts: nonConflictedBoard, shuffledCellValues: shuffledCellValues, @@ -384,6 +388,7 @@ class Game { printlog(' shuffledCellValues: $shuffledCellValues'); printlog(''); printlog(' isRunning: $isRunning'); + printlog(' isStarted: $isStarted'); printlog(' isFinished: $isFinished'); printlog(' selectedCell: ${selectedCell?.toString() ?? ''}'); printlog(' showConflicts: $showConflicts'); diff --git a/lib/ui/screens/screen_parameters.dart b/lib/ui/screens/screen_parameters.dart index fe20130eefec4ef76849c171ac5f18420c208826..ff6e2ab91e80f18f545a6f4fb1082d22afccec10 100644 --- a/lib/ui/screens/screen_parameters.dart +++ b/lib/ui/screens/screen_parameters.dart @@ -6,11 +6,15 @@ import 'package:sudoku/config/default_global_settings.dart'; import 'package:sudoku/cubit/settings_game_cubit.dart'; import 'package:sudoku/cubit/settings_global_cubit.dart'; import 'package:sudoku/ui/painters/parameter_painter.dart'; +import 'package:sudoku/ui/widgets/button_delete_saved_game.dart'; import 'package:sudoku/ui/widgets/button_game_start_new.dart'; +import 'package:sudoku/ui/widgets/button_resume_saved_game.dart'; import 'package:sudoku/ui/widgets/parameter_image.dart'; class ScreenParameters extends StatelessWidget { - const ScreenParameters({super.key}); + const ScreenParameters({super.key, required this.canResume}); + + final bool canResume; final double separatorHeight = 8.0; @@ -32,7 +36,13 @@ class ScreenParameters extends StatelessWidget { } lines.add(SizedBox(height: separatorHeight)); - lines.add(const Expanded(child: StartNewGameButton())); + lines.add(Expanded( + child: canResume ? const ResumeSavedGameButton() : const StartNewGameButton(), + )); + lines.add(SizedBox.square( + dimension: MediaQuery.of(context).size.width / 4, + child: canResume ? const DeleteSavedGameButton() : const SizedBox.shrink(), + )); lines.add(SizedBox(height: separatorHeight)); // Global settings diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart index 2b450cac224517da2565ca260b95b66744106e37..2bfdbfe6f159b9f9860953e89e3f027efb47461c 100644 --- a/lib/ui/skeleton.dart +++ b/lib/ui/skeleton.dart @@ -22,7 +22,11 @@ class SkeletonScreen extends StatelessWidget { ), child: BlocBuilder<GameCubit, GameState>( builder: (BuildContext context, GameState gameState) { - return gameState.game.isRunning ? const ScreenGame() : const ScreenParameters(); + return gameState.game.isRunning + ? const ScreenGame() + : ScreenParameters( + canResume: gameState.game.isStarted && !gameState.game.isFinished, + ); }, ), ), diff --git a/lib/ui/widgets/button_delete_saved_game.dart b/lib/ui/widgets/button_delete_saved_game.dart new file mode 100644 index 0000000000000000000000000000000000000000..fa18bcefd95d5d5dce7e8378e5e5c55b11fc0d67 --- /dev/null +++ b/lib/ui/widgets/button_delete_saved_game.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:sudoku/cubit/game_cubit.dart'; + +class DeleteSavedGameButton extends StatelessWidget { + const DeleteSavedGameButton({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + + return TextButton( + child: const Image( + image: AssetImage('assets/icons/button_delete_saved_game.png'), + fit: BoxFit.fill, + ), + onPressed: () { + gameCubit.deleteSavedGame(); + }, + ); + }, + ); + } +} diff --git a/lib/ui/widgets/button_resume_saved_game.dart b/lib/ui/widgets/button_resume_saved_game.dart new file mode 100644 index 0000000000000000000000000000000000000000..316a318410fc458937a964a5afdd13752cdff72e --- /dev/null +++ b/lib/ui/widgets/button_resume_saved_game.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:sudoku/cubit/game_cubit.dart'; + +class ResumeSavedGameButton extends StatelessWidget { + const ResumeSavedGameButton({super.key}); + + @override + Widget build(BuildContext context) { + return BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + + return TextButton( + child: const Image( + image: AssetImage('assets/icons/button_resume_game.png'), + fit: BoxFit.fill, + ), + onPressed: () { + gameCubit.resumeSavedGame(); + }, + ); + }, + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index 6c79d6b72d4e8694622522f0345e41bab3e78cca..fca46c759fa15b07e37ecd0e5bb5008cff7776fe 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A sudoku game application. publish_to: 'none' -version: 0.1.19+68 +version: 0.1.20+69 environment: sdk: '^3.0.0'