Einstellungen ausgestalten #153
27
.gitignore
vendored
27
.gitignore
vendored
@@ -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
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
<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="game_tracker"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,11 @@
|
|||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>https</string>
|
||||||
|
<string>http</string>
|
||||||
|
</array>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>LaunchScreen</string>
|
<string>LaunchScreen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
"all_players": "Alle Spieler:innen",
|
"all_players": "Alle Spieler:innen",
|
||||||
"all_players_selected": "Alle Spieler:innen ausgewählt",
|
"all_players_selected": "Alle Spieler:innen ausgewählt",
|
||||||
"amount_of_matches": "Anzahl der Spiele",
|
"amount_of_matches": "Anzahl der Spiele",
|
||||||
|
"app_name": "Game Tracker",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"choose_game": "Spielvorlage wählen",
|
"choose_game": "Spielvorlage wählen",
|
||||||
"choose_group": "Gruppe wählen",
|
"choose_group": "Gruppe wählen",
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
"create_match": "Spiel erstellen",
|
"create_match": "Spiel erstellen",
|
||||||
"create_new_group": "Neue Gruppe erstellen",
|
"create_new_group": "Neue Gruppe erstellen",
|
||||||
"create_new_match": "Neues Spiel erstellen",
|
"create_new_match": "Neues Spiel erstellen",
|
||||||
|
"data": "Daten",
|
||||||
"data_successfully_deleted": "Daten erfolgreich gelöscht",
|
"data_successfully_deleted": "Daten erfolgreich gelöscht",
|
||||||
"data_successfully_exported": "Daten erfolgreich exportiert",
|
"data_successfully_exported": "Daten erfolgreich exportiert",
|
||||||
"data_successfully_imported": "Daten erfolgreich importiert",
|
"data_successfully_imported": "Daten erfolgreich importiert",
|
||||||
@@ -34,13 +36,17 @@
|
|||||||
"info": "Info",
|
"info": "Info",
|
||||||
"invalid_schema": "Ungültiges Schema",
|
"invalid_schema": "Ungültiges Schema",
|
||||||
"least_points": "Niedrigste Punkte",
|
"least_points": "Niedrigste Punkte",
|
||||||
|
"legal": "Rechtliches",
|
||||||
|
"legal_notice": "Impressum",
|
||||||
|
"licenses": "Lizenzen",
|
||||||
"match_in_progress": "Spiel läuft...",
|
"match_in_progress": "Spiel läuft...",
|
||||||
"match_name": "Spieltitel",
|
"match_name": "Spieltitel",
|
||||||
"matches": "Spiele",
|
"matches": "Spiele",
|
||||||
"menu": "Menü",
|
|
||||||
"most_points": "Höchste Punkte",
|
"most_points": "Höchste Punkte",
|
||||||
"no_data_available": "Keine Daten verfügbar",
|
"no_data_available": "Keine Daten verfügbar",
|
||||||
"no_groups_created_yet": "Noch keine Gruppen erstellt",
|
"no_groups_created_yet": "Noch keine Gruppen erstellt",
|
||||||
|
"no_licenses_found": "Keine Lizenzen gefunden",
|
||||||
|
"no_license_text_available": "Kein Lizenztext verfügbar",
|
||||||
"no_matches_created_yet": "Noch keine Spiele erstellt",
|
"no_matches_created_yet": "Noch keine Spiele erstellt",
|
||||||
"no_players_created_yet": "Noch keine Spieler:in erstellt",
|
"no_players_created_yet": "Noch keine Spieler:in erstellt",
|
||||||
"no_players_found_with_that_name": "Keine Spieler:in mit diesem Namen gefunden",
|
"no_players_found_with_that_name": "Keine Spieler:in mit diesem Namen gefunden",
|
||||||
@@ -54,6 +60,7 @@
|
|||||||
"player_name": "Spieler:innenname",
|
"player_name": "Spieler:innenname",
|
||||||
"players": "Spieler:innen",
|
"players": "Spieler:innen",
|
||||||
"players_count": "{count} Spieler",
|
"players_count": "{count} Spieler",
|
||||||
|
"privacy_policy": "Datenschutzerklärung",
|
||||||
"quick_create": "Schnellzugriff",
|
"quick_create": "Schnellzugriff",
|
||||||
"recent_matches": "Letzte Spiele",
|
"recent_matches": "Letzte Spiele",
|
||||||
"ruleset": "Regelwerk",
|
"ruleset": "Regelwerk",
|
||||||
|
|||||||
@@ -39,6 +39,9 @@
|
|||||||
"@create_new_match": {
|
"@create_new_match": {
|
||||||
"description": "Button text to create a new match"
|
"description": "Button text to create a new match"
|
||||||
},
|
},
|
||||||
|
"@data": {
|
||||||
|
"description": "Data label"
|
||||||
|
},
|
||||||
"@data_successfully_deleted": {
|
"@data_successfully_deleted": {
|
||||||
"description": "Success message after deleting data"
|
"description": "Success message after deleting data"
|
||||||
},
|
},
|
||||||
@@ -110,6 +113,15 @@
|
|||||||
"@least_points": {
|
"@least_points": {
|
||||||
"description": "Title for least points ruleset"
|
"description": "Title for least points ruleset"
|
||||||
},
|
},
|
||||||
|
"@legal": {
|
||||||
|
"description": "Legal section header"
|
||||||
|
},
|
||||||
|
"@legal_notice": {
|
||||||
|
"description": "Legal notice menu item"
|
||||||
|
},
|
||||||
|
"@licenses": {
|
||||||
|
"description": "Licenses menu item"
|
||||||
|
},
|
||||||
"@match_in_progress": {
|
"@match_in_progress": {
|
||||||
"description": "Message when match is in progress"
|
"description": "Message when match is in progress"
|
||||||
},
|
},
|
||||||
@@ -119,9 +131,6 @@
|
|||||||
"@matches": {
|
"@matches": {
|
||||||
"description": "Label for matches"
|
"description": "Label for matches"
|
||||||
},
|
},
|
||||||
"@menu": {
|
|
||||||
"description": "Menu label"
|
|
||||||
},
|
|
||||||
"@most_points": {
|
"@most_points": {
|
||||||
"description": "Title for most points ruleset"
|
"description": "Title for most points ruleset"
|
||||||
},
|
},
|
||||||
@@ -131,6 +140,12 @@
|
|||||||
"@no_groups_created_yet": {
|
"@no_groups_created_yet": {
|
||||||
"description": "Message when no groups exist"
|
"description": "Message when no groups exist"
|
||||||
},
|
},
|
||||||
|
"@no_licenses_found": {
|
||||||
|
"description": "Message when no licenses are found"
|
||||||
|
},
|
||||||
|
"@no_license_text_available": {
|
||||||
|
"description": "Message when no license text is available"
|
||||||
|
},
|
||||||
"@no_matches_created_yet": {
|
"@no_matches_created_yet": {
|
||||||
"description": "Message when no matches exist"
|
"description": "Message when no matches exist"
|
||||||
},
|
},
|
||||||
@@ -175,6 +190,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@privacy_policy": {
|
||||||
|
"description": "Privacy policy menu item"
|
||||||
|
},
|
||||||
"@quick_create": {
|
"@quick_create": {
|
||||||
"description": "Title for quick create section"
|
"description": "Title for quick create section"
|
||||||
},
|
},
|
||||||
@@ -209,7 +227,7 @@
|
|||||||
"description": "Shows the number of selected players"
|
"description": "Shows the number of selected players"
|
||||||
},
|
},
|
||||||
"@settings": {
|
"@settings": {
|
||||||
"description": "Settings label"
|
"description": "Label for the App Settings"
|
||||||
},
|
},
|
||||||
"@single_loser": {
|
"@single_loser": {
|
||||||
"description": "Title for single loser ruleset"
|
"description": "Title for single loser ruleset"
|
||||||
@@ -272,6 +290,7 @@
|
|||||||
"create_match": "Create match",
|
"create_match": "Create match",
|
||||||
"create_new_group": "Create new group",
|
"create_new_group": "Create new group",
|
||||||
"create_new_match": "Create new match",
|
"create_new_match": "Create new match",
|
||||||
|
"data": "Data",
|
||||||
"data_successfully_deleted": "Data successfully deleted",
|
"data_successfully_deleted": "Data successfully deleted",
|
||||||
"data_successfully_exported": "Data successfully exported",
|
"data_successfully_exported": "Data successfully exported",
|
||||||
"data_successfully_imported": "Data successfully imported",
|
"data_successfully_imported": "Data successfully imported",
|
||||||
@@ -294,13 +313,17 @@
|
|||||||
"info": "Info",
|
"info": "Info",
|
||||||
"invalid_schema": "Invalid Schema",
|
"invalid_schema": "Invalid Schema",
|
||||||
"least_points": "Least Points",
|
"least_points": "Least Points",
|
||||||
|
"legal": "Legal",
|
||||||
|
"legal_notice": "Legal Notice",
|
||||||
|
"licenses": "Licenses",
|
||||||
"match_in_progress": "Match in progress...",
|
"match_in_progress": "Match in progress...",
|
||||||
"match_name": "Match name",
|
"match_name": "Match name",
|
||||||
"matches": "Matches",
|
"matches": "Matches",
|
||||||
"menu": "Menu",
|
|
||||||
"most_points": "Most Points",
|
"most_points": "Most Points",
|
||||||
"no_data_available": "No data available",
|
"no_data_available": "No data available",
|
||||||
"no_groups_created_yet": "No groups created yet",
|
"no_groups_created_yet": "No groups created yet",
|
||||||
|
"no_licenses_found": "No licenses found",
|
||||||
|
"no_license_text_available": "No license text available",
|
||||||
"no_matches_created_yet": "No matches created yet",
|
"no_matches_created_yet": "No matches created yet",
|
||||||
"no_players_created_yet": "No players created yet",
|
"no_players_created_yet": "No players created yet",
|
||||||
"no_players_found_with_that_name": "No players found with that name",
|
"no_players_found_with_that_name": "No players found with that name",
|
||||||
@@ -314,6 +337,7 @@
|
|||||||
"player_name": "Player name",
|
"player_name": "Player name",
|
||||||
"players": "Players",
|
"players": "Players",
|
||||||
"players_count": "{count} Players",
|
"players_count": "{count} Players",
|
||||||
|
"privacy_policy": "Privacy Policy",
|
||||||
"quick_create": "Quick Create",
|
"quick_create": "Quick Create",
|
||||||
"recent_matches": "Recent Matches",
|
"recent_matches": "Recent Matches",
|
||||||
"ruleset": "Ruleset",
|
"ruleset": "Ruleset",
|
||||||
|
|||||||
@@ -176,6 +176,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Create new match'**
|
/// **'Create new match'**
|
||||||
String get create_new_match;
|
String get create_new_match;
|
||||||
|
|
||||||
|
/// Data label
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Data'**
|
||||||
|
String get data;
|
||||||
|
|
||||||
/// Success message after deleting data
|
/// Success message after deleting data
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -308,6 +314,24 @@ abstract class AppLocalizations {
|
|||||||
/// **'Least Points'**
|
/// **'Least Points'**
|
||||||
String get least_points;
|
String get least_points;
|
||||||
|
|
||||||
|
/// Legal section header
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Legal'**
|
||||||
|
String get legal;
|
||||||
|
|
||||||
|
/// Legal notice menu item
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Legal Notice'**
|
||||||
|
String get legal_notice;
|
||||||
|
|
||||||
|
/// Licenses menu item
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Licenses'**
|
||||||
|
String get licenses;
|
||||||
|
|
||||||
/// Message when match is in progress
|
/// Message when match is in progress
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -326,12 +350,6 @@ abstract class AppLocalizations {
|
|||||||
/// **'Matches'**
|
/// **'Matches'**
|
||||||
String get matches;
|
String get matches;
|
||||||
|
|
||||||
/// Menu label
|
|
||||||
///
|
|
||||||
/// In en, this message translates to:
|
|
||||||
/// **'Menu'**
|
|
||||||
String get menu;
|
|
||||||
|
|
||||||
/// Title for most points ruleset
|
/// Title for most points ruleset
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -350,6 +368,18 @@ abstract class AppLocalizations {
|
|||||||
/// **'No groups created yet'**
|
/// **'No groups created yet'**
|
||||||
String get no_groups_created_yet;
|
String get no_groups_created_yet;
|
||||||
|
|
||||||
|
/// Message when no licenses are found
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'No licenses found'**
|
||||||
|
String get no_licenses_found;
|
||||||
|
|
||||||
|
/// Message when no license text is available
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'No license text available'**
|
||||||
|
String get no_license_text_available;
|
||||||
|
|
||||||
/// Message when no matches exist
|
/// Message when no matches exist
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -428,6 +458,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'{count} Players'**
|
/// **'{count} Players'**
|
||||||
String players_count(int count);
|
String players_count(int count);
|
||||||
|
|
||||||
|
/// Privacy policy menu item
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Privacy Policy'**
|
||||||
|
String get privacy_policy;
|
||||||
|
|
||||||
/// Title for quick create section
|
/// Title for quick create section
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
@@ -494,7 +530,7 @@ abstract class AppLocalizations {
|
|||||||
/// **'Selected players'**
|
/// **'Selected players'**
|
||||||
String get selected_players;
|
String get selected_players;
|
||||||
|
|
||||||
/// Settings label
|
/// Label for the App Settings
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Settings'**
|
/// **'Settings'**
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get create_new_match => 'Neues Spiel erstellen';
|
String get create_new_match => 'Neues Spiel erstellen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get data => 'Daten';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get data_successfully_deleted => 'Daten erfolgreich gelöscht';
|
String get data_successfully_deleted => 'Daten erfolgreich gelöscht';
|
||||||
|
|
||||||
@@ -118,6 +121,15 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get least_points => 'Niedrigste Punkte';
|
String get least_points => 'Niedrigste Punkte';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get legal => 'Rechtliches';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get legal_notice => 'Impressum';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get licenses => 'Lizenzen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get match_in_progress => 'Spiel läuft...';
|
String get match_in_progress => 'Spiel läuft...';
|
||||||
|
|
||||||
@@ -127,9 +139,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get matches => 'Spiele';
|
String get matches => 'Spiele';
|
||||||
|
|
||||||
@override
|
|
||||||
String get menu => 'Menü';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get most_points => 'Höchste Punkte';
|
String get most_points => 'Höchste Punkte';
|
||||||
|
|
||||||
@@ -139,6 +148,12 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get no_groups_created_yet => 'Noch keine Gruppen erstellt';
|
String get no_groups_created_yet => 'Noch keine Gruppen erstellt';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get no_licenses_found => 'Keine Lizenzen gefunden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get no_license_text_available => 'Kein Lizenztext verfügbar';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get no_matches_created_yet => 'Noch keine Spiele erstellt';
|
String get no_matches_created_yet => 'Noch keine Spiele erstellt';
|
||||||
|
|
||||||
@@ -181,6 +196,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
return '$count Spieler';
|
return '$count Spieler';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get privacy_policy => 'Datenschutzerklärung';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get quick_create => 'Schnellzugriff';
|
String get quick_create => 'Schnellzugriff';
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get create_new_match => 'Create new match';
|
String get create_new_match => 'Create new match';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get data => 'Data';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get data_successfully_deleted => 'Data successfully deleted';
|
String get data_successfully_deleted => 'Data successfully deleted';
|
||||||
|
|
||||||
@@ -118,6 +121,15 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get least_points => 'Least Points';
|
String get least_points => 'Least Points';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get legal => 'Legal';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get legal_notice => 'Legal Notice';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get licenses => 'Licenses';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get match_in_progress => 'Match in progress...';
|
String get match_in_progress => 'Match in progress...';
|
||||||
|
|
||||||
@@ -127,9 +139,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get matches => 'Matches';
|
String get matches => 'Matches';
|
||||||
|
|
||||||
@override
|
|
||||||
String get menu => 'Menu';
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get most_points => 'Most Points';
|
String get most_points => 'Most Points';
|
||||||
|
|
||||||
@@ -139,6 +148,12 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get no_groups_created_yet => 'No groups created yet';
|
String get no_groups_created_yet => 'No groups created yet';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get no_licenses_found => 'No licenses found';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get no_license_text_available => 'No license text available';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get no_matches_created_yet => 'No matches created yet';
|
String get no_matches_created_yet => 'No matches created yet';
|
||||||
|
|
||||||
@@ -181,6 +196,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
return '$count Players';
|
return '$count Players';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get privacy_policy => 'Privacy Policy';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get quick_create => 'Quick Create';
|
String get quick_create => 'Quick Create';
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
|||||||
import 'package:game_tracker/presentation/views/main_menu/group_view/groups_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/group_view/groups_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/home_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/home_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/match_view/match_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/match_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/settings_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/settings_view/settings_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/navbar_item.dart';
|
import 'package:game_tracker/presentation/widgets/navbar_item.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -1,219 +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/settings_list_tile.dart';
|
|
||||||
import 'package:game_tracker/services/data_transfer_service.dart';
|
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
|
||||||
|
|
||||||
class SettingsView extends StatefulWidget {
|
|
||||||
const SettingsView({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<SettingsView> createState() => _SettingsViewState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SettingsViewState extends State<SettingsView> {
|
|
||||||
PackageInfo _packageInfo = PackageInfo(
|
|
||||||
appName: 'n.A.',
|
|
||||||
packageName: 'n.A.',
|
|
||||||
version: 'n.A.',
|
|
||||||
buildNumber: 'n.A.',
|
|
||||||
);
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_initPackageInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final loc = AppLocalizations.of(context);
|
|
||||||
return ScaffoldMessenger(
|
|
||||||
child: Scaffold(
|
|
||||||
appBar: AppBar(backgroundColor: CustomTheme.backgroundColor),
|
|
||||||
backgroundColor: CustomTheme.backgroundColor,
|
|
||||||
body: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(24, 0, 24, 10),
|
|
||||||
child: Text(
|
|
||||||
textAlign: TextAlign.start,
|
|
||||||
loc.menu,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 28,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
|
|
||||||
child: Text(
|
|
||||||
textAlign: TextAlign.start,
|
|
||||||
loc.settings,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 22,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SettingsListTile(
|
|
||||||
title: loc.export_data,
|
|
||||||
icon: Icons.upload_rounded,
|
|
||||||
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
|
||||||
onPressed: () async {
|
|
||||||
final String json = await DataTransferService.getAppDataAsJson(
|
|
||||||
context,
|
|
||||||
);
|
|
||||||
final result = await DataTransferService.exportData(
|
|
||||||
json,
|
|
||||||
'game_tracker-data',
|
|
||||||
);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
showExportSnackBar(context: context, result: result);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SettingsListTile(
|
|
||||||
title: loc.import_data,
|
|
||||||
icon: Icons.download_rounded,
|
|
||||||
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
|
||||||
onPressed: () async {
|
|
||||||
final result = await DataTransferService.importData(context);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
showImportSnackBar(context: context, result: result);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
SettingsListTile(
|
|
||||||
title: loc.delete_all_data,
|
|
||||||
icon: Icons.delete_rounded,
|
|
||||||
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog<bool>(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: Text('${loc.delete_all_data}?'),
|
|
||||||
content: Text(loc.this_cannot_be_undone),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(false),
|
|
||||||
child: Text(loc.cancel),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(true),
|
|
||||||
child: Text(loc.delete),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).then((confirmed) {
|
|
||||||
if (confirmed == true && context.mounted) {
|
|
||||||
DataTransferService.deleteAllData(context);
|
|
||||||
showSnackbar(
|
|
||||||
context: context,
|
|
||||||
message: AppLocalizations.of(
|
|
||||||
context,
|
|
||||||
).data_successfully_deleted,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(20),
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
'Version ${_packageInfo.version} (${_packageInfo.buildNumber})',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.grey.shade600,
|
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Displays a snackbar based on the import result.
|
|
||||||
///
|
|
||||||
/// [context] The BuildContext to show the snackbar in.
|
|
||||||
/// [result] The result of the import operation.
|
|
||||||
void showImportSnackBar({
|
|
||||||
required BuildContext context,
|
|
||||||
required ImportResult result,
|
|
||||||
}) {
|
|
||||||
final loc = AppLocalizations.of(context);
|
|
||||||
switch (result) {
|
|
||||||
case ImportResult.success:
|
|
||||||
showSnackbar(context: context, message: loc.data_successfully_imported);
|
|
||||||
case ImportResult.invalidSchema:
|
|
||||||
showSnackbar(context: context, message: loc.invalid_schema);
|
|
||||||
case ImportResult.fileReadError:
|
|
||||||
showSnackbar(context: context, message: loc.error_reading_file);
|
|
||||||
case ImportResult.canceled:
|
|
||||||
showSnackbar(context: context, message: loc.import_canceled);
|
|
||||||
case ImportResult.formatException:
|
|
||||||
showSnackbar(context: context, message: loc.format_exception);
|
|
||||||
case ImportResult.unknownException:
|
|
||||||
showSnackbar(context: context, message: loc.unknown_exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Displays a snackbar based on the export result.
|
|
||||||
///
|
|
||||||
/// [context] The BuildContext to show the snackbar in.
|
|
||||||
/// [result] The result of the export operation.
|
|
||||||
void showExportSnackBar({
|
|
||||||
required BuildContext context,
|
|
||||||
required ExportResult result,
|
|
||||||
}) {
|
|
||||||
final loc = AppLocalizations.of(context);
|
|
||||||
switch (result) {
|
|
||||||
case ExportResult.success:
|
|
||||||
showSnackbar(context: context, message: loc.data_successfully_exported);
|
|
||||||
case ExportResult.canceled:
|
|
||||||
showSnackbar(context: context, message: loc.export_canceled);
|
|
||||||
case ExportResult.unknownException:
|
|
||||||
showSnackbar(context: context, message: loc.unknown_exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Displays a snackbar with the given message and optional action.
|
|
||||||
///
|
|
||||||
/// [context] The BuildContext to show the snackbar in.
|
|
||||||
/// [message] The message to display in the snackbar.
|
|
||||||
/// [duration] The duration for which the snackbar is displayed.
|
|
||||||
/// [action] An optional callback function to execute when the action button is pressed.
|
|
||||||
void showSnackbar({
|
|
||||||
required BuildContext context,
|
|
||||||
required String message,
|
|
||||||
Duration duration = const Duration(seconds: 3),
|
|
||||||
VoidCallback? action,
|
|
||||||
}) {
|
|
||||||
final loc = AppLocalizations.of(context);
|
|
||||||
final messenger = ScaffoldMessenger.of(context);
|
|
||||||
messenger.hideCurrentSnackBar();
|
|
||||||
messenger.showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(message, style: const TextStyle(color: Colors.white)),
|
|
||||||
backgroundColor: CustomTheme.onBoxColor,
|
|
||||||
duration: duration,
|
|
||||||
action: action != null
|
|
||||||
? SnackBarAction(label: loc.undo, onPressed: action)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _initPackageInfo() async {
|
|
||||||
final info = await PackageInfo.fromPlatform();
|
|
||||||
setState(() {
|
|
||||||
_packageInfo = info;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
|
import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
||||||
|
import 'package:game_tracker/presentation/views/main_menu/settings_view/licenses/oss_licenses.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
class LicenseDetailView extends StatelessWidget {
|
||||||
|
final Package package;
|
||||||
|
|
||||||
|
const LicenseDetailView({super.key, required this.package});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final loc = AppLocalizations.of(context);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(title: const Text('Lizenzdetails')),
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Center(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
flixcoo marked this conversation as resolved
Outdated
|
|||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
margin: const EdgeInsetsGeometry.only(right: 15),
|
||||||
|
width: 60,
|
||||||
|
height: 60,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CustomTheme.primaryColor.withAlpha(40),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.description,
|
||||||
|
color: CustomTheme.primaryColor,
|
||||||
|
size: 30,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
package.name,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
style: const TextStyle(
|
||||||
|
height: 0,
|
||||||
|
fontSize: 24,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (package.version != null) ...[
|
||||||
|
Text(
|
||||||
|
'Version ${package.version}',
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
if (package.authors.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
SelectableText(
|
||||||
|
package.authors.join(', '),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.grey.shade500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (package.homepage != null &&
|
||||||
|
package.homepage!.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
final uri = Uri.parse(package.homepage!);
|
||||||
|
await launchUrl(uri, mode: LaunchMode.platformDefault);
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
width: 300,
|
||||||
|
flixcoo marked this conversation as resolved
Outdated
sneeex
commented
clickable machen? clickable machen?
|
|||||||
|
child: Text(
|
||||||
|
package.homepage!,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: CustomTheme.secondaryColor,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
decorationColor: CustomTheme.secondaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
||||||
|
decoration: CustomTheme.standardBoxDecoration,
|
||||||
|
child: (package.license != null && package.license!.isNotEmpty)
|
||||||
|
? SelectableText(
|
||||||
|
package.license!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Colors.grey.shade300,
|
||||||
|
height: 1.5,
|
||||||
|
fontFamily: 'monospace',
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Center(
|
||||||
|
heightFactor: 25,
|
||||||
|
child: Text(
|
||||||
|
loc.no_license_text_available,
|
||||||
|
style: TextStyle(color: Colors.grey.shade500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,32 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
|
import 'package:game_tracker/l10n/generated/app_localizations.dart';
|
||||||
|
import 'package:game_tracker/presentation/views/main_menu/settings_view/licenses/oss_licenses.dart';
|
||||||
|
import 'package:game_tracker/presentation/widgets/tiles/license_tile.dart';
|
||||||
|
|
||||||
|
class LicensesView extends StatelessWidget {
|
||||||
|
const LicensesView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final loc = AppLocalizations.of(context);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(loc.licenses),
|
||||||
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
|
body: ListView.builder(
|
||||||
|
itemCount: allDependencies.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final package = allDependencies[index];
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
|
||||||
|
child: LicenseTile(package: package),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,310 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.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/views/main_menu/settings_view/licenses_view.dart';
|
||||||
|
import 'package:game_tracker/presentation/widgets/tiles/settings_list_tile.dart';
|
||||||
|
import 'package:game_tracker/services/data_transfer_service.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
class SettingsView extends StatefulWidget {
|
||||||
|
const SettingsView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<SettingsView> createState() => _SettingsViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SettingsViewState extends State<SettingsView> {
|
||||||
|
PackageInfo _packageInfo = PackageInfo(
|
||||||
|
appName: 'n.A.',
|
||||||
|
packageName: 'n.A.',
|
||||||
|
version: 'n.A.',
|
||||||
|
buildNumber: 'n.A.',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_initPackageInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final loc = AppLocalizations.of(context);
|
||||||
|
return ScaffoldMessenger(
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(backgroundColor: CustomTheme.backgroundColor),
|
||||||
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
|
body: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16, bottom: 10),
|
||||||
|
child: Text(
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
loc.settings,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 28,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10),
|
||||||
|
child: Text(
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
loc.data,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SettingsListTile(
|
||||||
|
title: loc.export_data,
|
||||||
|
icon: Icons.upload,
|
||||||
|
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onPressed: () async {
|
||||||
|
final String json =
|
||||||
|
await DataTransferService.getAppDataAsJson(context);
|
||||||
|
final result = await DataTransferService.exportData(
|
||||||
|
json,
|
||||||
|
'game_tracker-data',
|
||||||
|
);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showExportSnackBar(context: context, result: result);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SettingsListTile(
|
||||||
|
title: loc.import_data,
|
||||||
|
icon: Icons.download,
|
||||||
|
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onPressed: () async {
|
||||||
|
final result = await DataTransferService.importData(context);
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showImportSnackBar(context: context, result: result);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SettingsListTile(
|
||||||
|
title: loc.delete_all_data,
|
||||||
|
icon: Icons.delete,
|
||||||
|
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Text('${loc.delete_all_data}?'),
|
||||||
|
content: Text(loc.this_cannot_be_undone),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: Text(loc.cancel),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
child: Text(loc.delete),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).then((confirmed) {
|
||||||
|
if (confirmed == true && context.mounted) {
|
||||||
|
DataTransferService.deleteAllData(context);
|
||||||
|
showSnackbar(
|
||||||
|
context: context,
|
||||||
|
message: AppLocalizations.of(
|
||||||
|
context,
|
||||||
|
).data_successfully_deleted,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 16, top: 10, bottom: 10),
|
||||||
|
child: Text(
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
loc.legal,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SettingsListTile(
|
||||||
|
title: loc.licenses,
|
||||||
|
icon: Icons.insert_drive_file,
|
||||||
|
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const LicensesView(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SettingsListTile(
|
||||||
|
title: loc.legal_notice,
|
||||||
|
icon: Icons.account_balance_sharp,
|
||||||
|
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onPressed: null,
|
||||||
|
),
|
||||||
|
SettingsListTile(
|
||||||
|
title: loc.privacy_policy,
|
||||||
|
icon: Icons.gpp_good_rounded,
|
||||||
|
suffixWidget: const Icon(Icons.arrow_forward_ios, size: 16),
|
||||||
|
onPressed: null,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 30, bottom: 20),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
spacing: 4,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 12),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
spacing: 40,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
child: const Icon(Icons.language),
|
||||||
|
onTap: () => {
|
||||||
|
launchUrl(Uri.parse('https://liquid-dev.de')),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
child: const FaIcon(FontAwesomeIcons.github),
|
||||||
|
onTap: () => {
|
||||||
|
launchUrl(
|
||||||
|
Uri.parse(
|
||||||
|
'https://github.com/liquiddevelopmentde',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
child: Icon(
|
||||||
|
Platform.isIOS
|
||||||
|
? CupertinoIcons.mail_solid
|
||||||
|
: Icons.email,
|
||||||
|
),
|
||||||
|
onTap: () => launchUrl(
|
||||||
|
Uri.parse('mailto:hi@liquid-dev.de'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'© ${DateFormat('yyyy').format(DateTime.now())} Liquid Development',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.grey.shade600,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Version ${_packageInfo.version} (${_packageInfo.buildNumber})',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.grey.shade600,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Displays a snackbar based on the import result.
|
||||||
|
///
|
||||||
|
/// [context] The BuildContext to show the snackbar in.
|
||||||
|
/// [result] The result of the import operation.
|
||||||
|
void showImportSnackBar({
|
||||||
|
required BuildContext context,
|
||||||
|
required ImportResult result,
|
||||||
|
}) {
|
||||||
|
final loc = AppLocalizations.of(context);
|
||||||
|
switch (result) {
|
||||||
|
case ImportResult.success:
|
||||||
|
showSnackbar(context: context, message: loc.data_successfully_imported);
|
||||||
|
case ImportResult.invalidSchema:
|
||||||
|
showSnackbar(context: context, message: loc.invalid_schema);
|
||||||
|
case ImportResult.fileReadError:
|
||||||
|
showSnackbar(context: context, message: loc.error_reading_file);
|
||||||
|
case ImportResult.canceled:
|
||||||
|
showSnackbar(context: context, message: loc.import_canceled);
|
||||||
|
case ImportResult.formatException:
|
||||||
|
showSnackbar(context: context, message: loc.format_exception);
|
||||||
|
case ImportResult.unknownException:
|
||||||
|
showSnackbar(context: context, message: loc.unknown_exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Displays a snackbar based on the export result.
|
||||||
|
///
|
||||||
|
/// [context] The BuildContext to show the snackbar in.
|
||||||
|
/// [result] The result of the export operation.
|
||||||
|
void showExportSnackBar({
|
||||||
|
required BuildContext context,
|
||||||
|
required ExportResult result,
|
||||||
|
}) {
|
||||||
|
final loc = AppLocalizations.of(context);
|
||||||
|
switch (result) {
|
||||||
|
case ExportResult.success:
|
||||||
|
showSnackbar(context: context, message: loc.data_successfully_exported);
|
||||||
|
case ExportResult.canceled:
|
||||||
|
showSnackbar(context: context, message: loc.export_canceled);
|
||||||
|
case ExportResult.unknownException:
|
||||||
|
showSnackbar(context: context, message: loc.unknown_exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Displays a snackbar with the given message and optional action.
|
||||||
|
///
|
||||||
|
/// [context] The BuildContext to show the snackbar in.
|
||||||
|
/// [message] The message to display in the snackbar.
|
||||||
|
/// [duration] The duration for which the snackbar is displayed.
|
||||||
|
/// [action] An optional callback function to execute when the action button is pressed.
|
||||||
|
void showSnackbar({
|
||||||
|
required BuildContext context,
|
||||||
|
required String message,
|
||||||
|
Duration duration = const Duration(seconds: 3),
|
||||||
|
VoidCallback? action,
|
||||||
|
}) {
|
||||||
|
final loc = AppLocalizations.of(context);
|
||||||
|
final messenger = ScaffoldMessenger.of(context);
|
||||||
|
messenger.hideCurrentSnackBar();
|
||||||
|
messenger.showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(message, style: const TextStyle(color: Colors.white)),
|
||||||
|
backgroundColor: CustomTheme.onBoxColor,
|
||||||
|
duration: duration,
|
||||||
|
action: action != null
|
||||||
|
? SnackBarAction(label: loc.undo, onPressed: action)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes the package information.
|
||||||
|
Future<void> _initPackageInfo() async {
|
||||||
|
final info = await PackageInfo.fromPlatform();
|
||||||
|
setState(() {
|
||||||
|
_packageInfo = info;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
106
lib/presentation/widgets/tiles/license_tile.dart
Normal file
106
lib/presentation/widgets/tiles/license_tile.dart
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
|
import 'package:game_tracker/presentation/views/main_menu/settings_view/licenses/license_detail_view.dart';
|
||||||
|
import 'package:game_tracker/presentation/views/main_menu/settings_view/licenses/oss_licenses.dart';
|
||||||
|
|
||||||
|
class LicenseTile extends StatelessWidget {
|
||||||
|
final Package package;
|
||||||
|
|
||||||
|
const LicenseTile({super.key, required this.package});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => LicenseDetailView(package: package),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(bottom: 8),
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 12),
|
||||||
|
decoration: CustomTheme.standardBoxDecoration.copyWith(
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
width: 50,
|
||||||
|
height: 50,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CustomTheme.primaryColor.withAlpha(40),
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
Icons.description,
|
||||||
|
color: CustomTheme.primaryColor,
|
||||||
|
size: 32,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
package.name,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (package.version != null &&
|
||||||
|
package.version!.isNotEmpty) ...[
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 2,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: CustomTheme.onBoxColor,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
'v${package.version}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.grey.shade500,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(
|
||||||
|
package.description,
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.grey.shade400,
|
||||||
|
height: 1.3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
// Arrow Icon
|
||||||
|
Icon(Icons.chevron_right, color: Colors.grey.shade600, size: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,7 +38,7 @@ class SettingsListTile extends StatelessWidget {
|
|||||||
onTap: onPressed ?? () {},
|
onTap: onPressed ?? () {},
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 14),
|
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
|
||||||
decoration: CustomTheme.standardBoxDecoration,
|
decoration: CustomTheme.standardBoxDecoration,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -47,12 +47,17 @@ class SettingsListTile extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(8),
|
width: 44,
|
||||||
|
height: 44,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: CustomTheme.primaryColor,
|
color: CustomTheme.primaryColor.withAlpha(40),
|
||||||
shape: BoxShape.circle,
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
child: Icon(
|
||||||
|
icon,
|
||||||
|
size: 28,
|
||||||
|
color: CustomTheme.primaryColor.withGreen(40),
|
||||||
),
|
),
|
||||||
child: Icon(icon, size: 24),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
|
flixcoo marked this conversation as resolved
Outdated
sneeex
commented
hier container irgendwie bisschen kleiner? bei licenses tile, steht ja wenigstens noch viel drin hier container irgendwie bisschen kleiner?
finde das wirkt so überdimensioniert
<img width="409" alt="grafik.png" src="attachments/0a67cbea-f23e-4c5e-ac1c-af50971e0d6b">
bei licenses tile, steht ja wenigstens noch viel drin
|
|||||||
Text(title, style: const TextStyle(fontSize: 18)),
|
Text(title, style: const TextStyle(fontSize: 18)),
|
||||||
|
|||||||
27
pubspec.yaml
27
pubspec.yaml
@@ -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.4+101
|
version: 0.0.5+143
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.8.1
|
sdk: ^3.8.1
|
||||||
@@ -9,27 +9,32 @@ environment:
|
|||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
|
clock: ^1.1.2
|
||||||
|
cupertino_icons: ^1.0.6
|
||||||
drift: ^2.27.0
|
drift: ^2.27.0
|
||||||
drift_flutter: ^0.2.4
|
drift_flutter: ^0.2.4
|
||||||
|
file_picker: ^10.3.6
|
||||||
|
file_saver: ^0.3.1
|
||||||
|
font_awesome_flutter: ^10.12.0
|
||||||
|
intl: any
|
||||||
|
json_schema: ^5.2.2
|
||||||
|
package_info_plus: ^9.0.0
|
||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
provider: ^6.1.5
|
provider: ^6.1.5
|
||||||
skeletonizer: ^2.1.0+1
|
skeletonizer: ^2.1.0+1
|
||||||
|
url_launcher: ^6.3.2
|
||||||
uuid: ^4.5.2
|
uuid: ^4.5.2
|
||||||
file_picker: ^10.3.6
|
|
||||||
json_schema: ^5.2.2
|
|
||||||
file_saver: ^0.3.1
|
|
||||||
clock: ^1.1.2
|
|
||||||
intl: any
|
|
||||||
flutter_localizations:
|
|
||||||
sdk: flutter
|
|
||||||
package_info_plus: ^9.0.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_lints: ^5.0.0
|
|
||||||
drift_dev: ^2.27.0
|
|
||||||
build_runner: ^2.5.4
|
build_runner: ^2.5.4
|
||||||
|
dart_pubspec_licenses: ^3.0.14
|
||||||
|
drift_dev: ^2.27.0
|
||||||
|
flutter_lints: ^5.0.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
|
|||||||
Reference in New Issue
Block a user
whitespace?