Merge pull request #87 from flixcoo/enhance/86-rework-import--and-export-button
Reworked SettingsView
This commit is contained in:
@@ -83,8 +83,9 @@
|
|||||||
"point_limit_subtitle": "... hier ist Schluss",
|
"point_limit_subtitle": "... hier ist Schluss",
|
||||||
"reset_to_default": "Auf Standard zurücksetzen",
|
"reset_to_default": "Auf Standard zurücksetzen",
|
||||||
"game_data": "Spieldaten",
|
"game_data": "Spieldaten",
|
||||||
"import_data": "Daten importieren",
|
"import_data": "Spieldaten importieren",
|
||||||
"export_data": "Daten exportieren",
|
"export_data": "Spieldaten exportieren",
|
||||||
|
"app": "App",
|
||||||
|
|
||||||
"import_success_title": "Import erfolgreich",
|
"import_success_title": "Import erfolgreich",
|
||||||
"import_success_message":"Die Spieldaten wurden erfolgreich importiert.",
|
"import_success_message":"Die Spieldaten wurden erfolgreich importiert.",
|
||||||
@@ -92,16 +93,18 @@
|
|||||||
"import_validation_error_message": "Es wurden keine Cabo-Counter Spieldaten gefunden. Bitte stellen Sie sicher, dass es sich um eine gültige Cabo-Counter Exportdatei handelt.",
|
"import_validation_error_message": "Es wurden keine Cabo-Counter Spieldaten gefunden. Bitte stellen Sie sicher, dass es sich um eine gültige Cabo-Counter Exportdatei handelt.",
|
||||||
"import_format_error_title": "Falsches Format",
|
"import_format_error_title": "Falsches Format",
|
||||||
"import_format_error_message": "Die Datei ist kein gültiges JSON-Format oder enthält ungültige Daten.",
|
"import_format_error_message": "Die Datei ist kein gültiges JSON-Format oder enthält ungültige Daten.",
|
||||||
"import_generic_error_title": "Import fehlgeschlagen",
|
"import_generic_error_title": "Import fehlgeschlagen",
|
||||||
"import_generic_error_message": "Der Import ist fehlgeschlagen.",
|
"import_generic_error_message": "Der Import ist fehlgeschlagen.",
|
||||||
|
|
||||||
"export_error_title": "Fehler",
|
"export_error_title": "Fehler",
|
||||||
"export_error_message": "Datei konnte nicht exportiert werden",
|
"export_error_message": "Datei konnte nicht exportiert werden",
|
||||||
|
|
||||||
"error_found": "Fehler gefunden?",
|
"error_found": "Fehler gefunden?",
|
||||||
"create_issue": "Issue erstellen",
|
"create_issue": "Issue erstellen",
|
||||||
|
"wiki": "Wiki",
|
||||||
"app_version": "App-Version",
|
"app_version": "App-Version",
|
||||||
"build": "Build",
|
"build": "Build-Nr.",
|
||||||
"load_version": "Lade Version...",
|
"loading": "Lädt...",
|
||||||
|
|
||||||
"about_text": "Hey :) Danke, dass du als eine:r der ersten User meiner ersten eigenen App dabei bist! Ich hab sehr viel Arbeit in dieses Projekt gesteckt und auch, wenn ich (hoffentlich) an vieles Gedacht hab, wird auf jeden Fall noch nicht alles 100% funktionieren. Solltest du also irgendwelche Fehler entdecken oder Feedback zum Design oder der Benutzerfreundlichkeit haben, teile Sie mir gern über die Testflight App oder auf den dir bekannten Wegen mit. Danke! "
|
"about_text": "Hey :) Danke, dass du als eine:r der ersten User meiner ersten eigenen App dabei bist! Ich hab sehr viel Arbeit in dieses Projekt gesteckt und auch, wenn ich (hoffentlich) an vieles Gedacht hab, wird auf jeden Fall noch nicht alles 100% funktionieren. Solltest du also irgendwelche Fehler entdecken oder Feedback zum Design oder der Benutzerfreundlichkeit haben, teile Sie mir gern über die Testflight App oder auf den dir bekannten Wegen mit. Danke! "
|
||||||
}
|
}
|
||||||
@@ -71,6 +71,10 @@
|
|||||||
"export_game": "Export Game",
|
"export_game": "Export Game",
|
||||||
|
|
||||||
"game_process": "Spielverlauf",
|
"game_process": "Spielverlauf",
|
||||||
|
"id_error_title": "ID Error",
|
||||||
|
"id_error_message": "The game has not yet been assigned an ID. If you want to delete the game, please do so via the main menu. All newly created games have an ID.",
|
||||||
|
"end_game_title": "End the game?",
|
||||||
|
"end_game_message": "Do you want to end the game? The game gets marked as finished and cannot be continued.",
|
||||||
|
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"cabo_penalty": "Cabo Penalty",
|
"cabo_penalty": "Cabo Penalty",
|
||||||
@@ -81,10 +85,7 @@
|
|||||||
"game_data": "Game Data",
|
"game_data": "Game Data",
|
||||||
"import_data": "Import Data",
|
"import_data": "Import Data",
|
||||||
"export_data": "Export Data",
|
"export_data": "Export Data",
|
||||||
"id_error_title": "ID Error",
|
"app": "App",
|
||||||
"id_error_message": "The game has not yet been assigned an ID. If you want to delete the game, please do so via the main menu. All newly created games have an ID.",
|
|
||||||
"end_game_title": "End the game?",
|
|
||||||
"end_game_message": "Do you want to end the game? The game gets marked as finished and cannot be continued.",
|
|
||||||
|
|
||||||
"import_success_title": "Import successful",
|
"import_success_title": "Import successful",
|
||||||
"import_success_message":"The game data has been successfully imported.",
|
"import_success_message":"The game data has been successfully imported.",
|
||||||
@@ -97,11 +98,13 @@
|
|||||||
|
|
||||||
"export_error_title": "Export failed",
|
"export_error_title": "Export failed",
|
||||||
"export_error_message": "Could not export file",
|
"export_error_message": "Could not export file",
|
||||||
|
|
||||||
"error_found": "Found a bug?",
|
"error_found": "Found a bug?",
|
||||||
"create_issue": "Create Issue",
|
"create_issue": "Create Issue",
|
||||||
|
"wiki": "Wiki",
|
||||||
"app_version": "App Version",
|
"app_version": "App Version",
|
||||||
"load_version": "Loading version...",
|
"loading": "Loading...",
|
||||||
"build": "Build",
|
"build": "Build No.",
|
||||||
|
|
||||||
"about_text": "Hey :) Thanks for being one of the first users of my app! I’ve put a lot of work into this project, and even though I tried to think of everything, it might not work perfectly just yet. So if you discover any bugs or have feedback on the design or usability, please let me know via the TestFlight app or by sending me a message or email. Thank you very much!"
|
"about_text": "Hey :) Thanks for being one of the first users of my app! I’ve put a lot of work into this project, and even though I tried to think of everything, it might not work perfectly just yet. So if you discover any bugs or have feedback on the design or usability, please let me know via the TestFlight app or by sending me a message or email. Thank you very much!"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -467,15 +467,21 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @import_data.
|
/// No description provided for @import_data.
|
||||||
///
|
///
|
||||||
/// In de, this message translates to:
|
/// In de, this message translates to:
|
||||||
/// **'Daten importieren'**
|
/// **'Spieldaten importieren'**
|
||||||
String get import_data;
|
String get import_data;
|
||||||
|
|
||||||
/// No description provided for @export_data.
|
/// No description provided for @export_data.
|
||||||
///
|
///
|
||||||
/// In de, this message translates to:
|
/// In de, this message translates to:
|
||||||
/// **'Daten exportieren'**
|
/// **'Spieldaten exportieren'**
|
||||||
String get export_data;
|
String get export_data;
|
||||||
|
|
||||||
|
/// No description provided for @app.
|
||||||
|
///
|
||||||
|
/// In de, this message translates to:
|
||||||
|
/// **'App'**
|
||||||
|
String get app;
|
||||||
|
|
||||||
/// No description provided for @import_success_title.
|
/// No description provided for @import_success_title.
|
||||||
///
|
///
|
||||||
/// In de, this message translates to:
|
/// In de, this message translates to:
|
||||||
@@ -548,6 +554,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Issue erstellen'**
|
/// **'Issue erstellen'**
|
||||||
String get create_issue;
|
String get create_issue;
|
||||||
|
|
||||||
|
/// No description provided for @wiki.
|
||||||
|
///
|
||||||
|
/// In de, this message translates to:
|
||||||
|
/// **'Wiki'**
|
||||||
|
String get wiki;
|
||||||
|
|
||||||
/// No description provided for @app_version.
|
/// No description provided for @app_version.
|
||||||
///
|
///
|
||||||
/// In de, this message translates to:
|
/// In de, this message translates to:
|
||||||
@@ -557,14 +569,14 @@ abstract class AppLocalizations {
|
|||||||
/// No description provided for @build.
|
/// No description provided for @build.
|
||||||
///
|
///
|
||||||
/// In de, this message translates to:
|
/// In de, this message translates to:
|
||||||
/// **'Build'**
|
/// **'Build-Nr.'**
|
||||||
String get build;
|
String get build;
|
||||||
|
|
||||||
/// No description provided for @load_version.
|
/// No description provided for @loading.
|
||||||
///
|
///
|
||||||
/// In de, this message translates to:
|
/// In de, this message translates to:
|
||||||
/// **'Lade Version...'**
|
/// **'Lädt...'**
|
||||||
String get load_version;
|
String get loading;
|
||||||
|
|
||||||
/// No description provided for @about_text.
|
/// No description provided for @about_text.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -203,10 +203,13 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
String get game_data => 'Spieldaten';
|
String get game_data => 'Spieldaten';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get import_data => 'Daten importieren';
|
String get import_data => 'Spieldaten importieren';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get export_data => 'Daten exportieren';
|
String get export_data => 'Spieldaten exportieren';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get app => 'App';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get import_success_title => 'Import erfolgreich';
|
String get import_success_title => 'Import erfolgreich';
|
||||||
@@ -247,14 +250,17 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get create_issue => 'Issue erstellen';
|
String get create_issue => 'Issue erstellen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get wiki => 'Wiki';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get app_version => 'App-Version';
|
String get app_version => 'App-Version';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get build => 'Build';
|
String get build => 'Build-Nr.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get load_version => 'Lade Version...';
|
String get loading => 'Lädt...';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get about_text =>
|
String get about_text =>
|
||||||
|
|||||||
@@ -205,6 +205,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get export_data => 'Export Data';
|
String get export_data => 'Export Data';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get app => 'App';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get import_success_title => 'Import successful';
|
String get import_success_title => 'Import successful';
|
||||||
|
|
||||||
@@ -244,14 +247,17 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get create_issue => 'Create Issue';
|
String get create_issue => 'Create Issue';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get wiki => 'Wiki';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get app_version => 'App Version';
|
String get app_version => 'App Version';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get build => 'Build';
|
String get build => 'Build No.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get load_version => 'Loading version...';
|
String get loading => 'Loading...';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get about_text =>
|
String get about_text =>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import 'package:cabo_counter/l10n/app_localizations.dart';
|
import 'package:cabo_counter/l10n/app_localizations.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/tab_view.dart';
|
||||||
import 'package:cabo_counter/services/config_service.dart';
|
import 'package:cabo_counter/services/config_service.dart';
|
||||||
import 'package:cabo_counter/services/local_storage_service.dart';
|
import 'package:cabo_counter/services/local_storage_service.dart';
|
||||||
|
import 'package:cabo_counter/services/version_service.dart';
|
||||||
import 'package:cabo_counter/utility/custom_theme.dart';
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
import 'package:cabo_counter/views/tab_view.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ Future<void> main() async {
|
|||||||
await ConfigService.initConfig();
|
await ConfigService.initConfig();
|
||||||
ConfigService.pointLimit = await ConfigService.getPointLimit();
|
ConfigService.pointLimit = await ConfigService.getPointLimit();
|
||||||
ConfigService.caboPenalty = await ConfigService.getCaboPenalty();
|
ConfigService.caboPenalty = await ConfigService.getCaboPenalty();
|
||||||
|
await VersionService.init();
|
||||||
runApp(const App());
|
runApp(const App());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'package:cabo_counter/data/game_manager.dart';
|
import 'package:cabo_counter/data/game_manager.dart';
|
||||||
import 'package:cabo_counter/data/game_session.dart';
|
import 'package:cabo_counter/data/game_session.dart';
|
||||||
import 'package:cabo_counter/l10n/app_localizations.dart';
|
import 'package:cabo_counter/l10n/app_localizations.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/create_game_view.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/graph_view.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/round_view.dart';
|
||||||
import 'package:cabo_counter/services/local_storage_service.dart';
|
import 'package:cabo_counter/services/local_storage_service.dart';
|
||||||
import 'package:cabo_counter/utility/custom_theme.dart';
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
import 'package:cabo_counter/views/create_game_view.dart';
|
|
||||||
import 'package:cabo_counter/views/graph_view.dart';
|
|
||||||
import 'package:cabo_counter/views/round_view.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'package:cabo_counter/data/game_manager.dart';
|
import 'package:cabo_counter/data/game_manager.dart';
|
||||||
import 'package:cabo_counter/data/game_session.dart';
|
import 'package:cabo_counter/data/game_session.dart';
|
||||||
import 'package:cabo_counter/l10n/app_localizations.dart';
|
import 'package:cabo_counter/l10n/app_localizations.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/active_game_view.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/mode_selection_view.dart';
|
||||||
import 'package:cabo_counter/services/config_service.dart';
|
import 'package:cabo_counter/services/config_service.dart';
|
||||||
import 'package:cabo_counter/utility/custom_theme.dart';
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
import 'package:cabo_counter/views/active_game_view.dart';
|
|
||||||
import 'package:cabo_counter/views/mode_selection_view.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
enum CreateStatus {
|
enum CreateStatus {
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import 'package:cabo_counter/data/game_manager.dart';
|
import 'package:cabo_counter/data/game_manager.dart';
|
||||||
import 'package:cabo_counter/l10n/app_localizations.dart';
|
import 'package:cabo_counter/l10n/app_localizations.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/active_game_view.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/create_game_view.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/settings_view.dart';
|
||||||
import 'package:cabo_counter/services/config_service.dart';
|
import 'package:cabo_counter/services/config_service.dart';
|
||||||
import 'package:cabo_counter/services/local_storage_service.dart';
|
import 'package:cabo_counter/services/local_storage_service.dart';
|
||||||
import 'package:cabo_counter/utility/custom_theme.dart';
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
import 'package:cabo_counter/views/active_game_view.dart';
|
|
||||||
import 'package:cabo_counter/views/create_game_view.dart';
|
|
||||||
import 'package:cabo_counter/views/settings_view.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
230
lib/presentation/views/settings_view.dart
Normal file
230
lib/presentation/views/settings_view.dart
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
import 'package:cabo_counter/l10n/app_localizations.dart';
|
||||||
|
import 'package:cabo_counter/presentation/widgets/custom_form_row.dart';
|
||||||
|
import 'package:cabo_counter/presentation/widgets/stepper.dart';
|
||||||
|
import 'package:cabo_counter/services/config_service.dart';
|
||||||
|
import 'package:cabo_counter/services/local_storage_service.dart';
|
||||||
|
import 'package:cabo_counter/services/version_service.dart';
|
||||||
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.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> {
|
||||||
|
UniqueKey _stepperKey1 = UniqueKey();
|
||||||
|
UniqueKey _stepperKey2 = UniqueKey();
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CupertinoPageScaffold(
|
||||||
|
navigationBar: CupertinoNavigationBar(
|
||||||
|
middle: Text(AppLocalizations.of(context).settings),
|
||||||
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).points,
|
||||||
|
style: CustomTheme.rowTitle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 15, 10, 10),
|
||||||
|
child: CupertinoFormSection.insetGrouped(
|
||||||
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
children: [
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: 'Cabo-Strafe',
|
||||||
|
prefixIcon: CupertinoIcons.bolt_fill,
|
||||||
|
suffixWidget: Stepper(
|
||||||
|
key: _stepperKey1,
|
||||||
|
initialValue: ConfigService.caboPenalty,
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 50,
|
||||||
|
step: 1,
|
||||||
|
onChanged: (newCaboPenalty) {
|
||||||
|
setState(() {
|
||||||
|
ConfigService.setCaboPenalty(newCaboPenalty);
|
||||||
|
ConfigService.caboPenalty = newCaboPenalty;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: 'Punkte-Limit',
|
||||||
|
prefixIcon: FontAwesomeIcons.bullseye,
|
||||||
|
suffixWidget: Stepper(
|
||||||
|
key: _stepperKey2,
|
||||||
|
initialValue: ConfigService.pointLimit,
|
||||||
|
minValue: 30,
|
||||||
|
maxValue: 1000,
|
||||||
|
step: 10,
|
||||||
|
onChanged: (newPointLimit) {
|
||||||
|
setState(() {
|
||||||
|
ConfigService.setPointLimit(newPointLimit);
|
||||||
|
ConfigService.pointLimit = newPointLimit;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText:
|
||||||
|
AppLocalizations.of(context).reset_to_default,
|
||||||
|
prefixIcon: CupertinoIcons.arrow_counterclockwise,
|
||||||
|
onPressed: () {
|
||||||
|
ConfigService.resetConfig();
|
||||||
|
setState(() {
|
||||||
|
_stepperKey1 = UniqueKey();
|
||||||
|
_stepperKey2 = UniqueKey();
|
||||||
|
print('Config reset to default');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
])),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).game_data,
|
||||||
|
style: CustomTheme.rowTitle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 15, 10, 10),
|
||||||
|
child: CupertinoFormSection.insetGrouped(
|
||||||
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
children: [
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: AppLocalizations.of(context).import_data,
|
||||||
|
prefixIcon: CupertinoIcons.square_arrow_down,
|
||||||
|
onPressed: () async {
|
||||||
|
final status =
|
||||||
|
await LocalStorageService.importJsonFile();
|
||||||
|
showFeedbackDialog(status);
|
||||||
|
},
|
||||||
|
suffixWidget: const CupertinoListTileChevron(),
|
||||||
|
),
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: AppLocalizations.of(context).export_data,
|
||||||
|
prefixIcon: CupertinoIcons.square_arrow_up,
|
||||||
|
onPressed: () => LocalStorageService.exportGameData(),
|
||||||
|
suffixWidget: const CupertinoListTileChevron(),
|
||||||
|
),
|
||||||
|
])),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
||||||
|
child: Text(
|
||||||
|
AppLocalizations.of(context).app,
|
||||||
|
style: CustomTheme.rowTitle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(10, 15, 10, 0),
|
||||||
|
child: CupertinoFormSection.insetGrouped(
|
||||||
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
children: [
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: AppLocalizations.of(context).create_issue,
|
||||||
|
prefixIcon: FontAwesomeIcons.github,
|
||||||
|
onPressed: () => launchUrl(Uri.parse(
|
||||||
|
'https://github.com/flixcoo/Cabo-Counter/issues')),
|
||||||
|
suffixWidget: const CupertinoListTileChevron(),
|
||||||
|
),
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: AppLocalizations.of(context).wiki,
|
||||||
|
prefixIcon: CupertinoIcons.book,
|
||||||
|
onPressed: () => launchUrl(Uri.parse(
|
||||||
|
'https://github.com/flixcoo/Cabo-Counter/wiki')),
|
||||||
|
suffixWidget: const CupertinoListTileChevron(),
|
||||||
|
),
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText:
|
||||||
|
AppLocalizations.of(context).app_version,
|
||||||
|
prefixIcon: CupertinoIcons.tag,
|
||||||
|
onPressed: null,
|
||||||
|
suffixWidget: Text(VersionService.getVersion(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: CustomTheme.primaryColor,
|
||||||
|
))),
|
||||||
|
CustomFormRow(
|
||||||
|
prefixText: AppLocalizations.of(context).build,
|
||||||
|
prefixIcon: CupertinoIcons.number,
|
||||||
|
onPressed: null,
|
||||||
|
suffixWidget: Text(VersionService.getBuildNumber(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: CustomTheme.primaryColor,
|
||||||
|
))),
|
||||||
|
])),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showFeedbackDialog(ImportStatus status) {
|
||||||
|
if (status == ImportStatus.canceled) return;
|
||||||
|
final (title, message) = _getDialogContent(status);
|
||||||
|
|
||||||
|
showCupertinoDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return CupertinoAlertDialog(
|
||||||
|
title: Text(title),
|
||||||
|
content: Text(message),
|
||||||
|
actions: [
|
||||||
|
CupertinoDialogAction(
|
||||||
|
child: Text(AppLocalizations.of(context).ok),
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
(String, String) _getDialogContent(ImportStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case ImportStatus.success:
|
||||||
|
return (
|
||||||
|
AppLocalizations.of(context).import_success_title,
|
||||||
|
AppLocalizations.of(context).import_success_message
|
||||||
|
);
|
||||||
|
case ImportStatus.validationError:
|
||||||
|
return (
|
||||||
|
AppLocalizations.of(context).import_validation_error_title,
|
||||||
|
AppLocalizations.of(context).import_validation_error_message
|
||||||
|
);
|
||||||
|
|
||||||
|
case ImportStatus.formatError:
|
||||||
|
return (
|
||||||
|
AppLocalizations.of(context).import_format_error_title,
|
||||||
|
AppLocalizations.of(context).import_format_error_message
|
||||||
|
);
|
||||||
|
case ImportStatus.genericError:
|
||||||
|
return (
|
||||||
|
AppLocalizations.of(context).import_generic_error_title,
|
||||||
|
AppLocalizations.of(context).import_generic_error_message
|
||||||
|
);
|
||||||
|
case ImportStatus.canceled:
|
||||||
|
return ('', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:cabo_counter/l10n/app_localizations.dart';
|
import 'package:cabo_counter/l10n/app_localizations.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/information_view.dart';
|
||||||
|
import 'package:cabo_counter/presentation/views/main_menu_view.dart';
|
||||||
import 'package:cabo_counter/utility/custom_theme.dart';
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
import 'package:cabo_counter/views/information_view.dart';
|
|
||||||
import 'package:cabo_counter/views/main_menu_view.dart';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
class TabView extends StatefulWidget {
|
class TabView extends StatefulWidget {
|
||||||
53
lib/presentation/widgets/custom_form_row.dart
Normal file
53
lib/presentation/widgets/custom_form_row.dart
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import 'package:cabo_counter/presentation/widgets/stepper.dart';
|
||||||
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
|
class CustomFormRow extends StatefulWidget {
|
||||||
|
final String prefixText;
|
||||||
|
final IconData prefixIcon;
|
||||||
|
final Widget? suffixWidget;
|
||||||
|
final void Function()? onPressed;
|
||||||
|
const CustomFormRow({
|
||||||
|
super.key,
|
||||||
|
required this.prefixText,
|
||||||
|
required this.prefixIcon,
|
||||||
|
this.onPressed,
|
||||||
|
this.suffixWidget,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CustomFormRow> createState() => _CustomFormRowState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomFormRowState extends State<CustomFormRow> {
|
||||||
|
late Widget suffixWidget;
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
suffixWidget = widget.suffixWidget ?? const SizedBox.shrink();
|
||||||
|
return CupertinoButton(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
onPressed: widget.onPressed,
|
||||||
|
child: CupertinoFormRow(
|
||||||
|
prefix: Row(
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
widget.prefixIcon,
|
||||||
|
color: CustomTheme.primaryColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(widget.prefixText),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: suffixWidget is Stepper
|
||||||
|
? const EdgeInsets.fromLTRB(15, 0, 0, 0)
|
||||||
|
: const EdgeInsets.symmetric(vertical: 10, horizontal: 15),
|
||||||
|
child: suffixWidget,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:cabo_counter/utility/custom_theme.dart';
|
||||||
import 'package:flutter/cupertino.dart'; // Für iOS-Style
|
import 'package:flutter/cupertino.dart'; // Für iOS-Style
|
||||||
|
|
||||||
class Stepper extends StatefulWidget {
|
class Stepper extends StatefulWidget {
|
||||||
@@ -34,18 +35,20 @@ class _StepperState extends State<Stepper> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
CupertinoButton(
|
CupertinoButton(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: EdgeInsets.zero,
|
||||||
onPressed: _decrement,
|
onPressed: _decrement,
|
||||||
child: const Icon(CupertinoIcons.minus),
|
child: const Icon(CupertinoIcons.minus),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||||
child: Text('$_value', style: const TextStyle(fontSize: 18)),
|
child: Text('$_value',
|
||||||
|
style: TextStyle(fontSize: 18, color: CustomTheme.white)),
|
||||||
),
|
),
|
||||||
CupertinoButton(
|
CupertinoButton(
|
||||||
padding: const EdgeInsets.all(8),
|
padding: EdgeInsets.zero,
|
||||||
onPressed: _increment,
|
onPressed: _increment,
|
||||||
child: const Icon(CupertinoIcons.add),
|
child: const Icon(CupertinoIcons.add),
|
||||||
),
|
),
|
||||||
@@ -21,7 +21,7 @@ class LocalStorageService {
|
|||||||
static const String _fileName = 'game_data.json';
|
static const String _fileName = 'game_data.json';
|
||||||
|
|
||||||
/// Writes the game session list to a JSON file and returns it as string.
|
/// Writes the game session list to a JSON file and returns it as string.
|
||||||
static String getGameDataAsJsonFile() {
|
static String _getGameDataAsJsonFile() {
|
||||||
final jsonFile =
|
final jsonFile =
|
||||||
gameManager.gameList.map((session) => session.toJson()).toList();
|
gameManager.gameList.map((session) => session.toJson()).toList();
|
||||||
return json.encode(jsonFile);
|
return json.encode(jsonFile);
|
||||||
@@ -39,7 +39,7 @@ class LocalStorageService {
|
|||||||
print('[local_storage_service.dart] Versuche, Daten zu speichern...');
|
print('[local_storage_service.dart] Versuche, Daten zu speichern...');
|
||||||
try {
|
try {
|
||||||
final file = await _getFilePath();
|
final file = await _getFilePath();
|
||||||
final jsonFile = getGameDataAsJsonFile();
|
final jsonFile = _getGameDataAsJsonFile();
|
||||||
await file.writeAsString(jsonFile);
|
await file.writeAsString(jsonFile);
|
||||||
print(
|
print(
|
||||||
'[local_storage_service.dart] Die Spieldaten wurden zwischengespeichert.');
|
'[local_storage_service.dart] Die Spieldaten wurden zwischengespeichert.');
|
||||||
@@ -70,7 +70,7 @@ class LocalStorageService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!await validateJsonSchema(jsonString, true)) {
|
if (!await _validateJsonSchema(jsonString, true)) {
|
||||||
print(
|
print(
|
||||||
'[local_storage_service.dart] Die Datei konnte nicht validiert werden');
|
'[local_storage_service.dart] Die Datei konnte nicht validiert werden');
|
||||||
gameManager.gameList = [];
|
gameManager.gameList = [];
|
||||||
@@ -105,7 +105,7 @@ class LocalStorageService {
|
|||||||
/// Opens the file picker to export game data as a JSON file.
|
/// Opens the file picker to export game data as a JSON file.
|
||||||
/// This method will export the given [jsonString] as a JSON file. It opens
|
/// This method will export the given [jsonString] as a JSON file. It opens
|
||||||
/// the file picker with the choosen [fileName].
|
/// the file picker with the choosen [fileName].
|
||||||
static Future<bool> exportJsonData(
|
static Future<bool> _exportJsonData(
|
||||||
String jsonString,
|
String jsonString,
|
||||||
String fileName,
|
String fileName,
|
||||||
) async {
|
) async {
|
||||||
@@ -133,16 +133,16 @@ class LocalStorageService {
|
|||||||
|
|
||||||
/// Opens the file picker to export all game sessions as a JSON file.
|
/// Opens the file picker to export all game sessions as a JSON file.
|
||||||
static Future<bool> exportGameData() async {
|
static Future<bool> exportGameData() async {
|
||||||
String jsonString = getGameDataAsJsonFile();
|
String jsonString = _getGameDataAsJsonFile();
|
||||||
String fileName = 'cabo_counter-game_data';
|
String fileName = 'cabo_counter-game_data';
|
||||||
return exportJsonData(jsonString, fileName);
|
return _exportJsonData(jsonString, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the file picker to save a single game session as a JSON file.
|
/// Opens the file picker to save a single game session as a JSON file.
|
||||||
static Future<bool> exportSingleGameSession(GameSession session) async {
|
static Future<bool> exportSingleGameSession(GameSession session) async {
|
||||||
String jsonString = json.encode(session.toJson());
|
String jsonString = json.encode(session.toJson());
|
||||||
String fileName = 'cabo_counter-game_${session.id.substring(0, 7)}';
|
String fileName = 'cabo_counter-game_${session.id.substring(0, 7)}';
|
||||||
return exportJsonData(jsonString, fileName);
|
return _exportJsonData(jsonString, fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Opens the file picker to import a JSON file and loads the game data from it.
|
/// Opens the file picker to import a JSON file and loads the game data from it.
|
||||||
@@ -162,7 +162,7 @@ class LocalStorageService {
|
|||||||
try {
|
try {
|
||||||
final jsonString = await _readFileContent(path.files.single);
|
final jsonString = await _readFileContent(path.files.single);
|
||||||
|
|
||||||
if (await validateJsonSchema(jsonString, true)) {
|
if (await _validateJsonSchema(jsonString, true)) {
|
||||||
// Checks if the JSON String is in the gameList format
|
// Checks if the JSON String is in the gameList format
|
||||||
|
|
||||||
final jsonData = json.decode(jsonString) as List<dynamic>;
|
final jsonData = json.decode(jsonString) as List<dynamic>;
|
||||||
@@ -172,12 +172,12 @@ class LocalStorageService {
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
for (GameSession s in importedList) {
|
for (GameSession s in importedList) {
|
||||||
importSession(s);
|
_importSession(s);
|
||||||
}
|
}
|
||||||
} else if (await validateJsonSchema(jsonString, false)) {
|
} else if (await _validateJsonSchema(jsonString, false)) {
|
||||||
// Checks if the JSON String is in the single game format
|
// Checks if the JSON String is in the single game format
|
||||||
final jsonData = json.decode(jsonString) as Map<String, dynamic>;
|
final jsonData = json.decode(jsonString) as Map<String, dynamic>;
|
||||||
importSession(GameSession.fromJson(jsonData));
|
_importSession(GameSession.fromJson(jsonData));
|
||||||
} else {
|
} else {
|
||||||
return ImportStatus.validationError;
|
return ImportStatus.validationError;
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ class LocalStorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Imports a single game session into the gameList.
|
/// Imports a single game session into the gameList.
|
||||||
static Future<void> importSession(GameSession session) async {
|
static Future<void> _importSession(GameSession session) async {
|
||||||
if (gameManager.gameExistsInGameList(session.id)) {
|
if (gameManager.gameExistsInGameList(session.id)) {
|
||||||
print(
|
print(
|
||||||
'[local_storage_service.dart] Die Session mit der ID ${session.id} existiert bereits. Sie wird überschrieben.');
|
'[local_storage_service.dart] Die Session mit der ID ${session.id} existiert bereits. Sie wird überschrieben.');
|
||||||
@@ -221,7 +221,7 @@ class LocalStorageService {
|
|||||||
/// This method checks if the provided [jsonString] is valid against the
|
/// This method checks if the provided [jsonString] is valid against the
|
||||||
/// JSON schema. It takes a boolean [isGameList] to determine
|
/// JSON schema. It takes a boolean [isGameList] to determine
|
||||||
/// which schema to use (game list or single game).
|
/// which schema to use (game list or single game).
|
||||||
static Future<bool> validateJsonSchema(
|
static Future<bool> _validateJsonSchema(
|
||||||
String jsonString, bool isGameList) async {
|
String jsonString, bool isGameList) async {
|
||||||
final String schemaString;
|
final String schemaString;
|
||||||
|
|
||||||
|
|||||||
32
lib/services/version_service.dart
Normal file
32
lib/services/version_service.dart
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import 'package:cabo_counter/utility/globals.dart';
|
||||||
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
|
class VersionService {
|
||||||
|
static String _version = '-.-.-';
|
||||||
|
static String _buildNumber = '-';
|
||||||
|
|
||||||
|
static Future<void> init() async {
|
||||||
|
var packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
_version = packageInfo.version;
|
||||||
|
_buildNumber = packageInfo.buildNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getVersionNumber() {
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getVersion() {
|
||||||
|
if (_version == '-.-.-') {
|
||||||
|
return getVersionNumber();
|
||||||
|
}
|
||||||
|
return '${Globals.appDevPhase} $_version';
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getBuildNumber() {
|
||||||
|
return _buildNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String getVersionWithBuild() {
|
||||||
|
return '$_version ($_buildNumber)';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
import 'package:cabo_counter/l10n/app_localizations.dart';
|
|
||||||
import 'package:cabo_counter/services/config_service.dart';
|
|
||||||
import 'package:cabo_counter/services/local_storage_service.dart';
|
|
||||||
import 'package:cabo_counter/utility/custom_theme.dart';
|
|
||||||
import 'package:cabo_counter/utility/globals.dart';
|
|
||||||
import 'package:cabo_counter/widgets/stepper.dart';
|
|
||||||
import 'package:flutter/cupertino.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> {
|
|
||||||
UniqueKey _stepperKey1 = UniqueKey();
|
|
||||||
UniqueKey _stepperKey2 = UniqueKey();
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return CupertinoPageScaffold(
|
|
||||||
navigationBar: CupertinoNavigationBar(
|
|
||||||
middle: Text(AppLocalizations.of(context).settings),
|
|
||||||
),
|
|
||||||
child: SafeArea(
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context).points,
|
|
||||||
style: CustomTheme.rowTitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(15, 10, 10, 0),
|
|
||||||
child: CupertinoListTile(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
title: Text(AppLocalizations.of(context).cabo_penalty),
|
|
||||||
subtitle: Text(
|
|
||||||
AppLocalizations.of(context).cabo_penalty_subtitle),
|
|
||||||
trailing: Stepper(
|
|
||||||
key: _stepperKey1,
|
|
||||||
initialValue: ConfigService.caboPenalty,
|
|
||||||
minValue: 0,
|
|
||||||
maxValue: 50,
|
|
||||||
step: 1,
|
|
||||||
onChanged: (newCaboPenalty) {
|
|
||||||
setState(() {
|
|
||||||
ConfigService.setCaboPenalty(newCaboPenalty);
|
|
||||||
ConfigService.caboPenalty = newCaboPenalty;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(15, 10, 10, 0),
|
|
||||||
child: CupertinoListTile(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
title: Text(AppLocalizations.of(context).point_limit),
|
|
||||||
subtitle:
|
|
||||||
Text(AppLocalizations.of(context).point_limit_subtitle),
|
|
||||||
trailing: Stepper(
|
|
||||||
key: _stepperKey2,
|
|
||||||
initialValue: ConfigService.pointLimit,
|
|
||||||
minValue: 30,
|
|
||||||
maxValue: 1000,
|
|
||||||
step: 10,
|
|
||||||
onChanged: (newPointLimit) {
|
|
||||||
setState(() {
|
|
||||||
ConfigService.setPointLimit(newPointLimit);
|
|
||||||
ConfigService.pointLimit = newPointLimit;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
|
|
||||||
child: Center(
|
|
||||||
heightFactor: 0.9,
|
|
||||||
child: CupertinoButton(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
onPressed: () => setState(() {
|
|
||||||
ConfigService.resetConfig();
|
|
||||||
_stepperKey1 = UniqueKey();
|
|
||||||
_stepperKey2 = UniqueKey();
|
|
||||||
}),
|
|
||||||
child:
|
|
||||||
Text(AppLocalizations.of(context).reset_to_default),
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(10, 10, 0, 0),
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context).game_data,
|
|
||||||
style: CustomTheme.rowTitle,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 30),
|
|
||||||
child: Center(
|
|
||||||
heightFactor: 1,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
CupertinoButton(
|
|
||||||
color: CustomTheme.primaryColor,
|
|
||||||
sizeStyle: CupertinoButtonSize.medium,
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context).import_data,
|
|
||||||
style:
|
|
||||||
TextStyle(color: CustomTheme.backgroundColor),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
final success =
|
|
||||||
await LocalStorageService.importJsonFile();
|
|
||||||
showFeedbackDialog(success);
|
|
||||||
}),
|
|
||||||
const SizedBox(
|
|
||||||
width: 20,
|
|
||||||
),
|
|
||||||
CupertinoButton(
|
|
||||||
color: CustomTheme.primaryColor,
|
|
||||||
sizeStyle: CupertinoButtonSize.medium,
|
|
||||||
child: Text(
|
|
||||||
AppLocalizations.of(context).export_data,
|
|
||||||
style:
|
|
||||||
TextStyle(color: CustomTheme.backgroundColor),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
|
||||||
final success =
|
|
||||||
await LocalStorageService.exportGameData();
|
|
||||||
if (!success && context.mounted) {
|
|
||||||
showCupertinoDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => CupertinoAlertDialog(
|
|
||||||
title: Text(AppLocalizations.of(context)
|
|
||||||
.export_error_title),
|
|
||||||
content: Text(AppLocalizations.of(context)
|
|
||||||
.export_error_message),
|
|
||||||
actions: [
|
|
||||||
CupertinoDialogAction(
|
|
||||||
child:
|
|
||||||
Text(AppLocalizations.of(context).ok),
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
bottom: 30,
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Center(
|
|
||||||
child: Text(AppLocalizations.of(context).error_found),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 30),
|
|
||||||
child: Center(
|
|
||||||
child: CupertinoButton(
|
|
||||||
onPressed: () => launchUrl(Uri.parse(
|
|
||||||
'https://github.com/flixcoo/Cabo-Counter/issues')),
|
|
||||||
child: Text(AppLocalizations.of(context).create_issue),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FutureBuilder<PackageInfo>(
|
|
||||||
future: _getPackageInfo(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (snapshot.hasData) {
|
|
||||||
return Text(
|
|
||||||
'${Globals.appDevPhase} ${snapshot.data!.version} '
|
|
||||||
'(${AppLocalizations.of(context).build} ${snapshot.data!.buildNumber})',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
} else if (snapshot.hasError) {
|
|
||||||
return Text(
|
|
||||||
'${AppLocalizations.of(context).app_version} -.-.- (${AppLocalizations.of(context).build} -)',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Text(
|
|
||||||
AppLocalizations.of(context).load_version,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<PackageInfo> _getPackageInfo() async {
|
|
||||||
return await PackageInfo.fromPlatform();
|
|
||||||
}
|
|
||||||
|
|
||||||
void showFeedbackDialog(ImportStatus status) {
|
|
||||||
if (status == ImportStatus.canceled) return;
|
|
||||||
final (title, message) = _getDialogContent(status);
|
|
||||||
|
|
||||||
showCupertinoDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) {
|
|
||||||
return CupertinoAlertDialog(
|
|
||||||
title: Text(title),
|
|
||||||
content: Text(message),
|
|
||||||
actions: [
|
|
||||||
CupertinoDialogAction(
|
|
||||||
child: Text(AppLocalizations.of(context).ok),
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
(String, String) _getDialogContent(ImportStatus status) {
|
|
||||||
switch (status) {
|
|
||||||
case ImportStatus.success:
|
|
||||||
return (
|
|
||||||
AppLocalizations.of(context).import_success_title,
|
|
||||||
AppLocalizations.of(context).import_success_message
|
|
||||||
);
|
|
||||||
case ImportStatus.validationError:
|
|
||||||
return (
|
|
||||||
AppLocalizations.of(context).import_validation_error_title,
|
|
||||||
AppLocalizations.of(context).import_validation_error_message
|
|
||||||
);
|
|
||||||
|
|
||||||
case ImportStatus.formatError:
|
|
||||||
return (
|
|
||||||
AppLocalizations.of(context).import_format_error_title,
|
|
||||||
AppLocalizations.of(context).import_format_error_message
|
|
||||||
);
|
|
||||||
case ImportStatus.genericError:
|
|
||||||
return (
|
|
||||||
AppLocalizations.of(context).import_generic_error_title,
|
|
||||||
AppLocalizations.of(context).import_generic_error_message
|
|
||||||
);
|
|
||||||
case ImportStatus.canceled:
|
|
||||||
return ('', '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ name: cabo_counter
|
|||||||
description: "Mobile app for the card game Cabo"
|
description: "Mobile app for the card game Cabo"
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
|
|
||||||
version: 0.3.9+331
|
version: 0.4.0+382
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.5.4
|
sdk: ^3.5.4
|
||||||
|
|||||||
Reference in New Issue
Block a user