Compare commits
1 Commits
feature/11
...
c7b4623198
| Author | SHA1 | Date | |
|---|---|---|---|
| c7b4623198 |
@@ -6,23 +6,17 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install jq
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y jq
|
|
||||||
|
|
||||||
- name: Install Flutter (wget)
|
- name: Install Flutter (wget)
|
||||||
run: |
|
run: |
|
||||||
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
wget --show-progress --progress=bar:force:noscroll:giga https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
||||||
tar xf flutter_linux_3.38.2-stable.tar.xz
|
tar xf flutter_linux_3.38.2-stable.tar.xz
|
||||||
# Set Git safe directory for Flutter path
|
|
||||||
git config --global --add safe.directory "$(pwd)/flutter"
|
git config --global --add safe.directory "$(pwd)/flutter"
|
||||||
# Set Flutter path
|
echo "$(pwd)/flutter/bin" >> $GITEA_PATH
|
||||||
echo "$(pwd)/flutter/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
@@ -32,26 +26,22 @@ jobs:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
RUNNER_TOOL_CACHE: /toolcache
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get install -y jq
|
|
||||||
|
|
||||||
- name: Install Flutter (wget)
|
- name: Install Flutter (wget)
|
||||||
run: |
|
run: |
|
||||||
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
wget --show-progress --progress=bar:force:noscroll:giga https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
||||||
tar xf flutter_linux_3.38.2-stable.tar.xz
|
tar xf flutter_linux_3.38.2-stable.tar.xz
|
||||||
# Set Git safe directory for Flutter path
|
|
||||||
git config --global --add safe.directory "$(pwd)/flutter"
|
git config --global --add safe.directory "$(pwd)/flutter"
|
||||||
# Set Flutter path
|
echo "$(pwd)/flutter/bin" >> $GITEA_PATH
|
||||||
echo "$(pwd)/flutter/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Get dependencies
|
- name: Get dependencies
|
||||||
run: flutter pub get
|
run: flutter pub get
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: flutter test
|
run: flutter test
|
||||||
|
|||||||
@@ -7,44 +7,95 @@ 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
|
- name: Install Flutter (wget)
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
wget --show-progress --progress=bar:force:noscroll:giga https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
||||||
apt-get install -y jq
|
tar xf flutter_linux_3.38.2-stable.tar.xz
|
||||||
|
git config --global --add safe.directory "$(pwd)/flutter"
|
||||||
|
echo "$(pwd)/flutter/bin" >> $GITEA_PATH
|
||||||
|
|
||||||
|
- name: Get dependencies
|
||||||
|
run: flutter pub get
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: flutter test
|
||||||
|
|
||||||
|
format:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Install Flutter (wget)
|
- name: Install Flutter (wget)
|
||||||
run: |
|
run: |
|
||||||
wget https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
wget --show-progress --progress=bar:force:noscroll:giga https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.38.2-stable.tar.xz
|
||||||
tar xf flutter_linux_3.38.2-stable.tar.xz
|
tar xf flutter_linux_3.38.2-stable.tar.xz
|
||||||
# Set Git safe directory for Flutter path
|
|
||||||
git config --global --add safe.directory "$(pwd)/flutter"
|
git config --global --add safe.directory "$(pwd)/flutter"
|
||||||
# Set Flutter path
|
echo "$(pwd)/flutter/bin" >> $GITEA_PATH
|
||||||
echo "$(pwd)/flutter/bin" >> $GITHUB_PATH
|
|
||||||
|
|
||||||
- name: Get & upgrade dependencies
|
- name: Get dependencies
|
||||||
run: |
|
run: flutter pub get
|
||||||
flutter pub get
|
|
||||||
flutter pub upgrade --major-versions
|
|
||||||
|
|
||||||
- name: Auto-format
|
- name: Check code format
|
||||||
run: |
|
id: check_format
|
||||||
dart format lib
|
continue-on-error: true
|
||||||
dart fix --apply lib
|
run: flutter analyze lib test
|
||||||
|
|
||||||
# Needs credentials, push access and the right files need to be staged
|
- name: Format code
|
||||||
- name: Commit Changes
|
if: steps.check_format.outcome == 'failure'
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
git config --global user.name "Gitea Actions"
|
git fetch origin ${{ gitea.head_ref }}
|
||||||
git config --global user.email "actions@gitea.com"
|
git checkout ${{ gitea.head_ref }}
|
||||||
git status
|
|
||||||
git add lib/
|
dart fix --apply lib
|
||||||
git status
|
dart fix --apply test
|
||||||
git commit -m "Actions: Auto-formatting [skip ci]"
|
|
||||||
git push
|
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 add lib test
|
||||||
|
git commit -m "Auto-format code [skip ci]"
|
||||||
|
git push origin HEAD:${{ gitea.head_ref }}
|
||||||
|
else
|
||||||
|
echo "No changes to commit"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Verify format
|
||||||
|
run: flutter analyze lib test
|
||||||
|
|
||||||
|
update_version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: Format
|
||||||
|
if: gitea.ref == 'refs/heads/development'
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ secrets.BOT_TOKEN }}
|
||||||
|
ref: ${{ gitea.head_ref }}
|
||||||
|
|
||||||
|
- name: Increment version number
|
||||||
|
uses: https://github.com/stikkyapp/update-pubspec-version@v2
|
||||||
|
with:
|
||||||
|
strategy: 'patch'
|
||||||
|
path: './pubspec.yaml'
|
||||||
|
|
||||||
|
|
||||||
|
- name: Commit version update
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.BOT_TOKEN }}
|
||||||
|
run: |
|
||||||
|
git config --global user.name "Gitea Actions [bot]"
|
||||||
|
git config --global user.email "actions@yannick-weigert.de"
|
||||||
|
git add pubspec.yaml
|
||||||
|
git commit -m "Updated version number [skip ci]"
|
||||||
|
git push origin HEAD:${{ gitea.head_ref }}
|
||||||
@@ -19,7 +19,4 @@ class Constants {
|
|||||||
|
|
||||||
/// Maximum length for team names
|
/// Maximum length for team names
|
||||||
static const int MAX_TEAM_NAME_LENGTH = 32;
|
static const int MAX_TEAM_NAME_LENGTH = 32;
|
||||||
|
|
||||||
/// Maximum length for game descriptions
|
|
||||||
static const int MAX_GAME_DESCRIPTION_LENGTH = 256;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
import 'package:clock/clock.dart';
|
|
||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
class Game {
|
|
||||||
final String id;
|
|
||||||
final DateTime createdAt;
|
|
||||||
final String name;
|
|
||||||
final String? ruleset;
|
|
||||||
final String? description;
|
|
||||||
final int? color;
|
|
||||||
final String? icon;
|
|
||||||
|
|
||||||
Game({
|
|
||||||
String? id,
|
|
||||||
DateTime? createdAt,
|
|
||||||
required this.name,
|
|
||||||
this.ruleset,
|
|
||||||
this.description,
|
|
||||||
this.color,
|
|
||||||
this.icon,
|
|
||||||
}) : id = id ?? const Uuid().v4(),
|
|
||||||
createdAt = createdAt ?? clock.now();
|
|
||||||
}
|
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
"choose_group": "Gruppe wählen",
|
"choose_group": "Gruppe wählen",
|
||||||
"choose_ruleset": "Regelwerk wählen",
|
"choose_ruleset": "Regelwerk wählen",
|
||||||
"could_not_add_player": "Spieler:in {playerName} konnte nicht hinzugefügt werden",
|
"could_not_add_player": "Spieler:in {playerName} konnte nicht hinzugefügt werden",
|
||||||
"create_game": "Spielvorlage erstellen",
|
|
||||||
"create_group": "Gruppe erstellen",
|
"create_group": "Gruppe erstellen",
|
||||||
"create_match": "Spiel erstellen",
|
"create_match": "Spiel erstellen",
|
||||||
"create_new_group": "Neue Gruppe erstellen",
|
"create_new_group": "Neue Gruppe erstellen",
|
||||||
@@ -23,10 +22,7 @@
|
|||||||
"days_ago": "vor {count} Tagen",
|
"days_ago": "vor {count} Tagen",
|
||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
"delete_all_data": "Alle Daten löschen",
|
"delete_all_data": "Alle Daten löschen",
|
||||||
"delete_game": "Spielvorlage löschen",
|
|
||||||
"delete_group": "Gruppe löschen",
|
"delete_group": "Gruppe löschen",
|
||||||
"description": "Beschreibung",
|
|
||||||
"edit_game": "Spielvorlage bearbeiten",
|
|
||||||
"edit_group": "Gruppe bearbeiten",
|
"edit_group": "Gruppe bearbeiten",
|
||||||
"error_creating_group": "Fehler beim Erstellen der Gruppe, bitte erneut versuchen",
|
"error_creating_group": "Fehler beim Erstellen der Gruppe, bitte erneut versuchen",
|
||||||
"error_reading_file": "Fehler beim Lesen der Datei",
|
"error_reading_file": "Fehler beim Lesen der Datei",
|
||||||
|
|||||||
@@ -30,9 +30,6 @@
|
|||||||
"@could_not_add_player": {
|
"@could_not_add_player": {
|
||||||
"description": "Error message when adding a player fails"
|
"description": "Error message when adding a player fails"
|
||||||
},
|
},
|
||||||
"@create_game": {
|
|
||||||
"description": "Button text to create a game"
|
|
||||||
},
|
|
||||||
"@create_group": {
|
"@create_group": {
|
||||||
"description": "Button text to create a group"
|
"description": "Button text to create a group"
|
||||||
},
|
},
|
||||||
@@ -74,18 +71,9 @@
|
|||||||
"@delete_all_data": {
|
"@delete_all_data": {
|
||||||
"description": "Confirmation dialog for deleting all data"
|
"description": "Confirmation dialog for deleting all data"
|
||||||
},
|
},
|
||||||
"@delete_game": {
|
|
||||||
"description": "Button text to delete a game"
|
|
||||||
},
|
|
||||||
"@delete_group": {
|
"@delete_group": {
|
||||||
"description": "Button text to delete a group"
|
"description": "Button text to delete a group"
|
||||||
},
|
},
|
||||||
"description": {
|
|
||||||
"description": "Description label"
|
|
||||||
},
|
|
||||||
"edit_game": {
|
|
||||||
"description": "Button text to edit a game"
|
|
||||||
},
|
|
||||||
"@edit_group": {
|
"@edit_group": {
|
||||||
"description": "Button text to edit a group"
|
"description": "Button text to edit a group"
|
||||||
},
|
},
|
||||||
@@ -320,7 +308,6 @@
|
|||||||
"choose_group": "Choose Group",
|
"choose_group": "Choose Group",
|
||||||
"choose_ruleset": "Choose Ruleset",
|
"choose_ruleset": "Choose Ruleset",
|
||||||
"could_not_add_player": "Could not add player",
|
"could_not_add_player": "Could not add player",
|
||||||
"create_game": "Create Game",
|
|
||||||
"create_group": "Create Group",
|
"create_group": "Create Group",
|
||||||
"create_match": "Create match",
|
"create_match": "Create match",
|
||||||
"create_new_group": "Create new group",
|
"create_new_group": "Create new group",
|
||||||
@@ -333,10 +320,7 @@
|
|||||||
"days_ago": "{count} days ago",
|
"days_ago": "{count} days ago",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"delete_all_data": "Delete all data",
|
"delete_all_data": "Delete all data",
|
||||||
"delete_game": "Delete Game",
|
|
||||||
"delete_group": "Delete Group",
|
"delete_group": "Delete Group",
|
||||||
"description": "Description",
|
|
||||||
"edit_game": "Edit Game",
|
|
||||||
"edit_group": "Edit Group",
|
"edit_group": "Edit Group",
|
||||||
"error_creating_group": "Error while creating group, please try again",
|
"error_creating_group": "Error while creating group, please try again",
|
||||||
"error_reading_file": "Error reading file",
|
"error_reading_file": "Error reading file",
|
||||||
|
|||||||
@@ -98,18 +98,6 @@ abstract class AppLocalizations {
|
|||||||
Locale('en'),
|
Locale('en'),
|
||||||
];
|
];
|
||||||
|
|
||||||
/// No description provided for @description.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Description'**
|
|
||||||
String get description;
|
|
||||||
|
|
||||||
/// No description provided for @edit_game.
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Edit Game'**
|
|
||||||
String get edit_game;
|
|
||||||
|
|
||||||
/// Label for all players list
|
/// Label for all players list
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -170,12 +158,6 @@ abstract class AppLocalizations {
|
|||||||
/// **'Could not add player'**
|
/// **'Could not add player'**
|
||||||
String could_not_add_player(Object playerName);
|
String could_not_add_player(Object playerName);
|
||||||
|
|
||||||
/// Button text to create a game
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Create Game'**
|
|
||||||
String get create_game;
|
|
||||||
|
|
||||||
/// Button text to create a group
|
/// Button text to create a group
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -248,12 +230,6 @@ abstract class AppLocalizations {
|
|||||||
/// **'Delete all data'**
|
/// **'Delete all data'**
|
||||||
String get delete_all_data;
|
String get delete_all_data;
|
||||||
|
|
||||||
/// Button text to delete a game
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Delete Game'**
|
|
||||||
String get delete_game;
|
|
||||||
|
|
||||||
/// Button text to delete a group
|
/// Button text to delete a group
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -8,12 +8,6 @@ import 'app_localizations.dart';
|
|||||||
class AppLocalizationsDe extends AppLocalizations {
|
class AppLocalizationsDe extends AppLocalizations {
|
||||||
AppLocalizationsDe([String locale = 'de']) : super(locale);
|
AppLocalizationsDe([String locale = 'de']) : super(locale);
|
||||||
|
|
||||||
@override
|
|
||||||
String get description => 'Beschreibung';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get edit_game => 'Spielvorlage bearbeiten';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get all_players => 'Alle Spieler:innen';
|
String get all_players => 'Alle Spieler:innen';
|
||||||
|
|
||||||
@@ -46,9 +40,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
return 'Spieler:in $playerName konnte nicht hinzugefügt werden';
|
return 'Spieler:in $playerName konnte nicht hinzugefügt werden';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
String get create_game => 'Spielvorlage erstellen';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get create_group => 'Gruppe erstellen';
|
String get create_group => 'Gruppe erstellen';
|
||||||
|
|
||||||
@@ -87,9 +78,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get delete_all_data => 'Alle Daten löschen';
|
String get delete_all_data => 'Alle Daten löschen';
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_game => 'Spielvorlage löschen';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get delete_group => 'Gruppe löschen';
|
String get delete_group => 'Gruppe löschen';
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,6 @@ import 'app_localizations.dart';
|
|||||||
class AppLocalizationsEn extends AppLocalizations {
|
class AppLocalizationsEn extends AppLocalizations {
|
||||||
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
AppLocalizationsEn([String locale = 'en']) : super(locale);
|
||||||
|
|
||||||
@override
|
|
||||||
String get description => 'Description';
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get edit_game => 'Edit Game';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get all_players => 'All players';
|
String get all_players => 'All players';
|
||||||
|
|
||||||
@@ -46,9 +40,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
return 'Could not add player';
|
return 'Could not add player';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
String get create_game => 'Create Game';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get create_group => 'Create Group';
|
String get create_group => 'Create Group';
|
||||||
|
|
||||||
@@ -87,9 +78,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get delete_all_data => 'Delete all data';
|
String get delete_all_data => 'Delete all data';
|
||||||
|
|
||||||
@override
|
|
||||||
String get delete_game => 'Delete Game';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get delete_group => 'Delete Group';
|
String get delete_group => 'Delete Group';
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/core/adaptive_page_route.dart';
|
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:game_tracker/core/enums.dart';
|
import 'package:game_tracker/core/enums.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/match_view/create_match/game_view/create_game_view.dart';
|
|
||||||
import 'package:game_tracker/presentation/widgets/text_input/custom_search_bar.dart';
|
import 'package:game_tracker/presentation/widgets/text_input/custom_search_bar.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/title_description_list_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/title_description_list_tile.dart';
|
||||||
|
|
||||||
@@ -54,17 +51,6 @@ class _ChooseGameViewState extends State<ChooseGameView> {
|
|||||||
Navigator.of(context).pop(selectedGameIndex);
|
Navigator.of(context).pop(selectedGameIndex);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
actions: [IconButton(
|
|
||||||
icon: const Icon(Icons.add),
|
|
||||||
onPressed: () async {
|
|
||||||
await Navigator.push(context, adaptivePageRoute(
|
|
||||||
builder: (context) => CreateGameView(
|
|
||||||
callback: () {}, //TODO: implement callback
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)],
|
|
||||||
title: Text(loc.choose_game),
|
title: Text(loc.choose_game),
|
||||||
),
|
),
|
||||||
body: PopScope(
|
body: PopScope(
|
||||||
@@ -99,7 +85,7 @@ class _ChooseGameViewState extends State<ChooseGameView> {
|
|||||||
context,
|
context,
|
||||||
),
|
),
|
||||||
isHighlighted: selectedGameIndex == index,
|
isHighlighted: selectedGameIndex == index,
|
||||||
onTap: () async {
|
onPressed: () async {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selectedGameIndex == index) {
|
if (selectedGameIndex == index) {
|
||||||
selectedGameIndex = -1;
|
selectedGameIndex = -1;
|
||||||
@@ -108,16 +94,6 @@ class _ChooseGameViewState extends State<ChooseGameView> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onLongPress: () async {
|
|
||||||
await Navigator.push(context, adaptivePageRoute(
|
|
||||||
builder: (context) => CreateGameView(
|
|
||||||
//TODO: implement callback & giving real game to create game view
|
|
||||||
gameToEdit: Game(name: 'Cabo', description: '', ruleset: 'Highest Points'),
|
|
||||||
callback: () {},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
|
||||||
import 'package:game_tracker/core/enums.dart';
|
|
||||||
import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/title_description_list_tile.dart';
|
|
||||||
class ChooseRulesetView extends StatefulWidget {
|
|
||||||
/// A view that allows the user to choose a ruleset from a list of available rulesets
|
|
||||||
/// - [rulesets]: A list of tuples containing the ruleset and its description
|
|
||||||
/// - [initialRulesetIndex]: The index of the initially selected ruleset
|
|
||||||
const ChooseRulesetView({
|
|
||||||
super.key,
|
|
||||||
required this.rulesets,
|
|
||||||
required this.initialRulesetIndex,
|
|
||||||
});
|
|
||||||
/// A list of tuples containing the ruleset and its description
|
|
||||||
final List<(Ruleset, String)> rulesets;
|
|
||||||
/// The index of the initially selected ruleset
|
|
||||||
final int initialRulesetIndex;
|
|
||||||
@override
|
|
||||||
State<ChooseRulesetView> createState() => _ChooseRulesetViewState();
|
|
||||||
}
|
|
||||||
class _ChooseRulesetViewState extends State<ChooseRulesetView> {
|
|
||||||
/// Currently selected ruleset index
|
|
||||||
late int selectedRulesetIndex;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
selectedRulesetIndex = widget.initialRulesetIndex;
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final loc = AppLocalizations.of(context);
|
|
||||||
return DefaultTabController(
|
|
||||||
length: 2,
|
|
||||||
initialIndex: 0,
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: CustomTheme.backgroundColor,
|
|
||||||
appBar: AppBar(
|
|
||||||
leading: IconButton(
|
|
||||||
icon: const Icon(Icons.arrow_back_ios),
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop(
|
|
||||||
selectedRulesetIndex == -1
|
|
||||||
? null
|
|
||||||
: widget.rulesets[selectedRulesetIndex].$1,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
title: Text(loc.choose_ruleset),
|
|
||||||
),
|
|
||||||
body: PopScope(
|
|
||||||
// This fixes that the Android Back Gesture didn't return the
|
|
||||||
// selectedRulesetIndex and therefore the selected Ruleset wasn't saved
|
|
||||||
canPop: false,
|
|
||||||
onPopInvokedWithResult: (bool didPop, Object? result) {
|
|
||||||
if (didPop) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop(
|
|
||||||
selectedRulesetIndex == -1
|
|
||||||
? null
|
|
||||||
: widget.rulesets[selectedRulesetIndex].$1,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: ListView.builder(
|
|
||||||
padding: const EdgeInsets.only(bottom: 85),
|
|
||||||
itemCount: widget.rulesets.length,
|
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
return TitleDescriptionListTile(
|
|
||||||
onTap: () async {
|
|
||||||
setState(() {
|
|
||||||
if (selectedRulesetIndex == index) {
|
|
||||||
selectedRulesetIndex = -1;
|
|
||||||
} else {
|
|
||||||
selectedRulesetIndex = index;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
title: translateRulesetToString(
|
|
||||||
widget.rulesets[index].$1,
|
|
||||||
context,
|
|
||||||
),
|
|
||||||
description: widget.rulesets[index].$2,
|
|
||||||
isHighlighted: selectedRulesetIndex == index,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:game_tracker/core/adaptive_page_route.dart';
|
|
||||||
import 'package:game_tracker/core/constants.dart';
|
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
|
||||||
import 'package:game_tracker/core/enums.dart';
|
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
|
||||||
import 'package:game_tracker/presentation/views/main_menu/match_view/create_match/game_view/choose_ruleset_view.dart';
|
|
||||||
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
|
||||||
import 'package:game_tracker/presentation/widgets/text_input/text_input_field.dart';
|
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/choose_tile.dart';
|
|
||||||
|
|
||||||
class CreateGameView extends StatefulWidget {
|
|
||||||
const CreateGameView({super.key, this.gameToEdit, required this.callback});
|
|
||||||
|
|
||||||
final Game? gameToEdit;
|
|
||||||
|
|
||||||
final VoidCallback callback;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<CreateGameView> createState() => _CreateGameViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _CreateGameViewState extends State<CreateGameView> {
|
|
||||||
Ruleset? selectedRuleset;
|
|
||||||
int selectedRulesetIndex = -1;
|
|
||||||
late List<(Ruleset, String)> _rulesets;
|
|
||||||
|
|
||||||
final _gameNameController = TextEditingController();
|
|
||||||
final _descriptionController = TextEditingController();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_gameNameController.addListener(() => setState(() {}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
super.didChangeDependencies();
|
|
||||||
final loc = AppLocalizations.of(context);
|
|
||||||
_rulesets = [
|
|
||||||
(Ruleset.singleWinner, loc.ruleset_single_winner),
|
|
||||||
(Ruleset.singleLoser, loc.ruleset_single_loser),
|
|
||||||
(Ruleset.mostPoints, loc.ruleset_most_points),
|
|
||||||
(Ruleset.leastPoints, loc.ruleset_least_points),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (widget.gameToEdit != null) {
|
|
||||||
_gameNameController.text = widget.gameToEdit!.name;
|
|
||||||
_descriptionController.text = widget.gameToEdit!.description ?? '';
|
|
||||||
// TODO: Handle ruleset initialization from gameToEdit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_gameNameController.dispose();
|
|
||||||
_descriptionController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
var loc = AppLocalizations.of(context);
|
|
||||||
final isEditing = widget.gameToEdit != null;
|
|
||||||
|
|
||||||
return ScaffoldMessenger(
|
|
||||||
child: Scaffold(
|
|
||||||
backgroundColor: CustomTheme.backgroundColor,
|
|
||||||
appBar: AppBar(
|
|
||||||
title: Text(isEditing ? loc.edit_game : loc.create_game),
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
margin: CustomTheme.tileMargin,
|
|
||||||
child: TextInputField(
|
|
||||||
controller: _gameNameController,
|
|
||||||
maxLength: Constants.MAX_MATCH_NAME_LENGTH,
|
|
||||||
hintText: loc.game_name,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
ChooseTile(
|
|
||||||
title: loc.ruleset,
|
|
||||||
trailingText: selectedRuleset == null
|
|
||||||
? loc.none
|
|
||||||
: translateRulesetToString(selectedRuleset!, context),
|
|
||||||
onPressed: () async {
|
|
||||||
final result = await Navigator.of(context).push<Ruleset?>(
|
|
||||||
adaptivePageRoute(
|
|
||||||
builder: (context) => ChooseRulesetView(
|
|
||||||
rulesets: _rulesets,
|
|
||||||
initialRulesetIndex: selectedRulesetIndex,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
selectedRuleset = result;
|
|
||||||
selectedRulesetIndex =
|
|
||||||
result == null ? -1 : _rulesets.indexWhere((r) => r.$1 == result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
margin: CustomTheme.tileMargin,
|
|
||||||
child: TextInputField(
|
|
||||||
controller: _descriptionController,
|
|
||||||
hintText: loc.description,
|
|
||||||
minLines: 6,
|
|
||||||
maxLines: 6,
|
|
||||||
maxLength: Constants.MAX_GAME_DESCRIPTION_LENGTH,
|
|
||||||
showCounterText: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(12.0),
|
|
||||||
child: CustomWidthButton(
|
|
||||||
text: isEditing ? loc.edit_group : loc.create_game,
|
|
||||||
sizeRelativeToWidth: 1,
|
|
||||||
buttonType: ButtonType.primary,
|
|
||||||
onPressed: _gameNameController.text.trim().isNotEmpty && selectedRulesetIndex != -1
|
|
||||||
? () {
|
|
||||||
//TODO: Handle saving to db & updating game selection view
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -8,18 +8,12 @@ class TextInputField extends StatelessWidget {
|
|||||||
/// - [onChanged]: Optional callback invoked when the text in the field changes.
|
/// - [onChanged]: Optional callback invoked when the text in the field changes.
|
||||||
/// - [hintText]: The hint text displayed in the text input field when it is empty
|
/// - [hintText]: The hint text displayed in the text input field when it is empty
|
||||||
/// - [maxLength]: Optional parameter for maximum length of the input text.
|
/// - [maxLength]: Optional parameter for maximum length of the input text.
|
||||||
/// - [maxLines]: The maximum number of lines for the text input field. Defaults to 1.
|
|
||||||
/// - [minLines]: The minimum number of lines for the text input field. Defaults to 1.
|
|
||||||
/// - [showCounterText]: Whether to show the counter text in the text input field. Defaults to false.
|
|
||||||
const TextInputField({
|
const TextInputField({
|
||||||
super.key,
|
super.key,
|
||||||
required this.controller,
|
required this.controller,
|
||||||
required this.hintText,
|
required this.hintText,
|
||||||
this.onChanged,
|
this.onChanged,
|
||||||
this.maxLength,
|
this.maxLength,
|
||||||
this.maxLines = 1,
|
|
||||||
this.minLines = 1,
|
|
||||||
this.showCounterText = false
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The controller for the text input field.
|
/// The controller for the text input field.
|
||||||
@@ -34,15 +28,6 @@ class TextInputField extends StatelessWidget {
|
|||||||
/// Optional parameter for maximum length of the input text.
|
/// Optional parameter for maximum length of the input text.
|
||||||
final int? maxLength;
|
final int? maxLength;
|
||||||
|
|
||||||
/// The maximum number of lines for the text input field.
|
|
||||||
final int? maxLines;
|
|
||||||
|
|
||||||
/// The minimum number of lines for the text input field.
|
|
||||||
final int? minLines;
|
|
||||||
|
|
||||||
/// Whether to show the counter text in the text input field.
|
|
||||||
final bool showCounterText;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return TextField(
|
return TextField(
|
||||||
@@ -50,14 +35,13 @@ class TextInputField extends StatelessWidget {
|
|||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
maxLength: maxLength,
|
maxLength: maxLength,
|
||||||
maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds,
|
maxLengthEnforcement: MaxLengthEnforcement.truncateAfterCompositionEnds,
|
||||||
maxLines: maxLines,
|
|
||||||
minLines: minLines,
|
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: CustomTheme.boxColor,
|
fillColor: CustomTheme.boxColor,
|
||||||
hintText: hintText,
|
hintText: hintText,
|
||||||
hintStyle: const TextStyle(fontSize: 18),
|
hintStyle: const TextStyle(fontSize: 18),
|
||||||
counterText: showCounterText ? null : '',
|
// Hides the character counter
|
||||||
|
counterText: '',
|
||||||
enabledBorder: OutlineInputBorder(
|
enabledBorder: OutlineInputBorder(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||||
borderSide: BorderSide(color: CustomTheme.boxBorder),
|
borderSide: BorderSide(color: CustomTheme.boxBorder),
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ class TitleDescriptionListTile extends StatelessWidget {
|
|||||||
/// - [title]: The title text displayed on the tile.
|
/// - [title]: The title text displayed on the tile.
|
||||||
/// - [description]: The description text displayed below the title.
|
/// - [description]: The description text displayed below the title.
|
||||||
/// - [onPressed]: The callback invoked when the tile is tapped.
|
/// - [onPressed]: The callback invoked when the tile is tapped.
|
||||||
/// - [onLongPress]: The callback invoked when the tile is tapped.
|
|
||||||
/// - [isHighlighted]: A boolean to determine if the tile should be highlighted.
|
/// - [isHighlighted]: A boolean to determine if the tile should be highlighted.
|
||||||
/// - [badgeText]: Optional text to display in a badge on the right side of the title.
|
/// - [badgeText]: Optional text to display in a badge on the right side of the title.
|
||||||
/// - [badgeColor]: Optional color for the badge background.
|
/// - [badgeColor]: Optional color for the badge background.
|
||||||
@@ -14,8 +13,7 @@ class TitleDescriptionListTile extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.description,
|
required this.description,
|
||||||
this.onTap,
|
this.onPressed,
|
||||||
this.onLongPress,
|
|
||||||
this.isHighlighted = false,
|
this.isHighlighted = false,
|
||||||
this.badgeText,
|
this.badgeText,
|
||||||
this.badgeColor,
|
this.badgeColor,
|
||||||
@@ -28,10 +26,7 @@ class TitleDescriptionListTile extends StatelessWidget {
|
|||||||
final String description;
|
final String description;
|
||||||
|
|
||||||
/// The callback invoked when the tile is tapped.
|
/// The callback invoked when the tile is tapped.
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onPressed;
|
||||||
|
|
||||||
/// The callback invoked when the tile is long-pressed.
|
|
||||||
final VoidCallback? onLongPress;
|
|
||||||
|
|
||||||
/// A boolean to determine if the tile should be highlighted.
|
/// A boolean to determine if the tile should be highlighted.
|
||||||
final bool isHighlighted;
|
final bool isHighlighted;
|
||||||
@@ -45,8 +40,7 @@ class TitleDescriptionListTile extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: onTap,
|
onTap: onPressed,
|
||||||
onLongPress: onLongPress,
|
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 12),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: game_tracker
|
name: game_tracker
|
||||||
description: "Game Tracking App for Card Games"
|
description: "Game Tracking App for Card Games"
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.0.10+248
|
version: 0.0.10+237
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.8.1
|
sdk: ^3.8.1
|
||||||
|
|||||||
Reference in New Issue
Block a user