Added new kamikaze button and bundles navigation functionality

This commit is contained in:
2025-07-19 16:46:20 +02:00
parent bda9f00501
commit 0ac446b032
7 changed files with 84 additions and 25 deletions

View File

@@ -71,6 +71,7 @@
"results": "Ergebnisse",
"who_said_cabo": "Wer hat CABO gesagt?",
"kamikaze": "Kamikaze",
"who_has_kamikaze": "Wer hat Kamikaze?",
"done": "Fertig",
"next_round": "Nächste Runde",
"bonus_points_title": "Bonus-Punkte!",

View File

@@ -71,6 +71,7 @@
"results": "Results",
"who_said_cabo": "Who called Cabo?",
"kamikaze": "Kamikaze",
"who_has_kamikaze": "Who has Kamikaze?",
"done": "Done",
"next_round": "Next Round",
"bonus_points_title": "Bonus-Points!",

View File

@@ -404,6 +404,12 @@ abstract class AppLocalizations {
/// **'Kamikaze'**
String get kamikaze;
/// No description provided for @who_has_kamikaze.
///
/// In de, this message translates to:
/// **'Wer hat Kamikaze?'**
String get who_has_kamikaze;
/// No description provided for @done.
///
/// In de, this message translates to:

View File

@@ -172,6 +172,9 @@ class AppLocalizationsDe extends AppLocalizations {
@override
String get kamikaze => 'Kamikaze';
@override
String get who_has_kamikaze => 'Wer hat Kamikaze?';
@override
String get done => 'Fertig';

View File

@@ -170,6 +170,9 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get kamikaze => 'Kamikaze';
@override
String get who_has_kamikaze => 'Who has Kamikaze?';
@override
String get done => 'Done';

View File

@@ -154,6 +154,17 @@ class _RoundViewState extends State<RoundView> {
),
),
),
Center(
child: CupertinoButton(
onPressed: () async {
if (await _showKamikazeSheet(context)) {
if (!context.mounted) return;
_endOfRoundNavigation(context, true);
}
},
child: Text(AppLocalizations.of(context).kamikaze),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: CupertinoListTile(
@@ -308,15 +319,8 @@ class _RoundViewState extends State<RoundView> {
children: [
CupertinoButton(
onPressed: _areRoundInputsValid()
? () async {
List<int> bonusPlayersIndices = _finishRound();
if (bonusPlayersIndices.isNotEmpty) {
await _showBonusPopup(
context, bonusPlayersIndices);
}
LocalStorageService.saveGameSessions();
if (!context.mounted) return;
Navigator.pop(context);
? () {
_endOfRoundNavigation(context, false);
}
: null,
child: Text(AppLocalizations.of(context).done),
@@ -324,21 +328,8 @@ class _RoundViewState extends State<RoundView> {
if (!widget.gameSession.isGameFinished)
CupertinoButton(
onPressed: _areRoundInputsValid()
? () async {
List<int> bonusPlayersIndices =
_finishRound();
if (bonusPlayersIndices.isNotEmpty) {
await _showBonusPopup(
context, bonusPlayersIndices);
}
LocalStorageService.saveGameSessions();
if (widget.gameSession.isGameFinished &&
context.mounted) {
Navigator.pop(context);
} else if (context.mounted) {
Navigator.pop(
context, widget.roundNumber + 1);
}
? () {
_endOfRoundNavigation(context, true);
}
: null,
child: Text(AppLocalizations.of(context).next_round),
@@ -401,6 +392,36 @@ class _RoundViewState extends State<RoundView> {
];
}
Future<bool> _showKamikazeSheet(BuildContext context) async {
return await showCupertinoModalPopup<bool?>(
context: context,
builder: (BuildContext context) {
return CupertinoActionSheet(
title: Text(AppLocalizations.of(context).kamikaze),
message: Text(AppLocalizations.of(context).who_has_kamikaze),
actions: widget.gameSession.players.asMap().entries.map((entry) {
final index = entry.key;
final name = entry.value;
return CupertinoActionSheetAction(
onPressed: () {
_kamikazePlayerIndex =
_kamikazePlayerIndex == index ? null : index;
Navigator.pop(context, true);
},
child: Text(name),
);
}).toList(),
cancelButton: CupertinoActionSheetAction(
onPressed: () => Navigator.pop(context, false),
isDestructiveAction: true,
child: Text(AppLocalizations.of(context).cancel),
),
);
},
) ??
false;
}
/// Focuses the next text field in the list of text fields.
/// [index] is the index of the current text field.
void _focusNextTextfield(int index) {
@@ -521,6 +542,30 @@ class _RoundViewState extends State<RoundView> {
return resultText;
}
/// Handles the navigation for the end of the round.
/// It checks for bonus players and shows a popup, saves the game session,
/// and navigates to the next round or back to the previous screen.
/// It takes the BuildContext [context] and a boolean [navigateToNextRound] to determine
/// if it should navigate to the next round or not.
Future<void> _endOfRoundNavigation(
BuildContext context, bool navigateToNextRound) async {
List<int> bonusPlayersIndices = _finishRound();
if (bonusPlayersIndices.isNotEmpty) {
await _showBonusPopup(context, bonusPlayersIndices);
}
LocalStorageService.saveGameSessions();
if (context.mounted) {
if (!navigateToNextRound || widget.gameSession.isGameFinished) {
Navigator.pop(context);
return;
} else {
Navigator.pop(context, widget.roundNumber + 1);
}
}
}
@override
void dispose() {
for (final controller in _scoreControllerList) {

View File

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