Merge branch 'development' into feature/132-verschiedene-regelsaetze-implementieren

# Conflicts:
#	lib/presentation/views/main_menu/match_view/match_result_view.dart
This commit is contained in:
2026-04-14 23:05:45 +02:00
60 changed files with 3471 additions and 2221 deletions

View File

@@ -1,21 +1,24 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tallee/core/constants.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/widgets/buttons/custom_width_button.dart';
import 'package:tallee/presentation/widgets/player_selection.dart';
import 'package:tallee/presentation/widgets/text_input/text_input_field.dart';
class CreateGroupView extends StatefulWidget {
const CreateGroupView({super.key, this.groupToEdit});
const CreateGroupView({super.key, this.groupToEdit, this.onMembersChanged});
/// The group to edit, if any
final Group? groupToEdit;
final VoidCallback? onMembersChanged;
@override
State<CreateGroupView> createState() => _CreateGroupViewState();
}
@@ -69,49 +72,6 @@ class _CreateGroupViewState extends State<CreateGroupView> {
title: Text(
widget.groupToEdit == null ? loc.create_new_group : loc.edit_group,
),
actions: widget.groupToEdit == null
? []
: [
IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
if (widget.groupToEdit != null) {
showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: Text(loc.delete_group),
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) async {
if (confirmed == true && context.mounted) {
bool success = await db.groupDao.deleteGroup(
groupId: widget.groupToEdit!.id,
);
if (!context.mounted) return;
if (success) {
Navigator.pop(context);
} else {
if (!mounted) return;
showSnackbar(message: loc.error_deleting_group);
}
}
});
}
},
),
],
),
body: SafeArea(
child: Column(
@@ -122,6 +82,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
child: TextInputField(
controller: _groupNameController,
hintText: loc.group_name,
maxLength: Constants.MAX_GROUP_NAME_LENGTH,
),
),
Expanded(
@@ -144,42 +105,7 @@ class _CreateGroupViewState extends State<CreateGroupView> {
(_groupNameController.text.isEmpty ||
(selectedPlayers.length < 2))
? null
: () async {
late Group? updatedGroup;
late bool success;
if (widget.groupToEdit == null) {
success = await db.groupDao.addGroup(
group: Group(
name: _groupNameController.text.trim(),
members: selectedPlayers,
),
);
} else {
updatedGroup = Group(
id: widget.groupToEdit!.id,
name: _groupNameController.text.trim(),
description: '',
members: selectedPlayers,
);
//TODO: Implement group editing in database
/*
success = await db.groupDao.updateGroup(
group: updatedGroup,
);
*/
success = true;
}
if (!context.mounted) return;
if (success) {
Navigator.pop(context, updatedGroup);
} else {
showSnackbar(
message: widget.groupToEdit == null
? loc.error_creating_group
: loc.error_editing_group,
);
}
},
: _saveGroup,
),
const SizedBox(height: 20),
],
@@ -189,6 +115,104 @@ class _CreateGroupViewState extends State<CreateGroupView> {
);
}
/// Saves the group by creating a new one or updating the existing one,
/// depending on whether the widget is in edit mode.
Future<void> _saveGroup() async {
final loc = AppLocalizations.of(context);
late bool success;
Group? updatedGroup;
if (widget.groupToEdit == null) {
success = await _createGroup();
} else {
final result = await _editGroup();
success = result.$1;
updatedGroup = result.$2;
}
if (!mounted) return;
if (success) {
Navigator.pop(context, updatedGroup);
} else {
showSnackbar(
message: widget.groupToEdit == null
? loc.error_creating_group
: loc.error_editing_group,
);
}
}
/// Handles creating a new group and returns whether the operation was successful.
Future<bool> _createGroup() async {
final groupName = _groupNameController.text.trim();
final success = await db.groupDao.addGroup(
group: Group(name: groupName, description: '', members: selectedPlayers),
);
return success;
}
/// Handles editing an existing group and returns a tuple of
/// (success, updatedGroup).
Future<(bool, Group?)> _editGroup() async {
final groupName = _groupNameController.text.trim();
Group? updatedGroup = Group(
id: widget.groupToEdit!.id,
name: groupName,
description: '',
members: selectedPlayers,
);
bool successfullNameChange = true;
bool successfullMemberChange = true;
if (widget.groupToEdit!.name != groupName) {
successfullNameChange = await db.groupDao.updateGroupName(
groupId: widget.groupToEdit!.id,
newName: groupName,
);
}
if (widget.groupToEdit!.members != selectedPlayers) {
successfullMemberChange = await db.groupDao.replaceGroupPlayers(
groupId: widget.groupToEdit!.id,
newPlayers: selectedPlayers,
);
await deleteObsoleteMatchGroupRelations();
widget.onMembersChanged?.call();
}
final success = successfullNameChange && successfullMemberChange;
return (success, updatedGroup);
}
/// Removes the group association from matches that no longer belong to the edited group.
///
/// After updating the group's members, matches that were previously linked to
/// this group but don't have any of the newly selected players are considered
/// obsolete. For each such match, the group association is removed by setting
/// its [groupId] to null.
Future<void> deleteObsoleteMatchGroupRelations() async {
final groupMatches = await db.matchDao.getGroupMatches(
groupId: widget.groupToEdit!.id,
);
final selectedPlayerIds = selectedPlayers.map((p) => p.id).toSet();
final relationshipsToDelete = groupMatches.where((match) {
return !match.players.any(
(player) => selectedPlayerIds.contains(player.id),
);
}).toList();
for (var match in relationshipsToDelete) {
await db.matchDao.removeMatchGroup(matchId: match.id);
}
}
/// Displays a snackbar with the given message and optional action.
///
/// [message] The message to display in the snackbar.

