Updated buttons, implemented animatedOpacity

This commit is contained in:
2025-07-20 17:51:30 +02:00
parent 5ebce36c12
commit a4693ccf39
4 changed files with 117 additions and 172 deletions

View File

@@ -365,7 +365,7 @@ abstract class AppLocalizations {
/// No description provided for @no_name_message. /// No description provided for @no_name_message.
/// ///
/// In de, this message translates to: /// In de, this message translates to:
/// **'Jeder Spieler muss einen Namen haben.'** /// **'Jede:r Spieler:in muss einen Namen haben.'**
String get no_name_message; String get no_name_message;
/// No description provided for @select_game_mode. /// No description provided for @select_game_mode.

View File

@@ -149,7 +149,7 @@ class AppLocalizationsDe extends AppLocalizations {
String get no_name_title => 'Kein Name'; String get no_name_title => 'Kein Name';
@override @override
String get no_name_message => 'Jeder Spieler muss einen Namen haben.'; String get no_name_message => 'Jede:r Spieler:in muss einen Namen haben.';
@override @override
String get select_game_mode => 'Spielmodus auswählen'; String get select_game_mode => 'Spielmodus auswählen';

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/active_game_view.dart'; import 'package:cabo_counter/presentation/views/active_game_view.dart';
import 'package:cabo_counter/presentation/views/mode_selection_view.dart'; import 'package:cabo_counter/presentation/views/mode_selection_view.dart';
import 'package:cabo_counter/presentation/widgets/custom_button.dart';
import 'package:cabo_counter/services/config_service.dart'; import 'package:cabo_counter/services/config_service.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -136,97 +137,28 @@ class _CreateGameViewState extends State<CreateGameView> {
style: CustomTheme.rowTitle, style: CustomTheme.rowTitle,
), ),
), ),
Expanded( Flexible(
child: ReorderableListView.builder( child: ReorderableListView.builder(
physics: const NeverScrollableScrollPhysics(), shrinkWrap: true,
itemCount: _playerNameTextControllers.length + 2, physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(8),
itemCount: _playerNameTextControllers.length,
onReorder: (oldIndex, newIndex) { onReorder: (oldIndex, newIndex) {
setState(() {
if (oldIndex < _playerNameTextControllers.length && if (oldIndex < _playerNameTextControllers.length &&
newIndex <= _playerNameTextControllers.length) { newIndex <= _playerNameTextControllers.length) {
setState(() {
if (newIndex > oldIndex) newIndex--; if (newIndex > oldIndex) newIndex--;
final item = final item =
_playerNameTextControllers.removeAt(oldIndex); _playerNameTextControllers.removeAt(oldIndex);
_playerNameTextControllers.insert(newIndex, item); _playerNameTextControllers.insert(newIndex, item);
});
} }
});
}, },
itemBuilder: (context, index) { itemBuilder: (context, index) {
// Create game button
if (index == _playerNameTextControllers.length + 1) {
return Container(
key: const ValueKey('create_game_button'),
child: CupertinoButton(
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: CustomTheme.primaryColor,
),
padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 8),
child: Text(
AppLocalizations.of(context).create_game,
style: TextStyle(
color: CustomTheme.backgroundColor,
),
),
),
],
),
onPressed: () {
_checkAllGameAttributes();
},
),
);
}
// Add player button
if (index == _playerNameTextControllers.length) {
return Container(
key: const ValueKey('add_player_button'),
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 4.0, horizontal: 10),
child: CupertinoButton(
padding: EdgeInsets.zero,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Icon(
CupertinoIcons.add_circled_solid,
color: CustomTheme.primaryColor,
),
const SizedBox(width: 6),
Text(
AppLocalizations.of(context)
.add_player,
style: TextStyle(
color:
CustomTheme.primaryColor),
),
]),
onPressed: () {
if (_playerNameTextControllers.length <
maxPlayers) {
setState(() {
_playerNameTextControllers
.add(TextEditingController());
});
} else {
showFeedbackDialog(
CreateStatus.maxPlayers);
}
})));
} else {
// Player entries
return Padding( return Padding(
key: ValueKey(_playerNameTextControllers[index]), key: ValueKey(
padding: const EdgeInsets.symmetric( 'player_${_playerNameTextControllers[index].hashCode}'),
vertical: 8.0, horizontal: 5), padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Row( child: Row(
children: [ children: [
CupertinoButton( CupertinoButton(
@@ -253,70 +185,83 @@ class _CreateGameViewState extends State<CreateGameView> {
decoration: const BoxDecoration(), decoration: const BoxDecoration(),
), ),
), ),
AnimatedOpacity(
opacity: _playerNameTextControllers.length > 1
? 1.0
: 0.0,
duration: const Duration(milliseconds: 300),
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: ReorderableDragStartListener(
index: index,
child: const Icon(
CupertinoIcons.line_horizontal_3,
color: CupertinoColors.systemGrey,
),
),
),
)
], ],
), ),
); );
} }),
})), ),
Center( Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 0, 50),
child: Center(
child: CupertinoButton( child: CupertinoButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text( CupertinoButton(
AppLocalizations.of(context).create_game, padding: EdgeInsets.zero,
style: const TextStyle( onPressed: null,
color: CupertinoColors.activeGreen, child: Icon(
CupertinoIcons.plus_circle_fill,
color: CustomTheme.primaryColor,
size: 25,
)),
Stack(children: [
Expanded(
child: Center(
child: Text(
AppLocalizations.of(context).add_player,
style: TextStyle(color: CustomTheme.primaryColor),
), ),
), ),
),
]),
], ],
), ),
onPressed: () async { onPressed: () {
if (_gameTitleTextController.text == '') { if (_playerNameTextControllers.length < maxPlayers) {
showFeedbackDialog(CreateStatus.noGameTitle); setState(() {
return; _playerNameTextControllers.add(TextEditingController());
} });
if (gameMode == GameMode.none) { } else {
showFeedbackDialog(CreateStatus.noModeSelected); showFeedbackDialog(CreateStatus.maxPlayers);
return;
}
if (_playerNameTextControllers.length < 2) {
showFeedbackDialog(CreateStatus.minPlayers);
return;
}
if (!everyPlayerHasAName()) {
showFeedbackDialog(CreateStatus.noPlayerName);
return;
}
List<String> players = [];
for (var controller in _playerNameTextControllers) {
players.add(controller.text);
}
bool isPointsLimitEnabled = gameMode == GameMode.pointLimit;
GameSession gameSession = GameSession(
createdAt: DateTime.now(),
gameTitle: _gameTitleTextController.text,
players: players,
pointLimit: ConfigService.getPointLimit(),
caboPenalty: ConfigService.getCaboPenalty(),
isPointsLimitEnabled: isPointsLimitEnabled,
);
final index = await gameManager.addGameSession(gameSession);
final session = gameManager.gameList[index];
if (context.mounted) {
Navigator.pushReplacement(
context,
CupertinoPageRoute(
builder: (context) =>
ActiveGameView(gameSession: session)));
} }
}, },
), ),
), ),
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 50),
child: Center(
key: const ValueKey('create_game_button'),
child: CustomButton(
child: Text(
AppLocalizations.of(context).create_game,
style: TextStyle(
color: CustomTheme.primaryColor,
),
),
onPressed: () {
_checkAllGameAttributes();
},
),
),
),
], ],
)))); ))));
} }

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+556 version: 0.5.0+558
environment: environment:
sdk: ^3.5.4 sdk: ^3.5.4