704 Commits

Author SHA1 Message Date
1f17b80f64 Merge branch 'development' into feature/180-Spielerprofile-implementieren
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 51s
Pull Request Pipeline / localizations (pull_request) Successful in 28s
Pull Request Pipeline / test (pull_request) Successful in 49s
2026-05-23 00:42:59 +02:00
3048e5c75d Updated licenses [skip ci] 2026-05-22 22:38:11 +00:00
5cb89f6334 Updated version number [skip ci] 2026-05-22 22:37:33 +00:00
4eb485e40a Updated flutter files
All checks were successful
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / test (push) Successful in 45s
Push Pipeline / generate_licenses (push) Successful in 39s
Push Pipeline / generate_localizations (push) Successful in 28s
Push Pipeline / sort_arb_files (push) Successful in 34s
Push Pipeline / format (push) Successful in 53s
Push Pipeline / build (push) Successful in 5m56s
Renovate / renovate (push) Successful in 47s
2026-05-23 00:37:21 +02:00
773056b162 Merge remote-tracking branch 'origin/development' into development 2026-05-23 00:34:47 +02:00
4dd4a2f35a fix: reorder attribute 2026-05-23 00:34:28 +02:00
7d0f9b5c33 fix: import 2026-05-23 00:33:52 +02:00
dffc6b9151 Updated licenses [skip ci] 2026-05-22 22:30:21 +00:00
dec61fd88f Updated version number [skip ci] 2026-05-22 22:29:43 +00:00
66a72f1c3c Removed version again
Some checks failed
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 39s
Push Pipeline / test (push) Successful in 47s
Push Pipeline / generate_localizations (push) Successful in 28s
Push Pipeline / sort_arb_files (push) Successful in 33s
Push Pipeline / format (push) Failing after 1m4s
Push Pipeline / build (push) Has been skipped
2026-05-23 00:29:34 +02:00
ef32aeae52 Updated version number [skip ci] 2026-05-22 22:27:03 +00:00
ec9ed1f19e Removed version
Some checks failed
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / test (push) Failing after 1m42s
Push Pipeline / generate_licenses (push) Failing after 1m42s
Push Pipeline / generate_localizations (push) Failing after 12s
Push Pipeline / sort_arb_files (push) Failing after 13s
Push Pipeline / format (push) Has been skipped
Push Pipeline / build (push) Has been skipped
2026-05-23 00:26:53 +02:00
fad5a392cd Merge branch 'development' into feature/180-Spielerprofile-implementieren
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 53s
Pull Request Pipeline / localizations (pull_request) Successful in 25s
# Conflicts:
#	lib/l10n/arb/app_de.arb
#	lib/l10n/arb/app_en.arb
#	lib/l10n/generated/app_localizations.dart
#	lib/l10n/generated/app_localizations_de.dart
#	lib/l10n/generated/app_localizations_en.dart
2026-05-23 00:22:03 +02:00
811079705f Updated licenses [skip ci] 2026-05-22 22:12:45 +00:00
5211007629 Updated version number [skip ci] 2026-05-22 22:12:09 +00:00
e27b0cc941 Resetted version number + build needs format
All checks were successful
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 36s
Push Pipeline / test (push) Successful in 45s
Push Pipeline / generate_localizations (push) Successful in 28s
Push Pipeline / sort_arb_files (push) Successful in 33s
Push Pipeline / format (push) Successful in 51s
Push Pipeline / build (push) Successful in 5m24s
2026-05-23 00:11:57 +02:00
a6649b4258 Updated licenses [skip ci] 2026-05-22 22:10:08 +00:00
d2cb1b511a Updated version number [skip ci] 2026-05-22 22:09:31 +00:00
6cb5cc401b Merge remote-tracking branch 'origin/development' into development
Some checks failed
Push Pipeline / update_version (push) Successful in 7s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / test (push) Successful in 47s
Push Pipeline / generate_localizations (push) Successful in 29s
Push Pipeline / sort_arb_files (push) Successful in 34s
Push Pipeline / format (push) Successful in 1m6s
Push Pipeline / build (push) Has been cancelled
2026-05-23 00:09:17 +02:00
e35997dd6c put build step at the end 2026-05-23 00:09:11 +02:00
f6a5ab8943 Updated licenses [skip ci] 2026-05-22 22:08:31 +00:00
b74a21b02a Updated version number [skip ci] 2026-05-22 22:07:53 +00:00
87c597f29a feat: updatePlayerName keeps created order in nameCount
Some checks failed
Push Pipeline / test (push) Successful in 46s
Push Pipeline / update_version (push) Successful in 7s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / generate_localizations (push) Successful in 31s
Push Pipeline / build (push) Has been cancelled
Push Pipeline / format (push) Has been cancelled
Push Pipeline / sort_arb_files (push) Has been cancelled
2026-05-23 00:06:56 +02:00
c10bc9dbdc Actions & PR Template verbessern (#223)
Some checks failed
Push Pipeline / test (push) Successful in 47s
Push Pipeline / update_version (push) Failing after 31s
Push Pipeline / generate_licenses (push) Failing after 36s
Push Pipeline / generate_localizations (push) Successful in 28s
Push Pipeline / sort_arb_files (push) Successful in 37s
Push Pipeline / format (push) Has been skipped
Push Pipeline / build (push) Successful in 5m32s
### Zugehörige Issue(s)

Closes #222

### Beschreibung

Die Push & PR-Pipelines wurden um Überprüfungen und Formatierung für die Lokalisierung erweitert. Außerdem wurde eine PR-Checkliste zum PR-Template hinzugefügt.

### Änderungen

- Template um `PR-Checklist` ergänzt (siehe Diff, gerne Ideen für mehr Punkte)
- PR-Pipeline überprüft jetzt ob `untranslated_messages.json` leer (also `{}`) ist. Wenn nicht, schlägt sie fehl
- In der Push-Pipeline werden jetzt die `.arb`-Files sortiert
- In der Push-Pipeline werden jetzt die lokalisierungen generiert
- Renovate Workflow hinzugefügt, welcher jede Woche die Dependencies überprüft (siehe [diese Test-PR](#244))

### Zusätzliche Anmerkungen

Ich wollt eigentlich auch einen Job zum generieren der DB-Files einbauen. Das hat jedoch nicht geklappt (siehe [hier](https://git.yannick-weigert.de/liquid-development/game-tracker/actions/runs/1013/jobs/3) oder [hier](https://git.yannick-weigert.de/liquid-development/game-tracker/actions/runs/1014/jobs/3)), weil der jedes mal mehr als 10 Minuten gedauert hat und dann getimeoutet ist

![grafik.png](/attachments/49f7fb43-08a2-4378-9b89-fa2334c69344)

Co-authored-by: Gitea Actions [bot] <actions@yannick-weigert.de>
Reviewed-on: #223
Co-authored-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
Co-committed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
2026-05-22 19:12:59 +00:00
5a652a5f2c feat: updatePlayerName keeps created order in nameCount
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-22 20:06:27 +02:00
4dcd4f0f71 fix: name count 3 player issue 2026-05-22 20:00:28 +02:00
25bc213769 Merge remote-tracking branch 'origin/feature/180-Spielerprofile-implementieren' into feature/180-Spielerprofile-implementieren
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-22 08:45:43 +02:00
9adcc29cda fix: updatePlayerName corrects the name count after renaming to different name
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 55s
2026-05-21 23:57:59 +02:00
78c59a9b52 feat: add localization for no matches played and not part of any group 2026-05-21 16:20:48 +02:00
bf2cd2bf58 feat: add player creation callbacks to update member and match lists when group/match creation is canceled but player created
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 55s
2026-05-21 16:08:59 +02:00
ccb0d32c54 fix: tests for name count
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-21 15:45:29 +02:00
82095ab41a fix: name count 2026-05-21 15:33:26 +02:00
2a38462c57 fix linter issues
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 44s
Pull Request Pipeline / lint (pull_request) Successful in 56s
2026-05-21 10:34:01 +02:00
9909d959b0 implement missing localization
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 47s
Pull Request Pipeline / lint (pull_request) Failing after 56s
2026-05-21 10:33:16 +02:00
b61a93328f made alertDialog Confirm Button deactivate based on input, fix app skeleton alignment issue, implement correct nameCount Display
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 42s
Pull Request Pipeline / lint (pull_request) Failing after 51s
2026-05-21 09:47:49 +02:00
679e869229 fix: player count calc error
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 44s
Pull Request Pipeline / lint (pull_request) Failing after 52s
2026-05-20 19:58:59 +02:00
869c70ff63 add player change callbacks and improve player detail view
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 47s
Pull Request Pipeline / lint (pull_request) Failing after 53s
2026-05-20 19:50:34 +02:00
b305145d34 implement basic player_detail_view.dart
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Failing after 51s
2026-05-20 15:15:47 +02:00
31dc899741 Updated licenses [skip ci] 2026-05-14 13:10:36 +00:00
1d1c02a575 Updated version number [skip ci] 2026-05-14 13:09:54 +00:00
7f024534aa Merge pull request 'Haptisches Feedback hinzufügen' (#216) from feature/215-haptisches-feedback-hinzufügen into development
All checks were successful
Push Pipeline / test (push) Successful in 47s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 39s
Push Pipeline / format (push) Successful in 1m6s
Push Pipeline / build (push) Successful in 5m33s
Reviewed-on: #216
Reviewed-by: Felix Kirchner <flixcoo@noreply.git.yannick-weigert.de>
2026-05-14 13:09:01 +00:00
f5b24cb923 disable button splash
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 55s
2026-05-13 16:31:24 +02:00
0d497236b0 remove space
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-13 15:55:38 +02:00
cadb5793e7 Merge remote-tracking branch 'origin/feature/215-haptisches-feedback-hinzufügen' into feature/215-haptisches-feedback-hinzufügen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-13 15:38:24 +02:00
f87a873362 remove tooltip attribute 2026-05-13 15:38:19 +02:00
e2882c1c6a changed long press vibration
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-13 13:54:01 +02:00
f5fbb3ecc4 fix: long press feedback on every call
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 53s
2026-05-13 13:48:44 +02:00
02bb7e4daa Merge remote-tracking branch 'origin/feature/215-haptisches-feedback-hinzufügen' into feature/215-haptisches-feedback-hinzufügen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-13 12:45:01 +02:00
a8369249b4 change settings_view buttons to haptic icon button 2026-05-13 12:44:39 +02:00
7e35ccae6b add vibration to long tap 2026-05-13 12:37:19 +02:00
b82cca939f remove unnecessary click 2026-05-13 12:37:11 +02:00
1edad99a1c Merge branch 'development' into feature/215-haptisches-feedback-hinzufügen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 55s
2026-05-11 19:19:54 +00:00
7a22deea1b Updated licenses [skip ci] 2026-05-11 19:15:48 +00:00
0f3863d446 Updated version number [skip ci] 2026-05-11 19:14:13 +00:00
9c5792c410 Merge pull request 'Flutter Version erhöhen in PR jobs' (#219) from hotfix/218-Flutter-Version-erhöhen-in-PR-jobs into development
All checks were successful
Push Pipeline / test (push) Successful in 47s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 39s
Push Pipeline / format (push) Successful in 59s
Push Pipeline / build (push) Successful in 5m45s
Reviewed-on: #219
Reviewed-by: Felix Kirchner <flixcoo@noreply.git.yannick-weigert.de>
2026-05-11 19:13:19 +00:00
2aed053c42 bump flutter version
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m13s
Pull Request Pipeline / lint (pull_request) Successful in 2m26s
2026-05-11 18:55:51 +00:00
424fa34cab bump version to 3.41.0 2026-05-11 18:54:50 +00:00
f1899bfe44 feat: add haptic feedback to even more user interactions
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Failing after 51s
2026-05-11 10:59:48 +02:00
bc59d1d91c feat: add haptic feedback to more user interactions
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 49s
Pull Request Pipeline / lint (pull_request) Failing after 50s
2026-05-11 10:27:35 +02:00
1d20127af4 feat: add haptic feedback for various user interactions
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Failing after 48s
2026-05-10 23:04:43 +02:00
699d4378b2 Updated licenses [skip ci] 2026-05-10 17:14:44 +00:00
1c5735eb41 Updated version number [skip ci] 2026-05-10 17:14:04 +00:00
9fb2b4ddc2 Merge pull request 'Implementierung von multiple Winners' (#214) from feature/205-Implementierung-von-multipleWinners into development
All checks were successful
Push Pipeline / test (push) Successful in 46s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / format (push) Successful in 59s
Push Pipeline / build (push) Successful in 5m29s
Reviewed-on: #214
Reviewed-by: Felix Kirchner <flixcoo@noreply.git.yannick-weigert.de>
2026-05-10 17:13:11 +00:00
c75b3e4a6d updated comment
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 51s
2026-05-10 19:12:12 +02:00
60a92dafe1 updated logic
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 19:07:20 +02:00
e503db1c1b fix: removed unnecessary method
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-10 18:51:59 +02:00
50bf111f03 fix: single result row
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 49s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 18:47:48 +02:00
341b293151 fix: text alignment 2026-05-10 18:41:34 +02:00
6db265ea99 feat: replaced variable content with generated lists
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 51s
2026-05-10 18:39:36 +02:00
eb2e704ef9 Merge remote-tracking branch 'origin/feature/205-Implementierung-von-multipleWinners' into feature/205-Implementierung-von-multipleWinners
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-10 18:24:21 +02:00
0c44c54bd7 fix: schema test created json 2026-05-10 18:24:12 +02:00
b94cc1ac18 Merge remote-tracking branch 'origin/feature/205-Implementierung-von-multipleWinners' into feature/205-Implementierung-von-multipleWinners
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 18:23:45 +02:00
9ae562d92a update schema test 2026-05-10 18:23:39 +02:00
f5f97f676c fix: wrong tile hidden 2026-05-10 18:22:56 +02:00
f98208b508 fix: button enabled condition
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 49s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 18:17:01 +02:00
2a3c0fc98c fix schema
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 17:50:16 +02:00
009c53ad89 fix title and ruleset/color choose order in game creation
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 16:36:46 +02:00
8076f082bc fix lint
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-10 16:28:08 +02:00
3c5c0dbf20 Add support for multiple winners and update localization
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Failing after 51s
2026-05-10 16:26:51 +02:00
03ab2045b2 Add support for selecting multiple winners and update localization
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Failing after 51s
2026-05-10 14:54:00 +02:00
881382b399 Updated licenses [skip ci] 2026-05-09 21:39:01 +00:00
e5fd54f112 Updated version number [skip ci] 2026-05-09 21:38:23 +00:00
c225599aa3 Merge pull request 'Neuer Regelsatz: Platzierung' (#213) from feature/206-Neuer-Regelsatz-Platzierung into development
All checks were successful
Push Pipeline / test (push) Successful in 44s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 36s
Push Pipeline / format (push) Successful in 55s
Push Pipeline / build (push) Successful in 5m25s
Reviewed-on: #213
Reviewed-by: Felix Kirchner <flixcoo@noreply.git.yannick-weigert.de>
2026-05-09 21:37:30 +00:00
df73fc87eb localizations
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-09 23:16:56 +02:00
28222cbd2a Merge branch 'development' into feature/206-Neuer-Regelsatz-Platzierung
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
# Conflicts:
#	lib/l10n/generated/app_localizations.dart
#	lib/presentation/views/main_menu/match_view/match_detail_view.dart
#	lib/presentation/views/main_menu/match_view/match_result_view.dart
2026-05-09 23:16:17 +02:00
f0ff4fbfc0 feat: placement text color
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 54s
2026-05-09 20:32:39 +02:00
e24183eb9c Updated licenses [skip ci] 2026-05-09 18:00:12 +00:00
cde64a2683 Updated version number [skip ci] 2026-05-09 17:59:32 +00:00
e9d9cc98b4 Merge pull request 'Live-Edit Modus' (#207) from feature/202-live-edit-modus into development
All checks were successful
Push Pipeline / test (push) Successful in 48s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 37s
Push Pipeline / format (push) Successful in 55s
Push Pipeline / build (push) Successful in 5m31s
Reviewed-on: #207

ich habe schwere depressionen wegen merge conflicts :(((
2026-05-09 17:58:37 +00:00
518bbb407c Updated icon and match tile icon style
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 19:54:24 +02:00
0eb27ab284 add icon for placement ruleset
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-09 19:48:02 +02:00
a42e635282 Merge branch 'development' into feature/202-live-edit-modus
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 49s
Pull Request Pipeline / lint (pull_request) Successful in 51s
# Conflicts:
#	lib/l10n/generated/app_localizations.dart
#	pubspec.yaml
2026-05-09 19:36:21 +02:00
3923e955fd regenerate localization
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Failing after 51s
2026-05-09 19:19:18 +02:00
759e168216 Merge remote-tracking branch 'origin/development' into feature/206-Neuer-Regelsatz-Platzierung
# Conflicts:
#	lib/l10n/arb/app_de.arb
#	lib/l10n/arb/app_en.arb
#	lib/l10n/generated/app_localizations.dart
#	lib/l10n/generated/app_localizations_de.dart
#	lib/l10n/generated/app_localizations_en.dart
2026-05-09 19:18:54 +02:00
9e76acce29 Updated licenses [skip ci] 2026-05-09 17:15:22 +00:00
84f8a77c72 Updated version number [skip ci] 2026-05-09 17:14:43 +00:00
e5b44b2660 Merge pull request 'Implementierung der Games' (#203) from feature/119-implementierung-der-games-2 into development
All checks were successful
Push Pipeline / test (push) Successful in 47s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / format (push) Successful in 54s
Push Pipeline / build (push) Successful in 5m30s
Reviewed-on: #203
2026-05-09 17:13:46 +00:00
ae572a5dbd Refactored trailing widgets
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 53s
2026-05-09 18:55:00 +02:00
1de0ef52ad feat: updated placement num styling
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 18:41:03 +02:00
496d411af6 feat: updated drag effect 2026-05-09 18:37:02 +02:00
79ce3efd0a implement setPlacement in Score Dao & add placement game type to match tile
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-09 18:19:30 +02:00
616c239375 change placement to text in match detail view
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 17:47:23 +02:00
9781a20b38 implement dragging animation
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 17:36:18 +02:00
385bd39aa1 change placement tile decoration
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 49s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-09 17:30:44 +02:00
f7c8160c58 fix: removed print in test
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 17:28:57 +02:00
5c9db7244a fix: adjusted test
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 17:22:16 +02:00
fbb83aaf7b fix: localization plural 2026-05-09 17:17:33 +02:00
2d2a83ea4c remove matchStateUpdate bcs alr implement in another pr 2026-05-09 17:14:38 +02:00
f9eafa5b3d add: empty game list messages
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 53s
2026-05-09 15:01:21 +02:00
40e2229aa5 feat: long press adds 10 points repeatedly
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 14:52:12 +02:00
8dbf2a573e feat: negative numbers in score list tile 2026-05-09 14:39:28 +02:00
90331bfc07 fix: button view logic 2026-05-09 14:29:01 +02:00
df757af7ec fix: choose tile alignment
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 13:33:50 +02:00
fd553e1d24 fix: chevron tap
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 13:27:24 +02:00
5b668d28b7 add translation for drag to set placement
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 13:02:42 +02:00
2fdcc3e8aa remove unecessessary prefix text
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-09 13:01:42 +02:00
350c5430a4 implement updateMatchStateAfterSave to refresh match scores
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 52s
2026-05-09 12:57:42 +02:00
61ed6db9a3 Merge branch 'development' into feature/202-live-edit-modus
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 10:40:55 +00:00
f0062dd9d9 add const
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-09 12:34:07 +02:00
6f155182b5 remove scroll-physics from single winner & placement ruleset listview
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Failing after 50s
2026-05-09 12:33:54 +02:00
8b7a519e64 fix: update string interpolation and use const TextStyle for consistency
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-09 11:51:13 +02:00
868460b023 feat: update TextIconListTile to support custom icons
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Failing after 49s
2026-05-09 11:50:49 +02:00
003a5122fa Merge branch 'development' into feature/119-implementierung-der-games-2
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 49s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-09 11:30:26 +02:00
bc997633eb feat: add placement ruleset and related localization
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Failing after 48s
2026-05-09 02:08:40 +02:00
044a6acbbe Updated licenses [skip ci] 2026-05-08 22:02:41 +00:00
5b3b706c28 Updated version number [skip ci] 2026-05-08 22:00:28 +00:00
a159569c40 Merge branch 'development' into feature/202-live-edit-modus
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 52s
Pull Request Pipeline / test (pull_request) Successful in 45s
2026-05-08 21:59:56 +00:00
7fa9b61d49 Merge pull request 'StatisticsView + HomeView zusammenlegen' (#208) from enhancement/192-statisticsview-+-homeview-zusammenlegen into development
All checks were successful
Push Pipeline / test (push) Successful in 45s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 36s
Push Pipeline / format (push) Successful in 52s
Push Pipeline / build (push) Successful in 5m35s
Reviewed-on: #208
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-05-08 21:59:35 +00:00
86a920e934 fix: tab title
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-08 23:33:15 +02:00
28fb608b30 fix: increased font size
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-08 19:45:46 +02:00
0d1ed3e666 fix: no element error 2026-05-08 19:36:52 +02:00
4520281cb6 fix: popup area 2026-05-08 19:33:22 +02:00
8169d92c6c Merge branch 'development' into enhancement/192-statisticsview-+-homeview-zusammenlegen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-08 18:59:54 +02:00
3494d397ed Updated licenses [skip ci] 2026-05-08 16:52:55 +00:00
514b1c32e7 Updated version number [skip ci] 2026-05-08 16:52:14 +00:00
08ae9269b1 Merge pull request 'Navbar animation verbessert' (#210) from enhancement/209-navbar-animation-verbessern into development
All checks were successful
Push Pipeline / test (push) Successful in 45s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 39s
Push Pipeline / format (push) Successful in 55s
Push Pipeline / build (push) Successful in 5m29s
Reviewed-on: #210
Reviewed-by: Felix Kirchner <flixcoo@noreply.git.yannick-weigert.de>
2026-05-08 16:51:22 +00:00
686a13c64f Merge branch 'development' into enhancement/209-navbar-animation-verbessern
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-08 16:48:37 +00:00
726630027e Merge branch 'development' into feature/119-implementierung-der-games-2
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-08 18:09:56 +02:00
03849b1d88 Merge branch 'development' into feature/202-live-edit-modus
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-08 18:09:41 +02:00
4190eb2bc6 Merge remote-tracking branch 'origin/enhancement/192-statisticsview-+-homeview-zusammenlegen' into enhancement/192-statisticsview-+-homeview-zusammenlegen
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 57s
Pull Request Pipeline / test (pull_request) Successful in 54s
2026-05-08 18:06:35 +02:00
cd7e61e2c7 Applied #212 fix 2026-05-08 18:06:05 +02:00
f6dccbfc76 Improved skeleton data 2026-05-08 18:06:05 +02:00
284395bb77 Deleted home view 2026-05-08 18:06:02 +02:00
aeba2e93e0 Updated licenses [skip ci] 2026-05-08 16:04:25 +00:00
23f0c9c23e Updated statistics view 2026-05-08 18:04:01 +02:00
610a842b8a Updated version number [skip ci] 2026-05-08 16:03:46 +00:00
3750020663 Merge pull request 'Home Info Tile Design überarbeitet' (#212) from enhancement/211-Home-Info-Tile-Design-überarbeiten into development
All checks were successful
Push Pipeline / test (push) Successful in 45s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 38s
Push Pipeline / format (push) Successful in 54s
Push Pipeline / build (push) Successful in 5m41s
Reviewed-on: #212
Reviewed-by: Felix Kirchner <flixcoo@noreply.git.yannick-weigert.de>
2026-05-08 16:02:30 +00:00
4dd794c08f Applied #212 fix
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-05-08 18:02:00 +02:00
b6a252287d refactor: adjust heights and alignment in QuickInfoTile for better layout
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-08 12:17:40 +02:00
34a24c9dec Enhance navbar item animations
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-07 20:39:01 +02:00
87ea5b47ee Improved skeleton data
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-06 20:34:55 +02:00
013fd29182 Updated LiveEditListTile
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-06 20:18:46 +02:00
46041be837 compiling localizations
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-06 19:55:56 +02:00
045d2afa39 removed descriptions
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-06 19:54:34 +02:00
4037a961d1 Merge branch 'development' into feature/202-live-edit-modus
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-05 22:48:37 +02:00
5bac5f1c38 fix: score update
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Successful in 59s
2026-05-05 22:45:57 +02:00
ec4d6ce5ec Docs 2026-05-05 22:45:35 +02:00
883a32e0ca Fixed button 2026-05-05 22:38:11 +02:00
bb46cace03 Added localizations 2026-05-05 22:36:01 +02:00
dc3807356e Changed button style
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 32s
Pull Request Pipeline / lint (pull_request) Failing after 34s
2026-05-05 22:28:55 +02:00
f8c6d3d089 Deleted home view
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-05 13:42:43 +02:00
f2626bd5af Updated statistics view 2026-05-05 13:42:39 +02:00
f3380e6c08 Reordered tests
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-05 11:45:22 +02:00
eadf05e116 Fixed incoming changes 2026-05-05 11:43:35 +02:00
9896008335 Refactoring 2026-05-05 11:42:38 +02:00
b9cfab1447 Merge branch 'development' into feature/119-implementierung-der-games-2
# Conflicts:
#	lib/data/dao/match_dao.dart
2026-05-05 11:40:32 +02:00
f0c1ce9881 Updated licenses [skip ci] 2026-05-05 09:30:59 +00:00
ee7bff9062 Updated version number [skip ci] 2026-05-05 09:30:20 +00:00
0c2495b10a Merge pull request 'Tests refactoren' (#201) from tests/197-tests-refactoren into development
All checks were successful
Push Pipeline / test (push) Successful in 44s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 37s
Push Pipeline / format (push) Successful in 55s
Push Pipeline / build (push) Successful in 5m23s
Reviewed-on: #201
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-05-05 09:29:28 +00:00
fef8380860 added const
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-04 15:41:01 +02:00
3be7dac227 Added button to leave live edit mode
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-04 15:29:28 +02:00
e25a2bde69 Added delay before reversing animation 2026-05-04 15:01:22 +02:00
3dfd2c7c08 Moved file 2026-05-04 15:00:33 +02:00
1e95f1997d Updated border color 2026-05-04 15:00:26 +02:00
5877793b99 Updated secondary button style 2026-05-04 15:00:13 +02:00
ea5577c288 Implemented new live edit mode 2026-05-04 15:00:00 +02:00
a9b86fe7ff Added icons to rulesets
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Failing after 47s
2026-05-04 11:09:05 +02:00
b53facc16c Added singleWinner as default ruleset 2026-05-04 11:03:59 +02:00
8194fb2f28 Removed selectedRulesetIndex 2026-05-04 11:03:34 +02:00
94bb477cd9 Added popups to create game view replacing two screens
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-04 10:44:40 +02:00
8c52db9981 Added popups to create game view 2026-05-04 10:43:43 +02:00
6272794cc5 feat: showing game color in choose tile 2026-05-03 10:59:46 +02:00
5d832c98a7 fix: callbacks when game deletes matches
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-03 10:45:18 +02:00
e3aef81ab6 feat: Deleting games associated with matches deletes them
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 42s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-05-03 01:00:44 +02:00
92bf74683f feat: games with match associations cant be deleted
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-02 16:32:25 +02:00
2e1314ccd4 Implemented consistency changes 2026-05-02 16:11:15 +02:00
633a0599eb Implemented game tile in choose game view 2026-05-02 16:04:20 +02:00
e895359dac Updated highlighting 2026-05-02 16:04:06 +02:00
b664bcacda Created seperate game tile and simplified title description list tile 2026-05-02 16:02:49 +02:00
c64fd0c9b4 Added game label 2026-05-02 15:33:31 +02:00
5789650c97 Refactoring
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-05-02 01:31:49 +02:00
9e4f44491c Made match notes non nullable
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-05-02 01:28:00 +02:00
078daeffc9 Fixed test issues
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-05-01 18:06:09 +02:00
ab9a8d0193 Fixed test issues
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-05-01 18:01:07 +02:00
0f2e3493c4 Updated player-group dao + tests 2026-05-01 17:46:47 +02:00
ae3a8b496e Added copyWith(), == and hashCode overwrites for model classes 2026-05-01 17:22:20 +02:00
cbc8a1afce Updated player-match dao and tests 2026-05-01 16:49:33 +02:00
f49440367c Finalized and updated team implementation, updated team dao, tests, and ex-/import 2026-05-01 14:31:15 +02:00
be6b968a43 Updated match dao + tests 2026-05-01 11:57:03 +02:00
2f5b9e5ff2 Cherry picked changes from 119-implementierung-der-games
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-04-28 15:27:52 +02:00
785873d3c8 Fixed error in game tests
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-04-24 16:36:36 +02:00
99b894c580 Updated score dao + tests 2026-04-24 16:36:27 +02:00
92577e4ed9 Updated games dao + tests 2026-04-24 16:01:14 +02:00
95cad71ea0 Updated player dao + tests 2026-04-24 14:29:01 +02:00
8df5c24fa8 Updated group dao + tests 2026-04-24 13:51:20 +02:00
e8c50b2f32 Renamed file 2026-04-24 13:10:34 +02:00
a5f00f16ab Updated licenses [skip ci] 2026-04-24 10:33:06 +00:00
da99a6ec99 Updated version number [skip ci] 2026-04-24 10:32:28 +00:00
7effa77f82 Merge pull request 'Verschiedene Regelsätze implementieren' (#194) from feature/132-verschiedene-regelsaetze-implementieren into development
All checks were successful
Push Pipeline / test (push) Successful in 44s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 37s
Push Pipeline / format (push) Successful in 1m0s
Push Pipeline / build (push) Successful in 5m42s
Reviewed-on: #194
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-04-24 10:31:36 +00:00
1d02c04b7a Merge branch 'development' into feature/132-verschiedene-regelsaetze-implementieren
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 54s
# Conflicts:
#	lib/core/common.dart
#	lib/presentation/views/main_menu/statistics_view.dart
#	lib/presentation/widgets/player_selection.dart
2026-04-24 12:15:57 +02:00
39eba80e3f Updated licenses [skip ci] 2026-04-24 09:20:20 +00:00
daf1bc27d8 Updated version number [skip ci] 2026-04-24 09:19:39 +00:00
3140c9310b Merge pull request 'Kennzeichnung für doppelte Spielernamen' (#200) from enhancement/182-kennzeichnung-fuer-doppelte-spielernamen into development
All checks were successful
Push Pipeline / test (push) Successful in 48s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 39s
Push Pipeline / format (push) Successful in 59s
Push Pipeline / build (push) Successful in 5m48s
Reviewed-on: #200
2026-04-24 09:18:44 +00:00
23b903e28a Added ruleset depending icons and adjusted mvp text
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 45s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-04-22 00:19:48 +02:00
6f0147420a Added fallback 2026-04-22 00:02:36 +02:00
2fe43a5ad1 Removed unnecessary table association
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-04-21 23:40:55 +02:00
a7e234cf10 Removed unnecessary function
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-04-21 23:39:44 +02:00
db554557fe Fixed versioning
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 50s
Pull Request Pipeline / lint (pull_request) Successful in 53s
2026-04-21 23:36:06 +02:00
1a2ad547be Downgraded flutter again
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 45s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-04-21 23:27:35 +02:00
52518dc525 Downgraded flutter again
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 17s
Pull Request Pipeline / test (pull_request) Failing after 19s
2026-04-21 23:26:30 +02:00
0b991026c7 Updated packages
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 17s
Pull Request Pipeline / test (pull_request) Failing after 18s
2026-04-21 23:25:07 +02:00
bdb33f1ec8 Updated json schmema 2026-04-21 23:19:46 +02:00
d381036849 simplified json map 2026-04-21 22:33:07 +02:00
5cbcf626e8 Removed game in compact mode 2026-04-21 22:32:52 +02:00
852b5f444c Merge branch 'development' into feature/132-verschiedene-regelsaetze-implementieren
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 52s
Pull Request Pipeline / lint (pull_request) Successful in 56s
2026-04-21 22:22:47 +02:00
b4b598d1f5 Fixed state bug
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 55s
Pull Request Pipeline / lint (pull_request) Successful in 57s
2026-04-21 22:22:35 +02:00
dfc7788087 Updated skeleton data 2026-04-21 22:17:31 +02:00
e910f1dcd3 Fixed tests 2026-04-21 22:17:17 +02:00
b1abbf6376 Added missing score import 2026-04-21 22:14:04 +02:00
b0a8529c1c Formatting 2026-04-21 22:13:44 +02:00
a3ae8ef5b8 Fixed json methods 2026-04-21 22:13:15 +02:00
f24aeff55a Fixed bug 2026-04-21 22:12:13 +02:00
543b4d949e Implemented correct score handling 2026-04-21 22:11:45 +02:00
571d32f07a Added toString method + default values 2026-04-21 22:11:09 +02:00
31c6e03f4d Fixed tests 2026-04-21 20:26:11 +02:00
2035e5b7d4 Removed unnecessary declared attributes 2026-04-21 20:24:10 +02:00
0bad0862a7 Adjusted colors 2026-04-21 20:19:05 +02:00
4322e75811 Implemented basic game choosing functionality 2026-04-21 20:17:54 +02:00
2c2bb582fd Added null & empty handling 2026-04-21 20:17:35 +02:00
5e6cf22a9f Added empty check for score fields 2026-04-21 20:17:17 +02:00
9230b0caba Removed dead code 2026-04-21 20:06:41 +02:00
68141a3da2 Updated game + ruleset display 2026-04-21 20:06:33 +02:00
86f2ba01e5 Updated localization declaration 2026-04-21 20:06:14 +02:00
c6a9e53cff Updated getting winner & looser functions 2026-04-21 18:53:03 +02:00
9364f0d9d6 Updated score and winner handling 2026-04-21 18:38:00 +02:00
522441b0ca Added tie localization 2026-04-21 18:35:40 +02:00
316a50dad0 Added point localizations 2026-04-21 17:19:11 +02:00
1363c1fb06 Added function for point label 2026-04-21 17:19:01 +02:00
487dbf944c Merge branch 'development' into enhancement/182-kennzeichnung-fuer-doppelte-spielernamen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 42s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-04-21 10:59:34 +00:00
381c1ae23a Merge branch 'main' into enhancement/182-kennzeichnung-fuer-doppelte-spielernamen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 48s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-04-21 12:56:36 +02:00
32ed7ac3b5 Updated licenses [skip ci] 2026-04-21 08:48:30 +00:00
b2eeabe1ef Updated version number [skip ci] 2026-04-21 08:47:45 +00:00
c63f9067d3 Merge pull request 'Popup-Buttons überarbeiten' (#199) from enhancement/popup-buttons-ueberarbeiten into development
All checks were successful
Push Pipeline / test (push) Successful in 50s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / generate_licenses (push) Successful in 43s
Push Pipeline / format (push) Successful in 1m9s
Push Pipeline / build (push) Successful in 6m1s
Reviewed-on: #199
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-04-21 08:46:46 +00:00
4e97f6723a Added nameCount to statistic tiles
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Successful in 50s
2026-04-20 16:39:33 +02:00
9a0386f22d Added case for not fetching a player
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-04-19 23:41:10 +02:00
fcf845af4d Implemented name count update in player selection
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 43s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-04-19 23:22:14 +02:00
653b85d28d Fixed tests 2026-04-19 23:11:23 +02:00
9a2afbfd3b Added ui implementation 2026-04-19 22:49:21 +02:00
a1398623b0 Added database functionality + tests 2026-04-19 22:49:06 +02:00
9c4eff5056 Moved button
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-04-19 16:02:14 +02:00
ad2e4bc398 Added constraint parameter 2026-04-19 15:56:11 +02:00
2ad3698067 Updated documentation 2026-04-19 15:25:22 +02:00
32e1c587d4 Updated popups in views 2026-04-19 15:19:38 +02:00
55437d83c4 Changed popup class structure 2026-04-19 15:19:30 +02:00
15702a108d Add: custom dialog action 2026-04-19 15:18:27 +02:00
ddf32797aa Implemented ruleset in match view
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Failing after 46s
2026-04-14 23:26:26 +02:00
df1bc4bf32 Merge branch 'development' into feature/132-verschiedene-regelsaetze-implementieren
# Conflicts:
#	lib/presentation/views/main_menu/match_view/match_result_view.dart
2026-04-14 23:09:15 +02:00
36fda30f27 Updated licenses [skip ci] 2026-04-14 16:13:31 +00:00
1ab869ec26 Updated version number [skip ci] 2026-04-14 16:12:55 +00:00
52b78e44e4 Merge pull request 'Score implementation ergänzen' (#196) from feature/191-score-implementation-ergaenzen into development
All checks were successful
Push Pipeline / test (push) Successful in 42s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 35s
Push Pipeline / format (push) Successful in 54s
Push Pipeline / build (push) Successful in 5m32s
Reviewed-on: #196
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-04-14 16:12:05 +00:00
e827f4c527 Fixed references
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 42s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-04-13 22:53:39 +02:00
73c85b1ff2 Renamed score dao
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 44s
Pull Request Pipeline / test (pull_request) Failing after 1m33s
2026-04-13 22:49:30 +02:00
c43b7b478c Updated comments
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-04-13 22:47:29 +02:00
c9188c222a Added edge cases for games, groups, teams and matches 2026-04-13 22:16:34 +02:00
fcca74cea5 Refactoring 2026-04-13 22:16:12 +02:00
80672343b9 Refactoring
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 41s
Pull Request Pipeline / lint (pull_request) Successful in 48s
2026-04-12 02:02:27 +02:00
d903a9fd7e Refactoring 2026-04-12 02:02:16 +02:00
bed8a05057 Refactoring 2026-04-12 02:01:26 +02:00
8a312152a5 Refactoring 2026-04-12 02:01:12 +02:00
eeb68496d5 Removed tester input
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 41s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-04-12 01:42:47 +02:00
65704b4a03 Updated schema to add scores attribute
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 46s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-04-12 01:42:02 +02:00
f40113ef2c Added restriction to schema 2026-04-12 01:37:31 +02:00
723699d363 Added test for json schema
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 44s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-04-12 01:32:21 +02:00
0823a4ed41 Corrected type
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 42s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-04-12 01:21:17 +02:00
22753d29c1 Refactored method, added tests for DTS
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 44s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-04-12 01:20:13 +02:00
541cbe9a54 Overhauled score tests
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 40s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-04-12 00:07:16 +02:00
26d60fc8b2 Updated score saving in match 2026-04-11 23:34:57 +02:00
520edd0ca6 Removed matchId from Score class
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 43s
Pull Request Pipeline / lint (pull_request) Successful in 49s
2026-04-09 18:00:19 +02:00
73533b8c4f Renamed ScoreEntry to Score 2026-04-08 23:55:24 +02:00
be58c9ce01 Refactoring + fixed tests 2026-04-08 23:53:27 +02:00
6a49b92310 Moved dao methods 2026-04-08 23:33:42 +02:00
855b7c8bea Moved dao methods 2026-04-08 23:22:33 +02:00
e10f05adb5 Temp fixed all database functionality 2026-04-08 22:33:02 +02:00
ad6d08374e Renamed folder to "models" 2026-04-08 22:27:50 +02:00
14d46d7e52 Seperated score entry class
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 42s
Pull Request Pipeline / lint (pull_request) Failing after 47s
2026-04-08 22:20:47 +02:00
b6fa71726e Added scores to match class 2026-04-08 22:20:07 +02:00
98c846ddc6 Added scores to match class 2026-04-08 22:19:01 +02:00
42f476919b Removed score column 2026-04-08 22:17:37 +02:00
13c88cb958 Updated licenses [skip ci] 2026-03-09 20:32:00 +00:00
6e4375e459 Updated version number [skip ci] 2026-03-09 20:31:22 +00:00
59d1efb4fb Merge pull request 'Bearbeiten und Löschen von Gruppen' (#148) from feature/118-bearbeiten-und-löschen-von-gruppen into development
All checks were successful
Push Pipeline / test (push) Successful in 38s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 34s
Push Pipeline / format (push) Successful in 52s
Push Pipeline / build (push) Successful in 5m8s
Reviewed-on: #148
Reviewed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
2026-03-09 20:30:38 +00:00
611033b5cd Moved getGroupMatches + Tests
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-09 21:27:05 +01:00
4e98dcde41 remove nullable from match name
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-09 21:13:20 +01:00
a304d9adf7 change getGroupMatches 2026-03-09 21:13:08 +01:00
23d00c64ab fix comments
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 40s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-03-09 21:00:13 +01:00
4726d170a1 update dependencies in pubspec.yaml for build_runner and drift_dev
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-09 15:29:26 +01:00
3fe421676c update onDelete behavior for groupId in match_table to set null 2026-03-09 15:29:18 +01:00
b0b039875a add callback & implement deleteObsoleteMatchGroupRelations func 2026-03-09 15:29:03 +01:00
840faab024 add statistics reload and fix wrong best player calculation 2026-03-09 15:28:37 +01:00
6c50eaefc7 Add deleteMatchGroup method & tests 2026-03-09 15:27:15 +01:00
9b2fcf1860 Fix: Linter exclude
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 40s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-03-08 22:27:27 +01:00
f0c575d2c9 Implemented different result view depending on ruleset
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Failing after 45s
2026-03-08 22:25:55 +01:00
d5a7bb320f Implememented different result tiles in match detail view for different rulesets 2026-03-08 22:25:23 +01:00
4f91130cb5 Merge remote-tracking branch 'origin/feature/118-bearbeiten-und-löschen-von-gruppen' into feature/118-bearbeiten-und-löschen-von-gruppen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-08 15:10:37 +01:00
2214ea8e7d Refactor group creation and editing logic into separate methods 2026-03-08 15:10:31 +01:00
5b7ef4051d Merge remote-tracking branch 'origin/feature/118-bearbeiten-und-löschen-von-gruppen' into feature/118-bearbeiten-und-löschen-von-gruppen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-03-08 12:22:57 +01:00
e3c39521a0 Merge remote-tracking branch 'origin/feature/118-bearbeiten-und-löschen-von-gruppen' into feature/118-bearbeiten-und-löschen-von-gruppen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-03-08 11:27:38 +01:00
b83719f16d Refactor group saving logic into a separate method 2026-03-08 11:27:18 +01:00
de0344d63d Added game fix 2026-03-08 11:10:06 +01:00
4ae1432943 excluded license file from linter rules
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-03-08 11:07:13 +01:00
84b8541822 Fixed match edit error with game
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Failing after 46s
2026-03-08 11:00:42 +01:00
544e55c4fd Merge branch 'development' into feature/132-verschiedene-regelsaetze-implementieren
# Conflicts:
#	lib/l10n/arb/app_de.arb
#	lib/l10n/arb/app_en.arb
#	lib/l10n/generated/app_localizations.dart
#	lib/l10n/generated/app_localizations_de.dart
#	lib/l10n/generated/app_localizations_en.dart
#	lib/presentation/views/main_menu/match_view/match_result_view.dart
2026-03-08 10:57:33 +01:00
feb2b756bd Merge branch 'development' into feature/118-bearbeiten-und-löschen-von-gruppen
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Failing after 45s
2026-03-08 08:39:24 +00:00
244c1b0bb0 Updated licenses [skip ci] 2026-03-08 08:29:28 +00:00
bfad74db22 Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 45s
Pull Request Pipeline / test (pull_request) Successful in 40s
# Conflicts:
#	lib/presentation/views/main_menu/group_view/create_group_view.dart
2026-03-08 09:29:06 +01:00
864fde35ef Updated version number [skip ci] 2026-03-08 08:28:54 +00:00
934c048687 Merge pull request 'Bearbeiten und Löschen von Matches' (#171) from feature/120-bearbeiten-und-loeschen-von-matches into development
All checks were successful
Push Pipeline / test (push) Successful in 38s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 34s
Push Pipeline / format (push) Successful in 49s
Push Pipeline / build (push) Successful in 5m35s
Reviewed-on: #171
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-03-08 08:28:10 +00:00
c50ad288fa Implemented basic structure
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Failing after 44s
2026-03-08 08:29:45 +01:00
494dec8c61 Added localizations 2026-03-08 08:29:15 +01:00
975679b048 Updated dependencie 2026-03-08 08:24:35 +01:00
8e20fe1034 fix dart analysis issues
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-03-07 23:34:43 +01:00
81aad9280c Merge dev & implement db
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Failing after 44s
2026-03-07 23:33:25 +01:00
73c8865eb5 Removed todo
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-07 22:48:57 +01:00
9d2b6a0286 Adapted getTemporaryGame method 2026-03-07 22:47:28 +01:00
588b5053e8 typo 2026-03-07 22:46:21 +01:00
0597b21ac1 Added condition 2026-03-07 22:45:55 +01:00
a846e4d7ea Removed dead code 2026-03-07 22:44:49 +01:00
16aecffdbe Change var name 2026-03-07 22:43:24 +01:00
7810443a00 Fix: SetState Error
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-03-07 22:11:51 +01:00
27c6d8b293 Small corrections 2026-03-07 21:57:51 +01:00
0822039a5f Fix: Not updated match view after updating matches players
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-07 21:50:25 +01:00
0b118800e4 Fixed issue with group replacing solo players 2026-03-07 21:33:51 +01:00
90cc9587ca Removed import
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-03-07 17:43:42 +01:00
4c479676d2 Added properties
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Failing after 44s
2026-03-07 17:38:32 +01:00
4bcb10df81 Fix: Winner gets resetted, if player gets removed from the game 2026-03-07 17:03:52 +01:00
664af7ffee Updated dependencies 2026-03-07 16:51:37 +01:00
2bd5c30094 Fix: Setting winner
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 39s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-03-06 22:21:07 +01:00
e909f347e3 Removed unused function 2026-03-06 22:11:15 +01:00
8e4fe26ad9 Updated theme 2026-03-06 22:09:58 +01:00
a8ade294b5 Added common.dart
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 40s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-03-06 21:53:46 +01:00
688a8a1706 Added comment 2026-03-06 20:59:13 +01:00
598b8d0f9e Updated player receiving logic 2026-03-06 20:59:04 +01:00
cff95aff00 Updated view aligning with new database 2026-03-06 16:51:26 +01:00
f07532c1e2 Fix: Added correct localizations 2026-03-06 16:51:01 +01:00
b68c570d47 Fixed issues with match.players including group.members, added callback 2026-03-06 16:49:56 +01:00
8bd251ac7d Fixed match result view with new db 2026-03-05 22:24:14 +01:00
89ad6824e6 Added import, removed unessecary player add 2026-03-05 22:22:13 +01:00
f9edf64e83 Small changes 2026-03-05 22:21:50 +01:00
37955c5701 test: Setting & fetching winner 2026-03-05 12:25:09 +01:00
5ed35362ac Fix: Setting & fetching winner 2026-03-05 12:25:01 +01:00
8e75f6af56 Merge branch 'development' into feature/120-bearbeiten-und-loeschen-von-matches
# Conflicts:
#	lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart
2026-03-05 11:00:43 +01:00
5b8dd6adb2 Updated version number [skip ci] 2026-03-04 19:02:47 +00:00
1273c99fdc Merge pull request 'Neue Datenbank Struktur' (#156) from feature/88-neue-datenbank-struktur into development
Some checks failed
Push Pipeline / test (push) Successful in 36s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Failing after 25s
Push Pipeline / format (push) Has been skipped
Push Pipeline / build (push) Successful in 6m12s
Reviewed-on: #156
Reviewed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-03-04 19:02:03 +00:00
gelbeinhalb
e5bc2076dc Merge remote-tracking branch 'origin/development' into feature/88-neue-datenbank-struktur
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 40s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-03-04 19:34:38 +01:00
gelbeinhalb
5d45339337 set notes default
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 38s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-03-04 13:36:07 +01:00
gelbeinhalb
f04d57382c set notes default
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 41s
Pull Request Pipeline / lint (pull_request) Successful in 47s
2026-03-04 13:35:43 +01:00
gelbeinhalb
5094554475 set description default 2026-03-04 13:35:18 +01:00
gelbeinhalb
866f79998c set description default 2026-03-04 13:35:04 +01:00
e71943f6e2 Implemented Radio Theme
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 35s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-02-24 18:01:10 +01:00
f07103a516 Fixed theme issue 2026-02-24 17:49:24 +01:00
b84a893706 Typo
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 36s
Pull Request Pipeline / lint (pull_request) Successful in 42s
2026-02-23 21:35:26 +01:00
527ffd194f Fixed PR problems
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-02-23 21:34:29 +01:00
9e9491c98e Merge remote-tracking branch 'refs/remotes/origin/development' into feature/120-bearbeiten-und-loeschen-von-matches
# Conflicts:
#	lib/presentation/views/main_menu/custom_navigation_bar.dart
#	lib/presentation/views/main_menu/group_view/create_group_view.dart
#	lib/presentation/views/main_menu/group_view/group_detail_view.dart
#	lib/presentation/views/main_menu/group_view/group_view.dart
#	lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart
#	lib/presentation/views/main_menu/match_view/match_view.dart
#	pubspec.yaml
2026-02-23 21:23:28 +01:00
gelbeinhalb
8e4cff19d1 change comment 2026-02-23 19:29:20 +01:00
048fb0ef43 Updated licenses [skip ci] 2026-02-07 20:19:54 +00:00
a4bc03111d Updated version number [skip ci] 2026-02-07 20:19:24 +00:00
00abc4d1c0 Merge pull request 'NavBar optimieren' (#189) from enhancement/188-navbar-optimieren into development
All checks were successful
Push Pipeline / test (push) Successful in 33s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 28s
Push Pipeline / format (push) Successful in 53s
Push Pipeline / build (push) Successful in 6m2s
Reviewed-on: #189
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-02-07 20:18:46 +00:00
d4fcc8106f Removed spacing in navbar item
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 44s
2026-02-07 20:21:46 +01:00
gelbeinhalb
e4ea46c6cd Merge remote-tracking branch 'origin/development' into feature/88-neue-datenbank-struktur
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 40s
Pull Request Pipeline / test (pull_request) Successful in 36s
2026-02-07 20:11:51 +01:00
gelbeinhalb
e881cf0555 fix expected null when empty string is correct
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 40s
Pull Request Pipeline / test (pull_request) Successful in 35s
2026-02-07 18:17:08 +01:00
gelbeinhalb
278544788e fix formatting
Some checks failed
Pull Request Pipeline / lint (pull_request) Successful in 1m25s
Pull Request Pipeline / test (pull_request) Failing after 36s
2026-02-07 17:40:27 +01:00
gelbeinhalb
a12f4eb1c1 implement winner methods
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 28s
Pull Request Pipeline / lint (pull_request) Failing after 40s
2026-02-07 17:35:43 +01:00
gelbeinhalb
0eb8e2683c add replace players in a match test 2026-02-07 17:31:23 +01:00
gelbeinhalb
07b9b78252 add replace players in a match method 2026-02-07 17:31:19 +01:00
gelbeinhalb
fa9ad9dbae add test for replacing group players 2026-02-07 17:26:07 +01:00
gelbeinhalb
25699dffc0 add replaceGroupPlayers method 2026-02-07 17:25:49 +01:00
487efb4d61 Added type annotation
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 35s
Pull Request Pipeline / lint (pull_request) Successful in 46s
2026-02-06 14:07:43 +01:00
3f790cfbb1 Renamed variable 2026-02-06 14:04:16 +01:00
ee1962ef9c Implemented new nav bar 2026-02-06 14:03:57 +01:00
a4d4703069 Updated licenses [skip ci] 2026-02-06 12:32:19 +00:00
fabb7bae19 Updated version number [skip ci] 2026-02-06 12:31:47 +00:00
gelbeinhalb
70d6178829 restructure tests 2026-02-01 19:51:57 +01:00
gelbeinhalb
7aba8554c0 players cant be null
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 40s
Pull Request Pipeline / lint (pull_request) Failing after 44s
2026-02-01 18:23:58 +01:00
gelbeinhalb
dbef735a82 add color enum 2026-02-01 18:13:03 +01:00
gelbeinhalb
ccfea71a35 reduce line length 2026-02-01 17:56:24 +01:00
gelbeinhalb
415cae18cd added endedAt to matches 2026-02-01 17:55:42 +01:00
gelbeinhalb
2a3ea32193 change how optional parameters are defined 2026-02-01 17:31:40 +01:00
gelbeinhalb
2ea68dcc89 fix errors after merging 2026-02-01 17:29:19 +01:00
gelbeinhalb
acf3a7b003 Merge remote-tracking branch 'origin/development' into feature/88-neue-datenbank-struktur
# Conflicts:
#	lib/data/dao/group_match_dao.dart
#	lib/data/dao/match_dao.dart
#	lib/data/dao/player_match_dao.dart
#	lib/data/db/database.dart
#	lib/data/db/database.g.dart
#	lib/data/db/tables/group_match_table.dart
#	lib/data/db/tables/player_match_table.dart
#	lib/data/dto/match.dart
#	lib/presentation/views/main_menu/home_view.dart
#	lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart
#	lib/presentation/views/main_menu/match_view/match_view.dart
#	lib/services/data_transfer_service.dart
#	test/db_tests/game_test.dart
#	test/db_tests/group_match_test.dart
#	test/db_tests/player_match_test.dart
2026-02-01 15:55:06 +01:00
gelbeinhalb
1d352821fc all parameters are now required 2026-01-30 13:13:06 +01:00
d1458443eb Added ref again
Some checks failed
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / build (push) Failing after 31s
Push Pipeline / generate_licenses (push) Successful in 30s
Push Pipeline / test (push) Successful in 38s
Push Pipeline / format (push) Successful in 41s
2026-01-26 14:47:26 +01:00
9c00b48de5 Updated licenses [skip ci] 2026-01-26 13:38:35 +00:00
03ce304a0a Updated version number [skip ci] 2026-01-26 13:38:01 +00:00
dde617d429 Tried new workflow fix
Some checks failed
Push Pipeline / update_version (push) Successful in 4s
Push Pipeline / generate_licenses (push) Successful in 33s
Push Pipeline / test (push) Successful in 39s
Push Pipeline / format (push) Successful in 47s
Push Pipeline / build (push) Failing after 1m42s
2026-01-26 14:37:23 +01:00
03a2df4fdf Updated version number [skip ci] 2026-01-26 08:55:12 +00:00
96ef70b209 Updated version number [skip ci] 2026-01-26 08:45:49 +00:00
4ae59ec881 Merge pull request 'README vervollständigen' (#150) from enhancement/81-readme-vervollstaendigen into development
Some checks failed
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Failing after 30s
Push Pipeline / format (push) Has been skipped
Push Pipeline / test (push) Successful in 38s
Push Pipeline / build (push) Successful in 5m5s
Reviewed-on: #150
2026-01-26 08:45:42 +00:00
gelbeinhalb
3bd6dd4189 fix typo 2026-01-25 10:15:50 +01:00
c162e245bd Updated license name in Readme
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 42s
2026-01-24 22:35:11 +01:00
481afd7533 Added example CONTRIBUTING.md
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 43s
2026-01-24 19:17:33 +01:00
af42ebbf92 Merge remote-tracking branch 'origin/development' into enhancement/81-readme-vervollstaendigen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 37s
Pull Request Pipeline / lint (pull_request) Successful in 45s
2026-01-24 17:48:25 +01:00
34e442dbe9 added white space
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-24 17:47:32 +01:00
8783d0ac44 Version badges in one row
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-24 17:30:56 +01:00
7f356b0c86 Updated licenses [skip ci] 2026-01-24 13:55:49 +00:00
e4a2ac6b47 Updated version number [skip ci] 2026-01-24 13:55:18 +00:00
6065b53ce9 Updated workflow
All checks were successful
Push Pipeline / test (push) Successful in 36s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Successful in 30s
Push Pipeline / format (push) Successful in 50s
Push Pipeline / build (push) Successful in 5m21s
2026-01-24 14:53:31 +01:00
c644ccfb06 Updated version number [skip ci] 2026-01-24 12:21:35 +00:00
2dd7d0285d Pipeline Push Error (again) (#187)
Some checks failed
Push Pipeline / test (push) Successful in 34s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Failing after 30s
Push Pipeline / format (push) Has been skipped
Push Pipeline / build (push) Successful in 5m23s
Pipeline Push Error (again) (#187)
Co-authored-by: Gitea Actions [bot] <actions@yannick-weigert.de>
Reviewed-on: #187
2026-01-24 12:20:55 +00:00
cf5883b430 Updated version number [skip ci] 2026-01-24 12:03:27 +00:00
7af2b43193 Merge pull request 'Hotfix: Pipeline Push Error' (#186) from hotifx/pipeline-push-error into development
Some checks failed
Push Pipeline / test (push) Successful in 36s
Push Pipeline / update_version (push) Successful in 5s
Push Pipeline / generate_licenses (push) Failing after 28s
Push Pipeline / format (push) Has been skipped
Push Pipeline / build (push) Successful in 5m15s
Reviewed-on: #186
2026-01-24 12:02:46 +00:00
90cc4d4c2a Added missing flutter step
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 36s
Pull Request Pipeline / lint (pull_request) Successful in 42s
2026-01-24 12:49:40 +01:00
db2ba2571f Added pull 2026-01-24 12:49:21 +01:00
3b01c4623c Updated version number [skip ci] 2026-01-24 11:41:50 +00:00
c5c9a43459 Update licenses in push pipeline (#184)
Some checks failed
Push Pipeline / test (push) Successful in 35s
Push Pipeline / update_version (push) Successful in 4s
Push Pipeline / generate_licenses (push) Failing after 2m1s
Push Pipeline / format (push) Has been skipped
Push Pipeline / build (push) Successful in 5m22s
Update licenses in push pipeline (#184)
Co-authored-by: Gitea Actions [bot] <actions@yannick-weigert.de>
Reviewed-on: #184
2026-01-24 11:41:07 +00:00
b2e58f2539 Updated version number [skip ci] 2026-01-24 10:33:32 +00:00
58dc5d8c2e Extend workflow to include build stage (#185)
All checks were successful
Push Pipeline / test (push) Successful in 35s
Push Pipeline / format (push) Successful in 50s
Push Pipeline / update_version (push) Successful in 4s
Push Pipeline / build (push) Successful in 5m22s
Extend workflow to include build stage (#185)
Reviewed-on: #185
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-24 10:32:00 +00:00
fd7dbd1155 Added gnu license
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m5s
2026-01-23 22:30:54 +01:00
61b72cf595 Merge remote-tracking branch 'origin/enhancement/81-readme-vervollstaendigen' into enhancement/81-readme-vervollstaendigen
# Conflicts:
#	LICENSE
2026-01-23 22:15:01 +01:00
81c6c377d4 Added placeholder LICENSE and CONTRIBUTING.md 2026-01-23 22:14:51 +01:00
92f2b4db95 Added placeholder LICENSE and CONTRIBUTING.md
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-23 22:14:12 +01:00
5178adf71c Changed screenshot order
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m14s
2026-01-23 22:11:33 +01:00
4a6d639f1c Updated readme
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 1m59s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-23 22:10:30 +01:00
e9cf707fca Merge branch 'refs/heads/development' into enhancement/81-readme-vervollstaendigen 2026-01-23 20:56:56 +01:00
2b7941202a Updated version number [skip ci] 2026-01-23 12:31:09 +00:00
92317bcbdf Merge pull request 'App-Name, Icon und Design' (#179) from documentation/131-app-name-icon-und-design into development
All checks were successful
Push Pipeline / test (push) Successful in 1m56s
Push Pipeline / format (push) Successful in 2m4s
Push Pipeline / update_version (push) Successful in 4s
Reviewed-on: #179
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-23 12:28:56 +00:00
gelbeinhalb
b0cb385756 ruleset is now a required game enum parameter
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-23 11:54:37 +01:00
gelbeinhalb
118b316a35 description is now a required game parameter 2026-01-23 11:25:20 +01:00
gelbeinhalb
55f5aac4e2 color is now a required game parameter 2026-01-23 11:08:11 +01:00
ceade5cafd Fixed ios laucn screen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m0s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-22 22:34:36 +01:00
6060afc543 Renamed package & bundle identifier
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 1m58s
Pull Request Pipeline / lint (pull_request) Successful in 2m18s
2026-01-22 22:13:12 +01:00
ac6399d707 Merge branch 'development' into documentation/131-app-name-icon-und-design 2026-01-22 21:46:11 +01:00
gelbeinhalb
6006c6d3f7 Merge remote-tracking branch 'origin/development' into feature/88-neue-datenbank-struktur
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 1m58s
Pull Request Pipeline / lint (pull_request) Successful in 2m17s
2026-01-21 16:10:47 +01:00
gelbeinhalb
0ddb4edbc9 remove unused variable
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-21 16:08:21 +01:00
gelbeinhalb
7339194ba0 fix data import and export
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Failing after 2m18s
2026-01-21 15:43:56 +01:00
gelbeinhalb
bd5e38a3ca save game to database on create 2026-01-21 15:42:47 +01:00
gelbeinhalb
12b713bb70 remove skip from test
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m0s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-21 12:04:13 +01:00
gelbeinhalb
e55cea0dcc fix missing await 2026-01-21 12:04:00 +01:00
gelbeinhalb
b2a3a0cf75 fix getting non-existent team throws exception test
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m19s
2026-01-21 11:55:15 +01:00
gelbeinhalb
f142169371 fix overlapping members in teams test 2026-01-21 11:54:00 +01:00
gelbeinhalb
0b778210ef add new team tests
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-21 11:36:23 +01:00
gelbeinhalb
748361d04f add new score tests 2026-01-21 11:33:37 +01:00
gelbeinhalb
2e6a2b8e55 add more player_match tests 2026-01-21 11:26:46 +01:00
gelbeinhalb
15894096f3 fix missing await error 2026-01-21 11:11:46 +01:00
gelbeinhalb
d488eac3ae add more group tests 2026-01-21 11:11:37 +01:00
gelbeinhalb
19b2685714 add more player tests 2026-01-21 11:03:09 +01:00
gelbeinhalb
068ca95afc Merge branch 'feature/88-neue-datenbank-struktur' of git.yannick-weigert.de:liquid-development/game-tracker into feature/88-neue-datenbank-struktur
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m16s
2026-01-20 16:34:43 +01:00
gelbeinhalb
0d28f4b87c remove winner test again 2026-01-20 16:34:38 +01:00
gelbeinhalb
2e454a530a remove winner test again 2026-01-20 16:33:12 +01:00
gelbeinhalb
6c39e1e574 remove winner check
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-20 16:31:52 +01:00
gelbeinhalb
b33260ec23 fix match missing game 2026-01-20 16:31:43 +01:00
gelbeinhalb
b108375ad5 remove winner tests
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m15s
2026-01-20 16:03:37 +01:00
gelbeinhalb
e09ccf9356 add comments to all tests
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-20 15:58:16 +01:00
8ee2b6cb06 Updated version number [skip ci] 2026-01-20 14:55:05 +00:00
b14b7733ca Merge pull request 'Push Pipeline Error' (#181) from hotfix/push-pipeline-error into development
All checks were successful
Push Pipeline / test (push) Successful in 2m7s
Push Pipeline / format (push) Successful in 2m8s
Push Pipeline / update_version (push) Successful in 5s
Reviewed-on: #181
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-01-20 14:52:47 +00:00
gelbeinhalb
b0b21bcba6 add new group tests 2026-01-20 15:48:40 +01:00
gelbeinhalb
dec74e9b62 add game tests 2026-01-20 15:41:05 +01:00
gelbeinhalb
4e73babb71 rename game_test to match_test 2026-01-20 15:28:26 +01:00
bc51b23563 Updated ref names
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m13s
Pull Request Pipeline / test (pull_request) Successful in 2m22s
2026-01-20 12:03:31 +01:00
057f8c1d58 Changed workflow back to prod mode 2026-01-20 12:00:33 +01:00
4c1c22123e Updated version number [skip ci] 2026-01-20 10:59:27 +00:00
e9929426e0 Removed development restriction
All checks were successful
Push Pipeline / test (push) Successful in 1m57s
Push Pipeline / update_version (push) Successful in 6s
Push Pipeline / format (push) Successful in 2m6s
2026-01-20 11:57:17 +01:00
eb404f3ef2 Fixed push pipeline
All checks were successful
Push Pipeline / test (push) Successful in 1m57s
Push Pipeline / update_version (push) Has been skipped
Push Pipeline / format (push) Successful in 2m17s
2026-01-20 11:54:15 +01:00
c7b4623198 Workflows um Format Stage erweitern (#175)
Some checks failed
Push Pipeline / test (push) Successful in 1m58s
Push Pipeline / update_version (push) Failing after 4s
Push Pipeline / format (push) Successful in 2m8s
Extend workflows with format stage

Co-authored-by: Gitea Actions [bot] <>
Reviewed-on: #175
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-01-20 10:48:49 +00:00
ccd0c62e3c Added launchscreen
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m3s
Pull Request Pipeline / test (pull_request) Successful in 1m56s
2026-01-19 20:04:58 +01:00
gelbeinhalb
25e0c75dc6 add team_test.dart.dart
Some checks failed
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
Pull Request Pipeline / test (pull_request) Failing after 1m56s
2026-01-19 19:52:00 +01:00
gelbeinhalb
fb59372c97 add score_test.dart 2026-01-19 19:51:48 +01:00
9f71c22a56 Fixed pipeline
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m4s
Pull Request Pipeline / test (pull_request) Successful in 2m5s
2026-01-19 16:14:26 +01:00
87d7fbebcd Updated quick create button color
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m6s
Pull Request Pipeline / test (pull_request) Successful in 2m25s
2026-01-19 16:07:20 +01:00
c625174017 Updated text color 2026-01-19 16:07:12 +01:00
gelbeinhalb
8dd2f5f8b8 add name to team
Some checks failed
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
Pull Request Pipeline / test (pull_request) Failing after 1m56s
2026-01-19 15:46:25 +01:00
gelbeinhalb
c97fdc2b5f add match method to change created at
Some checks failed
Pull Request Pipeline / lint (pull_request) Successful in 2m4s
Pull Request Pipeline / test (pull_request) Failing after 1m59s
2026-01-19 14:58:33 +01:00
gelbeinhalb
764ce13240 fix felix typos :) 2026-01-19 14:57:19 +01:00
gelbeinhalb
715b3debbb add updateGroupDescription 2026-01-19 14:18:59 +01:00
gelbeinhalb
bb11c86816 Merge remote-tracking branch 'origin/development' into feature/88-neue-datenbank-struktur
# Conflicts:
#	lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart
2026-01-19 14:05:32 +01:00
53a33ca2e1 Updated app name
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
Pull Request Pipeline / test (pull_request) Successful in 1m56s
2026-01-18 22:58:28 +01:00
e1dd40a1c3 first app icon and theme update 2026-01-18 22:53:54 +01:00
45b11359b3 Merge pull request 'Maximale Input in Textfelder gefixtx' (#176) from hotifx/fix-input-length into development
Reviewed-on: #176
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-18 13:49:53 +00:00
57fb8dbcc8 Merge branch 'development' into hotifx/fix-input-length
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-18 13:46:25 +00:00
9a5929382b Changed button icon
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-18 13:08:33 +01:00
cca09cc27e Renamed MatchProfileView to MatchDetailView 2026-01-18 13:01:24 +01:00
f00aa15518 Merge remote-tracking branch 'origin/feature/118-bearbeiten-und-löschen-von-gruppen' into feature/120-bearbeiten-und-loeschen-von-matches
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m15s
# Conflicts:
#	lib/l10n/generated/app_localizations.dart
2026-01-18 12:59:56 +01:00
810f635987 merge fix
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-18 12:25:47 +01:00
49a6259d8a Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
# Conflicts:
#	lib/presentation/views/main_menu/group_view/create_group_view.dart
#	pubspec.yaml
2026-01-18 12:24:07 +01:00
5a30538aa5 Merge pull request 'Text Overflows durch Tastatur' (#173) from bug/162-text-overflows-durch-tastatur into development
Reviewed-on: #173
2026-01-18 11:23:04 +00:00
1e18105ce0 Merge remote-tracking branch 'origin/development' into bug/162-text-overflows-durch-tastatur
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
# Conflicts:
#	pubspec.yaml
2026-01-18 11:45:50 +01:00
e4c3bc1c5e merge & made group_detail_view.dart & group_create_view.dart work together when editing
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-18 11:41:50 +01:00
14d30f55a7 Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
# Conflicts:
#	lib/l10n/arb/app_de.arb
#	lib/l10n/arb/app_en.arb
#	lib/l10n/generated/app_localizations.dart
#	lib/l10n/generated/app_localizations_de.dart
#	lib/l10n/generated/app_localizations_en.dart
#	lib/presentation/views/main_menu/group_view/groups_view.dart
#	lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart
#	lib/presentation/widgets/tiles/group_tile.dart
#	pubspec.yaml
2026-01-18 11:15:04 +01:00
f1df067824 delete group view & update build nr
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m14s
2026-01-18 10:51:53 +01:00
765610b184 Enhanced editing
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m18s
2026-01-18 01:02:35 +01:00
48d99a0386 Added match editing 2026-01-18 00:46:50 +01:00
a56e738064 Implemented winner update 2026-01-18 00:42:18 +01:00
1450e9b958 Updated attributes 2026-01-18 00:36:21 +01:00
eb114f2853 Added empty winner tile 2026-01-18 00:36:15 +01:00
7faf80de03 Updated extra player count 2026-01-18 00:14:45 +01:00
8fe01c332e Added comment 2026-01-18 00:10:31 +01:00
374c9295ef Implemented MatchProfileView 2026-01-18 00:08:39 +01:00
9ce2ca0ceb Merge pull request 'Match braucht Game' (#174) from enhancement/103-match-braucht-game into development
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m15s
Pull Request Pipeline / lint (pull_request) Successful in 2m15s
Reviewed-on: #174
2026-01-17 22:03:55 +00:00
39e6e485ac remove newline
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-17 22:54:22 +01:00
e9633a898c bump version 2026-01-17 22:54:18 +01:00
94c3bad02b Removed counter
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-17 22:41:02 +01:00
ed2d672dee Implemented maxLength attribute 2026-01-17 22:40:56 +01:00
449639df0e Merge remote-tracking branch 'origin/development' into enhancement/103-match-braucht-game
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
# Conflicts:
#	pubspec.yaml
2026-01-17 21:35:42 +01:00
a713ccb59c Merge pull request 'Gruppenprofile implementieren' (#172) from feature/169-gruppenprofile-implementieren into development
Reviewed-on: #172
2026-01-17 20:34:26 +00:00
f5924c4758 adjusted spacing & changed runAlignment to alignment
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m20s
2026-01-17 21:27:22 +01:00
5c9f44e947 bump build nr
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-17 21:12:53 +01:00
5f987806d6 remove ruleset 2026-01-17 21:12:43 +01:00
92c62000af remove margin from title_description_list_tile.dart 2026-01-17 21:12:17 +01:00
8b7300eac3 Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m7s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
# Conflicts:
#	pubspec.yaml
2026-01-17 16:05:08 +01:00
babe74f2be Merge remote-tracking branch 'origin/feature/169-gruppenprofile-implementieren' into feature/169-gruppenprofile-implementieren
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m15s
Pull Request Pipeline / lint (pull_request) Successful in 2m16s
2026-01-17 15:21:13 +01:00
8a38b9c3ea Updated dateformat to localize 2026-01-17 15:18:56 +01:00
ddd0a5d8bd Updated dateformat to localize
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m11s
Pull Request Pipeline / lint (pull_request) Successful in 2m12s
2026-01-17 15:17:33 +01:00
be9d1b52d2 Merge branch 'development' into feature/169-gruppenprofile-implementieren
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m19s
Pull Request Pipeline / lint (pull_request) Successful in 2m21s
# Conflicts:
#	pubspec.yaml
2026-01-17 14:56:26 +01:00
514e0f8064 Changed date format
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m21s
Pull Request Pipeline / lint (pull_request) Successful in 2m26s
2026-01-17 14:54:06 +01:00
ff47ef38c1 Changed alignment 2026-01-17 14:51:12 +01:00
fa2706395c Merge remote-tracking branch 'origin/development' into bug/162-text-overflows-durch-tastatur
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
# Conflicts:
#	pubspec.yaml
2026-01-17 14:44:49 +01:00
2d1ac3a17c Merge pull request 'Konstanten für Länge von Namen' (#170) from enhancement/158-konstanten-für-länge-von-namen into development
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
Reviewed-on: #170
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-17 13:42:50 +00:00
4fd8d2129b Merge remote-tracking branch 'origin/enhancement/158-konstanten-für-länge-von-namen' into enhancement/158-konstanten-für-länge-von-namen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m14s
Pull Request Pipeline / lint (pull_request) Successful in 2m18s
2026-01-17 14:35:44 +01:00
db41f40a52 Edited comment 2026-01-17 14:35:21 +01:00
0e747710ab Edited comment
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-17 14:33:24 +01:00
9f44f02a35 Changed length to 32 2026-01-17 14:32:25 +01:00
3addaa0f9d Disable resizing when using keyboard
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m7s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-17 14:22:45 +01:00
919a38afe5 fix merge conflicts
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-17 10:21:55 +01:00
def31acfb1 Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
# Conflicts:
#	lib/presentation/views/main_menu/group_view/create_group_view.dart
#	lib/presentation/views/main_menu/settings_view/settings_view.dart
#	lib/presentation/widgets/tiles/group_tile.dart
2026-01-17 10:16:41 +01:00
abb0fcbbd6 Updated file name
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-17 00:57:28 +01:00
fc6eb2b9cf Added comments
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m7s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-17 00:52:13 +01:00
6a0896d818 Implemented ColoredIconContainer 2026-01-17 00:52:09 +01:00
a8129eb134 Implemented first version of group profile 2026-01-16 23:34:47 +01:00
783f772da1 Implemented constants
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m41s
Pull Request Pipeline / lint (pull_request) Successful in 2m45s
2026-01-16 21:52:58 +01:00
b7930d5e2e Adjusted constant name 2026-01-16 21:41:42 +01:00
1b709707b5 Added constants 2026-01-16 21:41:20 +01:00
gelbeinhalb
6a6e36ed7c remove pair
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-16 15:55:17 +01:00
gelbeinhalb
d21c37966e tests create testGame now
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-16 14:15:55 +01:00
gelbeinhalb
b6554c104a Merge remote-tracking branch 'origin/development' into feature/88-neue-datenbank-struktur
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m7s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-16 13:55:05 +01:00
gelbeinhalb
a68bbddc1a temporarily removed group_match_test.dart
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m5s
2026-01-16 13:54:15 +01:00
gelbeinhalb
32fa82e5e7 check for game object on match create 2026-01-16 13:53:57 +01:00
gelbeinhalb
49e990dfea add TEMPORARY winner getter and setter methods to match_dao.dart
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 1m57s
Pull Request Pipeline / lint (pull_request) Failing after 3m32s
2026-01-16 13:44:03 +01:00
gelbeinhalb
40e970a5dc re-add winner parameter 2026-01-16 13:37:00 +01:00
gelbeinhalb
b9b6ff85ea update g files
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 2m5s
Pull Request Pipeline / lint (pull_request) Failing after 2m9s
2026-01-16 12:38:25 +01:00
gelbeinhalb
52c1605ce9 update database.dart 2026-01-16 12:38:16 +01:00
gelbeinhalb
c2a9bda8b1 add team_dao.dart 2026-01-16 12:38:09 +01:00
gelbeinhalb
a13d9c55ea add score_dao.dart 2026-01-16 12:37:37 +01:00
gelbeinhalb
b737cae356 remove group_match_dao.dart 2026-01-16 12:27:20 +01:00
gelbeinhalb
3857665444 update player_match_dao.dart 2026-01-16 12:23:24 +01:00
gelbeinhalb
4b900c12bf add description to player 2026-01-16 12:22:23 +01:00
gelbeinhalb
867d0c55da update match_dao.dart
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m8s
Pull Request Pipeline / test (pull_request) Failing after 2m27s
2026-01-16 12:00:07 +01:00
gelbeinhalb
02d3220c1a add group_match_dao.dart 2026-01-16 11:57:50 +01:00
gelbeinhalb
3ca612b0a1 add description attribute to group_dao.dart 2026-01-16 11:56:47 +01:00
gelbeinhalb
cb66b76e5a add game_dao.dart 2026-01-16 11:55:47 +01:00
gelbeinhalb
b9b72cdd50 add pair
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m11s
Pull Request Pipeline / test (pull_request) Failing after 2m30s
2026-01-16 11:10:42 +01:00
gelbeinhalb
4a56df7f8f add team 2026-01-16 11:09:18 +01:00
gelbeinhalb
f2a12265ad add createdAt to team 2026-01-16 11:09:08 +01:00
gelbeinhalb
c82d72544e add description to player 2026-01-16 11:04:54 +01:00
gelbeinhalb
072021bd4c update match class 2026-01-16 10:50:03 +01:00
gelbeinhalb
6a9e5dc9eb add game.dart
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m8s
Pull Request Pipeline / test (pull_request) Failing after 2m29s
2026-01-16 10:28:55 +01:00
cef02956b1 Merge pull request 'Class Doc-Comment zu Konstruktor verschieben' (#167) from refactoring/157-class-doc-comment-zu-konstruktor-verschieben into development
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m12s
Pull Request Pipeline / lint (pull_request) Successful in 2m12s
Reviewed-on: #167
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-14 18:10:21 +00:00
a479cea5be Merge branch 'development' into refactoring/157-class-doc-comment-zu-konstruktor-verschieben
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-14 09:12:03 +00:00
bbd41a65df Merge pull request 'Neues Popup Design' (#152) from feature/129-neues-popup-design into development
Reviewed-on: #152
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
Reviewed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
2026-01-13 22:01:05 +00:00
2cadab004d Merge cleaning
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-13 22:58:35 +01:00
6a3e184a95 Merge branch 'development' into feature/129-neues-popup-design
# Conflicts:
#	lib/presentation/views/main_menu/settings_view/settings_view.dart
2026-01-13 22:57:19 +01:00
5350113ee1 Updated doc strings 2026-01-13 22:54:19 +01:00
bb79eecdfd Updated and added comments
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-13 22:24:31 +01:00
db51990695 Revert "add background color option to AnimatedDialogButton"
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m19s
This reverts commit 4019ed083f.
2026-01-13 22:17:38 +01:00
e483fc38f3 Merge pull request 'Anzeigefehler mit Snackbar' (#166) from bug/155-anzeigefehler-mit-snackbar into development
Reviewed-on: #166
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-01-13 21:09:21 +00:00
4019ed083f add background color option to AnimatedDialogButton
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m47s
Pull Request Pipeline / test (pull_request) Successful in 2m38s
2026-01-13 21:53:45 +01:00
7be0b96491 Added hiding to prevent stacking snackbars
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m19s
Pull Request Pipeline / lint (pull_request) Successful in 2m23s
2026-01-13 21:45:22 +01:00
efdb5e0361 Fixed snackbar 2026-01-13 21:44:38 +01:00
016c1ceb6e add context to mounted check
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-13 21:38:53 +01:00
1b297d15b0 fix snackbar showing also showing on other screens (#155)
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m10s
Pull Request Pipeline / lint (pull_request) Successful in 2m12s
2026-01-13 21:35:10 +01:00
82ad2b74f8 refactor: enhance documentation and fix punctuation in localization strings
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-13 21:16:59 +01:00
ed642e3d4f merge dev into #118
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 1m59s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-13 21:07:23 +01:00
7cc3873a31 Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
# Conflicts:
#	lib/presentation/views/main_menu/settings_view.dart
2026-01-13 21:02:04 +01:00
b1e9bb3aeb update localization comments for clarity in group and match creation 2026-01-13 21:01:31 +01:00
4161e1e88b add docs to custom_alert_dialog.dart
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-13 20:50:54 +01:00
d662680a34 fix dart analysis errors
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m9s
Pull Request Pipeline / lint (pull_request) Successful in 2m16s
2026-01-13 20:46:42 +01:00
b69d2784df Merge remote-tracking branch 'origin/development' into feature/129-neues-popup-design
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m16s
Pull Request Pipeline / lint (pull_request) Failing after 2m38s
2026-01-13 20:45:47 +01:00
d7f4b1c227 seperate button into widget & change to agreed design 2026-01-13 20:41:03 +01:00
7a1752f773 Merge pull request 'TopCenteredMessage Anzeigefehler' (#161) from bug/159-topcenteredmessage-anzeigefehler into development
Reviewed-on: #161
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-13 14:30:53 +00:00
57357f8aad Merge branch 'development' into bug/159-topcenteredmessage-anzeigefehler
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m12s
# Conflicts:
#	pubspec.yaml
2026-01-13 15:25:59 +01:00
806ed200f7 Merge pull request 'Neues NavBar Design' (#143) from enhancement/138-neues-navbar-design into development
Reviewed-on: #143
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
2026-01-13 14:11:05 +00:00
d5bd0bca5f Fixed displayment bug with TopCenteredMessage
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-12 23:19:37 +01:00
5da12939cb Updated Dart version
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m12s
Pull Request Pipeline / lint (pull_request) Successful in 2m18s
2026-01-12 20:30:57 +01:00
0d20b5847f Updated versions
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m19s
2026-01-12 20:29:18 +01:00
973e327232 Merge remote-tracking branch 'origin/development' into enhancement/81-readme-vervollstaendigen 2026-01-12 20:29:06 +01:00
8c41f6a255 Merge remote-tracking branch 'origin/development' into enhancement/138-neues-navbar-design
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
# Conflicts:
#	pubspec.yaml
2026-01-12 20:21:35 +01:00
70f570489a Merge pull request 'Einstellungen ausgestalten' (#153) from feature/151-einstellungen-ausgestalten into development
Reviewed-on: #153
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-12 19:00:26 +00:00
fa7740101b Small changes on navbar
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-12 19:34:35 +01:00
5aa2a335e3 Merge branch 'development' into enhancement/138-neues-navbar-design
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-12 18:23:26 +00:00
80e601c10e Changed formatting of link displayment
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-12 19:21:04 +01:00
2124c523bc Fixed link issue on android 2026-01-12 19:20:52 +01:00
7d0da81cf5 Updated license tile sizes 2026-01-12 19:09:31 +01:00
cd3a5c2a49 Merge branch 'development' into feature/151-einstellungen-ausgestalten
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m18s
Pull Request Pipeline / test (pull_request) Successful in 2m18s
2026-01-12 17:34:56 +00:00
4628e96456 Merge pull request 'Hotfix: Textarea in Bug Template umgestaltet' (#160) from hotifx/issue-template-fix into development
Reviewed-on: #160
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-12 17:34:48 +00:00
da61f45e8e Merge remote-tracking branch 'origin/development' into enhancement/138-neues-navbar-design
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m13s
Pull Request Pipeline / lint (pull_request) Successful in 2m21s
2026-01-12 17:56:20 +01:00
9344f8212c Updated version number
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m14s
Pull Request Pipeline / lint (pull_request) Successful in 2m22s
2026-01-12 17:55:52 +01:00
6d42d59bad Removed area
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m21s
2026-01-12 17:49:35 +01:00
46118c274c Updated textarea in template
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m14s
Pull Request Pipeline / lint (pull_request) Successful in 2m31s
2026-01-12 17:46:58 +01:00
ab06662397 Merge branch 'development' into feature/129-neues-popup-design
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m0s
Pull Request Pipeline / lint (pull_request) Successful in 2m12s
2026-01-12 16:42:05 +00:00
679f4c94d9 Updated button size
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-12 17:33:20 +01:00
8bf2b9e3dd Updated navbar item color & size 2026-01-12 17:31:30 +01:00
cde40ef293 Updated buttons in main menu
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 1m57s
Pull Request Pipeline / lint (pull_request) Successful in 2m5s
2026-01-12 17:23:43 +01:00
0fb6208345 Created new buttons for the main menu 2026-01-12 17:23:34 +01:00
ec5a686f90 Merge pull request 'Issue-Templates aktualisiert' (#154) from setup/update-issue-and-pr-templates into development
Reviewed-on: #154
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-12 16:22:04 +00:00
f0c6dd8401 Adjusted container size and padding
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m9s
Pull Request Pipeline / lint (pull_request) Successful in 2m17s
2026-01-12 16:20:36 +01:00
7bdad57cc8 Removed old code 2026-01-12 16:18:13 +01:00
5da1b6eecb Removed expanded widget 2026-01-12 16:17:18 +01:00
cdafd4bb6f Made links clickable 2026-01-12 16:16:59 +01:00
6aee055df2 Removed whitespace 2026-01-12 16:04:37 +01:00
6d9871a5f0 Removed Web
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-12 16:03:09 +01:00
gelbeinhalb
be01b5f72a add description to group
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m10s
Pull Request Pipeline / test (pull_request) Failing after 2m29s
2026-01-12 12:51:25 +01:00
gelbeinhalb
e2fe0c7d4d remove group_match_dao
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m18s
Pull Request Pipeline / test (pull_request) Failing after 2m42s
2026-01-12 11:42:03 +01:00
gelbeinhalb
b72ab70e02 add score table
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m22s
Pull Request Pipeline / test (pull_request) Failing after 2m52s
2026-01-12 11:38:38 +01:00
gelbeinhalb
189daf76dd move createdAt below description 2026-01-12 11:35:57 +01:00
gelbeinhalb
0f987f4c7a move match below ids 2026-01-12 11:34:02 +01:00
gelbeinhalb
5dd8f31942 add description to group_table.dart
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m29s
Pull Request Pipeline / test (pull_request) Failing after 2m54s
2026-01-12 11:33:00 +01:00
gelbeinhalb
0394f5edf9 delete group_match_table.dart 2026-01-12 11:32:23 +01:00
gelbeinhalb
d8abad6fd8 add groupid gameid and notes to match 2026-01-12 11:30:37 +01:00
gelbeinhalb
7e6c309de0 add game table 2026-01-12 11:26:39 +01:00
gelbeinhalb
3344575132 add team id and score
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m0s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-12 11:20:40 +01:00
gelbeinhalb
9b66e58dc0 add team table 2026-01-12 11:17:13 +01:00
gelbeinhalb
56562b22bb add description to player 2026-01-12 11:16:02 +01:00
4bbbcdd93f Updated label
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m11s
2026-01-12 00:47:43 +01:00
fed5c55dd4 Updated placeholder
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m7s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-12 00:18:51 +01:00
c157644b44 Folder fix 2/2
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-11 20:00:51 +01:00
5a5898787f Folder fix 1/2 2026-01-11 20:00:38 +01:00
9d3a45c01d Updated PR Template
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-11 19:57:02 +01:00
485ac87fdb Added new yaml issue templates
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m14s
2026-01-11 19:41:45 +01:00
1ebcfc9e57 implement animation
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-11 17:21:05 +01:00
758f1e6c3a .gitea/PULL_REQUEST_TEMPLATE.md aktualisiert 2026-01-11 16:14:43 +00:00
22ce742d43 change button alignment & remove InkWell Animation
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m8s
Pull Request Pipeline / lint (pull_request) Successful in 2m10s
2026-01-11 17:14:28 +01:00
7fc4bbfb13 Added placeholder setting tiles for legal
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m13s
Pull Request Pipeline / lint (pull_request) Successful in 2m14s
2026-01-11 17:09:05 +01:00
857e05127d Updated arb files 2026-01-11 16:55:28 +01:00
86982ada0f Updated license file
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-11 16:48:08 +01:00
e51bf3eabb Updated spacing 2026-01-11 16:48:02 +01:00
d7f08c5f50 Updated license tile and adjusted settings tile accordingly
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m37s
Pull Request Pipeline / test (pull_request) Successful in 2m36s
2026-01-11 16:33:56 +01:00
9248284292 Removed double patterns
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m13s
Pull Request Pipeline / lint (pull_request) Successful in 2m22s
2026-01-11 16:32:19 +01:00
9a00e543d7 Implemented adaptive mail icon 2026-01-11 16:00:19 +01:00
5ea7797b3e Moved files 2026-01-11 15:44:05 +01:00
c8b76ae0ea Updated l10n config 2026-01-11 15:43:46 +01:00
c5fa540c5f Added licenses to settings 2026-01-11 15:43:36 +01:00
3ceae8341b add const
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m30s
Pull Request Pipeline / lint (pull_request) Successful in 2m31s
2026-01-11 15:26:50 +01:00
76ce3af643 implement custom alert dialog
Some checks failed
Pull Request Pipeline / lint (pull_request) Failing after 2m34s
Pull Request Pipeline / test (pull_request) Successful in 2m33s
2026-01-11 15:26:10 +01:00
ab20bd764b implement draft blur navbar
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m0s
Pull Request Pipeline / lint (pull_request) Failing after 2m6s
2026-01-11 11:30:00 +01:00
8ca4e3210e remove button in match view for testing 2026-01-11 11:28:21 +01:00
e384230a0b Updated gradle version 2026-01-10 23:37:54 +01:00
1e4fd2a164 Added ios permissions for web 2026-01-10 23:37:47 +01:00
a491427a1d Added license tile, social media icons & copyright 2026-01-10 23:37:33 +01:00
caf60d046b fix merge mistake
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 3m9s
Pull Request Pipeline / test (pull_request) Successful in 2m30s
2026-01-10 22:20:14 +01:00
38663c6b67 Merge remote-tracking branch 'origin/development' into feature/118-bearbeiten-und-löschen-von-gruppen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m33s
Pull Request Pipeline / lint (pull_request) Successful in 2m44s
# Conflicts:
#	lib/l10n/arb/app_de.arb
#	lib/l10n/arb/app_en.arb
#	lib/l10n/generated/app_localizations_de.dart
#	lib/presentation/views/main_menu/settings_view.dart
2026-01-10 22:19:19 +01:00
a480530919 Merge branch 'development' into enhancement/138-neues-navbar-design
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m31s
Pull Request Pipeline / lint (pull_request) Successful in 2m34s
# Conflicts:
#	pubspec.yaml
2026-01-10 22:18:54 +01:00
ee84c60ba6 remove questionmark
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m5s
2026-01-10 22:13:26 +01:00
b6dd0541ae rename CreateGroupView to GroupDetailView for clarity and consistency
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m4s
2026-01-10 22:11:28 +01:00
906c8d8450 Merge pull request 'Versions- und Build Nr in Einstellungen' (#149) from enhancement/146-versions-und-build-nr-in-einstellungen into development
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 1m58s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
Reviewed-on: #149
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-10 20:56:25 +00:00
000bdc8cbc Merge remote-tracking branch 'origin/development' into enhancement/146-versions-und-build-nr-in-einstellungen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m6s
2026-01-10 21:54:09 +01:00
525acec1d3 Merge branch 'development' into feature/118-bearbeiten-und-löschen-von-gruppen
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Failing after 2m3s
2026-01-10 20:48:25 +00:00
497f30421d Updated string
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m9s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-10 21:29:45 +01:00
adedb85eb2 Merge pull request 'Gruppen nach Spielern durchsuchen' (#147) from enhancement/136-gruppen-nach-spielern-durchsuchen into development
Reviewed-on: #147
Reviewed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
2026-01-10 20:27:53 +00:00
2a72332bcd Updated error string
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m9s
2026-01-10 21:23:28 +01:00
45a419cae7 implement group edit view
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Failing after 2m3s
2026-01-10 20:14:37 +01:00
7aa41abe61 Implemented version number 2026-01-10 16:20:21 +01:00
e1263d51ad Merge branch 'development' into enhancement/136-gruppen-nach-spielern-durchsuchen
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m0s
Pull Request Pipeline / lint (pull_request) Successful in 2m3s
2026-01-10 15:06:17 +00:00
8791b5296e Merge pull request 'MatchSummaryTile durch MatchTile ersetzen' (#142) from enhancement/137-matchsummarytile-durch-matchtile-ersetzen into development
Reviewed-on: #142
Reviewed-by: Mathis Kirchner <mathis.kirchner.mk@gmail.com>
2026-01-10 15:05:42 +00:00
f2a4327166 Implemented adaptive page route
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m6s
2026-01-10 15:55:19 +01:00
d34990ed50 Removed print 2026-01-10 15:54:41 +01:00
2ef671884d New method for specific winner refreshing 2026-01-10 15:54:11 +01:00
2ef8eb6534 Made winner field non final 2026-01-10 15:53:31 +01:00
6f0e5ba5c2 add ability to search for groups members in choose_group_view.dart
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m6s
2026-01-10 15:19:18 +01:00
1c07346aaf Updated version
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m20s
Pull Request Pipeline / lint (pull_request) Successful in 2m28s
2026-01-10 15:16:09 +01:00
830a64b5dd Small changes
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m29s
Pull Request Pipeline / lint (pull_request) Successful in 2m32s
2026-01-10 15:15:52 +01:00
9221f64fa5 Merge branch 'development' into enhancement/137-matchsummarytile-durch-matchtile-ersetzen
# Conflicts:
#	lib/presentation/views/main_menu/match_view/match_view.dart
#	pubspec.yaml
2026-01-10 15:15:14 +01:00
c4f6749882 Fixed state issue in home view
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m3s
2026-01-10 15:13:56 +01:00
14a043785e Merge pull request 'PageRoutes adaptable machen' (#145) from enhancement/128-PageRoutes-adaptable-machen into development
Reviewed-on: #145
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
Reviewed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
2026-01-10 14:06:10 +00:00
9eb9c0eb7f remove unneccessary import
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m18s
Pull Request Pipeline / lint (pull_request) Successful in 2m18s
2026-01-10 15:02:01 +01:00
54ec865f04 fix merge issues
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m14s
Pull Request Pipeline / lint (pull_request) Failing after 2m23s
2026-01-10 15:00:33 +01:00
d5e7a17127 Merge remote-tracking branch 'origin/development' into enhancement/128-PageRoutes-adaptable-machen
# Conflicts:
#	lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart
2026-01-10 14:57:33 +01:00
275f64b296 Merge pull request 'SnackBar Sichtbarkeit' (#144) from bug/130-Snackbar-Sichtbarkeit into development
Reviewed-on: #144
Reviewed-by: gelbeinhalb <spam@yannick-weigert.de>
Reviewed-by: Felix Kirchner <felix.kirchner.fk@gmail.com>
2026-01-10 13:54:57 +00:00
97ca62b083 refactor: rename AdaptivePageRoute to adaptivePageRoute for lowerCamelCase
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m13s
Pull Request Pipeline / test (pull_request) Successful in 2m18s
2026-01-10 14:52:59 +01:00
32fb1550ff Merge remote-tracking branch 'origin/enhancement/128-PageRoutes-adaptable-machen' into enhancement/128-PageRoutes-adaptable-machen
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Failing after 2m10s
# Conflicts:
#	lib/main.dart
2026-01-10 14:44:53 +01:00
d67972624e replaced ternary operator solution with custom adaptive_page_route.dart 2026-01-10 14:44:33 +01:00
595cf6ead0 Changed skeleton data from 3 to 2 tiles
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m2s
Pull Request Pipeline / lint (pull_request) Successful in 2m4s
2026-01-10 14:20:09 +01:00
6faafe9fab Changed android page transition to Android U transition
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m5s
Pull Request Pipeline / lint (pull_request) Successful in 2m8s
2026-01-10 14:16:16 +01:00
66b90aac25 Fixed issue with android page transition
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m5s
2026-01-10 14:09:08 +01:00
d22855fc1a Fixed match view tile width
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m6s
Pull Request Pipeline / lint (pull_request) Successful in 2m6s
2026-01-10 13:57:54 +01:00
1be86bc3c5 Added theme box design 2026-01-10 13:57:46 +01:00
db3e8215fa Added ios swipe back gesture
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m6s
2026-01-10 13:42:09 +01:00
2c4cef76d8 Reimplemented info tile & match tile into it
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m3s
2026-01-09 23:55:29 +01:00
a4ef9705f9 made PageRoutes adapt to os, default to MaterialPageRoute
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m4s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-09 22:22:26 +01:00
799c849570 wrap every view that uses a snackbar in ScaffoldMessenger
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m6s
2026-01-09 21:55:58 +01:00
799b7d8403 Implemented new nav bar with selected animation
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m3s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-09 21:12:09 +01:00
644728a9df Removed unneccesary code
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m4s
2026-01-09 20:19:23 +01:00
afb7a5f1d4 MatchTiles only show when recent games are available 2026-01-09 20:15:50 +01:00
3d510d5b3d Implemented compact mode for match tiles 2026-01-09 20:04:10 +01:00
a9d2325eee Implemented match tile in home view 2026-01-09 19:50:51 +01:00
349ff948de Modified match tile 2026-01-09 19:50:44 +01:00
0f79495775 Implemented badges
All checks were successful
Pull Request Pipeline / lint (pull_request) Successful in 2m25s
Pull Request Pipeline / test (pull_request) Successful in 2m27s
2025-12-06 15:42:02 +01:00
192 changed files with 59750 additions and 4931 deletions

View File

@@ -1,35 +0,0 @@
---
name: Bug report
about: Erstelle eine Meldung für etwas, das nicht Funktioniert, wie es soll.
title: ''
labels: 'Task/Bug'
assignees: ''
---
# Bug Report
## Beschreibung
[Eine klare und prägnante Beschreibung des Bugs]
## Schritte zur Reproduktion
1. Schritt 1
2. Schritt 2
3. ...
## Erwartetes Verhalten
[Was hätte passieren sollen]
## Tatsächliches Verhalten
[Was tatsächlich passiert ist]
## Screenshots/Protokolle
[Falls zutreffend, füge Screenshots, Error Logs oder Stack Traces hinzu]
## Umgebung
- Plattform: Android, iOS, Web
- OS: [z. B. iOS 18.5, Android 14]
- Flutter Version: [z.B. 3.35.6]
## Verwandte Issues
[Verweisen Sie auf ähnliche Issues oder PRs]

View File

@@ -1,22 +0,0 @@
---
name: Enhancement
about: Enhancements for current features
title: ''
labels: 'Task\Enhancement'
assignees: ''
---
# Enhancement
## Aktuelles Verhalten
[Beschreibe die bestehende Funktionalität]
## Einschränkungen/Probleme
[Was sind die aktuellen Mängel?]
## Vorgeschlagene Verbesserung
[Wie kann das Problem bzw. die Einschränkung verbessert werden?]
## Zugehörige Issues
[Links zu verwandten oder blockierenden Issues]

View File

@@ -1,19 +0,0 @@
---
name: Feature
about: Neues Feature für die App
title: ''
labels: 'Task\Feature'
assignees: ''
---
# Feature
## Beschreibung
[Ausführliche Erläuterung der vorgeschlagenen Funktion]
## Vorgeschlagene Lösung
[Beschreibe, wie die Feature funktionieren soll]
## Zugehörige Issues
[Links zu verwandten oder blockierenden Issues]

View File

@@ -1,16 +0,0 @@
# [PR Titel]
**Zugehörige Issue(s):**
Closes `<issue-no>`
## Beschreibung
*Eine klare und prägnante Übersicht über die vorgenommenen Änderungen. Erläutere nicht nur das was gemacht wurde, sondern auch warum.*
## Änderungen
- [ ] Neue Funktion X hinzugefügt
- [ ] Bug in Komponente Y behoben
- [ ] Modul Z für bessere Leistung refactored
- [ ] Dependencies aktualisiert
## Zusätzliche Anmerkungen
*Gibt es zusätzlichen Kontext, Einschränkungen oder Informationen, die Reviewer wissen sollten?*

View File

@@ -0,0 +1,53 @@
name: Bug Report
about: Erstelle eine Bug Report
labels: 'Task/Bug'
title: ''
body:
- type: textarea
id: description
attributes:
label: Beschreibung
description: Beschreibe klar und pregnant das Fehlerverhalten
placeholder: |
- Was genau ist das unerwünschte Verhalten?
- Welche Auswirkungen hat der Fehler?
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: Schritte zur Reproduktion
description: Beschreibe, wie der Fehler reproduziert werden kann
placeholder: |
- 1. Schritt 1
- 2. Schritt 2
- 3. ...
- type: dropdown
id: enviroment
attributes:
label: Umgebung
description: Gebe an, auf welchen Platformen dieser Fehler auftritt
list: false
multiple: true
options: ['Android', 'iOS']
- type: textarea
id: solution
attributes:
label: Lösungsidee
description: Beschreibe, wie das Problem bzw. gelöst werden kann
placeholder: |
- Button X ändern, sodass ...
- Funktion X so erweitern, dass ...
- Design anpassen, sodass ...
- type: textarea
attributes:
label: Verwandte Issues
description: Verweise auf ähnliche Issues oder PRs
placeholder: |
- Knüpft an Issue #35 an
- Ersetzt Issue #12
- Brauch Implementierung von #43

View File

@@ -0,0 +1,36 @@
name: Enhancement
about: Erstelle ein Enhancement-Ticket
labels: 'Task/Enhancement'
title: ''
body:
- type: textarea
id: description
attributes:
label: Aktuelles Verhalten
description: Beschreibe, wie die Funktionalität aktuell gestaltet ist
placeholder: |
- Aktuell macht Button X folgendes ...
- Das Problem ist, dass ...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Vorgeschlagene Verbesserung
description: Beschreibe, wie das Problem bzw. die Einschränkung verbessert werden kann
placeholder: |
- Button X ändern, sodass ...
- Funktion X so erweitern, dass ...
- Design anpassen, sodass ...
validations:
required: true
- type: textarea
attributes:
label: Zugehörige Issues
description: Links zu verwandten oder blockierenden Issues
placeholder: |
- Knüpft an Issue #35 an
- Ersetzt Issue #12
- Brauch Implementierung von #43

View File

@@ -0,0 +1,36 @@
name: Feature
about: Erstelle ein Feature-Ticket
labels: 'Task/Feature'
title: ''
body:
- type: textarea
id: description
attributes:
label: Beschreibung
description: Ausführliche Erläuterung der vorgeschlagenen Funktion
placeholder: |
- Welchen Zweck erfüllt das Feature?
- Welches Problem löst das Feature?
- Wer profitiert davon?
- Warum ist es wichtig?
validations:
required: true
- type: textarea
id: solution
attributes:
label: Vorgeschlagene Lösung
description: Beschreibe, wie das Feature funktionieren soll
placeholder: |
- Neues Widget, das folgendermaßen aussieht ...
- Neue Ansicht, die folgende Inhalte hat
- Neue Funktionsweise von Komponente XY
- type: textarea
attributes:
label: Zugehörige Issues
description: Links zu verwandten oder blockierenden Issues
placeholder: |
- Knüpft an Issue #35 an
- Ersetzt Issue #12
- Brauch Implementierung von #43

View File

@@ -0,0 +1,64 @@
name: Pull Request
about: Vorlage für Pull Requests
title: "WIP: [Name des Issues]"
body:
- type: input
id: related_issue
attributes:
label: Zugehörige Issue(s)
description: Issues welche mit diesem Pull Request geschlossen werden sollen
placeholder: "Closes #123"
validations:
required: true
- type: textarea
id: description
attributes:
label: Beschreibung
description: |
Eine klare und prägnante Zusammenfassung aller vorgenommenen Änderungen.
placeholder: |
Was wurde geändert?
validations:
required: true
- type: textarea
id: changes
attributes:
label: Änderungen
description: Liste alle Änderungen detailiert auf, die in diesem Pull Request vorgenommen wurden.
placeholder: |
- Neue Funktion X hinzugefügt
- Bug in Komponente X behoben
- Modul X für bessere Leistung refactored
- Dependencies aktualisiert
- type: checkboxes
id: checklist
attributes:
label: PR-Checkliste
description: Stelle sicher, dass alle Punkte erfüllt sind, bevor du den Pull Request zum Review freigibst.
options:
- label: Ich habe für Navigationen den AdaptiveNavigator` verwendet
required: false
- label: Ich habe alle Strings lokalisiert (de/en)
required: false
- label: Ich habe die Testdaten aktualisiert oder erweitert
required: false
- label: Ich habe das JSON-Schema angepasst
required: false
- label: Ich habe Tests für neue Datenbank/DAO-Funktionen hinzugefügt
required: false
- type: textarea
id: additional_notes
attributes:
label: Zusätzliche Anmerkungen
description: |
Gibt es zusätzlichen Kontext, Einschränkungen oder Informationen,
die Reviewer wissen sollten?
placeholder: |
- Bekannte Einschränkungen
- Offene TODOs
- Hinweise für Reviewer

View File

@@ -10,22 +10,21 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
# Required for Flutter action
- name: Install jq - name: Install jq
run: | run: |
apt-get update apt-get update
apt-get install -y jq apt-get install -y jq
- name: Install Flutter (wget) - name: Set up Flutter
run: | uses: subosito/flutter-action@v2
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz with:
tar xf flutter_linux_3.38.2-stable.tar.xz channel: stable
# Set Git safe directory for Flutter path
git config --global --add safe.directory "$(pwd)/flutter"
# Set Flutter path
echo "$(pwd)/flutter/bin" >> $GITHUB_PATH
- name: Get dependencies - name: Get dependencies
run: flutter pub get run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Analyze Formatting - name: Analyze Formatting
run: flutter analyze lib test run: flutter analyze lib test
@@ -36,22 +35,62 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install dependencies # Required for Flutter action
- name: Install jq
run: | run: |
apt-get update apt-get update
apt-get install -y jq apt-get install -y jq
- name: Install Flutter (wget) - name: Set up Flutter
run: | uses: subosito/flutter-action@v2
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz with:
tar xf flutter_linux_3.38.2-stable.tar.xz channel: stable
# Set Git safe directory for Flutter path
git config --global --add safe.directory "$(pwd)/flutter"
# Set Flutter path
echo "$(pwd)/flutter/bin" >> $GITHUB_PATH
- name: Get dependencies - name: Get dependencies
run: flutter pub get run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Run tests - name: Run tests
run: flutter test run: flutter test
localizations:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# Required for Flutter action
- name: Install jq
run: |
apt-get update
apt-get install -y jq
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
- name: Get dependencies
run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Check for untranslated messages
run: |
flutter gen-l10n --no-use-deferred-loading
UNTRANSLATED_FILE=lib/l10n/untranslated_messages.json
if [ ! -f "$UNTRANSLATED_FILE" ]; then
echo "Expected $UNTRANSLATED_FILE to be generated, but it does not exist."
exit 1
fi
CONTENT=$(tr -d '[:space:]' < "$UNTRANSLATED_FILE")
if [ "$CONTENT" != "{}" ]; then
echo "Found untranslated messages:"
cat "$UNTRANSLATED_FILE"
exit 1
fi
echo "All messages translated."

View File

@@ -7,44 +7,310 @@ on:
- "main" - "main"
jobs: jobs:
format: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: false # Needs bot user
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Install dependencies # Required for Flutter action
- name: Install jq
run: | run: |
apt-get update apt-get update
apt-get install -y jq apt-get install -y jq
- name: Install Flutter (wget) - name: Set up Flutter
run: | uses: subosito/flutter-action@v2
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz with:
tar xf flutter_linux_3.38.2-stable.tar.xz channel: stable
# Set Git safe directory for Flutter path
git config --global --add safe.directory "$(pwd)/flutter"
# Set Flutter path
echo "$(pwd)/flutter/bin" >> $GITHUB_PATH
- name: Get & upgrade dependencies - name: Get dependencies
run: | run: |
git config --global --add safe.directory '*'
flutter pub get flutter pub get
flutter pub upgrade --major-versions
- name: Auto-format - name: Run tests
run: flutter test
update_version:
runs-on: ubuntu-latest
if: gitea.ref == 'refs/heads/development'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
BRANCH_NAME: ${{ gitea.ref_name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.BOT_TOKEN }}
ref: ${{ gitea.ref_name }}
- name: Increment version number
uses: stikkyapp/update-pubspec-version@v2
with:
strategy: 'patch'
path: './pubspec.yaml'
- name: Commit version update
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
run: | run: |
dart format lib git config --global user.name "Gitea Actions [bot]"
git config --global user.email "actions@yannick-weigert.de"
git config pull.rebase false
git pull origin "$BRANCH_NAME"
git add pubspec.yaml
git commit -m "Updated version number [skip ci]"
git push origin HEAD:$BRANCH_NAME
generate_licenses:
runs-on: ubuntu-latest
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
BRANCH_NAME: ${{ gitea.ref_name }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.BOT_TOKEN }}
ref: ${{ gitea.ref_name }}
# Required for Flutter action
- name: Install jq
run: |
apt-get update
apt-get install -y jq
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
- name: Get dependencies
run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Generate oss_licenses.dart
run: flutter pub run dart_pubspec_licenses:generate -o lib/presentation/views/main_menu/settings_view/licenses/oss_licenses.dart
- name: Commit license update
run: |
if [ -n "$(git status --porcelain lib test)" ]; then
git config --global user.name "Gitea Actions [bot]"
git config --global user.email "actions@yannick-weigert.de"
git config pull.rebase false
git pull origin "$BRANCH_NAME"
git add lib test
git commit -m "Updated licenses [skip ci]"
git push origin HEAD:$BRANCH_NAME
else
echo "No changes to commit"
fi
generate_localizations:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# Required for Flutter action
- name: Install jq
run: |
apt-get update
apt-get install -y jq
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
- name: Get dependencies
run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Generate localizations
run: flutter gen-l10n --no-use-deferred-loading
- name: Check for changes
id: check_changes
run: |
if [ -n "$(git status --porcelain lib/l10n)" ]; then
echo "has_changes=true" >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
- name: Commit generated localizations
if: steps.check_changes.outputs.has_changes == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
BRANCH_NAME: ${{ gitea.ref_name }}
run: |
git fetch origin "$BRANCH_NAME"
git checkout "$BRANCH_NAME"
if [ -n "$(git status --porcelain lib test)" ]; then
git config --global user.name "Gitea Actions [bot]"
git config --global user.email "actions@yannick-weigert.de"
git config pull.rebase false
git pull origin "$BRANCH_NAME"
git add lib/l10n
git commit -m "Generated localizations [skip ci]"
git push origin "HEAD:$BRANCH_NAME"
else
echo "No changes to commit"
fi
sort_arb_files:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
# Required for Flutter action
- name: Install jq
run: |
apt-get update
apt-get install -y jq
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
- name: Get dependencies
run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Sort .arb-Files
run: |
shopt -s nullglob
for file in lib/l10n/arb/app_*.arb; do
echo "Sorting $file"
dart run arb_utils sort "$file"
done
- name: Check for changes
id: check_changes
run: |
if [ -n "$(git status --porcelain lib/l10n/arb)" ]; then
echo "has_changes=true" >> "$GITHUB_OUTPUT"
else
echo "has_changes=false" >> "$GITHUB_OUTPUT"
fi
- name: Commit sorted .arb-Files
if: steps.check_changes.outputs.has_changes == 'true'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
BRANCH_NAME: ${{ gitea.ref_name }}
run: |
git fetch origin "$BRANCH_NAME"
git checkout "$BRANCH_NAME"
if [ -n "$(git status --porcelain lib/l10n/arb)" ]; then
git config --global user.name "Gitea Actions [bot]"
git config --global user.email "actions@yannick-weigert.de"
git config pull.rebase false
git pull origin "$BRANCH_NAME"
git add lib/l10n/arb
git commit -m "Sort .arb files [skip ci]"
git push origin "HEAD:$BRANCH_NAME"
else
echo "No changes to commit"
fi
format:
runs-on: ubuntu-latest
needs: [update_version, generate_licenses, generate_localizations, sort_arb_files]
steps:
- name: Checkout code
uses: actions/checkout@v4
# Required for Flutter action
- name: Install jq
run: |
apt-get update
apt-get install -y jq
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
- name: Get dependencies
run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Check code format
id: check_format
continue-on-error: true
run: flutter analyze lib test
- name: Format code
if: steps.check_format.outcome == 'failure'
env:
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
BRANCH_NAME: ${{ gitea.ref_name }}
run: |
git fetch origin "$BRANCH_NAME"
git checkout "$BRANCH_NAME"
dart fix --apply lib dart fix --apply lib
dart fix --apply test
# Needs credentials, push access and the right files need to be staged if [ -n "$(git status --porcelain lib test)" ]; then
- name: Commit Changes git config --global user.name "Gitea Actions [bot]"
git config --global user.email "actions@yannick-weigert.de"
git config pull.rebase false
git pull origin "$BRANCH_NAME"
git add lib test
git commit -m "Auto-format code [skip ci]"
git push origin HEAD:$BRANCH_NAME
else
echo "No changes to commit"
fi
- name: Verify format
run: flutter analyze lib test
build:
needs: format
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Java (Temurin 17)
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
# Required for Flutter action
- name: Install jq
run: | run: |
git config --global user.name "Gitea Actions" apt-get update
git config --global user.email "actions@gitea.com" apt-get install -y jq
git status
git add lib/ - name: Set up Flutter
git status uses: subosito/flutter-action@v2
git commit -m "Actions: Auto-formatting [skip ci]" with:
git push channel: stable
- name: Get dependencies
run: |
git config --global --add safe.directory '*'
flutter pub get
- name: Build APK
run: flutter build apk --release

View File

@@ -0,0 +1,35 @@
name: Renovate
on:
schedule:
- cron: '0 12 * * 0'
push:
branches:
- setup/222-actions-&-pr-template-verbessern
jobs:
renovate:
runs-on: ubuntu-latest
container:
image: node:20-bookworm
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Upgrade git
run: |
apt-get update
apt-get install -y git
git --version
- name: Run Renovate
env:
RENOVATE_TOKEN: ${{ secrets.BOT_TOKEN }}
RENOVATE_PLATFORM: gitea
RENOVATE_ENDPOINT: https://git.yannick-weigert.de
RENOVATE_REPOSITORIES: liquid-development/game-tracker
RENOVATE_GIT_AUTHOR: "Gitea Actions <actions@yannick-weigert.de>"
RENOVATE_CONFIG_FILE: renovate.json
LOG_LEVEL: info
run: |
npm install -g renovate
renovate

29
.gitignore vendored
View File

@@ -3,7 +3,6 @@
# Miscellaneous # Miscellaneous
*.class *.class
*.lock
*.log *.log
*.pyc *.pyc
*.swp *.swp
@@ -79,6 +78,7 @@ unlinked_spec.ds
local.properties local.properties
# iOS/XCode related # iOS/XCode related
Podfile.lock
**/ios/**/*.mode1v3 **/ios/**/*.mode1v3
**/ios/**/*.mode2v3 **/ios/**/*.mode2v3
**/ios/**/*.moved-aside **/ios/**/*.moved-aside
@@ -150,25 +150,9 @@ app.*.symbols
.gclient_previous_custom_vars .gclient_previous_custom_vars
.gclient_previous_sync_commits .gclient_previous_sync_commits
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.build/
.buildlog/
.history
.svn/
.swiftpm/ .swiftpm/
migrate_working_dir/ migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in # The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line # VS Code which you may wish to be included in version control, so this line
@@ -176,17 +160,8 @@ migrate_working_dir/
#.vscode/ #.vscode/
# Flutter/Dart/Pub related # Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.pub-cache/
.pub/
/build/ /build/
# Symbolication related
app.*.symbols
# Obfuscation related # Obfuscation related
app.*.map.json app.*.map.json
@@ -196,3 +171,5 @@ app.*.map.json
/android/app/profile /android/app/profile
/android/app/release /android/app/release
/devtools_options.yaml /devtools_options.yaml
untranslated_messages.json

13
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,13 @@
# Contributing
## Code of Conduct
`<insert link to code of conduct here>`
## Code Style
`<insert styling guidelines here>`
## Repository structure
`<insert folder structure and explanation here>`

165
LICENSE Normal file
View File

@@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@@ -1,7 +1,63 @@
# Game Tracker <p align="center">
<img alt="Tallee Logo" src="/artefacts/app-logo.png" width="200"/>
<h2 align="center">Tallee</h2>
</p>
<p align="center">
An open-source app to track card- and board games, manage players & groups and get statistics about your played games.
</p>
<p align="center">
<a href="https://apps.apple.com/">
<img src="https://tools.applemediaservices.com/api/badges/download-on-the-app-store/black/en-US"
alt="Download on the App Store"
height="48"
/>
</a>
<a href="https://play.google.com/">
<img alt="Get it on Google Play"
title="Google Play"
src="https://raw.githubusercontent.com/pd4d10/git-touch/main/assets/google-play-badge.png"
height="48"
/>
</a>
</p>
![Version](https://img.shields.io/badge/App--Version-0.0.1_Alpha-orange)
![Flutter](https://img.shields.io/badge/Flutter-3.38.6-027DFD?logo=flutter)
![iOS26](https://img.shields.io/badge/iOS-26-white?logo=apple)
![Android16](https://img.shields.io/badge/Android-16-3DDC84?logo=android)
## Screenshots
<table align="center" cellspacing="8">
<tr>
<td><img src="/artefacts/screenshot-1.png" alt="Screenshot 1" width="240" /></td>
<td><img src="/artefacts/screenshot-2.png" alt="Screenshot 2" width="240" /></td>
<td><img src="/artefacts/screenshot-3.png" alt="Screenshot 3" width="240" /></td>
<td><img src="/artefacts/screenshot-4.png" alt="Screenshot 4" width="240" /></td>
</tr>
</table>
## Contributing
Contributions are welcome! If you find a bug or have a feature request, please open an issue on GitHub. If you'd like to
contribute code, feel free to fork the repository and submit a pull request. For contribution guidelines, please refer
to [CONTRIBUTING.md](CONTRIBUTING.md).
## License
This project is licensed under the GNU LGPLv3 License. See the [LICENSE](LICENSE) file for details.
## Contributors
<a href="https://github.com/liquiddevelopmentde/game-tracker/graphs/contributors">
<img src="https://contrib.rocks/image?repo=liquiddevelopmentde/game-tracker" />
</a>
## Credits
Tallee is developed and maintained by [Liquid Development](https://liquid-dev.de). For more information or support regarding Tallee, contact us through our website or [hello@liquid-dev.de](mailto:hello@liquid-dev.de).
![Created by Liquid Development](https://img.shields.io/badge/Created_by-Liquid_Development-027DFD?logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iRWJlbmVfMSIgZGF0YS1uYW1lPSJFYmVuZSAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3MjUuNDggODk3LjMiPgogIDxkZWZzPgogICAgPHN0eWxlPgogICAgICAuY2xzLTEgewogICAgICAgIGZpbGw6ICNmZmY7CiAgICAgIH0KICAgIDwvc3R5bGU+CiAgPC9kZWZzPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTcwNS4yNiw3MDEuOTJsNi40LDExLjA4Yy0xLjk1LTMuODEtNC4wOS03LjUxLTYuNC0xMS4wOFoiLz4KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik02MDIuMzksODk3LjI1aC03LjIxYzEuMi4wMywyLjQuMDUsMy42MS4wNXMyLjQxLS4wMiwzLjYxLS4wNVoiLz4KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0wLDY5NS4zOGwyLjY4LTQuNjRjLS45MywxLjUyLTEuODIsMy4wNy0yLjY4LDQuNjRaIi8+CiAgPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNjgyLjU1LDcyMy40NWw2LjA1LDEwLjQ5Yy0xLjc5LTMuNjQtMy44MS03LjE1LTYuMDUtMTAuNDlaIi8+CiAgPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMzcuNzIsNzMzLjI4bDUuMy05LjE4Yy0xLjk0LDIuOTQtMy43MSw2LjAxLTUuMyw5LjE4WiIvPgogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTcxMS42Niw3MTMuMDFsLTYuNC0xMS4wOC0yMjAuNDYtMzgxLjg0aDBWMTAxLjg0YzIwLjY3LTYuOTgsMzUuNTYtMjYuNTIsMzUuNTYtNDkuNTQsMC0yOC44OC0yMy40MS01Mi4zLTUyLjMtNTIuM2gtMjA5LjQ4Yy0yOC44OCwwLTUyLjMsMjMuNDEtNTIuMyw1Mi4zLDAsMjIuNzEsMTQuNDgsNDIuMDMsMzQuNyw0OS4yNXYyMTguNTRsLS4zMy41OEwxOC44OSw3MDQuNzlsLTIuNjgsNC42NGMtOS45OSwxOC4xMi0xNS42OCwzOC45Ni0xNS42OCw2MS4xMiwwLDY5Ljk3LDU2LjY0LDEyNi43LDEyNi41MSwxMjYuN2g0NzUuMzVjNjguMy0xLjkxLDEyMy4wOS01Ny44OCwxMjMuMDktMTI2LjY0LDAtMjAuNzQtNC45OS00MC4zMi0xMy44Mi01Ny42Wk02MDguNTYsODYyLjUzSDExNy40M2MtNDkuMzcsMC04OS4zOS00MC4wMi04OS4zOS04OS4zOSwwLTE0LjM2LDMuMzktMjcuOTMsOS40MS0zOS45Nmw1LjMtOS4xOCwyMzMuMi00MDMuOTJoLS4wOFYxMDQuNTloMTcuODFjOS40NywwLDE3LjE1LTcuNjgsMTcuMTUtMTcuMTVzLTcuNjgtMTcuMTUtMTcuMTUtMTcuMTVoLTM1LjU5di0uMDJjLTkuNzItLjI2LTE3LjUyLTguMi0xNy41Mi0xNy45OHM3LjgtMTcuNzIsMTcuNTItMTcuOTh2LS4wMmgyMDkuMjZjOS45NCwwLDE4LDguMDYsMTgsMThzLTguMDYsMTgtMTgsMThoLTM0LjQ4Yy05LjQ3LDAtMTcuMTUsNy42OC0xNy4xNSwxNy4xNXM3LjY4LDE3LjE1LDE3LjE1LDE3LjE1aDE3LjA0djIxNS40OWguMDdsMjMyLjgyLDQwMy4yNiw2LjA2LDEwLjVjNS44MiwxMS44Niw5LjA5LDI1LjIsOS4wOSwzOS4zLDAsNDkuMzctNDAuMDIsODkuMzktODkuMzksODkuMzlaIi8+CiAgPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMzgxLjY4LDU0NS4zOGMtMy4wOCwxLjY4LTYuMTgsMy4zLTkuMzIsNC44NiwzLjA3LTEuNjcsNi4xOC0zLjI5LDkuMzItNC44NloiLz4KICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01ODMuNDIsNTUxLjE5bC0yMC42Ny0zNS44Yy0xMy42OS0xLjg0LTI3LjY3LTIuNzktNDEuODYtMi43OS0xNy45OSwwLTM1LjYyLDEuNTMtNTIuNzgsNC40Ni0zMC41Niw1LjIxLTU5LjYsMTQuODktODYuNDIsMjguMzMtMy4wOCwxLjY4LTYuMTgsMy4zLTkuMzIsNC44Ni00MS44OCwyMC45OS04OS4xNiwzMi43OS0xMzkuMTksMzIuNzktMzQuODUsMC02OC4zNS01Ljc0LTk5LjYzLTE2LjMxLDAsMCwwLC4wMiwwLC4wMmwtMTYuNTIsMjguNjFjMzcuMDEsMTUuNTMsNzcuNjUsMjQuMTIsMTIwLjMsMjQuMTIsMTcuOTgsMCwzNS42MS0xLjUzLDUyLjc2LTQuNDYsMzIuNzctNS41OSw2My43OC0xNi4zMSw5Mi4yLTMxLjI5Ljg3LS40NiwxLjczLS45MiwyLjYtMS40LDQzLjI5LTIyLjgyLDkyLjYyLTM1Ljc0LDE0NC45Ni0zNS43NCwxOC4yOCwwLDM2LjE4LDEuNTksNTMuNTksNC42MWwtLjAyLS4wMloiLz4KICA8Zz4KICAgIDxjaXJjbGUgY2xhc3M9ImNscy0xIiBjeD0iNTg3LjY0IiBjeT0iODAzLjQiIHI9IjE4Ljk2Ii8+CiAgICA8cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik01MTUuNTIsNzg0LjQzSDEwMy41NWMtMTAuOTIsMC0xOS43Niw4LjQ5LTE5Ljc2LDE4Ljk2czguODUsMTguOTYsMTkuNzYsMTguOTZoNDExLjk3YzEwLjkyLDAsMTkuNzYtOC40OSwxOS43Ni0xOC45NnMtOC44NS0xOC45Ni0xOS43Ni0xOC45NloiLz4KICA8L2c+CiAgPGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIyODMuMzIiIGN5PSI0NjcuNTkiIHI9IjE4Ljk2Ii8+CiAgPGNpcmNsZSBjbGFzcz0iY2xzLTEiIGN4PSIzMjYuMjMiIGN5PSIzNjYuMjUiIHI9IjE4Ljk2Ii8+CiAgPHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDA2LjU2LDM4NS4yMmMtMjQuMDYsMC00My41NiwxOS41LTQzLjU2LDQzLjU2czE5LjUsNDMuNTYsNDMuNTYsNDMuNTYsNDMuNTYtMTkuNSw0My41Ni00My41Ni0xOS41LTQzLjU2LTQzLjU2LTQzLjU2Wk00MDYuNTYsNDQ3Ljc0Yy0xMC40NywwLTE4Ljk2LTguNDktMTguOTYtMTguOTZzOC40OS0xOC45NiwxOC45Ni0xOC45NiwxOC45Niw4LjQ5LDE4Ljk2LDE4Ljk2LTguNDksMTguOTYtMTguOTYsMTguOTZaIi8+Cjwvc3ZnPg==)
![Version](https://img.shields.io/badge/Version-0.3.0-orange)
![Flutter](https://img.shields.io/badge/Flutter-3.32.1-blue?logo=flutter)
![Dart](https://img.shields.io/badge/Dart-3.8.1-blue?logo=dart)
A all-in-one app to track card- and board games, manage players and groups and get statistics about your played games.

View File

@@ -1,5 +1,9 @@
include: package:flutter_lints/flutter.yaml include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- lib/presentation/views/main_menu/settings_view/licenses/oss_licenses.dart
linter: linter:
rules: rules:
avoid_print: false avoid_print: false
@@ -11,3 +15,4 @@ linter:
prefer_const_literals_to_create_immutables: true prefer_const_literals_to_create_immutables: true
unnecessary_const: true unnecessary_const: true
lines_longer_than_80_chars: false lines_longer_than_80_chars: false
constant_identifier_names: false

View File

@@ -6,7 +6,7 @@ plugins {
} }
android { android {
namespace = "com.example.game_tracker" namespace = "de.liquid.tallee"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
@@ -21,7 +21,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.example.game_tracker" applicationId = "de.liquid.tallee"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion

View File

@@ -1,6 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:label="game_tracker" android:label="Tallee"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@@ -42,5 +43,14 @@
<action android:name="android.intent.action.PROCESS_TEXT"/> <action android:name="android.intent.action.PROCESS_TEXT"/>
<data android:mimeType="text/plain"/> <data android:mimeType="text/plain"/>
</intent> </intent>
<!-- Required for url_launcher to open URLs in external browser -->
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" />
</intent>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries> </queries>
</manifest> </manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,4 +1,4 @@
package com.example.game_tracker package de.liquid.tallee
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity

Binary file not shown.

Before

Width:  |  Height:  |  Size: 828 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 448 B

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 656 B

After

Width:  |  Height:  |  Size: 938 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 596 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 508 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 824 B

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<color name="app_icon_background">#E6F1E4</color> <color name="launch_background">#ef681f</color>
<color name="launch_background">#0B0B0B</color>
</resources> </resources>

View File

@@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- Referenz unbedingt als @color/launch_background (nicht @colors/...) --> <color name="ic_launcher_background">#EF681F</color>
<color name="ic_launcher_background">@color/app_icon_background</color>
</resources> </resources>

View File

@@ -18,7 +18,7 @@ pluginManagement {
plugins { plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.3" apply false id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false id("org.jetbrains.kotlin.android") version "2.1.0" apply false
} }

BIN
artefacts/app-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
artefacts/screenshot-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

BIN
artefacts/screenshot-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

BIN
artefacts/screenshot-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

BIN
artefacts/screenshot-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

View File

@@ -15,12 +15,56 @@
}, },
"name": { "name": {
"type": "string" "type": "string"
},
"description": {
"type": "string"
} }
}, },
"additionalProperties": false,
"required": [ "required": [
"id", "id",
"createdAt", "createdAt",
"name" "name",
"description"
]
}
},
"games": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"name": {
"type": "string"
},
"ruleset": {
"type": "string"
},
"description": {
"type": "string"
},
"color": {
"type": "string"
},
"icon": {
"type": "string"
}
},
"additionalProperties": false,
"required": [
"id",
"createdAt",
"name",
"ruleset",
"description",
"color",
"icon"
] ]
} }
}, },
@@ -38,6 +82,9 @@
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
"description": {
"type": "string"
},
"memberIds": { "memberIds": {
"type": "array", "type": "array",
"items": { "items": {
@@ -45,10 +92,12 @@
} }
} }
}, },
"additionalProperties": false,
"required": [ "required": [
"id", "id",
"name", "name",
"createdAt", "createdAt",
"description",
"memberIds" "memberIds"
] ]
} }
@@ -67,10 +116,19 @@
"createdAt": { "createdAt": {
"type": "string" "type": "string"
}, },
"endedAt": {
"type": [
"string",
"null"
]
},
"gameId": {
"type": "string"
},
"groupId": { "groupId": {
"anyOf": [ "type": [
{"type": "string"}, "string",
{"type": "null"} "null"
] ]
}, },
"playerIds": { "playerIds": {
@@ -79,25 +137,55 @@
"type": "string" "type": "string"
} }
}, },
"winnerId": { "scores": {
"anyOf": [ "type": "object",
{"type": "string"}, "additionalProperties": {
{"type": "null"} "oneOf": [
] {
"type": "null"
},
{
"type": "object",
"properties": {
"roundNumber": {
"type": "number"
},
"score": {
"type": "number"
},
"change": {
"type": "number"
}
},
"required": ["roundNumber", "score", "change"],
"additionalProperties": false
}
]
}
},
"notes": {
"type": "string"
},
"teams": {
"type": ["array", "null"]
} }
}, },
"additionalProperties": false,
"required": [ "required": [
"id", "id",
"name", "name",
"createdAt", "createdAt",
"groupId", "gameId",
"playerIds" "playerIds",
"notes"
] ]
} }
} }
}, },
"additionalProperties": false,
"required": [ "required": [
"players", "players",
"games",
"groups", "groups",
"matches" "matches"
] ]

View File

@@ -20,7 +20,5 @@
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key>
<string>13.0</string>
</dict> </dict>
</plist> </plist>

View File

@@ -16,6 +16,7 @@
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
DDD6907F99188C9B97C6B11F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D622CF241440C10C19C0D397 /* Pods_Runner.framework */; }; DDD6907F99188C9B97C6B11F /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D622CF241440C10C19C0D397 /* Pods_Runner.framework */; };
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -65,6 +66,7 @@
B68CF4A64F0B5E45B43D6900 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; }; B68CF4A64F0B5E45B43D6900 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
D622CF241440C10C19C0D397 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D622CF241440C10C19C0D397 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E754D1191B3E54E52B6DCC49 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; }; E754D1191B3E54E52B6DCC49 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -80,6 +82,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
DDD6907F99188C9B97C6B11F /* Pods_Runner.framework in Frameworks */, DDD6907F99188C9B97C6B11F /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@@ -98,6 +101,7 @@
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */, 9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
@@ -152,7 +156,6 @@
B68CF4A64F0B5E45B43D6900 /* Pods-RunnerTests.release.xcconfig */, B68CF4A64F0B5E45B43D6900 /* Pods-RunnerTests.release.xcconfig */,
E754D1191B3E54E52B6DCC49 /* Pods-RunnerTests.profile.xcconfig */, E754D1191B3E54E52B6DCC49 /* Pods-RunnerTests.profile.xcconfig */,
); );
name = Pods;
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -188,6 +191,9 @@
productType = "com.apple.product-type.bundle.unit-test"; productType = "com.apple.product-type.bundle.unit-test";
}; };
97C146ED1CF9000F007C117D /* Runner */ = { 97C146ED1CF9000F007C117D /* Runner */ = {
packageProductDependencies = (
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
);
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
@@ -213,6 +219,9 @@
/* Begin PBXProject section */ /* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = { 97C146E61CF9000F007C117D /* Project object */ = {
packageReferences = (
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */,
);
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
BuildIndependentTargetsInParallel = YES; BuildIndependentTargetsInParallel = YES;
@@ -478,7 +487,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.example.gameTracker; PRODUCT_BUNDLE_IDENTIFIER = de.liquid.tallee;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -661,7 +670,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.example.gameTracker; PRODUCT_BUNDLE_IDENTIFIER = de.liquid.tallee;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -684,7 +693,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.example.gameTracker; PRODUCT_BUNDLE_IDENTIFIER = de.liquid.tallee;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -726,6 +735,18 @@
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
isa = XCSwiftPackageProductDependency;
productName = FlutterGeneratedPluginSwiftPackage;
};
/* End XCSwiftPackageProductDependency section */
}; };
rootObject = 97C146E61CF9000F007C117D /* Project object */; rootObject = 97C146E61CF9000F007C117D /* Project object */;
} }

View File

@@ -0,0 +1,67 @@
{
"pins" : [
{
"identity" : "csqlite",
"kind" : "remoteSourceControl",
"location" : "https://github.com/simolus3/CSQLite.git",
"state" : {
"revision" : "1ee46d19a4f451a7aa64ffc64fc99b4748131e62"
}
},
{
"identity" : "dkcamera",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zhangao0086/DKCamera",
"state" : {
"branch" : "master",
"revision" : "5c691d11014b910aff69f960475d70e65d9dcc96"
}
},
{
"identity" : "dkimagepickercontroller",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zhangao0086/DKImagePickerController",
"state" : {
"branch" : "4.3.9",
"revision" : "0bdfeacefa308545adde07bef86e349186335915"
}
},
{
"identity" : "dkphotogallery",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zhangao0086/DKPhotoGallery",
"state" : {
"branch" : "master",
"revision" : "311c1bc7a94f1538f82773a79c84374b12a2ef3d"
}
},
{
"identity" : "sdwebimage",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SDWebImage/SDWebImage",
"state" : {
"revision" : "2de3a496eaf6df9a1312862adcfd54acd73c39c0",
"version" : "5.21.7"
}
},
{
"identity" : "swiftygif",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kirualex/SwiftyGif.git",
"state" : {
"revision" : "4430cbc148baa3907651d40562d96325426f409a",
"version" : "5.4.5"
}
},
{
"identity" : "tocropviewcontroller",
"kind" : "remoteSourceControl",
"location" : "https://github.com/TimOliver/TOCropViewController",
"state" : {
"revision" : "d4a6d8100f4b886fdbc8ae399bf144ff3e9afb7e",
"version" : "2.8.0"
}
}
],
"version" : 2
}

View File

@@ -5,6 +5,24 @@
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"> buildImplicitDependencies = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
<ActionContent
title = "Run Prepare Flutter Framework Script"
scriptText = "/bin/sh &quot;$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh&quot; prepare&#10;">
<EnvironmentBuildable>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</EnvironmentBuildable>
</ActionContent>
</ExecutionAction>
</PreActions>
<BuildActionEntries> <BuildActionEntries>
<BuildActionEntry <BuildActionEntry
buildForTesting = "YES" buildForTesting = "YES"

View File

@@ -0,0 +1,67 @@
{
"pins" : [
{
"identity" : "csqlite",
"kind" : "remoteSourceControl",
"location" : "https://github.com/simolus3/CSQLite.git",
"state" : {
"revision" : "1ee46d19a4f451a7aa64ffc64fc99b4748131e62"
}
},
{
"identity" : "dkcamera",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zhangao0086/DKCamera",
"state" : {
"branch" : "master",
"revision" : "5c691d11014b910aff69f960475d70e65d9dcc96"
}
},
{
"identity" : "dkimagepickercontroller",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zhangao0086/DKImagePickerController",
"state" : {
"branch" : "4.3.9",
"revision" : "0bdfeacefa308545adde07bef86e349186335915"
}
},
{
"identity" : "dkphotogallery",
"kind" : "remoteSourceControl",
"location" : "https://github.com/zhangao0086/DKPhotoGallery",
"state" : {
"branch" : "master",
"revision" : "311c1bc7a94f1538f82773a79c84374b12a2ef3d"
}
},
{
"identity" : "sdwebimage",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SDWebImage/SDWebImage",
"state" : {
"revision" : "2de3a496eaf6df9a1312862adcfd54acd73c39c0",
"version" : "5.21.7"
}
},
{
"identity" : "swiftygif",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kirualex/SwiftyGif.git",
"state" : {
"revision" : "4430cbc148baa3907651d40562d96325426f409a",
"version" : "5.4.5"
}
},
{
"identity" : "tocropviewcontroller",
"kind" : "remoteSourceControl",
"location" : "https://github.com/TimOliver/TOCropViewController",
"state" : {
"revision" : "d4a6d8100f4b886fdbc8ae399bf144ff3e9afb7e",
"version" : "2.8.0"
}
}
],
"version" : 2
}

View File

@@ -2,12 +2,15 @@ import Flutter
import UIKit import UIKit
@main @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions) return super.application(application, didFinishLaunchingWithOptions: launchOptions)
} }
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -1,14 +1 @@
{ {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"}]}
"images" : [
{
"filename" : "icon_x1024.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -5,9 +5,9 @@
"color-space" : "srgb", "color-space" : "srgb",
"components" : { "components" : {
"alpha" : "1.000", "alpha" : "1.000",
"blue" : "0.043", "blue" : "0.122",
"green" : "0.043", "green" : "0.408",
"red" : "0.043" "red" : "0.937"
} }
}, },
"idiom" : "universal" "idiom" : "universal"

View File

@@ -1,17 +1,8 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "icon.png", "filename" : "icon-transparent.png",
"idiom" : "universal", "idiom" : "universal"
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
} }
], ],
"info" : { "info" : {

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24412" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="24506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_12" orientation="portrait" appearance="light"/> <device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24405"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24504"/>
<capability name="Named colors" minToolsVersion="9.0"/> <capability name="Named colors" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
@@ -20,12 +20,19 @@
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/> <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Tallee" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="m4u-iU-Cmv">
<rect key="frame" x="153" y="747" width="87" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="Futura-Bold" family="Futura" pointSize="28"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="LauncherIcon" translatesAutoresizingMaskIntoConstraints="NO" id="ygV-Op-Bu5"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="LauncherIcon" translatesAutoresizingMaskIntoConstraints="NO" id="ygV-Op-Bu5">
<rect key="frame" x="46" y="334" width="301" height="184"/> <rect key="frame" x="46" y="334" width="301" height="184"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</imageView> </imageView>
</subviews> </subviews>
<color key="backgroundColor" name="LauncherBackgroundColor"/> <color key="backgroundColor" name="LauncherColor"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
@@ -36,8 +43,8 @@
<color key="tintColor" red="0.90196078431372551" green="0.94509803921568625" blue="0.89411764705882346" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="tintColor" red="0.90196078431372551" green="0.94509803921568625" blue="0.89411764705882346" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<resources> <resources>
<image name="LauncherIcon" width="1000" height="1000"/> <image name="LauncherIcon" width="1000" height="1000"/>
<namedColor name="LauncherBackgroundColor"> <namedColor name="LauncherColor">
<color red="0.90196078431372551" green="0.94509803921568625" blue="0.89411764705882346" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.93699997663497925" green="0.40799999237060547" blue="0.12200000137090683" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor> </namedColor>
</resources> </resources>
</document> </document>

View File

@@ -2,10 +2,12 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Game Tracker</string> <string>Tallee</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string> <string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
@@ -13,7 +15,7 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>game_tracker</string> <string>tallee</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
@@ -22,8 +24,36 @@
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>https</string>
<string>http</string>
</array>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
@@ -39,9 +69,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@@ -3,3 +3,4 @@ template-arb-file: app_en.arb
output-localization-file: app_localizations.dart output-localization-file: app_localizations.dart
output-dir: lib/l10n/generated output-dir: lib/l10n/generated
nullable-getter: false nullable-getter: false
untranslated-messages-file: lib/l10n/untranslated_messages.json

View File

@@ -0,0 +1,23 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
/// Returns a platform-adaptive page route based on the current platform.
/// - On iOS, it returns a [CupertinoPageRoute].
/// - On other platforms, it returns a [MaterialPageRoute].
Route<T> adaptivePageRoute<T>({
required Widget Function(BuildContext) builder,
bool fullscreenDialog = false,
}) {
if (Platform.isIOS) {
return CupertinoPageRoute<T>(
builder: builder,
fullscreenDialog: fullscreenDialog,
);
}
return MaterialPageRoute<T>(
builder: builder,
fullscreenDialog: fullscreenDialog,
);
}

129
lib/core/common.dart Normal file
View File

@@ -0,0 +1,129 @@
import 'package:flutter/material.dart';
import 'package:fluttericon/rpg_awesome_icons.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/models/match.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/l10n/generated/app_localizations.dart';
/// Translates a [Ruleset] enum value to its corresponding localized string.
String translateRulesetToString(Ruleset ruleset, BuildContext context) {
final loc = AppLocalizations.of(context);
switch (ruleset) {
case Ruleset.highestScore:
return loc.highest_score;
case Ruleset.lowestScore:
return loc.lowest_score;
case Ruleset.singleWinner:
return loc.single_winner;
case Ruleset.singleLoser:
return loc.single_loser;
case Ruleset.multipleWinners:
return loc.multiple_winners;
case Ruleset.placement:
return loc.placement;
}
}
/// Translates a [GameColor] enum value to its corresponding localized string.
String translateGameColorToString(GameColor color, BuildContext context) {
final loc = AppLocalizations.of(context);
switch (color) {
case GameColor.red:
return loc.color_red;
case GameColor.blue:
return loc.color_blue;
case GameColor.green:
return loc.color_green;
case GameColor.yellow:
return loc.color_yellow;
case GameColor.purple:
return loc.color_purple;
case GameColor.orange:
return loc.color_orange;
case GameColor.pink:
return loc.color_pink;
case GameColor.teal:
return loc.color_teal;
}
}
/// Returns the [Color] object corresponding to a [GameColor] enum value.
Color getColorFromGameColor(GameColor color) {
switch (color) {
case GameColor.red:
return Colors.red;
case GameColor.blue:
return Colors.blue;
case GameColor.green:
return Colors.green;
case GameColor.yellow:
return const Color(0xFFF7CA28);
case GameColor.purple:
return Colors.purple;
case GameColor.orange:
return const Color(0xFFef681f);
case GameColor.pink:
return Colors.pink;
case GameColor.teal:
return Colors.teal;
}
}
/// Returns [IconData] corresponding to a [Ruleset] enum value.
IconData getRulesetIcon(Ruleset ruleset) {
switch (ruleset) {
case Ruleset.highestScore:
return Icons.arrow_upward;
case Ruleset.lowestScore:
return Icons.arrow_downward;
case Ruleset.singleWinner:
return Icons.emoji_events;
case Ruleset.singleLoser:
return Icons.sentiment_dissatisfied;
case Ruleset.multipleWinners:
return Icons.group;
case Ruleset.placement:
return RpgAwesome.podium;
}
}
/// Counts how many players in the [match] are not part of the group
///
/// Returns the text you append after the group name, e.g. " + 5" or an empty
/// string if there are no extra players
String getExtraPlayerCount(Match match) {
int count = 0;
if (match.group == null) {
return '';
}
final groupMembers = match.group!.members;
final players = match.players;
for (var player in players) {
if (!groupMembers.any((member) => member.id == player.id)) {
count++;
}
}
if (count == 0) {
return '';
}
return ' + ${count.toString()}';
}
String getNameCountText(Player player) {
if (player.nameCount >= 1) {
return ' #${player.nameCount}';
}
return '';
}
String getPointLabel(AppLocalizations loc, int points) {
if (points == 1) {
return '$points ${loc.point}';
} else {
return '$points ${loc.points}';
}
}

View File

@@ -1,6 +1,25 @@
/// Application-wide constants
class Constants { class Constants {
Constants._(); // Private constructor to prevent instantiation Constants._(); // Private constructor to prevent instantiation
/// Minimum duration of all app skeletons /// Minimum duration of all app skeletons
static Duration minimumSkeletonDuration = const Duration(milliseconds: 250); static const Duration MINIMUM_SKELETON_DURATION = Duration(milliseconds: 250);
/// Maximum length for player names
static const int MAX_PLAYER_NAME_LENGTH = 32;
/// Maximum length for group names
static const int MAX_GROUP_NAME_LENGTH = 32;
/// Maximum length for match names
static const int MAX_MATCH_NAME_LENGTH = 32;
/// Maximum length for game names
static const int MAX_GAME_NAME_LENGTH = 32;
/// Maximum length for team names
static const int MAX_TEAM_NAME_LENGTH = 32;
/// Maximum length for game descriptions
static const int MAX_GAME_DESCRIPTION_LENGTH = 256;
} }

View File

@@ -1,16 +1,45 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tallee/presentation/widgets/buttons/haptic_back_button.dart';
import 'package:tallee/presentation/widgets/buttons/haptic_close_button.dart';
/// Theme class that defines colors, border radius, padding, and decorations
class CustomTheme { class CustomTheme {
CustomTheme._(); // Private constructor to prevent instantiation CustomTheme._(); // Private constructor to prevent instantiation
// ==================== Colors ==================== // ==================== Colors ====================
static Color primaryColor = const Color(0xFF7505E4);
static Color secondaryColor = const Color(0xFFAFA2FF); /// Primary color of the app theme
static Color backgroundColor = const Color(0xFF0B0B0B); static const Color primaryColor = Color(0xFFef681f);
static Color boxColor = const Color(0xFF101010);
static Color onBoxColor = const Color(0xFF181818); /// Secondary color of the app theme
static Color boxBorder = const Color(0xFF272727); static const Color secondaryColor = Color(0xFFf2a981);
static const Color textColor = Colors.white;
/// Background color of the app theme
static const Color backgroundColor = Color(0xFF0B0B0B);
/// Default color for boxes and containers
static const Color boxColor = Color(0xFF101010);
/// Default border color for boxes and containers
static const Color boxBorderColor = Color(0xFF272727);
/// Color for boxes and containers displayed on boxes
static const Color onBoxColor = Color(0xFF181818);
/// Text color used throughout the app
static const Color textColor = Color(0xFFFFFFFF);
/// Text color used throughout the app
static const Color hintColor = Color(0xFF888888);
/// Background color for the navigation bar
static const Color navBarBackgroundColor = Color(0xFF131313);
/// Selected color for the [NavbarItem]
static Color navBarItemSelectedColor = primaryColor.withGreen(100);
/// Unselected color for the [NavbarItem]
static Color navBarItemUnselectedColor = Colors.grey.shade400;
// ==================== Border Radius ==================== // ==================== Border Radius ====================
static const double standardBorderRadius = 12.0; static const double standardBorderRadius = 12.0;
@@ -30,30 +59,53 @@ class CustomTheme {
// ==================== Decorations ==================== // ==================== Decorations ====================
static BoxDecoration standardBoxDecoration = BoxDecoration( static BoxDecoration standardBoxDecoration = BoxDecoration(
color: boxColor, color: boxColor,
border: Border.all(color: boxBorder), border: Border.all(color: boxBorderColor),
borderRadius: standardBorderRadiusAll, borderRadius: standardBorderRadiusAll,
); );
static BoxDecoration highlightedBoxDecoration = BoxDecoration( static BoxDecoration highlightedBoxDecoration = BoxDecoration(
color: boxColor, color: boxColor,
border: Border.all(color: primaryColor), border: Border.all(color: textColor, width: 2),
borderRadius: standardBorderRadiusAll, borderRadius: standardBorderRadiusAll,
boxShadow: [BoxShadow(color: primaryColor.withAlpha(120), blurRadius: 12)],
); );
// ==================== App Bar Theme ==================== // ==================== Component Themes ====================
static AppBarTheme appBarTheme = AppBarTheme( static const AppBarTheme appBarTheme = AppBarTheme(
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
foregroundColor: textColor, foregroundColor: textColor,
elevation: 0, elevation: 0,
scrolledUnderElevation: 0, scrolledUnderElevation: 0,
centerTitle: true, centerTitle: true,
titleTextStyle: const TextStyle( titleTextStyle: TextStyle(
color: textColor, color: textColor,
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
iconTheme: const IconThemeData(color: textColor), iconTheme: IconThemeData(color: textColor),
);
static final ActionIconThemeData actionIconTheme = ActionIconThemeData(
backButtonIconBuilder: (context) => const HapticBackButton(),
closeButtonIconBuilder: (context) => const HapticCloseButton(),
);
static const SearchBarThemeData searchBarTheme = SearchBarThemeData(
textStyle: WidgetStatePropertyAll(TextStyle(color: textColor)),
hintStyle: WidgetStatePropertyAll(TextStyle(color: hintColor)),
);
static final RadioThemeData radioTheme = RadioThemeData(
fillColor: WidgetStateProperty.resolveWith<Color>((states) {
if (states.contains(WidgetState.selected)) {
return primaryColor;
}
return textColor;
}),
);
static const InputDecorationTheme inputDecorationTheme = InputDecorationTheme(
labelStyle: TextStyle(color: textColor),
hintStyle: TextStyle(color: hintColor),
); );
} }

View File

@@ -1,6 +1,3 @@
import 'package:flutter/material.dart';
import 'package:game_tracker/l10n/generated/app_localizations.dart';
/// Button types used for styling the [CustomWidthButton] /// Button types used for styling the [CustomWidthButton]
/// - [ButtonType.primary]: Primary button style. /// - [ButtonType.primary]: Primary button style.
/// - [ButtonType.secondary]: Secondary button style. /// - [ButtonType.secondary]: Secondary button style.
@@ -29,24 +26,21 @@ enum ImportResult {
/// - [ExportResult.unknownException]: An exception occurred during export. /// - [ExportResult.unknownException]: An exception occurred during export.
enum ExportResult { success, canceled, unknownException } enum ExportResult { success, canceled, unknownException }
/// Different rulesets available for matches /// Different rulesets available for games
/// - [Ruleset.singleWinner]: The match is won by a single player /// - [Ruleset.highestScore]: The player with the highest score wins.
/// - [Ruleset.singleLoser]: The match is lost by a single player /// - [Ruleset.lowestScore]: The player with the lowest score wins.
/// - [Ruleset.mostPoints]: The player with the most points wins. /// - [Ruleset.singleWinner]: The match is won by a single player.
/// - [Ruleset.leastPoints]: The player with the fewest points wins. /// - [Ruleset.singleLoser]: The match has a single loser.
enum Ruleset { singleWinner, singleLoser, mostPoints, leastPoints } /// - [Ruleset.multipleWinners]: Multiple players can be winners.
/// - [Ruleset.placement]: The player with the highest placement wins.
/// Translates a [Ruleset] enum value to its corresponding localized string. enum Ruleset {
String translateRulesetToString(Ruleset ruleset, BuildContext context) { singleWinner,
final loc = AppLocalizations.of(context); multipleWinners,
switch (ruleset) { highestScore,
case Ruleset.singleWinner: lowestScore,
return loc.single_winner; placement,
case Ruleset.singleLoser: singleLoser,
return loc.single_loser;
case Ruleset.mostPoints:
return loc.most_points;
case Ruleset.leastPoints:
return loc.least_points;
}
} }
/// Different colors for highlighting games
enum GameColor { red, orange, yellow, green, teal, blue, purple, pink }

218
lib/data/dao/game_dao.dart Normal file
View File

@@ -0,0 +1,218 @@
import 'package:drift/drift.dart';
import 'package:tallee/core/enums.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/db/tables/game_table.dart';
import 'package:tallee/data/models/game.dart';
part 'game_dao.g.dart';
@DriftAccessor(tables: [GameTable])
class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
GameDao(super.db);
/* Create */
/// Adds a new [game] to the database.
/// If a game with the same ID already exists, no action is taken.
/// Returns `true` if the game was added, `false` otherwise.
Future<bool> addGame({required Game game}) async {
if (!await gameExists(gameId: game.id)) {
await into(gameTable).insert(
GameTableCompanion.insert(
id: game.id,
name: game.name,
ruleset: game.ruleset.name,
description: game.description,
color: game.color.name,
icon: game.icon,
createdAt: game.createdAt,
),
mode: InsertMode.insertOrReplace,
);
return true;
}
return false;
}
/// Adds multiple [games] to the database in a batch operation.
/// Uses insertOrIgnore to avoid overwriting existing games.
Future<bool> addGamesAsList({required List<Game> games}) async {
if (games.isEmpty) return false;
await db.batch(
(b) => b.insertAll(
gameTable,
games
.map(
(game) => GameTableCompanion.insert(
id: game.id,
name: game.name,
ruleset: game.ruleset.name,
description: game.description,
color: game.color.name,
icon: game.icon,
createdAt: game.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrIgnore,
),
);
return true;
}
/* Read */
/// Retrieves the total count of games in the database.
Future<int> getGameCount() async {
final count =
await (selectOnly(gameTable)..addColumns([gameTable.id.count()]))
.map((row) => row.read(gameTable.id.count()))
.getSingle();
return count ?? 0;
}
/// Checks if a game with the given [gameId] exists in the database.
/// Returns `true` if the game exists, `false` otherwise.
Future<bool> gameExists({required String gameId}) async {
final query = select(gameTable)..where((g) => g.id.equals(gameId));
final result = await query.getSingleOrNull();
return result != null;
}
/// Retrieves all games from the database.
Future<List<Game>> getAllGames() async {
final query = select(gameTable);
final result = await query.get();
return result
.map(
(row) => Game(
id: row.id,
name: row.name,
ruleset: Ruleset.values.firstWhere((e) => e.name == row.ruleset),
description: row.description,
color: GameColor.values.firstWhere((e) => e.name == row.color),
icon: row.icon,
createdAt: row.createdAt,
),
)
.toList();
}
/// Retrieves a [Game] by its [gameId].
Future<Game> getGameById({required String gameId}) async {
final query = select(gameTable)..where((g) => g.id.equals(gameId));
final result = await query.getSingle();
return Game(
id: result.id,
name: result.name,
ruleset: Ruleset.values.firstWhere((e) => e.name == result.ruleset),
description: result.description,
color: GameColor.values.firstWhere((e) => e.name == result.color),
icon: result.icon,
createdAt: result.createdAt,
);
}
/* Update */
/// Updates the name of the game with the given [gameId] to [name].
Future<bool> updateGameName({
required String gameId,
required String name,
}) async {
final rowsAffected =
await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(name: Value(name)),
);
return rowsAffected > 0;
}
/// Updates the ruleset of the game with the given [gameId].
Future<bool> updateGameRuleset({
required String gameId,
required Ruleset ruleset,
}) async {
final rowsAffected =
await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(ruleset: Value(ruleset.name)),
);
return rowsAffected > 0;
}
/// Updates the description of the game with the given [gameId].
Future<bool> updateGameDescription({
required String gameId,
required String description,
}) async {
final rowsAffected =
await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(description: Value(description)),
);
return rowsAffected > 0;
}
/// Updates the color of the game with the given [gameId].
Future<bool> updateGameColor({
required String gameId,
required GameColor color,
}) async {
final rowsAffected =
await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(color: Value(color.name)),
);
return rowsAffected > 0;
}
/// Updates the icon of the game with the given [gameId].
Future<bool> updateGameIcon({
required String gameId,
required String icon,
}) async {
final rowsAffected =
await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(icon: Value(icon)),
);
return rowsAffected > 0;
}
/* Delete */
/// Deletes the game with the given [gameId] from the database.
/// Returns `true` if the game was deleted, `false` if the game did not exist.
Future<bool> deleteGame({required String gameId}) async {
final query = delete(gameTable)..where((g) => g.id.equals(gameId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Deletes all games from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteAllGames() async {
final query = delete(gameTable);
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Retrieves all games with their respective match counts.
/// Returns a list of tuples (Game, matchCount).
Future<List<(Game, int)>> getGameUsage() async {
final games = await getAllGames();
final results = <(Game, int)>[];
for (final game in games) {
final matchCount =
await (selectOnly(db.matchTable)
..where(db.matchTable.gameId.equals(game.id))
..addColumns([db.matchTable.id.count()]))
.map((row) => row.read(db.matchTable.id.count()))
.getSingle();
results.add((game, matchCount ?? 0));
}
return results;
}
}

View File

@@ -0,0 +1,16 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'game_dao.dart';
// ignore_for_file: type=lint
mixin _$GameDaoMixin on DatabaseAccessor<AppDatabase> {
$GameTableTable get gameTable => attachedDatabase.gameTable;
GameDaoManager get managers => GameDaoManager(this);
}
class GameDaoManager {
final _$GameDaoMixin _db;
GameDaoManager(this._db);
$$GameTableTableTableManager get gameTable =>
$$GameTableTableTableManager(_db.attachedDatabase, _db.gameTable);
}

View File

@@ -1,51 +1,18 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:tallee/data/db/database.dart';
import 'package:game_tracker/data/db/tables/group_table.dart'; import 'package:tallee/data/db/tables/group_table.dart';
import 'package:game_tracker/data/db/tables/player_group_table.dart'; import 'package:tallee/data/db/tables/match_table.dart';
import 'package:game_tracker/data/dto/group.dart'; import 'package:tallee/data/db/tables/player_group_table.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:tallee/data/models/group.dart';
import 'package:tallee/data/models/player.dart';
part 'group_dao.g.dart'; part 'group_dao.g.dart';
@DriftAccessor(tables: [GroupTable, PlayerGroupTable]) @DriftAccessor(tables: [GroupTable, PlayerGroupTable, MatchTable])
class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin { class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
GroupDao(super.db); GroupDao(super.db);
/// Retrieves all groups from the database. /* Create */
Future<List<Group>> getAllGroups() async {
final query = select(groupTable);
final result = await query.get();
return Future.wait(
result.map((groupData) async {
final members = await db.playerGroupDao.getPlayersOfGroup(
groupId: groupData.id,
);
return Group(
id: groupData.id,
name: groupData.name,
members: members,
createdAt: groupData.createdAt,
);
}),
);
}
/// Retrieves a [Group] by its [groupId], including its members.
Future<Group> getGroupById({required String groupId}) async {
final query = select(groupTable)..where((g) => g.id.equals(groupId));
final result = await query.getSingle();
List<Player> members = await db.playerGroupDao.getPlayersOfGroup(
groupId: groupId,
);
return Group(
id: result.id,
name: result.name,
members: members,
createdAt: result.createdAt,
);
}
/// Adds a new group with the given [id] and [name] to the database. /// Adds a new group with the given [id] and [name] to the database.
/// This method also adds the group's members to the [PlayerGroupTable]. /// This method also adds the group's members to the [PlayerGroupTable].
@@ -56,6 +23,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
GroupTableCompanion.insert( GroupTableCompanion.insert(
id: group.id, id: group.id,
name: group.name, name: group.name,
description: group.description,
createdAt: group.createdAt, createdAt: group.createdAt,
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
@@ -105,6 +73,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
(group) => GroupTableCompanion.insert( (group) => GroupTableCompanion.insert(
id: group.id, id: group.id,
name: group.name, name: group.name,
description: group.description,
createdAt: group.createdAt, createdAt: group.createdAt,
), ),
) )
@@ -132,6 +101,7 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
(p) => PlayerTableCompanion.insert( (p) => PlayerTableCompanion.insert(
id: p.id, id: p.id,
name: p.name, name: p.name,
description: p.description,
createdAt: p.createdAt, createdAt: p.createdAt,
), ),
) )
@@ -166,25 +136,44 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
}); });
} }
/// Deletes the group with the given [id] from the database. /* Read */
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteGroup({required String groupId}) async { /// Retrieves all groups from the database.
final query = (delete(groupTable)..where((g) => g.id.equals(groupId))); Future<List<Group>> getAllGroups() async {
final rowsAffected = await query.go(); final query = select(groupTable);
return rowsAffected > 0; final result = await query.get();
return Future.wait(
result.map((groupData) async {
final members = await db.playerGroupDao.getPlayersOfGroup(
groupId: groupData.id,
);
return Group(
id: groupData.id,
name: groupData.name,
description: groupData.description,
members: members,
createdAt: groupData.createdAt,
);
}),
);
} }
/// Updates the name of the group with the given [id] to [newName]. /// Retrieves a [Group] by its [groupId], including its members.
/// Returns `true` if more than 0 rows were affected, otherwise `false`. Future<Group> getGroupById({required String groupId}) async {
Future<bool> updateGroupname({ final query = select(groupTable)..where((g) => g.id.equals(groupId));
required String groupId, final result = await query.getSingle();
required String newName,
}) async { List<Player> members = await db.playerGroupDao.getPlayersOfGroup(
final rowsAffected = groupId: groupId,
await (update(groupTable)..where((g) => g.id.equals(groupId))).write( );
GroupTableCompanion(name: Value(newName)),
); return Group(
return rowsAffected > 0; id: result.id,
name: result.name,
description: result.description,
members: members,
createdAt: result.createdAt,
);
} }
/// Retrieves the number of groups in the database. /// Retrieves the number of groups in the database.
@@ -196,6 +185,38 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
return count ?? 0; return count ?? 0;
} }
/// Retrieves all groups a specific player belongs to.
/// Returns an empty list if the player is not part of any group.
Future<List<Group>> getGroupsByPlayer({required String playerId}) async {
final playerGroups = await (select(
playerGroupTable,
)..where((pg) => pg.playerId.equals(playerId))).get();
if (playerGroups.isEmpty) return [];
final groupIds = playerGroups.map((pg) => pg.groupId).toSet().toList();
final rows =
await (select(groupTable)
..where((g) => g.id.isIn(groupIds))
..orderBy([(g) => OrderingTerm.desc(g.createdAt)]))
.get();
return Future.wait(
rows.map((groupData) async {
final members = await db.playerGroupDao.getPlayersOfGroup(
groupId: groupData.id,
);
return Group(
id: groupData.id,
name: groupData.name,
description: groupData.description,
members: members,
createdAt: groupData.createdAt,
);
}),
);
}
/// Checks if a group with the given [groupId] exists in the database. /// Checks if a group with the given [groupId] exists in the database.
/// Returns `true` if the group exists, `false` otherwise. /// Returns `true` if the group exists, `false` otherwise.
Future<bool> groupExists({required String groupId}) async { Future<bool> groupExists({required String groupId}) async {
@@ -204,6 +225,16 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
return result != null; return result != null;
} }
/* Delete */
/// Deletes the group with the given [id] from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteGroup({required String groupId}) async {
final query = (delete(groupTable)..where((g) => g.id.equals(groupId)));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Deletes all groups from the database. /// Deletes all groups from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`. /// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteAllGroups() async { Future<bool> deleteAllGroups() async {
@@ -211,4 +242,32 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
final rowsAffected = await query.go(); final rowsAffected = await query.go();
return rowsAffected > 0; return rowsAffected > 0;
} }
/* Update */
/// Updates the name of the group with the given [id] to [name].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGroupName({
required String groupId,
required String name,
}) async {
final rowsAffected =
await (update(groupTable)..where((g) => g.id.equals(groupId))).write(
GroupTableCompanion(name: Value(name)),
);
return rowsAffected > 0;
}
/// Updates the description of the group with the given [groupId] to [description].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGroupDescription({
required String groupId,
required String description,
}) async {
final rowsAffected =
await (update(groupTable)..where((g) => g.id.equals(groupId))).write(
GroupTableCompanion(description: Value(description)),
);
return rowsAffected > 0;
}
} }

View File

@@ -8,4 +8,25 @@ mixin _$GroupDaoMixin on DatabaseAccessor<AppDatabase> {
$PlayerTableTable get playerTable => attachedDatabase.playerTable; $PlayerTableTable get playerTable => attachedDatabase.playerTable;
$PlayerGroupTableTable get playerGroupTable => $PlayerGroupTableTable get playerGroupTable =>
attachedDatabase.playerGroupTable; attachedDatabase.playerGroupTable;
$GameTableTable get gameTable => attachedDatabase.gameTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable;
GroupDaoManager get managers => GroupDaoManager(this);
}
class GroupDaoManager {
final _$GroupDaoMixin _db;
GroupDaoManager(this._db);
$$GroupTableTableTableManager get groupTable =>
$$GroupTableTableTableManager(_db.attachedDatabase, _db.groupTable);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
$$PlayerGroupTableTableTableManager get playerGroupTable =>
$$PlayerGroupTableTableTableManager(
_db.attachedDatabase,
_db.playerGroupTable,
);
$$GameTableTableTableManager get gameTable =>
$$GameTableTableTableManager(_db.attachedDatabase, _db.gameTable);
$$MatchTableTableTableManager get matchTable =>
$$MatchTableTableTableManager(_db.attachedDatabase, _db.matchTable);
} }

View File

@@ -1,98 +0,0 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/group_match_table.dart';
import 'package:game_tracker/data/dto/group.dart';
part 'group_match_dao.g.dart';
@DriftAccessor(tables: [GroupMatchTable])
class GroupMatchDao extends DatabaseAccessor<AppDatabase>
with _$GroupMatchDaoMixin {
GroupMatchDao(super.db);
/// Associates a group with a match by inserting a record into the
/// [GroupMatchTable].
Future<void> addGroupToMatch({
required String matchId,
required String groupId,
}) async {
if (await matchHasGroup(matchId: matchId)) {
throw Exception('Match already has a group');
}
await into(groupMatchTable).insert(
GroupMatchTableCompanion.insert(groupId: groupId, matchId: matchId),
mode: InsertMode.insertOrIgnore,
);
}
/// Retrieves the [Group] associated with the given [matchId].
/// Returns `null` if no group is found.
Future<Group?> getGroupOfMatch({required String matchId}) async {
final result = await (select(
groupMatchTable,
)..where((g) => g.matchId.equals(matchId))).getSingleOrNull();
if (result == null) {
return null;
}
final group = await db.groupDao.getGroupById(groupId: result.groupId);
return group;
}
/// Checks if there is a group associated with the given [matchId].
/// Returns `true` if there is a group, otherwise `false`.
Future<bool> matchHasGroup({required String matchId}) async {
final count =
await (selectOnly(groupMatchTable)
..where(groupMatchTable.matchId.equals(matchId))
..addColumns([groupMatchTable.groupId.count()]))
.map((row) => row.read(groupMatchTable.groupId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Checks if a specific group is associated with a specific match.
/// Returns `true` if the group is in the match, otherwise `false`.
Future<bool> isGroupInMatch({
required String matchId,
required String groupId,
}) async {
final count =
await (selectOnly(groupMatchTable)
..where(
groupMatchTable.matchId.equals(matchId) &
groupMatchTable.groupId.equals(groupId),
)
..addColumns([groupMatchTable.groupId.count()]))
.map((row) => row.read(groupMatchTable.groupId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Removes the association of a group from a match based on [groupId] and
/// [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeGroupFromMatch({
required String matchId,
required String groupId,
}) async {
final query = delete(groupMatchTable)
..where((g) => g.matchId.equals(matchId) & g.groupId.equals(groupId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Updates the group associated with a match to [newGroupId] based on
/// [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGroupOfMatch({
required String matchId,
required String newGroupId,
}) async {
final updatedRows =
await (update(groupMatchTable)..where((g) => g.matchId.equals(matchId)))
.write(GroupMatchTableCompanion(groupId: Value(newGroupId)));
return updatedRows > 0;
}
}

View File

@@ -1,10 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'group_match_dao.dart';
// ignore_for_file: type=lint
mixin _$GroupMatchDaoMixin on DatabaseAccessor<AppDatabase> {
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable;
$GroupMatchTableTable get groupMatchTable => attachedDatabase.groupMatchTable;
}

View File

@@ -1,87 +1,60 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:tallee/data/db/database.dart';
import 'package:game_tracker/data/db/tables/match_table.dart'; import 'package:tallee/data/db/tables/game_table.dart';
import 'package:game_tracker/data/dto/group.dart'; import 'package:tallee/data/db/tables/group_table.dart';
import 'package:game_tracker/data/dto/match.dart'; import 'package:tallee/data/db/tables/match_table.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:tallee/data/db/tables/player_match_table.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/data/models/team.dart';
part 'match_dao.g.dart'; part 'match_dao.g.dart';
@DriftAccessor(tables: [MatchTable]) @DriftAccessor(tables: [MatchTable, GameTable, GroupTable, PlayerMatchTable])
class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin { class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
MatchDao(super.db); MatchDao(super.db);
/// Retrieves all matches from the database. /* Create */
Future<List<Match>> getAllMatches() async {
final query = select(matchTable);
final result = await query.get();
return Future.wait( /// Adds a new [Match] to the database. Also adds players associations and teams.
result.map((row) async { /// This method assumes that the game and group (if any) are already present
final group = await db.groupMatchDao.getGroupOfMatch(matchId: row.id); /// in the database.
final players = await db.playerMatchDao.getPlayersOfMatch( Future<bool> addMatch({required Match match}) async {
matchId: row.id, if (await matchExists(matchId: match.id)) return false;
);
final winner = row.winnerId != null
? await db.playerDao.getPlayerById(playerId: row.winnerId!)
: null;
return Match(
id: row.id,
name: row.name,
group: group,
players: players,
createdAt: row.createdAt,
winner: winner,
);
}),
);
}
/// Retrieves a [Match] by its [matchId].
Future<Match> getMatchById({required String matchId}) async {
final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingle();
List<Player>? players;
if (await db.playerMatchDao.matchHasPlayers(matchId: matchId)) {
players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId);
}
Group? group;
if (await db.groupMatchDao.matchHasGroup(matchId: matchId)) {
group = await db.groupMatchDao.getGroupOfMatch(matchId: matchId);
}
Player? winner;
if (result.winnerId != null) {
winner = await db.playerDao.getPlayerById(playerId: result.winnerId!);
}
return Match(
id: result.id,
name: result.name,
players: players,
group: group,
winner: winner,
createdAt: result.createdAt,
);
}
/// Adds a new [Match] to the database. Also adds players and group
/// associations. This method assumes that the players and groups added to
/// this match are already present in the database.
Future<void> addMatch({required Match match}) async {
await db.transaction(() async { await db.transaction(() async {
await into(matchTable).insert( await into(matchTable).insert(
MatchTableCompanion.insert( MatchTableCompanion.insert(
id: match.id, id: match.id,
gameId: match.game.id,
groupId: Value(match.group?.id),
name: match.name, name: match.name,
winnerId: Value(match.winner?.id), notes: match.notes,
createdAt: match.createdAt, createdAt: match.createdAt,
endedAt: Value(match.endedAt),
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
); );
if (match.players != null) { // Add teams
for (final p in match.players ?? []) { if (match.teams != null && match.teams!.isNotEmpty) {
await db.teamDao.addTeamsAsList(teams: match.teams!, matchId: match.id);
}
// Collect all player IDs that are already in teams
final playersInTeams = <String>{};
if (match.teams != null) {
for (final team in match.teams!) {
for (final member in team.members) {
playersInTeams.add(member.id);
}
}
}
// Add players that are not in teams
for (final p in match.players) {
if (!playersInTeams.contains(p.id)) {
await db.playerMatchDao.addPlayerToMatch( await db.playerMatchDao.addPlayerToMatch(
matchId: match.id, matchId: match.id,
playerId: p.id, playerId: p.id,
@@ -89,53 +62,68 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
} }
} }
if (match.group != null) { for (final pid in match.scores.keys) {
await db.groupMatchDao.addGroupToMatch( final playerScores = match.scores[pid];
matchId: match.id, if (playerScores != null) {
groupId: match.group!.id, await db.scoreEntryDao.addScore(
); entry: playerScores,
playerId: pid,
matchId: match.id,
);
}
} }
}); });
return true;
} }
/// Adds multiple [Match]s to the database in a batch operation. /// Adds multiple [Match]es to the database in a batch operation.
/// Also adds associated players and groups if they exist. /// Also adds associated players and groups if they exist.
/// If the [matches] list is empty, the method returns immediately. /// If the [matches] list is empty, the method returns immediately.
/// This Method should only be used to import matches from a different device. /// This method should only be used to import matches from a different device.
Future<void> addMatchAsList({required List<Match> matches}) async { Future<bool> addMatchesAsList({required List<Match> matches}) async {
if (matches.isEmpty) return; if (matches.isEmpty) return false;
await db.transaction(() async { await db.transaction(() async {
// Add all matches in batch // Add all games first (deduplicated)
await db.batch( final uniqueGames = <String, Game>{};
(b) => b.insertAll( for (final match in matches) {
matchTable, uniqueGames[match.game.id] = match.game;
matches }
.map(
(match) => MatchTableCompanion.insert(
id: match.id,
name: match.name,
createdAt: match.createdAt,
winnerId: Value(match.winner?.id),
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
// Add all groups of the matches in batch // Add games
// Using insertOrIgnore to avoid overwriting existing groups (which would if (uniqueGames.isNotEmpty) {
// trigger cascade deletes on player_group associations) await db.batch(
(b) => b.insertAll(
db.gameTable,
uniqueGames.values
.map(
(game) => GameTableCompanion.insert(
id: game.id,
name: game.name,
ruleset: game.ruleset.name,
description: game.description,
color: game.color.name,
icon: game.icon,
createdAt: game.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrIgnore,
),
);
}
// Add groups
await db.batch( await db.batch(
(b) => b.insertAll( (b) => b.insertAll(
db.groupTable, db.groupTable,
matches matches
.where((match) => match.group != null) .where((match) => match.group != null)
.map( .map(
(matches) => GroupTableCompanion.insert( (match) => GroupTableCompanion.insert(
id: matches.group!.id, id: match.group!.id,
name: matches.group!.name, name: match.group!.name,
createdAt: matches.group!.createdAt, description: match.group!.description,
createdAt: match.group!.createdAt,
), ),
) )
.toList(), .toList(),
@@ -143,13 +131,32 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
), ),
); );
// Add all players of the matches in batch (unique) // Add matches
await db.batch(
(b) => b.insertAll(
matchTable,
matches
.map(
(match) => MatchTableCompanion.insert(
id: match.id,
gameId: match.game.id,
groupId: Value(match.group?.id),
name: match.name,
notes: match.notes,
createdAt: match.createdAt,
endedAt: Value(match.endedAt),
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
// Add players
final uniquePlayers = <String, Player>{}; final uniquePlayers = <String, Player>{};
for (final match in matches) { for (final match in matches) {
if (match.players != null) { for (final p in match.players) {
for (final p in match.players!) { uniquePlayers[p.id] = p;
uniquePlayers[p.id] = p;
}
} }
// Also include members of groups // Also include members of groups
if (match.group != null) { if (match.group != null) {
@@ -160,8 +167,6 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
} }
if (uniquePlayers.isNotEmpty) { if (uniquePlayers.isNotEmpty) {
// Using insertOrIgnore to avoid triggering cascade deletes on
// player_group/player_match associations when players already exist
await db.batch( await db.batch(
(b) => b.insertAll( (b) => b.insertAll(
db.playerTable, db.playerTable,
@@ -170,6 +175,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
(p) => PlayerTableCompanion.insert( (p) => PlayerTableCompanion.insert(
id: p.id, id: p.id,
name: p.name, name: p.name,
description: p.description,
createdAt: p.createdAt, createdAt: p.createdAt,
), ),
) )
@@ -179,25 +185,43 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
); );
} }
// Add all player-match associations in batch
await db.batch((b) { await db.batch((b) {
for (final match in matches) { for (final match in matches) {
if (match.players != null) { for (final entry in match.scores.entries) {
for (final p in match.players ?? []) { if (entry.value != null) {
b.insert( b.insert(
db.playerMatchTable, db.scoreEntryTable,
PlayerMatchTableCompanion.insert( ScoreEntryTableCompanion.insert(
matchId: match.id, matchId: match.id,
playerId: p.id, playerId: entry.key,
score: entry.value!.score,
roundNumber: entry.value!.roundNumber,
change: entry.value!.change,
), ),
mode: InsertMode.insertOrIgnore, mode: InsertMode.insertOrReplace,
); );
} }
} }
} }
}); });
// Add all player-group associations in batch // Add player-match associations
await db.batch((b) {
for (final match in matches) {
for (final p in match.players) {
b.insert(
db.playerMatchTable,
PlayerMatchTableCompanion.insert(
matchId: match.id,
playerId: p.id,
),
mode: InsertMode.insertOrIgnore,
);
}
}
});
// Add player-group associations
await db.batch((b) { await db.batch((b) {
for (final match in matches) { for (final match in matches) {
if (match.group != null) { if (match.group != null) {
@@ -215,30 +239,27 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
} }
}); });
// Add all group-match associations in batch // Add teams for matches
await db.batch((b) { for (final match in matches) {
for (final match in matches) { if (match.teams != null && match.teams!.isNotEmpty) {
if (match.group != null) { await db.teamDao.addTeamsAsList(
b.insert( teams: match.teams!,
db.groupMatchTable, matchId: match.id,
GroupMatchTableCompanion.insert( );
matchId: match.id,
groupId: match.group!.id,
),
mode: InsertMode.insertOrIgnore,
);
}
} }
}); }
}); });
return true;
} }
/// Deletes the match with the given [matchId] from the database. /* Read */
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteMatch({required String matchId}) async { /// Checks if a match with the given [matchId] exists in the database.
final query = delete(matchTable)..where((g) => g.id.equals(matchId)); /// Returns `true` if the match exists, otherwise `false`.
final rowsAffected = await query.go(); Future<bool> matchExists({required String matchId}) async {
return rowsAffected > 0; final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingleOrNull();
return result != null;
} }
/// Retrieves the number of matches in the database. /// Retrieves the number of matches in the database.
@@ -250,12 +271,262 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
return count ?? 0; return count ?? 0;
} }
/// Checks if a match with the given [matchId] exists in the database. /// Retrieves all matches from the database.
/// Returns `true` if the match exists, otherwise `false`. Future<List<Match>> getAllMatches() async {
Future<bool> matchExists({required String matchId}) async { final query = select(matchTable);
final result = await query.get();
return Future.wait(
result.map((row) async {
final game = await db.gameDao.getGameById(gameId: row.gameId);
Group? group;
if (row.groupId != null) {
group = await db.groupDao.getGroupById(groupId: row.groupId!);
}
final players = await db.playerMatchDao.getPlayersOfMatch(
matchId: row.id,
);
final scores = await db.scoreEntryDao.getAllMatchScores(
matchId: row.id,
);
final teams = await _getMatchTeams(matchId: row.id);
return Match(
id: row.id,
name: row.name,
game: game,
group: group,
players: players,
teams: teams.isEmpty ? null : teams,
notes: row.notes,
createdAt: row.createdAt,
endedAt: row.endedAt,
scores: scores,
);
}),
);
}
/// Retrieves a [Match] by its [matchId].
Future<Match> getMatchById({required String matchId}) async {
final query = select(matchTable)..where((g) => g.id.equals(matchId)); final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingleOrNull(); final result = await query.getSingle();
return result != null;
final game = await db.gameDao.getGameById(gameId: result.gameId);
Group? group;
if (result.groupId != null) {
group = await db.groupDao.getGroupById(groupId: result.groupId!);
}
final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId);
final scores = await db.scoreEntryDao.getAllMatchScores(matchId: matchId);
final teams = await _getMatchTeams(matchId: matchId);
return Match(
id: result.id,
name: result.name,
game: game,
group: group,
players: players,
teams: teams.isEmpty ? null : teams,
notes: result.notes,
createdAt: result.createdAt,
endedAt: result.endedAt,
scores: scores,
);
}
/// Retrieves the number of matches associated with a specific game.
Future<int> getMatchCountByGame({required String gameId}) async {
final count =
await (selectOnly(matchTable)
..where(matchTable.gameId.equals(gameId))
..addColumns([matchTable.id.count()]))
.map((row) => row.read(matchTable.id.count()))
.getSingle();
return count ?? 0;
}
Future<List<Match>> getMatchesByPlayer({required String playerId}) async {
final playerMatches = await (select(
playerMatchTable,
)..where((pm) => pm.playerId.equals(playerId))).get();
if (playerMatches.isEmpty) return [];
final matchIds = playerMatches.map((pm) => pm.matchId).toSet().toList();
final rows =
await (select(matchTable)
..where((m) => m.id.isIn(matchIds))
..orderBy([(m) => OrderingTerm.desc(m.createdAt)]))
.get();
return Future.wait(
rows.map((row) async {
final game = await db.gameDao.getGameById(gameId: row.gameId);
Group? group;
if (row.groupId != null) {
group = await db.groupDao.getGroupById(groupId: row.groupId!);
}
final players = await db.playerMatchDao.getPlayersOfMatch(
matchId: row.id,
);
final scores = await db.scoreEntryDao.getAllMatchScores(
matchId: row.id,
);
final teams = await _getMatchTeams(matchId: row.id);
return Match(
id: row.id,
name: row.name,
game: game,
group: group,
players: players,
teams: teams.isEmpty ? null : teams,
notes: row.notes,
createdAt: row.createdAt,
endedAt: row.endedAt,
scores: scores,
);
}),
);
}
/// Retrieves all matches associated with the given [groupId].
/// Queries the database directly, filtering by [groupId].
Future<List<Match>> getMatchesByGroup({required String groupId}) async {
final query = select(matchTable)..where((m) => m.groupId.equals(groupId));
final rows = await query.get();
return Future.wait(
rows.map((row) async {
final game = await db.gameDao.getGameById(gameId: row.gameId);
final group = await db.groupDao.getGroupById(groupId: groupId);
final players = await db.playerMatchDao.getPlayersOfMatch(
matchId: row.id,
);
final teams = await _getMatchTeams(matchId: row.id);
return Match(
id: row.id,
name: row.name,
game: game,
group: group,
players: players,
teams: teams.isEmpty ? null : teams,
notes: row.notes,
createdAt: row.createdAt,
endedAt: row.endedAt,
);
}),
);
}
/// Helper method to retrieve teams for a specific match
Future<List<Team>> _getMatchTeams({required String matchId}) async {
// Get all unique team IDs from PlayerMatchTable for this match
final playerMatchQuery = select(db.playerMatchTable)
..where((pm) => pm.matchId.equals(matchId) & pm.teamId.isNotNull());
final playerMatches = await playerMatchQuery.get();
if (playerMatches.isEmpty) return [];
final teamIds = playerMatches
.map((pm) => pm.teamId)
.whereType<String>()
.toSet()
.toList();
// Fetch all teams
final teams = await Future.wait(
teamIds.map((teamId) => db.teamDao.getTeamById(teamId: teamId)),
);
return teams;
}
/* Update */
/// Changes the name of the match with the given [matchId] to [name].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchName({
required String matchId,
required String name,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(name: Value(name)),
);
return rowsAffected > 0;
}
/// Updates the group of the match with the given [matchId].
/// Replaces the existing group association with the new group specified by [groupId].
/// Pass null to remove the group association.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchGroup({
required String matchId,
required String? groupId,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(groupId: Value(groupId)),
);
return rowsAffected > 0;
}
/// Updates the notes of the match with the given [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchNotes({
required String matchId,
required String notes,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(notes: Value(notes)),
);
return rowsAffected > 0;
}
/// Removes the group association of the match with the given [matchId].
/// Sets the groupId to null.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeMatchGroup({required String matchId}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
const MatchTableCompanion(groupId: Value(null)),
);
return rowsAffected > 0;
}
/// Updates the endedAt timestamp of the match with the given [matchId].
/// Pass null to remove the ended time (mark match as ongoing).
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchEndedAt({
required String matchId,
required DateTime endedAt,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(endedAt: Value(endedAt)),
);
return rowsAffected > 0;
}
/* Delete */
/// Deletes the match with the given [matchId] from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteMatch({required String matchId}) async {
final query = delete(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.go();
return rowsAffected > 0;
} }
/// Deletes all matches from the database. /// Deletes all matches from the database.
@@ -266,61 +537,11 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
return rowsAffected > 0; return rowsAffected > 0;
} }
/// Sets the winner of the match with the given [matchId] to the player with /// Deletes all matches associated with a specific game.
/// the given [winnerId]. /// Returns the number of matches deleted.
/// Returns `true` if more than 0 rows were affected, otherwise `false`. Future<int> deleteMatchesByGame({required String gameId}) async {
Future<bool> setWinner({ final query = delete(matchTable)..where((m) => m.gameId.equals(gameId));
required String matchId, final rowsAffected = await query.go();
required String winnerId, return rowsAffected;
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(winnerId: Value(winnerId)),
);
return rowsAffected > 0;
}
/// Retrieves the winner of the match with the given [matchId].
/// Returns the [Player] who won the match, or `null` if no winner is set.
Future<Player?> getWinner({required String matchId}) async {
final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingleOrNull();
if (result == null || result.winnerId == null) {
return null;
}
final winner = await db.playerDao.getPlayerById(playerId: result.winnerId!);
return winner;
}
/// Removes the winner of the match with the given [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeWinner({required String matchId}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
const MatchTableCompanion(winnerId: Value(null)),
);
return rowsAffected > 0;
}
/// Checks if the match with the given [matchId] has a winner set.
/// Returns `true` if a winner is set, otherwise `false`.
Future<bool> hasWinner({required String matchId}) async {
final query = select(matchTable)
..where((g) => g.id.equals(matchId) & g.winnerId.isNotNull());
final result = await query.getSingleOrNull();
return result != null;
}
/// Changes the title of the match with the given [matchId] to [newName].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchName({
required String matchId,
required String newName,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(name: Value(newName)),
);
return rowsAffected > 0;
} }
} }

View File

@@ -4,5 +4,32 @@ part of 'match_dao.dart';
// ignore_for_file: type=lint // ignore_for_file: type=lint
mixin _$MatchDaoMixin on DatabaseAccessor<AppDatabase> { mixin _$MatchDaoMixin on DatabaseAccessor<AppDatabase> {
$GameTableTable get gameTable => attachedDatabase.gameTable;
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable; $MatchTableTable get matchTable => attachedDatabase.matchTable;
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
$TeamTableTable get teamTable => attachedDatabase.teamTable;
$PlayerMatchTableTable get playerMatchTable =>
attachedDatabase.playerMatchTable;
MatchDaoManager get managers => MatchDaoManager(this);
}
class MatchDaoManager {
final _$MatchDaoMixin _db;
MatchDaoManager(this._db);
$$GameTableTableTableManager get gameTable =>
$$GameTableTableTableManager(_db.attachedDatabase, _db.gameTable);
$$GroupTableTableTableManager get groupTable =>
$$GroupTableTableTableManager(_db.attachedDatabase, _db.groupTable);
$$MatchTableTableTableManager get matchTable =>
$$MatchTableTableTableManager(_db.attachedDatabase, _db.matchTable);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
$$TeamTableTableTableManager get teamTable =>
$$TeamTableTableTableManager(_db.attachedDatabase, _db.teamTable);
$$PlayerMatchTableTableTableManager get playerMatchTable =>
$$PlayerMatchTableTableTableManager(
_db.attachedDatabase,
_db.playerMatchTable,
);
} }

View File

@@ -1,7 +1,8 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:flutter/cupertino.dart';
import 'package:game_tracker/data/db/tables/player_table.dart'; import 'package:tallee/data/db/database.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:tallee/data/db/tables/player_table.dart';
import 'package:tallee/data/models/player.dart';
part 'player_dao.g.dart'; part 'player_dao.g.dart';
@@ -9,38 +10,22 @@ part 'player_dao.g.dart';
class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin { class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
PlayerDao(super.db); PlayerDao(super.db);
/// Retrieves all players from the database. /* Create */
Future<List<Player>> getAllPlayers() async {
final query = select(playerTable);
final result = await query.get();
return result
.map(
(row) => Player(id: row.id, name: row.name, createdAt: row.createdAt),
)
.toList();
}
/// Retrieves a [Player] by their [id].
Future<Player> getPlayerById({required String playerId}) async {
final query = select(playerTable)..where((p) => p.id.equals(playerId));
final result = await query.getSingle();
return Player(
id: result.id,
name: result.name,
createdAt: result.createdAt,
);
}
/// Adds a new [player] to the database. /// Adds a new [player] to the database.
/// If a player with the same ID already exists, updates their name to /// If a player with the same ID already exists, updates their name to
/// the new one. /// the new one.
Future<bool> addPlayer({required Player player}) async { Future<bool> addPlayer({required Player player}) async {
if (!await playerExists(playerId: player.id)) { if (!await playerExists(playerId: player.id)) {
final int nameCount = await _processNameCount(name: player.name);
await into(playerTable).insert( await into(playerTable).insert(
PlayerTableCompanion.insert( PlayerTableCompanion.insert(
id: player.id, id: player.id,
name: player.name, name: player.name,
description: player.description,
createdAt: player.createdAt, createdAt: player.createdAt,
nameCount: Value(nameCount),
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
); );
@@ -55,50 +40,74 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
Future<bool> addPlayersAsList({required List<Player> players}) async { Future<bool> addPlayersAsList({required List<Player> players}) async {
if (players.isEmpty) return false; if (players.isEmpty) return false;
// Filter out players that already exist
final newPlayers = <Player>[];
for (final player in players) {
if (!await playerExists(playerId: player.id)) {
newPlayers.add(player);
}
}
if (newPlayers.isEmpty) return false;
// Group players by name
final nameGroups = <String, List<Player>>{};
for (final player in newPlayers) {
nameGroups.putIfAbsent(player.name, () => []).add(player);
}
final playersToInsert = <PlayerTableCompanion>[];
// Process each group of players with the same name
for (final entry in nameGroups.entries) {
final name = entry.key;
final playersWithName = entry.value;
// Get the current nameCount
var nameCount = await _processNameCount(name: name);
// One player with the same name
if (playersWithName.length == 1) {
final player = playersWithName[0];
playersToInsert.add(
PlayerTableCompanion.insert(
id: player.id,
name: player.name,
description: player.description,
createdAt: player.createdAt,
nameCount: Value(nameCount),
),
);
} else {
if (nameCount == 0) nameCount++;
// Multiple players with the same name
for (var i = 0; i < playersWithName.length; i++) {
final player = playersWithName[i];
playersToInsert.add(
PlayerTableCompanion.insert(
id: player.id,
name: player.name,
description: player.description,
createdAt: player.createdAt,
nameCount: Value(nameCount + i),
),
);
}
}
}
await db.batch( await db.batch(
(b) => b.insertAll( (b) => b.insertAll(
playerTable, playerTable,
players playersToInsert,
.map( mode: InsertMode.insertOrReplace,
(player) => PlayerTableCompanion.insert(
id: player.id,
name: player.name,
createdAt: player.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrIgnore,
), ),
); );
return true; return true;
} }
/// Deletes the player with the given [id] from the database. /* Read */
/// Returns `true` if the player was deleted, `false` if the player did not exist.
Future<bool> deletePlayer({required String playerId}) async {
final query = delete(playerTable)..where((p) => p.id.equals(playerId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Checks if a player with the given [id] exists in the database.
/// Returns `true` if the player exists, `false` otherwise.
Future<bool> playerExists({required String playerId}) async {
final query = select(playerTable)..where((p) => p.id.equals(playerId));
final result = await query.getSingleOrNull();
return result != null;
}
/// Updates the name of the player with the given [playerId] to [newName].
Future<void> updatePlayername({
required String playerId,
required String newName,
}) async {
await (update(playerTable)..where((p) => p.id.equals(playerId))).write(
PlayerTableCompanion(name: Value(newName)),
);
}
/// Retrieves the total count of players in the database. /// Retrieves the total count of players in the database.
Future<int> getPlayerCount() async { Future<int> getPlayerCount() async {
@@ -109,6 +118,218 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
return count ?? 0; return count ?? 0;
} }
/// Checks if a player with the given [playerId] exists in the database.
/// Returns `true` if the player exists, `false` otherwise.
Future<bool> playerExists({required String playerId}) async {
final query = select(playerTable)..where((p) => p.id.equals(playerId));
final result = await query.getSingleOrNull();
return result != null;
}
/// Retrieves all players from the database.
Future<List<Player>> getAllPlayers() async {
final query = select(playerTable);
final result = await query.get();
return result
.map(
(row) => Player(
id: row.id,
name: row.name,
description: row.description,
createdAt: row.createdAt,
nameCount: row.nameCount,
),
)
.toList();
}
/// Retrieves a [Player] by their [id].
Future<Player> getPlayerById({required String playerId}) async {
final query = select(playerTable)..where((p) => p.id.equals(playerId));
final result = await query.getSingle();
return Player(
id: result.id,
name: result.name,
description: result.description,
createdAt: result.createdAt,
nameCount: result.nameCount,
);
}
/* Update */
/// Updates the name of the player with the given [playerId] to [name].
///
/// Keeps the `nameCount` values of the affected name groups consistent:
/// - The renamed player gets a fresh `nameCount` for the new name group.
/// - All players in the previous name group whose `nameCount` was greater
/// than the removed one get decremented by 1, so the numbering stays
/// contiguous (1..N) in `createdAt` order.
/// - If only one player remains in the previous name group, their
/// `nameCount` is reset to 0.
Future<bool> updatePlayerName({
required String playerId,
required String name,
}) async {
return transaction(() async {
final previousPlayer = await (select(
playerTable,
)..where((p) => p.id.equals(playerId))).getSingleOrNull();
if (previousPlayer == null) return false;
final previousName = previousPlayer.name;
final previousCount = previousPlayer.nameCount;
// Determine the nameCount for the renamed player in the new group.
final newNameCount = await _processNameCount(name: name);
final rowsAffected =
await (update(
playerTable,
)..where((p) => p.id.equals(playerId))).write(
PlayerTableCompanion(
name: Value(name),
nameCount: Value(newNameCount),
),
);
// Consolidate the previous name group.
final remainingCount = await getNameCount(name: previousName);
if (remainingCount == 1) {
// Only one player left
await (update(playerTable)..where((p) => p.name.equals(previousName)))
.write(const PlayerTableCompanion(nameCount: Value(0)));
} else if (remainingCount > 1 && previousCount > 0) {
// Shift every player above the gap down by one to keep numbering in order.
await (update(playerTable)..where(
(p) =>
p.name.equals(previousName) &
p.nameCount.isBiggerThanValue(previousCount),
))
.write(
PlayerTableCompanion.custom(
nameCount: playerTable.nameCount - const Constant(1),
),
);
}
return rowsAffected > 0;
});
}
/// Updates the description of the player with the given [playerId] to
/// [description].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updatePlayerDescription({
required String playerId,
required String description,
}) async {
final rowsAffected =
await (update(playerTable)..where((g) => g.id.equals(playerId))).write(
PlayerTableCompanion(description: Value(description)),
);
return rowsAffected > 0;
}
/* Delete */
/// Deletes the player with the given [id] from the database.
/// Returns `true` if the player was deleted, `false` if the player did not exist.
Future<bool> deletePlayer({required String playerId}) async {
final query = delete(playerTable)..where((p) => p.id.equals(playerId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/* Name count management */
/// Retrieves the count of players with the given [name].
/// Returns the highest name count if players with the same name exist,
/// otherwise `null`.
Future<int> getNameCount({required String name}) async {
final query = select(playerTable)..where((p) => p.name.equals(name));
final result = await query.get();
return result.length;
}
/// Updates the nameCount for the player with the given [playerId] to [nameCount].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateNameCount({
required String playerId,
required int nameCount,
}) async {
final query = update(playerTable)..where((p) => p.id.equals(playerId));
final rowsAffected = await query.write(
PlayerTableCompanion(nameCount: Value(nameCount)),
);
return rowsAffected > 0;
}
@visibleForTesting
Future<Player?> getPlayerWithHighestNameCount({required String name}) async {
final query = select(playerTable)
..where((p) => p.name.equals(name))
..orderBy([(p) => OrderingTerm.desc(p.nameCount)])
..limit(1);
final result = await query.getSingleOrNull();
if (result != null) {
return Player(
id: result.id,
name: result.name,
description: result.description,
createdAt: result.createdAt,
nameCount: result.nameCount,
);
}
return null;
}
/// Processes the name count for a new player with the given [name].
///- 0 Player: returning 0
///- 1 Player: returning 2, and initializes the nameCount for the existing player to 1
///- Other: returning the existing count + 1
Future<int> _processNameCount({required String name}) async {
final nameCount = await calculateNameCount(name: name);
if (nameCount == 2) {
// If one other player exists with the same name, initialize the nameCount
await initializeNameCount(name: name);
}
return nameCount;
}
@visibleForTesting
/// Calculates the name count for a new player with the given [name].
/// - 0 Players: Name count is 0
/// - 1 Player: Name count is 2 (since the existing player will be 1)
/// - Other: Name count is the existing count + 1
Future<int> calculateNameCount({required String name}) async {
final count = await getNameCount(name: name);
final int nameCount;
if (count == 0) {
// If no other players exist with the same name, the returned nameCount is 0
nameCount = 0;
} else if (count == 1) {
// If one other player with the name count exists, the returned name count is 2
nameCount = 2;
} else {
// If more than one player exists with the same name, just increment
// the nameCount for the new player
nameCount = count + 1;
}
return nameCount;
}
@visibleForTesting
Future<bool> initializeNameCount({required String name}) async {
final rowsAffected =
await (update(playerTable)..where((p) => p.name.equals(name))).write(
const PlayerTableCompanion(nameCount: Value(1)),
);
return rowsAffected > 0;
}
/// Deletes all players from the database. /// Deletes all players from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`. /// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteAllPlayers() async { Future<bool> deleteAllPlayers() async {

View File

@@ -5,4 +5,12 @@ part of 'player_dao.dart';
// ignore_for_file: type=lint // ignore_for_file: type=lint
mixin _$PlayerDaoMixin on DatabaseAccessor<AppDatabase> { mixin _$PlayerDaoMixin on DatabaseAccessor<AppDatabase> {
$PlayerTableTable get playerTable => attachedDatabase.playerTable; $PlayerTableTable get playerTable => attachedDatabase.playerTable;
PlayerDaoManager get managers => PlayerDaoManager(this);
}
class PlayerDaoManager {
final _$PlayerDaoMixin _db;
PlayerDaoManager(this._db);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
} }

View File

@@ -1,8 +1,8 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:tallee/data/db/database.dart';
import 'package:game_tracker/data/db/tables/player_group_table.dart'; import 'package:tallee/data/db/tables/player_group_table.dart';
import 'package:game_tracker/data/db/tables/player_table.dart'; import 'package:tallee/data/db/tables/player_table.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:tallee/data/models/player.dart';
part 'player_group_dao.g.dart'; part 'player_group_dao.g.dart';
@@ -11,8 +11,7 @@ class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
with _$PlayerGroupDaoMixin { with _$PlayerGroupDaoMixin {
PlayerGroupDao(super.db); PlayerGroupDao(super.db);
/// No need for a groupHasPlayers method since the members attribute is /* Create */
/// not nullable
/// Adds a [player] to a group with the given [groupId]. /// Adds a [player] to a group with the given [groupId].
/// If the player is already in the group, no action is taken. /// If the player is already in the group, no action is taken.
@@ -27,16 +26,17 @@ class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
} }
if (!await db.playerDao.playerExists(playerId: player.id)) { if (!await db.playerDao.playerExists(playerId: player.id)) {
db.playerDao.addPlayer(player: player); await db.playerDao.addPlayer(player: player);
} }
await into(playerGroupTable).insert( await into(playerGroupTable).insert(
PlayerGroupTableCompanion.insert(playerId: player.id, groupId: groupId), PlayerGroupTableCompanion.insert(playerId: player.id, groupId: groupId),
); );
return true; return true;
} }
/* Read */
/// Retrieves all players belonging to a specific group by [groupId]. /// Retrieves all players belonging to a specific group by [groupId].
Future<List<Player>> getPlayersOfGroup({required String groupId}) async { Future<List<Player>> getPlayersOfGroup({required String groupId}) async {
final query = select(playerGroupTable) final query = select(playerGroupTable)
@@ -53,18 +53,6 @@ class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
return groupMembers; return groupMembers;
} }
/// Removes a player from a group based on [playerId] and [groupId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removePlayerFromGroup({
required String playerId,
required String groupId,
}) async {
final query = delete(playerGroupTable)
..where((p) => p.playerId.equals(playerId) & p.groupId.equals(groupId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Checks if a player with [playerId] is in the group with [groupId]. /// Checks if a player with [playerId] is in the group with [groupId].
/// Returns `true` if the player is in the group, otherwise `false`. /// Returns `true` if the player is in the group, otherwise `false`.
Future<bool> isPlayerInGroup({ Future<bool> isPlayerInGroup({
@@ -76,4 +64,65 @@ class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
final result = await query.getSingleOrNull(); final result = await query.getSingleOrNull();
return result != null; return result != null;
} }
/* Update */
/// Replaces all players in a group with the provided list of players.
/// Removes all existing players from the group and adds the new players.
/// Also adds any new players to the player table if they don't exist.
/// Returns `true` if the group exists and players were replaced, `false` otherwise.
Future<bool> replaceGroupPlayers({
required String groupId,
required List<Player> newPlayers,
}) async {
if (!await db.groupDao.groupExists(groupId: groupId)) return false;
if (newPlayers.isEmpty) return false;
await db.transaction(() async {
// Remove all existing players from the group
final deleteQuery = delete(db.playerGroupTable)
..where((p) => p.groupId.equals(groupId));
await deleteQuery.go();
// Add new players to the player table if they don't exist
await Future.wait(
newPlayers.map((player) async {
if (!await db.playerDao.playerExists(playerId: player.id)) {
await db.playerDao.addPlayer(player: player);
}
}),
);
// Add the new players to the group
await db.batch(
(b) => b.insertAll(
db.playerGroupTable,
newPlayers
.map(
(player) => PlayerGroupTableCompanion.insert(
playerId: player.id,
groupId: groupId,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
});
return true;
}
/* Delete */
/// Removes a player from a group based on [playerId] and [groupId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removePlayerFromGroup({
required String playerId,
required String groupId,
}) async {
final query = delete(playerGroupTable)
..where((p) => p.playerId.equals(playerId) & p.groupId.equals(groupId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
} }

View File

@@ -8,4 +8,19 @@ mixin _$PlayerGroupDaoMixin on DatabaseAccessor<AppDatabase> {
$GroupTableTable get groupTable => attachedDatabase.groupTable; $GroupTableTable get groupTable => attachedDatabase.groupTable;
$PlayerGroupTableTable get playerGroupTable => $PlayerGroupTableTable get playerGroupTable =>
attachedDatabase.playerGroupTable; attachedDatabase.playerGroupTable;
PlayerGroupDaoManager get managers => PlayerGroupDaoManager(this);
}
class PlayerGroupDaoManager {
final _$PlayerGroupDaoMixin _db;
PlayerGroupDaoManager(this._db);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
$$GroupTableTableTableManager get groupTable =>
$$GroupTableTableTableManager(_db.attachedDatabase, _db.groupTable);
$$PlayerGroupTableTableTableManager get playerGroupTable =>
$$PlayerGroupTableTableTableManager(
_db.attachedDatabase,
_db.playerGroupTable,
);
} }

View File

@@ -1,46 +1,41 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:tallee/data/db/database.dart';
import 'package:game_tracker/data/db/tables/player_match_table.dart'; import 'package:tallee/data/db/tables/player_match_table.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:tallee/data/db/tables/team_table.dart';
import 'package:tallee/data/models/player.dart';
part 'player_match_dao.g.dart'; part 'player_match_dao.g.dart';
@DriftAccessor(tables: [PlayerMatchTable]) @DriftAccessor(tables: [PlayerMatchTable, TeamTable])
class PlayerMatchDao extends DatabaseAccessor<AppDatabase> class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
with _$PlayerMatchDaoMixin { with _$PlayerMatchDaoMixin {
PlayerMatchDao(super.db); PlayerMatchDao(super.db);
/* Create */
/// Associates a player with a match by inserting a record into the /// Associates a player with a match by inserting a record into the
/// [PlayerMatchTable]. /// [PlayerMatchTable]. Optionally associates with a team and sets initial score.
Future<void> addPlayerToMatch({ Future<bool> addPlayerToMatch({
required String matchId, required String matchId,
required String playerId, required String playerId,
String? teamId,
}) async { }) async {
await into(playerMatchTable).insert( final rowsAffected = await into(playerMatchTable).insert(
PlayerMatchTableCompanion.insert(playerId: playerId, matchId: matchId), PlayerMatchTableCompanion.insert(
mode: InsertMode.insertOrIgnore, playerId: playerId,
matchId: matchId,
teamId: Value(teamId),
),
mode: InsertMode.insertOrReplace,
); );
return rowsAffected > 0;
} }
/// Retrieves a list of [Player]s associated with the given [matchId]. /* Read */
/// Returns null if no players are found.
Future<List<Player>?> getPlayersOfMatch({required String matchId}) async {
final result = await (select(
playerMatchTable,
)..where((p) => p.matchId.equals(matchId))).get();
if (result.isEmpty) return null;
final futures = result.map(
(row) => db.playerDao.getPlayerById(playerId: row.playerId),
);
final players = await Future.wait(futures);
return players;
}
/// Checks if there are any players associated with the given [matchId]. /// Checks if there are any players associated with the given [matchId].
/// Returns `true` if there are players, otherwise `false`. /// Returns `true` if there are players, otherwise `false`.
Future<bool> matchHasPlayers({required String matchId}) async { Future<bool> hasMatchPlayers({required String matchId}) async {
final count = final count =
await (selectOnly(playerMatchTable) await (selectOnly(playerMatchTable)
..where(playerMatchTable.matchId.equals(matchId)) ..where(playerMatchTable.matchId.equals(matchId))
@@ -66,37 +61,85 @@ class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
return (count ?? 0) > 0; return (count ?? 0) > 0;
} }
/// Removes the association of a player with a match by deleting the record /// Retrieves a list of [Player]s associated with the given [matchId].
/// from the [PlayerMatchTable]. /// Returns empty list if no players are found.
/// Returns `true` if more than 0 rows were affected, otherwise `false`. Future<List<Player>> getPlayersOfMatch({required String matchId}) async {
Future<bool> removePlayerFromMatch({ final result = await (select(
playerMatchTable,
)..where((p) => p.matchId.equals(matchId))).get();
if (result.isEmpty) return [];
final futures = result.map(
(row) => db.playerDao.getPlayerById(playerId: row.playerId),
);
final players = await Future.wait(futures);
return players;
}
/// Retrieves a list of [Player]s associated with a specific team in a match.
/// Returns empty list if no players are found for the team in the match.
Future<List<Player>> getPlayersOfTeamInMatch({
required String matchId,
required String teamId,
}) async {
final result =
await (select(playerMatchTable)
..where((p) => p.matchId.equals(matchId))
..where((p) => p.teamId.equals(teamId)))
.get();
if (result.isEmpty) return [];
final futures = result.map(
(row) => db.playerDao.getPlayerById(playerId: row.playerId),
);
final players = await Future.wait(futures);
return players;
}
/* Updated */
/// Updates the team for a player in a match.
/// Returns `true` if the update was successful, otherwise `false`.
Future<bool> updatePlayersTeam({
required String matchId, required String matchId,
required String playerId, required String playerId,
required String? teamId,
}) async { }) async {
final query = delete(playerMatchTable) final rowsAffected =
..where((pg) => pg.matchId.equals(matchId)) await (update(playerMatchTable)..where(
..where((pg) => pg.playerId.equals(playerId)); (p) => p.matchId.equals(matchId) & p.playerId.equals(playerId),
final rowsAffected = await query.go(); ))
.write(PlayerMatchTableCompanion(teamId: Value(teamId)));
return rowsAffected > 0; return rowsAffected > 0;
} }
/// Updates the players associated with a match based on the provided /// Updates the players associated with a match based on the provided
/// [newPlayer] list. It adds new players and removes players that are no /// [player] list. It adds new players and removes players that are no
/// longer associated with the match. /// longer associated with the match.
Future<void> updatePlayersFromMatch({ Future<bool> updateMatchPlayers({
required String matchId, required String matchId,
required List<Player> newPlayer, required List<Player> player,
}) async { }) async {
if (player.isEmpty) return false;
final currentPlayers = await getPlayersOfMatch(matchId: matchId); final currentPlayers = await getPlayersOfMatch(matchId: matchId);
// Create sets of player IDs for easy comparison // Create sets of player IDs for easy comparison
final currentPlayerIds = currentPlayers?.map((p) => p.id).toSet() ?? {}; final currentPlayerIds = currentPlayers.map((p) => p.id).toSet();
final newPlayerIdsSet = newPlayer.map((p) => p.id).toSet(); final newPlayerIdsSet = player.map((p) => p.id).toSet();
// Are the current and new player identical?
if (currentPlayerIds.containsAll(newPlayerIdsSet) &&
newPlayerIdsSet.containsAll(currentPlayerIds)) {
return false;
}
// Determine players to add and remove // Determine players to add and remove
final playersToAdd = newPlayerIdsSet.difference(currentPlayerIds); final playersToAdd = newPlayerIdsSet.difference(currentPlayerIds);
final playersToRemove = currentPlayerIds.difference(newPlayerIdsSet); final playersToRemove = currentPlayerIds.difference(newPlayerIdsSet);
db.transaction(() async { await db.transaction(() async {
// Remove old players // Remove old players
if (playersToRemove.isNotEmpty) { if (playersToRemove.isNotEmpty) {
await (delete(playerMatchTable)..where( await (delete(playerMatchTable)..where(
@@ -126,5 +169,22 @@ class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
); );
} }
}); });
return true;
}
/* Delete */
/// Removes the association of a player with a match by deleting the record
/// from the [PlayerMatchTable].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removePlayerFromMatch({
required String matchId,
required String playerId,
}) async {
final query = delete(playerMatchTable)
..where((pg) => pg.matchId.equals(matchId))
..where((pg) => pg.playerId.equals(playerId));
final rowsAffected = await query.go();
return rowsAffected > 0;
} }
} }

View File

@@ -5,7 +5,31 @@ part of 'player_match_dao.dart';
// ignore_for_file: type=lint // ignore_for_file: type=lint
mixin _$PlayerMatchDaoMixin on DatabaseAccessor<AppDatabase> { mixin _$PlayerMatchDaoMixin on DatabaseAccessor<AppDatabase> {
$PlayerTableTable get playerTable => attachedDatabase.playerTable; $PlayerTableTable get playerTable => attachedDatabase.playerTable;
$GameTableTable get gameTable => attachedDatabase.gameTable;
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable; $MatchTableTable get matchTable => attachedDatabase.matchTable;
$TeamTableTable get teamTable => attachedDatabase.teamTable;
$PlayerMatchTableTable get playerMatchTable => $PlayerMatchTableTable get playerMatchTable =>
attachedDatabase.playerMatchTable; attachedDatabase.playerMatchTable;
PlayerMatchDaoManager get managers => PlayerMatchDaoManager(this);
}
class PlayerMatchDaoManager {
final _$PlayerMatchDaoMixin _db;
PlayerMatchDaoManager(this._db);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
$$GameTableTableTableManager get gameTable =>
$$GameTableTableTableManager(_db.attachedDatabase, _db.gameTable);
$$GroupTableTableTableManager get groupTable =>
$$GroupTableTableTableManager(_db.attachedDatabase, _db.groupTable);
$$MatchTableTableTableManager get matchTable =>
$$MatchTableTableTableManager(_db.attachedDatabase, _db.matchTable);
$$TeamTableTableTableManager get teamTable =>
$$TeamTableTableTableManager(_db.attachedDatabase, _db.teamTable);
$$PlayerMatchTableTableTableManager get playerMatchTable =>
$$PlayerMatchTableTableTableManager(
_db.attachedDatabase,
_db.playerMatchTable,
);
} }

View File

@@ -0,0 +1,402 @@
import 'dart:async';
import 'package:drift/drift.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/db/tables/score_entry_table.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/data/models/score_entry.dart';
part 'score_entry_dao.g.dart';
@DriftAccessor(tables: [ScoreEntryTable])
class ScoreEntryDao extends DatabaseAccessor<AppDatabase>
with _$ScoreEntryDaoMixin {
ScoreEntryDao(super.db);
/* Create */
/// Adds a score entry to the database.
Future<void> addScore({
required String playerId,
required String matchId,
required ScoreEntry entry,
}) async {
await into(scoreEntryTable).insert(
ScoreEntryTableCompanion.insert(
playerId: playerId,
matchId: matchId,
roundNumber: entry.roundNumber,
score: entry.score,
change: entry.change,
),
mode: InsertMode.insertOrReplace,
);
}
Future<void> addScoresAsList({
required List<ScoreEntry> entrys,
required String playerId,
required String matchId,
}) async {
if (entrys.isEmpty) return;
final entries = entrys
.map(
(score) => ScoreEntryTableCompanion.insert(
playerId: playerId,
matchId: matchId,
roundNumber: score.roundNumber,
score: score.score,
change: score.change,
),
)
.toList();
await batch((batch) {
batch.insertAll(
scoreEntryTable,
entries,
mode: InsertMode.insertOrReplace,
);
});
}
/* Read */
/// Retrieves the score for a specific round.
Future<ScoreEntry?> getScore({
required String playerId,
required String matchId,
int roundNumber = 0,
}) async {
final query = select(scoreEntryTable)
..where(
(s) =>
s.playerId.equals(playerId) &
s.matchId.equals(matchId) &
s.roundNumber.equals(roundNumber),
);
final result = await query.getSingleOrNull();
if (result == null) return null;
return ScoreEntry(
roundNumber: result.roundNumber,
score: result.score,
change: result.change,
);
}
/// Retrieves all scores for a specific match.
Future<Map<String, ScoreEntry?>> getAllMatchScores({
required String matchId,
}) async {
final query = select(scoreEntryTable)
..where((s) => s.matchId.equals(matchId));
final result = await query.get();
final Map<String, ScoreEntry?> scoresByPlayer = {};
for (final row in result) {
final score = ScoreEntry(
roundNumber: row.roundNumber,
score: row.score,
change: row.change,
);
scoresByPlayer[row.playerId] = score;
}
return scoresByPlayer;
}
/// Retrieves all scores for a specific player in a match.
Future<List<ScoreEntry>> getAllPlayerScoresInMatch({
required String playerId,
required String matchId,
}) async {
final query = select(scoreEntryTable)
..where((s) => s.playerId.equals(playerId) & s.matchId.equals(matchId))
..orderBy([(s) => OrderingTerm.asc(s.roundNumber)]);
final result = await query.get();
return result
.map(
(row) => ScoreEntry(
roundNumber: row.roundNumber,
score: row.score,
change: row.change,
),
)
.toList()
..sort(
(scoreA, scoreB) => scoreA.roundNumber.compareTo(scoreB.roundNumber),
);
}
/// Gets the highest (latest) round number for a match.
/// Returns `null` if there are no scores for the match.
Future<int?> getLatestRoundNumber({required String matchId}) async {
final query = selectOnly(scoreEntryTable)
..where(scoreEntryTable.matchId.equals(matchId))
..addColumns([scoreEntryTable.roundNumber.max()]);
final result = await query.getSingle();
return result.read(scoreEntryTable.roundNumber.max());
}
/// Aggregates the total score for a player in a match by summing all their
/// score entry changes. Returns `0` if there are no scores for the player
/// in the match.
Future<int> getTotalScoreForPlayer({
required String playerId,
required String matchId,
}) async {
final scores = await getAllPlayerScoresInMatch(
playerId: playerId,
matchId: matchId,
);
if (scores.isEmpty) return 0;
// Return the sum of all score changes
return scores.fold<int>(0, (sum, element) => sum + element.change);
}
/* Update */
/// Updates a score entry.
Future<bool> updateScore({
required String playerId,
required String matchId,
required ScoreEntry entry,
}) async {
final rowsAffected =
await (update(scoreEntryTable)..where(
(s) =>
s.playerId.equals(playerId) &
s.matchId.equals(matchId) &
s.roundNumber.equals(entry.roundNumber),
))
.write(
ScoreEntryTableCompanion(
score: Value(entry.score),
change: Value(entry.change),
),
);
return rowsAffected > 0;
}
/* Delete */
/// Deletes a score entry.
Future<bool> deleteScore({
required String playerId,
required String matchId,
int roundNumber = 0,
}) async {
final query = delete(scoreEntryTable)
..where(
(s) =>
s.playerId.equals(playerId) &
s.matchId.equals(matchId) &
s.roundNumber.equals(roundNumber),
);
final rowsAffected = await query.go();
return rowsAffected > 0;
}
Future<bool> deleteAllScoresForMatch({required String matchId}) async {
final query = delete(scoreEntryTable)
..where((s) => s.matchId.equals(matchId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
Future<bool> deleteAllScoresForPlayerInMatch({
required String matchId,
required String playerId,
}) async {
final query = delete(scoreEntryTable)
..where((s) => s.playerId.equals(playerId) & s.matchId.equals(matchId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/* Winner handling */
Future<bool> hasWinner({required String matchId}) async {
return await getWinner(matchId: matchId) != null;
}
// Setting the winner for a game and clearing previous winner if exists.
Future<bool> setWinner({
required String matchId,
required String playerId,
}) async {
// Clear previous winner if exists
await deleteAllScoresForMatch(matchId: matchId);
// Set the winner's score to 1
final rowsAffected = await into(scoreEntryTable).insert(
ScoreEntryTableCompanion.insert(
playerId: playerId,
matchId: matchId,
roundNumber: 0,
score: 1,
change: 0,
),
mode: InsertMode.insertOrReplace,
);
return rowsAffected > 0;
}
/// Retrieves the winner of a match by looking for a score entry where score
/// is 1. Returns `null` if no player found, else the first with the score.
Future<Player?> getWinner({required String matchId}) async {
final query =
select(scoreEntryTable).join([
innerJoin(
db.playerTable,
db.playerTable.id.equalsExp(scoreEntryTable.playerId),
),
])..where(
scoreEntryTable.matchId.equals(matchId) &
scoreEntryTable.score.equals(1),
);
final result = await query.get();
if (result.isEmpty) return null;
final playerData = result.first.readTable(db.playerTable);
return Player(
id: playerData.id,
name: playerData.name,
createdAt: playerData.createdAt,
description: playerData.description,
);
}
/// Removes the winner of a match.
///
/// Returns `true` if the winner was removed, `false` if there are multiple
/// scores or if the winner cannot be removed.
Future<bool> removeWinner({required String matchId}) async {
return await deleteAllScoresForMatch(matchId: matchId);
}
/* multiple winners handling */
/// Sets the winners for a match.
///
/// Returns `true` if more than 0 rows were affected
Future<bool> setWinners({
required List<Player> winners,
required String matchId,
}) async {
// Clear previous winners if exists
await deleteAllScoresForMatch(matchId: matchId);
if (winners.isEmpty) return false;
await batch((batch) {
batch.insertAll(
scoreEntryTable,
winners
.map(
(player) => ScoreEntryTableCompanion.insert(
playerId: player.id,
matchId: matchId,
roundNumber: 0,
score: 1,
change: 0,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
);
});
return true;
}
/* Loser handling */
Future<bool> hasLoser({required String matchId}) async {
return await getLoser(matchId: matchId) != null;
}
// Setting the looser for a game and clearing previous looser if exists.
Future<bool> setLoser({
required String matchId,
required String playerId,
}) async {
// Clear previous loosers if exists
deleteAllScoresForMatch(matchId: matchId);
// Set the loosers score to 0
final rowsAffected = await into(scoreEntryTable).insert(
ScoreEntryTableCompanion.insert(
playerId: playerId,
matchId: matchId,
roundNumber: 0,
score: 0,
change: 0,
),
mode: InsertMode.insertOrReplace,
);
return rowsAffected > 0;
}
/// Retrieves the looser of a match by looking for a score entry where score
/// is 0. Returns `null` if no player found, else the first with the score.
Future<Player?> getLoser({required String matchId}) async {
final query =
select(scoreEntryTable).join([
innerJoin(
db.playerTable,
db.playerTable.id.equalsExp(scoreEntryTable.playerId),
),
])..where(
scoreEntryTable.matchId.equals(matchId) &
scoreEntryTable.score.equals(0),
);
final result = await query.get();
if (result.isEmpty) return null;
final playerData = result.first.readTable(db.playerTable);
return Player(
id: playerData.id,
name: playerData.name,
createdAt: playerData.createdAt,
description: playerData.description,
);
}
/// Removes the looser of a match.
///
/// Returns `true` if the looser was removed, `false` if there are multiple
/// scores or if the looser cannot be removed.
Future<bool> removeLoser({required String matchId}) async {
final scores = await getAllMatchScores(matchId: matchId);
if (scores.length > 1) {
return false;
} else {
return await deleteAllScoresForMatch(matchId: matchId);
}
}
/* placement handling */
/// Sets the placement for each player in a match.
/// The highest score is assigned to the first player, the second highest to the second player, and so on.
Future<void> setPlacements({
required String matchId,
required List<Player> players,
}) async {
for (int i = 0; i < players.length; i++) {
await db.scoreEntryDao.addScore(
matchId: matchId,
playerId: players[i].id,
entry: ScoreEntry(roundNumber: 0, score: players.length - i, change: 0),
);
}
}
}

View File

@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'score_entry_dao.dart';
// ignore_for_file: type=lint
mixin _$ScoreEntryDaoMixin on DatabaseAccessor<AppDatabase> {
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
$GameTableTable get gameTable => attachedDatabase.gameTable;
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable;
$ScoreEntryTableTable get scoreEntryTable => attachedDatabase.scoreEntryTable;
ScoreEntryDaoManager get managers => ScoreEntryDaoManager(this);
}
class ScoreEntryDaoManager {
final _$ScoreEntryDaoMixin _db;
ScoreEntryDaoManager(this._db);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
$$GameTableTableTableManager get gameTable =>
$$GameTableTableTableManager(_db.attachedDatabase, _db.gameTable);
$$GroupTableTableTableManager get groupTable =>
$$GroupTableTableTableManager(_db.attachedDatabase, _db.groupTable);
$$MatchTableTableTableManager get matchTable =>
$$MatchTableTableTableManager(_db.attachedDatabase, _db.matchTable);
$$ScoreEntryTableTableTableManager get scoreEntryTable =>
$$ScoreEntryTableTableTableManager(
_db.attachedDatabase,
_db.scoreEntryTable,
);
}

182
lib/data/dao/team_dao.dart Normal file
View File

@@ -0,0 +1,182 @@
import 'package:drift/drift.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/db/tables/player_match_table.dart';
import 'package:tallee/data/db/tables/team_table.dart';
import 'package:tallee/data/models/player.dart';
import 'package:tallee/data/models/team.dart';
part 'team_dao.g.dart';
@DriftAccessor(tables: [TeamTable, PlayerMatchTable])
class TeamDao extends DatabaseAccessor<AppDatabase> with _$TeamDaoMixin {
TeamDao(super.db);
/* Create */
/// Adds a new [team] to the database.
/// Returns `true` if the team was added, `false` otherwise.
Future<bool> addTeam({required Team team, required String matchId}) async {
if (await teamExists(teamId: team.id)) return false;
await into(teamTable).insert(
TeamTableCompanion.insert(
id: team.id,
name: team.name,
createdAt: team.createdAt,
),
mode: InsertMode.insertOrReplace,
);
await db.batch((batch) async {
for (final player in team.members) {
await into(playerMatchTable).insert(
PlayerMatchTableCompanion.insert(
playerId: player.id,
matchId: matchId,
teamId: Value(team.id),
),
mode: InsertMode.insertOrReplace,
);
}
});
return true;
}
/// Adds multiple [teams] to the database in a batch operation.
Future<bool> addTeamsAsList({
required List<Team> teams,
required String matchId,
}) async {
if (teams.isEmpty) return false;
await db.batch(
(b) => b.insertAll(
teamTable,
teams
.map(
(team) => TeamTableCompanion.insert(
id: team.id,
name: team.name,
createdAt: team.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrIgnore,
),
);
for (final team in teams) {
await db.batch((batch) async {
for (final player in team.members) {
await into(db.playerMatchTable).insert(
PlayerMatchTableCompanion.insert(
playerId: player.id,
matchId: matchId,
teamId: Value(team.id),
),
mode: InsertMode.insertOrReplace,
);
}
});
}
return true;
}
/* Read */
/// Retrieves the total count of teams in the database.
Future<int> getTeamCount() async {
final count =
await (selectOnly(teamTable)..addColumns([teamTable.id.count()]))
.map((row) => row.read(teamTable.id.count()))
.getSingle();
return count ?? 0;
}
/// Checks if a team with the given [teamId] exists in the database.
/// Returns `true` if the team exists, `false` otherwise.
Future<bool> teamExists({required String teamId}) async {
final query = select(teamTable)..where((t) => t.id.equals(teamId));
final result = await query.getSingleOrNull();
return result != null;
}
/// Retrieves all teams from the database.
Future<List<Team>> getAllTeams() async {
final query = select(teamTable);
final result = await query.get();
return Future.wait(
result.map((row) async {
final members = await _getTeamMembers(teamId: row.id);
return Team(
id: row.id,
name: row.name,
createdAt: row.createdAt,
members: members,
);
}),
);
}
/// Retrieves a [Team] by its [teamId], including its members.
Future<Team> getTeamById({required String teamId}) async {
final query = select(teamTable)..where((t) => t.id.equals(teamId));
final result = await query.getSingle();
final members = await _getTeamMembers(teamId: teamId);
return Team(
id: result.id,
name: result.name,
createdAt: result.createdAt,
members: members,
);
}
/// Helper method to get team members from PlayerMatchTable.
Future<List<Player>> _getTeamMembers({required String teamId}) async {
// Get all player_match entries with this teamId
final playerMatchQuery = select(db.playerMatchTable)
..where((pm) => pm.teamId.equals(teamId));
final playerMatches = await playerMatchQuery.get();
if (playerMatches.isEmpty) return [];
// Get unique player IDs
final playerIds = playerMatches.map((pm) => pm.playerId).toSet();
// Fetch all players
final players = await Future.wait(
playerIds.map((id) => db.playerDao.getPlayerById(playerId: id)),
);
return players;
}
/* Update */
/// Updates the name of the team with the given [teamId].
Future<bool> updateTeamName({
required String teamId,
required String name,
}) async {
final rowsAffected =
await (update(teamTable)..where((t) => t.id.equals(teamId))).write(
TeamTableCompanion(name: Value(name)),
);
return rowsAffected > 0;
}
/* Delete */
/// Deletes all teams from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteAllTeams() async {
final query = delete(teamTable);
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Deletes the team with the given [teamId] from the database.
/// Returns `true` if the team was deleted, `false` otherwise.
Future<bool> deleteTeam({required String teamId}) async {
final query = delete(teamTable)..where((t) => t.id.equals(teamId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
}

View File

@@ -0,0 +1,35 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'team_dao.dart';
// ignore_for_file: type=lint
mixin _$TeamDaoMixin on DatabaseAccessor<AppDatabase> {
$TeamTableTable get teamTable => attachedDatabase.teamTable;
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
$GameTableTable get gameTable => attachedDatabase.gameTable;
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable;
$PlayerMatchTableTable get playerMatchTable =>
attachedDatabase.playerMatchTable;
TeamDaoManager get managers => TeamDaoManager(this);
}
class TeamDaoManager {
final _$TeamDaoMixin _db;
TeamDaoManager(this._db);
$$TeamTableTableTableManager get teamTable =>
$$TeamTableTableTableManager(_db.attachedDatabase, _db.teamTable);
$$PlayerTableTableTableManager get playerTable =>
$$PlayerTableTableTableManager(_db.attachedDatabase, _db.playerTable);
$$GameTableTableTableManager get gameTable =>
$$GameTableTableTableManager(_db.attachedDatabase, _db.gameTable);
$$GroupTableTableTableManager get groupTable =>
$$GroupTableTableTableManager(_db.attachedDatabase, _db.groupTable);
$$MatchTableTableTableManager get matchTable =>
$$MatchTableTableTableManager(_db.attachedDatabase, _db.matchTable);
$$PlayerMatchTableTableTableManager get playerMatchTable =>
$$PlayerMatchTableTableTableManager(
_db.attachedDatabase,
_db.playerMatchTable,
);
}

View File

@@ -1,18 +1,22 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:drift_flutter/drift_flutter.dart'; import 'package:drift_flutter/drift_flutter.dart';
import 'package:game_tracker/data/dao/group_dao.dart';
import 'package:game_tracker/data/dao/group_match_dao.dart';
import 'package:game_tracker/data/dao/match_dao.dart';
import 'package:game_tracker/data/dao/player_dao.dart';
import 'package:game_tracker/data/dao/player_group_dao.dart';
import 'package:game_tracker/data/dao/player_match_dao.dart';
import 'package:game_tracker/data/db/tables/group_match_table.dart';
import 'package:game_tracker/data/db/tables/group_table.dart';
import 'package:game_tracker/data/db/tables/match_table.dart';
import 'package:game_tracker/data/db/tables/player_group_table.dart';
import 'package:game_tracker/data/db/tables/player_match_table.dart';
import 'package:game_tracker/data/db/tables/player_table.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:tallee/data/dao/game_dao.dart';
import 'package:tallee/data/dao/group_dao.dart';
import 'package:tallee/data/dao/match_dao.dart';
import 'package:tallee/data/dao/player_dao.dart';
import 'package:tallee/data/dao/player_group_dao.dart';
import 'package:tallee/data/dao/player_match_dao.dart';
import 'package:tallee/data/dao/score_entry_dao.dart';
import 'package:tallee/data/dao/team_dao.dart';
import 'package:tallee/data/db/tables/game_table.dart';
import 'package:tallee/data/db/tables/group_table.dart';
import 'package:tallee/data/db/tables/match_table.dart';
import 'package:tallee/data/db/tables/player_group_table.dart';
import 'package:tallee/data/db/tables/player_match_table.dart';
import 'package:tallee/data/db/tables/player_table.dart';
import 'package:tallee/data/db/tables/score_entry_table.dart';
import 'package:tallee/data/db/tables/team_table.dart';
part 'database.g.dart'; part 'database.g.dart';
@@ -23,7 +27,9 @@ part 'database.g.dart';
MatchTable, MatchTable,
PlayerGroupTable, PlayerGroupTable,
PlayerMatchTable, PlayerMatchTable,
GroupMatchTable, GameTable,
TeamTable,
ScoreEntryTable,
], ],
daos: [ daos: [
PlayerDao, PlayerDao,
@@ -31,7 +37,9 @@ part 'database.g.dart';
MatchDao, MatchDao,
PlayerGroupDao, PlayerGroupDao,
PlayerMatchDao, PlayerMatchDao,
GroupMatchDao, GameDao,
ScoreEntryDao,
TeamDao,
], ],
) )
class AppDatabase extends _$AppDatabase { class AppDatabase extends _$AppDatabase {

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
import 'package:drift/drift.dart';
class GameTable extends Table {
TextColumn get id => text()();
TextColumn get name => text()();
TextColumn get ruleset => text()();
TextColumn get description => text()();
TextColumn get color => text()();
TextColumn get icon => text()();
DateTimeColumn get createdAt => dateTime()();
@override
Set<Column<Object>> get primaryKey => {id};
}

View File

@@ -1,13 +0,0 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/tables/group_table.dart';
import 'package:game_tracker/data/db/tables/match_table.dart';
class GroupMatchTable extends Table {
TextColumn get groupId =>
text().references(GroupTable, #id, onDelete: KeyAction.cascade)();
TextColumn get matchId =>
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
@override
Set<Column<Object>> get primaryKey => {groupId, matchId};
}

View File

@@ -3,6 +3,7 @@ import 'package:drift/drift.dart';
class GroupTable extends Table { class GroupTable extends Table {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get description => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
@override @override

View File

@@ -1,10 +1,20 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:tallee/data/db/tables/game_table.dart';
import 'package:tallee/data/db/tables/group_table.dart';
class MatchTable extends Table { class MatchTable extends Table {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get gameId =>
text().references(GameTable, #id, onDelete: KeyAction.cascade)();
// Nullable if there is no group associated with the match
// onDelete: If a group gets deleted, groupId in the match gets set to null
TextColumn get groupId => text()
.references(GroupTable, #id, onDelete: KeyAction.setNull)
.nullable()();
TextColumn get name => text()(); TextColumn get name => text()();
late final winnerId = text().nullable()(); TextColumn get notes => text()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
DateTimeColumn get endedAt => dateTime().nullable()();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -1,6 +1,6 @@
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/tables/group_table.dart'; import 'package:tallee/data/db/tables/group_table.dart';
import 'package:game_tracker/data/db/tables/player_table.dart'; import 'package:tallee/data/db/tables/player_table.dart';
class PlayerGroupTable extends Table { class PlayerGroupTable extends Table {
TextColumn get playerId => TextColumn get playerId =>

Some files were not shown because too many files have changed in this diff Show More