From e50ca462f959de89c5d0c133b723650ed70631fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr> Date: Fri, 5 Apr 2024 22:26:26 +0200 Subject: [PATCH] Improve layout --- android/gradle.properties | 4 +- .../metadata/android/en-US/changelogs/30.txt | 1 + .../metadata/android/fr-FR/changelogs/30.txt | 1 + lib/ui/screens/game.dart | 13 ++-- lib/ui/widgets/game_top_indicator.dart | 61 +++++-------------- lib/ui/widgets/global_app_bar.dart | 2 +- lib/ui/widgets/{ => helpers}/app_titles.dart | 0 .../widgets/helpers/outlined_text_widget.dart | 49 +++++++++++++++ .../indicator_available_blocks.dart | 51 ++++++++++++++++ .../indicators/indicator_moves_count.dart | 24 ++++++++ .../widgets/indicators/indicator_score.dart | 24 ++++++++ .../indicators/indicator_shuffle_button.dart | 32 ++++++++++ lib/ui/widgets/parameters.dart | 34 ++--------- pubspec.lock | 28 +++------ pubspec.yaml | 3 +- 15 files changed, 221 insertions(+), 106 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/30.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/30.txt rename lib/ui/widgets/{ => helpers}/app_titles.dart (100%) create mode 100644 lib/ui/widgets/helpers/outlined_text_widget.dart create mode 100644 lib/ui/widgets/indicators/indicator_available_blocks.dart create mode 100644 lib/ui/widgets/indicators/indicator_moves_count.dart create mode 100644 lib/ui/widgets/indicators/indicator_score.dart create mode 100644 lib/ui/widgets/indicators/indicator_shuffle_button.dart diff --git a/android/gradle.properties b/android/gradle.properties index d965699..cc4e56e 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.0.29 -app.versionCode=29 +app.versionName=0.0.30 +app.versionCode=30 diff --git a/fastlane/metadata/android/en-US/changelogs/30.txt b/fastlane/metadata/android/en-US/changelogs/30.txt new file mode 100644 index 0000000..1c6fefb --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/30.txt @@ -0,0 +1 @@ +Improve layout and design. diff --git a/fastlane/metadata/android/fr-FR/changelogs/30.txt b/fastlane/metadata/android/fr-FR/changelogs/30.txt new file mode 100644 index 0000000..3a1b67c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/30.txt @@ -0,0 +1 @@ +Amélioration des graphismes. diff --git a/lib/ui/screens/game.dart b/lib/ui/screens/game.dart index 8877778..5f56240 100644 --- a/lib/ui/screens/game.dart +++ b/lib/ui/screens/game.dart @@ -12,15 +12,10 @@ class ScreenGame extends StatelessWidget { Widget build(BuildContext context) { return Material( color: Theme.of(context).colorScheme.background, - child: Column( - children: <Widget>[ - const SizedBox(height: 8), - BlocBuilder<GameCubit, GameState>( - builder: (BuildContext context, GameState gameState) { - return gameState.currentGame.isRunning ? const GameWidget() : const Parameters(); - }, - ), - ], + child: BlocBuilder<GameCubit, GameState>( + builder: (BuildContext context, GameState gameState) { + return gameState.currentGame.isRunning ? const GameWidget() : const Parameters(); + }, ), ); } diff --git a/lib/ui/widgets/game_top_indicator.dart b/lib/ui/widgets/game_top_indicator.dart index bdbbc85..3d639b7 100644 --- a/lib/ui/widgets/game_top_indicator.dart +++ b/lib/ui/widgets/game_top_indicator.dart @@ -1,70 +1,39 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:unicons/unicons.dart'; import 'package:jeweled/cubit/game_cubit.dart'; import 'package:jeweled/models/game.dart'; +import 'package:jeweled/ui/widgets/indicators/indicator_available_blocks.dart'; +import 'package:jeweled/ui/widgets/indicators/indicator_moves_count.dart'; +import 'package:jeweled/ui/widgets/indicators/indicator_score.dart'; +import 'package:jeweled/ui/widgets/indicators/indicator_shuffle_button.dart'; class GameTopIndicatorWidget extends StatelessWidget { const GameTopIndicatorWidget({super.key}); @override Widget build(BuildContext context) { - const Color scoreTextColor = Colors.white; - const Color movesCountTextColor = Colors.grey; - const Color availableBlocksCountTextColor = Colors.green; - - const double scoreFontSize = 40; - const double movesCountFontSize = 15; - const double availableBlocksCountFontSize = 20; - return BlocBuilder<GameCubit, GameState>( builder: (BuildContext context, GameState gameState) { final Game currentGame = gameState.currentGame; - return Table( + return Column( children: [ - TableRow( + ScoreIndicator(game: currentGame), + Table( + defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: [ - Column( + TableRow( children: [ - Text( - currentGame.score.toString(), - style: const TextStyle( - fontSize: scoreFontSize, - fontWeight: FontWeight.w600, - color: scoreTextColor, - ), - ), - Text( - currentGame.movesCount.toString(), - style: const TextStyle( - fontSize: movesCountFontSize, - fontWeight: FontWeight.w600, - color: movesCountTextColor, - ), + Center( + child: MovesCountsIndicator(game: currentGame), ), - ], - ), - Column( - children: [ - Text( - currentGame.availableBlocksCount.toString(), - style: const TextStyle( - fontSize: availableBlocksCountFontSize, - fontWeight: FontWeight.w600, - color: availableBlocksCountTextColor, - ), + AvailableBlocksCountIndicator(game: currentGame), + Center( + child: ShuffleButton(game: currentGame), ), - TextButton( - child: const Icon(UniconsSolid.refresh), - onPressed: () { - final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); - gameCubit.shuffleColors(currentGame.globalSettings.colorsTheme); - }, - ) ], - ), + ) ], ), ], diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart index 58905ec..1d425fb 100644 --- a/lib/ui/widgets/global_app_bar.dart +++ b/lib/ui/widgets/global_app_bar.dart @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:jeweled/cubit/game_cubit.dart'; import 'package:jeweled/models/game.dart'; -import 'package:jeweled/ui/widgets/app_titles.dart'; +import 'package:jeweled/ui/widgets/helpers/app_titles.dart'; class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget { const GlobalAppBar({super.key}); diff --git a/lib/ui/widgets/app_titles.dart b/lib/ui/widgets/helpers/app_titles.dart similarity index 100% rename from lib/ui/widgets/app_titles.dart rename to lib/ui/widgets/helpers/app_titles.dart diff --git a/lib/ui/widgets/helpers/outlined_text_widget.dart b/lib/ui/widgets/helpers/outlined_text_widget.dart new file mode 100644 index 0000000..8e33709 --- /dev/null +++ b/lib/ui/widgets/helpers/outlined_text_widget.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +class OutlinedText extends StatelessWidget { + const OutlinedText({ + super.key, + required this.text, + required this.fontSize, + required this.textColor, + required this.outlineColor, + }); + + final String text; + final double fontSize; + final Color textColor; + final Color outlineColor; + + @override + Widget build(BuildContext context) { + final double delta = fontSize / 35; + + return Text( + text, + style: TextStyle( + inherit: true, + fontSize: fontSize, + fontWeight: FontWeight.w600, + color: textColor, + shadows: [ + Shadow( + offset: Offset(-delta, -delta), + color: outlineColor, + ), + Shadow( + offset: Offset(delta, -delta), + color: outlineColor, + ), + Shadow( + offset: Offset(delta, delta), + color: outlineColor, + ), + Shadow( + offset: Offset(-delta, delta), + color: outlineColor, + ), + ], + ), + ); + } +} diff --git a/lib/ui/widgets/indicators/indicator_available_blocks.dart b/lib/ui/widgets/indicators/indicator_available_blocks.dart new file mode 100644 index 0000000..865b933 --- /dev/null +++ b/lib/ui/widgets/indicators/indicator_available_blocks.dart @@ -0,0 +1,51 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; + +import 'package:jeweled/models/game.dart'; +import 'package:jeweled/ui/widgets/helpers/outlined_text_widget.dart'; +import 'package:jeweled/utils/color_extensions.dart'; + +class AvailableBlocksCountIndicator extends StatelessWidget { + const AvailableBlocksCountIndicator({super.key, required this.game}); + + final Game game; + + @override + Widget build(BuildContext context) { + // Minimum available blocks count value to fill bar + const minBlocksCount = 6; + + // Normalized [0..1] value + final double barValue = min(minBlocksCount, game.availableBlocksCount) / minBlocksCount; + + // Bar color: red < orange < green + final Color baseColor = (barValue < 0.5 + ? Color.lerp(Colors.red, Colors.orange, barValue * 2) + : Color.lerp(Colors.orange, Colors.green, (barValue - 0.5) * 2)) ?? + Colors.grey; + + const barHeight = 25.0; + const Color textColor = Color.fromARGB(255, 238, 238, 238); + const Color outlineColor = Color.fromARGB(255, 200, 200, 200); + + return Stack( + alignment: Alignment.center, + children: [ + LinearProgressIndicator( + value: barValue, + color: baseColor, + backgroundColor: baseColor.darken(), + minHeight: barHeight, + borderRadius: const BorderRadius.all(Radius.circular(15)), + ), + OutlinedText( + text: game.availableBlocksCount.toString(), + fontSize: barHeight, + textColor: textColor, + outlineColor: outlineColor, + ), + ], + ); + } +} diff --git a/lib/ui/widgets/indicators/indicator_moves_count.dart b/lib/ui/widgets/indicators/indicator_moves_count.dart new file mode 100644 index 0000000..f6ebaa8 --- /dev/null +++ b/lib/ui/widgets/indicators/indicator_moves_count.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +import 'package:jeweled/models/game.dart'; +import 'package:jeweled/ui/widgets/helpers/outlined_text_widget.dart'; +import 'package:jeweled/utils/color_extensions.dart'; + +class MovesCountsIndicator extends StatelessWidget { + const MovesCountsIndicator({super.key, required this.game}); + + final Game game; + + @override + Widget build(BuildContext context) { + const Color baseColor = Color.fromARGB(255, 215, 1, 133); + final Color outlineColor = baseColor.darken(); + + return OutlinedText( + text: game.movesCount.toString(), + fontSize: 40, + textColor: baseColor, + outlineColor: outlineColor, + ); + } +} diff --git a/lib/ui/widgets/indicators/indicator_score.dart b/lib/ui/widgets/indicators/indicator_score.dart new file mode 100644 index 0000000..6f7dc83 --- /dev/null +++ b/lib/ui/widgets/indicators/indicator_score.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; + +import 'package:jeweled/models/game.dart'; +import 'package:jeweled/ui/widgets/helpers/outlined_text_widget.dart'; +import 'package:jeweled/utils/color_extensions.dart'; + +class ScoreIndicator extends StatelessWidget { + const ScoreIndicator({super.key, required this.game}); + + final Game game; + + @override + Widget build(BuildContext context) { + const Color baseColor = Color.fromARGB(255, 218, 218, 218); + final Color outlineColor = baseColor.darken(); + + return OutlinedText( + text: game.score.toString(), + fontSize: 70, + textColor: baseColor, + outlineColor: outlineColor, + ); + } +} diff --git a/lib/ui/widgets/indicators/indicator_shuffle_button.dart b/lib/ui/widgets/indicators/indicator_shuffle_button.dart new file mode 100644 index 0000000..5688bf1 --- /dev/null +++ b/lib/ui/widgets/indicators/indicator_shuffle_button.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'package:jeweled/cubit/game_cubit.dart'; +import 'package:jeweled/models/game.dart'; +import 'package:jeweled/ui/widgets/helpers/outlined_text_widget.dart'; +import 'package:jeweled/utils/color_extensions.dart'; + +class ShuffleButton extends StatelessWidget { + const ShuffleButton({super.key, required this.game}); + + final Game game; + + @override + Widget build(BuildContext context) { + const Color textColor = Color.fromARGB(255, 215, 1, 133); + final Color outlineColor = textColor.darken(); + + return TextButton( + child: OutlinedText( + text: '🔄', + fontSize: 25, + textColor: textColor, + outlineColor: outlineColor, + ), + onPressed: () { + final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); + gameCubit.shuffleColors(game.globalSettings.colorsTheme); + }, + ); + } +} diff --git a/lib/ui/widgets/parameters.dart b/lib/ui/widgets/parameters.dart index 21cc610..c8f858a 100644 --- a/lib/ui/widgets/parameters.dart +++ b/lib/ui/widgets/parameters.dart @@ -92,7 +92,7 @@ class Parameters extends StatelessWidget { } lines.add(SizedBox(height: separatorHeight)); - lines.add(buildStartNewGameButton()); + lines.add(Expanded(child: buildStartNewGameButton())); lines.add(SizedBox(height: separatorHeight)); // Global settings @@ -138,39 +138,17 @@ class Parameters extends StatelessWidget { } static Widget buildStartNewGameButton() { - const double blockMargin = 3.0; - const double blockPadding = 2.0; - return BlocBuilder<GameSettingsCubit, GameSettingsState>( builder: (BuildContext context, GameSettingsState gameSettingsState) { return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>( builder: (BuildContext context, GlobalSettingsState globalSettingsState) { final GameCubit gameCubit = BlocProvider.of<GameCubit>(context); - return Container( - margin: const EdgeInsets.all(blockMargin), - padding: const EdgeInsets.all(blockPadding), - child: Table( - defaultColumnWidth: const IntrinsicColumnWidth(), - children: [ - TableRow( - children: [ - buildDecorationImageWidget(), - Column( - children: [ - TextButton( - child: buildImageContainerWidget('button_start'), - onPressed: () => gameCubit.startNewGame( - gameSettings: gameSettingsState.settings, - globalSettings: globalSettingsState.settings, - ), - ), - ], - ), - buildDecorationImageWidget(), - ], - ), - ], + return TextButton( + child: buildImageContainerWidget('button_start'), + onPressed: () => gameCubit.startNewGame( + gameSettings: gameSettingsState.settings, + globalSettings: globalSettingsState.settings, ), ); }, diff --git a/pubspec.lock b/pubspec.lock index f689e87..47304c5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: bloc - sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" url: "https://pub.dev" source: hosted - version: "8.1.3" + version: "8.1.4" characters: dependency: transitive description: @@ -98,18 +98,18 @@ packages: dependency: "direct main" description: name: flutter_bloc - sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1" + sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2 url: "https://pub.dev" source: hosted - version: "8.1.4" + version: "8.1.5" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7 + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.2" flutter_localizations: dependency: transitive description: flutter @@ -132,10 +132,10 @@ packages: dependency: "direct main" description: name: hydrated_bloc - sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d" + sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c url: "https://pub.dev" source: hosted - version: "9.1.4" + version: "9.1.5" intl: dependency: transitive description: @@ -333,14 +333,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" - unicons: - dependency: "direct main" - description: - name: unicons - sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670 - url: "https://pub.dev" - source: hosted - version: "2.1.1" vector_math: dependency: transitive description: @@ -361,10 +353,10 @@ packages: dependency: transitive description: name: win32 - sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" url: "https://pub.dev" source: hosted - version: "5.2.0" + version: "5.4.0" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 4f9bb6c..a11b99e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Jeweled Game publish_to: 'none' -version: 0.0.29+29 +version: 0.0.30+30 environment: sdk: '^3.0.0' @@ -17,7 +17,6 @@ dependencies: hive: ^2.2.3 hydrated_bloc: ^9.0.0 path_provider: ^2.0.11 - unicons: ^2.1.1 dev_dependencies: flutter_lints: ^3.0.1 -- GitLab