Merge pull request #76 from flixcoo/feature/62-implement-delete-game-button-in-activegameview

Implement delete game button in activegameview
This commit is contained in:
2025-07-03 20:24:44 +02:00
committed by GitHub
15 changed files with 208 additions and 78 deletions

View File

@@ -5,6 +5,9 @@
"items": { "items": {
"type": "object", "type": "object",
"properties": { "properties": {
"id": {
"type": "string"
},
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },

View File

@@ -15,14 +15,9 @@ class GameManager extends ChangeNotifier {
notifyListeners(); // Propagate session changes notifyListeners(); // Propagate session changes
}); });
gameList.add(session); gameList.add(session);
print(
'[game_manager.dart] Added game session: ${session.gameTitle} at ${session.createdAt}');
gameList.sort((a, b) => b.createdAt.compareTo(a.createdAt)); gameList.sort((a, b) => b.createdAt.compareTo(a.createdAt));
print(
'[game_manager.dart] Sorted game sessions by creation date. Total sessions: ${gameList.length}');
notifyListeners(); notifyListeners();
await LocalStorageService.saveGameSessions(); await LocalStorageService.saveGameSessions();
print('[game_manager.dart] Saved game sessions to local storage.');
return gameList.indexOf(session); return gameList.indexOf(session);
} }
@@ -30,12 +25,26 @@ class GameManager extends ChangeNotifier {
/// Takes a [index] as input. It then removes the session at the specified index from the `gameList`, /// Takes a [index] as input. It then removes the session at the specified index from the `gameList`,
/// sorts the list in descending order based on the creation date, and notifies listeners of the change. /// sorts the list in descending order based on the creation date, and notifies listeners of the change.
/// It also saves the updated game sessions to local storage. /// It also saves the updated game sessions to local storage.
void removeGameSession(int index) { void removeGameSessionByIndex(int index) {
gameList[index].removeListener(notifyListeners); gameList[index].removeListener(notifyListeners);
gameList.removeAt(index); gameList.removeAt(index);
notifyListeners(); notifyListeners();
LocalStorageService.saveGameSessions(); LocalStorageService.saveGameSessions();
} }
/// Removes a game session by its ID.
/// Takes a String [id] as input. It finds the index of the game session with the matching ID
/// in the `gameList`, and then calls `removeGameSessionByIndex` with that index.
void removeGameSessionById(String id) {
final int index =
gameList.indexWhere((session) => session.id.toString() == id);
if (index == -1) return;
removeGameSessionByIndex(index);
}
bool gameExistsInGameList(String id) {
return gameList.any((session) => session.id.toString() == id);
}
} }
final gameManager = GameManager(); final gameManager = GameManager();

View File

