From 349ff948defb9b668d6783511fcdadd048a09a20 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 9 Jan 2026 19:50:44 +0100 Subject: [PATCH 01/29] Modified match tile --- .../main_menu/match_view/match_view.dart | 29 ++++++++++--------- .../widgets/tiles/match_tile.dart | 12 ++++++-- pubspec.yaml | 7 +---- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index 45b957f..108b592 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -78,20 +78,23 @@ class _MatchViewState extends State { height: MediaQuery.paddingOf(context).bottom - 20, ); } - return MatchTile( - onTap: () async { - Navigator.push( - context, - CupertinoPageRoute( - fullscreenDialog: true, - builder: (context) => MatchResultView( - match: matches[index], - onWinnerChanged: loadGames, + return Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: MatchTile( + onTap: () async { + Navigator.push( + context, + CupertinoPageRoute( + fullscreenDialog: true, + builder: (context) => MatchResultView( + match: matches[index], + onWinnerChanged: loadGames, + ), ), - ), - ); - }, - match: matches[index], + ); + }, + match: matches[index], + ), ); }, ), diff --git a/lib/presentation/widgets/tiles/match_tile.dart b/lib/presentation/widgets/tiles/match_tile.dart index 55d81c3..21e24c0 100644 --- a/lib/presentation/widgets/tiles/match_tile.dart +++ b/lib/presentation/widgets/tiles/match_tile.dart @@ -11,7 +11,12 @@ import 'package:intl/intl.dart'; /// - [match]: The match data to be displayed. /// - [onTap]: The callback invoked when the tile is tapped. class MatchTile extends StatefulWidget { - const MatchTile({super.key, required this.match, required this.onTap}); + const MatchTile({ + super.key, + required this.match, + required this.onTap, + this.width, + }); /// The match data to be displayed. final Match match; @@ -19,6 +24,8 @@ class MatchTile extends StatefulWidget { /// The callback invoked when the tile is tapped. final VoidCallback onTap; + final double? width; + @override State createState() => _MatchTileState(); } @@ -41,7 +48,8 @@ class _MatchTileState extends State { return GestureDetector( onTap: widget.onTap, child: Container( - margin: CustomTheme.tileMargin, + margin: EdgeInsets.zero, + width: widget.width, padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: CustomTheme.boxColor, diff --git a/pubspec.yaml b/pubspec.yaml index e79ca17..993ef78 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.1+21 +version: 0.0.1+23 environment: sdk: ^3.8.1 @@ -9,11 +9,6 @@ environment: dependencies: flutter: sdk: flutter - material_symbols_icons: ^4.2815.1 - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 drift: ^2.27.0 drift_flutter: ^0.2.4 path_provider: ^2.1.5 From a9d2325eee9c9f4ed4ab83cb0d8367bc864df987 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 9 Jan 2026 19:50:51 +0100 Subject: [PATCH 02/29] Implemented match tile in home view --- .../views/main_menu/home_view.dart | 132 +++++++++++------- 1 file changed, 84 insertions(+), 48 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 170adb4..0761f08 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -5,10 +5,11 @@ import 'package:game_tracker/data/dto/group.dart'; import 'package:game_tracker/data/dto/match.dart'; import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; +import 'package:game_tracker/presentation/views/main_menu/match_view/match_result_view.dart'; import 'package:game_tracker/presentation/widgets/app_skeleton.dart'; import 'package:game_tracker/presentation/widgets/buttons/quick_create_button.dart'; import 'package:game_tracker/presentation/widgets/tiles/info_tile.dart'; -import 'package:game_tracker/presentation/widgets/tiles/match_summary_tile.dart'; +import 'package:game_tracker/presentation/widgets/tiles/match_tile.dart'; import 'package:game_tracker/presentation/widgets/tiles/quick_info_tile.dart'; import 'package:provider/provider.dart'; @@ -86,6 +87,38 @@ class _HomeViewState extends State { ], ), Padding( + padding: const EdgeInsets.only(top: 8.0), + child: MatchTile( + width: constraints.maxWidth * 0.95, + match: recentMatches[0], + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => + MatchResultView(match: recentMatches[0]), + ), + ); + }, + ), + ), + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: MatchTile( + width: constraints.maxWidth * 0.95, + match: recentMatches[1], + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => + MatchResultView(match: recentMatches[1]), + ), + ); + }, + ), + ), + /*Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: InfoTile( width: constraints.maxWidth * 0.95, @@ -156,53 +189,56 @@ class _HomeViewState extends State { ), ), ), - ), - InfoTile( - width: constraints.maxWidth * 0.95, - title: loc.quick_create, - icon: Icons.add_box_rounded, - content: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - QuickCreateButton( - text: 'Category 1', - onPressed: () {}, - ), - QuickCreateButton( - text: 'Category 2', - onPressed: () {}, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - QuickCreateButton( - text: 'Category 3', - onPressed: () {}, - ), - QuickCreateButton( - text: 'Category 4', - onPressed: () {}, - ), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - QuickCreateButton( - text: 'Category 5', - onPressed: () {}, - ), - QuickCreateButton( - text: 'Category 6', - onPressed: () {}, - ), - ], - ), - ], + ),*/ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: InfoTile( + width: constraints.maxWidth * 0.95, + title: loc.quick_create, + icon: Icons.add_box_rounded, + content: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton( + text: 'Category 1', + onPressed: () {}, + ), + QuickCreateButton( + text: 'Category 2', + onPressed: () {}, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton( + text: 'Category 3', + onPressed: () {}, + ), + QuickCreateButton( + text: 'Category 4', + onPressed: () {}, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + QuickCreateButton( + text: 'Category 5', + onPressed: () {}, + ), + QuickCreateButton( + text: 'Category 6', + onPressed: () {}, + ), + ], + ), + ], + ), ), ), ], From 3d510d5b3d5ea1efccdc40030da73a839adeeb67 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 9 Jan 2026 20:04:10 +0100 Subject: [PATCH 03/29] Implemented compact mode for match tiles --- .../views/main_menu/home_view.dart | 2 + .../widgets/tiles/match_tile.dart | 63 ++++++++++++++++++- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 0761f08..6599b98 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -89,6 +89,7 @@ class _HomeViewState extends State { Padding( padding: const EdgeInsets.only(top: 8.0), child: MatchTile( + compact: true, width: constraints.maxWidth * 0.95, match: recentMatches[0], onTap: () { @@ -105,6 +106,7 @@ class _HomeViewState extends State { Padding( padding: const EdgeInsets.only(top: 8.0), child: MatchTile( + compact: true, width: constraints.maxWidth * 0.95, match: recentMatches[1], onTap: () { diff --git a/lib/presentation/widgets/tiles/match_tile.dart b/lib/presentation/widgets/tiles/match_tile.dart index 21e24c0..59ee0b9 100644 --- a/lib/presentation/widgets/tiles/match_tile.dart +++ b/lib/presentation/widgets/tiles/match_tile.dart @@ -10,12 +10,15 @@ import 'package:intl/intl.dart'; /// creation date, associated group, winner, and players. /// - [match]: The match data to be displayed. /// - [onTap]: The callback invoked when the tile is tapped. +/// - [width]: Optional width for the tile. +/// - [compact]: Whether to display the tile in a compact mode class MatchTile extends StatefulWidget { const MatchTile({ super.key, required this.match, required this.onTap, this.width, + this.compact = false, }); /// The match data to be displayed. @@ -24,8 +27,12 @@ class MatchTile extends StatefulWidget { /// The callback invoked when the tile is tapped. final VoidCallback onTap; + /// Optional width for the tile. final double? width; + /// Whether to display the tile in a compact mode + final bool compact; + @override State createState() => _MatchTileState(); } @@ -88,7 +95,22 @@ class _MatchTileState extends State { const SizedBox(width: 6), Expanded( child: Text( - group.name, + '${group.name}${widget.match.players != null ? ' + ${widget.match.players?.length}' : ''}', + style: const TextStyle(fontSize: 14, color: Colors.grey), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SizedBox(height: 12), + ] else if (widget.compact) ...[ + Row( + children: [ + const Icon(Icons.person, size: 16, color: Colors.grey), + const SizedBox(width: 6), + Expanded( + child: Text( + '${widget.match.players!.length} ${loc.players}', style: const TextStyle(fontSize: 14, color: Colors.grey), overflow: TextOverflow.ellipsis, ), @@ -135,9 +157,46 @@ class _MatchTileState extends State { ), ), const SizedBox(height: 12), + ] else ...[ + Container( + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 12, + ), + decoration: BoxDecoration( + color: Colors.amber.withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: Colors.amber.withValues(alpha: 0.3), + width: 1, + ), + ), + child: Row( + children: [ + const Icon( + Icons.watch_later, + size: 20, + color: Colors.amber, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + loc.match_in_progress, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w600, + color: CustomTheme.textColor, + ), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + const SizedBox(height: 12), ], - if (_allPlayers.isNotEmpty) ...[ + if (_allPlayers.isNotEmpty && widget.compact == false) ...[ Text( loc.players, style: const TextStyle( From afb7a5f1d4c18be253b15b6acb2d8187b9ae9b00 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 9 Jan 2026 20:15:50 +0100 Subject: [PATCH 04/29] MatchTiles only show when recent games are available --- .../views/main_menu/home_view.dart | 66 ++++++++++--------- pubspec.yaml | 2 +- 2 files changed, 35 insertions(+), 33 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 6599b98..a94eae4 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -86,40 +86,42 @@ class _HomeViewState extends State { ), ], ), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: MatchTile( - compact: true, - width: constraints.maxWidth * 0.95, - match: recentMatches[0], - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, - builder: (context) => - MatchResultView(match: recentMatches[0]), - ), - ); - }, + if (recentMatches.isNotEmpty) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: MatchTile( + compact: true, + width: constraints.maxWidth * 0.95, + match: recentMatches[0], + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => + MatchResultView(match: recentMatches[0]), + ), + ); + }, + ), ), - ), - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: MatchTile( - compact: true, - width: constraints.maxWidth * 0.95, - match: recentMatches[1], - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, - builder: (context) => - MatchResultView(match: recentMatches[1]), - ), - ); - }, + if (recentMatches.length > 1) + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: MatchTile( + compact: true, + width: constraints.maxWidth * 0.95, + match: recentMatches[1], + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => + MatchResultView(match: recentMatches[1]), + ), + ); + }, + ), ), - ), /*Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: InfoTile( diff --git a/pubspec.yaml b/pubspec.yaml index 993ef78..835cabf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.1+23 +version: 0.0.1+43 environment: sdk: ^3.8.1 From 644728a9dfffb7d0c1ec26f77379a475fe9d49a5 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 9 Jan 2026 20:18:52 +0100 Subject: [PATCH 05/29] Removed unneccesary code --- .../views/main_menu/home_view.dart | 92 ------------------- pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 93 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index a94eae4..c9825c8 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -122,78 +122,6 @@ class _HomeViewState extends State { }, ), ), - /*Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), - child: InfoTile( - width: constraints.maxWidth * 0.95, - title: loc.recent_matches, - icon: Icons.timer, - content: Padding( - padding: const EdgeInsets.symmetric(horizontal: 40.0), - child: Visibility( - visible: !isLoading && loadedRecentMatches.isNotEmpty, - replacement: Center( - heightFactor: 12, - child: Text( - AppLocalizations.of( - context, - ).no_recent_matches_available, - ), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - MatchSummaryTile( - matchTitle: recentMatches[0].name, - game: 'Winner', - ruleset: 'Ruleset', - players: _getPlayerText( - recentMatches[0], - context, - ), - winner: recentMatches[0].winner == null - ? AppLocalizations.of( - context, - ).match_in_progress - : recentMatches[0].winner!.name, - ), - const Padding( - padding: EdgeInsets.symmetric(vertical: 8.0), - child: Divider(), - ), - if (loadedRecentMatches.length > 1) ...[ - MatchSummaryTile( - matchTitle: recentMatches[1].name, - game: 'Winner', - ruleset: 'Ruleset', - players: _getPlayerText( - recentMatches[1], - context, - ), - winner: recentMatches[1].winner == null - ? AppLocalizations.of( - context, - ).match_in_progress - : recentMatches[1].winner!.name, - ), - const SizedBox(height: 8), - ] else ...[ - Center( - heightFactor: 5.35, - child: Text( - AppLocalizations.of( - context, - ).no_second_match_available, - ), - ), - ], - ], - ), - ), - ), - ), - ),*/ Padding( padding: const EdgeInsets.only(top: 8.0), child: InfoTile( @@ -271,11 +199,6 @@ class _HomeViewState extends State { ..sort((a, b) => b.createdAt.compareTo(a.createdAt))) .take(2) .toList(); - if (loadedRecentMatches.length < 2) { - recentMatches.add( - Match(name: 'Dummy Match', winner: null, group: null, players: null), - ); - } if (mounted) { setState(() { isLoading = false; @@ -283,19 +206,4 @@ class _HomeViewState extends State { } }); } - - /// Generates a text representation of the players in the match. - /// If the match has a group, it returns the group name and the number of additional players. - /// If there is no group, it returns the count of players. - String _getPlayerText(Match game, context) { - final loc = AppLocalizations.of(context); - if (game.group == null) { - final playerCount = game.players?.length ?? 0; - return loc.players_count(playerCount); - } - if (game.players == null || game.players!.isEmpty) { - return game.group!.name; - } - return '${game.group!.name} + ${game.players!.length}'; - } } diff --git a/pubspec.yaml b/pubspec.yaml index 835cabf..5887957 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.1+43 +version: 0.0.2+47 environment: sdk: ^3.8.1 From 799c849570685334cdcb82279b694c96e7b2bf7f Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Fri, 9 Jan 2026 21:55:58 +0100 Subject: [PATCH 06/29] wrap every view that uses a snackbar in ScaffoldMessenger --- .../group_view/create_group_view.dart | 114 ++++---- .../create_match/create_match_view.dart | 254 +++++++++--------- .../views/main_menu/settings_view.dart | 196 +++++++------- 3 files changed, 285 insertions(+), 279 deletions(-) diff --git a/lib/presentation/views/main_menu/group_view/create_group_view.dart b/lib/presentation/views/main_menu/group_view/create_group_view.dart index f92df0f..8192c6b 100644 --- a/lib/presentation/views/main_menu/group_view/create_group_view.dart +++ b/lib/presentation/views/main_menu/group_view/create_group_view.dart @@ -44,66 +44,68 @@ class _CreateGroupViewState extends State { @override Widget build(BuildContext context) { final loc = AppLocalizations.of(context); - return Scaffold( - backgroundColor: CustomTheme.backgroundColor, - appBar: AppBar(title: Text(loc.create_new_group)), - body: SafeArea( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: CustomTheme.standardMargin, - child: TextInputField( - controller: _groupNameController, - hintText: loc.group_name, + return ScaffoldMessenger( + child: Scaffold( + backgroundColor: CustomTheme.backgroundColor, + appBar: AppBar(title: Text(loc.create_new_group)), + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: CustomTheme.standardMargin, + child: TextInputField( + controller: _groupNameController, + hintText: loc.group_name, + ), ), - ), - Expanded( - child: PlayerSelection( - onChanged: (value) { - setState(() { - selectedPlayers = [...value]; - }); - }, + Expanded( + child: PlayerSelection( + onChanged: (value) { + setState(() { + selectedPlayers = [...value]; + }); + }, + ), ), - ), - CustomWidthButton( - text: loc.create_group, - sizeRelativeToWidth: 0.95, - buttonType: ButtonType.primary, - onPressed: - (_groupNameController.text.isEmpty || - (selectedPlayers.length < 2)) - ? null - : () async { - bool success = await db.groupDao.addGroup( - group: Group( - name: _groupNameController.text.trim(), - members: selectedPlayers, - ), - ); - if (!context.mounted) return; - if (success) { - Navigator.pop(context); - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - backgroundColor: CustomTheme.boxColor, - content: Center( - child: Text( - AppLocalizations.of( - context, - ).error_creating_group, - style: const TextStyle(color: Colors.white), - ), - ), + CustomWidthButton( + text: loc.create_group, + sizeRelativeToWidth: 0.95, + buttonType: ButtonType.primary, + onPressed: + (_groupNameController.text.isEmpty || + (selectedPlayers.length < 2)) + ? null + : () async { + bool success = await db.groupDao.addGroup( + group: Group( + name: _groupNameController.text.trim(), + members: selectedPlayers, ), ); - } - }, - ), - const SizedBox(height: 20), - ], + if (!context.mounted) return; + if (success) { + Navigator.pop(context); + } else { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + backgroundColor: CustomTheme.boxColor, + content: Center( + child: Text( + AppLocalizations.of( + context, + ).error_creating_group, + style: const TextStyle(color: Colors.white), + ), + ), + ), + ); + } + }, + ), + const SizedBox(height: 20), + ], + ), ), ), ); diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index dc6690b..518fd24 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -119,140 +119,142 @@ class _CreateMatchViewState extends State { @override Widget build(BuildContext context) { final loc = AppLocalizations.of(context); - return Scaffold( - backgroundColor: CustomTheme.backgroundColor, - appBar: AppBar(title: Text(loc.create_new_match)), - body: SafeArea( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Container( - margin: CustomTheme.tileMargin, - child: TextInputField( - controller: _matchNameController, - hintText: hintText ?? '', + return ScaffoldMessenger( + child: Scaffold( + backgroundColor: CustomTheme.backgroundColor, + appBar: AppBar(title: Text(loc.create_new_match)), + body: SafeArea( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: CustomTheme.tileMargin, + child: TextInputField( + controller: _matchNameController, + hintText: hintText ?? '', + ), ), - ), - ChooseTile( - title: loc.game, - trailingText: selectedGameIndex == -1 - ? loc.none - : games[selectedGameIndex].$1, - onPressed: () async { - selectedGameIndex = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ChooseGameView( - games: games, - initialGameIndex: selectedGameIndex, + ChooseTile( + title: loc.game, + trailingText: selectedGameIndex == -1 + ? loc.none + : games[selectedGameIndex].$1, + onPressed: () async { + selectedGameIndex = await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ChooseGameView( + games: games, + initialGameIndex: selectedGameIndex, + ), ), - ), - ); - setState(() { - if (selectedGameIndex != -1) { - hintText = games[selectedGameIndex].$1; - selectedRuleset = games[selectedGameIndex].$3; - selectedRulesetIndex = _rulesets.indexWhere( - (r) => r.$1 == selectedRuleset, - ); - } else { - hintText = loc.match_name; - selectedRuleset = null; - } - }); - }, - ), - ChooseTile( - title: loc.ruleset, - trailingText: selectedRuleset == null - ? loc.none - : translateRulesetToString(selectedRuleset!, context), - onPressed: () async { - selectedRuleset = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ChooseRulesetView( - rulesets: _rulesets, - initialRulesetIndex: selectedRulesetIndex, - ), - ), - ); - if (!mounted) return; - selectedRulesetIndex = _rulesets.indexWhere( - (r) => r.$1 == selectedRuleset, - ); - selectedGameIndex = -1; - setState(() {}); - }, - ), - ChooseTile( - title: loc.group, - trailingText: selectedGroup == null - ? loc.none_group - : selectedGroup!.name, - onPressed: () async { - selectedGroup = await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ChooseGroupView( - groups: groupsList, - initialGroupId: selectedGroupId, - ), - ), - ); - selectedGroupId = selectedGroup?.id ?? ''; - if (selectedGroup != null) { - filteredPlayerList = playerList - .where( - (p) => !selectedGroup!.members.any((m) => m.id == p.id), - ) - .toList(); - } else { - filteredPlayerList = List.from(playerList); - } - setState(() {}); - }, - ), - Expanded( - child: PlayerSelection( - key: ValueKey(selectedGroup?.id ?? 'no_group'), - initialSelectedPlayers: selectedPlayers ?? [], - availablePlayers: filteredPlayerList, - onChanged: (value) { + ); setState(() { - selectedPlayers = value; + if (selectedGameIndex != -1) { + hintText = games[selectedGameIndex].$1; + selectedRuleset = games[selectedGameIndex].$3; + selectedRulesetIndex = _rulesets.indexWhere( + (r) => r.$1 == selectedRuleset, + ); + } else { + hintText = loc.match_name; + selectedRuleset = null; + } }); }, ), - ), - CustomWidthButton( - text: loc.create_match, - sizeRelativeToWidth: 0.95, - buttonType: ButtonType.primary, - onPressed: _enableCreateGameButton() - ? () async { - Match match = Match( - name: _matchNameController.text.isEmpty - ? (hintText ?? '') - : _matchNameController.text.trim(), - createdAt: DateTime.now(), - group: selectedGroup, - players: selectedPlayers, - ); - await db.matchDao.addMatch(match: match); - if (context.mounted) { - Navigator.pushReplacement( - context, - CupertinoPageRoute( - fullscreenDialog: true, - builder: (context) => MatchResultView( - match: match, - onWinnerChanged: widget.onWinnerChanged, - ), - ), + ChooseTile( + title: loc.ruleset, + trailingText: selectedRuleset == null + ? loc.none + : translateRulesetToString(selectedRuleset!, context), + onPressed: () async { + selectedRuleset = await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ChooseRulesetView( + rulesets: _rulesets, + initialRulesetIndex: selectedRulesetIndex, + ), + ), + ); + if (!mounted) return; + selectedRulesetIndex = _rulesets.indexWhere( + (r) => r.$1 == selectedRuleset, + ); + selectedGameIndex = -1; + setState(() {}); + }, + ), + ChooseTile( + title: loc.group, + trailingText: selectedGroup == null + ? loc.none_group + : selectedGroup!.name, + onPressed: () async { + selectedGroup = await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ChooseGroupView( + groups: groupsList, + initialGroupId: selectedGroupId, + ), + ), + ); + selectedGroupId = selectedGroup?.id ?? ''; + if (selectedGroup != null) { + filteredPlayerList = playerList + .where( + (p) => !selectedGroup!.members.any((m) => m.id == p.id), + ) + .toList(); + } else { + filteredPlayerList = List.from(playerList); + } + setState(() {}); + }, + ), + Expanded( + child: PlayerSelection( + key: ValueKey(selectedGroup?.id ?? 'no_group'), + initialSelectedPlayers: selectedPlayers ?? [], + availablePlayers: filteredPlayerList, + onChanged: (value) { + setState(() { + selectedPlayers = value; + }); + }, + ), + ), + CustomWidthButton( + text: loc.create_match, + sizeRelativeToWidth: 0.95, + buttonType: ButtonType.primary, + onPressed: _enableCreateGameButton() + ? () async { + Match match = Match( + name: _matchNameController.text.isEmpty + ? (hintText ?? '') + : _matchNameController.text.trim(), + createdAt: DateTime.now(), + group: selectedGroup, + players: selectedPlayers, ); + await db.matchDao.addMatch(match: match); + if (context.mounted) { + Navigator.pushReplacement( + context, + CupertinoPageRoute( + fullscreenDialog: true, + builder: (context) => MatchResultView( + match: match, + onWinnerChanged: widget.onWinnerChanged, + ), + ), + ); + } } - } - : null, - ), - ], + : null, + ), + ], + ), ), ), ); diff --git a/lib/presentation/views/main_menu/settings_view.dart b/lib/presentation/views/main_menu/settings_view.dart index 374c463..c5fcfa2 100644 --- a/lib/presentation/views/main_menu/settings_view.dart +++ b/lib/presentation/views/main_menu/settings_view.dart @@ -21,105 +21,107 @@ class _SettingsViewState extends State { @override Widget build(BuildContext context) { final loc = AppLocalizations.of(context); - return Scaffold( - appBar: AppBar(backgroundColor: CustomTheme.backgroundColor), - backgroundColor: CustomTheme.backgroundColor, - body: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) => - SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(24, 0, 24, 10), - child: Text( - textAlign: TextAlign.start, - loc.menu, - style: const TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - ), - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 10, - ), - child: Text( - textAlign: TextAlign.start, - loc.settings, - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - ), - ), - ), - SettingsListTile( - title: loc.export_data, - icon: Icons.upload_rounded, - suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), - onPressed: () async { - final String json = - await DataTransferService.getAppDataAsJson(context); - final result = await DataTransferService.exportData( - json, - 'game_tracker-data', - ); - if (!context.mounted) return; - showExportSnackBar(context: context, result: result); - }, - ), - SettingsListTile( - title: loc.import_data, - icon: Icons.download_rounded, - suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), - onPressed: () async { - final result = await DataTransferService.importData( - context, - ); - if (!context.mounted) return; - showImportSnackBar(context: context, result: result); - }, - ), - SettingsListTile( - title: loc.delete_all_data, - icon: Icons.delete_rounded, - suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), - onPressed: () { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text(loc.delete_all_data), - content: Text(loc.this_cannot_be_undone), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text(loc.cancel), - ), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text(loc.delete), - ), - ], + return ScaffoldMessenger( + child: Scaffold( + appBar: AppBar(backgroundColor: CustomTheme.backgroundColor), + backgroundColor: CustomTheme.backgroundColor, + body: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) => + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(24, 0, 24, 10), + child: Text( + textAlign: TextAlign.start, + loc.menu, + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, ), - ).then((confirmed) { - if (confirmed == true && context.mounted) { - DataTransferService.deleteAllData(context); - showSnackbar( - context: context, - message: AppLocalizations.of( - context, - ).data_successfully_deleted, - ); - } - }); - }, - ), - ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 24, + vertical: 10, + ), + child: Text( + textAlign: TextAlign.start, + loc.settings, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ), + ), + SettingsListTile( + title: loc.export_data, + icon: Icons.upload_rounded, + suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), + onPressed: () async { + final String json = + await DataTransferService.getAppDataAsJson(context); + final result = await DataTransferService.exportData( + json, + 'game_tracker-data', + ); + if (!context.mounted) return; + showExportSnackBar(context: context, result: result); + }, + ), + SettingsListTile( + title: loc.import_data, + icon: Icons.download_rounded, + suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), + onPressed: () async { + final result = await DataTransferService.importData( + context, + ); + if (!context.mounted) return; + showImportSnackBar(context: context, result: result); + }, + ), + SettingsListTile( + title: loc.delete_all_data, + icon: Icons.delete_rounded, + suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(loc.delete_all_data), + content: Text(loc.this_cannot_be_undone), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text(loc.cancel), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text(loc.delete), + ), + ], + ), + ).then((confirmed) { + if (confirmed == true && context.mounted) { + DataTransferService.deleteAllData(context); + showSnackbar( + context: context, + message: AppLocalizations.of( + context, + ).data_successfully_deleted, + ); + } + }); + }, + ), + ], + ), ), - ), + ), ), ); } From a4ef9705f950042bd4a73d0b6df4f15327314424 Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Fri, 9 Jan 2026 22:22:26 +0100 Subject: [PATCH 07/29] made PageRoutes adapt to os, default to MaterialPageRoute --- .../main_menu/custom_navigation_bar.dart | 5 +++- .../main_menu/group_view/groups_view.dart | 9 +++++++- .../create_match/create_match_view.dart | 23 ++++++++++++++++--- .../main_menu/match_view/match_view.dart | 5 +++- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index a8b18c8..17eeb41 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -1,3 +1,6 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; @@ -56,7 +59,7 @@ class _CustomNavigationBarState extends State onPressed: () async { await Navigator.push( context, - MaterialPageRoute(builder: (_) => const SettingsView()), + Platform.isIOS ? CupertinoPageRoute(builder: (_) => const SettingsView()) : MaterialPageRoute(builder: (_) => const SettingsView()), ); setState(() { tabKeyCount++; diff --git a/lib/presentation/views/main_menu/group_view/groups_view.dart b/lib/presentation/views/main_menu/group_view/groups_view.dart index 57d05a4..d19028f 100644 --- a/lib/presentation/views/main_menu/group_view/groups_view.dart +++ b/lib/presentation/views/main_menu/group_view/groups_view.dart @@ -1,3 +1,6 @@ +import 'dart:io'; + +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/custom_theme.dart'; @@ -85,7 +88,11 @@ class _GroupsViewState extends State { onPressed: () async { await Navigator.push( context, - MaterialPageRoute( + Platform.isIOS ? CupertinoPageRoute( + builder: (context) { + return const CreateGroupView(); + }, + ) : MaterialPageRoute( builder: (context) { return const CreateGroupView(); }, diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index dc6690b..cff066d 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/custom_theme.dart'; @@ -140,7 +142,12 @@ class _CreateMatchViewState extends State { : games[selectedGameIndex].$1, onPressed: () async { selectedGameIndex = await Navigator.of(context).push( - MaterialPageRoute( + Platform.isIOS ? CupertinoPageRoute( + builder: (context) => ChooseGameView( + games: games, + initialGameIndex: selectedGameIndex, + ), + ) : MaterialPageRoute( builder: (context) => ChooseGameView( games: games, initialGameIndex: selectedGameIndex, @@ -168,7 +175,12 @@ class _CreateMatchViewState extends State { : translateRulesetToString(selectedRuleset!, context), onPressed: () async { selectedRuleset = await Navigator.of(context).push( - MaterialPageRoute( + Platform.isIOS ? CupertinoPageRoute( + builder: (context) => ChooseRulesetView( + rulesets: _rulesets, + initialRulesetIndex: selectedRulesetIndex, + ), + ) : MaterialPageRoute( builder: (context) => ChooseRulesetView( rulesets: _rulesets, initialRulesetIndex: selectedRulesetIndex, @@ -190,7 +202,12 @@ class _CreateMatchViewState extends State { : selectedGroup!.name, onPressed: () async { selectedGroup = await Navigator.of(context).push( - MaterialPageRoute( + Platform.isIOS ? CupertinoPageRoute( + builder: (context) => ChooseGroupView( + groups: groupsList, + initialGroupId: selectedGroupId, + ), + ): MaterialPageRoute( builder: (context) => ChooseGroupView( groups: groupsList, initialGroupId: selectedGroupId, diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index 45b957f..55d35c6 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -1,4 +1,5 @@ import 'dart:core' hide Match; +import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; @@ -105,7 +106,9 @@ class _MatchViewState extends State { onPressed: () async { Navigator.push( context, - MaterialPageRoute( + Platform.isIOS ? CupertinoPageRoute( + builder: (context) => + CreateMatchView(onWinnerChanged: loadGames)) : MaterialPageRoute( builder: (context) => CreateMatchView(onWinnerChanged: loadGames), ), From 2c4cef76d8fb0e8fe96ecd6b7213fd1235467500 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Fri, 9 Jan 2026 23:55:29 +0100 Subject: [PATCH 08/29] Reimplemented info tile & match tile into it --- .../views/main_menu/home_view.dart | 80 ++++++++++--------- pubspec.yaml | 2 +- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index c9825c8..118c0e1 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -34,7 +34,7 @@ class _HomeViewState extends State { /// Recent matches to display, initially filled with skeleton matches List recentMatches = List.filled( - 2, + 3, Match( name: 'Skeleton Match', group: Group( @@ -44,7 +44,6 @@ class _HomeViewState extends State { Player(name: 'Skeleton Player 2'), ], ), - winner: Player(name: 'Skeleton Player 1'), ), ); @@ -86,44 +85,46 @@ class _HomeViewState extends State { ), ], ), - if (recentMatches.isNotEmpty) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: MatchTile( - compact: true, - width: constraints.maxWidth * 0.95, - match: recentMatches[0], - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, - builder: (context) => - MatchResultView(match: recentMatches[0]), - ), - ); - }, - ), - ), - if (recentMatches.length > 1) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: MatchTile( - compact: true, - width: constraints.maxWidth * 0.95, - match: recentMatches[1], - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - fullscreenDialog: true, - builder: (context) => - MatchResultView(match: recentMatches[1]), - ), - ); - }, - ), - ), Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: InfoTile( + width: constraints.maxWidth * 0.95, + title: loc.recent_matches, + icon: Icons.history_rounded, + content: Column( + children: [ + if (recentMatches.isNotEmpty) + for (Match match in recentMatches) + Padding( + padding: const EdgeInsets.symmetric( + vertical: 6.0, + ), + child: MatchTile( + compact: true, + width: constraints.maxWidth * 0.9, + match: match, + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + fullscreenDialog: true, + builder: (context) => + MatchResultView(match: match), + ), + ); + }, + ), + ) + else + Center( + heightFactor: 5, + child: Text(loc.no_recent_matches_available), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.zero, child: InfoTile( width: constraints.maxWidth * 0.95, title: loc.quick_create, @@ -173,6 +174,7 @@ class _HomeViewState extends State { ), ), ), + SizedBox(height: MediaQuery.paddingOf(context).bottom), ], ), ), diff --git a/pubspec.yaml b/pubspec.yaml index 5887957..2474f78 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.2+47 +version: 0.0.2+57 environment: sdk: ^3.8.1 From db3e8215fa48308b8a892309d53e6e7f890e91c3 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 13:42:09 +0100 Subject: [PATCH 09/29] Added ios swipe back gesture --- lib/main.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index 1dee10b..8889755 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -44,6 +44,9 @@ class GameTracker extends StatelessWidget { seedColor: CustomTheme.primaryColor, brightness: Brightness.dark, ).copyWith(surface: CustomTheme.backgroundColor), + pageTransitionsTheme: const PageTransitionsTheme( + builders: {TargetPlatform.iOS: CupertinoPageTransitionsBuilder()}, + ), ), home: const CustomNavigationBar(), ); From 1be86bc3c5ec15ffd4d030a9906728cc4d950aa2 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 13:57:46 +0100 Subject: [PATCH 10/29] Added theme box design --- lib/presentation/widgets/tiles/match_tile.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/presentation/widgets/tiles/match_tile.dart b/lib/presentation/widgets/tiles/match_tile.dart index 59ee0b9..88ae1f1 100644 --- a/lib/presentation/widgets/tiles/match_tile.dart +++ b/lib/presentation/widgets/tiles/match_tile.dart @@ -58,11 +58,7 @@ class _MatchTileState extends State { margin: EdgeInsets.zero, width: widget.width, padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: CustomTheme.boxColor, - border: Border.all(color: CustomTheme.boxBorder), - borderRadius: BorderRadius.circular(12), - ), + decoration: CustomTheme.standardBoxDecoration, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ From d22855fc1a2d3a109a1e645fdbf005723d74364c Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 13:57:54 +0100 Subject: [PATCH 11/29] Fixed match view tile width --- .../main_menu/match_view/match_view.dart | 33 ++++++++++--------- pubspec.yaml | 2 +- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index 108b592..a0b88d0 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -78,22 +78,25 @@ class _MatchViewState extends State { height: MediaQuery.paddingOf(context).bottom - 20, ); } - return Padding( - padding: const EdgeInsets.only(bottom: 12.0), - child: MatchTile( - onTap: () async { - Navigator.push( - context, - CupertinoPageRoute( - fullscreenDialog: true, - builder: (context) => MatchResultView( - match: matches[index], - onWinnerChanged: loadGames, + return Center( + child: Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: MatchTile( + width: MediaQuery.sizeOf(context).width * 0.95, + onTap: () async { + Navigator.push( + context, + CupertinoPageRoute( + fullscreenDialog: true, + builder: (context) => MatchResultView( + match: matches[index], + onWinnerChanged: loadGames, + ), ), - ), - ); - }, - match: matches[index], + ); + }, + match: matches[index], + ), ), ); }, diff --git a/pubspec.yaml b/pubspec.yaml index 2474f78..ff49b8d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.2+57 +version: 0.0.2+70 environment: sdk: ^3.8.1 From 66b90aac25871ac5afea2b7db3c91f2f7ddf283d Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 14:09:08 +0100 Subject: [PATCH 12/29] Fixed issue with android page transition --- lib/main.dart | 5 ++++- pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8889755..8fdd4e4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -45,7 +45,10 @@ class GameTracker extends StatelessWidget { brightness: Brightness.dark, ).copyWith(surface: CustomTheme.backgroundColor), pageTransitionsTheme: const PageTransitionsTheme( - builders: {TargetPlatform.iOS: CupertinoPageTransitionsBuilder()}, + builders: { + TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), + TargetPlatform.android: FadeForwardsPageTransitionsBuilder(), + }, ), ), home: const CustomNavigationBar(), diff --git a/pubspec.yaml b/pubspec.yaml index e79ca17..4944deb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.1+21 +version: 0.0.1+33 environment: sdk: ^3.8.1 From 6faafe9fab327d4e4cfd782dbec8954cc31441a0 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 14:16:16 +0100 Subject: [PATCH 13/29] Changed android page transition to Android U transition --- lib/main.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 8fdd4e4..2f64e2e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -47,7 +47,7 @@ class GameTracker extends StatelessWidget { pageTransitionsTheme: const PageTransitionsTheme( builders: { TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), - TargetPlatform.android: FadeForwardsPageTransitionsBuilder(), + TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), }, ), ), diff --git a/pubspec.yaml b/pubspec.yaml index 4944deb..26253fd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.1+33 +version: 0.0.1+37 environment: sdk: ^3.8.1 From 595cf6ead07a7548fd1e073518ab30e55568eb65 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 14:20:09 +0100 Subject: [PATCH 14/29] Changed skeleton data from 3 to 2 tiles --- lib/presentation/views/main_menu/home_view.dart | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 118c0e1..29da229 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -34,7 +34,7 @@ class _HomeViewState extends State { /// Recent matches to display, initially filled with skeleton matches List recentMatches = List.filled( - 3, + 2, Match( name: 'Skeleton Match', group: Group( diff --git a/pubspec.yaml b/pubspec.yaml index ff49b8d..1255a27 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.2+70 +version: 0.0.2+73 environment: sdk: ^3.8.1 From d67972624e25227ce6fd7a64cb9fad7b3bfac1d4 Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Sat, 10 Jan 2026 14:44:33 +0100 Subject: [PATCH 15/29] replaced ternary operator solution with custom adaptive_page_route.dart --- lib/core/adaptive_page_route.dart | 19 ++++++++++++++ lib/main.dart | 3 ++- .../main_menu/custom_navigation_bar.dart | 5 ++-- .../main_menu/group_view/groups_view.dart | 9 ++----- .../create_match/create_match_view.dart | 26 ++++--------------- .../main_menu/match_view/match_view.dart | 12 +++------ 6 files changed, 34 insertions(+), 40 deletions(-) create mode 100644 lib/core/adaptive_page_route.dart diff --git a/lib/core/adaptive_page_route.dart b/lib/core/adaptive_page_route.dart new file mode 100644 index 0000000..631f000 --- /dev/null +++ b/lib/core/adaptive_page_route.dart @@ -0,0 +1,19 @@ +import 'dart:io'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +Route AdaptivePageRoute({ + required Widget Function(BuildContext) builder, + bool fullscreenDialog = false, +}) { + if (Platform.isIOS) { + return CupertinoPageRoute( + builder: builder, + fullscreenDialog: fullscreenDialog, + ); + } + return MaterialPageRoute( + builder: builder, + fullscreenDialog: fullscreenDialog, + ); +} diff --git a/lib/main.dart b/lib/main.dart index 8889755..9b9683d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -45,7 +45,8 @@ class GameTracker extends StatelessWidget { brightness: Brightness.dark, ).copyWith(surface: CustomTheme.backgroundColor), pageTransitionsTheme: const PageTransitionsTheme( - builders: {TargetPlatform.iOS: CupertinoPageTransitionsBuilder()}, + builders: {TargetPlatform.iOS: CupertinoPageTransitionsBuilder(), TargetPlatform.android: PredictiveBackPageTransitionsBuilder() + }, ), ), home: const CustomNavigationBar(), diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index 17eeb41..4850e5a 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -1,7 +1,6 @@ -import 'dart:io'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; import 'package:game_tracker/presentation/views/main_menu/group_view/groups_view.dart'; @@ -59,7 +58,7 @@ class _CustomNavigationBarState extends State onPressed: () async { await Navigator.push( context, - Platform.isIOS ? CupertinoPageRoute(builder: (_) => const SettingsView()) : MaterialPageRoute(builder: (_) => const SettingsView()), + AdaptivePageRoute(builder: (_) => const SettingsView()), ); setState(() { tabKeyCount++; diff --git a/lib/presentation/views/main_menu/group_view/groups_view.dart b/lib/presentation/views/main_menu/group_view/groups_view.dart index d19028f..ce9f697 100644 --- a/lib/presentation/views/main_menu/group_view/groups_view.dart +++ b/lib/presentation/views/main_menu/group_view/groups_view.dart @@ -1,7 +1,6 @@ -import 'dart:io'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -88,11 +87,7 @@ class _GroupsViewState extends State { onPressed: () async { await Navigator.push( context, - Platform.isIOS ? CupertinoPageRoute( - builder: (context) { - return const CreateGroupView(); - }, - ) : MaterialPageRoute( + AdaptivePageRoute( builder: (context) { return const CreateGroupView(); }, diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index cff066d..77fe6b9 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -1,7 +1,6 @@ -import 'dart:io'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/core/enums.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -142,12 +141,7 @@ class _CreateMatchViewState extends State { : games[selectedGameIndex].$1, onPressed: () async { selectedGameIndex = await Navigator.of(context).push( - Platform.isIOS ? CupertinoPageRoute( - builder: (context) => ChooseGameView( - games: games, - initialGameIndex: selectedGameIndex, - ), - ) : MaterialPageRoute( + AdaptivePageRoute( builder: (context) => ChooseGameView( games: games, initialGameIndex: selectedGameIndex, @@ -175,12 +169,7 @@ class _CreateMatchViewState extends State { : translateRulesetToString(selectedRuleset!, context), onPressed: () async { selectedRuleset = await Navigator.of(context).push( - Platform.isIOS ? CupertinoPageRoute( - builder: (context) => ChooseRulesetView( - rulesets: _rulesets, - initialRulesetIndex: selectedRulesetIndex, - ), - ) : MaterialPageRoute( + AdaptivePageRoute( builder: (context) => ChooseRulesetView( rulesets: _rulesets, initialRulesetIndex: selectedRulesetIndex, @@ -202,12 +191,7 @@ class _CreateMatchViewState extends State { : selectedGroup!.name, onPressed: () async { selectedGroup = await Navigator.of(context).push( - Platform.isIOS ? CupertinoPageRoute( - builder: (context) => ChooseGroupView( - groups: groupsList, - initialGroupId: selectedGroupId, - ), - ): MaterialPageRoute( + AdaptivePageRoute( builder: (context) => ChooseGroupView( groups: groupsList, initialGroupId: selectedGroupId, @@ -257,7 +241,7 @@ class _CreateMatchViewState extends State { if (context.mounted) { Navigator.pushReplacement( context, - CupertinoPageRoute( + AdaptivePageRoute( fullscreenDialog: true, builder: (context) => MatchResultView( match: match, diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index 55d35c6..6797ffc 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -1,8 +1,7 @@ import 'dart:core' hide Match; -import 'dart:io'; - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -83,7 +82,7 @@ class _MatchViewState extends State { onTap: () async { Navigator.push( context, - CupertinoPageRoute( + AdaptivePageRoute( fullscreenDialog: true, builder: (context) => MatchResultView( match: matches[index], @@ -106,12 +105,9 @@ class _MatchViewState extends State { onPressed: () async { Navigator.push( context, - Platform.isIOS ? CupertinoPageRoute( + AdaptivePageRoute( builder: (context) => - CreateMatchView(onWinnerChanged: loadGames)) : MaterialPageRoute( - builder: (context) => - CreateMatchView(onWinnerChanged: loadGames), - ), + CreateMatchView(onWinnerChanged: loadGames)) ); }, ), From 97ca62b083760766c588f80c766073cebee31c10 Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Sat, 10 Jan 2026 14:52:59 +0100 Subject: [PATCH 16/29] refactor: rename AdaptivePageRoute to adaptivePageRoute for lowerCamelCase --- lib/core/adaptive_page_route.dart | 2 +- .../views/main_menu/custom_navigation_bar.dart | 3 +-- .../views/main_menu/group_view/groups_view.dart | 3 +-- .../match_view/create_match/create_match_view.dart | 9 ++++----- .../views/main_menu/match_view/match_view.dart | 5 ++--- 5 files changed, 9 insertions(+), 13 deletions(-) diff --git a/lib/core/adaptive_page_route.dart b/lib/core/adaptive_page_route.dart index 631f000..ba68557 100644 --- a/lib/core/adaptive_page_route.dart +++ b/lib/core/adaptive_page_route.dart @@ -2,7 +2,7 @@ import 'dart:io'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -Route AdaptivePageRoute({ +Route adaptivePageRoute({ required Widget Function(BuildContext) builder, bool fullscreenDialog = false, }) { diff --git a/lib/presentation/views/main_menu/custom_navigation_bar.dart b/lib/presentation/views/main_menu/custom_navigation_bar.dart index 4850e5a..0693189 100644 --- a/lib/presentation/views/main_menu/custom_navigation_bar.dart +++ b/lib/presentation/views/main_menu/custom_navigation_bar.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; @@ -58,7 +57,7 @@ class _CustomNavigationBarState extends State onPressed: () async { await Navigator.push( context, - AdaptivePageRoute(builder: (_) => const SettingsView()), + adaptivePageRoute(builder: (_) => const SettingsView()), ); setState(() { tabKeyCount++; diff --git a/lib/presentation/views/main_menu/group_view/groups_view.dart b/lib/presentation/views/main_menu/group_view/groups_view.dart index ce9f697..239aa23 100644 --- a/lib/presentation/views/main_menu/group_view/groups_view.dart +++ b/lib/presentation/views/main_menu/group_view/groups_view.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; @@ -87,7 +86,7 @@ class _GroupsViewState extends State { onPressed: () async { await Navigator.push( context, - AdaptivePageRoute( + adaptivePageRoute( builder: (context) { return const CreateGroupView(); }, diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 77fe6b9..281928e 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; @@ -141,7 +140,7 @@ class _CreateMatchViewState extends State { : games[selectedGameIndex].$1, onPressed: () async { selectedGameIndex = await Navigator.of(context).push( - AdaptivePageRoute( + adaptivePageRoute( builder: (context) => ChooseGameView( games: games, initialGameIndex: selectedGameIndex, @@ -169,7 +168,7 @@ class _CreateMatchViewState extends State { : translateRulesetToString(selectedRuleset!, context), onPressed: () async { selectedRuleset = await Navigator.of(context).push( - AdaptivePageRoute( + adaptivePageRoute( builder: (context) => ChooseRulesetView( rulesets: _rulesets, initialRulesetIndex: selectedRulesetIndex, @@ -191,7 +190,7 @@ class _CreateMatchViewState extends State { : selectedGroup!.name, onPressed: () async { selectedGroup = await Navigator.of(context).push( - AdaptivePageRoute( + adaptivePageRoute( builder: (context) => ChooseGroupView( groups: groupsList, initialGroupId: selectedGroupId, @@ -241,7 +240,7 @@ class _CreateMatchViewState extends State { if (context.mounted) { Navigator.pushReplacement( context, - AdaptivePageRoute( + adaptivePageRoute( fullscreenDialog: true, builder: (context) => MatchResultView( match: match, diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index 6797ffc..1781302 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -1,5 +1,4 @@ import 'dart:core' hide Match; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; @@ -82,7 +81,7 @@ class _MatchViewState extends State { onTap: () async { Navigator.push( context, - AdaptivePageRoute( + adaptivePageRoute( fullscreenDialog: true, builder: (context) => MatchResultView( match: matches[index], @@ -105,7 +104,7 @@ class _MatchViewState extends State { onPressed: () async { Navigator.push( context, - AdaptivePageRoute( + adaptivePageRoute( builder: (context) => CreateMatchView(onWinnerChanged: loadGames)) ); From 54ec865f04298ee0dfa3652dd5ab8f81c95405b7 Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Sat, 10 Jan 2026 15:00:33 +0100 Subject: [PATCH 17/29] fix merge issues --- .../match_view/create_match/create_match_view.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 134906e..9740b92 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -142,7 +142,7 @@ class _CreateMatchViewState extends State { : games[selectedGameIndex].$1, onPressed: () async { selectedGameIndex = await Navigator.of(context).push( - MaterialPageRoute( + adaptivePageRoute( builder: (context) => ChooseGameView( games: games, initialGameIndex: selectedGameIndex, @@ -170,7 +170,7 @@ class _CreateMatchViewState extends State { : translateRulesetToString(selectedRuleset!, context), onPressed: () async { selectedRuleset = await Navigator.of(context).push( - MaterialPageRoute( + adaptivePageRoute( builder: (context) => ChooseRulesetView( rulesets: _rulesets, initialRulesetIndex: selectedRulesetIndex, @@ -192,7 +192,7 @@ class _CreateMatchViewState extends State { : selectedGroup!.name, onPressed: () async { selectedGroup = await Navigator.of(context).push( - MaterialPageRoute( + adaptivePageRoute( builder: (context) => ChooseGroupView( groups: groupsList, initialGroupId: selectedGroupId, @@ -242,7 +242,7 @@ class _CreateMatchViewState extends State { if (context.mounted) { Navigator.pushReplacement( context, - CupertinoPageRoute( + adaptivePageRoute( fullscreenDialog: true, builder: (context) => MatchResultView( match: match, From 9eb9c0eb7f4493f546cd74b37ec8c2ff8f400e30 Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Sat, 10 Jan 2026 15:02:01 +0100 Subject: [PATCH 18/29] remove unneccessary import --- .../main_menu/match_view/create_match/create_match_view.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 9740b92..b9885a4 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -1,4 +1,3 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; From c4f67498827285fabe69a72ae8ea47f6b17faf7f Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:13:56 +0100 Subject: [PATCH 19/29] Fixed state issue in home view --- lib/presentation/views/main_menu/home_view.dart | 5 +++-- pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 29da229..f59831c 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -103,14 +103,15 @@ class _HomeViewState extends State { compact: true, width: constraints.maxWidth * 0.9, match: match, - onTap: () { - Navigator.of(context).push( + onTap: () async { + await Navigator.of(context).push( MaterialPageRoute( fullscreenDialog: true, builder: (context) => MatchResultView(match: match), ), ); + loadHomeViewData(); }, ), ) diff --git a/pubspec.yaml b/pubspec.yaml index 1255a27..2e4273b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.2+73 +version: 0.0.2+75 environment: sdk: ^3.8.1 From 830a64b5dda0767b0b26de73893195888513a6bd Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:15:52 +0100 Subject: [PATCH 20/29] Small changes --- lib/presentation/views/main_menu/match_view/match_view.dart | 6 ++++-- pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index 94dbb77..ecfa9ca 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -1,4 +1,5 @@ import 'dart:core' hide Match; + import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; @@ -111,8 +112,9 @@ class _MatchViewState extends State { Navigator.push( context, adaptivePageRoute( - builder: (context) => - CreateMatchView(onWinnerChanged: loadGames)) + builder: (context) => + CreateMatchView(onWinnerChanged: loadGames), + ), ); }, ), diff --git a/pubspec.yaml b/pubspec.yaml index 2e4273b..629a028 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.2+75 +version: 0.0.2+92 environment: sdk: ^3.8.1 From 1c07346aaf8fec6a17e4567606a03446c36efddc Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:16:09 +0100 Subject: [PATCH 21/29] Updated version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 629a028..b6f2ed3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.2+92 +version: 0.0.3+92 environment: sdk: ^3.8.1 From 6f0e5ba5c2adb3ca4afe1153f323a64f8a5e2531 Mon Sep 17 00:00:00 2001 From: Mathis Kirchner Date: Sat, 10 Jan 2026 15:19:18 +0100 Subject: [PATCH 22/29] add ability to search for groups members in choose_group_view.dart --- .../match_view/create_match/choose_group_view.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/match_view/create_match/choose_group_view.dart b/lib/presentation/views/main_menu/match_view/create_match/choose_group_view.dart index 97fbcef..9e34460 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/choose_group_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/choose_group_view.dart @@ -140,7 +140,11 @@ class _ChooseGroupViewState extends State { filteredGroups.clear(); filteredGroups.addAll( widget.groups.where( - (group) => group.name.toLowerCase().contains(query.toLowerCase()), + (group) => + group.name.toLowerCase().contains(query.toLowerCase()) || + group.members.any( + (player) => player.name.toLowerCase().contains(query.toLowerCase()), + ), ), ); } From 2ef8eb65346f66aa67ac53fa56ff0fe31062f71f Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:53:31 +0100 Subject: [PATCH 23/29] Made winner field non final --- lib/data/dto/match.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index fcb4dae..9570f66 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -9,7 +9,7 @@ class Match { final String name; final List? players; final Group? group; - final Player? winner; + Player? winner; Match({ String? id, From 2ef671884d4cfd30b60fa48b6b22351105a387e8 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:54:11 +0100 Subject: [PATCH 24/29] New method for specific winner refreshing --- .../views/main_menu/home_view.dart | 18 ++++++++++++++++-- pubspec.yaml | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index f59831c..1b07839 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -111,7 +111,7 @@ class _HomeViewState extends State { MatchResultView(match: match), ), ); - loadHomeViewData(); + await updatedWinnerinRecentMatches(match.id); }, ), ) @@ -186,7 +186,7 @@ class _HomeViewState extends State { /// Loads the data for the HomeView from the database. /// This includes the match count, group count, and recent matches. - void loadHomeViewData() { + Future loadHomeViewData() async { final db = Provider.of(context, listen: false); Future.wait([ db.matchDao.getMatchCount(), @@ -209,4 +209,18 @@ class _HomeViewState extends State { } }); } + + /// Updates the winner information for a specific match in the recent matches list. + Future updatedWinnerinRecentMatches(String matchId) async { + final db = Provider.of(context, listen: false); + final winner = await db.matchDao.getWinner(matchId: matchId); + print('Winner for match $matchId: ${winner?.name}'); + + final matchIndex = recentMatches.indexWhere((match) => match.id == matchId); + if (matchIndex != -1) { + setState(() { + recentMatches[matchIndex].winner = winner; + }); + } + } } diff --git a/pubspec.yaml b/pubspec.yaml index b6f2ed3..7ace12f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.3+92 +version: 0.0.3+93 environment: sdk: ^3.8.1 From d34990ed50b537fdeefd07f7e6ca0cd9eac2bc95 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:54:41 +0100 Subject: [PATCH 25/29] Removed print --- lib/presentation/views/main_menu/home_view.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 1b07839..29d6d67 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -214,8 +214,6 @@ class _HomeViewState extends State { Future updatedWinnerinRecentMatches(String matchId) async { final db = Provider.of(context, listen: false); final winner = await db.matchDao.getWinner(matchId: matchId); - print('Winner for match $matchId: ${winner?.name}'); - final matchIndex = recentMatches.indexWhere((match) => match.id == matchId); if (matchIndex != -1) { setState(() { From f2a4327166f26107f6ac39743eedc8626d9ff1bf Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 15:55:19 +0100 Subject: [PATCH 26/29] Implemented adaptive page route --- lib/presentation/views/main_menu/home_view.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 29d6d67..affbe92 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/dto/group.dart'; @@ -105,7 +106,7 @@ class _HomeViewState extends State { match: match, onTap: () async { await Navigator.of(context).push( - MaterialPageRoute( + adaptivePageRoute( fullscreenDialog: true, builder: (context) => MatchResultView(match: match), From 7aa41abe61629a2864a33e35b5c83fa53e96b2b0 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 16:20:21 +0100 Subject: [PATCH 27/29] Implemented version number --- .../views/main_menu/settings_view.dart | 210 ++++++++++-------- pubspec.yaml | 3 +- 2 files changed, 118 insertions(+), 95 deletions(-) diff --git a/lib/presentation/views/main_menu/settings_view.dart b/lib/presentation/views/main_menu/settings_view.dart index c5fcfa2..9c61d8d 100644 --- a/lib/presentation/views/main_menu/settings_view.dart +++ b/lib/presentation/views/main_menu/settings_view.dart @@ -4,6 +4,7 @@ import 'package:game_tracker/core/enums.dart'; import 'package:game_tracker/l10n/generated/app_localizations.dart'; import 'package:game_tracker/presentation/widgets/tiles/settings_list_tile.dart'; import 'package:game_tracker/services/data_transfer_service.dart'; +import 'package:package_info_plus/package_info_plus.dart'; class SettingsView extends StatefulWidget { const SettingsView({super.key}); @@ -13,9 +14,18 @@ class SettingsView extends StatefulWidget { } class _SettingsViewState extends State { + PackageInfo _packageInfo = PackageInfo( + appName: 'Unknown', + packageName: 'Unknown', + version: 'Unknown', + buildNumber: 'Unknown', + buildSignature: 'Unknown', + installerStore: 'Unknown', + ); @override void initState() { super.initState(); + _initPackageInfo(); } @override @@ -25,102 +35,107 @@ class _SettingsViewState extends State { child: Scaffold( appBar: AppBar(backgroundColor: CustomTheme.backgroundColor), backgroundColor: CustomTheme.backgroundColor, - body: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) => - SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.fromLTRB(24, 0, 24, 10), - child: Text( - textAlign: TextAlign.start, - loc.menu, - style: const TextStyle( - fontSize: 28, - fontWeight: FontWeight.bold, - ), - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 24, - vertical: 10, - ), - child: Text( - textAlign: TextAlign.start, - loc.settings, - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - ), - ), - ), - SettingsListTile( - title: loc.export_data, - icon: Icons.upload_rounded, - suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), - onPressed: () async { - final String json = - await DataTransferService.getAppDataAsJson(context); - final result = await DataTransferService.exportData( - json, - 'game_tracker-data', - ); - if (!context.mounted) return; - showExportSnackBar(context: context, result: result); - }, - ), - SettingsListTile( - title: loc.import_data, - icon: Icons.download_rounded, - suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), - onPressed: () async { - final result = await DataTransferService.importData( - context, - ); - if (!context.mounted) return; - showImportSnackBar(context: context, result: result); - }, - ), - SettingsListTile( - title: loc.delete_all_data, - icon: Icons.delete_rounded, - suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), - onPressed: () { - showDialog( - context: context, - builder: (context) => AlertDialog( - title: Text(loc.delete_all_data), - content: Text(loc.this_cannot_be_undone), - actions: [ - TextButton( - onPressed: () => Navigator.of(context).pop(false), - child: Text(loc.cancel), - ), - TextButton( - onPressed: () => Navigator.of(context).pop(true), - child: Text(loc.delete), - ), - ], - ), - ).then((confirmed) { - if (confirmed == true && context.mounted) { - DataTransferService.deleteAllData(context); - showSnackbar( - context: context, - message: AppLocalizations.of( - context, - ).data_successfully_deleted, - ); - } - }); - }, - ), - ], + body: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(24, 0, 24, 10), + child: Text( + textAlign: TextAlign.start, + loc.menu, + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, ), ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), + child: Text( + textAlign: TextAlign.start, + loc.settings, + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ), + ), + SettingsListTile( + title: loc.export_data, + icon: Icons.upload_rounded, + suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), + onPressed: () async { + final String json = await DataTransferService.getAppDataAsJson( + context, + ); + final result = await DataTransferService.exportData( + json, + 'game_tracker-data', + ); + if (!context.mounted) return; + showExportSnackBar(context: context, result: result); + }, + ), + SettingsListTile( + title: loc.import_data, + icon: Icons.download_rounded, + suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), + onPressed: () async { + final result = await DataTransferService.importData(context); + if (!context.mounted) return; + showImportSnackBar(context: context, result: result); + }, + ), + SettingsListTile( + title: loc.delete_all_data, + icon: Icons.delete_rounded, + suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16), + onPressed: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text(loc.delete_all_data), + content: Text(loc.this_cannot_be_undone), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(false), + child: Text(loc.cancel), + ), + TextButton( + onPressed: () => Navigator.of(context).pop(true), + child: Text(loc.delete), + ), + ], + ), + ).then((confirmed) { + if (confirmed == true && context.mounted) { + DataTransferService.deleteAllData(context); + showSnackbar( + context: context, + message: AppLocalizations.of( + context, + ).data_successfully_deleted, + ); + } + }); + }, + ), + const Spacer(), + Padding( + padding: const EdgeInsets.all(20), + child: Center( + child: Text( + 'Version ${_packageInfo.version} (${_packageInfo.buildNumber})', + style: TextStyle( + color: Colors.grey.shade600, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], ), ), ); @@ -196,4 +211,11 @@ class _SettingsViewState extends State { ), ); } + + Future _initPackageInfo() async { + final info = await PackageInfo.fromPlatform(); + setState(() { + _packageInfo = info; + }); + } } diff --git a/pubspec.yaml b/pubspec.yaml index 7ace12f..67fd5c5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.3+93 +version: 0.0.4+97 environment: sdk: ^3.8.1 @@ -22,6 +22,7 @@ dependencies: intl: any flutter_localizations: sdk: flutter + package_info_plus: ^9.0.0 dev_dependencies: flutter_test: From 2a72332bcd9e5e0f5ac4de997657fbd2edcd4d60 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 21:23:28 +0100 Subject: [PATCH 28/29] Updated error string --- lib/presentation/views/main_menu/settings_view.dart | 10 ++++------ pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/presentation/views/main_menu/settings_view.dart b/lib/presentation/views/main_menu/settings_view.dart index 9c61d8d..2019891 100644 --- a/lib/presentation/views/main_menu/settings_view.dart +++ b/lib/presentation/views/main_menu/settings_view.dart @@ -15,12 +15,10 @@ class SettingsView extends StatefulWidget { class _SettingsViewState extends State { PackageInfo _packageInfo = PackageInfo( - appName: 'Unknown', - packageName: 'Unknown', - version: 'Unknown', - buildNumber: 'Unknown', - buildSignature: 'Unknown', - installerStore: 'Unknown', + appName: 'n.A.', + packageName: 'n.A.', + version: 'n.A.', + buildNumber: 'n.A.', ); @override void initState() { diff --git a/pubspec.yaml b/pubspec.yaml index 67fd5c5..970eff4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.4+97 +version: 0.0.4+99 environment: sdk: ^3.8.1 From 497f30421d8b358dfc6511cb2f7d2b7270e730d4 Mon Sep 17 00:00:00 2001 From: Felix Kirchner Date: Sat, 10 Jan 2026 21:29:45 +0100 Subject: [PATCH 29/29] Updated string --- lib/l10n/arb/app_de.arb | 2 +- lib/l10n/arb/app_en.arb | 2 +- lib/l10n/generated/app_localizations.dart | 2 +- lib/l10n/generated/app_localizations_de.dart | 2 +- lib/l10n/generated/app_localizations_en.dart | 2 +- lib/presentation/views/main_menu/settings_view.dart | 2 +- pubspec.yaml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/l10n/arb/app_de.arb b/lib/l10n/arb/app_de.arb index 4d86460..947c31c 100644 --- a/lib/l10n/arb/app_de.arb +++ b/lib/l10n/arb/app_de.arb @@ -17,7 +17,7 @@ "data_successfully_imported": "Daten erfolgreich importiert", "days_ago": "vor {count} Tagen", "delete": "Löschen", - "delete_all_data": "Alle Daten löschen?", + "delete_all_data": "Alle Daten löschen", "error_creating_group": "Fehler beim Erstellen der Gruppe, bitte erneut versuchen", "error_reading_file": "Fehler beim Lesen der Datei", "export_canceled": "Export abgebrochen", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index 17c3b06..7bae9db 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -277,7 +277,7 @@ "data_successfully_imported": "Data successfully imported", "days_ago": "{count} days ago", "delete": "Delete", - "delete_all_data": "Delete all data?", + "delete_all_data": "Delete all data", "error_creating_group": "Error while creating group, please try again", "error_reading_file": "Error reading file", "export_canceled": "Export canceled", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index 5080ff3..1da83f8 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -209,7 +209,7 @@ abstract class AppLocalizations { /// Confirmation dialog for deleting all data /// /// In en, this message translates to: - /// **'Delete all data?'** + /// **'Delete all data'** String get delete_all_data; /// Error message when group creation fails diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index c720941..75a1325 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -67,7 +67,7 @@ class AppLocalizationsDe extends AppLocalizations { String get delete => 'Löschen'; @override - String get delete_all_data => 'Alle Daten löschen?'; + String get delete_all_data => 'Alle Daten löschen'; @override String get error_creating_group => diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index cd71035..00b933b 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -67,7 +67,7 @@ class AppLocalizationsEn extends AppLocalizations { String get delete => 'Delete'; @override - String get delete_all_data => 'Delete all data?'; + String get delete_all_data => 'Delete all data'; @override String get error_creating_group => diff --git a/lib/presentation/views/main_menu/settings_view.dart b/lib/presentation/views/main_menu/settings_view.dart index 2019891..0fa7085 100644 --- a/lib/presentation/views/main_menu/settings_view.dart +++ b/lib/presentation/views/main_menu/settings_view.dart @@ -93,7 +93,7 @@ class _SettingsViewState extends State { showDialog( context: context, builder: (context) => AlertDialog( - title: Text(loc.delete_all_data), + title: Text('${loc.delete_all_data}?'), content: Text(loc.this_cannot_be_undone), actions: [ TextButton( diff --git a/pubspec.yaml b/pubspec.yaml index 970eff4..dbb26c3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: game_tracker description: "Game Tracking App for Card Games" publish_to: 'none' -version: 0.0.4+99 +version: 0.0.4+101 environment: sdk: ^3.8.1