Merge pull request #125 from flixcoo/hotfix/124-hotfix-update-default-mode-logic

Hotfix: Update default mode logic
This commit is contained in:
2025-07-20 16:45:17 +02:00
committed by GitHub
9 changed files with 118 additions and 100 deletions

View File

@@ -58,9 +58,9 @@
"no_name_message": "Jeder Spieler muss einen Namen haben.", "no_name_message": "Jeder Spieler muss einen Namen haben.",
"select_game_mode": "Spielmodus auswählen", "select_game_mode": "Spielmodus auswählen",
"no_mode_selected": "Kein Modus", "no_mode_selected": "Wähle einen Spielmodus",
"no_default_mode": "Kein Standard-Modus", "no_default_mode": "Kein Modus",
"no_default_description": "Der Standard-Modus wird zurückgesetzt.", "no_default_description": "Entscheide bei jedem Spiel selber, welchen Modus du spielen möchtest.",
"point_limit_description": "Es wird so lange gespielt, bis ein:e Spieler:in mehr als {pointLimit} Punkte erreicht", "point_limit_description": "Es wird so lange gespielt, bis ein:e Spieler:in mehr als {pointLimit} Punkte erreicht",
"@point_limit_description": { "@point_limit_description": {
"placeholders": { "placeholders": {

View File

@@ -377,19 +377,19 @@ abstract class AppLocalizations {
/// No description provided for @no_mode_selected. /// No description provided for @no_mode_selected.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
/// **'Kein Modus'** /// **'Wähle einen Spielmodus'**
String get no_mode_selected; String get no_mode_selected;
/// No description provided for @no_default_mode. /// No description provided for @no_default_mode.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
/// **'Kein Standard-Modus'** /// **'Kein Modus'**
String get no_default_mode; String get no_default_mode;
/// No description provided for @no_default_description. /// No description provided for @no_default_description.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
/// **'Der Standard-Modus wird zurückgesetzt.'** /// **'Entscheide bei jedem Spiel selber, welchen Modus du spielen möchtest.'**
String get no_default_description; String get no_default_description;
/// No description provided for @point_limit_description. /// No description provided for @point_limit_description.

View File

@@ -155,13 +155,14 @@ class AppLocalizationsDe extends AppLocalizations {
String get select_game_mode => 'Spielmodus auswählen'; String get select_game_mode => 'Spielmodus auswählen';
@override @override
String get no_mode_selected => 'Kein Modus'; String get no_mode_selected => 'Wähle einen Spielmodus';
@override @override
String get no_default_mode => 'Kein Standard-Modus'; String get no_default_mode => 'Kein Modus';
@override @override
String get no_default_description => 'Der Standard-Modus wird zurückgesetzt.'; String get no_default_description =>
'Entscheide bei jedem Spiel selber, welchen Modus du spielen möchtest.';
@override @override
String point_limit_description(int pointLimit) { String point_limit_description(int pointLimit) {

View File

@@ -4,6 +4,7 @@ import 'package:cabo_counter/data/game_session.dart';
import 'package:cabo_counter/l10n/generated/app_localizations.dart'; import 'package:cabo_counter/l10n/generated/app_localizations.dart';
import 'package:cabo_counter/presentation/views/create_game_view.dart'; import 'package:cabo_counter/presentation/views/create_game_view.dart';
import 'package:cabo_counter/presentation/views/graph_view.dart'; import 'package:cabo_counter/presentation/views/graph_view.dart';
import 'package:cabo_counter/presentation/views/mode_selection_view.dart';
import 'package:cabo_counter/presentation/views/points_view.dart'; import 'package:cabo_counter/presentation/views/points_view.dart';
import 'package:cabo_counter/presentation/views/round_view.dart'; import 'package:cabo_counter/presentation/views/round_view.dart';
import 'package:cabo_counter/services/local_storage_service.dart'; import 'package:cabo_counter/services/local_storage_service.dart';
@@ -205,9 +206,11 @@ class _ActiveGameViewState extends State<ActiveGameView> {
CupertinoPageRoute( CupertinoPageRoute(
builder: (_) => CreateGameView( builder: (_) => CreateGameView(
gameTitle: gameSession.gameTitle, gameTitle: gameSession.gameTitle,
isPointsLimitEnabled: widget gameMode: widget.gameSession
.gameSession .isPointsLimitEnabled ==
.isPointsLimitEnabled, true
? GameMode.pointLimit
: GameMode.unlimited,
players: gameSession.players, players: gameSession.players,
))); )));
}, },

View File

@@ -16,15 +16,15 @@ enum CreateStatus {
} }
class CreateGameView extends StatefulWidget { class CreateGameView extends StatefulWidget {
final GameMode gameMode;
final String? gameTitle; final String? gameTitle;
final bool? isPointsLimitEnabled;
final List<String>? players; final List<String>? players;
const CreateGameView({ const CreateGameView({
super.key, super.key,
this.gameTitle, this.gameTitle,
this.isPointsLimitEnabled,
this.players, this.players,
required this.gameMode,
}); });
@override @override
@@ -42,19 +42,14 @@ class _CreateGameViewState extends State<CreateGameView> {
/// Maximum number of players allowed in the game. /// Maximum number of players allowed in the game.
final int maxPlayers = 5; final int maxPlayers = 5;
/// Variable to store whether the points limit feature is enabled. /// Variable to hold the selected game mode.
bool? _isPointsLimitEnabled; late GameMode gameMode;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.isPointsLimitEnabled == null) { gameMode = widget.gameMode;
_isPointsLimitEnabled =
ConfigService.gameMode == -1 ? null : ConfigService.gameMode == 1;
} else {
_isPointsLimitEnabled = widget.isPointsLimitEnabled;
}
_gameTitleTextController.text = widget.gameTitle ?? ''; _gameTitleTextController.text = widget.gameTitle ?? '';
@@ -106,10 +101,10 @@ class _CreateGameViewState extends State<CreateGameView> {
suffix: Row( suffix: Row(
children: [ children: [
Text( Text(
_isPointsLimitEnabled == null gameMode == GameMode.none
? AppLocalizations.of(context).select_mode ? AppLocalizations.of(context).no_mode_selected
: (_isPointsLimitEnabled! : (gameMode == GameMode.pointLimit
? '${ConfigService.pointLimit} ${AppLocalizations.of(context).points}' ? '${ConfigService.getPointLimit()} ${AppLocalizations.of(context).points}'
: AppLocalizations.of(context).unlimited), : AppLocalizations.of(context).unlimited),
), ),
const SizedBox(width: 3), const SizedBox(width: 3),
@@ -121,29 +116,15 @@ class _CreateGameViewState extends State<CreateGameView> {
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => ModeSelectionMenu( builder: (context) => ModeSelectionMenu(
pointLimit: ConfigService.pointLimit, pointLimit: ConfigService.getPointLimit(),
showDeselection: false, showDeselection: false,
), ),
), ),
); );
switch (selectedMode) { setState(() {
case GameMode.pointLimit: gameMode = selectedMode ?? gameMode;
setState(() { });
_isPointsLimitEnabled = true;
});
break;
case GameMode.unlimited:
setState(() {
_isPointsLimitEnabled = false;
});
break;
case GameMode.none:
default:
setState(() {
_isPointsLimitEnabled = null;
});
}
}, },
), ),
), ),
@@ -249,7 +230,7 @@ class _CreateGameViewState extends State<CreateGameView> {
showFeedbackDialog(CreateStatus.noGameTitle); showFeedbackDialog(CreateStatus.noGameTitle);
return; return;
} }
if (_isPointsLimitEnabled == null) { if (gameMode == GameMode.none) {
showFeedbackDialog(CreateStatus.noModeSelected); showFeedbackDialog(CreateStatus.noModeSelected);
return; return;
} }
@@ -266,13 +247,16 @@ class _CreateGameViewState extends State<CreateGameView> {
for (var controller in _playerNameTextControllers) { for (var controller in _playerNameTextControllers) {
players.add(controller.text); players.add(controller.text);
} }
bool isPointsLimitEnabled = gameMode == GameMode.pointLimit;
GameSession gameSession = GameSession( GameSession gameSession = GameSession(
createdAt: DateTime.now(), createdAt: DateTime.now(),
gameTitle: _gameTitleTextController.text, gameTitle: _gameTitleTextController.text,
players: players, players: players,
pointLimit: ConfigService.pointLimit, pointLimit: ConfigService.getPointLimit(),
caboPenalty: ConfigService.caboPenalty, caboPenalty: ConfigService.getCaboPenalty(),
isPointsLimitEnabled: _isPointsLimitEnabled!, isPointsLimitEnabled: isPointsLimitEnabled,
); );
final index = await gameManager.addGameSession(gameSession); final index = await gameManager.addGameSession(gameSession);
final session = gameManager.gameList[index]; final session = gameManager.gameList[index];

View File

@@ -77,7 +77,8 @@ class _MainMenuViewState extends State<MainMenuView> {
onPressed: () => Navigator.push( onPressed: () => Navigator.push(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => const CreateGameView(), builder: (context) => CreateGameView(
gameMode: ConfigService.getGameMode()),
), ),
), ),
icon: const Icon(CupertinoIcons.add)), icon: const Icon(CupertinoIcons.add)),
@@ -96,8 +97,8 @@ class _MainMenuViewState extends State<MainMenuView> {
onTap: () => Navigator.push( onTap: () => Navigator.push(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => builder: (context) => CreateGameView(
const CreateGameView(), gameMode: ConfigService.getGameMode()),
), ),
), ),
child: Icon( child: Icon(
@@ -216,9 +217,9 @@ class _MainMenuViewState extends State<MainMenuView> {
/// Translates the game mode boolean into the corresponding String. /// Translates the game mode boolean into the corresponding String.
/// If [pointLimit] is true, it returns '101 Punkte', otherwise it returns 'Unbegrenzt'. /// If [pointLimit] is true, it returns '101 Punkte', otherwise it returns 'Unbegrenzt'.
String _translateGameMode(bool pointLimit) { String _translateGameMode(bool isPointLimitEnabled) {
if (pointLimit) { if (isPointLimitEnabled) {
return '${ConfigService.pointLimit} ${AppLocalizations.of(context).points}'; return '${ConfigService.getPointLimit()} ${AppLocalizations.of(context).points}';
} }
return AppLocalizations.of(context).unlimited; return AppLocalizations.of(context).unlimited;
} }

View File

@@ -21,7 +21,7 @@ class SettingsView extends StatefulWidget {
class _SettingsViewState extends State<SettingsView> { class _SettingsViewState extends State<SettingsView> {
UniqueKey _stepperKey1 = UniqueKey(); UniqueKey _stepperKey1 = UniqueKey();
UniqueKey _stepperKey2 = UniqueKey(); UniqueKey _stepperKey2 = UniqueKey();
int defaultMode = ConfigService.gameMode; GameMode defaultMode = ConfigService.getGameMode();
@override @override
void initState() { void initState() {
super.initState(); super.initState();
@@ -57,7 +57,7 @@ class _SettingsViewState extends State<SettingsView> {
prefixIcon: CupertinoIcons.bolt_fill, prefixIcon: CupertinoIcons.bolt_fill,
suffixWidget: CustomStepper( suffixWidget: CustomStepper(
key: _stepperKey1, key: _stepperKey1,
initialValue: ConfigService.caboPenalty, initialValue: ConfigService.getCaboPenalty(),
minValue: 0, minValue: 0,
maxValue: 50, maxValue: 50,
step: 1, step: 1,
@@ -73,7 +73,7 @@ class _SettingsViewState extends State<SettingsView> {
prefixIcon: FontAwesomeIcons.bullseye, prefixIcon: FontAwesomeIcons.bullseye,
suffixWidget: CustomStepper( suffixWidget: CustomStepper(
key: _stepperKey2, key: _stepperKey2,
initialValue: ConfigService.pointLimit, initialValue: ConfigService.getPointLimit(),
minValue: 30, minValue: 30,
maxValue: 1000, maxValue: 1000,
step: 10, step: 10,
@@ -91,11 +91,10 @@ class _SettingsViewState extends State<SettingsView> {
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Text(
defaultMode == -1 defaultMode == GameMode.none
? AppLocalizations.of(context) ? AppLocalizations.of(context).no_default_mode
.no_mode_selected : (defaultMode == GameMode.pointLimit
: (defaultMode == 1 ? '${ConfigService.getPointLimit()} ${AppLocalizations.of(context).points}'
? '${ConfigService.pointLimit} ${AppLocalizations.of(context).points}'
: AppLocalizations.of(context).unlimited), : AppLocalizations.of(context).unlimited),
), ),
const SizedBox(width: 5), const SizedBox(width: 5),
@@ -107,29 +106,15 @@ class _SettingsViewState extends State<SettingsView> {
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => ModeSelectionMenu( builder: (context) => ModeSelectionMenu(
pointLimit: ConfigService.pointLimit, pointLimit: ConfigService.getPointLimit(),
showDeselection: true, showDeselection: true,
), ),
), ),
); );
switch (selectedMode) { setState(() {
case GameMode.pointLimit: defaultMode = selectedMode ?? GameMode.none;
setState(() { });
defaultMode = 1;
});
break;
case GameMode.unlimited:
setState(() {
defaultMode = 0;
});
break;
case GameMode.none:
default:
setState(() {
defaultMode = -1;
});
}
ConfigService.setGameMode(defaultMode); ConfigService.setGameMode(defaultMode);
}, },
), ),
@@ -142,7 +127,7 @@ class _SettingsViewState extends State<SettingsView> {
setState(() { setState(() {
_stepperKey1 = UniqueKey(); _stepperKey1 = UniqueKey();
_stepperKey2 = UniqueKey(); _stepperKey2 = UniqueKey();
defaultMode = ConfigService.gameMode; defaultMode = ConfigService.getGameMode();
}); });
}, },
) )

View File

@@ -1,3 +1,4 @@
import 'package:cabo_counter/presentation/views/mode_selection_view.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
/// This class handles the configuration settings for the app. /// This class handles the configuration settings for the app.
@@ -8,9 +9,9 @@ class ConfigService {
static const String _keyCaboPenalty = 'caboPenalty'; static const String _keyCaboPenalty = 'caboPenalty';
static const String _keyGameMode = 'gameMode'; static const String _keyGameMode = 'gameMode';
// Actual values used in the app // Actual values used in the app
static int pointLimit = 100; static int _pointLimit = 100;
static int caboPenalty = 5; static int _caboPenalty = 5;
static int gameMode = -1; static int _gameMode = -1;
// Default values // Default values
static const int _defaultPointLimit = 100; static const int _defaultPointLimit = 100;
static const int _defaultCaboPenalty = 5; static const int _defaultCaboPenalty = 5;
@@ -21,43 +22,86 @@ class ConfigService {
// Initialize pointLimit, caboPenalty, and gameMode from SharedPreferences // Initialize pointLimit, caboPenalty, and gameMode from SharedPreferences
// If they are not set, use the default values // If they are not set, use the default values
pointLimit = prefs.getInt(_keyPointLimit) ?? _defaultPointLimit; _pointLimit = prefs.getInt(_keyPointLimit) ?? _defaultPointLimit;
caboPenalty = prefs.getInt(_keyCaboPenalty) ?? _defaultCaboPenalty; _caboPenalty = prefs.getInt(_keyCaboPenalty) ?? _defaultCaboPenalty;
gameMode = prefs.getInt(_keyGameMode) ?? _defaultGameMode; _gameMode = prefs.getInt(_keyGameMode) ?? _defaultGameMode;
// Save the initial values to SharedPreferences // Save the initial values to SharedPreferences
prefs.setInt(_keyPointLimit, pointLimit); prefs.setInt(_keyPointLimit, _pointLimit);
prefs.setInt(_keyCaboPenalty, caboPenalty); prefs.setInt(_keyCaboPenalty, _caboPenalty);
prefs.setInt(_keyGameMode, gameMode); prefs.setInt(_keyGameMode, _gameMode);
} }
static Future<void> setGameMode(int newGameMode) async { /// Retrieves the current game mode.
final prefs = await SharedPreferences.getInstance(); ///
await prefs.setInt(_keyGameMode, newGameMode); /// The game mode is determined based on the stored integer value:
gameMode = newGameMode; /// - `0`: [GameMode.pointLimit]
/// - `1`: [GameMode.unlimited]
/// - Any other value: [GameMode.none] (-1 is used as a default for no mode)
///
/// Returns the corresponding [GameMode] enum value.
static GameMode getGameMode() {
switch (_gameMode) {
case 0:
return GameMode.pointLimit;
case 1:
return GameMode.unlimited;
default:
return GameMode.none;
}
} }
/// Sets the game mode for the application.
///
/// [newGameMode] is the new game mode to be set. It can be one of the following:
/// - `GameMode.pointLimit`: The game ends when a pleayer reaches the point limit.
/// - `GameMode.unlimited`: Every game goes for infinity until you end it.
/// - `GameMode.none`: No default mode set.
///
/// This method updates the `_gameMode` field and persists the value in `SharedPreferences`.
static Future<void> setGameMode(GameMode newGameMode) async {
int gameMode;
switch (newGameMode) {
case GameMode.pointLimit:
gameMode = 0;
break;
case GameMode.unlimited:
gameMode = 1;
break;
default:
gameMode = -1;
}
final prefs = await SharedPreferences.getInstance();
await prefs.setInt(_keyGameMode, gameMode);
_gameMode = gameMode;
}
static int getPointLimit() => _pointLimit;
/// Setter for the point limit. /// Setter for the point limit.
/// [newPointLimit] is the new point limit to be set. /// [newPointLimit] is the new point limit to be set.
static Future<void> setPointLimit(int newPointLimit) async { static Future<void> setPointLimit(int newPointLimit) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setInt(_keyPointLimit, newPointLimit); await prefs.setInt(_keyPointLimit, newPointLimit);
pointLimit = newPointLimit; _pointLimit = newPointLimit;
} }
static int getCaboPenalty() => _caboPenalty;
/// Setter for the cabo penalty. /// Setter for the cabo penalty.
/// [newCaboPenalty] is the new cabo penalty to be set. /// [newCaboPenalty] is the new cabo penalty to be set.
static Future<void> setCaboPenalty(int newCaboPenalty) async { static Future<void> setCaboPenalty(int newCaboPenalty) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setInt(_keyCaboPenalty, newCaboPenalty); await prefs.setInt(_keyCaboPenalty, newCaboPenalty);
caboPenalty = newCaboPenalty; _caboPenalty = newCaboPenalty;
} }
/// Resets the configuration to default values. /// Resets the configuration to default values.
static Future<void> resetConfig() async { static Future<void> resetConfig() async {
ConfigService.pointLimit = _defaultPointLimit; ConfigService._pointLimit = _defaultPointLimit;
ConfigService.caboPenalty = _defaultCaboPenalty; ConfigService._caboPenalty = _defaultCaboPenalty;
ConfigService.gameMode = _defaultGameMode; ConfigService._gameMode = _defaultGameMode;
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setInt(_keyPointLimit, _defaultPointLimit); await prefs.setInt(_keyPointLimit, _defaultPointLimit);
await prefs.setInt(_keyCaboPenalty, _defaultCaboPenalty); await prefs.setInt(_keyCaboPenalty, _defaultCaboPenalty);

View File

@@ -2,7 +2,7 @@ name: cabo_counter
description: "Mobile app for the card game Cabo" description: "Mobile app for the card game Cabo"
publish_to: 'none' publish_to: 'none'
version: 0.5.0+542 version: 0.5.0+544
environment: environment:
sdk: ^3.5.4 sdk: ^3.5.4