diff --git a/lib/l10n/arb/app_de.arb b/lib/l10n/arb/app_de.arb index dceb8fc..3c157ad 100644 --- a/lib/l10n/arb/app_de.arb +++ b/lib/l10n/arb/app_de.arb @@ -58,6 +58,9 @@ "no_name_message": "Jeder Spieler muss einen Namen haben.", "select_game_mode": "Spielmodus auswählen", + "no_mode_selected": "Kein Modus ausgewählt", + "no_default_mode": "Kein Standard-Modus", + "no_default_description": "Der Standard-Modus wird zurückgesetzt.", "point_limit_description": "Es wird so lange gespielt, bis ein:e Spieler:in mehr als {pointLimit} Punkte erreicht", "@point_limit_description": { "placeholders": { @@ -109,9 +112,8 @@ "settings": "Einstellungen", "cabo_penalty": "Cabo-Strafe", - "cabo_penalty_subtitle": "... für falsches Cabo sagen", "point_limit": "Punkte-Limit", - "point_limit_subtitle": "... hier ist Schluss", + "standard_mode": "Standard-Modus", "reset_to_default": "Auf Standard zurücksetzen", "game_data": "Spieldaten", "import_data": "Spieldaten importieren", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 3009d6e..ea169e9 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -58,6 +58,9 @@ "no_name_message": "Each player must have a name.", "select_game_mode": "Select game mode", + "no_mode_selected": "No mode selected", + "no_default_mode": "No default mode", + "no_default_description": "The default mode gets reset.", "point_limit_description": "The game ends when a player scores more than {pointLimit} points.", "@point_limit_description": { "placeholders": { @@ -109,9 +112,8 @@ "settings": "Settings", "cabo_penalty": "Cabo Penalty", - "cabo_penalty_subtitle": "A point penalty for incorrectly calling Cabo.", "point_limit": "Point Limit", - "point_limit_subtitle": "The required score to win the game.", + "standard_mode": "Default Mode", "reset_to_default": "Reset to Default", "game_data": "Game Data", "import_data": "Import Data", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index 695fb57..cc4eb12 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -374,6 +374,24 @@ abstract class AppLocalizations { /// **'Spielmodus auswählen'** String get select_game_mode; + /// No description provided for @no_mode_selected. + /// + /// In de, this message translates to: + /// **'Kein Modus ausgewählt'** + String get no_mode_selected; + + /// No description provided for @no_default_mode. + /// + /// In de, this message translates to: + /// **'Kein Standard-Modus'** + String get no_default_mode; + + /// No description provided for @no_default_description. + /// + /// In de, this message translates to: + /// **'Der Standard-Modus wird zurückgesetzt.'** + String get no_default_description; + /// No description provided for @point_limit_description. /// /// In de, this message translates to: @@ -519,23 +537,17 @@ abstract class AppLocalizations { /// **'Cabo-Strafe'** String get cabo_penalty; - /// No description provided for @cabo_penalty_subtitle. - /// - /// In de, this message translates to: - /// **'... für falsches Cabo sagen'** - String get cabo_penalty_subtitle; - /// No description provided for @point_limit. /// /// In de, this message translates to: /// **'Punkte-Limit'** String get point_limit; - /// No description provided for @point_limit_subtitle. + /// No description provided for @standard_mode. /// /// In de, this message translates to: - /// **'... hier ist Schluss'** - String get point_limit_subtitle; + /// **'Standard-Modus'** + String get standard_mode; /// No description provided for @reset_to_default. /// diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index 3ef54b8..3820070 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -154,6 +154,15 @@ class AppLocalizationsDe extends AppLocalizations { @override String get select_game_mode => 'Spielmodus auswählen'; + @override + String get no_mode_selected => 'Kein Modus ausgewählt'; + + @override + String get no_default_mode => 'Kein Standard-Modus'; + + @override + String get no_default_description => 'Der Standard-Modus wird zurückgesetzt.'; + @override String point_limit_description(int pointLimit) { return 'Es wird so lange gespielt, bis ein:e Spieler:in mehr als $pointLimit Punkte erreicht'; @@ -243,14 +252,11 @@ class AppLocalizationsDe extends AppLocalizations { @override String get cabo_penalty => 'Cabo-Strafe'; - @override - String get cabo_penalty_subtitle => '... für falsches Cabo sagen'; - @override String get point_limit => 'Punkte-Limit'; @override - String get point_limit_subtitle => '... hier ist Schluss'; + String get standard_mode => 'Standard-Modus'; @override String get reset_to_default => 'Auf Standard zurücksetzen'; diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index 8a86b95..6b2689e 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -152,6 +152,15 @@ class AppLocalizationsEn extends AppLocalizations { @override String get select_game_mode => 'Select game mode'; + @override + String get no_mode_selected => 'No mode selected'; + + @override + String get no_default_mode => 'No default mode'; + + @override + String get no_default_description => 'The default mode gets reset.'; + @override String point_limit_description(int pointLimit) { return 'The game ends when a player scores more than $pointLimit points.'; @@ -241,15 +250,11 @@ class AppLocalizationsEn extends AppLocalizations { @override String get cabo_penalty => 'Cabo Penalty'; - @override - String get cabo_penalty_subtitle => - 'A point penalty for incorrectly calling Cabo.'; - @override String get point_limit => 'Point Limit'; @override - String get point_limit_subtitle => 'The required score to win the game.'; + String get standard_mode => 'Default Mode'; @override String get reset_to_default => 'Reset to Default'; diff --git a/lib/main.dart b/lib/main.dart index 9279426..8b45434 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -12,8 +12,6 @@ Future main() async { await SystemChrome.setPreferredOrientations( [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]); await ConfigService.initConfig(); - ConfigService.pointLimit = await ConfigService.getPointLimit(); - ConfigService.caboPenalty = await ConfigService.getCaboPenalty(); await VersionService.init(); runApp(const App()); } diff --git a/lib/presentation/views/create_game_view.dart b/lib/presentation/views/create_game_view.dart index 0d23494..2634788 100644 --- a/lib/presentation/views/create_game_view.dart +++ b/lib/presentation/views/create_game_view.dart @@ -49,7 +49,13 @@ class _CreateGameViewState extends State { void initState() { super.initState(); - _isPointsLimitEnabled = widget.isPointsLimitEnabled; + if (widget.isPointsLimitEnabled == null) { + _isPointsLimitEnabled = + ConfigService.gameMode == -1 ? null : ConfigService.gameMode == 1; + } else { + _isPointsLimitEnabled = widget.isPointsLimitEnabled; + } + _gameTitleTextController.text = widget.gameTitle ?? ''; if (widget.players != null) { @@ -91,7 +97,6 @@ class _CreateGameViewState extends State { controller: _gameTitleTextController, ), ), - // Spielmodus-Auswahl mit Chevron Padding( padding: const EdgeInsets.fromLTRB(15, 10, 10, 0), child: CupertinoTextField( @@ -117,14 +122,27 @@ class _CreateGameViewState extends State { CupertinoPageRoute( builder: (context) => ModeSelectionMenu( pointLimit: ConfigService.pointLimit, + showDeselection: false, ), ), ); - if (selectedMode != null) { - setState(() { - _isPointsLimitEnabled = selectedMode; - }); + switch (selectedMode) { + case GameMode.pointLimit: + setState(() { + _isPointsLimitEnabled = true; + }); + break; + case GameMode.unlimited: + setState(() { + _isPointsLimitEnabled = false; + }); + break; + case GameMode.none: + default: + setState(() { + _isPointsLimitEnabled = null; + }); } }, ), @@ -138,11 +156,9 @@ class _CreateGameViewState extends State { ), Expanded( child: ListView.builder( - itemCount: _playerNameTextControllers.length + - 1, // +1 für den + Button + itemCount: _playerNameTextControllers.length + 1, itemBuilder: (context, index) { if (index == _playerNameTextControllers.length) { - // + Button als letztes Element return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: CupertinoButton( diff --git a/lib/presentation/views/mode_selection_view.dart b/lib/presentation/views/mode_selection_view.dart index a7d3ce7..0424dab 100644 --- a/lib/presentation/views/mode_selection_view.dart +++ b/lib/presentation/views/mode_selection_view.dart @@ -2,9 +2,17 @@ import 'package:cabo_counter/core/custom_theme.dart'; import 'package:cabo_counter/l10n/generated/app_localizations.dart'; import 'package:flutter/cupertino.dart'; +enum GameMode { + none, + pointLimit, + unlimited, +} + class ModeSelectionMenu extends StatelessWidget { final int pointLimit; - const ModeSelectionMenu({super.key, required this.pointLimit}); + final bool showDeselection; + const ModeSelectionMenu( + {super.key, required this.pointLimit, required this.showDeselection}); @override Widget build(BuildContext context) { @@ -26,12 +34,12 @@ class ModeSelectionMenu extends StatelessWidget { maxLines: 3, ), onTap: () { - Navigator.pop(context, true); + Navigator.pop(context, GameMode.pointLimit); }, ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), + padding: const EdgeInsets.fromLTRB(0, 16, 0, 0), child: CupertinoListTile( title: Text(AppLocalizations.of(context).unlimited, style: CustomTheme.modeTitle), @@ -41,10 +49,27 @@ class ModeSelectionMenu extends StatelessWidget { maxLines: 3, ), onTap: () { - Navigator.pop(context, false); + Navigator.pop(context, GameMode.unlimited); }, ), ), + Visibility( + visible: showDeselection, + child: Padding( + padding: const EdgeInsets.fromLTRB(0, 16, 0, 0), + child: CupertinoListTile( + title: Text(AppLocalizations.of(context).no_default_mode, + style: CustomTheme.modeTitle), + subtitle: Text( + AppLocalizations.of(context).no_default_description, + style: CustomTheme.modeDescription, + maxLines: 3, + ), + onTap: () { + Navigator.pop(context, GameMode.none); + }, + ), + )), ], ), ); diff --git a/lib/presentation/views/settings_view.dart b/lib/presentation/views/settings_view.dart index d6f0833..c649a20 100644 --- a/lib/presentation/views/settings_view.dart +++ b/lib/presentation/views/settings_view.dart @@ -1,6 +1,7 @@ import 'package:cabo_counter/core/constants.dart'; import 'package:cabo_counter/core/custom_theme.dart'; import 'package:cabo_counter/l10n/generated/app_localizations.dart'; +import 'package:cabo_counter/presentation/views/mode_selection_view.dart'; import 'package:cabo_counter/presentation/widgets/custom_form_row.dart'; import 'package:cabo_counter/presentation/widgets/custom_stepper.dart'; import 'package:cabo_counter/services/config_service.dart'; @@ -20,6 +21,7 @@ class SettingsView extends StatefulWidget { class _SettingsViewState extends State { UniqueKey _stepperKey1 = UniqueKey(); UniqueKey _stepperKey2 = UniqueKey(); + int defaultMode = ConfigService.gameMode; @override void initState() { super.initState(); @@ -62,7 +64,6 @@ class _SettingsViewState extends State { onChanged: (newCaboPenalty) { setState(() { ConfigService.setCaboPenalty(newCaboPenalty); - ConfigService.caboPenalty = newCaboPenalty; }); }, ), @@ -79,11 +80,59 @@ class _SettingsViewState extends State { onChanged: (newPointLimit) { setState(() { ConfigService.setPointLimit(newPointLimit); - ConfigService.pointLimit = newPointLimit; }); }, ), ), + CustomFormRow( + prefixText: AppLocalizations.of(context).standard_mode, + prefixIcon: CupertinoIcons.square_stack, + suffixWidget: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + defaultMode == -1 + ? AppLocalizations.of(context) + .no_mode_selected + : (defaultMode == 1 + ? '${ConfigService.pointLimit} ${AppLocalizations.of(context).points}' + : AppLocalizations.of(context).unlimited), + ), + const SizedBox(width: 10), + const CupertinoListTileChevron() + ], + ), + onPressed: () async { + final selectedMode = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => ModeSelectionMenu( + pointLimit: ConfigService.pointLimit, + showDeselection: true, + ), + ), + ); + + switch (selectedMode) { + case GameMode.pointLimit: + setState(() { + defaultMode = 1; + }); + break; + case GameMode.unlimited: + setState(() { + defaultMode = 0; + }); + break; + case GameMode.none: + default: + setState(() { + defaultMode = -1; + }); + } + ConfigService.setGameMode(defaultMode); + }, + ), CustomFormRow( prefixText: AppLocalizations.of(context).reset_to_default, @@ -93,6 +142,7 @@ class _SettingsViewState extends State { setState(() { _stepperKey1 = UniqueKey(); _stepperKey2 = UniqueKey(); + defaultMode = ConfigService.gameMode; }); }, ) diff --git a/lib/services/config_service.dart b/lib/services/config_service.dart index 70f6133..a360fe4 100644 --- a/lib/services/config_service.dart +++ b/lib/services/config_service.dart @@ -6,27 +6,35 @@ import 'package:shared_preferences/shared_preferences.dart'; class ConfigService { static const String _keyPointLimit = 'pointLimit'; static const String _keyCaboPenalty = 'caboPenalty'; + static const String _keyGameMode = 'gameMode'; // Actual values used in the app static int pointLimit = 100; static int caboPenalty = 5; + static int gameMode = -1; // Default values static const int _defaultPointLimit = 100; static const int _defaultCaboPenalty = 5; + static const int _defaultGameMode = -1; static Future initConfig() async { final prefs = await SharedPreferences.getInstance(); - // Default values only set if they are not already set - prefs.setInt( - _keyPointLimit, prefs.getInt(_keyPointLimit) ?? _defaultPointLimit); - prefs.setInt( - _keyCaboPenalty, prefs.getInt(_keyCaboPenalty) ?? _defaultCaboPenalty); + // Initialize pointLimit, caboPenalty, and gameMode from SharedPreferences + // If they are not set, use the default values + pointLimit = prefs.getInt(_keyPointLimit) ?? _defaultPointLimit; + caboPenalty = prefs.getInt(_keyCaboPenalty) ?? _defaultCaboPenalty; + gameMode = prefs.getInt(_keyGameMode) ?? _defaultGameMode; + + // Save the initial values to SharedPreferences + prefs.setInt(_keyPointLimit, pointLimit); + prefs.setInt(_keyCaboPenalty, caboPenalty); + prefs.setInt(_keyGameMode, gameMode); } - /// Getter for the point limit. - static Future getPointLimit() async { + static Future setGameMode(int newGameMode) async { final prefs = await SharedPreferences.getInstance(); - return prefs.getInt(_keyPointLimit) ?? _defaultPointLimit; + await prefs.setInt(_keyGameMode, newGameMode); + gameMode = newGameMode; } /// Setter for the point limit. @@ -34,12 +42,7 @@ class ConfigService { static Future setPointLimit(int newPointLimit) async { final prefs = await SharedPreferences.getInstance(); await prefs.setInt(_keyPointLimit, newPointLimit); - } - - /// Getter for the cabo penalty. - static Future getCaboPenalty() async { - final prefs = await SharedPreferences.getInstance(); - return prefs.getInt(_keyCaboPenalty) ?? _defaultCaboPenalty; + pointLimit = newPointLimit; } /// Setter for the cabo penalty. @@ -47,12 +50,14 @@ class ConfigService { static Future setCaboPenalty(int newCaboPenalty) async { final prefs = await SharedPreferences.getInstance(); await prefs.setInt(_keyCaboPenalty, newCaboPenalty); + caboPenalty = newCaboPenalty; } /// Resets the configuration to default values. static Future resetConfig() async { ConfigService.pointLimit = _defaultPointLimit; ConfigService.caboPenalty = _defaultCaboPenalty; + ConfigService.gameMode = _defaultGameMode; final prefs = await SharedPreferences.getInstance(); await prefs.setInt(_keyPointLimit, _defaultPointLimit); await prefs.setInt(_keyCaboPenalty, _defaultCaboPenalty); diff --git a/pubspec.yaml b/pubspec.yaml index 37af518..dca4d3a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: cabo_counter description: "Mobile app for the card game Cabo" publish_to: 'none' -version: 0.4.9+533 +version: 0.4.9+540 environment: sdk: ^3.5.4