View File

@@ -4,9 +4,9 @@ import 'package:provider/provider.dart';
import 'package:tallee/core/adaptive_page_route.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/group_view/create_group_view.dart';
import 'package:tallee/presentation/widgets/app_skeleton.dart';
@@ -191,7 +191,12 @@ class _GroupDetailViewState extends State<GroupDetailView> {
context,
adaptivePageRoute(
builder: (context) {
return CreateGroupView(groupToEdit: _group);
return CreateGroupView(
groupToEdit: _group,
onMembersChanged: () {
_loadStatistics();
},
);
},
),
);
@@ -242,10 +247,8 @@ class _GroupDetailViewState extends State<GroupDetailView> {
/// Loads statistics for this group
Future<void> _loadStatistics() async {
final matches = await db.matchDao.getAllMatches();
final groupMatches = matches
.where((match) => match.group?.id == _group.id)
.toList();
isLoading = true;
final groupMatches = await db.matchDao.getGroupMatches(groupId: _group.id);
setState(() {
totalMatches = groupMatches.length;
@@ -260,7 +263,9 @@ class _GroupDetailViewState extends State<GroupDetailView> {
// Count wins for each player
for (var match in matches) {
if (match.winner != null) {
if (match.winner != null &&
_group.members.any((m) => m.id == match.winner?.id)) {
print(match.winner);
bestPlayerCounts.update(
match.winner!,
(value) => value + 1,

View File

@@ -4,8 +4,8 @@ import 'package:tallee/core/adaptive_page_route.dart';
import 'package:tallee/core/constants.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/group_view/create_group_view.dart';
import 'package:tallee/presentation/views/main_menu/group_view/group_detail_view.dart';

View File

@@ -4,10 +4,10 @@ import 'package:tallee/core/adaptive_page_route.dart';
import 'package:tallee/core/constants.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/game.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/game.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/match_view/match_result_view.dart';
import 'package:tallee/presentation/widgets/app_skeleton.dart';
@@ -42,7 +42,13 @@ class _HomeViewState extends State<HomeView> {
2,
Match(
name: 'Skeleton Match',
game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: GameColor.blue, icon: ''),
game: Game(
name: '',
ruleset: Ruleset.singleWinner,
description: '',
color: GameColor.blue,
icon: '',
),
group: Group(
name: 'Skeleton Group',
description: '',
@@ -104,7 +110,9 @@ class _HomeViewState extends State<HomeView> {
if (recentMatches.isNotEmpty)
for (Match match in recentMatches)
Padding(
padding: const EdgeInsets.symmetric(vertical: 6.0),
padding: const EdgeInsets.symmetric(
vertical: 6.0,
),
child: MatchTile(
compact: true,
width: constraints.maxWidth * 0.9,
@@ -113,7 +121,8 @@ class _HomeViewState extends State<HomeView> {
await Navigator.of(context).push(
adaptivePageRoute(
fullscreenDialog: true,
builder: (context) => MatchResultView(match: match),
builder: (context) =>
MatchResultView(match: match),
),
);
await updatedWinnerInRecentMatches(match.id);
@@ -121,7 +130,10 @@ class _HomeViewState extends State<HomeView> {
),
)
else
Center(heightFactor: 5, child: Text(loc.no_recent_matches_available)),
Center(
heightFactor: 5,
child: Text(loc.no_recent_matches_available),
),
],
),
),
@@ -137,22 +149,40 @@ class _HomeViewState extends State<HomeView> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
QuickCreateButton(text: 'Category 1', onPressed: () {}),
QuickCreateButton(text: 'Category 2', onPressed: () {}),
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: () {}),
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: () {}),
QuickCreateButton(
text: 'Category 5',
onPressed: () {},
),
QuickCreateButton(
text: 'Category 6',
onPressed: () {},
),
],
),
],
@@ -181,9 +211,11 @@ class _HomeViewState extends State<HomeView> {
matchCount = results[0] as int;
groupCount = results[1] as int;
loadedRecentMatches = results[2] as List<Match>;
recentMatches = (loadedRecentMatches..sort((a, b) => b.createdAt.compareTo(a.createdAt)))
.take(2)
.toList();
recentMatches =
(loadedRecentMatches
..sort((a, b) => b.createdAt.compareTo(a.createdAt)))
.take(2)
.toList();
if (mounted) {
setState(() {
isLoading = false;
@@ -195,7 +227,7 @@ class _HomeViewState extends State<HomeView> {
/// Updates the winner information for a specific match in the recent matches list.
Future<void> updatedWinnerInRecentMatches(String matchId) async {
final db = Provider.of<AppDatabase>(context, listen: false);
final winner = await db.matchDao.getWinner(matchId: matchId);
final winner = await db.scoreEntryDao.getWinner(matchId: matchId);
final matchIndex = recentMatches.indexWhere((match) => match.id == matchId);
if (matchIndex != -1) {
setState(() {

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/widgets/text_input/custom_search_bar.dart';
import 'package:tallee/presentation/widgets/tiles/group_tile.dart';

View File

@@ -5,10 +5,10 @@ import 'package:tallee/core/constants.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/game.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/game.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/match_view/create_match/choose_game_view.dart';
import 'package:tallee/presentation/views/main_menu/match_view/create_match/choose_group_view.dart';

View File

@@ -6,7 +6,7 @@ import 'package:tallee/core/common.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/match_view/create_match/create_match_view.dart';
import 'package:tallee/presentation/views/main_menu/match_view/match_result_view.dart';

View File

@@ -3,8 +3,8 @@ import 'package:provider/provider.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/widgets/buttons/custom_width_button.dart';
import 'package:tallee/presentation/widgets/tiles/custom_radio_list_tile.dart';
@@ -204,11 +204,11 @@ class _MatchResultViewState extends State<MatchResultView> {
Future<bool> _handleWinner() async {
if (_selectedPlayer == null) {
return await db.matchDao.removeWinner(matchId: widget.match.id);
await db.scoreEntryDao.removeWinner(matchId: widget.match.id);
} else {
return await db.matchDao.setWinner(
await db.scoreEntryDao.setWinner(
matchId: widget.match.id,
winnerId: _selectedPlayer!.id,
playerId: _selectedPlayer!.id,
);
}
}

View File

@@ -6,10 +6,10 @@ import 'package:tallee/core/constants.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/game.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/game.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/views/main_menu/match_view/create_match/create_match_view.dart';
import 'package:tallee/presentation/views/main_menu/match_view/match_detail_view.dart';

View File

@@ -70,6 +70,8 @@ const allDependencies = <Package>[
_http_parser,
_intl,
_io,
_jni,
_jni_flutter,
_js,
_json_annotation,
_json_schema,
@@ -360,13 +362,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// async 2.13.0
/// async 2.13.1
const _async = Package(
name: 'async',
description: "Utility functions and classes related to the 'dart:async' library.",
repository: 'https://github.com/dart-lang/core/tree/main/pkgs/async',
authors: [],
version: '2.13.0',
version: '2.13.1',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -442,13 +444,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// build 4.0.4
/// build 4.0.5
const _build = Package(
name: 'build',
description: 'A package for authoring build_runner compatible code generators.',
repository: 'https://github.com/dart-lang/build/tree/master/build',
authors: [],
version: '4.0.4',
version: '4.0.5',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -565,13 +567,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// build_runner 2.12.2
/// build_runner 2.13.1
const _build_runner = Package(
name: 'build_runner',
description: 'A build system for Dart code generation and modular compilation.',
repository: 'https://github.com/dart-lang/build/tree/master/build_runner',
authors: [],
version: '2.12.2',
version: '2.13.1',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -649,14 +651,14 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// built_value 8.12.4
/// built_value 8.12.5
const _built_value = Package(
name: 'built_value',
description: '''Value types with builders, Dart classes as enums, and serialization. This library is the runtime dependency.
''',
repository: 'https://github.com/google/built_value.dart/tree/master/built_value',
authors: [],
version: '8.12.4',
version: '8.12.5',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -1436,18 +1438,18 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// cupertino_icons 1.0.8
/// cupertino_icons 1.0.9
const _cupertino_icons = Package(
name: 'cupertino_icons',
description: 'Default icons asset for Cupertino widgets based on Apple styled icons',
repository: 'https://github.com/flutter/packages/tree/main/third_party/packages/cupertino_icons',
authors: [],
version: '1.0.8',
version: '1.0.9',
spdxIdentifiers: ['MIT'],
isMarkdown: false,
isSdk: false,
dependencies: [],
devDependencies: [PackageRef('flutter'), PackageRef('flutter_test')],
devDependencies: [PackageRef('collection'), PackageRef('flutter'), PackageRef('flutter_test'), PackageRef('path')],
license: '''The MIT License (MIT)
Copyright (c) 2016 Vladimir Kharlampidi
@@ -2627,13 +2629,13 @@ const _flutter_localizations = Package(
devDependencies: [PackageRef('flutter_test')],
);
/// flutter_plugin_android_lifecycle 2.0.33
/// flutter_plugin_android_lifecycle 2.0.34
const _flutter_plugin_android_lifecycle = Package(
name: 'flutter_plugin_android_lifecycle',
description: 'Flutter plugin for accessing an Android Lifecycle within other plugins.',
repository: 'https://github.com/flutter/packages/tree/main/packages/flutter_plugin_android_lifecycle',
authors: [],
version: '2.0.33',
version: '2.0.34',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -3173,6 +3175,88 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// jni 1.0.0
const _jni = Package(
name: 'jni',
description: 'A library to access JNI from Dart and Flutter that acts as a support library for package:jnigen.',
repository: 'https://github.com/dart-lang/native/tree/main/pkgs/jni',
authors: [],
version: '1.0.0',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
dependencies: [PackageRef('args'), PackageRef('collection'), PackageRef('ffi'), PackageRef('meta'), PackageRef('package_config'), PackageRef('path'), PackageRef('plugin_platform_interface')],
devDependencies: [PackageRef('dart_style'), PackageRef('logging'), PackageRef('test')],
license: '''Copyright 2022, the Dart project authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// jni_flutter 1.0.1
const _jni_flutter = Package(
name: 'jni_flutter',
description: 'A library to access Flutter Android specific APIs from Dart.',
repository: 'https://github.com/dart-lang/native/tree/main/pkgs/jni_flutter',
authors: [],
version: '1.0.1',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
dependencies: [PackageRef('flutter'), PackageRef('jni')],
devDependencies: [PackageRef('flutter_test')],
license: '''Copyright 2026, the Dart project authors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// js 0.7.2
const _js = Package(
name: 'js',
@@ -3511,13 +3595,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// markdown 7.3.0
/// markdown 7.3.1
const _markdown = Package(
name: 'markdown',
description: 'A portable Markdown library written in Dart that can parse Markdown into HTML.',
repository: 'https://github.com/dart-lang/tools/tree/main/pkgs/markdown',
authors: [],
version: '7.3.0',
version: '7.3.1',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -3890,13 +3974,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// native_toolchain_c 0.17.5
/// native_toolchain_c 0.17.6
const _native_toolchain_c = Package(
name: 'native_toolchain_c',
description: 'A library to invoke the native C compiler installed on the host machine.',
repository: 'https://github.com/dart-lang/native/tree/main/pkgs/native_toolchain_c',
authors: [],
version: '0.17.5',
version: '0.17.6',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -4110,14 +4194,14 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// package_info_plus 9.0.0
/// package_info_plus 9.0.1
const _package_info_plus = Package(
name: 'package_info_plus',
description: 'Flutter plugin for querying information about the application package, such as CFBundleVersion on iOS or versionCode on Android.',
homepage: 'https://github.com/fluttercommunity/plus_plugins',
repository: 'https://github.com/fluttercommunity/plus_plugins/tree/main/packages/package_info_plus/package_info_plus',
authors: [],
version: '9.0.0',
version: '9.0.1',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -4194,13 +4278,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// pana 0.23.10
/// pana 0.23.11
const _pana = Package(
name: 'pana',
description: 'PAckage aNAlyzer - produce a report summarizing the health and quality of a Dart package.',
repository: 'https://github.com/dart-lang/pana',
authors: [],
version: '0.23.10',
version: '0.23.11',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -4315,17 +4399,17 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// path_provider_android 2.2.22
/// path_provider_android 2.3.1
const _path_provider_android = Package(
name: 'path_provider_android',
description: 'Android implementation of the path_provider plugin.',
repository: 'https://github.com/flutter/packages/tree/main/packages/path_provider/path_provider_android',
authors: [],
version: '2.2.22',
version: '2.3.1',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
dependencies: [PackageRef('flutter'), PackageRef('path_provider_platform_interface')],
dependencies: [PackageRef('flutter'), PackageRef('jni'), PackageRef('jni_flutter'), PackageRef('path_provider_platform_interface')],
devDependencies: [PackageRef('flutter_test'), PackageRef('test')],
license: '''Copyright 2013 The Flutter Authors
@@ -36119,13 +36203,13 @@ Copyright (C) 2009-2017, International Business Machines Corporation,
Google, and others. All Rights Reserved.''',
);
/// source_gen 4.2.0
/// source_gen 4.2.2
const _source_gen = Package(
name: 'source_gen',
description: 'Source code generation builders and utilities for the Dart build system',
repository: 'https://github.com/dart-lang/source_gen/tree/master/source_gen',
authors: [],
version: '4.2.0',
version: '4.2.2',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -36318,13 +36402,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.''',
);
/// sqlite3_flutter_libs 0.5.41
/// sqlite3_flutter_libs 0.5.42
const _sqlite3_flutter_libs = Package(
name: 'sqlite3_flutter_libs',
description: 'Flutter plugin to include native sqlite3 libraries with your app',
homepage: 'https://github.com/simolus3/sqlite3.dart/tree/v2/sqlite3_flutter_libs',
authors: [],
version: '0.5.41',
version: '0.5.42',
spdxIdentifiers: ['MIT'],
isMarkdown: false,
isSdk: false,
@@ -36835,13 +36919,13 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
);
/// url_launcher_android 6.3.28
/// url_launcher_android 6.3.29
const _url_launcher_android = Package(
name: 'url_launcher_android',
description: 'Android implementation of the url_launcher plugin.',
repository: 'https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_android',
authors: [],
version: '6.3.28',
version: '6.3.29',
spdxIdentifiers: ['BSD-3-Clause'],
isMarkdown: false,
isSdk: false,
@@ -37796,12 +37880,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.''',
);
/// tallee 0.0.18+252
/// tallee 0.0.20+254
const _tallee = Package(
name: 'tallee',
description: 'Tracking App for Card Games',
authors: [],
version: '0.0.18+252',
version: '0.0.20+254',
spdxIdentifiers: ['LGPL-3.0'],
isMarkdown: false,
isSdk: false,

View File

@@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tallee/core/constants.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/widgets/app_skeleton.dart';
import 'package:tallee/presentation/widgets/tiles/statistics_tile.dart';
@@ -167,7 +167,8 @@ class _StatisticsViewState extends State<StatisticsView> {
final playerId = winCounts[i].$1;
final player = players.firstWhere(
(p) => p.id == playerId,
orElse: () => Player(id: playerId, name: loc.not_available, description: ''),
orElse: () =>
Player(id: playerId, name: loc.not_available, description: ''),
);
winCounts[i] = (player.name, winCounts[i].$2);
}
@@ -208,11 +209,11 @@ class _StatisticsViewState extends State<StatisticsView> {
// -1 means player not found in matchCounts
if (index != -1) {
final current = matchCounts[index].$2;
matchCounts[index] = (playerId, current + 1);
} else {
matchCounts.add((playerId, 1));
}
matchCounts[index] = (playerId, current + 1);
} else {
matchCounts.add((playerId, 1));
}
}
}
// Adding all players with zero matches
@@ -229,7 +230,8 @@ class _StatisticsViewState extends State<StatisticsView> {
final playerId = matchCounts[i].$1;
final player = players.firstWhere(
(p) => p.id == playerId,
orElse: () => Player(id: playerId, name: loc.not_available, description: ''),
orElse: () =>
Player(id: playerId, name: loc.not_available, description: ''),
);
matchCounts[i] = (player.name, matchCounts[i].$2);
}

View File

@@ -3,7 +3,7 @@ import 'package:provider/provider.dart';
import 'package:tallee/core/constants.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/dto/player.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/widgets/app_skeleton.dart';
import 'package:tallee/presentation/widgets/text_input/custom_search_bar.dart';

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/data/dto/group.dart';
import 'package:tallee/data/models/group.dart';
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
class GroupTile extends StatefulWidget {

View File

@@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tallee/core/common.dart';
import 'package:tallee/core/custom_theme.dart';
import 'package:tallee/data/dto/match.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';