From 55a61be44b2a3876a7b7fbee5ad244cf8f95d5ff Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 11 Jul 2025 11:10:06 +0200 Subject: [PATCH] Added Delete all games button to Settings --- lib/l10n/arb/app_de.arb | 3 + lib/l10n/arb/app_en.arb | 3 + lib/l10n/generated/app_localizations.dart | 18 ++ lib/l10n/generated/app_localizations_de.dart | 10 + lib/l10n/generated/app_localizations_en.dart | 12 +- lib/presentation/views/settings_view.dart | 321 ++++++++++--------- pubspec.yaml | 2 +- 7 files changed, 222 insertions(+), 147 deletions(-) diff --git a/lib/l10n/arb/app_de.arb b/lib/l10n/arb/app_de.arb index d89399b..113cce1 100644 --- a/lib/l10n/arb/app_de.arb +++ b/lib/l10n/arb/app_de.arb @@ -95,6 +95,9 @@ "game_data": "Spieldaten", "import_data": "Spieldaten importieren", "export_data": "Spieldaten exportieren", + "delete_data": "Alle Spieldaten löschen", + "delete_data_title": "Spieldaten löschen?", + "delete_data_message": "Bist du sicher, dass du alle Spieldaten löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.", "app": "App", "import_success_title": "Import erfolgreich", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index e01e242..1f5fe3c 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -95,6 +95,9 @@ "game_data": "Game Data", "import_data": "Import Data", "export_data": "Export Data", + "delete_data": "Delete all Game Data", + "delete_data_title": "Delete game data?", + "delete_data_message": "Bist du sicher, dass du alle Spieldaten löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.", "app": "App", "import_success_title": "Import successful", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index af778ae..979d46b 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -530,6 +530,24 @@ abstract class AppLocalizations { /// **'Spieldaten exportieren'** String get export_data; + /// No description provided for @delete_data. + /// + /// In de, this message translates to: + /// **'Alle Spieldaten löschen'** + String get delete_data; + + /// No description provided for @delete_data_title. + /// + /// In de, this message translates to: + /// **'Spieldaten löschen?'** + String get delete_data_title; + + /// No description provided for @delete_data_message. + /// + /// In de, this message translates to: + /// **'Bist du sicher, dass du alle Spieldaten löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.'** + String get delete_data_message; + /// No description provided for @app. /// /// In de, this message translates to: diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index afe558f..c4b2491 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -237,6 +237,16 @@ class AppLocalizationsDe extends AppLocalizations { @override String get export_data => 'Spieldaten exportieren'; + @override + String get delete_data => 'Alle Spieldaten löschen'; + + @override + String get delete_data_title => 'Spieldaten löschen?'; + + @override + String get delete_data_message => + 'Bist du sicher, dass du alle Spieldaten löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.'; + @override String get app => 'App'; diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index a986058..3cbde9c 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -92,7 +92,7 @@ class AppLocalizationsEn extends AppLocalizations { 'If you are not satisfied with the app, please let me know before leaving a bad rating. I will try to fix the issue as soon as possible.'; @override - String get contact_email => 'Contac via E-Mail'; + String get contact_email => 'Contact via E-Mail'; @override String get email_subject => 'Feedback: Cabo Counter App'; @@ -234,6 +234,16 @@ class AppLocalizationsEn extends AppLocalizations { @override String get export_data => 'Export Data'; + @override + String get delete_data => 'Delete all Game Data'; + + @override + String get delete_data_title => 'Delete game data?'; + + @override + String get delete_data_message => + 'Bist du sicher, dass du alle Spieldaten löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.'; + @override String get app => 'App'; diff --git a/lib/presentation/views/settings_view.dart b/lib/presentation/views/settings_view.dart index 9bed7fc..ab8ec7d 100644 --- a/lib/presentation/views/settings_view.dart +++ b/lib/presentation/views/settings_view.dart @@ -32,162 +32,193 @@ class _SettingsViewState extends State { middle: Text(AppLocalizations.of(context).settings), ), child: SafeArea( - child: Stack( - children: [ - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(10, 10, 0, 0), - child: Text( - AppLocalizations.of(context).points, - style: CustomTheme.rowTitle, - ), + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(10, 10, 0, 0), + child: Text( + AppLocalizations.of(context).points, + style: CustomTheme.rowTitle, ), - Padding( - padding: const EdgeInsets.fromLTRB(10, 15, 10, 10), - child: CupertinoFormSection.insetGrouped( - backgroundColor: CustomTheme.backgroundColor, - margin: EdgeInsets.zero, - children: [ - CustomFormRow( - prefixText: 'Cabo-Strafe', - prefixIcon: CupertinoIcons.bolt_fill, - suffixWidget: CustomStepper( - key: _stepperKey1, - initialValue: ConfigService.caboPenalty, - minValue: 0, - maxValue: 50, - step: 1, - onChanged: (newCaboPenalty) { - setState(() { - ConfigService.setCaboPenalty(newCaboPenalty); - ConfigService.caboPenalty = newCaboPenalty; - }); - }, - ), - ), - CustomFormRow( - prefixText: 'Punkte-Limit', - prefixIcon: FontAwesomeIcons.bullseye, - suffixWidget: CustomStepper( - key: _stepperKey2, - initialValue: ConfigService.pointLimit, - minValue: 30, - maxValue: 1000, - step: 10, - onChanged: (newPointLimit) { - setState(() { - ConfigService.setPointLimit(newPointLimit); - ConfigService.pointLimit = newPointLimit; - }); - }, - ), - ), - CustomFormRow( - prefixText: - AppLocalizations.of(context).reset_to_default, - prefixIcon: CupertinoIcons.arrow_counterclockwise, - onPressed: () { - ConfigService.resetConfig(); + ), + Padding( + padding: const EdgeInsets.fromLTRB(10, 15, 10, 10), + child: CupertinoFormSection.insetGrouped( + backgroundColor: CustomTheme.backgroundColor, + margin: EdgeInsets.zero, + children: [ + CustomFormRow( + prefixText: AppLocalizations.of(context).cabo_penalty, + prefixIcon: CupertinoIcons.bolt_fill, + suffixWidget: CustomStepper( + key: _stepperKey1, + initialValue: ConfigService.caboPenalty, + minValue: 0, + maxValue: 50, + step: 1, + onChanged: (newCaboPenalty) { setState(() { - _stepperKey1 = UniqueKey(); - _stepperKey2 = UniqueKey(); + ConfigService.setCaboPenalty(newCaboPenalty); + ConfigService.caboPenalty = newCaboPenalty; }); }, - ) - ])), - Padding( - padding: const EdgeInsets.fromLTRB(10, 10, 0, 0), - child: Text( - AppLocalizations.of(context).game_data, - style: CustomTheme.rowTitle, - ), - ), - Padding( - padding: const EdgeInsets.fromLTRB(10, 15, 10, 10), - child: CupertinoFormSection.insetGrouped( - backgroundColor: CustomTheme.backgroundColor, - margin: EdgeInsets.zero, - children: [ - CustomFormRow( - prefixText: AppLocalizations.of(context).import_data, - prefixIcon: CupertinoIcons.square_arrow_down, - onPressed: () async { - final status = - await LocalStorageService.importJsonFile(); - showFeedbackDialog(status); + ), + ), + CustomFormRow( + prefixText: AppLocalizations.of(context).point_limit, + prefixIcon: FontAwesomeIcons.bullseye, + suffixWidget: CustomStepper( + key: _stepperKey2, + initialValue: ConfigService.pointLimit, + minValue: 30, + maxValue: 1000, + step: 10, + onChanged: (newPointLimit) { + setState(() { + ConfigService.setPointLimit(newPointLimit); + ConfigService.pointLimit = newPointLimit; + }); }, - suffixWidget: const CupertinoListTileChevron(), ), - CustomFormRow( - prefixText: AppLocalizations.of(context).export_data, - prefixIcon: CupertinoIcons.square_arrow_up, - onPressed: () => LocalStorageService.exportGameData(), - suffixWidget: const CupertinoListTileChevron(), - ), - ])), - Padding( - padding: const EdgeInsets.fromLTRB(10, 10, 0, 0), - child: Text( - AppLocalizations.of(context).app, - style: CustomTheme.rowTitle, - ), + ), + CustomFormRow( + prefixText: + AppLocalizations.of(context).reset_to_default, + prefixIcon: CupertinoIcons.arrow_counterclockwise, + onPressed: () { + ConfigService.resetConfig(); + setState(() { + _stepperKey1 = UniqueKey(); + _stepperKey2 = UniqueKey(); + }); + }, + ) + ])), + Padding( + padding: const EdgeInsets.fromLTRB(10, 10, 0, 0), + child: Text( + AppLocalizations.of(context).game_data, + style: CustomTheme.rowTitle, ), - Padding( - padding: const EdgeInsets.fromLTRB(10, 15, 10, 0), - child: CupertinoFormSection.insetGrouped( - backgroundColor: CustomTheme.backgroundColor, - margin: EdgeInsets.zero, - children: [ - CustomFormRow( - prefixText: AppLocalizations.of(context).wiki, - prefixIcon: CupertinoIcons.book, - onPressed: () => - launchUrl(Uri.parse(Constants.GITHUB_WIKI_LINK)), - suffixWidget: const CupertinoListTileChevron(), - ), - CustomFormRow( - prefixText: - AppLocalizations.of(context).privacy_policy, - prefixIcon: CupertinoIcons.doc_append, - onPressed: () => launchUrl( - Uri.parse(Constants.PRIVACY_POLICY_LINK)), - suffixWidget: const CupertinoListTileChevron(), - ), - CustomFormRow( - prefixText: AppLocalizations.of(context).error_found, - prefixIcon: FontAwesomeIcons.github, - onPressed: () => launchUrl( - Uri.parse(Constants.GITHUB_ISSUES_LINK)), - suffixWidget: const CupertinoListTileChevron(), - ), - CustomFormRow( - prefixText: - AppLocalizations.of(context).app_version, - prefixIcon: CupertinoIcons.tag, - onPressed: null, - suffixWidget: Text(VersionService.getVersion(), - style: TextStyle( - color: CustomTheme.primaryColor, - ))), - CustomFormRow( - prefixText: AppLocalizations.of(context).build, - prefixIcon: CupertinoIcons.number, - onPressed: null, - suffixWidget: Text(VersionService.getBuildNumber(), - style: TextStyle( - color: CustomTheme.primaryColor, - ))), - ])), - ], - ), - ], + ), + Padding( + padding: const EdgeInsets.fromLTRB(10, 15, 10, 10), + child: CupertinoFormSection.insetGrouped( + backgroundColor: CustomTheme.backgroundColor, + margin: EdgeInsets.zero, + children: [ + CustomFormRow( + prefixText: AppLocalizations.of(context).import_data, + prefixIcon: CupertinoIcons.square_arrow_down, + onPressed: () async { + final status = + await LocalStorageService.importJsonFile(); + showFeedbackDialog(status); + }, + suffixWidget: const CupertinoListTileChevron(), + ), + CustomFormRow( + prefixText: AppLocalizations.of(context).export_data, + prefixIcon: CupertinoIcons.square_arrow_up, + onPressed: () => LocalStorageService.exportGameData(), + suffixWidget: const CupertinoListTileChevron(), + ), + CustomFormRow( + prefixText: AppLocalizations.of(context).delete_data, + prefixIcon: CupertinoIcons.trash, + onPressed: () => _deleteAllGames(), + ), + ])), + Padding( + padding: const EdgeInsets.fromLTRB(10, 10, 0, 0), + child: Text( + AppLocalizations.of(context).app, + style: CustomTheme.rowTitle, + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(10, 15, 10, 0), + child: CupertinoFormSection.insetGrouped( + backgroundColor: CustomTheme.backgroundColor, + margin: EdgeInsets.zero, + children: [ + CustomFormRow( + prefixText: AppLocalizations.of(context).wiki, + prefixIcon: CupertinoIcons.book, + onPressed: () => + launchUrl(Uri.parse(Constants.GITHUB_WIKI_LINK)), + suffixWidget: const CupertinoListTileChevron(), + ), + CustomFormRow( + prefixText: AppLocalizations.of(context).privacy_policy, + prefixIcon: CupertinoIcons.doc_append, + onPressed: () => + launchUrl(Uri.parse(Constants.PRIVACY_POLICY_LINK)), + suffixWidget: const CupertinoListTileChevron(), + ), + CustomFormRow( + prefixText: AppLocalizations.of(context).error_found, + prefixIcon: FontAwesomeIcons.github, + onPressed: () => + launchUrl(Uri.parse(Constants.GITHUB_ISSUES_LINK)), + suffixWidget: const CupertinoListTileChevron(), + ), + CustomFormRow( + prefixText: AppLocalizations.of(context).app_version, + prefixIcon: CupertinoIcons.tag, + onPressed: null, + suffixWidget: Text(VersionService.getVersion(), + style: TextStyle( + color: CustomTheme.primaryColor, + ))), + CustomFormRow( + prefixText: AppLocalizations.of(context).build, + prefixIcon: CupertinoIcons.number, + onPressed: null, + suffixWidget: Text(VersionService.getBuildNumber(), + style: TextStyle( + color: CustomTheme.primaryColor, + ))), + ])), + const SizedBox(height: 50) + ], + ), )), ); } + /// Shows a dialog to confirm the deletion of all game data. + /// When confirmed, it deletes all game data from local storage. + void _deleteAllGames() { + showCupertinoDialog( + context: context, + builder: (context) { + return CupertinoAlertDialog( + title: Text(AppLocalizations.of(context).delete_data_title), + content: Text(AppLocalizations.of(context).delete_data_message), + actions: [ + CupertinoDialogAction( + child: Text(AppLocalizations.of(context).cancel), + onPressed: () => Navigator.pop(context), + ), + CupertinoDialogAction( + isDestructiveAction: true, + isDefaultAction: true, + child: Text(AppLocalizations.of(context).delete), + onPressed: () { + LocalStorageService.deleteAllGames(); + Navigator.pop(context); + }, + ), + ], + ); + }, + ); + } + void showFeedbackDialog(ImportStatus status) { if (status == ImportStatus.canceled) return; final (title, message) = _getDialogContent(status); diff --git a/pubspec.yaml b/pubspec.yaml index 31146e6..ca5ef95 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.0+467 +version: 0.4.2+470 environment: sdk: ^3.5.4