From 8d8a9ccf2c5c6910ae5963811f24d9ce326ae0e3 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Fri, 17 Feb 2023 13:47:52 +0100 Subject: [PATCH 01/13] wip --- assets/config.json | 4 +++ lib/main.dart | 2 +- lib/models/settings.dart | 13 ++++++++++ lib/pages/main_page.dart | 36 +++++++++++++++++++-------- lib/pages/scanner_page.dart | 27 ++++++++++++++++++++ lib/pages/settings_page.dart | 10 -------- lib/service/json_service.dart | 9 +++++++ lib/service/settings_service.dart | 24 ++++++++++++++++++ lib/widgets/missing_config_popup.dart | 19 ++++++++++++++ pubspec.yaml | 2 ++ 10 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 assets/config.json create mode 100644 lib/models/settings.dart create mode 100644 lib/pages/scanner_page.dart delete mode 100644 lib/pages/settings_page.dart create mode 100644 lib/service/json_service.dart create mode 100644 lib/widgets/missing_config_popup.dart diff --git a/assets/config.json b/assets/config.json new file mode 100644 index 0000000..a80b05f --- /dev/null +++ b/assets/config.json @@ -0,0 +1,4 @@ +{ + "group": "Gruppe 2", + "key": "value" +} diff --git a/lib/main.dart b/lib/main.dart index bc91015..6e5d7a5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,6 +10,6 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return const MaterialApp(title: _title, home: MyHomePage()); + return MaterialApp(title: _title, home: MyHomePage()); } } diff --git a/lib/models/settings.dart b/lib/models/settings.dart new file mode 100644 index 0000000..4dced6e --- /dev/null +++ b/lib/models/settings.dart @@ -0,0 +1,13 @@ +class Settings { + final String group; + final String key; + //final List relapseCategories; + + Settings(this.group, this.key); //, this.relapseCategories); + + Settings.fromJson(Map json) + : group = json['group'].toString(), + key = json['key'].toString() + //relapseCategories = json['relapse_categories'] + ; +} diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 3241a4c..a1f7213 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/pages/mood_page.dart'; import 'package:smoke_cess_app/pages/relapse_page.dart'; -import 'package:smoke_cess_app/pages/settings_page.dart'; +import 'package:smoke_cess_app/pages/scanner_page.dart'; import 'package:smoke_cess_app/pages/sleep_page.dart'; import 'package:smoke_cess_app/pages/timer_page.dart'; +import 'package:smoke_cess_app/service/settings_service.dart'; +import 'package:smoke_cess_app/widgets/missing_config_popup.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @@ -13,24 +15,38 @@ class MyHomePage extends StatefulWidget { } class MyHomePageState extends State { - int _selectedIndex = 2; + int _selectedIndex = 4; + final SettingsService settingsService = SettingsService(); + final List _titles = [ 'Stimmung', 'Schlaf', 'Timer', 'Rückfall', - 'Einstellungen' + 'Scanner' ]; - static const List _widgetOptions = [ - MoodPage(), - SleepPage(), - StopWatchTimerPage(), - RelapsePage(), + static final List _widgetOptions = [ + const MoodPage(), + const SleepPage(), + const StopWatchTimerPage(), + const RelapsePage(), SettingsPage(), ]; void _onItemTapped(int index) { - setState(() => _selectedIndex = index); + setState(() async { + (await settingsService.getGroup() != null) + ? _selectedIndex = index + : showDialog( + context: context, + builder: (BuildContext context) { + Future.delayed( + const Duration(seconds: 3), + () => Navigator.of(context) + .pop(true)); //Dismiss popup after 3 seconds + return const MissingConfigPopup(); + }); + }); } @override @@ -58,7 +74,7 @@ class MyHomePageState extends State { icon: Icon(Icons.smoke_free_outlined, color: Colors.black), label: 'Rückfall'), NavigationDestination( - icon: Icon(Icons.settings, color: Colors.black), + icon: Icon(Icons.camera_alt_outlined, color: Colors.black), label: 'Settings'), ], diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart new file mode 100644 index 0000000..f3bf96a --- /dev/null +++ b/lib/pages/scanner_page.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/service/settings_service.dart'; + +class SettingsPage extends StatelessWidget { + SettingsPage({super.key}); + SettingsService service = SettingsService(); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('Hier taucht die Kamera zum Scannen auf'), + const SizedBox(height: 30), + ElevatedButton( + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20)), + onPressed: () { + service.loadSettings(); + }, + child: const Text('Read JSON'), + ) + ], + )); + } +} diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart deleted file mode 100644 index 899b163..0000000 --- a/lib/pages/settings_page.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'package:flutter/material.dart'; - -class SettingsPage extends StatelessWidget { - const SettingsPage({super.key}); - - @override - Widget build(BuildContext context) { - return const Center(child: Text('Hier können Settings eingestellt werden')); - } -} diff --git a/lib/service/json_service.dart b/lib/service/json_service.dart new file mode 100644 index 0000000..d20dacf --- /dev/null +++ b/lib/service/json_service.dart @@ -0,0 +1,9 @@ +import 'package:flutter/services.dart'; +import 'dart:convert'; + +const String configJSONPath = 'assets/config.json'; + +Future> loadLocalConfigJSON() async { + String content = await rootBundle.loadString(configJSONPath); + return jsonDecode(content); +} diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index ebd5b05..7b41f0c 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -1,4 +1,6 @@ import 'package:shared_preferences/shared_preferences.dart'; +import 'package:smoke_cess_app/models/settings.dart'; +import 'package:smoke_cess_app/service/json_service.dart'; class SettingsService { final Future _prefs = SharedPreferences.getInstance(); @@ -7,6 +9,11 @@ class SettingsService { setIntSetting('workout_duration_minutes', 5); } + //access group setting which was saved in local storage + Future getGroup() { + return getStringSetting('group'); + } + void setStringSetting(String settingKey, String settingValue) => _prefs.then((pref) => pref.setString(settingKey, settingValue)); @@ -19,7 +26,24 @@ class SettingsService { Future getIntSetting(String settingKey) => _prefs.then((pref) => pref.getInt(settingKey)); + void setStringList(String settingKey, List list) => + _prefs.then((pref) => pref.setStringList(settingKey, list)); + //Add other setters and getters if needed //other possible SharedPreferences Types: Int, Bool, Double, StringList //see https://pub.dev/packages/shared_preferences + + Future loadSettings() async { + Map configJSON = await loadLocalConfigJSON(); + Settings settings = Settings.fromJson(configJSON); + print(settings.group); + saveSettings(settings); + String gruppe = (await getGroup())!; + print('Gruppe: $gruppe'); + } + + void saveSettings(Settings settings) { + setStringSetting('group', settings.group); + setStringSetting('key', settings.key); + } } diff --git a/lib/widgets/missing_config_popup.dart b/lib/widgets/missing_config_popup.dart new file mode 100644 index 0000000..43ed2c8 --- /dev/null +++ b/lib/widgets/missing_config_popup.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class MissingConfigPopup extends StatelessWidget { + const MissingConfigPopup({super.key}); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Fehlende Konfiguration'), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Text("Bitte QR Code Scannen"), + ], + ), + ); + } +} diff --git a/pubspec.yaml b/pubspec.yaml index ea481f5..8502294 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,6 +62,8 @@ flutter: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg + assets: + - config.json # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware From 4e2dd41adc9e6b032159c15ae0398747407c19d5 Mon Sep 17 00:00:00 2001 From: Parricc35 <63447810+Parricc35@users.noreply.github.com> Date: Sat, 18 Feb 2023 13:09:52 +0100 Subject: [PATCH 02/13] Added json group examples --- assets/group1.json | 13 +++++++++++++ assets/group3.json | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 assets/group1.json create mode 100644 assets/group3.json diff --git a/assets/group1.json b/assets/group1.json new file mode 100644 index 0000000..f265d8e --- /dev/null +++ b/assets/group1.json @@ -0,0 +1,13 @@ +{ + "group": "Gruppe 1", + "HITT_time": 35, + "relapse categories": ["App stresst mich", "langeweile", "lunge bruacht es"], + "mood_query": { + "days": ["Montag", "Freitag"], + "time": 800, // "8:00 + "sleep_query": { + "days": ["Dienstag", "Samstag"], + "time": 1000 // "10:00 + } + } +} diff --git a/assets/group3.json b/assets/group3.json new file mode 100644 index 0000000..73b129c --- /dev/null +++ b/assets/group3.json @@ -0,0 +1,14 @@ +{ + "group": "Gruppe 3", + "HITT_time": 35, + "chess_time": 1100, // "11:00" + "relapse categories": ["App stresst mich", "langeweile", "lunge bruacht es"], + "mood_query": { + "days": ["Montag", "Freitag"], + "time": 800, // "8:00 + "sleep_query": { + "days": ["Dienstag", "Samstag"], + "time": 1000 // "10:00 + } + } +} From e4cfa701d610c5222ea38bf942f80af67d9fe602 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sun, 19 Feb 2023 14:24:39 +0100 Subject: [PATCH 03/13] made settingsservice to collection of util functions to prevent diffrent instances and therefore different states --- lib/pages/main_page.dart | 13 ++--- lib/pages/scanner_page.dart | 3 +- lib/pages/timer_page.dart | 13 +---- lib/service/settings_service.dart | 80 ++++++++++++++----------------- 4 files changed, 44 insertions(+), 65 deletions(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index a1f7213..711efb1 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -16,7 +16,6 @@ class MyHomePage extends StatefulWidget { class MyHomePageState extends State { int _selectedIndex = 4; - final SettingsService settingsService = SettingsService(); final List _titles = [ 'Stimmung', @@ -33,17 +32,15 @@ class MyHomePageState extends State { SettingsPage(), ]; - void _onItemTapped(int index) { - setState(() async { - (await settingsService.getGroup() != null) + Future _onItemTapped(int index) async { + bool isConfigured = (await getGroup()) != null; + print('Gruppe: ${await getGroup()}, isConfigured: $isConfigured'); + setState(() { + isConfigured ? _selectedIndex = index : showDialog( context: context, builder: (BuildContext context) { - Future.delayed( - const Duration(seconds: 3), - () => Navigator.of(context) - .pop(true)); //Dismiss popup after 3 seconds return const MissingConfigPopup(); }); }); diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index f3bf96a..73a6a45 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -3,7 +3,6 @@ import 'package:smoke_cess_app/service/settings_service.dart'; class SettingsPage extends StatelessWidget { SettingsPage({super.key}); - SettingsService service = SettingsService(); @override Widget build(BuildContext context) { @@ -17,7 +16,7 @@ class SettingsPage extends StatelessWidget { style: ElevatedButton.styleFrom( textStyle: const TextStyle(fontSize: 20)), onPressed: () { - service.loadSettings(); + loadSettings(); }, child: const Text('Read JSON'), ) diff --git a/lib/pages/timer_page.dart b/lib/pages/timer_page.dart index 691d15d..a2e6f49 100644 --- a/lib/pages/timer_page.dart +++ b/lib/pages/timer_page.dart @@ -11,7 +11,6 @@ class StopWatchTimerPage extends StatefulWidget { } class StopWatchTimerPageState extends State { - SettingsService settings = SettingsService(); Duration duration = const Duration(minutes: 1); Timer? timer; @@ -19,21 +18,11 @@ class StopWatchTimerPageState extends State { @override void initState() { - setDurationWithSetting(); super.initState(); } - void setDurationWithSetting() { - settings.getIntSetting('workout_duration_minutes').then((workoutMinutes) => - {setState(() => duration = Duration(minutes: workoutMinutes ?? 10))}); - } - void reset() { - if (countDown) { - setDurationWithSetting(); - } else { - setState(() => duration = const Duration()); - } + setState(() => duration = const Duration()); } void startTimer() { diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index 7b41f0c..cc7a0f6 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -2,48 +2,42 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:smoke_cess_app/models/settings.dart'; import 'package:smoke_cess_app/service/json_service.dart'; -class SettingsService { - final Future _prefs = SharedPreferences.getInstance(); +final Future _prefs = SharedPreferences.getInstance(); - SettingsService() { - setIntSetting('workout_duration_minutes', 5); - } - - //access group setting which was saved in local storage - Future getGroup() { - return getStringSetting('group'); - } - - void setStringSetting(String settingKey, String settingValue) => - _prefs.then((pref) => pref.setString(settingKey, settingValue)); - - Future getStringSetting(String settingKey) => - _prefs.then((pref) => pref.getString(settingKey)); - - void setIntSetting(String settingKey, int settingValue) => - _prefs.then((pref) => pref.setInt(settingKey, settingValue)); - - Future getIntSetting(String settingKey) => - _prefs.then((pref) => pref.getInt(settingKey)); - - void setStringList(String settingKey, List list) => - _prefs.then((pref) => pref.setStringList(settingKey, list)); - - //Add other setters and getters if needed - //other possible SharedPreferences Types: Int, Bool, Double, StringList - //see https://pub.dev/packages/shared_preferences - - Future loadSettings() async { - Map configJSON = await loadLocalConfigJSON(); - Settings settings = Settings.fromJson(configJSON); - print(settings.group); - saveSettings(settings); - String gruppe = (await getGroup())!; - print('Gruppe: $gruppe'); - } - - void saveSettings(Settings settings) { - setStringSetting('group', settings.group); - setStringSetting('key', settings.key); - } +//access group setting which was saved in local storage +Future getGroup() { + return getStringSetting('group'); +} + +void setStringSetting(String settingKey, String settingValue) => + _prefs.then((pref) => pref.setString(settingKey, settingValue)); + +Future getStringSetting(String settingKey) => + _prefs.then((pref) => pref.getString(settingKey)); + +void setIntSetting(String settingKey, int settingValue) => + _prefs.then((pref) => pref.setInt(settingKey, settingValue)); + +Future getIntSetting(String settingKey) => + _prefs.then((pref) => pref.getInt(settingKey)); + +void setStringList(String settingKey, List list) => + _prefs.then((pref) => pref.setStringList(settingKey, list)); + +//Add other setters and getters if needed +//other possible SharedPreferences Types: Int, Bool, Double, StringList +//see https://pub.dev/packages/shared_preferences + +Future loadSettings() async { + Map configJSON = await loadLocalConfigJSON(); + Settings settings = Settings.fromJson(configJSON); + print(settings.group); + saveSettings(settings); + String gruppe = (await getGroup())!; + print('Gruppe: $gruppe'); +} + +void saveSettings(Settings settings) { + setStringSetting('group', settings.group); + setStringSetting('key', settings.key); } From cedd8c2143fb7d5d8268ab4e22980abcb5c6e5eb Mon Sep 17 00:00:00 2001 From: Parricc35 Date: Sun, 19 Feb 2023 13:58:42 +0000 Subject: [PATCH 04/13] change time to hours and minutes --- assets/group1.json | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/assets/group1.json b/assets/group1.json index f265d8e..e5aaeda 100644 --- a/assets/group1.json +++ b/assets/group1.json @@ -4,10 +4,13 @@ "relapse categories": ["App stresst mich", "langeweile", "lunge bruacht es"], "mood_query": { "days": ["Montag", "Freitag"], - "time": 800, // "8:00 + "hours": 8, + "minutes": 30 + }, "sleep_query": { "days": ["Dienstag", "Samstag"], - "time": 1000 // "10:00 + "hours": 9, + "minutes": 30 } - } + } From 66fed9d0722cb61860e26bdf62b0b8ef5bcf4877 Mon Sep 17 00:00:00 2001 From: Parricc35 Date: Sun, 19 Feb 2023 14:00:40 +0000 Subject: [PATCH 05/13] change time to hours and minutes --- assets/group3.json | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/assets/group3.json b/assets/group3.json index 73b129c..e742219 100644 --- a/assets/group3.json +++ b/assets/group3.json @@ -1,14 +1,20 @@ { "group": "Gruppe 3", "HITT_time": 35, - "chess_time": 1100, // "11:00" + "chess_time": { + "hours": 8, + "minutes": 30 + }, "relapse categories": ["App stresst mich", "langeweile", "lunge bruacht es"], "mood_query": { "days": ["Montag", "Freitag"], - "time": 800, // "8:00 + "hours": 10, + "minutes": 30 + }, "sleep_query": { "days": ["Dienstag", "Samstag"], - "time": 1000 // "10:00 + "hours": 11, + "minutes": 30 } - } + } From f67f44a0300ec4522857dc6793146e8172077b6d Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sun, 19 Feb 2023 15:06:57 +0100 Subject: [PATCH 06/13] alwas use new instance on shared preferences --- lib/service/settings_service.dart | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index cc7a0f6..e42173b 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -2,27 +2,28 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:smoke_cess_app/models/settings.dart'; import 'package:smoke_cess_app/service/json_service.dart'; -final Future _prefs = SharedPreferences.getInstance(); - //access group setting which was saved in local storage Future getGroup() { return getStringSetting('group'); } void setStringSetting(String settingKey, String settingValue) => - _prefs.then((pref) => pref.setString(settingKey, settingValue)); + SharedPreferences.getInstance() + .then((pref) => pref.setString(settingKey, settingValue)); Future getStringSetting(String settingKey) => - _prefs.then((pref) => pref.getString(settingKey)); + SharedPreferences.getInstance().then((pref) => pref.getString(settingKey)); void setIntSetting(String settingKey, int settingValue) => - _prefs.then((pref) => pref.setInt(settingKey, settingValue)); + SharedPreferences.getInstance() + .then((pref) => pref.setInt(settingKey, settingValue)); Future getIntSetting(String settingKey) => - _prefs.then((pref) => pref.getInt(settingKey)); + SharedPreferences.getInstance().then((pref) => pref.getInt(settingKey)); void setStringList(String settingKey, List list) => - _prefs.then((pref) => pref.setStringList(settingKey, list)); + SharedPreferences.getInstance() + .then((pref) => pref.setStringList(settingKey, list)); //Add other setters and getters if needed //other possible SharedPreferences Types: Int, Bool, Double, StringList From ac994ad6e0fe845fa069a1809754542d25067c03 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sun, 19 Feb 2023 17:31:46 +0100 Subject: [PATCH 07/13] write list and nested properties as json --- assets/group1.json | 13 ++++----- assets/group3.json | 13 ++++----- lib/models/settings.dart | 45 +++++++++++++++++++++++++----- lib/service/json_service.dart | 5 +++- lib/service/settings_service.dart | 46 ++++++++++++++++++++++--------- pubspec.yaml | 2 ++ 6 files changed, 89 insertions(+), 35 deletions(-) diff --git a/assets/group1.json b/assets/group1.json index e5aaeda..eadf04c 100644 --- a/assets/group1.json +++ b/assets/group1.json @@ -1,16 +1,15 @@ { "group": "Gruppe 1", "HITT_time": 35, - "relapse categories": ["App stresst mich", "langeweile", "lunge bruacht es"], + "relapse_categories": ["App stresst mich", "langeweile", "lunge braucht es"], "mood_query": { "days": ["Montag", "Freitag"], "hours": 8, "minutes": 30 }, - "sleep_query": { - "days": ["Dienstag", "Samstag"], - "hours": 9, - "minutes": 30 - } - + "sleep_query": { + "days": ["Dienstag", "Samstag"], + "hours": 9, + "minutes": 30 + } } diff --git a/assets/group3.json b/assets/group3.json index e742219..6e1d75c 100644 --- a/assets/group3.json +++ b/assets/group3.json @@ -5,16 +5,15 @@ "hours": 8, "minutes": 30 }, - "relapse categories": ["App stresst mich", "langeweile", "lunge bruacht es"], + "relapse_categories": ["App stresst mich", "langeweile", "lunge braucht es"], "mood_query": { "days": ["Montag", "Freitag"], "hours": 10, "minutes": 30 }, - "sleep_query": { - "days": ["Dienstag", "Samstag"], - "hours": 11, - "minutes": 30 - } - + "sleep_query": { + "days": ["Dienstag", "Samstag"], + "hours": 11, + "minutes": 30 + } } diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 4dced6e..0282083 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -1,13 +1,44 @@ +import 'package:smoke_cess_app/service/json_service.dart'; + class Settings { final String group; - final String key; - //final List relapseCategories; + final List? relapseCategories; + final QueryConfig moodQuery; + final QueryConfig sleepQuery; + final TimeConfig? chessTime; - Settings(this.group, this.key); //, this.relapseCategories); + Settings(this.group, this.relapseCategories, this.moodQuery, this.sleepQuery, + this.chessTime); Settings.fromJson(Map json) - : group = json['group'].toString(), - key = json['key'].toString() - //relapseCategories = json['relapse_categories'] - ; + : group = json['group'] as String, + relapseCategories = jsonPropertyAsList(json['relapse_categories']), + moodQuery = QueryConfig.fromJson(json['mood_query']), + sleepQuery = QueryConfig.fromJson(json['sleep_query']), + chessTime = + json['chess_time'] ? TimeConfig.fromJson(json['chess_time']) : null; +} + +class QueryConfig { + final int hours; + final int minutes; + final List? days; + + QueryConfig(this.hours, this.minutes, this.days); + + QueryConfig.fromJson(Map json) + : hours = json['hours'] as int, + minutes = json['minutes'] as int, + days = jsonPropertyAsList(json['days']); +} + +class TimeConfig { + final int hours; + final int minutes; + + TimeConfig(this.hours, this.minutes); + + TimeConfig.fromJson(Map json) + : hours = json['hours'] as int, + minutes = json['minutes'] as int; } diff --git a/lib/service/json_service.dart b/lib/service/json_service.dart index d20dacf..ca1b26a 100644 --- a/lib/service/json_service.dart +++ b/lib/service/json_service.dart @@ -1,9 +1,12 @@ import 'package:flutter/services.dart'; import 'dart:convert'; -const String configJSONPath = 'assets/config.json'; +const String configJSONPath = 'assets/group3.json'; Future> loadLocalConfigJSON() async { String content = await rootBundle.loadString(configJSONPath); return jsonDecode(content); } + +List? jsonPropertyAsList(dynamic property) => + property != null ? List.from(property) : null; diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index e42173b..ead6f9b 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -3,28 +3,45 @@ import 'package:smoke_cess_app/models/settings.dart'; import 'package:smoke_cess_app/service/json_service.dart'; //access group setting which was saved in local storage -Future getGroup() { - return getStringSetting('group'); -} +Future getGroup() => _getStringSetting('group'); -void setStringSetting(String settingKey, String settingValue) => +Future?> getRelapseCategories() => + _getStringListSetting('relapse_categories'); + +Future?> getSleepQueryDaysCategories() => + _getStringListSetting('sleep_query_days'); + +Future getSleepQueryHours() => _getIntSetting('sleep_query_hours'); +Future getSleepQueryMinutes() => _getIntSetting('sleep_query_minutes'); + +Future?> getMoodQueryDaysCategories() => + _getStringListSetting('mood_query_days'); + +Future getMoodQueryHours() => _getIntSetting('mood_query_hours'); +Future getMoodQueryMinutes() => _getIntSetting('mood_query_minutes'); + +void _setStringSetting(String settingKey, String settingValue) => SharedPreferences.getInstance() .then((pref) => pref.setString(settingKey, settingValue)); -Future getStringSetting(String settingKey) => +Future _getStringSetting(String settingKey) => SharedPreferences.getInstance().then((pref) => pref.getString(settingKey)); -void setIntSetting(String settingKey, int settingValue) => +void _setIntSetting(String settingKey, int settingValue) => SharedPreferences.getInstance() .then((pref) => pref.setInt(settingKey, settingValue)); -Future getIntSetting(String settingKey) => +Future _getIntSetting(String settingKey) => SharedPreferences.getInstance().then((pref) => pref.getInt(settingKey)); -void setStringList(String settingKey, List list) => +void _setStringListSetting(String settingKey, List list) => SharedPreferences.getInstance() .then((pref) => pref.setStringList(settingKey, list)); +Future?> _getStringListSetting(String settingKey) => + SharedPreferences.getInstance() + .then((pref) => pref.getStringList(settingKey)); + //Add other setters and getters if needed //other possible SharedPreferences Types: Int, Bool, Double, StringList //see https://pub.dev/packages/shared_preferences @@ -32,13 +49,16 @@ void setStringList(String settingKey, List list) => Future loadSettings() async { Map configJSON = await loadLocalConfigJSON(); Settings settings = Settings.fromJson(configJSON); - print(settings.group); saveSettings(settings); - String gruppe = (await getGroup())!; - print('Gruppe: $gruppe'); } void saveSettings(Settings settings) { - setStringSetting('group', settings.group); - setStringSetting('key', settings.key); + _setStringSetting('group', settings.group); + _setStringListSetting('relapse_categories', settings.relapseCategories!); + _setStringListSetting('mood_query_days', settings.moodQuery.days!); + _setIntSetting('mood_query_hours', settings.moodQuery.hours); + _setIntSetting('mood_query_minutes', settings.moodQuery.minutes); + _setStringListSetting('sleep_query_days', settings.sleepQuery.days!); + _setIntSetting('sleep_query_hours', settings.sleepQuery.hours); + _setIntSetting('sleep_query_minutes', settings.sleepQuery.minutes); } diff --git a/pubspec.yaml b/pubspec.yaml index 8502294..cf6766f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,6 +64,8 @@ flutter: # - images/a_dot_ham.jpeg assets: - config.json + - group1.json + - group3.json # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware From acfb9fea70935083fed99e8e3f9942717fa78c2f Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sun, 19 Feb 2023 17:44:20 +0100 Subject: [PATCH 08/13] added nullable chess time property in shared prefs --- lib/models/settings.dart | 5 +++-- lib/service/settings_service.dart | 11 +++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 0282083..359338f 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -15,8 +15,9 @@ class Settings { relapseCategories = jsonPropertyAsList(json['relapse_categories']), moodQuery = QueryConfig.fromJson(json['mood_query']), sleepQuery = QueryConfig.fromJson(json['sleep_query']), - chessTime = - json['chess_time'] ? TimeConfig.fromJson(json['chess_time']) : null; + chessTime = json['chess_time'] != null + ? TimeConfig.fromJson(json['chess_time']) + : null; } class QueryConfig { diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index ead6f9b..891f60b 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -20,6 +20,9 @@ Future?> getMoodQueryDaysCategories() => Future getMoodQueryHours() => _getIntSetting('mood_query_hours'); Future getMoodQueryMinutes() => _getIntSetting('mood_query_minutes'); +Future getChessHours() => _getIntSetting('chess_hours'); +Future getChessMinutes() => _getIntSetting('chess_minutes'); + void _setStringSetting(String settingKey, String settingValue) => SharedPreferences.getInstance() .then((pref) => pref.setString(settingKey, settingValue)); @@ -42,10 +45,6 @@ Future?> _getStringListSetting(String settingKey) => SharedPreferences.getInstance() .then((pref) => pref.getStringList(settingKey)); -//Add other setters and getters if needed -//other possible SharedPreferences Types: Int, Bool, Double, StringList -//see https://pub.dev/packages/shared_preferences - Future loadSettings() async { Map configJSON = await loadLocalConfigJSON(); Settings settings = Settings.fromJson(configJSON); @@ -61,4 +60,8 @@ void saveSettings(Settings settings) { _setStringListSetting('sleep_query_days', settings.sleepQuery.days!); _setIntSetting('sleep_query_hours', settings.sleepQuery.hours); _setIntSetting('sleep_query_minutes', settings.sleepQuery.minutes); + if (settings.chessTime != null) { + _setIntSetting('chess_hours', settings.chessTime!.hours); + _setIntSetting('chess_minutes', settings.chessTime!.minutes); + } } From b368baf744c84e3aa4fef6f9644d14800a6d704f Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Sun, 19 Feb 2023 17:54:30 +0100 Subject: [PATCH 09/13] rename settingpage --- lib/pages/main_page.dart | 12 ++++++------ lib/pages/scanner_page.dart | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 711efb1..6e479e5 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -24,12 +24,12 @@ class MyHomePageState extends State { 'Rückfall', 'Scanner' ]; - static final List _widgetOptions = [ - const MoodPage(), - const SleepPage(), - const StopWatchTimerPage(), - const RelapsePage(), - SettingsPage(), + static const List _widgetOptions = [ + MoodPage(), + SleepPage(), + StopWatchTimerPage(), + RelapsePage(), + ScannerPage(), ]; Future _onItemTapped(int index) async { diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 73a6a45..5ebb699 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/service/settings_service.dart'; -class SettingsPage extends StatelessWidget { - SettingsPage({super.key}); +class ScannerPage extends StatelessWidget { + const ScannerPage({super.key}); @override Widget build(BuildContext context) { From 465873f1c6832571249495c80a801098ad1cfebe Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Mon, 20 Feb 2023 14:45:41 +0100 Subject: [PATCH 10/13] add package and ios description for qr --- ios/Runner/Info.plist | 2 ++ pubspec.lock | 7 +++++++ pubspec.yaml | 1 + 3 files changed, 10 insertions(+) diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 097c0f1..8285717 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + NSCameraUsageDescription + This app needs camera access to scan QR codes CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName diff --git a/pubspec.lock b/pubspec.lock index 1cda953..7dd2477 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -121,6 +121,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + mobile_scanner: + dependency: "direct main" + description: + name: mobile_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" path: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index cf6766f..7c98b0f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,6 +36,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 shared_preferences: ^2.0.17 + mobile_scanner: ^3.0.0 dev_dependencies: flutter_test: From 74946d005c8e24d4231aab9af59b711d3671b878 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Mon, 20 Feb 2023 16:23:49 +0100 Subject: [PATCH 11/13] added barcode scanner --- android/app/build.gradle | 4 +- lib/pages/scanner_page.dart | 10 ++++- web/index.html | 78 +++++++++++++++++++------------------ 3 files changed, 52 insertions(+), 40 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index d8c9ecd..4fef84e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion flutter.compileSdkVersion + compileSdkVersion 33 ndkVersion flutter.ndkVersion compileOptions { @@ -47,7 +47,7 @@ android { applicationId "com.example.smoke_cess_app" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 5ebb699..fc4abe0 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:smoke_cess_app/service/settings_service.dart'; class ScannerPage extends StatelessWidget { @@ -10,7 +11,14 @@ class ScannerPage extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text('Hier taucht die Kamera zum Scannen auf'), + Expanded(child: MobileScanner(fit: BoxFit.contain,onDetect: (capture) { + final List barcodes = capture.barcodes; + for (final barcode in barcodes) { + debugPrint('Barcode found! ${barcode.rawValue}'); + } }, + + )) + , const SizedBox(height: 30), ElevatedButton( style: ElevatedButton.styleFrom( diff --git a/web/index.html b/web/index.html index 277f035..366d37f 100644 --- a/web/index.html +++ b/web/index.html @@ -1,7 +1,7 @@ - - - + - - - + + + - - - - - + + + + + - - + + - smoke_cess_app - + smoke_cess_app + - - - - - - + + + + + - + + + From 539359068786e0105cf40f31b054500f098ea44a Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Mon, 20 Feb 2023 19:32:23 +0100 Subject: [PATCH 12/13] added popup on successfull scan --- assets/config.json | 4 -- lib/pages/main_page.dart | 5 ++- lib/pages/scanner_page.dart | 61 ++++++++++++++++++++++----- lib/service/json_service.dart | 2 + lib/service/settings_service.dart | 2 +- lib/widgets/missing_config_popup.dart | 11 +++-- pubspec.yaml | 1 - 7 files changed, 65 insertions(+), 21 deletions(-) delete mode 100644 assets/config.json diff --git a/assets/config.json b/assets/config.json deleted file mode 100644 index a80b05f..0000000 --- a/assets/config.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "group": "Gruppe 2", - "key": "value" -} diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 6e479e5..76cec46 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -41,7 +41,10 @@ class MyHomePageState extends State { : showDialog( context: context, builder: (BuildContext context) { - return const MissingConfigPopup(); + return const MissingConfigPopup( + title: 'Fehlende Konfiguration', + text: 'Bitte QR Code Scannen!', + ); }); }); } diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index fc4abe0..9ce6301 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,30 +1,71 @@ import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:smoke_cess_app/models/settings.dart'; +import 'package:smoke_cess_app/service/json_service.dart'; import 'package:smoke_cess_app/service/settings_service.dart'; -class ScannerPage extends StatelessWidget { +import '../widgets/missing_config_popup.dart'; + +class ScannerPage extends StatefulWidget { const ScannerPage({super.key}); + @override + State createState() => ScannerPageState(); +} + +class ScannerPageState extends State { + bool scanning = false; + @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Expanded(child: MobileScanner(fit: BoxFit.contain,onDetect: (capture) { - final List barcodes = capture.barcodes; - for (final barcode in barcodes) { - debugPrint('Barcode found! ${barcode.rawValue}'); - } }, - - )) - , + scanning + ? Expanded( + child: MobileScanner( + fit: BoxFit.contain, + controller: MobileScannerController( + detectionTimeoutMs: 2000, + ), + onDetect: (capture) { + final List barcodes = capture.barcodes; + for (final barcode in barcodes) { + if (barcode.rawValue != null) { + String qrText = barcode.rawValue!; + Map json = stringToJSON(qrText); + Settings settings = Settings.fromJson(json); + saveSettings(settings); + setState(() { + scanning = false; + showDialog( + context: context, + builder: (BuildContext context) { + return MissingConfigPopup( + title: 'Konfiguration erfolgreich', + text: 'Du gehörst zu Gruppe ${settings.group}', + ); + }); + }); + } + } + }, + )) + : ElevatedButton( + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20)), + onPressed: () { + setState(() => scanning = true); + }, + child: const Text('Scan QR Code'), + ), const SizedBox(height: 30), ElevatedButton( style: ElevatedButton.styleFrom( textStyle: const TextStyle(fontSize: 20)), onPressed: () { - loadSettings(); + loadSettingsFromLocalJSON(); }, child: const Text('Read JSON'), ) diff --git a/lib/service/json_service.dart b/lib/service/json_service.dart index ca1b26a..6d09e9f 100644 --- a/lib/service/json_service.dart +++ b/lib/service/json_service.dart @@ -10,3 +10,5 @@ Future> loadLocalConfigJSON() async { List? jsonPropertyAsList(dynamic property) => property != null ? List.from(property) : null; + +Map stringToJSON(String jsonString) => jsonDecode(jsonString); diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index 891f60b..f83c979 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -45,7 +45,7 @@ Future?> _getStringListSetting(String settingKey) => SharedPreferences.getInstance() .then((pref) => pref.getStringList(settingKey)); -Future loadSettings() async { +Future loadSettingsFromLocalJSON() async { Map configJSON = await loadLocalConfigJSON(); Settings settings = Settings.fromJson(configJSON); saveSettings(settings); diff --git a/lib/widgets/missing_config_popup.dart b/lib/widgets/missing_config_popup.dart index 43ed2c8..620774e 100644 --- a/lib/widgets/missing_config_popup.dart +++ b/lib/widgets/missing_config_popup.dart @@ -1,17 +1,20 @@ import 'package:flutter/material.dart'; class MissingConfigPopup extends StatelessWidget { - const MissingConfigPopup({super.key}); + final String title; + final String text; + const MissingConfigPopup( + {super.key, required this.title, required this.text}); @override Widget build(BuildContext context) { return AlertDialog( - title: const Text('Fehlende Konfiguration'), + title: Text(title), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Text("Bitte QR Code Scannen"), + children: [ + Text(text), ], ), ); diff --git a/pubspec.yaml b/pubspec.yaml index 7c98b0f..92964f0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -64,7 +64,6 @@ flutter: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg assets: - - config.json - group1.json - group3.json From 6d4a958d8c6c3d9981794331d92d0ee272197429 Mon Sep 17 00:00:00 2001 From: Crondung <1922635@stud.hs-mannheim.de> Date: Mon, 20 Feb 2023 19:50:09 +0100 Subject: [PATCH 13/13] change group to int, show group in appbar if configured --- assets/group1.json | 2 +- assets/group3.json | 2 +- lib/models/settings.dart | 4 ++-- lib/pages/main_page.dart | 9 ++++++--- lib/pages/scanner_page.dart | 1 + lib/service/settings_service.dart | 4 ++-- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/assets/group1.json b/assets/group1.json index eadf04c..4e2de76 100644 --- a/assets/group1.json +++ b/assets/group1.json @@ -1,5 +1,5 @@ { - "group": "Gruppe 1", + "group": 1, "HITT_time": 35, "relapse_categories": ["App stresst mich", "langeweile", "lunge braucht es"], "mood_query": { diff --git a/assets/group3.json b/assets/group3.json index 6e1d75c..623ffc8 100644 --- a/assets/group3.json +++ b/assets/group3.json @@ -1,5 +1,5 @@ { - "group": "Gruppe 3", + "group": 3, "HITT_time": 35, "chess_time": { "hours": 8, diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 359338f..6691e91 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -1,7 +1,7 @@ import 'package:smoke_cess_app/service/json_service.dart'; class Settings { - final String group; + final int group; final List? relapseCategories; final QueryConfig moodQuery; final QueryConfig sleepQuery; @@ -11,7 +11,7 @@ class Settings { this.chessTime); Settings.fromJson(Map json) - : group = json['group'] as String, + : group = json['group'] as int, relapseCategories = jsonPropertyAsList(json['relapse_categories']), moodQuery = QueryConfig.fromJson(json['mood_query']), sleepQuery = QueryConfig.fromJson(json['sleep_query']), diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 76cec46..db4ff27 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -16,6 +16,7 @@ class MyHomePage extends StatefulWidget { class MyHomePageState extends State { int _selectedIndex = 4; + int? _gruppe; final List _titles = [ 'Stimmung', @@ -33,8 +34,8 @@ class MyHomePageState extends State { ]; Future _onItemTapped(int index) async { - bool isConfigured = (await getGroup()) != null; - print('Gruppe: ${await getGroup()}, isConfigured: $isConfigured'); + _gruppe = await getGroup(); + bool isConfigured = _gruppe != null; setState(() { isConfigured ? _selectedIndex = index @@ -52,7 +53,9 @@ class MyHomePageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(_titles[_selectedIndex])), + appBar: AppBar( + title: Text( + '${_titles[_selectedIndex]} ${_gruppe != null ? "Gruppe $_gruppe" : ""}')), body: _widgetOptions.elementAt(_selectedIndex), bottomNavigationBar: NavigationBar( onDestinationSelected: _onItemTapped, diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 9ce6301..fcd2c30 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -30,6 +30,7 @@ class ScannerPageState extends State { detectionTimeoutMs: 2000, ), onDetect: (capture) { + //TODO Errorhandling!! final List barcodes = capture.barcodes; for (final barcode in barcodes) { if (barcode.rawValue != null) { diff --git a/lib/service/settings_service.dart b/lib/service/settings_service.dart index f83c979..dca2839 100644 --- a/lib/service/settings_service.dart +++ b/lib/service/settings_service.dart @@ -3,7 +3,7 @@ import 'package:smoke_cess_app/models/settings.dart'; import 'package:smoke_cess_app/service/json_service.dart'; //access group setting which was saved in local storage -Future getGroup() => _getStringSetting('group'); +Future getGroup() => _getIntSetting('group'); Future?> getRelapseCategories() => _getStringListSetting('relapse_categories'); @@ -52,7 +52,7 @@ Future loadSettingsFromLocalJSON() async { } void saveSettings(Settings settings) { - _setStringSetting('group', settings.group); + _setIntSetting('group', settings.group); _setStringListSetting('relapse_categories', settings.relapseCategories!); _setStringListSetting('mood_query_days', settings.moodQuery.days!); _setIntSetting('mood_query_hours', settings.moodQuery.hours);