@@ -1,5 +1,6 @@
import 'package:cabo_counter/data/round.dart'; import 'package:cabo_counter/data/round.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:uuid/uuid.dart';
/// This class represents a game session for Cabo game. /// This class represents a game session for Cabo game.
/// [createdAt] is the timestamp of when the game session was created. /// [createdAt] is the timestamp of when the game session was created.
@@ -12,6 +13,7 @@ import 'package:flutter/cupertino.dart';
/// [isGameFinished] is a boolean indicating if the game has ended yet. /// [isGameFinished] is a boolean indicating if the game has ended yet.
/// [winner] is the name of the player who won the game. /// [winner] is the name of the player who won the game.
class GameSession extends ChangeNotifier { class GameSession extends ChangeNotifier {
late String id;
final DateTime createdAt; final DateTime createdAt;
final String gameTitle; final String gameTitle;
final List<String> players; final List<String> players;
@@ -33,17 +35,20 @@ class GameSession extends ChangeNotifier {
required this.isPointsLimitEnabled, required this.isPointsLimitEnabled,
}) { }) {
playerScores = List.filled(players.length, 0); playerScores = List.filled(players.length, 0);
var uuid = const Uuid();
id = uuid.v1();
} }
@override @override
toString() { toString() {
return ('GameSession: [createdAt: $createdAt, gameTitle: $gameTitle, ' return ('GameSession: [id: $id, createdAt: $createdAt, gameTitle: $gameTitle, '
'isPointsLimitEnabled: $isPointsLimitEnabled, pointLimit: $pointLimit, caboPenalty: $caboPenalty,' 'isPointsLimitEnabled: $isPointsLimitEnabled, pointLimit: $pointLimit, caboPenalty: $caboPenalty,'
' players: $players, playerScores: $playerScores, roundList: $roundList, winner: $winner]'); ' players: $players, playerScores: $playerScores, roundList: $roundList, winner: $winner]');
} }
/// Converts the GameSession object to a JSON map. /// Converts the GameSession object to a JSON map.
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'id': id,
'createdAt': createdAt.toIso8601String(), 'createdAt': createdAt.toIso8601String(),
'gameTitle': gameTitle, 'gameTitle': gameTitle,
'players': players, 'players': players,
@@ -59,7 +64,8 @@ class GameSession extends ChangeNotifier {
/// Creates a GameSession object from a JSON map. /// Creates a GameSession object from a JSON map.
GameSession.fromJson(Map<String, dynamic> json) GameSession.fromJson(Map<String, dynamic> json)
: createdAt = DateTime.parse(json['createdAt']), : id = json['id'] ?? const Uuid().v1(),
createdAt = DateTime.parse(json['createdAt']),
gameTitle = json['gameTitle'], gameTitle = json['gameTitle'],
players = List<String>.from(json['players']), players = List<String>.from(json['players']),
pointLimit = json['pointLimit'], pointLimit = json['pointLimit'],

View File

@@ -22,7 +22,7 @@
"empty_text_1": "Ganz schön leer hier...", "empty_text_1": "Ganz schön leer hier...",
"empty_text_2": "Füge über den Button oben rechts eine neue Runde hinzu", "empty_text_2": "Füge über den Button oben rechts eine neue Runde hinzu",
"delete_game_title": "Spiel löschen?", "delete_game_title": "Spiel löschen?",
"delete_game_message": "Bist du sicher, dass du die Runde {gameTitle} löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.", "delete_game_message": "Bist du sicher, dass du das Spiel \"{gameTitle}\" löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.",
"@delete_game_message": { "@delete_game_message": {
"placeholders": { "placeholders": {
"gameTitle": { "gameTitle": {
@@ -68,6 +68,9 @@
"delete_game": "Spiel löschen", "delete_game": "Spiel löschen",
"new_game_same_settings": "Neues Spiel mit gleichen Einstellungen", "new_game_same_settings": "Neues Spiel mit gleichen Einstellungen",
"export_game": "Spiel exportieren", "export_game": "Spiel exportieren",
"id_error_title": "ID Fehler",
"id_error_message": "Das Spiel hat bisher noch keine ID zugewiesen bekommen. Falls du das Spiel löschen möchtest, mache das bitte über das Hauptmenü. Alle neu erstellten Spiele haben eine ID.",
"game_process": "Spielverlauf", "game_process": "Spielverlauf",
@@ -80,7 +83,6 @@
"game_data": "Spieldaten", "game_data": "Spieldaten",
"import_data": "Daten importieren", "import_data": "Daten importieren",
"export_data": "Daten exportieren", "export_data": "Daten exportieren",
"error": "Fehler",
"import_success_title": "Import erfolgreich", "import_success_title": "Import erfolgreich",
"import_success_message":"Die Spieldaten wurden erfolgreich importiert.", "import_success_message":"Die Spieldaten wurden erfolgreich importiert.",
@@ -91,7 +93,8 @@
"import_generic_error_title": "Import fehlgeschlagen", "import_generic_error_title": "Import fehlgeschlagen",
"import_generic_error_message": "Der Import ist fehlgeschlagen.", "import_generic_error_message": "Der Import ist fehlgeschlagen.",
"error_export": "Datei konnte nicht exportiert werden", "export_error_title": "Fehler",
"export_error_message": "Datei konnte nicht exportiert werden",
"error_found": "Fehler gefunden?", "error_found": "Fehler gefunden?",
"create_issue": "Issue erstellen", "create_issue": "Issue erstellen",
"app_version": "App-Version", "app_version": "App-Version",

View File

@@ -22,7 +22,7 @@
"empty_text_1": "Pretty empty here...", "empty_text_1": "Pretty empty here...",
"empty_text_2": "Add a new round using the button in the top right corner.", "empty_text_2": "Add a new round using the button in the top right corner.",
"delete_game_title": "Delete game?", "delete_game_title": "Delete game?",
"delete_game_message": "Are you sure you want to delete the game {gameTitle}? This action cannot be undone.", "delete_game_message": "Are you sure you want to delete the game \"{gameTitle}\"? This action cannot be undone.",
"@delete_game_message": { "@delete_game_message": {
"placeholders": { "placeholders": {
"gameTitle": { "gameTitle": {
@@ -80,7 +80,8 @@
"game_data": "Game Data", "game_data": "Game Data",
"import_data": "Import Data", "import_data": "Import Data",
"export_data": "Export Data", "export_data": "Export Data",
"error": "Error", "id_error_title": "ID Error",
"id_error_message": "The game has not yet been assigned an ID. If you want to delete the game, please do so via the main menu. All newly created games have an ID.",
"import_success_title": "Import successful", "import_success_title": "Import successful",
"import_success_message":"The game data has been successfully imported.", "import_success_message":"The game data has been successfully imported.",
@@ -91,7 +92,8 @@
"import_generic_error_title": "Import failed", "import_generic_error_title": "Import failed",
"import_generic_error_message": "The import has failed.", "import_generic_error_message": "The import has failed.",
"error_export": "Could not export file", "export_error_title": "Export failed",
"export_error_message": "Could not export file",
"error_found": "Found a bug?", "error_found": "Found a bug?",
"create_issue": "Create Issue", "create_issue": "Create Issue",
"app_version": "App Version", "app_version": "App Version",

View File

@@ -215,7 +215,7 @@ abstract class AppLocalizations {
/// No description provided for @delete_game_message. /// No description provided for @delete_game_message.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
/// **'Bist du sicher, dass du die Runde {gameTitle} löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.'** /// **'Bist du sicher, dass du das Spiel \"{gameTitle}\" löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.'**
String delete_game_message(String gameTitle); String delete_game_message(String gameTitle);
/// No description provided for @overview. /// No description provided for @overview.
@@ -386,6 +386,18 @@ abstract class AppLocalizations {
/// **'Spiel exportieren'** /// **'Spiel exportieren'**
String get export_game; String get export_game;
/// No description provided for @id_error_title.
///
/// In de, this message translates to:
/// **'ID Fehler'**
String get id_error_title;
/// No description provided for @id_error_message.
///
/// In de, this message translates to:
/// **'Das Spiel hat bisher noch keine ID zugewiesen bekommen. Falls du das Spiel löschen möchtest, mache das bitte über das Hauptmenü. Alle neu erstellten Spiele haben eine ID.'**
String get id_error_message;
/// No description provided for @game_process. /// No description provided for @game_process.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
@@ -446,12 +458,6 @@ abstract class AppLocalizations {
/// **'Daten exportieren'** /// **'Daten exportieren'**
String get export_data; String get export_data;
/// No description provided for @error.
///
/// In de, this message translates to:
/// **'Fehler'**
String get error;
/// No description provided for @import_success_title. /// No description provided for @import_success_title.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
@@ -500,11 +506,17 @@ abstract class AppLocalizations {
/// **'Der Import ist fehlgeschlagen.'** /// **'Der Import ist fehlgeschlagen.'**
String get import_generic_error_message; String get import_generic_error_message;
/// No description provided for @error_export. /// No description provided for @export_error_title.
///
/// In de, this message translates to:
/// **'Fehler'**
String get export_error_title;
/// No description provided for @export_error_message.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
/// **'Datei konnte nicht exportiert werden'** /// **'Datei konnte nicht exportiert werden'**
String get error_export; String get export_error_message;
/// No description provided for @error_found. /// No description provided for @error_found.
/// ///

View File

@@ -68,7 +68,7 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String delete_game_message(String gameTitle) { String delete_game_message(String gameTitle) {
return 'Bist du sicher, dass du die Runde $gameTitle löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.'; return 'Bist du sicher, dass du das Spiel \"$gameTitle\" löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden.';
} }
@override @override
@@ -161,6 +161,13 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get export_game => 'Spiel exportieren'; String get export_game => 'Spiel exportieren';
@override
String get id_error_title => 'ID Fehler';
@override
String get id_error_message =>
'Das Spiel hat bisher noch keine ID zugewiesen bekommen. Falls du das Spiel löschen möchtest, mache das bitte über das Hauptmenü. Alle neu erstellten Spiele haben eine ID.';
@override @override
String get game_process => 'Spielverlauf'; String get game_process => 'Spielverlauf';
@@ -191,9 +198,6 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get export_data => 'Daten exportieren'; String get export_data => 'Daten exportieren';
@override
String get error => 'Fehler';
@override @override
String get import_success_title => 'Import erfolgreich'; String get import_success_title => 'Import erfolgreich';
@@ -222,7 +226,10 @@ class AppLocalizationsDe extends AppLocalizations {
String get import_generic_error_message => 'Der Import ist fehlgeschlagen.'; String get import_generic_error_message => 'Der Import ist fehlgeschlagen.';
@override @override
String get error_export => 'Datei konnte nicht exportiert werden'; String get export_error_title => 'Fehler';
@override
String get export_error_message => 'Datei konnte nicht exportiert werden';
@override @override
String get error_found => 'Fehler gefunden?'; String get error_found => 'Fehler gefunden?';

View File

@@ -68,7 +68,7 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String delete_game_message(String gameTitle) { String delete_game_message(String gameTitle) {
return 'Are you sure you want to delete the game $gameTitle? This action cannot be undone.'; return 'Are you sure you want to delete the game \"$gameTitle\"? This action cannot be undone.';
} }
@override @override
@@ -158,6 +158,13 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get export_game => 'Export Game'; String get export_game => 'Export Game';
@override
String get id_error_title => 'ID Error';
@override
String get id_error_message =>
'The game has not yet been assigned an ID. If you want to delete the game, please do so via the main menu. All newly created games have an ID.';
@override @override
String get game_process => 'Spielverlauf'; String get game_process => 'Spielverlauf';
@@ -188,9 +195,6 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get export_data => 'Export Data'; String get export_data => 'Export Data';
@override
String get error => 'Error';
@override @override
String get import_success_title => 'Import successful'; String get import_success_title => 'Import successful';
@@ -219,7 +223,10 @@ class AppLocalizationsEn extends AppLocalizations {
String get import_generic_error_message => 'The import has failed.'; String get import_generic_error_message => 'The import has failed.';
@override @override
String get error_export => 'Could not export file'; String get export_error_title => 'Export failed';
@override
String get export_error_message => 'Could not export file';
@override @override
String get error_found => 'Found a bug?'; String get error_found => 'Found a bug?';

View File

@@ -65,6 +65,7 @@ class _AppState extends State<App> with WidgetsBindingObserver {
return supportedLocales.first; return supportedLocales.first;
}, },
theme: CupertinoThemeData( theme: CupertinoThemeData(
applyThemeToAll: true,
brightness: Brightness.dark, brightness: Brightness.dark,
primaryColor: CustomTheme.primaryColor, primaryColor: CustomTheme.primaryColor,
scaffoldBackgroundColor: CustomTheme.backgroundColor, scaffoldBackgroundColor: CustomTheme.backgroundColor,

View File

@@ -86,6 +86,11 @@ class LocalStorageService {
GameSession.fromJson(jsonItem as Map<String, dynamic>)) GameSession.fromJson(jsonItem as Map<String, dynamic>))
.toList(); .toList();
for (GameSession session in gameManager.gameList) {
print(
'[local_storage_service.dart] Geladene Session: ${session.gameTitle} - ${session.id}');
}
print( print(
'[local_storage_service.dart] Die Spieldaten wurden erfolgreich geladen und verarbeitet'); '[local_storage_service.dart] Die Spieldaten wurden erfolgreich geladen und verarbeitet');
return true; return true;

View File

@@ -1,3 +1,4 @@
import 'package:cabo_counter/data/game_manager.dart';
import 'package:cabo_counter/data/game_session.dart'; import 'package:cabo_counter/data/game_session.dart';
import 'package:cabo_counter/l10n/app_localizations.dart'; import 'package:cabo_counter/l10n/app_localizations.dart';
import 'package:cabo_counter/utility/custom_theme.dart'; import 'package:cabo_counter/utility/custom_theme.dart';
@@ -17,15 +18,23 @@ class ActiveGameView extends StatefulWidget {
} }
class _ActiveGameViewState extends State<ActiveGameView> { class _ActiveGameViewState extends State<ActiveGameView> {
late final GameSession gameSession;
@override
void initState() {
super.initState();
gameSession = widget.gameSession;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListenableBuilder( return ListenableBuilder(
listenable: widget.gameSession, listenable: gameSession,
builder: (context, _) { builder: (context, _) {
List<int> sortedPlayerIndices = _getSortedPlayerIndices(); List<int> sortedPlayerIndices = _getSortedPlayerIndices();
return CupertinoPageScaffold( return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar( navigationBar: CupertinoNavigationBar(
middle: Text(widget.gameSession.gameTitle), middle: Text(gameSession.gameTitle),
), ),
child: SafeArea( child: SafeArea(
child: SingleChildScrollView( child: SingleChildScrollView(
@@ -42,7 +51,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemCount: widget.gameSession.players.length, itemCount: gameSession.players.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
int playerIndex = sortedPlayerIndices[index]; int playerIndex = sortedPlayerIndices[index];
return CupertinoListTile( return CupertinoListTile(
@@ -51,7 +60,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
_getPlacementPrefix(index), _getPlacementPrefix(index),
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text(
widget.gameSession.players[playerIndex], gameSession.players[playerIndex],
style: const TextStyle( style: const TextStyle(
fontWeight: FontWeight.bold), fontWeight: FontWeight.bold),
), ),
@@ -60,8 +69,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
trailing: Row( trailing: Row(
children: [ children: [
const SizedBox(width: 5), const SizedBox(width: 5),
Text( Text('${gameSession.playerScores[playerIndex]} '
'${widget.gameSession.playerScores[playerIndex]} '
'${AppLocalizations.of(context).points}') '${AppLocalizations.of(context).points}')
], ],
), ),
@@ -78,7 +86,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
ListView.builder( ListView.builder(
shrinkWrap: true, shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
itemCount: widget.gameSession.roundNumber, itemCount: gameSession.roundNumber,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Padding( return Padding(
padding: const EdgeInsets.all(1), padding: const EdgeInsets.all(1),
@@ -88,10 +96,9 @@ class _ActiveGameViewState extends State<ActiveGameView> {
title: Text( title: Text(
'${AppLocalizations.of(context).round} ${index + 1}', '${AppLocalizations.of(context).round} ${index + 1}',
), ),
trailing: index + 1 != trailing:
widget.gameSession.roundNumber || index + 1 != gameSession.roundNumber ||
widget.gameSession.isGameFinished == gameSession.isGameFinished == true
true
? (const Text('\u{2705}', ? (const Text('\u{2705}',
style: TextStyle(fontSize: 22))) style: TextStyle(fontSize: 22)))
: const Text('\u{23F3}', : const Text('\u{23F3}',
@@ -104,7 +111,7 @@ class _ActiveGameViewState extends State<ActiveGameView> {
CupertinoPageRoute( CupertinoPageRoute(
fullscreenDialog: true, fullscreenDialog: true,
builder: (context) => RoundView( builder: (context) => RoundView(
gameSession: widget.gameSession, gameSession: gameSession,
roundNumber: index + 1), roundNumber: index + 1),
), ),
); );
@@ -129,17 +136,21 @@ class _ActiveGameViewState extends State<ActiveGameView> {
), ),
onTap: () => Navigator.push( onTap: () => Navigator.push(
context, context,
MaterialPageRoute( CupertinoPageRoute(
builder: (_) => GraphView( builder: (_) => GraphView(
gameSession: widget.gameSession, gameSession: gameSession,
)))), )))),
CupertinoListTile( CupertinoListTile(
title: title: Text(
Text(AppLocalizations.of(context).delete_game, AppLocalizations.of(context).delete_game,
style: const TextStyle( ),
color: Colors.white30, onTap: () {
)), _showDeleteGameDialog().then((value) {
onTap: () {}, if (value) {
_removeGameSession(gameSession);
}
});
},
), ),
CupertinoListTile( CupertinoListTile(
title: Text( title: Text(
@@ -151,12 +162,11 @@ class _ActiveGameViewState extends State<ActiveGameView> {
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (_) => CreateGameView( builder: (_) => CreateGameView(
gameTitle: gameTitle: gameSession.gameTitle,
widget.gameSession.gameTitle,
isPointsLimitEnabled: widget isPointsLimitEnabled: widget
.gameSession .gameSession
.isPointsLimitEnabled, .isPointsLimitEnabled,
players: widget.gameSession.players, players: gameSession.players,
))); )));
}, },
), ),
@@ -180,11 +190,11 @@ class _ActiveGameViewState extends State<ActiveGameView> {
/// ascending order. /// ascending order.
List<int> _getSortedPlayerIndices() { List<int> _getSortedPlayerIndices() {
List<int> playerIndices = List<int> playerIndices =
List<int>.generate(widget.gameSession.players.length, (index) => index); List<int>.generate(gameSession.players.length, (index) => index);
// Sort the indices based on the summed points // Sort the indices based on the summed points
playerIndices.sort((a, b) { playerIndices.sort((a, b) {
int scoreA = widget.gameSession.playerScores[a]; int scoreA = gameSession.playerScores[a];
int scoreB = widget.gameSession.playerScores[b]; int scoreB = gameSession.playerScores[b];
return scoreA.compareTo(scoreB); return scoreA.compareTo(scoreB);
}); });
return playerIndices; return playerIndices;
@@ -217,4 +227,61 @@ class _ActiveGameViewState extends State<ActiveGameView> {
); );
} }
} }
Future<bool> _showDeleteGameDialog() async {
return await showCupertinoDialog<bool>(
context: context,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text(AppLocalizations.of(context).delete_game_title),
content: Text(
AppLocalizations.of(context)
.delete_game_message(gameSession.gameTitle),
),
actions: [
CupertinoDialogAction(
child: Text(AppLocalizations.of(context).cancel),
onPressed: () => Navigator.pop(context, false),
),
CupertinoDialogAction(
child: Text(
AppLocalizations.of(context).delete,
style: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.red),
),
onPressed: () {
Navigator.pop(context, true);
},
),
],
);
},
) ??
false;
}
Future<void> _removeGameSession(GameSession gameSession) async {
if (gameManager.gameExistsInGameList(gameSession.id)) {
Navigator.pop(context);
WidgetsBinding.instance.addPostFrameCallback((_) {
gameManager.removeGameSessionById(gameSession.id);
});
} else {
showCupertinoDialog(
context: context,
builder: (BuildContext context) {
return CupertinoAlertDialog(
title: Text(AppLocalizations.of(context).id_error_title),
content: Text(AppLocalizations.of(context).id_error_message),
actions: [
CupertinoDialogAction(
child: Text(AppLocalizations.of(context).ok),
onPressed: () => Navigator.pop(context),
),
],
);
});
}
}
} }

View File

@@ -320,12 +320,13 @@ class _CreateGameViewState extends State<CreateGameView> {
isPointsLimitEnabled: _isPointsLimitEnabled!, isPointsLimitEnabled: _isPointsLimitEnabled!,
); );
final index = await gameManager.addGameSession(gameSession); final index = await gameManager.addGameSession(gameSession);
final session = gameManager.gameList[index];
if (context.mounted) { if (context.mounted) {
Navigator.pushReplacement( Navigator.pushReplacement(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => ActiveGameView( builder: (context) =>
gameSession: gameManager.gameList[index]))); ActiveGameView(gameSession: session)));
} }
}, },
), ),

View File

@@ -131,7 +131,8 @@ class _MainMenuViewState extends State<MainMenuView> {
gameTitle); gameTitle);
}, },
onDismissed: (direction) { onDismissed: (direction) {
gameManager.removeGameSession(index); gameManager
.removeGameSessionByIndex(index);
}, },
dismissThresholds: const { dismissThresholds: const {
DismissDirection.startToEnd: 0.6 DismissDirection.startToEnd: 0.6
@@ -168,18 +169,19 @@ class _MainMenuViewState extends State<MainMenuView> {
CupertinoIcons.person_2_fill), CupertinoIcons.person_2_fill),
], ],
), ),
onTap: () async { onTap: () {
//ignore: unused_local_variable final session =
final val = await Navigator.push( gameManager.gameList[index];
Navigator.push(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => builder: (context) =>
ActiveGameView( ActiveGameView(
gameSession: gameManager gameSession: session),
.gameList[index]),
), ),
); ).then((_) {
setState(() {}); setState(() {});
});
}, },
), ),
), ),
@@ -224,7 +226,11 @@ class _MainMenuViewState extends State<MainMenuView> {
onPressed: () { onPressed: () {
Navigator.pop(context, true); Navigator.pop(context, true);
}, },
child: Text(AppLocalizations.of(context).delete), child: Text(
AppLocalizations.of(context).delete,
style: const TextStyle(
fontWeight: FontWeight.bold, color: Colors.red),
),
), ),
], ],
); );

View File

@@ -145,10 +145,10 @@ class _SettingsViewState extends State<SettingsView> {
showCupertinoDialog( showCupertinoDialog(
context: context, context: context,
builder: (context) => CupertinoAlertDialog( builder: (context) => CupertinoAlertDialog(
title: title: Text(AppLocalizations.of(context)
Text(AppLocalizations.of(context).error), .export_error_title),
content: Text(AppLocalizations.of(context) content: Text(AppLocalizations.of(context)
.error_export), .export_error_message),
actions: [ actions: [
CupertinoDialogAction( CupertinoDialogAction(
child: child:

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.3.5+269 version: 0.3.6+318
environment: environment:
sdk: ^3.5.4 sdk: ^3.5.4
@@ -26,6 +26,7 @@ dependencies:
sdk: flutter sdk: flutter
intl: any intl: any
syncfusion_flutter_charts: ^30.1.37 syncfusion_flutter_charts: ^30.1.37
uuid: ^4.5.1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: