From 3ae9a9b1bbdaa47d6e2734299842cbf025a0104a Mon Sep 17 00:00:00 2001 From: Sascha Date: Sun, 13 Feb 2022 13:33:09 +0100 Subject: [PATCH 01/23] Implemented password reset screen (#12) * added password reset to login screen * added new reset endpoint to user sync helper * in the future the email should have a way to open either the app or the browser (Maybe even implement it into web page of csharplassi) --- lib/localization/nssl_messages_de.dart | 7 +- lib/localization/nssl_messages_en.dart | 4 + lib/localization/nssl_strings.dart | 10 +- lib/main.dart | 4 +- lib/pages/forgot_password.dart | 128 ++++++++++++++++++ lib/pages/login.dart | 22 +-- lib/server_communication/request_classes.dart | 8 +- lib/server_communication/return_classes.dart | 9 ++ lib/server_communication/user_sync.dart | 36 +++-- 9 files changed, 198 insertions(+), 30 deletions(-) create mode 100644 lib/pages/forgot_password.dart diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index 8a70354..3167a28 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -133,6 +133,11 @@ class MessageLookup extends MessageLookupByLibrary { "boughtProducts": MessageLookupByLibrary.simpleMessage('Eingekauft'), "nothingBoughtYet": MessageLookupByLibrary.simpleMessage('Noch nichts eingekauft'), "reorderItems": MessageLookupByLibrary.simpleMessage('Reihenfolge'), - "refresh": MessageLookupByLibrary.simpleMessage('Aktualisieren') + "refresh": MessageLookupByLibrary.simpleMessage('Aktualisieren'), + "okayButton": MessageLookupByLibrary.simpleMessage('OKAY'), + "requestPasswordResetButton": MessageLookupByLibrary.simpleMessage("PASSWORT ZURÜCKSETZUNG BEANTRAGEN"), + "requestPasswordResetTitle": MessageLookupByLibrary.simpleMessage("Passwort zurücksetzen"), + "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage('Die Passwort zurücksetzen Email wurde erfolgreich an die Adresse gesendet, sollte diese existieren. Weitere Schritte für das abschließen des Resets sind in der Email enthalten.'), + }; } diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index 336c2d5..95cd79d 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -133,5 +133,9 @@ class MessageLookup extends MessageLookupByLibrary { "nothingBoughtYet": MessageLookupByLibrary.simpleMessage('Nothing bought yet'), "reorderItems": MessageLookupByLibrary.simpleMessage('Reorder'), "refresh": MessageLookupByLibrary.simpleMessage('Refresh'), + "okayButton": MessageLookupByLibrary.simpleMessage('OKAY'), + "requestPasswordResetButton": MessageLookupByLibrary.simpleMessage("REQUEST PASSWORD RESET"), + "requestPasswordResetTitle": MessageLookupByLibrary.simpleMessage("Password Reset"), + "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage('If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.'), }; } diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index b6af7bf..d79b3a6 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -301,8 +301,12 @@ class NSSLStrings { String reorderItems() => Intl.message('Reorder', name: 'reorderItems', locale: _localeName); - String refresh() => - Intl.message('Refresh', name: "refresh", locale: _localeName); - //String openAppDrawerTooltip() => Intl.message('Open navigation menu', name: 'openNavigationMenu', locale: _localeName); + String refresh() => Intl.message('Refresh', name: "refresh", locale: _localeName); + String okayButton() => Intl.message('OKAY', name: "okayButton", locale: _localeName); + + String requestPasswordResetButton() => Intl.message('REQUEST PASSWORD RESET', name: 'requestPasswordResetButton', locale: _localeName); + String requestPasswordResetTitle() => Intl.message('Password Reset', name: "requestPasswordResetTitle", locale: _localeName); + String requestPasswordResetSuccess() => Intl.message('If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.', name: "requestPasswordResetSuccess", locale: _localeName); + //String openAppDrawerTooltip() => Intl.message('Open navigation menu', name: 'openNavigationMenu', locale: _localeName); } diff --git a/lib/main.dart b/lib/main.dart index a4130b9..8482bd4 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'dart:ui'; import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:nssl/options/themes.dart'; +import 'package:nssl/pages/forgot_password.dart'; import 'package:nssl/pages/pages.dart'; import 'package:nssl/manager/manager_export.dart'; import 'package:nssl/models/model_export.dart'; @@ -13,6 +14,7 @@ import 'dart:async'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:nssl/server_communication/request_classes.dart'; // import 'package:shared_preferences/shared_preferences.dart'; class CustomScrollBehavior extends MaterialScrollBehavior { @@ -137,7 +139,7 @@ class _NSSLState extends State { '/login': (BuildContext context) => LoginPage(), '/registration': (BuildContext context) => Registration(), '/search': (BuildContext context) => ProductAddPage(), - '/forgot_password': (BuildContext context) => CustomThemePage(), + '/forgot_password': (BuildContext context) => ForgotPasswordPage(), }, showPerformanceOverlay: performanceOverlay, showSemanticsDebugger: false, diff --git a/lib/pages/forgot_password.dart b/lib/pages/forgot_password.dart new file mode 100644 index 0000000..1b9e55d --- /dev/null +++ b/lib/pages/forgot_password.dart @@ -0,0 +1,128 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:nssl/localization/nssl_strings.dart'; +import 'package:nssl/server_communication/s_c.dart'; + +class ForgotPasswordPage extends StatefulWidget { + ForgotPasswordPage({Key? key, this.scaffoldKey}) : super(key: key); + + final GlobalKey? scaffoldKey; + @override + ForgotPasswordPageState createState() => ForgotPasswordPageState(); +} + +class PersonData { + String name = ''; + String email = ''; + String password = ''; +} + +class ForInput { + TextEditingController textEditingController = TextEditingController(); + String errorText = ''; + GlobalKey key = GlobalKey(); + InputDecoration? decoration; + FocusNode focusNode = FocusNode(); +} + +class ForgotPasswordPageState extends State { + ForgotPasswordPageState() : super(); + GlobalKey _scaffoldKey = GlobalKey(); + final GlobalKey _formKey = GlobalKey(); + + var emailInput = ForInput(); + var submit = ForInput(); + var validateMode = AutovalidateMode.disabled; + + void showInSnackBar(String value) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(value), duration: Duration(seconds: 3))); + } + + Future _handleSubmitted() async { + final FormState form = _formKey.currentState!; + if (!form.validate()) { + validateMode = AutovalidateMode.onUserInteraction; + return; + } + + String email = emailInput.textEditingController.text; + + if (emailInput.textEditingController.text.length > 0 && + _validateEmail(emailInput.textEditingController.text) == null) { + var res = await UserSync.resetPassword(email, context); + if (!HelperMethods.reactToRespone(res, context, + scaffoldState: _scaffoldKey.currentState)) return; + await showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + content: Text( + NSSLStrings.of(context)!.requestPasswordResetSuccess()), + actions: [ + TextButton( + child: Text(NSSLStrings.of(context)!.okayButton()), + onPressed: () { + Navigator.of(context).pop(true); + }) + ])); + Navigator.pop(context); + } + } + + String? _validateEmail(String? value) { + if (value == null) return value; + if (value.isEmpty) return NSSLStrings.of(context)!.emailRequiredError(); + RegExp email = RegExp( + r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); + if (!email.hasMatch(value)) + return NSSLStrings.of(context)!.emailIncorrectFormatError(); + return null; + } + + _resetInput() { + emailInput.decoration = InputDecoration(labelText: "E-Mail"); + } + + @override + Widget build(BuildContext context) { + _resetInput(); + return Scaffold( + key: _scaffoldKey, + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: Text(NSSLStrings.of(context)!.requestPasswordResetTitle())), + body: Form( + key: _formKey, + autovalidateMode: validateMode, + child: ListView( + padding: const EdgeInsets.symmetric(horizontal: 32.0), + children: [ + ListTile( + title: TextFormField( + key: emailInput.key, + decoration: emailInput.decoration, + controller: emailInput.textEditingController, + keyboardType: TextInputType.emailAddress, + autofillHints: [AutofillHints.username, AutofillHints.email], + autocorrect: false, + autofocus: true, + validator: _validateEmail, + onSaved: (s) => _handleSubmitted(), + ), + ), + ListTile( + title: Container( + child: ElevatedButton( + key: submit.key, + child: Center( + child: Text(NSSLStrings.of(context)! + .requestPasswordResetButton())), + onPressed: _handleSubmitted, + ), + padding: const EdgeInsets.only(top: 16.0)), + ), + ]), + ), + ); + } +} diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 2c0331b..02edbb9 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -229,17 +229,17 @@ class LoginPageState extends State { ), ), ), -// ListTile( -// title: Container( -// child: TextButton( -// onPressed: () { -// Navigator.pushNamed(context, "/forgot_password"); -// }, -// child: -// Text(NSSLStrings.of(context).forgotPassword()), -// ), -// ), -// ), + ListTile( + title: Container( + child: TextButton( + onPressed: () { + Navigator.pushNamed(context, "/forgot_password"); + }, + child: + Text(NSSLStrings.of(context)?.forgotPassword() ?? ""), + ), + ), + ), //padding: EdgeInsets.only( // top: MediaQuery.of(context).size.height / 5), ] diff --git a/lib/server_communication/request_classes.dart b/lib/server_communication/request_classes.dart index df7369d..ecd8085 100644 --- a/lib/server_communication/request_classes.dart +++ b/lib/server_communication/request_classes.dart @@ -13,6 +13,12 @@ class ChangePasswordArgs { toJson() => {"oldPWHash": "$oldPWHash", "newPWHash": "$newPWHash"}; } +class ResetPasswordArgs { + ResetPasswordArgs(this.email); + String email; + toJson() => {"email": "$email"}; +} + class AddContributorArgs { AddContributorArgs(this.name); String name; @@ -29,7 +35,7 @@ class ChangeProductArgs { ChangeProductArgs({this.change, this.newName}); int? change; String? newName; - toJson() => {"change": "$change", "newName" : "$newName"}; + toJson() => {"change": "$change", "newName": "$newName"}; } class ChangeProductsArgs { diff --git a/lib/server_communication/return_classes.dart b/lib/server_communication/return_classes.dart index 732983a..8440084 100644 --- a/lib/server_communication/return_classes.dart +++ b/lib/server_communication/return_classes.dart @@ -5,6 +5,15 @@ import 'package:nssl/models_json.dart'; class BaseResult { bool? success; String? error; + static BaseResult fromJson(String dataString) => + _fromJson(jsonDecode(dataString)); + + static BaseResult _fromJson(Map data) { + var r = BaseResult(); + r.success = data["success"]; + r.error = data["error"]; + return r; + } } class CreateResult extends BaseResult { diff --git a/lib/server_communication/user_sync.dart b/lib/server_communication/user_sync.dart index 301173e..91e0bc0 100644 --- a/lib/server_communication/user_sync.dart +++ b/lib/server_communication/user_sync.dart @@ -5,27 +5,37 @@ import 'dart:async'; import 'helper_methods.dart'; import 'package:http/http.dart'; -final String path = "users"; -final String path2 = "session"; +final String usersPath = "users"; +final String sessionPath = "session"; +final String passwortPath = "password"; class UserSync { - static Future create( - String username, String email, String password, BuildContext context) => + static Future create(String username, String email, String password, + BuildContext context) => HelperMethods.post("registration", context, LoginArgs(username: username, pwHash: password, eMail: email), true); - static Future login(String username, String password, BuildContext context) => - HelperMethods.post( - path2, context, LoginArgs(username: username, pwHash: password), true); + static Future login( + String username, String password, BuildContext context) => + HelperMethods.post(sessionPath, context, + LoginArgs(username: username, pwHash: password), true); - static Future loginEmail(String email, String password, BuildContext context) => - HelperMethods.post(path2, context, LoginArgs(eMail: email, pwHash: password), true); + static Future loginEmail( + String email, String password, BuildContext context) => + HelperMethods.post(sessionPath, context, + LoginArgs(eMail: email, pwHash: password), true); - static Future info(BuildContext context) => HelperMethods.get(path, context); + static Future info(BuildContext context) => + HelperMethods.get(usersPath, context); static Future refreshToken(BuildContext? context) => - HelperMethods.put(path2, context, null, true); + HelperMethods.put(sessionPath, context, null, true); - static Future changePassword(String oldPassword, String newPassword, String? token, BuildContext context) => - HelperMethods.put(path, context, ChangePasswordArgs(oldPassword, newPassword)); + static Future changePassword(String oldPassword, String newPassword, + String? token, BuildContext context) => + HelperMethods.put( + usersPath, context, ChangePasswordArgs(oldPassword, newPassword)); + + static Future resetPassword(String email, BuildContext context) => + HelperMethods.post(passwortPath, context, ResetPasswordArgs(email), true); } From cb7477e641c86c49ff43fa4d0168d097c2e28397 Mon Sep 17 00:00:00 2001 From: Sascha Date: Sat, 4 Jun 2022 19:40:20 +0200 Subject: [PATCH 02/23] Added nssl icon to have a better splash screen (#13) --- assets/vectors/app_icon.svg | 65 ++++++++ icon - Kopie.png | Bin 10487 -> 0 bytes icon.png | Bin 7483 -> 0 bytes lib/main.dart | 30 ++-- lib/pages/barcode_scanner_page.dart | 26 +-- lib/pages/main_page.dart | 246 +++++++++------------------- pubspec.yaml | 17 +- 7 files changed, 178 insertions(+), 206 deletions(-) create mode 100644 assets/vectors/app_icon.svg delete mode 100644 icon - Kopie.png delete mode 100644 icon.png diff --git a/assets/vectors/app_icon.svg b/assets/vectors/app_icon.svg new file mode 100644 index 0000000..cdb5f3d --- /dev/null +++ b/assets/vectors/app_icon.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icon - Kopie.png b/icon - Kopie.png deleted file mode 100644 index 27ef7df98cb0b1168e41b36060747c7c6f07b535..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10487 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 diff --git a/icon.png b/icon.png deleted file mode 100644 index b8575d165f1e1064d2587bcce74265b5e0e79bde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7483 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 _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // make sure you call `initializeApp` before using other Firebase services. await Startup.initializeMinFunction(); //Startup.remoteMessages.add(message); - var dir = - await Startup.fs.systemTempDirectory.childDirectory("message").create(); + var dir = await Startup.fs.systemTempDirectory.childDirectory("message").create(); var file = dir.childFile(DateTime.now().microsecondsSinceEpoch.toString()); await file.writeAsString(jsonEncode(message.data)); } @@ -45,11 +43,20 @@ Future main() async { if (t.connectionState == ConnectionState.done) return NSSLPage(); else - return Container(color: Colors.green); + return MaterialApp( + builder: (context, child) { + return Center( + child: SizedBox( + height: 200, + width: 200, + child: SvgPicture.asset("assets/vectors/app_icon.svg"), + ), + ); + }, + ); }, - future: Startup.initialize().then((value) => - FirebaseMessaging.onBackgroundMessage( - _firebaseMessagingBackgroundHandler)), + future: Startup.initialize() + .then((value) => FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler)), )); } @@ -98,8 +105,7 @@ class _NSSLState extends State { // FirebaseMessaging.onBackgroundMessage((message) => CloudMessaging.onMessage(message, setState)); // firebaseMessaging.configure( // onMessage: (x) => CloudMessaging.onMessage(x, setState), onLaunch: (x) => Startup.initialize()); - for (var list in User.shoppingLists) - if (list.messagingEnabled) list.subscribeForFirebaseMessaging(); + for (var list in User.shoppingLists) if (list.messagingEnabled) list.subscribeForFirebaseMessaging(); } Future subscribeFirebase(BuildContext context) async { @@ -149,9 +155,7 @@ class _NSSLState extends State { } Scaffold mainAppHome() => Scaffold( - key: _mainScaffoldKey, - resizeToAvoidBottomInset: false, - body: MainPage() //CustomThemePage()//LoginPage(), + key: _mainScaffoldKey, resizeToAvoidBottomInset: false, body: MainPage() //CustomThemePage()//LoginPage(), ); Scaffold mainAppLoginRegister() => Scaffold( diff --git a/lib/pages/barcode_scanner_page.dart b/lib/pages/barcode_scanner_page.dart index d43d909..c2d3e0e 100644 --- a/lib/pages/barcode_scanner_page.dart +++ b/lib/pages/barcode_scanner_page.dart @@ -50,7 +50,7 @@ class _BarcodeScannerScreenState extends State @override void initState() { super.initState(); - WidgetsBinding.instance?.addObserver(this); + WidgetsBinding.instance.addObserver(this); // Use the recommended camera settings for the BarcodeCapture mode. _camera?.applySettings(BarcodeCapture.recommendedCameraSettings); @@ -92,16 +92,13 @@ class _BarcodeScannerScreenState extends State // Add a barcode capture overlay to the data capture view to render the location of captured barcodes on top of // the video preview. This is optional, but recommended for better visual feedback. - var overlay = BarcodeCaptureOverlay.withBarcodeCaptureForView( - _barcodeCapture, _captureView) + var overlay = BarcodeCaptureOverlay.withBarcodeCaptureForView(_barcodeCapture, _captureView) ..viewfinder = RectangularViewfinder.withStyleAndLineStyle( - RectangularViewfinderStyle.square, - RectangularViewfinderLineStyle.light); + RectangularViewfinderStyle.square, RectangularViewfinderLineStyle.light); // Adjust the overlay's barcode highlighting to match the new viewfinder styles and improve the visibility of feedback. // With 6.10 we will introduce this visual treatment as a new style for the overlay. - overlay.brush = Brush( - Color.fromARGB(0, 0, 0, 0), Color.fromARGB(255, 255, 255, 255), 3); + overlay.brush = Brush(Color.fromARGB(0, 0, 0, 0), Color.fromARGB(255, 255, 255, 255), 3); _captureView.addOverlay(overlay); @@ -119,8 +116,7 @@ class _BarcodeScannerScreenState extends State Widget child; if (_isPermissionMessageVisible) { child = PlatformText('No permission to access the camera!', - style: TextStyle( - fontSize: 14, fontWeight: FontWeight.bold, color: Colors.black)); + style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Colors.black)); } else { child = _captureView; } @@ -137,23 +133,19 @@ class _BarcodeScannerScreenState extends State } @override - void didScan( - BarcodeCapture barcodeCapture, BarcodeCaptureSession session) async { + void didScan(BarcodeCapture barcodeCapture, BarcodeCaptureSession session) async { _barcodeCapture.isEnabled = false; var code = session.newlyRecognizedBarcodes.first; - var data = (code.data == null || code.data?.isEmpty == true) - ? code.rawData - : code.data; + var data = (code.data == null || code.data?.isEmpty == true) ? code.rawData : code.data; Navigator.pop(context, data); } @override - void didUpdateSession( - BarcodeCapture barcodeCapture, BarcodeCaptureSession session) {} + void didUpdateSession(BarcodeCapture barcodeCapture, BarcodeCaptureSession session) {} @override void dispose() { - WidgetsBinding.instance?.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); _barcodeCapture.removeListener(this); _barcodeCapture.isEnabled = false; _camera?.switchToDesiredState(FrameSourceState.off); diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index d607ac3..dc8f080 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -23,8 +23,7 @@ class MainPage extends StatefulWidget { MainPageState createState() => MainPageState(); } -class MainPageState extends State - with TickerProviderStateMixin, WidgetsBindingObserver { +class MainPageState extends State with TickerProviderStateMixin, WidgetsBindingObserver { BuildContext? cont; final ScrollController _mainController = ScrollController(); @@ -52,7 +51,7 @@ class MainPageState extends State @override void initState() { super.initState(); - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); Startup.deleteMessagesFromFolder(); Startup.initializeNewListsFromServer(setState); @@ -85,20 +84,14 @@ class MainPageState extends State : [ PopupMenuButton( onSelected: selectedOption, - itemBuilder: (BuildContext context) => - >[ + itemBuilder: (BuildContext context) => >[ PopupMenuItem( - value: 'Options', - child: Text( - NSSLStrings.of(context)!.changeTheme())), + value: 'Options', child: Text(NSSLStrings.of(context)!.changeTheme())), PopupMenuItem( value: 'deleteCrossedOut', - child: Text(NSSLStrings.of(context)! - .deleteCrossedOutPB())), + child: Text(NSSLStrings.of(context)!.deleteCrossedOutPB())), PopupMenuItem( - value: 'reorderItems', - child: Text( - NSSLStrings.of(context)!.reorderItems())), + value: 'reorderItems', child: Text(NSSLStrings.of(context)!.reorderItems())), ]) ]), body: buildBody(context), @@ -108,33 +101,21 @@ class MainPageState extends State ? [] : [ TextButton( - child: Text(NSSLStrings.of(context)!.addPB()), - onPressed: () => _addWithoutSearchDialog(context)) + child: Text(NSSLStrings.of(context)!.addPB()), onPressed: () => _addWithoutSearchDialog(context)) ] + (Platform.isAndroid - ? [ - TextButton( - child: Text(NSSLStrings.of(context)!.scanPB()), - onPressed: _getEAN) - ] + ? [TextButton(child: Text(NSSLStrings.of(context)!.scanPB()), onPressed: _getEAN)] : []) + - [ - TextButton( - child: Text(NSSLStrings.of(context)!.searchPB()), - onPressed: search) - ]); + [TextButton(child: Text(NSSLStrings.of(context)!.searchPB()), onPressed: search)]); } Widget buildBody(BuildContext context) { cont = context; - if (User.currentList == null || User.currentList!.shoppingItems == null) - return const Text(""); - if (User.currentList!.shoppingItems!.any((item) => item?.sortOrder == null)) - updateOrderIndiciesAndSave(); + if (User.currentList == null || User.currentList!.shoppingItems == null) return const Text(""); + if (User.currentList!.shoppingItems!.any((item) => item?.sortOrder == null)) updateOrderIndiciesAndSave(); - User.currentList!.shoppingItems! - .sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); + User.currentList!.shoppingItems!.sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); var lv; if (User.currentList!.shoppingItems!.length > 0) { var mainList = User.currentList!.shoppingItems!.map((x) { @@ -149,10 +130,7 @@ class MainPageState extends State x.name ?? "", maxLines: 2, softWrap: true, - style: TextStyle( - decoration: x.crossedOut - ? TextDecoration.lineThrough - : TextDecoration.none), + style: TextStyle(decoration: x.crossedOut ? TextDecoration.lineThrough : TextDecoration.none), ), ], ), @@ -194,17 +172,13 @@ class MainPageState extends State }).toList(growable: true); if (isReorderingItems) { - lv = ReorderableListView( - onReorder: _onReorderItems, - scrollDirection: Axis.vertical, - children: mainList); + lv = ReorderableListView(onReorder: _onReorderItems, scrollDirection: Axis.vertical, children: mainList); } else { lv = CustomScrollView( controller: _mainController, slivers: [ SliverFixedExtentList( - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { + delegate: SliverChildBuilderDelegate((BuildContext context, int index) { return Container( alignment: FractionalOffset.center, child: mainList[index], @@ -237,14 +211,12 @@ class MainPageState extends State for (var old = oldIndex + 1; old < newIndex; old++) { item = User.currentList!.shoppingItems![old]; if (!item!.crossedOut) - User.currentList!.shoppingItems![old]!.sortOrder = - User.currentList!.shoppingItems![old]!.sortOrder! - 1; + User.currentList!.shoppingItems![old]!.sortOrder = User.currentList!.shoppingItems![old]!.sortOrder! - 1; } for (var newI = newIndex; newI < oldIndex; newI++) { item = User.currentList!.shoppingItems![newI]; if (!item!.crossedOut) - User.currentList!.shoppingItems![newI]!.sortOrder = - User.currentList!.shoppingItems![newI]!.sortOrder! - 1; + User.currentList!.shoppingItems![newI]!.sortOrder = User.currentList!.shoppingItems![newI]!.sortOrder! - 1; } }, ); @@ -253,14 +225,14 @@ class MainPageState extends State void sortAndOrderCrossedOut() { final crossedOffset = 0xFFFFFFFF; setState(() { - for (var crossedOut in User.currentList?.shoppingItems - ?.where((x) => x!.crossedOut && x.sortOrder! < crossedOffset) ?? - []) { + for (var crossedOut + in User.currentList?.shoppingItems?.where((x) => x!.crossedOut && x.sortOrder! < crossedOffset) ?? + []) { crossedOut?.sortOrder = crossedOut.sortOrder! + crossedOffset; } - for (var notCrossedOut in User.currentList?.shoppingItems - ?.where((x) => !x!.crossedOut && x.sortOrder! > crossedOffset) ?? - []) { + for (var notCrossedOut + in User.currentList?.shoppingItems?.where((x) => !x!.crossedOut && x.sortOrder! > crossedOffset) ?? + []) { notCrossedOut!.sortOrder = notCrossedOut.sortOrder! - crossedOffset; } }); @@ -276,20 +248,14 @@ class MainPageState extends State User.currentList?.save(); } - void showInSnackBar(String value, - {Duration? duration, SnackBarAction? action}) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(value), - duration: duration ?? Duration(seconds: 3), - action: action)); + void showInSnackBar(String value, {Duration? duration, SnackBarAction? action}) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(value), duration: duration ?? Duration(seconds: 3), action: action)); } - void showInDrawerSnackBar(String value, - {Duration? duration, SnackBarAction? action}) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(value), - duration: duration ?? Duration(seconds: 3), - action: action)); + void showInDrawerSnackBar(String value, {Duration? duration, SnackBarAction? action}) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(value), duration: duration ?? Duration(seconds: 3), action: action)); } Future register() => Navigator.pushNamed(cont!, "/registration"); @@ -302,24 +268,20 @@ class MainPageState extends State void handleDismissMain(DismissDirection dir, ShoppingItem s) async { var list = User.currentList; - final String action = (dir == DismissDirection.endToStart) - ? NSSLStrings.of(context)!.archived() - : NSSLStrings.of(context)!.deleted(); + final String action = + (dir == DismissDirection.endToStart) ? NSSLStrings.of(context)!.archived() : NSSLStrings.of(context)!.deleted(); var index = list!.shoppingItems!.indexOf(s); await list.deleteSingleItem(s); setState(() {}); ShoppingListSync.deleteProduct(list.id, s.id, context); updateOrderIndiciesAndSave(); - showInSnackBar( - NSSLStrings.of(context)!.youHaveActionItemMessage() + - "${s.name} $action", + showInSnackBar(NSSLStrings.of(context)!.youHaveActionItemMessage() + "${s.name} $action", action: SnackBarAction( label: NSSLStrings.of(context)!.undo(), onPressed: () { setState(() { list.addSingleItem(s, index: index); - ShoppingListSync.changeProductAmount( - list.id, s.id, s.amount, context); + ShoppingListSync.changeProductAmount(list.id, s.id, s.amount, context); ScaffoldMessenger.of(context).removeCurrentSnackBar(); updateOrderIndiciesAndSave(); }); @@ -339,10 +301,8 @@ class MainPageState extends State builder: (BuildContext context) => CustomThemePage(), fullscreenDialog: true, )) - .whenComplete(() => AdaptiveTheme.of(context).setTheme( - light: Themes.lightTheme.theme!, - dark: Themes.darkTheme.theme, - notify: true)); + .whenComplete(() => AdaptiveTheme.of(context) + .setTheme(light: Themes.lightTheme.theme!, dark: Themes.darkTheme.theme, notify: true)); break; case "PerformanceOverlay": setState(() => performanceOverlay = !performanceOverlay); @@ -391,23 +351,18 @@ class MainPageState extends State if (k.success!) { RegExp reg = RegExp("([0-9]+[.,]?[0-9]*(\\s)?[gkmlGKML]{1,2})"); - String? name = - reg.hasMatch(k.name!) ? k.name : "${k.name} ${k.quantity}${k.unit}"; - var item = list?.shoppingItems - ?.firstWhere((x) => x!.name == name, orElse: () => null); + String? name = reg.hasMatch(k.name!) ? k.name : "${k.name} ${k.quantity}${k.unit}"; + var item = list?.shoppingItems?.firstWhere((x) => x!.name == name, orElse: () => null); ShoppingItem afterAdd; if (item != null) { - var answer = await ShoppingListSync.changeProductAmount( - list!.id, item.id, 1, cont); + var answer = await ShoppingListSync.changeProductAmount(list!.id, item.id, 1, cont); var p = ChangeListItemResult.fromJson((answer).body); setState(() { item.amount = p.amount; item.changed = p.changed; }); } else { - var p = AddListItemResult.fromJson( - (await ShoppingListSync.addProduct(list!.id, name, '-', 1, cont)) - .body); + var p = AddListItemResult.fromJson((await ShoppingListSync.addProduct(list!.id, name, '-', 1, cont)).body); afterAdd = ShoppingItem("${p.name}") ..amount = 1 ..id = p.productId; @@ -422,8 +377,7 @@ class MainPageState extends State Navigator.push( context, MaterialPageRoute( - builder: (BuildContext context) => AddProductToDatabase(ean), - fullscreenDialog: true)); + builder: (BuildContext context) => AddProductToDatabase(ean), fullscreenDialog: true)); } void addListDialog() { @@ -434,10 +388,7 @@ class MainPageState extends State title: NSSLStrings.of(context)!.addNewListTitle(), context: cont); - showDialog( - builder: (BuildContext context) => sd, - context: cont!, - barrierDismissible: false); + showDialog(builder: (BuildContext context) => sd, context: cont!, barrierDismissible: false); } Future renameListDialog(int listId) { @@ -458,28 +409,23 @@ class MainPageState extends State var newList = ShoppingList(newListRes.id, newListRes.name); setState(() => User.shoppingLists.add(newList)); changeCurrentList(User.shoppingLists.indexOf(newList)); - firebaseMessaging - ?.subscribeToTopic(newList.id.toString() + "shoppingListTopic"); + firebaseMessaging?.subscribeToTopic(newList.id.toString() + "shoppingListTopic"); newList.save(); } Widget _buildDrawer(BuildContext context) { var isDarkTheme = AdaptiveTheme.of(context).mode == AdaptiveThemeMode.dark; var userheader = UserAccountsDrawerHeader( - accountName: - Text(User.username ?? NSSLStrings.of(context)!.notLoggedInYet()), - accountEmail: - Text(User.eMail ?? NSSLStrings.of(context)!.notLoggedInYet()), + accountName: Text(User.username ?? NSSLStrings.of(context)!.notLoggedInYet()), + accountEmail: Text(User.eMail ?? NSSLStrings.of(context)!.notLoggedInYet()), currentAccountPicture: CircleAvatar( child: Text( User.username?.substring(0, 2).toUpperCase() ?? "", style: TextStyle(color: isDarkTheme ? Colors.black : Colors.white), ), backgroundColor: isDarkTheme - ? Themes - .darkTheme.theme!.floatingActionButtonTheme.backgroundColor - : Themes - .lightTheme.theme!.floatingActionButtonTheme.backgroundColor), + ? Themes.darkTheme.theme!.floatingActionButtonTheme.backgroundColor + : Themes.lightTheme.theme!.floatingActionButtonTheme.backgroundColor), onDetailsPressed: () { _showDrawerContents = !_showDrawerContents; _showDrawerContents ? _controller!.reverse() : _controller!.forward(); @@ -490,29 +436,24 @@ class MainPageState extends State ? User.shoppingLists .map((x) => ListTile( title: Text(x.name ?? ""), - onTap: () => changeCurrentList(User.shoppingLists.indexOf( - User.shoppingLists.firstWhere((y) => y.id == x.id))), + onTap: () => + changeCurrentList(User.shoppingLists.indexOf(User.shoppingLists.firstWhere((y) => y.id == x.id))), trailing: PopupMenuButton( padding: EdgeInsets.zero, - onSelected: (v) async => - await drawerListItemMenuClicked(v), - itemBuilder: (BuildContext context) => - >[ + onSelected: (v) async => await drawerListItemMenuClicked(v), + itemBuilder: (BuildContext context) => >[ PopupMenuItem( - value: - x.id.toString() + "\u{1E}" + "Contributors", + value: x.id.toString() + "\u{1E}" + "Contributors", child: ListTile( leading: const Icon(Icons.person_add), - title: Text( - NSSLStrings.of(context)!.contributors()), + title: Text(NSSLStrings.of(context)!.contributors()), ), ), PopupMenuItem( value: x.id.toString() + "\u{1E}" + "BoughtList", child: ListTile( leading: const Icon(Icons.history), - title: Text( - NSSLStrings.of(context)!.boughtProducts()), + title: Text(NSSLStrings.of(context)!.boughtProducts()), // NSSLStrings.of(context)!.contributors()), ), ), @@ -527,29 +468,22 @@ class MainPageState extends State value: x.id.toString() + "\u{1E}" + 'Rename', child: ListTile( leading: const Icon(Icons.mode_edit), - title: Text( - NSSLStrings.of(context)!.rename()))), + title: Text(NSSLStrings.of(context)!.rename()))), PopupMenuItem( value: x.id.toString() + "\u{1E}" + 'Auto-Sync', child: ListTile( - leading: Icon(x.messagingEnabled - ? Icons.check_box - : Icons.check_box_outline_blank), - title: Text( - NSSLStrings.of(context)!.autoSync()))), + leading: Icon(x.messagingEnabled ? Icons.check_box : Icons.check_box_outline_blank), + title: Text(NSSLStrings.of(context)!.autoSync()))), const PopupMenuDivider(), PopupMenuItem( value: x.id.toString() + "\u{1E}" + 'Remove', child: ListTile( - leading: const Icon(Icons.delete), - title: Text( - NSSLStrings.of(context)!.remove()))) + leading: const Icon(Icons.delete), title: Text(NSSLStrings.of(context)!.remove()))) ]), )) .toList() : [ - ListTile( - title: Text(NSSLStrings.of(context)!.noListsInDrawerMessage())), + ListTile(title: Text(NSSLStrings.of(context)!.noListsInDrawerMessage())), ]; var emptyListTiles = []; for (int i = 0; i < list.length - 2; i++) @@ -612,9 +546,7 @@ class MainPageState extends State onRefresh: _handleDrawerRefresh, displacement: 1.0), persistentFooterButtons: [ - TextButton( - child: Text(NSSLStrings.of(context)!.addListPB()), - onPressed: addListDialog) + TextButton(child: Text(NSSLStrings.of(context)!.addListPB()), onPressed: addListDialog) ]); return Drawer(child: d); @@ -648,39 +580,30 @@ class MainPageState extends State context: cont!, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogAcceptDeny.create( - title: NSSLStrings.of(cont)?.deleteListTitle() ?? - "" + deleteList.name!, + title: NSSLStrings.of(cont)?.deleteListTitle() ?? "" + deleteList.name!, text: NSSLStrings.of(cont)?.deleteListText() ?? "", onSubmitted: (s) async { - var res = Result.fromJson( - (await ShoppingListSync.deleteList(id, cont)).body); + var res = Result.fromJson((await ShoppingListSync.deleteList(id, cont)).body); if (!(res.success ?? false)) showInDrawerSnackBar(res.error!); else { - showInDrawerSnackBar(deleteList.name! + - " " + - NSSLStrings.of(cont)!.removed()); + showInDrawerSnackBar(deleteList.name! + " " + NSSLStrings.of(cont)!.removed()); if (User.currentList!.id! == id) { - changeCurrentList(User.shoppingLists.indexOf( - User.shoppingLists.firstWhere((l) => l.id != id))); + changeCurrentList(User.shoppingLists.indexOf(User.shoppingLists.firstWhere((l) => l.id != id))); } - setState(() => - User.shoppingLists.removeWhere((x) => x.id == id)); + setState(() => User.shoppingLists.removeWhere((x) => x.id == id)); } }, context: cont)); break; case "Auto-Sync": var list = User.shoppingLists.firstWhere((x) => x.id == id); - list.messagingEnabled - ? list.unsubscribeFromFirebaseMessaging() - : list.subscribeForFirebaseMessaging(); + list.messagingEnabled ? list.unsubscribeFromFirebaseMessaging() : list.subscribeForFirebaseMessaging(); list.messagingEnabled = !list.messagingEnabled; list.save(); break; case "ExportAsPdf": - ExportManager.exportAsPDF( - User.shoppingLists.firstWhere((x) => x.id == id), context); + ExportManager.exportAsPDF(User.shoppingLists.firstWhere((x) => x.id == id), context); break; } } @@ -690,8 +613,7 @@ class MainPageState extends State setState(() => {}); } - Future _handleMainListRefresh() => - _handleListRefresh(User.currentList!.id); + Future _handleMainListRefresh() => _handleListRefresh(User.currentList!.id); Future _handleListRefresh(int? listId) async { await User.shoppingLists.firstWhere((s) => s.id == listId).refresh(cont); @@ -700,9 +622,7 @@ class MainPageState extends State Future shoppingItemChange(ShoppingItem s, int change) async { var res = ChangeListItemResult.fromJson( - (await ShoppingListSync.changeProductAmount( - User.currentList!.id!, s.id, change, cont)) - .body); + (await ShoppingListSync.changeProductAmount(User.currentList!.id!, s.id, change, cont)).body); setState(() { s.id = res.id; s.amount = res.amount; @@ -715,8 +635,7 @@ class MainPageState extends State List> buildChangeMenuItems(BuildContext context) { if (amountPopList.length == 0) for (int i = 1; i <= 99; i++) - amountPopList.add(PopupMenuItem( - value: i.toString(), child: Text(i.toString()))); + amountPopList.add(PopupMenuItem(value: i.toString(), child: Text(i.toString()))); return amountPopList; } @@ -750,11 +669,9 @@ class MainPageState extends State Future _addWithoutSearch(String value) async { var list = User.currentList; - var same = list!.shoppingItems! - .where((x) => x!.name!.toLowerCase() == value.toLowerCase()); + var same = list!.shoppingItems!.where((x) => x!.name!.toLowerCase() == value.toLowerCase()); if (same.length > 0) { - var res = await ShoppingListSync.changeProductAmount( - list.id, same.first!.id!, 1, cont); + var res = await ShoppingListSync.changeProductAmount(list.id, same.first!.id!, 1, cont); if (res.statusCode != 200) showInSnackBar(res.reasonPhrase!); var product = ChangeListItemResult.fromJson(res.body); if (!product.success!) showInSnackBar(product.error!); @@ -764,8 +681,7 @@ class MainPageState extends State }); same.first; } else { - var res = - await ShoppingListSync.addProduct(list.id, value, null, 1, cont); + var res = await ShoppingListSync.addProduct(list.id, value, null, 1, cont); if (res.statusCode != 200) showInSnackBar(res.reasonPhrase!); var product = AddListItemResult.fromJson(res.body); if (!product.success!) showInSnackBar(product.error!); @@ -780,8 +696,7 @@ class MainPageState extends State Future _deleteCrossedOutItems() async { var list = User.currentList; var sublist = list!.shoppingItems!.where((s) => s!.crossedOut).toList(); - var res = await ShoppingListSync.deleteProducts( - list.id, sublist.map((s) => s!.id).toList(), cont); + var res = await ShoppingListSync.deleteProducts(list.id, sublist.map((s) => s!.id).toList(), cont); if (!Result.fromJson(res.body).success!) return; setState(() { for (var item in sublist) list.shoppingItems?.remove(item); @@ -793,10 +708,7 @@ class MainPageState extends State label: NSSLStrings.of(context)!.undo(), onPressed: () async { var res = await ShoppingListSync.changeProducts( - list.id, - sublist.map((s) => s!.id).toList(), - sublist.map((s) => s!.amount).toList(), - cont); + list.id, sublist.map((s) => s!.id).toList(), sublist.map((s) => s!.amount).toList(), cont); var hashResult = HashResult.fromJson(res.body); int ownHash = 0; for (var item in sublist) ownHash += item!.id! + item.amount; @@ -822,9 +734,7 @@ class MainPageState extends State maxLines: 2, onSubmitted: (s) async { var res = ChangeListItemResult.fromJson( - (await ShoppingListSync.changeProductName( - User.currentList!.id, x!.id, s, cont)) - .body); + (await ShoppingListSync.changeProductName(User.currentList!.id, x!.id, s, cont)).body); setState(() { x.id = res.id; x.amount = res.amount; @@ -842,12 +752,10 @@ class MainPageState extends State var ids = []; ids.addAll(User.currentList!.shoppingItems!.map((e) => e!.clone())); ids.forEach((element) { - if (element.sortOrder! > 0xffffffff) - element.sortOrder = element.sortOrder! - 0xffffffff; + if (element.sortOrder! > 0xffffffff) element.sortOrder = element.sortOrder! - 0xffffffff; }); ids.sort((x, y) => x.sortOrder!.compareTo(y.sortOrder!)); - await ShoppingListSync.reorderProducts( - User.currentList!.id, ids.map((e) => e.id).toList(), context); + await ShoppingListSync.reorderProducts(User.currentList!.id, ids.map((e) => e.id).toList(), context); setState(() { isReorderingItems = false; }); diff --git a/pubspec.yaml b/pubspec.yaml index 4be792b..5a36154 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,11 +12,7 @@ dependencies: path_provider: intl: file: - # intl_translation: shared_preferences: - # jwt: - # git: git://github.com/susch19/dart-json_web_token.git - #jaguar_jwt: "^1.1.5" crypto: firebase_core: firebase_messaging: @@ -29,12 +25,17 @@ dependencies: permission_handler: scandit_flutter_datacapture_barcode: flutter_platform_widgets: - # scandit_flutter_datacapture_barcode: ^6.7.0 - # scandit_flutter_datacapture_core: ^6.7.0 - # flutter_scandit: ^0.1.0 pdf: flutter_colorpicker: adaptive_theme: + flutter_svg: + # scandit_flutter_datacapture_barcode: ^6.7.0 + # scandit_flutter_datacapture_core: ^6.7.0 + # flutter_scandit: ^0.1.0 + # intl_translation: + # jwt: + # git: git://github.com/susch19/dart-json_web_token.git + #jaguar_jwt: "^1.1.5" #git: https://github.com/tekartik/sqflite.git @@ -48,6 +49,8 @@ flutter: # included with your application, so that you can use the icons in # the Icons class. uses-material-design: true + assets: + - assets/vectors/ # To add assets to your application, add an assets section here, in # this "flutter" section, as in: From 8e5d487bd732c30725b0260e758e5aa52a3a1cde Mon Sep 17 00:00:00 2001 From: Sascha Date: Sat, 4 Jun 2022 20:16:29 +0200 Subject: [PATCH 03/23] Create a splashscreen (#14) * Use production url and change init function so that setstate isn't needed as a parameter * remove port for production use, this should be a config at some point * Added nssl icon to have a better splash screen * Add generated plugins files to gitignore * Removed generated plugin files --- .gitignore | 4 ++++ android/app/src/main/AndroidManifest.xml | 2 +- lib/manager/startup_manager.dart | 9 ++++----- lib/pages/barcode_scanner_page.dart | 3 +-- lib/pages/main_page.dart | 2 +- lib/server_communication/helper_methods.dart | 16 +++++++++------- linux/flutter/generated_plugin_registrant.cc | 11 ----------- linux/flutter/generated_plugins.cmake | 15 --------------- pubspec.yaml | 5 ++--- windows/flutter/generated_plugin_registrant.cc | 11 ----------- windows/flutter/generated_plugins.cmake | 15 --------------- 11 files changed, 22 insertions(+), 71 deletions(-) delete mode 100644 linux/flutter/generated_plugin_registrant.cc delete mode 100644 linux/flutter/generated_plugins.cmake delete mode 100644 windows/flutter/generated_plugin_registrant.cc delete mode 100644 windows/flutter/generated_plugins.cmake diff --git a/.gitignore b/.gitignore index 0652200..67a0cde 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,7 @@ ios/Flutter/flutter_export_environment.sh .dart_tool/* android/app/src/main/java/io/flutter/plugins/* lib/.license.dart +linux/flutter/generated_plugin_registrant.cc +linux/flutter/generated_plugins.cmake +windows/flutter/generated_plugin_registrant.cc +windows/flutter/generated_plugins.cmake diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d346c30..30d8ad8 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + diff --git a/lib/manager/startup_manager.dart b/lib/manager/startup_manager.dart index 7dfd3ee..fd5ef6e 100644 --- a/lib/manager/startup_manager.dart +++ b/lib/manager/startup_manager.dart @@ -21,7 +21,9 @@ class Startup { static Future initializeMinFunction() async { if (!Platform.isAndroid) return true; - return Firebase.initializeApp().then((value) async => await ScanditFlutterDataCaptureBarcode.initialize()).then((value) => true); + return Firebase.initializeApp() + .then((value) async => await ScanditFlutterDataCaptureBarcode.initialize()) + .then((value) => true); } static Future loadMessagesFromFolder(Function setState) async { @@ -106,7 +108,7 @@ class Startup { // await User.save(); } - static Future initializeNewListsFromServer(Function setState) async { + static Future initializeNewListsFromServer() async { var res = await ShoppingListSync.getLists(null); if (res.statusCode == 200) { @@ -135,9 +137,6 @@ class Startup { User.currentList = User.shoppingLists.firstWhere((x) => x.id == User.currentListIndex, orElse: () => User.shoppingLists.first); - var args = []; - args.add(() {}); - Function.apply(setState, args); return true; } } diff --git a/lib/pages/barcode_scanner_page.dart b/lib/pages/barcode_scanner_page.dart index c2d3e0e..ecd0751 100644 --- a/lib/pages/barcode_scanner_page.dart +++ b/lib/pages/barcode_scanner_page.dart @@ -5,7 +5,6 @@ */ import 'package:flutter/material.dart'; -import 'package:flutter_platform_widgets/flutter_platform_widgets.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:scandit_flutter_datacapture_barcode/scandit_flutter_datacapture_barcode.dart'; import 'package:scandit_flutter_datacapture_barcode/scandit_flutter_datacapture_barcode_capture.dart'; @@ -115,7 +114,7 @@ class _BarcodeScannerScreenState extends State Widget build(BuildContext context) { Widget child; if (_isPermissionMessageVisible) { - child = PlatformText('No permission to access the camera!', + child = Text('No permission to access the camera!', style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Colors.black)); } else { child = _captureView; diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index dc8f080..c0f405f 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -53,7 +53,7 @@ class MainPageState extends State with TickerProviderStateMixin, Widge super.initState(); WidgetsBinding.instance.addObserver(this); Startup.deleteMessagesFromFolder(); - Startup.initializeNewListsFromServer(setState); + Startup.initializeNewListsFromServer().then((value) => {if (value) setState(() {})}); _controller = AnimationController( vsync: this, diff --git a/lib/server_communication/helper_methods.dart b/lib/server_communication/helper_methods.dart index 3087054..1116d7e 100644 --- a/lib/server_communication/helper_methods.dart +++ b/lib/server_communication/helper_methods.dart @@ -10,11 +10,14 @@ import 'user_sync.dart'; class HelperMethods { static const String scheme = "https"; static const String host = "nssl.susch.eu"; + // static const String scheme = "http"; + // static const String host = "192.168.49.22"; // static const String url = "http://192.168.49.22:4344"; - static Future post(String path, BuildContext? context, [Object? body, skipTokenRefresh = false]) async { + static Future post(String path, BuildContext? context, + [Object? body, skipTokenRefresh = false]) async { if (!skipTokenRefresh) await handleTokenRefresh(context); - var res = await http.post(Uri(host: host, scheme: scheme, path: path), + var res = await http.post(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), body: jsonEncode(body), headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); reactToRespone(res, context); @@ -23,8 +26,8 @@ class HelperMethods { static Future get(String path, BuildContext? context, [String query = ""]) async { await handleTokenRefresh(context); - var res = await http.get(Uri(host: host, scheme: scheme, path: path, query: query), - headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token":User.token ?? ""}); + var res = await http.get(Uri(host: host, scheme: scheme, path: path, query: query /*, port: 4344*/), + headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); reactToRespone(res, context); return res; } @@ -32,7 +35,7 @@ class HelperMethods { static Future put(String path, BuildContext? context, [Object? body, bool skipTokenRefresh = false]) async { if (!skipTokenRefresh) await handleTokenRefresh(context); - var res = await http.put(Uri(host: host, scheme: scheme, path: path), + var res = await http.put(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), body: jsonEncode(body), headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); reactToRespone(res, context); @@ -41,7 +44,7 @@ class HelperMethods { static Future delete(String path, BuildContext? context) async { await handleTokenRefresh(context); - var res = await http.delete(Uri(host: host, scheme: scheme, path: path), + var res = await http.delete(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); reactToRespone(res, context); @@ -53,7 +56,6 @@ class HelperMethods { print(jsonString); } - static bool reactToRespone(http.Response respone, BuildContext? context, {ScaffoldState? scaffoldState}) { if (context == null) return false; if (respone.statusCode == 500) { diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc deleted file mode 100644 index e71a16d..0000000 --- a/linux/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,11 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - - -void fl_register_plugins(FlPluginRegistry* registry) { -} diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 51436ae..0000000 --- a/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) diff --git a/pubspec.yaml b/pubspec.yaml index 5a36154..bc2fd01 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: nssl description: An app for handling shopping lists environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.12.0' dependencies: flutter: @@ -23,8 +23,7 @@ dependencies: sqflite_common_ffi: process_run: permission_handler: - scandit_flutter_datacapture_barcode: - flutter_platform_widgets: + scandit_flutter_datacapture_barcode: 6.13.0 pdf: flutter_colorpicker: adaptive_theme: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc deleted file mode 100644 index 8b6d468..0000000 --- a/windows/flutter/generated_plugin_registrant.cc +++ /dev/null @@ -1,11 +0,0 @@ -// -// Generated file. Do not edit. -// - -// clang-format off - -#include "generated_plugin_registrant.h" - - -void RegisterPlugins(flutter::PluginRegistry* registry) { -} diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake deleted file mode 100644 index 4d10c25..0000000 --- a/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) From a357b8f0696e5f18ac0e4b6c14da1e961e60839b Mon Sep 17 00:00:00 2001 From: susch19 Date: Tue, 14 Sep 2021 21:48:59 +0200 Subject: [PATCH 04/23] Added settings and about page * reworked nssl string to not return a nullable, so it doesn't has to be checked everywhere * Added icons for the different things in for the about page * Added a splash screen with a simple icon and black background * changed icon for windows to use the correct nssl icon * Add a release app store and not the debug store for production release --- .gitignore | 5 +- android/app/build.gradle | 20 +- assets/images/scandit.png | Bin 0 -> 14911 bytes assets/vectors/github.svg | 50 +++ assets/vectors/google_play.svg | 411 ++++++++++++++++++ assets/vectors/nssl_icon.svg | 65 +++ lib/generated_plugin_registrant.dart | 2 + lib/helper/simple_dialog.dart | 10 +- lib/helper/simple_dialog_single_input.dart | 10 +- lib/localization/nssl_messages_all.dart | 36 +- lib/localization/nssl_messages_de.dart | 13 +- lib/localization/nssl_messages_en.dart | 1 + lib/localization/nssl_strings.dart | 18 +- lib/main.dart | 6 +- lib/manager/database_manager.dart | 1 + lib/pages/about.dart | 127 ++++++ lib/pages/change_password.dart | 24 +- lib/pages/custom_theme_page.dart | 14 +- lib/pages/login.dart | 8 +- lib/pages/main_page.dart | 173 +++++--- lib/pages/pages.dart | 4 +- lib/pages/product_add_to_database.dart | 26 +- lib/pages/registration.dart | 36 +- lib/pages/settings.dart | 49 +++ lib/pages/shopping_item_search.dart | 6 +- lib/server_communication/helper_methods.dart | 4 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.yaml | 7 +- windows/runner/Runner.rc | 2 +- windows/runner/resources/app_icon.ico | Bin 33772 -> 8861 bytes 30 files changed, 951 insertions(+), 179 deletions(-) create mode 100644 assets/images/scandit.png create mode 100644 assets/vectors/github.svg create mode 100644 assets/vectors/google_play.svg create mode 100644 assets/vectors/nssl_icon.svg create mode 100644 lib/pages/about.dart diff --git a/.gitignore b/.gitignore index 67a0cde..da3c53f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ packages pubspec.lock *.apk *.keystore +*.properties .vscode/ .flutter-plugins .flutter-plugins-dependencies @@ -20,8 +21,10 @@ android/app/google-services.json ios/Flutter/flutter_export_environment.sh .dart_tool/* android/app/src/main/java/io/flutter/plugins/* -lib/.license.dart linux/flutter/generated_plugin_registrant.cc linux/flutter/generated_plugins.cmake windows/flutter/generated_plugin_registrant.cc windows/flutter/generated_plugins.cmake +.license.dart +windows/sqlite3.dll +android/java_pid62552.hprof diff --git a/android/app/build.gradle b/android/app/build.gradle index c2b6020..d653868 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,6 +15,12 @@ apply plugin: 'com.android.application' apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + def keystoreProperties = new Properties() + def keystorePropertiesFile = rootProject.file('key.properties') + if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) + } + android { compileSdkVersion 31 @@ -32,11 +38,19 @@ android { targetSdkVersion 31 } - buildTypes { + signingConfigs { release { - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] } + } + + buildTypes { + release { + signingConfig signingConfigs.release + } debug { applicationIdSuffix ".debug" versionNameSuffix "-debug" diff --git a/assets/images/scandit.png b/assets/images/scandit.png new file mode 100644 index 0000000000000000000000000000000000000000..779216ba669ec5b2362aaec46415874c309adbb7 GIT binary patch literal 14911 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 + + + + + + + + + + + + + + + diff --git a/assets/vectors/google_play.svg b/assets/vectors/google_play.svg new file mode 100644 index 0000000..5c13b49 --- /dev/null +++ b/assets/vectors/google_play.svg @@ -0,0 +1,411 @@ + + + + diff --git a/assets/vectors/nssl_icon.svg b/assets/vectors/nssl_icon.svg new file mode 100644 index 0000000..cdb5f3d --- /dev/null +++ b/assets/vectors/nssl_icon.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index 26631ee..1527a79 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -8,6 +8,7 @@ import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_messaging_web/firebase_messaging_web.dart'; import 'package:shared_preferences_web/shared_preferences_web.dart'; +import 'package:url_launcher_web/url_launcher_web.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; @@ -16,5 +17,6 @@ void registerPlugins(Registrar registrar) { FirebaseCoreWeb.registerWith(registrar); FirebaseMessagingWeb.registerWith(registrar); SharedPreferencesPlugin.registerWith(registrar); + UrlLauncherPlugin.registerWith(registrar); registrar.registerMessageHandler(); } diff --git a/lib/helper/simple_dialog.dart b/lib/helper/simple_dialog.dart index 8b411d2..cd4ec6e 100644 --- a/lib/helper/simple_dialog.dart +++ b/lib/helper/simple_dialog.dart @@ -6,7 +6,7 @@ class SimpleDialogAcceptDeny { {String title = "", String text = "", ValueChanged? onSubmitted, - BuildContext? context}) { + required BuildContext context}) { return AlertDialog( title: title == "" ? null : Text(title), content: SingleChildScrollView( @@ -16,12 +16,12 @@ class SimpleDialogAcceptDeny { ), actions: [ TextButton( - child: Text(NSSLStrings.of(context)!.cancelButton()), - onPressed: () => Navigator.pop(context!, "")), + child: Text(NSSLStrings.of(context).cancelButton()), + onPressed: () => Navigator.pop(context, "")), TextButton( - child: Text(NSSLStrings.of(context)!.acceptButton()), + child: Text(NSSLStrings.of(context).acceptButton()), onPressed: () { - Navigator.pop(context!, ""); + Navigator.pop(context, ""); onSubmitted!(""); }) ]); diff --git a/lib/helper/simple_dialog_single_input.dart b/lib/helper/simple_dialog_single_input.dart index 9765be7..e1743db 100644 --- a/lib/helper/simple_dialog_single_input.dart +++ b/lib/helper/simple_dialog_single_input.dart @@ -9,7 +9,7 @@ class SimpleDialogSingleInput { String defaultText = "", int maxLines = 1, ValueChanged? onSubmitted, - BuildContext? context, + required BuildContext context, }) { var tec = TextEditingController(); tec.text = defaultText; @@ -25,18 +25,18 @@ class SimpleDialogSingleInput { maxLines: maxLines, autofocus: true, onSubmitted: (s) { - Navigator.pop(context!); + Navigator.pop(context); onSubmitted!(s); }), ], ), ), actions: [ - TextButton(child: Text(NSSLStrings.of(context)!.cancelButton()), onPressed: () => Navigator.pop(context!, "")), + TextButton(child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () => Navigator.pop(context, "")), TextButton( - child: Text(NSSLStrings.of(context)!.acceptButton()), + child: Text(NSSLStrings.of(context).acceptButton()), onPressed: () { - Navigator.pop(context!, ""); + Navigator.pop(context, ""); onSubmitted!(tec.text); }) ]); diff --git a/lib/localization/nssl_messages_all.dart b/lib/localization/nssl_messages_all.dart index 2dc68fd..0faba72 100644 --- a/lib/localization/nssl_messages_all.dart +++ b/lib/localization/nssl_messages_all.dart @@ -14,34 +14,30 @@ Map _deferredLibraries = { MessageLookupByLibrary? _findExact(localeName) { switch (localeName) { - case 'en': - return m_en.messages; - case 'es': - return null; //messages_es.messages; case 'de': return m_de.messages; default: - return null; + return m_en.messages; } } /// User programs should call this before using [localeName] for messages. -Future initializeMessages(String localeName) { - var lib = _deferredLibraries[Intl.canonicalizedLocale(localeName)]; - var load = lib == null ? Future.value(false) : Future.value(null); - return load.then((_) { - initializeInternalMessageLookup(() => CompositeMessageLookup()); - messageLookup.addLocale(localeName, _findGeneratedMessagesFor); - }); -} + Future initializeMessages(String localeName) { + var lib = _deferredLibraries[Intl.canonicalizedLocale(localeName)]; + var load = lib == null ? Future.value(false) : Future.value(null); + return load.then((_) { + initializeInternalMessageLookup(() => CompositeMessageLookup()); + messageLookup.addLocale(localeName, _findGeneratedMessagesFor); + }); + } -bool _messagesExistFor(String locale) { - var messages; - try { - messages = _findExact(locale); - } catch (e) {} - return messages != null; -} + bool _messagesExistFor(String locale) { + var messages; + try { + messages = _findExact(locale); + } catch (e) {} + return messages != null; + } MessageLookupByLibrary? _findGeneratedMessagesFor(locale) { var actualLocale = diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index 3167a28..4004f9d 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -8,7 +8,7 @@ class MessageLookup extends MessageLookupByLibrary { final Map messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "options": MessageLookupByLibrary.simpleMessage("Optionen"), - "changeTheme": MessageLookupByLibrary.simpleMessage("Theme ändern"), + "changeTheme": MessageLookupByLibrary.simpleMessage("Design ändern"), "scanPB": MessageLookupByLibrary.simpleMessage("SCANNEN"), "addPB": MessageLookupByLibrary.simpleMessage("ADD"), //TODO find good german word "searchPB": MessageLookupByLibrary.simpleMessage("SUCHEN"), @@ -138,6 +138,17 @@ class MessageLookup extends MessageLookupByLibrary { "requestPasswordResetButton": MessageLookupByLibrary.simpleMessage("PASSWORT ZURÜCKSETZUNG BEANTRAGEN"), "requestPasswordResetTitle": MessageLookupByLibrary.simpleMessage("Passwort zurücksetzen"), "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage('Die Passwort zurücksetzen Email wurde erfolgreich an die Adresse gesendet, sollte diese existieren. Weitere Schritte für das abschließen des Resets sind in der Email enthalten.'), + "settings": MessageLookupByLibrary.simpleMessage('Einstellungen'), + "about": MessageLookupByLibrary.simpleMessage('Über'), + "codeOnGithub": MessageLookupByLibrary.simpleMessage('Schau doch mal in den Code auf GitHub rein'), + "playstoreEntry": MessageLookupByLibrary.simpleMessage('Play Store Eintrag'), + "iconSource": MessageLookupByLibrary.simpleMessage('Wer hat dieses schicke Icon gemacht? Finde es heraus!'), + "scanditCredit":MessageLookupByLibrary.simpleMessage('hat diesen super Scanner in der App zur Verfügung gestellt'), + "aboutText": MessageLookupByLibrary.simpleMessage('In jahrelanger Handarbeit geschmiedet mit dem einzigen Ziel, die Einkaufsplanung mit anderen zu vereinfachen und dabei seine Lieblingsprodukte blitzschnell per Kamera zu erfassen.'), + "freeText": MessageLookupByLibrary.simpleMessage('Kostenlos, Werbefrei, für immer!'), + "questionsErrors": MessageLookupByLibrary.simpleMessage('Bei Fragen, Anregungen, Fehlern oder sonstigen Belangen kann jederzeit auf GitHub vorbeigeschaut werden, um ein Issue zu eröffnen.'), + + }; } diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index 95cd79d..cc4d6f5 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -137,5 +137,6 @@ class MessageLookup extends MessageLookupByLibrary { "requestPasswordResetButton": MessageLookupByLibrary.simpleMessage("REQUEST PASSWORD RESET"), "requestPasswordResetTitle": MessageLookupByLibrary.simpleMessage("Password Reset"), "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage('If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.'), + "settings": MessageLookupByLibrary.simpleMessage('Settings'), }; } diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index d79b3a6..b7d0725 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -11,15 +11,13 @@ class NSSLStrings { static Future load(Locale locale) { return initializeMessages(locale.toString()).then((dynamic _) { - // ignore: strong_mode_uses_dynamic_as_bottom return NSSLStrings(locale); + // ignore: strong_mode_uses_dynamic_as_bottom }); } - static NSSLStrings? of(BuildContext? context) { - if (context == null) return null; - - return Localizations.of(context, NSSLStrings); + static NSSLStrings of(BuildContext context) { + return Localizations.of(context, NSSLStrings)!; } // static final NSSLStrings instance = NSSLStrings(); @@ -302,8 +300,16 @@ class NSSLStrings { Intl.message('Reorder', name: 'reorderItems', locale: _localeName); String refresh() => Intl.message('Refresh', name: "refresh", locale: _localeName); + String settings() => Intl.message('Settings', name: "settings", locale: _localeName); + String about() => Intl.message('About', name: "about", locale: _localeName); + String codeOnGithub() => Intl.message('View Source Code on GitHub', name: "codeOnGithub", locale: _localeName); + String playstoreEntry() => Intl.message('Entry on Play Store', name: "playstoreEntry", locale: _localeName); + String iconSource() => Intl.message('Source of the App Icon', name: "iconSource", locale: _localeName); + String scanditCredit() => Intl.message('has provided the Scanner for this App', name: "scanditCredit", locale: _localeName); + String aboutText() => Intl.message('Forged over many years with the only intention to make it easier for multiple people to plan their shopping and add their favorite products via camera in an unmatched speed.', name: "aboutText", locale: _localeName); + String freeText() => Intl.message('Free of charge, no Advertisments, forever!', name: "freeText", locale: _localeName); + String questionsErrors() => Intl.message('Questions, Errors or everything else can be send by a GitHub issue.', name: "questionsErrors", locale: _localeName); String okayButton() => Intl.message('OKAY', name: "okayButton", locale: _localeName); - String requestPasswordResetButton() => Intl.message('REQUEST PASSWORD RESET', name: 'requestPasswordResetButton', locale: _localeName); String requestPasswordResetTitle() => Intl.message('Password Reset', name: "requestPasswordResetTitle", locale: _localeName); String requestPasswordResetSuccess() => Intl.message('If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.', name: "requestPasswordResetSuccess", locale: _localeName); diff --git a/lib/main.dart b/lib/main.dart index ba64e41..3ab82aa 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,7 +37,6 @@ Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { Future main() async { // iWonderHowLongThisTakes(); - runApp(FutureBuilder( builder: (c, t) { if (t.connectionState == ConnectionState.done) @@ -127,15 +126,14 @@ class _NSSLState extends State { builder: (theme, darkTheme) => MaterialApp( scrollBehavior: CustomScrollBehavior(), title: 'NSSL', - color: Colors.grey[500], localizationsDelegates: >[ new _NSSLLocalizationsDelegate(), GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, ], supportedLocales: const [ - const Locale('en', 'US'), - const Locale('de', 'DE'), + const Locale('en', ''), + const Locale('de', ''), ], theme: theme, darkTheme: darkTheme, diff --git a/lib/manager/database_manager.dart b/lib/manager/database_manager.dart index 8c3197a..a0bcfed 100644 --- a/lib/manager/database_manager.dart +++ b/lib/manager/database_manager.dart @@ -17,6 +17,7 @@ class DatabaseManager { sqfliteFfiInit(); var dbPath = path.join((await getApplicationDocumentsDirectory()).path, "db.db"); + print(dbPath); database = await databaseFactoryFfi.openDatabase(dbPath, options: OpenDatabaseOptions(version: _version, onCreate: (Database db, int version) async { await db .execute("CREATE TABLE ShoppingItems (id INTEGER PRIMARY KEY, name TEXT, amount INTEGER, crossed INTEGER, res_list_id INTEGER, sortorder INTEGER)"); diff --git a/lib/pages/about.dart b/lib/pages/about.dart new file mode 100644 index 0000000..2abb6fd --- /dev/null +++ b/lib/pages/about.dart @@ -0,0 +1,127 @@ +import 'package:adaptive_theme/adaptive_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:nssl/localization/nssl_strings.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class AboutPage extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(NSSLStrings.of(context).about()), + ), + body: buildBody(context), + ); + } + + Widget buildBody(BuildContext context) { + var iconColor = AdaptiveTheme.of(context).mode == AdaptiveThemeMode.dark ? Colors.white : Colors.black; + return ListView( + children: [ + Container( + margin: EdgeInsets.all(16.0), + child: Column( + children: [ + Center( + child: SvgPicture.asset( + "assets/vectors/nssl_icon.svg", + width: 200, + ), + ), + Container( + margin: EdgeInsets.only( + top: 8.0, + ), + child: Center( + child: Text( + "Non Sucking Shopping List", + style: TextStyle(fontWeight: FontWeight.bold), + ), + ), + ), + ], + ), + ), + Divider(), + ListTile( + title: Text( + NSSLStrings.of(context).freeText(), + style: TextStyle(fontWeight: FontWeight.bold), + textAlign: TextAlign.center, + ), + ), + ListTile( + title: Text( + NSSLStrings.of(context).aboutText(), + textAlign: TextAlign.center, + ), + // "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet."), + ), + ListTile( + title: Text( + NSSLStrings.of(context).questionsErrors(), + textAlign: TextAlign.center, + ), + ), + Divider(), + ListTile( + title: Text( + "Entwickelt von susch19 (Sascha Hering)", + ), + ), + ListTile( + title: Text("Version 0.25"), + ), + Divider(), + ListTile( + leading: SvgPicture.asset( + "assets/vectors/github.svg", + color: iconColor, + width: 32, + ), + title: Text(NSSLStrings.of(context).codeOnGithub()), + onTap: () { + var urlString = "https://github.com/susch19/nssl"; + canLaunch(urlString).then((value) { + if (value) launch(urlString); + }); + }, + ), + Divider(), + ListTile( + leading: SvgPicture.asset("assets/vectors/nssl_icon.svg", alignment: Alignment.center, width: 32), + title: Text(NSSLStrings.of(context).iconSource()), + onTap: () { + var urlString = "https://www.flaticon.com/free-icon/check-list_306470"; + canLaunch(urlString).then((value) { + if (value) launch(urlString); + }); + }, + ), + Divider(), + ListTile( + leading: SvgPicture.asset("assets/vectors/google_play.svg", alignment: Alignment.center, width: 32), + title: Text(NSSLStrings.of(context).playstoreEntry()), + onTap: () { + var urlString = "https://play.google.com/store/apps/details?id=de.susch19.nssl"; + canLaunch(urlString).then((value) { + if (value) launch(urlString); + }); + }, + ), + Divider(), + ListTile( + leading: Image.asset("assets/images/scandit.png", alignment: Alignment.center, width: 128, color: iconColor), + title: Text(NSSLStrings.of(context).scanditCredit()), + onTap: () { + var urlString = "https://scandit.com"; + canLaunch(urlString).then((value) { + if (value) launch(urlString); + }); + }, + ), + ], + ); + } +} diff --git a/lib/pages/change_password.dart b/lib/pages/change_password.dart index 4226a0e..fa0bddf 100644 --- a/lib/pages/change_password.dart +++ b/lib/pages/change_password.dart @@ -33,21 +33,21 @@ class ChangePasswordPageState extends State { oldPwInput.decoration = InputDecoration( labelText: oldPwInput.decoration!.labelText, helperText: oldPwInput.decoration!.helperText, - errorText: NSSLStrings.of(context)!.passwordEmptyError()); + errorText: NSSLStrings.of(context).passwordEmptyError()); error = true; } if (_validateEmpty(newPwInput.textEditingController)) { newPwInput.decoration = InputDecoration( labelText: newPwInput.decoration!.labelText, helperText: newPwInput.decoration!.helperText, - errorText: NSSLStrings.of(context)!.passwordEmptyError()); + errorText: NSSLStrings.of(context).passwordEmptyError()); error = true; } if (_validateEmpty(newPw2Input.textEditingController)) { newPw2Input.decoration = InputDecoration( labelText: newPw2Input.decoration!.labelText, helperText: newPw2Input.decoration!.helperText, - errorText: NSSLStrings.of(context)!.passwordEmptyError()); + errorText: NSSLStrings.of(context).passwordEmptyError()); error = true; } setState(() => {}); @@ -57,7 +57,7 @@ class ChangePasswordPageState extends State { newPw2Input.decoration = InputDecoration( labelText: newPw2Input.decoration!.labelText, helperText: newPw2Input.decoration!.helperText, - errorText: NSSLStrings.of(context)!.passwordsDontMatchError()); + errorText: NSSLStrings.of(context).passwordsDontMatchError()); setState(() => {}); return; } @@ -84,10 +84,10 @@ class ChangePasswordPageState extends State { return; } var dialog = AlertDialog( - title: Text(NSSLStrings.of(context)!.successful()), + title: Text(NSSLStrings.of(context).successful()), content: SingleChildScrollView( child: ListBody( - children: [Text(NSSLStrings.of(context)!.passwordSet())], + children: [Text(NSSLStrings.of(context).passwordSet())], ), ), actions: [ @@ -100,14 +100,14 @@ class ChangePasswordPageState extends State { _resetInput() { oldPwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.oldPasswordHint(), - labelText: NSSLStrings.of(context)!.oldPassword()); + helperText: NSSLStrings.of(context).oldPasswordHint(), + labelText: NSSLStrings.of(context).oldPassword()); newPwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.newPasswordHint(), - labelText: NSSLStrings.of(context)!.newPassword()); + helperText: NSSLStrings.of(context).newPasswordHint(), + labelText: NSSLStrings.of(context).newPassword()); newPw2Input.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.new2PasswordHint(), - labelText: NSSLStrings.of(context)!.new2Password()); + helperText: NSSLStrings.of(context).new2PasswordHint(), + labelText: NSSLStrings.of(context).new2Password()); } @override diff --git a/lib/pages/custom_theme_page.dart b/lib/pages/custom_theme_page.dart index e592ea7..462d665 100644 --- a/lib/pages/custom_theme_page.dart +++ b/lib/pages/custom_theme_page.dart @@ -46,15 +46,15 @@ class CustomThemePageState extends State { return await (showDialog( context: context, builder: (BuildContext context) => AlertDialog( - content: Text(NSSLStrings.of(context)!.discardNewTheme(), style: dialogTextStyle), + content: Text(NSSLStrings.of(context).discardNewTheme(), style: dialogTextStyle), actions: [ TextButton( - child: Text(NSSLStrings.of(context)!.cancelButton()), + child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () { Navigator.of(context).pop(false); }), TextButton( - child: Text(NSSLStrings.of(context)!.discardButton()), + child: Text(NSSLStrings.of(context).discardButton()), onPressed: () { Navigator.of(context).pop(true); }), @@ -111,7 +111,7 @@ class CustomThemePageState extends State { // backgroundColor: td.scaffoldBackgroundColor, key: _scaffoldKey, appBar: AppBar( - title: Text(NSSLStrings.of(context)!.changeTheme() + title: Text(NSSLStrings.of(context).changeTheme() // , style: textColorTheme ), // backgroundColor: td.primaryColor, @@ -124,7 +124,7 @@ class CustomThemePageState extends State { child: ListView(padding: const EdgeInsets.all(16.0), children: [ Column(mainAxisSize: MainAxisSize.min, children: [ Text( - NSSLStrings.of(context)!.changePrimaryColor(), + NSSLStrings.of(context).changePrimaryColor(), // style: td.textTheme.subtitle1, ), Slider( @@ -137,7 +137,7 @@ class CustomThemePageState extends State { ]), Column(mainAxisSize: MainAxisSize.min, children: [ Text( - NSSLStrings.of(context)!.changeAccentColor(), + NSSLStrings.of(context).changeAccentColor(), // style: td.textTheme.subtitle1, ), Slider( @@ -150,7 +150,7 @@ class CustomThemePageState extends State { ]), Row(children: [ Text( - NSSLStrings.of(context)!.changeDarkTheme(), + NSSLStrings.of(context).changeDarkTheme(), // style: td.textTheme.subtitle1, ), Checkbox( diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 02edbb9..ffa7761 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -96,7 +96,7 @@ class LoginPageState extends State { showInSnackBar(res.error!); return; } - showInSnackBar(NSSLStrings.of(context)!.loginSuccessfulMessage()); + showInSnackBar(NSSLStrings.of(context).loginSuccessfulMessage()); bool firstBoot = User.username == null; User.token = res.token; User.username = res.username; @@ -131,7 +131,7 @@ class LoginPageState extends State { } String? _validateEmail(String value) { - if (value.isEmpty) return NSSLStrings.of(context)!.emailRequiredError(); + if (value.isEmpty) return NSSLStrings.of(context).emailRequiredError(); RegExp email = RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); if (!email.hasMatch(value)) @@ -168,7 +168,7 @@ class LoginPageState extends State { return Scaffold( key: _scaffoldKey, resizeToAvoidBottomInset: true, - appBar: AppBar(title: Text(NSSLStrings.of(context)!.login())), + appBar: AppBar(title: Text(NSSLStrings.of(context).login())), body: Form( key: _formKey, autovalidateMode: validateMode, @@ -225,7 +225,7 @@ class LoginPageState extends State { ? Navigator.pushNamed(context, "/registration") : Navigator.popAndPushNamed(context, "/registration"); }, - child: Text(NSSLStrings.of(context)!.registerTextOnLogin()), + child: Text(NSSLStrings.of(context).registerTextOnLogin()), ), ), ), diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index c0f405f..d05aad2 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -77,23 +77,9 @@ class MainPageState extends State with TickerProviderStateMixin, Widge return Scaffold( appBar: AppBar( title: Text( - User.currentList?.name ?? NSSLStrings.of(context)!.noListLoaded(), + User.currentList?.name ?? NSSLStrings.of(context).noListLoaded(), ), - actions: isReorderingItems - ? [] - : [ - PopupMenuButton( - onSelected: selectedOption, - itemBuilder: (BuildContext context) => >[ - PopupMenuItem( - value: 'Options', child: Text(NSSLStrings.of(context)!.changeTheme())), - PopupMenuItem( - value: 'deleteCrossedOut', - child: Text(NSSLStrings.of(context)!.deleteCrossedOutPB())), - PopupMenuItem( - value: 'reorderItems', child: Text(NSSLStrings.of(context)!.reorderItems())), - ]) - ]), + actions: _getMainDropdownActions(context)), body: buildBody(context), floatingActionButton: isReorderingItems ? acceptReordingFAB() : null, drawer: _buildDrawer(context), @@ -101,12 +87,12 @@ class MainPageState extends State with TickerProviderStateMixin, Widge ? [] : [ TextButton( - child: Text(NSSLStrings.of(context)!.addPB()), onPressed: () => _addWithoutSearchDialog(context)) + child: Text(NSSLStrings.of(context).addPB()), onPressed: () => _addWithoutSearchDialog(context)) ] + (Platform.isAndroid - ? [TextButton(child: Text(NSSLStrings.of(context)!.scanPB()), onPressed: _getEAN)] + ? [TextButton(child: Text(NSSLStrings.of(context).scanPB()), onPressed: _getEAN)] : []) + - [TextButton(child: Text(NSSLStrings.of(context)!.searchPB()), onPressed: search)]); + [TextButton(child: Text(NSSLStrings.of(context).searchPB()), onPressed: search)]); } Widget buildBody(BuildContext context) { @@ -130,7 +116,9 @@ class MainPageState extends State with TickerProviderStateMixin, Widge x.name ?? "", maxLines: 2, softWrap: true, - style: TextStyle(decoration: x.crossedOut ? TextDecoration.lineThrough : TextDecoration.none), + style: TextStyle( + decoration: x.crossedOut ? TextDecoration.lineThrough : TextDecoration.none, + decorationThickness: 4), ), ], ), @@ -269,15 +257,15 @@ class MainPageState extends State with TickerProviderStateMixin, Widge void handleDismissMain(DismissDirection dir, ShoppingItem s) async { var list = User.currentList; final String action = - (dir == DismissDirection.endToStart) ? NSSLStrings.of(context)!.archived() : NSSLStrings.of(context)!.deleted(); + (dir == DismissDirection.endToStart) ? NSSLStrings.of(context).archived() : NSSLStrings.of(context).deleted(); var index = list!.shoppingItems!.indexOf(s); await list.deleteSingleItem(s); setState(() {}); ShoppingListSync.deleteProduct(list.id, s.id, context); updateOrderIndiciesAndSave(); - showInSnackBar(NSSLStrings.of(context)!.youHaveActionItemMessage() + "${s.name} $action", + showInSnackBar(NSSLStrings.of(context).youHaveActionItemMessage() + "${s.name} $action", action: SnackBarAction( - label: NSSLStrings.of(context)!.undo(), + label: NSSLStrings.of(context).undo(), onPressed: () { setState(() { list.addSingleItem(s, index: index); @@ -294,15 +282,8 @@ class MainPageState extends State with TickerProviderStateMixin, Widge case "Login/Register": login(); break; - case "Options": - await Navigator.push( - cont!, - MaterialPageRoute( - builder: (BuildContext context) => CustomThemePage(), - fullscreenDialog: true, - )) - .whenComplete(() => AdaptiveTheme.of(context) - .setTheme(light: Themes.lightTheme.theme!, dark: Themes.darkTheme.theme, notify: true)); + case "options": + Navigator.push(context, MaterialPageRoute(builder: (c) => SettingsPage(), fullscreenDialog: true)); break; case "PerformanceOverlay": setState(() => performanceOverlay = !performanceOverlay); @@ -313,6 +294,9 @@ class MainPageState extends State with TickerProviderStateMixin, Widge case "materialGrid": setState(() => materialGrid = !materialGrid); break; + case "logout": + _logout(); + break; case "ChangePassword": Navigator.push( cont!, @@ -382,11 +366,11 @@ class MainPageState extends State with TickerProviderStateMixin, Widge void addListDialog() { var sd = SimpleDialogSingleInput.create( - hintText: NSSLStrings.of(context)!.newNameOfListHint(), - labelText: NSSLStrings.of(context)!.listName(), + hintText: NSSLStrings.of(context).newNameOfListHint(), + labelText: NSSLStrings.of(context).listName(), onSubmitted: createNewList, - title: NSSLStrings.of(context)!.addNewListTitle(), - context: cont); + title: NSSLStrings.of(context).addNewListTitle(), + context: context); showDialog(builder: (BuildContext context) => sd, context: cont!, barrierDismissible: false); } @@ -396,11 +380,11 @@ class MainPageState extends State with TickerProviderStateMixin, Widge context: cont!, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogSingleInput.create( - hintText: NSSLStrings.of(context)!.renameListHint(), - labelText: NSSLStrings.of(context)!.listName(), + hintText: NSSLStrings.of(context).renameListHint(), + labelText: NSSLStrings.of(context).listName(), onSubmitted: (s) => renameList(listId, s), - title: NSSLStrings.of(context)!.renameListTitle(), - context: cont)); + title: NSSLStrings.of(context).renameListTitle(), + context: context)); } Future createNewList(String listName) async { @@ -416,8 +400,8 @@ class MainPageState extends State with TickerProviderStateMixin, Widge Widget _buildDrawer(BuildContext context) { var isDarkTheme = AdaptiveTheme.of(context).mode == AdaptiveThemeMode.dark; var userheader = UserAccountsDrawerHeader( - accountName: Text(User.username ?? NSSLStrings.of(context)!.notLoggedInYet()), - accountEmail: Text(User.eMail ?? NSSLStrings.of(context)!.notLoggedInYet()), + accountName: Text(User.username ?? NSSLStrings.of(context).notLoggedInYet()), + accountEmail: Text(User.eMail ?? NSSLStrings.of(context).notLoggedInYet()), currentAccountPicture: CircleAvatar( child: Text( User.username?.substring(0, 2).toUpperCase() ?? "", @@ -446,14 +430,14 @@ class MainPageState extends State with TickerProviderStateMixin, Widge value: x.id.toString() + "\u{1E}" + "Contributors", child: ListTile( leading: const Icon(Icons.person_add), - title: Text(NSSLStrings.of(context)!.contributors()), + title: Text(NSSLStrings.of(context).contributors()), ), ), PopupMenuItem( value: x.id.toString() + "\u{1E}" + "BoughtList", child: ListTile( leading: const Icon(Icons.history), - title: Text(NSSLStrings.of(context)!.boughtProducts()), + title: Text(NSSLStrings.of(context).boughtProducts()), // NSSLStrings.of(context)!.contributors()), ), ), @@ -468,22 +452,22 @@ class MainPageState extends State with TickerProviderStateMixin, Widge value: x.id.toString() + "\u{1E}" + 'Rename', child: ListTile( leading: const Icon(Icons.mode_edit), - title: Text(NSSLStrings.of(context)!.rename()))), + title: Text(NSSLStrings.of(context).rename()))), PopupMenuItem( value: x.id.toString() + "\u{1E}" + 'Auto-Sync', child: ListTile( leading: Icon(x.messagingEnabled ? Icons.check_box : Icons.check_box_outline_blank), - title: Text(NSSLStrings.of(context)!.autoSync()))), + title: Text(NSSLStrings.of(context).autoSync()))), const PopupMenuDivider(), PopupMenuItem( value: x.id.toString() + "\u{1E}" + 'Remove', child: ListTile( - leading: const Icon(Icons.delete), title: Text(NSSLStrings.of(context)!.remove()))) + leading: const Icon(Icons.delete), title: Text(NSSLStrings.of(context).remove()))) ]), )) .toList() : [ - ListTile(title: Text(NSSLStrings.of(context)!.noListsInDrawerMessage())), + ListTile(title: Text(NSSLStrings.of(context).noListsInDrawerMessage())), ]; var emptyListTiles = []; for (int i = 0; i < list.length - 2; i++) @@ -512,25 +496,21 @@ class MainPageState extends State with TickerProviderStateMixin, Widge children: [ ListTile( leading: const Icon(Icons.sync), - title: Text(NSSLStrings.of(context)!.refresh()), + title: Text(NSSLStrings.of(context).refresh()), onTap: () => _handleDrawerRefresh(), ), ListTile( leading: const Icon(Icons.restore_page_outlined), title: Text( - NSSLStrings.of(context)!.changePasswordPD(), + NSSLStrings.of(context).changePasswordPD(), ), onTap: () => selectedOption("ChangePassword"), ), ListTile( leading: const Icon(Icons.exit_to_app), - title: Text(NSSLStrings.of(context)!.logout()), + title: Text(NSSLStrings.of(context).logout()), onTap: () async { - await User.delete(); - User.username = null; - User.eMail = null; - User.token = null; - runApp(NSSL()); + await _logout(); }, ), Column(children: emptyListTiles) @@ -546,12 +526,20 @@ class MainPageState extends State with TickerProviderStateMixin, Widge onRefresh: _handleDrawerRefresh, displacement: 1.0), persistentFooterButtons: [ - TextButton(child: Text(NSSLStrings.of(context)!.addListPB()), onPressed: addListDialog) + TextButton(child: Text(NSSLStrings.of(context).addListPB()), onPressed: addListDialog) ]); return Drawer(child: d); } + Future _logout() async { + await User.delete(); + User.username = null; + User.eMail = null; + User.token = null; + runApp(NSSL()); + } + Future drawerListItemMenuClicked(String value) async { var splitted = value.split('\u{1E}'); int id = int.parse(splitted[0]); @@ -580,21 +568,21 @@ class MainPageState extends State with TickerProviderStateMixin, Widge context: cont!, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogAcceptDeny.create( - title: NSSLStrings.of(cont)?.deleteListTitle() ?? "" + deleteList.name!, - text: NSSLStrings.of(cont)?.deleteListText() ?? "", + title: NSSLStrings.of(context).deleteListTitle() + deleteList.name!, + text: NSSLStrings.of(context).deleteListText(), onSubmitted: (s) async { var res = Result.fromJson((await ShoppingListSync.deleteList(id, cont)).body); if (!(res.success ?? false)) showInDrawerSnackBar(res.error!); else { - showInDrawerSnackBar(deleteList.name! + " " + NSSLStrings.of(cont)!.removed()); + showInDrawerSnackBar(deleteList.name! + " " + NSSLStrings.of(context).removed()); if (User.currentList!.id! == id) { changeCurrentList(User.shoppingLists.indexOf(User.shoppingLists.firstWhere((l) => l.id != id))); } setState(() => User.shoppingLists.removeWhere((x) => x.id == id)); } }, - context: cont)); + context: context)); break; case "Auto-Sync": var list = User.shoppingLists.firstWhere((x) => x.id == id); @@ -654,9 +642,9 @@ class MainPageState extends State with TickerProviderStateMixin, Widge barrierDismissible: false, builder: (BuildContext context) => SimpleDialogSingleInput.create( context: context, - title: NSSLStrings.of(context)!.addProduct(), - hintText: NSSLStrings.of(context)!.addProductWithoutSearch(), - labelText: NSSLStrings.of(context)!.productName(), + title: NSSLStrings.of(context).addProduct(), + hintText: NSSLStrings.of(context).addProductWithoutSearch(), + labelText: NSSLStrings.of(context).productName(), onSubmitted: _addWithoutSearch)); } @@ -702,10 +690,10 @@ class MainPageState extends State with TickerProviderStateMixin, Widge for (var item in sublist) list.shoppingItems?.remove(item); }); updateOrderIndiciesAndSave(); - showInSnackBar(NSSLStrings.of(context)!.messageDeleteAllCrossedOut(), + showInSnackBar(NSSLStrings.of(context).messageDeleteAllCrossedOut(), duration: Duration(seconds: 10), action: SnackBarAction( - label: NSSLStrings.of(context)!.undo(), + label: NSSLStrings.of(context).undo(), onPressed: () async { var res = await ShoppingListSync.changeProducts( list.id, sublist.map((s) => s!.id).toList(), sublist.map((s) => s!.amount).toList(), cont); @@ -726,10 +714,10 @@ class MainPageState extends State with TickerProviderStateMixin, Widge context: cont!, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogSingleInput.create( - context: cont, - title: NSSLStrings.of(context)!.renameListItem(), - hintText: NSSLStrings.of(context)!.renameListHint(), - labelText: NSSLStrings.of(context)!.renameListItemLabel(), + context: context, + title: NSSLStrings.of(context).renameListItem(), + hintText: NSSLStrings.of(context).renameListHint(), + labelText: NSSLStrings.of(context).renameListItemLabel(), defaultText: x?.name ?? "", maxLines: 2, onSubmitted: (s) async { @@ -761,4 +749,49 @@ class MainPageState extends State with TickerProviderStateMixin, Widge }); }, ); + + List _getMainDropdownActions(BuildContext context) { + if (isReorderingItems) return []; + + return [ + // IconButton( + // onPressed: () { + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (BuildContext context) => SettingsPage(), + // fullscreenDialog: true, + // )); + // }, + // icon: Icon(Icons.settings)), + PopupMenuButton( + onSelected: selectedOption, + itemBuilder: (BuildContext context) => >[ + PopupMenuItem( + value: 'deleteCrossedOut', + child: Text( + NSSLStrings.of(context).deleteCrossedOutPB(), + ), + ), + PopupMenuItem( + value: 'reorderItems', + child: Text( + NSSLStrings.of(context).reorderItems(), + ), + ), + PopupMenuItem( + value: 'options', + child: Text( + NSSLStrings.of(context).options(), + ), + ), + PopupMenuItem( + value: 'logout', + child: Text( + NSSLStrings.of(context).logout(), + ), + ), + ]) + ]; + } } diff --git a/lib/pages/pages.dart b/lib/pages/pages.dart index d7a0a13..d80328e 100644 --- a/lib/pages/pages.dart +++ b/lib/pages/pages.dart @@ -8,4 +8,6 @@ export 'shopping_item_search.dart'; export 'custom_theme_page.dart'; export 'change_password.dart'; export 'bought_items.dart'; -export 'main_page.dart'; \ No newline at end of file +export 'main_page.dart'; +export 'settings.dart'; +export 'about.dart'; \ No newline at end of file diff --git a/lib/pages/product_add_to_database.dart b/lib/pages/product_add_to_database.dart index 0becf27..1b8b3ae 100644 --- a/lib/pages/product_add_to_database.dart +++ b/lib/pages/product_add_to_database.dart @@ -73,7 +73,7 @@ class AddProductToDatabaseState extends State { Future _handleSubmitted() async { if (_isSendToServer) { - showInSnackBar(NSSLStrings.of(context)!.bePatient()); + showInSnackBar(NSSLStrings.of(context).bePatient()); return false; } final FormState form = _formKey.currentState!; @@ -107,7 +107,7 @@ class AddProductToDatabaseState extends State { if (!res.success!) showInSnackBar(res.error!); else { - showInSnackBar(NSSLStrings.of(context)!.successful()); + showInSnackBar(NSSLStrings.of(context).successful()); if (putInList) { var list = User.currentList!; var pres = AddListItemResult.fromJson( @@ -139,7 +139,7 @@ class AddProductToDatabaseState extends State { return Scaffold( key: _scaffoldKey, appBar: AppBar( - title: Text(NSSLStrings.of(context)!.newProductTitle()), + title: Text(NSSLStrings.of(context).newProductTitle()), actions: [ TextButton( child: Text(NSSLStrings.of(context)!.saveButton(), @@ -156,8 +156,8 @@ class AddProductToDatabaseState extends State { Container( child: TextFormField( decoration: InputDecoration( - labelText: NSSLStrings.of(context)!.newProductName(), - hintText: NSSLStrings.of(context)!.newProductNameHint(), + labelText: NSSLStrings.of(context).newProductName(), + hintText: NSSLStrings.of(context).newProductNameHint(), ), autofocus: true, controller: tecProductName, @@ -167,9 +167,9 @@ class AddProductToDatabaseState extends State { child: TextFormField( decoration: InputDecoration( labelText: - NSSLStrings.of(context)!.newProductBrandName(), + NSSLStrings.of(context).newProductBrandName(), hintText: - NSSLStrings.of(context)!.newProductBrandNameHint()), + NSSLStrings.of(context).newProductBrandNameHint()), autofocus: false, controller: tecBrandName, onSaved: (s) => brandName = s, @@ -177,9 +177,9 @@ class AddProductToDatabaseState extends State { Container( child: TextFormField( decoration: InputDecoration( - labelText: NSSLStrings.of(context)!.newProductWeight(), + labelText: NSSLStrings.of(context).newProductWeight(), hintText: - NSSLStrings.of(context)!.newProductWeightHint()), + NSSLStrings.of(context).newProductWeightHint()), autofocus: false, onSaved: (s) => weight = s, controller: tecPackagingSize)), @@ -189,12 +189,12 @@ class AddProductToDatabaseState extends State { border: Border(bottom: BorderSide(color: theme.dividerColor))), alignment: FractionalOffset.bottomLeft, - child: Text(NSSLStrings.of(context)!.codeText() + gtin!)), + child: Text(NSSLStrings.of(context).codeText() + gtin!)), Container( padding: const EdgeInsets.symmetric(vertical: 8.0), alignment: FractionalOffset.bottomLeft, child: Row(children: [ - Text(NSSLStrings.of(context)!.newProductAddToList()), + Text(NSSLStrings.of(context).newProductAddToList()), Checkbox( value: putInList, onChanged: (b) => setState(() => putInList = !putInList)) @@ -210,9 +210,9 @@ class AddProductToDatabaseState extends State { String? _validateName(String? value) { _saveNeeded = true; - if (value!.isEmpty) return NSSLStrings.of(context)!.fieldRequiredError(); + if (value!.isEmpty) return NSSLStrings.of(context).fieldRequiredError(); if (value.length < 3) - return NSSLStrings.of(context)!.newProductNameToShort(); + return NSSLStrings.of(context).newProductNameToShort(); return null; } diff --git a/lib/pages/registration.dart b/lib/pages/registration.dart index 7626cc8..a1bd0f8 100644 --- a/lib/pages/registration.dart +++ b/lib/pages/registration.dart @@ -107,7 +107,7 @@ class RegistrationState extends State { showInSnackBar(response.error!); return; } - showInSnackBar(NSSLStrings.of(context)!.registrationSuccessfulMessage()); + showInSnackBar(NSSLStrings.of(context).registrationSuccessfulMessage()); var x = await UserSync.login(name, password, context); if (x.statusCode != 200) { @@ -127,32 +127,32 @@ class RegistrationState extends State { String? _validateName(String? value) { if (value!.isEmpty) - return NSSLStrings.of(context)!.usernameEmptyError(); + return NSSLStrings.of(context).usernameEmptyError(); else if (value.length < 4) - return NSSLStrings.of(context)!.usernameToShortError(); + return NSSLStrings.of(context).usernameToShortError(); return null; } String? _validateEmail(String? value) { - if (value!.isEmpty) return NSSLStrings.of(context)!.emailEmptyError(); + if (value!.isEmpty) return NSSLStrings.of(context).emailEmptyError(); RegExp email = RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); if (!email.hasMatch(value)) - return NSSLStrings.of(context)!.emailIncorrectFormatError(); + return NSSLStrings.of(context).emailIncorrectFormatError(); return null; } String? _validatePassword(String? value) { if (pwInput.textEditingController.text.isEmpty) - return NSSLStrings.of(context)!.chooseAPasswordPrompt(); + return NSSLStrings.of(context).chooseAPasswordPrompt(); return null; } String? _validatePassword2(String? value) { if (pwInput.textEditingController.text.isEmpty) - return NSSLStrings.of(context)!.reenterPasswordPrompt(); + return NSSLStrings.of(context).reenterPasswordPrompt(); if (pwInput.textEditingController.text != value) - return NSSLStrings.of(context)!.passwordsDontMatchError(); + return NSSLStrings.of(context).passwordsDontMatchError(); return null; } @@ -162,7 +162,7 @@ class RegistrationState extends State { return Scaffold( key: _scaffoldKey, appBar: AppBar( - title: Text(NSSLStrings.of(context)!.registrationTitle())), + title: Text(NSSLStrings.of(context).registrationTitle())), body: Form( key: _formKey, autovalidateMode: validateMode, @@ -231,7 +231,7 @@ class RegistrationState extends State { child: ElevatedButton( child: Center( child: Text( - NSSLStrings.of(context)!.registerButton()), + NSSLStrings.of(context).registerButton()), ), onPressed: _handleSubmitted, ), @@ -258,20 +258,20 @@ class RegistrationState extends State { _resetInput() { nameInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.usernameRegisterHint(), - labelText: NSSLStrings.of(context)!.username()); + helperText: NSSLStrings.of(context).usernameRegisterHint(), + labelText: NSSLStrings.of(context).username()); emailInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.emailRegisterHint(), - labelText: NSSLStrings.of(context)!.emailTitle()); + helperText: NSSLStrings.of(context).emailRegisterHint(), + labelText: NSSLStrings.of(context).emailTitle()); pwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.passwordRegisterHint(), - labelText: NSSLStrings.of(context)!.password()); + helperText: NSSLStrings.of(context).passwordRegisterHint(), + labelText: NSSLStrings.of(context).password()); pw2Input.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.retypePasswordHint(), - labelText: NSSLStrings.of(context)!.retypePasswordTitle()); + helperText: NSSLStrings.of(context).retypePasswordHint(), + labelText: NSSLStrings.of(context).retypePasswordTitle()); } @override diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index e69de29..9fd7bb3 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -0,0 +1,49 @@ +import 'package:adaptive_theme/adaptive_theme.dart'; +import 'package:flutter/material.dart'; +import 'package:nssl/localization/nssl_strings.dart'; +import 'package:nssl/options/themes.dart'; +import 'package:nssl/pages/pages.dart'; +import 'package:nssl/pages/product_add_to_database.dart'; + +class SettingsPage extends StatefulWidget { + SettingsPage(); + + @override + SettingsPageState createState() => SettingsPageState(); +} + +class SettingsPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + resizeToAvoidBottomInset: true, + appBar: AppBar( + title: Text(NSSLStrings.of(context).settings()), + leading: IconButton(onPressed: () => Navigator.pop(context), icon: Icon(Icons.arrow_back)), + ), + body: ListView(children: [ + ListTile( + leading: Icon(Icons.palette), + title: Text(NSSLStrings.of(context).changeTheme()), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (BuildContext context) => CustomThemePage(), + fullscreenDialog: true, + )) + .whenComplete(() => AdaptiveTheme.of(context) + .setTheme(light: Themes.lightTheme.theme!, dark: Themes.darkTheme.theme, notify: true)); + }, + ), + Divider(), + ListTile( + leading: Icon(Icons.info), + title: Text(NSSLStrings.of(context).about()), + onTap: () => Navigator.push( + context, MaterialPageRoute(builder: (c) => AboutPage(), fullscreenDialog: true)), + ), + ]), + ); + } +} diff --git a/lib/pages/shopping_item_search.dart b/lib/pages/shopping_item_search.dart index 91a6ad0..6607a25 100644 --- a/lib/pages/shopping_item_search.dart +++ b/lib/pages/shopping_item_search.dart @@ -63,11 +63,11 @@ class _ProductAddPageState extends State { showInSnackBar( item == null - ? NSSLStrings.of(context)!.addedProduct() + "$name" - : "$name" + NSSLStrings.of(context)!.productWasAlreadyInList(), + ? NSSLStrings.of(context).addedProduct() + "$name" + : "$name" + NSSLStrings.of(context).productWasAlreadyInList(), duration: Duration(seconds: item == null ? 2 : 4), action: SnackBarAction( - label: NSSLStrings.of(context)!.undo(), + label: NSSLStrings.of(context).undo(), onPressed: () async { var res = item == null ? await ShoppingListSync.deleteProduct( diff --git a/lib/server_communication/helper_methods.dart b/lib/server_communication/helper_methods.dart index 1116d7e..c5c9d3f 100644 --- a/lib/server_communication/helper_methods.dart +++ b/lib/server_communication/helper_methods.dart @@ -64,8 +64,8 @@ class HelperMethods { showDialog( builder: (BuildContext context) { return AlertDialog( - title: Text(NSSLStrings.of(context)!.tokenExpired()), - content: Text(NSSLStrings.of(context)!.tokenExpiredExplanation()), + title: Text(NSSLStrings.of(context).tokenExpired()), + content: Text(NSSLStrings.of(context).tokenExpiredExplanation()), actions: [ MaterialButton( onPressed: () async { diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b247c0f..f0bed44 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -11,6 +11,7 @@ import flutter_local_notifications import path_provider_macos import shared_preferences_macos import sqlite3_flutter_libs +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) @@ -19,4 +20,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.yaml b/pubspec.yaml index bc2fd01..8f6b04c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: # jwt: # git: git://github.com/susch19/dart-json_web_token.git #jaguar_jwt: "^1.1.5" + url_launcher: #git: https://github.com/tekartik/sqflite.git @@ -43,13 +44,13 @@ dependencies: # The following section is specific to Flutter. flutter: - + assets: + - assets/images/ + - assets/vectors/ # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the Icons class. uses-material-design: true - assets: - - assets/vectors/ # To add assets to your application, add an assets section here, in # this "flutter" section, as in: diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index 2d372d6..82af8a6 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -90,7 +90,7 @@ BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "de.susch19" "\0" - VALUE "FileDescription", "A new Flutter project." "\0" + VALUE "FileDescription", "NSSL" "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "nssl" "\0" VALUE "LegalCopyright", "Copyright (C) 2020 de.susch19. All rights reserved." "\0" diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico index c04e20caf6370ebb9253ad831cc31de4a9c965f6..dc94d2e4f04a5565747d8ad70272cabf16f2ab68 100644 GIT binary patch literal 8861 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 From 505353dbc2b8cd1ee51be32addddc55f5b9e2fd5 Mon Sep 17 00:00:00 2001 From: susch19 Date: Sat, 4 Jun 2022 20:58:45 +0200 Subject: [PATCH 05/23] Fixed list not beeing removed immidiately * because the wrong context was used for showing the snackbar * removed unnecessary not null operator --- lib/pages/bought_items.dart | 53 ++++++----------- lib/pages/change_password.dart | 35 ++++------- lib/pages/contributors.dart | 63 ++++++-------------- lib/pages/forgot_password.dart | 82 +++++++++++--------------- lib/pages/login.dart | 39 ++++-------- lib/pages/main_page.dart | 4 +- lib/pages/product_add_to_database.dart | 62 +++++++------------ lib/pages/shopping_item_search.dart | 35 ++++------- 8 files changed, 133 insertions(+), 240 deletions(-) diff --git a/lib/pages/bought_items.dart b/lib/pages/bought_items.dart index ecdde90..b3fd650 100644 --- a/lib/pages/bought_items.dart +++ b/lib/pages/bought_items.dart @@ -10,12 +10,10 @@ class BoughtItemsPage extends StatefulWidget { final String? title; final int listId; @override - _BoughtItemsPagePageState createState() => - new _BoughtItemsPagePageState(listId); + _BoughtItemsPagePageState createState() => new _BoughtItemsPagePageState(listId); } -class _BoughtItemsPagePageState extends State - with SingleTickerProviderStateMixin { +class _BoughtItemsPagePageState extends State with SingleTickerProviderStateMixin { final GlobalKey _mainScaffoldKey = GlobalKey(); var tec = TextEditingController(); @@ -38,8 +36,7 @@ class _BoughtItemsPagePageState extends State } _BoughtItemsPagePageState(this.listId) { - currentList = - User.shoppingLists.firstWhere((element) => element.id == listId); + currentList = User.shoppingLists.firstWhere((element) => element.id == listId); ShoppingListSync.getList(listId, null, bought: true).then((o) { if (o.statusCode == 500) { @@ -48,8 +45,7 @@ class _BoughtItemsPagePageState extends State } var z = GetBoughtListResult.fromJson(o.body); if (z.products.length <= 0) - showInSnackBar(NSSLStrings.of(context)!.nothingBoughtYet(), - duration: Duration(seconds: 10)); + showInSnackBar(NSSLStrings.of(context).nothingBoughtYet(), duration: Duration(seconds: 10)); else { shoppingItems.addAll(z.products.map((f) => ShoppingItem(f.name) ..id = f.id @@ -68,8 +64,7 @@ class _BoughtItemsPagePageState extends State } setState(() { - _controller = TabController( - vsync: this, length: shoppingItemsGrouped.keys.length); + _controller = TabController(vsync: this, length: shoppingItemsGrouped.keys.length); }); }); } @@ -83,17 +78,14 @@ class _BoughtItemsPagePageState extends State if (_controller == null) return Scaffold( appBar: AppBar( - title: Text(NSSLStrings.of(context)!.boughtProducts()), + title: Text(NSSLStrings.of(context).boughtProducts()), actions: [], ), body: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - child: SizedBox( - width: 40.0, - height: 40.0, - child: CircularProgressIndicator()), + child: SizedBox(width: 40.0, height: 40.0, child: CircularProgressIndicator()), padding: const EdgeInsets.only(top: 16.0), ) ], @@ -102,7 +94,7 @@ class _BoughtItemsPagePageState extends State return Scaffold( key: _mainScaffoldKey, appBar: AppBar( - title: Text(NSSLStrings.of(context)!.boughtProducts()), + title: Text(NSSLStrings.of(context).boughtProducts()), bottom: TabBar( controller: _controller, isScrollable: true, @@ -134,13 +126,10 @@ class _BoughtItemsPagePageState extends State ); } - void showInSnackBar(String value, - {Duration? duration, SnackBarAction? action}) { + void showInSnackBar(String value, {Duration? duration, SnackBarAction? action}) { ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(value), - duration: duration ?? Duration(seconds: 3), - action: action)); + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(value), duration: duration ?? Duration(seconds: 3), action: action)); } List createTabs() { @@ -169,24 +158,16 @@ class _BoughtItemsPagePageState extends State title: Text(i.name!), leading: Text(i.amount.toString() + "x"), onTap: () async { - var existingItem = currentList.shoppingItems - ?.firstOrNull((item) => item?.name == i.name); + var existingItem = currentList.shoppingItems?.firstOrNull((item) => item?.name == i.name); if (existingItem != null) { - var answer = - await ShoppingListSync.changeProductAmount( - currentList.id!, - existingItem.id, - i.amount, - context); - var p = - ChangeListItemResult.fromJson((answer).body); + var answer = await ShoppingListSync.changeProductAmount( + currentList.id!, existingItem.id, i.amount, context); + var p = ChangeListItemResult.fromJson((answer).body); existingItem.amount = p.amount; existingItem.changed = p.changed; } else { var p = AddListItemResult.fromJson( - (await ShoppingListSync.addProduct(listId, - i.name, null, i.amount, context)) - .body); + (await ShoppingListSync.addProduct(listId, i.name, null, i.amount, context)).body); var newItem = ShoppingItem(p.name) ..amount = i.amount ..id = p.productId; @@ -194,7 +175,7 @@ class _BoughtItemsPagePageState extends State currentList.addSingleItem(newItem); } showInSnackBar( - "${i.amount}x ${i.name}${NSSLStrings.of(context)?.newProductAddedToList()}${currentList.name}"); + "${i.amount}x ${i.name}${NSSLStrings.of(context).newProductAddedToList()}${currentList.name}"); }, ), ) diff --git a/lib/pages/change_password.dart b/lib/pages/change_password.dart index fa0bddf..89c375e 100644 --- a/lib/pages/change_password.dart +++ b/lib/pages/change_password.dart @@ -21,8 +21,7 @@ class ChangePasswordPageState extends State { var newPw2Input = ForInput(); void showInSnackBar(String value) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(value), duration: Duration(seconds: 3))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(value), duration: Duration(seconds: 3))); } void _handleSubmitted() { @@ -52,8 +51,7 @@ class ChangePasswordPageState extends State { } setState(() => {}); if (error == true) return; - if (newPwInput.textEditingController.text != - newPw2Input.textEditingController.text) { + if (newPwInput.textEditingController.text != newPw2Input.textEditingController.text) { newPw2Input.decoration = InputDecoration( labelText: newPw2Input.decoration!.labelText, helperText: newPw2Input.decoration!.helperText, @@ -68,19 +66,15 @@ class ChangePasswordPageState extends State { _changePassword() async { var res = await UserSync.changePassword( - oldPwInput.textEditingController.text, - newPwInput.textEditingController.text, - User.token, - context); + oldPwInput.textEditingController.text, newPwInput.textEditingController.text, User.token, context); if (res.statusCode != 200) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(res.reasonPhrase!), duration: Duration(seconds: 3))); + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(res.reasonPhrase!), duration: Duration(seconds: 3))); return; } var obj = Result.fromJson(res.body); if (!obj.success!) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(obj.error!), duration: Duration(seconds: 3))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(obj.error!), duration: Duration(seconds: 3))); return; } var dialog = AlertDialog( @@ -91,23 +85,18 @@ class ChangePasswordPageState extends State { ), ), actions: [ - TextButton( - child: const Text("OK"), - onPressed: () => Navigator.popUntil(context, (r) => r.isFirst)), + TextButton(child: const Text("OK"), onPressed: () => Navigator.popUntil(context, (r) => r.isFirst)), ]); showDialog(context: context, builder: (BuildContext context) => dialog); } _resetInput() { oldPwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context).oldPasswordHint(), - labelText: NSSLStrings.of(context).oldPassword()); + helperText: NSSLStrings.of(context).oldPasswordHint(), labelText: NSSLStrings.of(context).oldPassword()); newPwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context).newPasswordHint(), - labelText: NSSLStrings.of(context).newPassword()); + helperText: NSSLStrings.of(context).newPasswordHint(), labelText: NSSLStrings.of(context).newPassword()); newPw2Input.decoration = InputDecoration( - helperText: NSSLStrings.of(context).new2PasswordHint(), - labelText: NSSLStrings.of(context).new2Password()); + helperText: NSSLStrings.of(context).new2PasswordHint(), labelText: NSSLStrings.of(context).new2Password()); } @override @@ -121,7 +110,7 @@ class ChangePasswordPageState extends State { return Scaffold( key: _scaffoldKey, resizeToAvoidBottomInset: false, - appBar: AppBar(title: Text(NSSLStrings.of(context)!.changePasswordPD())), + appBar: AppBar(title: Text(NSSLStrings.of(context).changePasswordPD())), body: Container( padding: const EdgeInsets.symmetric(horizontal: 32.0), child: Column(mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -167,7 +156,7 @@ class ChangePasswordPageState extends State { child: ElevatedButton( // child: Center( child: Text( - NSSLStrings.of(context)!.changePasswordButton(), + NSSLStrings.of(context).changePasswordButton(), ), // ), onPressed: _handleSubmitted, diff --git a/lib/pages/contributors.dart b/lib/pages/contributors.dart index 92dea2c..a8797ef 100644 --- a/lib/pages/contributors.dart +++ b/lib/pages/contributors.dart @@ -10,8 +10,7 @@ class ContributorsPage extends StatefulWidget { final String? title; final int listId; @override - _ContributorsPagePageState createState() => - new _ContributorsPagePageState(listId); + _ContributorsPagePageState createState() => new _ContributorsPagePageState(listId); } class _ContributorsPagePageState extends State { @@ -37,9 +36,7 @@ class _ContributorsPagePageState extends State { } GetContributorsResult z = GetContributorsResult.fromJson(o.body); if (!z.success! || z.contributors.length <= 0) - showInSnackBar( - NSSLStrings.of(context)!.genericErrorMessageSnackbar() + - o.reasonPhrase!, + showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + o.reasonPhrase!, duration: Duration(seconds: 10)); else setState(() => conList.addAll(z.contributors)); @@ -54,9 +51,7 @@ class _ContributorsPagePageState extends State { title: Form( child: TextField( key: _iff, - decoration: InputDecoration( - hintText: NSSLStrings.of(context)! - .nameOfNewContributorHint()), + decoration: InputDecoration(hintText: NSSLStrings.of(context).nameOfNewContributorHint()), onSubmitted: (x) => _addContributor(x), autofocus: true, controller: tec))), @@ -75,9 +70,7 @@ class _ContributorsPagePageState extends State { var o = await ShoppingListSync.addContributor(listId, value, context); AddContributorResult z = AddContributorResult.fromJson(o.body); if (!z.success!) - showInSnackBar( - NSSLStrings.of(context)!.genericErrorMessageSnackbar() + z.error!, - duration: Duration(seconds: 10)); + showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + z.error!, duration: Duration(seconds: 10)); else setState(() => conList.add(ContributorResult() ..name = z.name @@ -88,25 +81,19 @@ class _ContributorsPagePageState extends State { Widget buildBody() { bool? isAdmin = false; if (conList.length > 0) { - isAdmin = conList - .firstWhere( - (x) => x.name!.toLowerCase() == User.username!.toLowerCase()) - .isAdmin; + isAdmin = conList.firstWhere((x) => x.name!.toLowerCase() == User.username!.toLowerCase()).isAdmin; var listView = ListView.builder( itemBuilder: (c, i) { return ListTile( title: Text(conList[i].name! + (conList[i].isAdmin! - ? NSSLStrings.of(context)!.contributorAdmin() - : NSSLStrings.of(context)!.contributorUser())), - trailing: isAdmin! && - conList[i].name!.toLowerCase() != - User.username!.toLowerCase() + ? NSSLStrings.of(context).contributorAdmin() + : NSSLStrings.of(context).contributorUser())), + trailing: isAdmin! && conList[i].name!.toLowerCase() != User.username!.toLowerCase() ? PopupMenuButton( padding: EdgeInsets.zero, onSelected: popupMenuClicked, - itemBuilder: (BuildContext context) => - >[ + itemBuilder: (BuildContext context) => >[ PopupMenuItem( value: conList[i].userId.toString() + "\u{1E}ChangeRight", //x.id.toString() + "\u{1E}" + 'Rename', @@ -115,18 +102,14 @@ class _ContributorsPagePageState extends State { ? const Icon(Icons.arrow_downward) : const Icon(Icons.arrow_upward)), title: (conList[i].isAdmin! - ? Text(NSSLStrings.of(context)! - .demoteMenu()) - : Text(NSSLStrings.of(context)! - .promoteMenu())))), + ? Text(NSSLStrings.of(context).demoteMenu()) + : Text(NSSLStrings.of(context).promoteMenu())))), const PopupMenuDivider(), // ignore: list_element_type_not_assignable PopupMenuItem( value: conList[i].userId.toString() + "\u{1E}Remove", //x.id.toString() + "\u{1E}" + 'Remove', child: ListTile( - leading: const Icon(Icons.delete), - title: Text( - NSSLStrings.of(context)!.remove()))) + leading: const Icon(Icons.delete), title: Text(NSSLStrings.of(context).remove()))) ]) : const Text(""), onTap: () => {}); @@ -138,21 +121,17 @@ class _ContributorsPagePageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Container( - child: SizedBox( - width: 40.0, height: 40.0, child: CircularProgressIndicator()), + child: SizedBox(width: 40.0, height: 40.0, child: CircularProgressIndicator()), padding: const EdgeInsets.only(top: 16.0), ) ], ); } - void showInSnackBar(String value, - {Duration? duration, SnackBarAction? action}) { + void showInSnackBar(String value, {Duration? duration, SnackBarAction? action}) { ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(value), - duration: duration ?? Duration(seconds: 3), - action: action)); + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(value), duration: duration ?? Duration(seconds: 3), action: action)); } Future popupMenuClicked(String value) async { @@ -161,14 +140,12 @@ class _ContributorsPagePageState extends State { switch (command) { case "Remove": var userId = int.parse(splitted[0]); - var res = - await ShoppingListSync.deleteContributor(listId, userId, context); + var res = await ShoppingListSync.deleteContributor(listId, userId, context); var enres = Result.fromJson(res.body); if (!enres.success!) showInSnackBar(enres.error!); else { - showInSnackBar(conList.firstWhere((x) => x.userId == userId).name! + - " was removed successfully"); + showInSnackBar(conList.firstWhere((x) => x.userId == userId).name! + " was removed successfully"); setState(() => conList.removeWhere((x) => x.userId == userId)); } break; @@ -186,9 +163,7 @@ class _ContributorsPagePageState extends State { } GetContributorsResult z = GetContributorsResult.fromJson(o.body); if (!z.success! || z.contributors.length <= 0) - showInSnackBar( - NSSLStrings.of(context)!.genericErrorMessageSnackbar() + - z.error!, + showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + z.error!, duration: Duration(seconds: 10)); else conList.clear(); diff --git a/lib/pages/forgot_password.dart b/lib/pages/forgot_password.dart index 1b9e55d..6611246 100644 --- a/lib/pages/forgot_password.dart +++ b/lib/pages/forgot_password.dart @@ -35,8 +35,7 @@ class ForgotPasswordPageState extends State { var validateMode = AutovalidateMode.disabled; void showInSnackBar(String value) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(value), duration: Duration(seconds: 3))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(value), duration: Duration(seconds: 3))); } Future _handleSubmitted() async { @@ -51,31 +50,27 @@ class ForgotPasswordPageState extends State { if (emailInput.textEditingController.text.length > 0 && _validateEmail(emailInput.textEditingController.text) == null) { var res = await UserSync.resetPassword(email, context); - if (!HelperMethods.reactToRespone(res, context, - scaffoldState: _scaffoldKey.currentState)) return; + if (!HelperMethods.reactToRespone(res, context, scaffoldState: _scaffoldKey.currentState)) return; await showDialog( context: context, - builder: (BuildContext context) => AlertDialog( - content: Text( - NSSLStrings.of(context)!.requestPasswordResetSuccess()), - actions: [ - TextButton( - child: Text(NSSLStrings.of(context)!.okayButton()), - onPressed: () { - Navigator.of(context).pop(true); - }) - ])); + builder: (BuildContext context) => + AlertDialog(content: Text(NSSLStrings.of(context).requestPasswordResetSuccess()), actions: [ + TextButton( + child: Text(NSSLStrings.of(context).okayButton()), + onPressed: () { + Navigator.of(context).pop(true); + }) + ])); Navigator.pop(context); } } String? _validateEmail(String? value) { if (value == null) return value; - if (value.isEmpty) return NSSLStrings.of(context)!.emailRequiredError(); + if (value.isEmpty) return NSSLStrings.of(context).emailRequiredError(); RegExp email = RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); - if (!email.hasMatch(value)) - return NSSLStrings.of(context)!.emailIncorrectFormatError(); + if (!email.hasMatch(value)) return NSSLStrings.of(context).emailIncorrectFormatError(); return null; } @@ -89,39 +84,34 @@ class ForgotPasswordPageState extends State { return Scaffold( key: _scaffoldKey, resizeToAvoidBottomInset: true, - appBar: AppBar( - title: Text(NSSLStrings.of(context)!.requestPasswordResetTitle())), + appBar: AppBar(title: Text(NSSLStrings.of(context).requestPasswordResetTitle())), body: Form( key: _formKey, autovalidateMode: validateMode, - child: ListView( - padding: const EdgeInsets.symmetric(horizontal: 32.0), - children: [ - ListTile( - title: TextFormField( - key: emailInput.key, - decoration: emailInput.decoration, - controller: emailInput.textEditingController, - keyboardType: TextInputType.emailAddress, - autofillHints: [AutofillHints.username, AutofillHints.email], - autocorrect: false, - autofocus: true, - validator: _validateEmail, - onSaved: (s) => _handleSubmitted(), + child: ListView(padding: const EdgeInsets.symmetric(horizontal: 32.0), children: [ + ListTile( + title: TextFormField( + key: emailInput.key, + decoration: emailInput.decoration, + controller: emailInput.textEditingController, + keyboardType: TextInputType.emailAddress, + autofillHints: [AutofillHints.username, AutofillHints.email], + autocorrect: false, + autofocus: true, + validator: _validateEmail, + onSaved: (s) => _handleSubmitted(), + ), + ), + ListTile( + title: Container( + child: ElevatedButton( + key: submit.key, + child: Center(child: Text(NSSLStrings.of(context).requestPasswordResetButton())), + onPressed: _handleSubmitted, ), - ), - ListTile( - title: Container( - child: ElevatedButton( - key: submit.key, - child: Center( - child: Text(NSSLStrings.of(context)! - .requestPasswordResetButton())), - onPressed: _handleSubmitted, - ), - padding: const EdgeInsets.only(top: 16.0)), - ), - ]), + padding: const EdgeInsets.only(top: 16.0)), + ), + ]), ), ); } diff --git a/lib/pages/login.dart b/lib/pages/login.dart index ffa7761..8462dd7 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -40,8 +40,7 @@ class LoginPageState extends State { var validateMode = AutovalidateMode.disabled; void showInSnackBar(String value) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(value), duration: Duration(seconds: 3))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(value), duration: Duration(seconds: 3))); } Future _handleSubmitted() async { @@ -76,15 +75,13 @@ class LoginPageState extends State { if (_validateEmail(nameInput.textEditingController.text) != null) { var res = await UserSync.login(name, password, context); - if (!HelperMethods.reactToRespone(res, context, - scaffoldState: _scaffoldKey.currentState)) + if (!HelperMethods.reactToRespone(res, context, scaffoldState: _scaffoldKey.currentState)) return; else _handleLoggedIn(LoginResult.fromJson(res.body)); } else { var res = await UserSync.loginEmail(name, password, context); - if (!HelperMethods.reactToRespone(res, context, - scaffoldState: _scaffoldKey.currentState)) + if (!HelperMethods.reactToRespone(res, context, scaffoldState: _scaffoldKey.currentState)) return; else _handleLoggedIn(LoginResult.fromJson(res.body)); @@ -122,10 +119,8 @@ class LoginPageState extends State { } String? _validateName(String? value) { - if (value!.isEmpty) - return NSSLStrings.of(context)!.nameEmailRequiredError(); - if (value.length < 4) - return NSSLStrings.of(context)!.usernameToShortError(); + if (value!.isEmpty) return NSSLStrings.of(context).nameEmailRequiredError(); + if (value.length < 4) return NSSLStrings.of(context).usernameToShortError(); return null; } @@ -134,25 +129,22 @@ class LoginPageState extends State { if (value.isEmpty) return NSSLStrings.of(context).emailRequiredError(); RegExp email = RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); - if (!email.hasMatch(value)) - return NSSLStrings.of(context)!.emailIncorrectFormatError(); + if (!email.hasMatch(value)) return NSSLStrings.of(context).emailIncorrectFormatError(); return null; } String? _validatePassword(String? value) { - if (pwInput.textEditingController.text.isEmpty) - return NSSLStrings.of(context)!.passwordEmptyError(); + if (pwInput.textEditingController.text.isEmpty) return NSSLStrings.of(context).passwordEmptyError(); return null; } _resetInput() { nameInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.usernameOrEmailForLoginHint(), - labelText: NSSLStrings.of(context)!.usernameOrEmailTitle()); + helperText: NSSLStrings.of(context).usernameOrEmailForLoginHint(), + labelText: NSSLStrings.of(context).usernameOrEmailTitle()); pwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context)!.choosenPasswordHint(), - labelText: NSSLStrings.of(context)!.password()); + helperText: NSSLStrings.of(context).choosenPasswordHint(), labelText: NSSLStrings.of(context).password()); } @override @@ -183,10 +175,7 @@ class LoginPageState extends State { //onChanged: (input) => nameInput.errorText = _validateName(input), controller: nameInput.textEditingController, keyboardType: TextInputType.emailAddress, - autofillHints: [ - AutofillHints.username, - AutofillHints.email - ], + autofillHints: [AutofillHints.username, AutofillHints.email], autocorrect: false, autofocus: true, validator: _validateName, @@ -210,8 +199,7 @@ class LoginPageState extends State { title: Container( child: ElevatedButton( key: submit.key, - child: Center( - child: Text(NSSLStrings.of(context)!.loginButton())), + child: Center(child: Text(NSSLStrings.of(context).loginButton())), onPressed: _handleSubmitted, ), padding: const EdgeInsets.only(top: 16.0)), @@ -235,8 +223,7 @@ class LoginPageState extends State { onPressed: () { Navigator.pushNamed(context, "/forgot_password"); }, - child: - Text(NSSLStrings.of(context)?.forgotPassword() ?? ""), + child: Text(NSSLStrings.of(context).forgotPassword()), ), ), ), diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index d05aad2..8961b63 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -539,7 +539,7 @@ class MainPageState extends State with TickerProviderStateMixin, Widge User.token = null; runApp(NSSL()); } - + Future drawerListItemMenuClicked(String value) async { var splitted = value.split('\u{1E}'); int id = int.parse(splitted[0]); @@ -575,11 +575,11 @@ class MainPageState extends State with TickerProviderStateMixin, Widge if (!(res.success ?? false)) showInDrawerSnackBar(res.error!); else { - showInDrawerSnackBar(deleteList.name! + " " + NSSLStrings.of(context).removed()); if (User.currentList!.id! == id) { changeCurrentList(User.shoppingLists.indexOf(User.shoppingLists.firstWhere((l) => l.id != id))); } setState(() => User.shoppingLists.removeWhere((x) => x.id == id)); + showInDrawerSnackBar(deleteList.name! + " " + NSSLStrings.of(cont!).removed()); } }, context: context)); diff --git a/lib/pages/product_add_to_database.dart b/lib/pages/product_add_to_database.dart index 1b8b3ae..6de38f0 100644 --- a/lib/pages/product_add_to_database.dart +++ b/lib/pages/product_add_to_database.dart @@ -44,22 +44,20 @@ class AddProductToDatabaseState extends State { if (!_saveNeeded) return true; final ThemeData theme = Theme.of(context); - final TextStyle dialogTextStyle = theme.textTheme.subtitle1! - .copyWith(color: theme.textTheme.caption!.color); + final TextStyle dialogTextStyle = theme.textTheme.subtitle1!.copyWith(color: theme.textTheme.caption!.color); return await (showDialog( context: context, builder: (BuildContext context) => AlertDialog( - content: Text(NSSLStrings.of(context)!.discardNewProduct(), - style: dialogTextStyle), + content: Text(NSSLStrings.of(context).discardNewProduct(), style: dialogTextStyle), actions: [ TextButton( - child: Text(NSSLStrings.of(context)!.cancelButton()), + child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () { Navigator.of(context).pop(false); }), TextButton( - child: Text(NSSLStrings.of(context)!.discardButton()), + child: Text(NSSLStrings.of(context).discardButton()), onPressed: () { Navigator.of(context).pop(true); }) @@ -78,8 +76,7 @@ class AddProductToDatabaseState extends State { } final FormState form = _formKey.currentState!; if (!form.validate()) { - showInSnackBar( - NSSLStrings.of(context)!.fixErrorsBeforeSubmittingPrompt()); + showInSnackBar(NSSLStrings.of(context).fixErrorsBeforeSubmittingPrompt()); validateMode = AutovalidateMode.onUserInteraction; return false; } else { @@ -96,8 +93,7 @@ class AddProductToDatabaseState extends State { unit = weight!.substring(match!.start, match.end); } _isSendToServer = true; - var first = (await ProductSync.addNewProduct( - "$productName $brandName", gtin, realWeight, unit, context)); + var first = (await ProductSync.addNewProduct("$productName $brandName", gtin, realWeight, unit, context)); if (first.statusCode != 200) { showInSnackBar(first.reasonPhrase!); _isSendToServer = false; @@ -111,9 +107,7 @@ class AddProductToDatabaseState extends State { if (putInList) { var list = User.currentList!; var pres = AddListItemResult.fromJson( - (await ShoppingListSync.addProduct(list.id, - "$productName $brandName $weight", gtin, 1, context)) - .body); + (await ShoppingListSync.addProduct(list.id, "$productName $brandName $weight", gtin, 1, context)).body); if (!pres.success!) showInSnackBar(pres.error!); else { @@ -138,21 +132,17 @@ class AddProductToDatabaseState extends State { return Scaffold( key: _scaffoldKey, - appBar: AppBar( - title: Text(NSSLStrings.of(context).newProductTitle()), - actions: [ - TextButton( - child: Text(NSSLStrings.of(context)!.saveButton(), - style: theme.textTheme.bodyText2! - .copyWith(color: Colors.white)), - onPressed: () => _handleSubmitted()) - ]), + appBar: AppBar(title: Text(NSSLStrings.of(context).newProductTitle()), actions: [ + TextButton( + child: Text(NSSLStrings.of(context).saveButton(), + style: theme.textTheme.bodyText2!.copyWith(color: Colors.white)), + onPressed: () => _handleSubmitted()) + ]), body: Form( key: _formKey, onWillPop: _onWillPop, autovalidateMode: validateMode, - child: - ListView(padding: const EdgeInsets.all(16.0), children: [ + child: ListView(padding: const EdgeInsets.all(16.0), children: [ Container( child: TextFormField( decoration: InputDecoration( @@ -166,10 +156,8 @@ class AddProductToDatabaseState extends State { Container( child: TextFormField( decoration: InputDecoration( - labelText: - NSSLStrings.of(context).newProductBrandName(), - hintText: - NSSLStrings.of(context).newProductBrandNameHint()), + labelText: NSSLStrings.of(context).newProductBrandName(), + hintText: NSSLStrings.of(context).newProductBrandNameHint()), autofocus: false, controller: tecBrandName, onSaved: (s) => brandName = s, @@ -178,16 +166,13 @@ class AddProductToDatabaseState extends State { child: TextFormField( decoration: InputDecoration( labelText: NSSLStrings.of(context).newProductWeight(), - hintText: - NSSLStrings.of(context).newProductWeightHint()), + hintText: NSSLStrings.of(context).newProductWeightHint()), autofocus: false, onSaved: (s) => weight = s, controller: tecPackagingSize)), Container( padding: const EdgeInsets.symmetric(vertical: 8.0), - decoration: BoxDecoration( - border: - Border(bottom: BorderSide(color: theme.dividerColor))), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: theme.dividerColor))), alignment: FractionalOffset.bottomLeft, child: Text(NSSLStrings.of(context).codeText() + gtin!)), Container( @@ -195,14 +180,12 @@ class AddProductToDatabaseState extends State { alignment: FractionalOffset.bottomLeft, child: Row(children: [ Text(NSSLStrings.of(context).newProductAddToList()), - Checkbox( - value: putInList, - onChanged: (b) => setState(() => putInList = !putInList)) + Checkbox(value: putInList, onChanged: (b) => setState(() => putInList = !putInList)) ])), Container( padding: const EdgeInsets.symmetric(vertical: 8.0), - child: Text(NSSLStrings.of(context)!.newProductStarExplanation(), - style: Theme.of(context).textTheme.caption), + child: + Text(NSSLStrings.of(context).newProductStarExplanation(), style: Theme.of(context).textTheme.caption), ), ])), ); @@ -211,8 +194,7 @@ class AddProductToDatabaseState extends State { String? _validateName(String? value) { _saveNeeded = true; if (value!.isEmpty) return NSSLStrings.of(context).fieldRequiredError(); - if (value.length < 3) - return NSSLStrings.of(context).newProductNameToShort(); + if (value.length < 3) return NSSLStrings.of(context).newProductNameToShort(); return null; } diff --git a/lib/pages/shopping_item_search.dart b/lib/pages/shopping_item_search.dart index 6607a25..24e8df4 100644 --- a/lib/pages/shopping_item_search.dart +++ b/lib/pages/shopping_item_search.dart @@ -40,21 +40,18 @@ class _ProductAddPageState extends State { if (list != null) { if (list.shoppingItems == null) list.shoppingItems = []; - var item = list.shoppingItems! - .firstWhere((x) => x!.name == name, orElse: () => null); + var item = list.shoppingItems!.firstWhere((x) => x!.name == name, orElse: () => null); ShoppingItem? afterAdd; if (item != null) { - var answer = await ShoppingListSync.changeProductAmount( - list.id!, item.id!, 1, context); + var answer = await ShoppingListSync.changeProductAmount(list.id!, item.id!, 1, context); var p = ChangeListItemResult.fromJson((answer).body); setState(() { item.amount = p.amount; item.changed = p.changed; }); } else { - var p = AddListItemResult.fromJson((await ShoppingListSync.addProduct( - list.id!, name!, gtin ?? '-', 1, context)) - .body); + var p = AddListItemResult.fromJson( + (await ShoppingListSync.addProduct(list.id!, name!, gtin ?? '-', 1, context)).body); afterAdd = ShoppingItem(p.name) ..amount = 1 ..id = p.productId; @@ -70,10 +67,8 @@ class _ProductAddPageState extends State { label: NSSLStrings.of(context).undo(), onPressed: () async { var res = item == null - ? await ShoppingListSync.deleteProduct( - list.id!, afterAdd!.id!, context) - : await ShoppingListSync.changeProductAmount( - list.id!, item.id!, -1, context); + ? await ShoppingListSync.deleteProduct(list.id!, afterAdd!.id!, context) + : await ShoppingListSync.changeProductAmount(list.id!, item.id!, -1, context); if (Result.fromJson(res.body).success!) { if (item == null) list.shoppingItems!.remove(afterAdd); @@ -98,8 +93,7 @@ class _ProductAddPageState extends State { title: Form( child: TextField( key: _iff, - decoration: InputDecoration( - hintText: NSSLStrings.of(context)!.searchProductHint()), + decoration: InputDecoration(hintText: NSSLStrings.of(context).searchProductHint()), onSubmitted: (x) => _searchProducts(x, 1), autofocus: true, controller: tec, @@ -132,8 +126,7 @@ class _ProductAddPageState extends State { List? z = jsonDecode(o.body); // .decode(o.body); if (!noMoreProducts && z!.length <= 0) { noMoreProducts = true; - showInSnackBar(NSSLStrings.of(context)!.noMoreProductsMessage(), - duration: Duration(seconds: 3)); + showInSnackBar(NSSLStrings.of(context).noMoreProductsMessage(), duration: Duration(seconds: 3)); } else setState(() => prList.addAll(z! .map((f) => ProductResult() @@ -152,8 +145,7 @@ class _ProductAddPageState extends State { lastLength = prList.length; } return ListTile( - title: Text(prList[i].name!), - onTap: () => _addProductToList(prList[i].name, prList[i].gtin)); + title: Text(prList[i].name!), onTap: () => _addProductToList(prList[i].name, prList[i].gtin)); }, itemCount: prList.length); return listView; @@ -161,12 +153,9 @@ class _ProductAddPageState extends State { return Text(""); } - void showInSnackBar(String value, - {Duration? duration, SnackBarAction? action}) { + void showInSnackBar(String value, {Duration? duration, SnackBarAction? action}) { ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(value), - duration: duration ?? Duration(seconds: 3), - action: action)); + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(value), duration: duration ?? Duration(seconds: 3), action: action)); } } From b24e47b807e8b19c764e56c7dd9c353340683188 Mon Sep 17 00:00:00 2001 From: susch19 Date: Sun, 13 Feb 2022 13:26:40 +0100 Subject: [PATCH 06/23] Started very early migration to riverpod state management --- lib/main.dart | 19 +-- lib/manager/database_manager.dart | 30 ++-- lib/manager/startup_manager.dart | 37 ----- lib/pages/login.dart | 19 +-- lib/pages/main_page.dart | 237 ++++++++++++++++-------------- lib/pages/registration.dart | 120 ++++----------- pubspec.yaml | 6 + 7 files changed, 189 insertions(+), 279 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 3ab82aa..cc5a28d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -15,6 +15,8 @@ import 'dart:async'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; class CustomScrollBehavior extends MaterialScrollBehavior { @override @@ -40,7 +42,9 @@ Future main() async { runApp(FutureBuilder( builder: (c, t) { if (t.connectionState == ConnectionState.done) - return NSSLPage(); + return ProviderScope( + child: NSSLPage(), + ); else return MaterialApp( builder: (context, child) { @@ -69,13 +73,8 @@ class NSSL extends StatelessWidget { class NSSLPage extends StatefulWidget { NSSLPage({Key? key}) : super(key: key); - static _NSSLState? state; @override - _NSSLState createState() { - var localState = new _NSSLState(); - state = localState; - return localState; - } + _NSSLState createState() => _NSSLState(); } class _NSSLState extends State { @@ -98,12 +97,6 @@ class _NSSLState extends State { FirebaseMessaging.onMessage.listen((event) { CloudMessaging.onMessage(event, setState); }); - // FirebaseMessaging.onBackgroundMessage((message) async { - // return; - // }); - // FirebaseMessaging.onBackgroundMessage((message) => CloudMessaging.onMessage(message, setState)); - // firebaseMessaging.configure( - // onMessage: (x) => CloudMessaging.onMessage(x, setState), onLaunch: (x) => Startup.initialize()); for (var list in User.shoppingLists) if (list.messagingEnabled) list.subscribeForFirebaseMessaging(); } diff --git a/lib/manager/database_manager.dart b/lib/manager/database_manager.dart index a0bcfed..c594c0d 100644 --- a/lib/manager/database_manager.dart +++ b/lib/manager/database_manager.dart @@ -1,5 +1,5 @@ import 'dart:async'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/widgets.dart'; import 'package:path_provider/path_provider.dart'; import 'package:nssl/models/model_export.dart'; @@ -15,18 +15,22 @@ class DatabaseManager { static Future initialize() async { WidgetsFlutterBinding.ensureInitialized(); sqfliteFfiInit(); - - var dbPath = path.join((await getApplicationDocumentsDirectory()).path, "db.db"); - print(dbPath); - database = await databaseFactoryFfi.openDatabase(dbPath, options: OpenDatabaseOptions(version: _version, onCreate: (Database db, int version) async { - await db - .execute("CREATE TABLE ShoppingItems (id INTEGER PRIMARY KEY, name TEXT, amount INTEGER, crossed INTEGER, res_list_id INTEGER, sortorder INTEGER)"); - await db.execute("CREATE TABLE ShoppingLists (id INTEGER PRIMARY KEY, name TEXT, messaging INTEGER, user_id INTEGER)"); - await db.execute( - "CREATE TABLE User (own_id INTEGER, username TEXT, email TEXT, token TEXT, current_list_index INTEGER)"); //TODO for multiple users any indicator of last user - await db.execute( - "CREATE TABLE Themes (id INTEGER PRIMARY KEY, primary_color INTEGER, accent_color INTEGER, brightness TEXT, accent_color_brightness TEXT, user_id INTEGER)"); - }, onUpgrade: _upgradeDatabase)); + + var dbPath = path.join((await getApplicationDocumentsDirectory()).path, "db.db"); + database = await databaseFactoryFfi.openDatabase(dbPath, + options: OpenDatabaseOptions( + version: _version, + onCreate: (Database db, int version) async { + await db.execute( + "CREATE TABLE ShoppingItems (id INTEGER PRIMARY KEY, name TEXT, amount INTEGER, crossed INTEGER, res_list_id INTEGER, sortorder INTEGER)"); + await db.execute( + "CREATE TABLE ShoppingLists (id INTEGER PRIMARY KEY, name TEXT, messaging INTEGER, user_id INTEGER)"); + await db.execute( + "CREATE TABLE User (own_id INTEGER, username TEXT, email TEXT, token TEXT, current_list_index INTEGER)"); //TODO for multiple users any indicator of last user + await db.execute( + "CREATE TABLE Themes (id INTEGER PRIMARY KEY, primary_color INTEGER, accent_color INTEGER, brightness TEXT, accent_color_brightness TEXT, user_id INTEGER)"); + }, + onUpgrade: _upgradeDatabase)); } static Future _upgradeDatabase(Database db, int oldVersion, int newVersion) async { diff --git a/lib/manager/startup_manager.dart b/lib/manager/startup_manager.dart index fd5ef6e..7ee3eb2 100644 --- a/lib/manager/startup_manager.dart +++ b/lib/manager/startup_manager.dart @@ -55,12 +55,10 @@ class Startup { } static Future initialize() async { - // var t = SharedPreferences.getInstance(); WidgetsFlutterBinding.ensureInitialized(); var f1 = initializeMinFunction(); await DatabaseManager.initialize(); await User.load(); - // sharedPreferences = await t; if (User.username == null || User.username == "" || User.eMail == null || User.eMail == "") return false; await Themes.loadTheme(); @@ -71,41 +69,6 @@ class Startup { User.shoppingLists.firstWhere((x) => x.id == User.currentListIndex, orElse: () => User.shoppingLists.first); await f1; return true; - - // FileManager.createFolder("ShoppingListsCo"); - // FileManager.createFile("token.txt"); - // FileManager.createFile("User.txt"); - // FileManager.createFile("listList.txt"); - - // User.token = await FileManager.readAsString("token.txt"); - - // var userData = await FileManager.readAsLines("User.txt"); - // if(userData.where((s)=> s.isNotEmpty).length == 2) { - // User.username = userData[0]; - // User.eMail = userData[1]; - // } - // else { - // User.username = null; - // User.eMail = null; - // } - // for (var list in dir.listSync()) - // if (list != null) - // User.shoppingLists.add(await ShoppingList - // .load(int.parse(list.path.split('/').last.split('.')[0]))); - - // await Themes.loadTheme(); - - // if (User.shoppingLists.length > 0) { - // var listId = int.parse(await FileManager.readAsString("lastList.txt")); - // User.currentList = User.shoppingLists.firstWhere((x) => x.id == listId); - // } else { - // User.currentList = ShoppingList() - // ..name = "No List yet" - // ..id = 1 - // ..shoppingItems = []; - // } - // User.currentListIndex = User.currentList.id; - // await User.save(); } static Future initializeNewListsFromServer() async { diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 8462dd7..fe8f5ad 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -51,24 +51,6 @@ class LoginPageState extends State { validateMode = AutovalidateMode.onUserInteraction; return; } - //form.save(); - /* var validate = _validateName(nameInput.textEditingController.text); - if (validate != null) { - nameInput.decoration = InputDecoration( - labelText: nameInput.decoration.labelText, - helperText: nameInput.decoration.helperText, - errorText: validate); - error = true; - } - if (_validatePassword(pwInput.textEditingController.text) != null) { - pwInput.decoration = InputDecoration( - labelText: pwInput.decoration.labelText, - helperText: pwInput.decoration.helperText, - errorText: _validatePassword(pwInput.textEditingController.text)); - error = true; - } - setState(() => {});*/ -// if (error == true) return; String name = nameInput.textEditingController.text; String password = pwInput.textEditingController.text; @@ -129,6 +111,7 @@ class LoginPageState extends State { if (value.isEmpty) return NSSLStrings.of(context).emailRequiredError(); RegExp email = RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); + if (!email.hasMatch(value)) return NSSLStrings.of(context).emailIncorrectFormatError(); return null; } diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 8961b63..949108a 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -17,6 +17,7 @@ import 'package:nssl/firebase/cloud_messsaging.dart'; import '../main.dart'; import 'barcode_scanner_page.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; class MainPage extends StatefulWidget { @override @@ -80,7 +81,7 @@ class MainPageState extends State with TickerProviderStateMixin, Widge User.currentList?.name ?? NSSLStrings.of(context).noListLoaded(), ), actions: _getMainDropdownActions(context)), - body: buildBody(context), + body: ShoppingListWidget(this), floatingActionButton: isReorderingItems ? acceptReordingFAB() : null, drawer: _buildDrawer(context), persistentFooterButtons: isReorderingItems @@ -95,99 +96,6 @@ class MainPageState extends State with TickerProviderStateMixin, Widge [TextButton(child: Text(NSSLStrings.of(context).searchPB()), onPressed: search)]); } - Widget buildBody(BuildContext context) { - cont = context; - - if (User.currentList == null || User.currentList!.shoppingItems == null) return const Text(""); - if (User.currentList!.shoppingItems!.any((item) => item?.sortOrder == null)) updateOrderIndiciesAndSave(); - - User.currentList!.shoppingItems!.sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); - var lv; - if (User.currentList!.shoppingItems!.length > 0) { - var mainList = User.currentList!.shoppingItems!.map((x) { - if (x == null || x.name == null) return Text("Null"); - // return Text(x.name!); - - var lt = ListTile( - key: ValueKey(x), - title: Wrap( - children: [ - Text( - x.name ?? "", - maxLines: 2, - softWrap: true, - style: TextStyle( - decoration: x.crossedOut ? TextDecoration.lineThrough : TextDecoration.none, - decorationThickness: 4), - ), - ], - ), - leading: PopupMenuButton( - child: FittedBox( - child: Row(children: [ - Text(x.amount.toString() + "x"), - const Icon(Icons.expand_more, size: 16.0), - SizedBox(height: 38.0), //for larger clickable size (2 Lines) - ]), - ), - initialValue: x.amount.toString(), - onSelected: (y) => shoppingItemChange(x, int.parse(y) - x.amount), - itemBuilder: buildChangeMenuItems, - ), - trailing: isReorderingItems ? Icon(Icons.reorder) : null, - onTap: isReorderingItems ? null : (() => crossOutMainListItem(x)), - onLongPress: isReorderingItems ? null : (() => renameListItem(x)), - ); - - if (isReorderingItems) { - return lt; - } else { - return Dismissible( - key: ValueKey(x), - child: lt, - onDismissed: (DismissDirection d) => handleDismissMain(d, x), - direction: DismissDirection.startToEnd, - background: Container( - decoration: BoxDecoration(color: Theme.of(context).primaryColor), - child: ListTile( - leading: Icon(Icons.delete, - // color: Theme.of(context).accentIconTheme.color, - size: 36.0), - ), - ), - ); - } - }).toList(growable: true); - - if (isReorderingItems) { - lv = ReorderableListView(onReorder: _onReorderItems, scrollDirection: Axis.vertical, children: mainList); - } else { - lv = CustomScrollView( - controller: _mainController, - slivers: [ - SliverFixedExtentList( - delegate: SliverChildBuilderDelegate((BuildContext context, int index) { - return Container( - alignment: FractionalOffset.center, - child: mainList[index], - ); - }, childCount: mainList.length), - itemExtent: 50.0) - ], - physics: AlwaysScrollableScrollPhysics(), - ); - } - } else - lv = ListView( - physics: const AlwaysScrollableScrollPhysics(), - children: [ListTile(title: const Text(""))], - ); - return RefreshIndicator( - child: lv, - onRefresh: _handleMainListRefresh, - ); - } - void _onReorderItems(int oldIndex, int newIndex) { if (User.currentList == null) return; @@ -212,18 +120,18 @@ class MainPageState extends State with TickerProviderStateMixin, Widge void sortAndOrderCrossedOut() { final crossedOffset = 0xFFFFFFFF; - setState(() { - for (var crossedOut - in User.currentList?.shoppingItems?.where((x) => x!.crossedOut && x.sortOrder! < crossedOffset) ?? - []) { - crossedOut?.sortOrder = crossedOut.sortOrder! + crossedOffset; - } - for (var notCrossedOut - in User.currentList?.shoppingItems?.where((x) => !x!.crossedOut && x.sortOrder! > crossedOffset) ?? - []) { - notCrossedOut!.sortOrder = notCrossedOut.sortOrder! - crossedOffset; - } - }); + // setState(() { + for (var crossedOut + in User.currentList?.shoppingItems?.where((x) => x!.crossedOut && x.sortOrder! < crossedOffset) ?? + []) { + crossedOut?.sortOrder = crossedOut.sortOrder! + crossedOffset; + } + for (var notCrossedOut + in User.currentList?.shoppingItems?.where((x) => !x!.crossedOut && x.sortOrder! > crossedOffset) ?? + []) { + notCrossedOut!.sortOrder = notCrossedOut.sortOrder! - crossedOffset; + } + // }); } void updateOrderIndiciesAndSave({bool syncToServer = false}) async { @@ -282,8 +190,15 @@ class MainPageState extends State with TickerProviderStateMixin, Widge case "Login/Register": login(); break; - case "options": - Navigator.push(context, MaterialPageRoute(builder: (c) => SettingsPage(), fullscreenDialog: true)); + case "Options": + await Navigator.push( + cont!, + MaterialPageRoute( + builder: (BuildContext context) => CustomThemePage(), + fullscreenDialog: true, + )) + .whenComplete(() => AdaptiveTheme.of(context) + .setTheme(light: Themes.lightTheme.theme!, dark: Themes.darkTheme.theme, notify: true)); break; case "PerformanceOverlay": setState(() => performanceOverlay = !performanceOverlay); @@ -795,3 +710,109 @@ class MainPageState extends State with TickerProviderStateMixin, Widge ]; } } + +final _isReorderingProvider = StateProvider((final _) { + return false; +}); + +class ShoppingListWidget extends ConsumerWidget { + final MainPageState mainPageState; + const ShoppingListWidget(this.mainPageState, {Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + if (User.currentList == null || User.currentList!.shoppingItems == null) return const Text(""); + if (User.currentList!.shoppingItems!.any((item) => item?.sortOrder == null)) + mainPageState.updateOrderIndiciesAndSave(); + + User.currentList!.shoppingItems!.sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); + var lv; + if (User.currentList!.shoppingItems!.length > 0) { + final isReorderingItems = ref.watch(_isReorderingProvider); + var mainList = User.currentList!.shoppingItems!.map((x) { + return getListTileForShoppingItem(x, isReorderingItems, context); + }).toList(growable: true); + + if (isReorderingItems) { + lv = ReorderableListView( + onReorder: mainPageState._onReorderItems, scrollDirection: Axis.vertical, children: mainList); + } else { + lv = CustomScrollView( + controller: mainPageState._mainController, + slivers: [ + SliverFixedExtentList( + delegate: SliverChildBuilderDelegate((BuildContext context, int index) { + return Container( + alignment: FractionalOffset.center, + child: mainList[index], + ); + }, childCount: mainList.length), + itemExtent: 50.0) + ], + physics: AlwaysScrollableScrollPhysics(), + ); + } + } else + lv = ListView( + physics: const AlwaysScrollableScrollPhysics(), + children: [ListTile(title: const Text(""))], + ); + return RefreshIndicator( + child: lv, + onRefresh: mainPageState._handleMainListRefresh, + ); + } + + Widget getListTileForShoppingItem(ShoppingItem? x, bool isReorderingItems, BuildContext context) { + if (x == null || x.name == null) return Text("Null"); + // return Text(x.name!); + + var lt = ListTile( + key: ValueKey(x), + title: Wrap( + children: [ + Text( + x.name ?? "", + maxLines: 2, + softWrap: true, + style: TextStyle(decoration: x.crossedOut ? TextDecoration.lineThrough : TextDecoration.none), + ), + ], + ), + leading: PopupMenuButton( + child: FittedBox( + child: Row(children: [ + Text(x.amount.toString() + "x"), + const Icon(Icons.expand_more, size: 16.0), + SizedBox(height: 38.0), //for larger clickable size (2 Lines) + ]), + ), + initialValue: x.amount.toString(), + onSelected: (y) => mainPageState.shoppingItemChange(x, int.parse(y) - x.amount), + itemBuilder: mainPageState.buildChangeMenuItems, + ), + trailing: isReorderingItems ? Icon(Icons.reorder) : null, + onTap: isReorderingItems ? null : (() => mainPageState.crossOutMainListItem(x)), + onLongPress: isReorderingItems ? null : (() => mainPageState.renameListItem(x)), + ); + + if (isReorderingItems) { + return lt; + } else { + return Dismissible( + key: ValueKey(x), + child: lt, + onDismissed: (DismissDirection d) => mainPageState.handleDismissMain(d, x), + direction: DismissDirection.startToEnd, + background: Container( + decoration: BoxDecoration(color: Theme.of(context).primaryColor), + child: ListTile( + leading: Icon(Icons.delete, + // color: Theme.of(context).accentIconTheme.color, + size: 36.0), + ), + ), + ); + } + } +} diff --git a/lib/pages/registration.dart b/lib/pages/registration.dart index a1bd0f8..3f0313a 100644 --- a/lib/pages/registration.dart +++ b/lib/pages/registration.dart @@ -29,8 +29,7 @@ class RegistrationState extends State { var validateMode = AutovalidateMode.disabled; void showInSnackBar(String value) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(value), duration: Duration(seconds: 3))); + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(value), duration: Duration(seconds: 3))); } Future _handleSubmitted() async { @@ -40,59 +39,6 @@ class RegistrationState extends State { return; } - /*ool error = false; - _resetInput(); - - String ni = _validateName(nameInput.textEditingController.text); - String ei = _validateEmail(emailInput.textEditingController.text); - String pi = _validatePassword(pwInput.textEditingController.text); - String p2i = _validatePassword2(pw2Input.textEditingController.text); - - if (ni != null) { - nameInput.decoration = InputDecoration( - labelText: nameInput.decoration.labelText, - helperText: nameInput.decoration.helperText, - errorText: ni); - nameInput.errorText = nameInput.decoration.errorText; - error = true; - } - if (ei != null) { - emailInput.decoration = InputDecoration( - labelText: emailInput.decoration.labelText, - helperText: emailInput.decoration.helperText, - errorText: ei); - emailInput.errorText = emailInput.decoration.errorText; - error = true; - } - if (pi != null) { - pwInput.decoration = InputDecoration( - labelText: pwInput.decoration.labelText, - helperText: pwInput.decoration.helperText, - errorText: pi); - pwInput.errorText = pwInput.decoration.errorText; - error = true; - } - if (p2i != null) { - pw2Input.decoration = InputDecoration( - labelText: pw2Input.decoration.labelText, - helperText: pw2Input.decoration.helperText, - errorText: p2i); - pw2Input.errorText = pw2Input.decoration.errorText; - error = true; - } - if (pwInput.textEditingController.text != - pw2Input.textEditingController.text) { - pw2Input.decoration = InputDecoration( - labelText: pw2Input.decoration.labelText, - helperText: pw2Input.decoration.helperText, - errorText: NSSLStrings.of(context).passwordsDontMatchError()); - pw2Input.errorText = pw2Input.decoration.errorText; - error = true; - } - - setState(() => {}); - - if (error == true) return;*/ String name = nameInput.textEditingController.text; String email = emailInput.textEditingController.text; String password = pwInput.textEditingController.text; @@ -165,7 +111,7 @@ class RegistrationState extends State { title: Text(NSSLStrings.of(context).registrationTitle())), body: Form( key: _formKey, - autovalidateMode: validateMode, + autovalidateMode: validateMode, child: ListView( // physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.symmetric(horizontal: 32.0), @@ -177,9 +123,7 @@ class RegistrationState extends State { autocorrect: false, validator: _validateName, onSaved: (s) { - FocusScope - .of(context) - .requestFocus(emailInput.focusNode); + FocusScope.of(context).requestFocus(emailInput.focusNode); }), TextFormField( key: emailInput.key, @@ -192,37 +136,33 @@ class RegistrationState extends State { onSaved: (s) { FocusScope.of(context).requestFocus(pwInput.focusNode); }), - Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Flexible( - child: TextFormField( - key: pwInput.key, - decoration: pwInput.decoration, - controller: pwInput.textEditingController, - focusNode: pwInput.focusNode, - autocorrect: false, - obscureText: true, - validator: _validatePassword, - onSaved: (s) { - FocusScope - .of(context) - .requestFocus(pw2Input.focusNode); - })), - SizedBox(width: 16.0), - Flexible( - child: TextFormField( - key: pw2Input.key, - decoration: pw2Input.decoration, - controller: pw2Input.textEditingController, - focusNode: pw2Input.focusNode, - autocorrect: false, - obscureText: true, - validator: _validatePassword2, - onSaved: (s) { - _handleSubmitted(); - })), - ]), + Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Flexible( + child: TextFormField( + key: pwInput.key, + decoration: pwInput.decoration, + controller: pwInput.textEditingController, + focusNode: pwInput.focusNode, + autocorrect: false, + obscureText: true, + validator: _validatePassword, + onSaved: (s) { + FocusScope.of(context).requestFocus(pw2Input.focusNode); + })), + SizedBox(width: 16.0), + Flexible( + child: TextFormField( + key: pw2Input.key, + decoration: pw2Input.decoration, + controller: pw2Input.textEditingController, + focusNode: pw2Input.focusNode, + autocorrect: false, + obscureText: true, + validator: _validatePassword2, + onSaved: (s) { + _handleSubmitted(); + })), + ]), Row(children: [ Flexible( child: Container( diff --git a/pubspec.yaml b/pubspec.yaml index 8f6b04c..c63fc75 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,6 +37,12 @@ dependencies: #jaguar_jwt: "^1.1.5" url_launcher: +dev_dependencies: + build_runner: ^2.0.6 + flutter_riverpod: ^2.0.0-dev.0 + flutter_lints: ^1.0.4 + json_serializable: ^6.1.3 + #git: https://github.com/tekartik/sqflite.git # For information on the generic Dart part of this file, see the From ccdf0912d1bec5cd5a94ab887a7d899aa9d18c57 Mon Sep 17 00:00:00 2001 From: susch19 Date: Sun, 5 Jun 2022 22:14:34 +0200 Subject: [PATCH 07/23] Migrated mostly to riverpod * moved everything regarding shoppinglist and shoppingitems into provider logic * split shoppingitems from shoppinglist and only link then with the ids, so whenever a list is edited, not all items have to be reloaded and when a item changes, doesn't trigger a reload for the list itself * made listid and sortorder required for shopping items, as having them nullable makes more problems and workarounds, because both are actually always required * removed the runApp workaround by using a int provider which triggers a reload when changed * use correct settings page, as it's now more than just the theme configurator * made shoppingitems and shoppinglist immutable, as it's better for riverpod when used as a model --- lib/firebase/cloud_messsaging.dart | 103 ++-- lib/main.dart | 67 +-- lib/manager/database_manager.dart | 9 +- lib/manager/export_manager.dart | 7 +- lib/manager/startup_manager.dart | 53 +- lib/models/shopping_item.dart | 99 +++- lib/models/shopping_list.dart | 417 ++++++++++------ lib/models/user.dart | 116 +++-- lib/models_json.dart | 56 +-- lib/options/themes.dart | 30 +- lib/pages/about.dart | 24 +- lib/pages/bought_items.dart | 197 ++++---- lib/pages/change_password.dart | 6 +- lib/pages/contributors.dart | 28 +- lib/pages/login.dart | 49 +- lib/pages/main_page.dart | 494 ++++++++++--------- lib/pages/product_add_to_database.dart | 33 +- lib/pages/registration.dart | 51 +- lib/pages/settings.dart | 1 - lib/pages/shopping_item_search.dart | 71 +-- lib/server_communication/helper_methods.dart | 11 +- lib/server_communication/jwt.dart | 20 +- lib/server_communication/return_classes.dart | 143 +++--- 23 files changed, 1168 insertions(+), 917 deletions(-) diff --git a/lib/firebase/cloud_messsaging.dart b/lib/firebase/cloud_messsaging.dart index e5734b4..89004b6 100644 --- a/lib/firebase/cloud_messsaging.dart +++ b/lib/firebase/cloud_messsaging.dart @@ -2,79 +2,108 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:nssl/helper/iterable_extensions.dart'; import 'package:nssl/models/model_export.dart'; +import 'package:riverpod/riverpod.dart'; FirebaseMessaging? get firebaseMessaging => Platform.isAndroid ? FirebaseMessaging.instance : null; +final cloudMessagingProvider = Provider((ref) { + return CloudMessaging(ref); +}); + class CloudMessaging { - static Future onMessage(RemoteMessage message, Function setState) async { - + static late Ref _ref; + + CloudMessaging(Ref ref) { + _ref = ref; + } + + static Future onMessage(RemoteMessage message) async { final dynamic data = message.data; int listId = int.parse(data["listId"]); - if (User.ownId == int.parse(data["userId"])) { + var ownId = _ref.read(userIdProvider); + if (ownId == int.parse(data["userId"])) { return null; } + var listController = _ref.read(shoppingListsProvider); - if (User.shoppingLists.firstWhere((x) => x.id == listId, orElse: () => ShoppingList.empty) == ShoppingList.empty) { + var list = listController.shoppingLists.firstOrNull((element) => element.id == listId); + + if (list == null) { var mapp = jsonDecode(data["items"]); //User was added to new list - User.shoppingLists.add(ShoppingList(listId, data["name"]) - ..shoppingItems = mapp - .map((x) => ShoppingItem(x["name"]) - ..id = x["id"] - ..amount = x["amount"] - ..sortOrder = x["sortOrder"]) - .toList()); - firebaseMessaging!.subscribeToTopic(listId.toString() + "shoppingListTopic"); + var items = _ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + newState + .addAll(mapp.map((x) => ShoppingItem(x["name"], listId, x["sortOrder"], id: x["id"], amount: x["amount"]))); + items.state = newState; + listController.addList(ShoppingList(listId, data["name"])); } else if (data.length == 1) { //List deleted - User.shoppingLists.removeWhere((x) => x.id == listId); - firebaseMessaging!.unsubscribeFromTopic(listId.toString() + "shoppingListTopic"); + listController.removeList(listId); } else { var action = data["action"]; - var list = User.shoppingLists.firstWhere((x) => x.id == listId); + var list = listController.shoppingLists.firstWhere((x) => x.id == listId); switch (action) { case "ItemChanged": //Id, Amount, action var id = int.parse(data["id"]); - list.shoppingItems!.firstWhere((x) => x!.id == id)!.amount = int.parse(data["amount"]); - list.save(); + var items = _ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + var item = newState.firstWhere((x) => x.id == id); + newState.remove(item); + newState.add(item.cloneWith(newAmount: int.parse(data["amount"]))); + items.state = newState; + listController.save(list); break; case "ItemDeleted": //Id, action var id = int.parse(data["id"]); - list.shoppingItems!.removeWhere((x) => x!.id == id); - list.save(); + listController.deleteSingleItemById(list, id); break; case "NewItemAdded": //Id, Name, Gtin, Amount, action - if (list.shoppingItems!.firstWhere((x) => x!.id == int.parse(data["id"]), orElse: () => null) != null) break; - list.shoppingItems!.add(ShoppingItem(data["name"]) - ..id = int.parse(data["id"]) - ..amount = int.parse(data["amount"]) - ..crossedOut = false - ..sortOrder = int.parse(data["sortOrder"])); - list.save(); + var newItemId = int.parse(data["id"]); + var existing = _ref.read(shoppingItemProvider.create(newItemId)); + if (existing != null) break; + + listController.addSingleItem( + list, + ShoppingItem(data["name"], list.id, int.parse(data["sortOrder"]), + id: int.parse(data["id"]), amount: int.parse(data["amount"]), crossedOut: false)); break; case "ListRename": //Name, action - list.name = data["name"]; - list.save(); + listController.rename(list.id, data["name"] as String); break; case "Refresh": //action - await list.refresh(); + listController.refresh(list); break; case "ItemRenamed": //product.Id, product.Name - list.shoppingItems!.firstWhere((x) => x!.id == int.parse(data["id"]))!.name = data["name"]; - list.save(); + var itemId = int.parse(data["id"]); + var items = _ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + var item = newState.firstWhere((x) => x.id == itemId); + newState.remove(item); + newState.add( + item.cloneWith(newName: data["name"]), + ); + items.state = newState; + listController.save(list); break; case "OrderChanged": - var id = int.parse(data["id"]); - list.shoppingItems!.firstWhere((x) => x!.id == id)!.sortOrder = int.parse(data["sortOrder"]); - list.save(); + var itemId = int.parse(data["id"]); + var items = _ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + var item = newState.firstWhere((x) => x.id == itemId); + newState.remove(item); + newState.add(item.cloneWith( + newAmount: int.parse(data["amount"]), + newSortOrder: int.parse(data["sortOrder"]), + )); + items.state = newState; + listController.save(list); break; } } - var args = []; - args.add(() {}); - Function.apply(setState, args); return null; } diff --git a/lib/main.dart b/lib/main.dart index cc5a28d..f9473ba 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -37,30 +37,37 @@ Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await file.writeAsString(jsonEncode(message.data)); } +final appRestartProvider = StateProvider( + (ref) => 0, +); + Future main() async { // iWonderHowLongThisTakes(); - runApp(FutureBuilder( - builder: (c, t) { - if (t.connectionState == ConnectionState.done) - return ProviderScope( - child: NSSLPage(), - ); - else - return MaterialApp( - builder: (context, child) { - return Center( - child: SizedBox( - height: 200, - width: 200, - child: SvgPicture.asset("assets/vectors/app_icon.svg"), - ), + runApp(ProviderScope(child: Consumer( + builder: (context, ref, child) { + return FutureBuilder( + builder: (c, t) { + if (t.connectionState == ConnectionState.done) { + ref.watch(appRestartProvider); + return NSSLPage(); + } else + return MaterialApp( + builder: (context, child) { + return Center( + child: SizedBox( + height: 200, + width: 200, + child: SvgPicture.asset("assets/vectors/app_icon.svg"), + ), + ); + }, ); - }, - ); + }, + future: Startup.initialize(ref) + .then((value) => FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler)), + ); }, - future: Startup.initialize() - .then((value) => FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler)), - )); + ))); } class NSSL extends StatelessWidget { @@ -70,14 +77,14 @@ class NSSL extends StatelessWidget { } } -class NSSLPage extends StatefulWidget { +class NSSLPage extends ConsumerStatefulWidget { NSSLPage({Key? key}) : super(key: key); @override _NSSLState createState() => _NSSLState(); } -class _NSSLState extends State { +class _NSSLState extends ConsumerState { _NSSLState() : super(); final GlobalKey _mainScaffoldKey = GlobalKey(); @@ -88,16 +95,18 @@ class _NSSLState extends State { @override void initState() { super.initState(); - + ref.read(cloudMessagingProvider); //Neded for ref on onMessage subscribeFirebase(context); FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { - CloudMessaging.onMessage(message, setState); + CloudMessaging.onMessage(message); }); FirebaseMessaging.onMessage.listen((event) { - CloudMessaging.onMessage(event, setState); + CloudMessaging.onMessage(event); }); - for (var list in User.shoppingLists) if (list.messagingEnabled) list.subscribeForFirebaseMessaging(); + + for (var list in ref.read(shoppingListsProvider).shoppingLists) + if (list.messagingEnabled) list.subscribeForFirebaseMessaging(); } Future subscribeFirebase(BuildContext context) async { @@ -106,12 +115,14 @@ class _NSSLState extends State { var initMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initMessage != null) { - CloudMessaging.onMessage(initMessage, setState); + CloudMessaging.onMessage(initMessage); } } @override Widget build(BuildContext context) { + var user = ref.watch(userProvider); + return AdaptiveTheme( light: Themes.lightTheme.theme!, dark: Themes.darkTheme.theme, @@ -131,7 +142,7 @@ class _NSSLState extends State { theme: theme, darkTheme: darkTheme, debugShowMaterialGrid: materialGrid, - home: User.username == null ? mainAppLoginRegister() : mainAppHome(), + home: user.ownId >= 0 ? mainAppHome() : mainAppLoginRegister(), routes: { '/login': (BuildContext context) => LoginPage(), '/registration': (BuildContext context) => Registration(), diff --git a/lib/manager/database_manager.dart b/lib/manager/database_manager.dart index c594c0d..7f47b50 100644 --- a/lib/manager/database_manager.dart +++ b/lib/manager/database_manager.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:flutter/widgets.dart'; import 'package:path_provider/path_provider.dart'; -import 'package:nssl/models/model_export.dart'; import 'package:path/path.dart' as path; import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; @@ -36,17 +35,17 @@ class DatabaseManager { static Future _upgradeDatabase(Database db, int oldVersion, int newVersion) async { //user_id new on ShoppingLists and Themes var list = (await db.rawQuery("SELECT * FROM User LIMIT 1")); - if (list.length != 0) User.ownId = list.first["own_id"] as int?; - + int? userId; + if (list.length != 0) userId = list.first["own_id"] as int?; bool userExists = list.length != 0; if (oldVersion == 1) { var lists = await db.rawQuery("SELECT * FROM ShoppingLists"); await db.execute("ALTER TABLE ShoppingLists ADD user_id INTEGER"); - if (lists.length > 0 && userExists) await db.rawUpdate('UPDATE ShoppingLists SET user_id = ?', [User.ownId]); + if (lists.length > 0 && userExists) await db.rawUpdate('UPDATE ShoppingLists SET user_id = ?', [userId]); var theme = await db.rawQuery("SELECT * FROM Themes"); await db.execute("ALTER TABLE Themes ADD user_id INTEGER"); - if (theme.length > 0 && userExists) await db.rawUpdate('UPDATE Themes SET user_id = ?', [User.ownId]); + if (theme.length > 0 && userExists) await db.rawUpdate('UPDATE Themes SET user_id = ?', [userId]); } if (oldVersion < 3) { diff --git a/lib/manager/export_manager.dart b/lib/manager/export_manager.dart index 9b3f28c..a54a44e 100644 --- a/lib/manager/export_manager.dart +++ b/lib/manager/export_manager.dart @@ -7,19 +7,20 @@ import 'package:pdf/widgets.dart'; import 'package:nssl/models/model_export.dart'; class ExportManager { - static Future exportAsPDF(ShoppingList list, [fm.BuildContext? context]) async { + static Future exportAsPDF(ShoppingList list, List shoppingItems, + [fm.BuildContext? context]) async { // if (!await PermissionRequestManager.requestPermission(PermissionGroup.storage)) { // return; // } - var paragraphs = list.shoppingItems!.map((f) => Paragraph(text: "${f!.amount}x ${f.name}")); + var paragraphs = shoppingItems.map((f) => Paragraph(text: "${f.amount}x ${f.name}")); final pdf = Document(); pdf.addPage(MultiPage( pageFormat: PdfPageFormat.a4, header: (Context context) { return Container( alignment: Alignment.center, - child: Text(list.name!, style: Theme.of(context).header0.copyWith(color: PdfColors.black))); + child: Text(list.name, style: Theme.of(context).header0.copyWith(color: PdfColors.black))); }, build: (Context c) => paragraphs.toList())); diff --git a/lib/manager/startup_manager.dart b/lib/manager/startup_manager.dart index 7ee3eb2..0636d57 100644 --- a/lib/manager/startup_manager.dart +++ b/lib/manager/startup_manager.dart @@ -8,11 +8,10 @@ import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:nssl/manager/database_manager.dart'; import 'package:nssl/models/model_export.dart'; import 'package:nssl/options/themes.dart'; -import 'package:nssl/server_communication/return_classes.dart'; -import 'package:nssl/server_communication/s_c.dart'; import 'package:scandit_flutter_datacapture_barcode/scandit_flutter_datacapture_barcode.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:file/local.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; class Startup { static SharedPreferences? sharedPreferences; @@ -26,7 +25,7 @@ class Startup { .then((value) => true); } - static Future loadMessagesFromFolder(Function setState) async { + static Future loadMessagesFromFolder(WidgetRef ref) async { var dir = await Startup.fs.systemTempDirectory.childDirectory("message").create(); var subFiles = dir.listSync(); if (subFiles.length == 0) return; @@ -37,7 +36,8 @@ class Startup { .forEach((subFile) { var str = subFile.readAsStringSync(); var remoteMessage = RemoteMessage(data: jsonDecode(str)); - CloudMessaging.onMessage(remoteMessage, setState); + ref.read(cloudMessagingProvider); + CloudMessaging.onMessage(remoteMessage); subFile.delete(); }); } @@ -54,51 +54,26 @@ class Startup { }); } - static Future initialize() async { + static Future initialize(WidgetRef ref) async { WidgetsFlutterBinding.ensureInitialized(); var f1 = initializeMinFunction(); await DatabaseManager.initialize(); - await User.load(); + var user = await ref.read(userFromDbProvider.future); - if (User.username == null || User.username == "" || User.eMail == null || User.eMail == "") return false; + if (user == null || user.username == "" || user.eMail == "") return false; + ref.read(themeProvider); await Themes.loadTheme(); - User.shoppingLists = await ShoppingList.load(); - if (User.shoppingLists.length == 0) return true; - User.currentList = - User.shoppingLists.firstWhere((x) => x.id == User.currentListIndex, orElse: () => User.shoppingLists.first); + var provider = ref.read(shoppingListsProvider); + await provider.load(); + await f1; return true; } - static Future initializeNewListsFromServer() async { - var res = await ShoppingListSync.getLists(null); - - if (res.statusCode == 200) { - var result = GetListsResult.fromJson(res.body); - - User.shoppingLists.clear(); - await DatabaseManager.database.rawDelete("DELETE FROM ShoppingLists where user_id = ?", [User.ownId]); - - var crossedOut = - (await DatabaseManager.database.rawQuery("SELECT id, crossed FROM ShoppingItems WHERE crossed = 1")); - result.shoppingLists.forEach((resu) { - var list = ShoppingList(resu.id, resu.name)..shoppingItems = []; - - for (var item in resu.products!) - list.shoppingItems!.add(ShoppingItem(item.name) - ..id = item.id - ..amount = item.amount - ..crossedOut = - (crossedOut.firstWhere((x) => x["id"] == item.id, orElse: () => {"crossed": 0})["crossed"] == 0 - ? false - : true)); - User.shoppingLists.add(list); - list.save(); - }); - } - User.currentList = - User.shoppingLists.firstWhere((x) => x.id == User.currentListIndex, orElse: () => User.shoppingLists.first); + static Future initializeNewListsFromServer(WidgetRef ref) async { + var provider = ref.read(shoppingListsProvider); + await provider.reloadAllLists(); return true; } diff --git a/lib/models/shopping_item.dart b/lib/models/shopping_item.dart index f77c8da..612b194 100644 --- a/lib/models/shopping_item.dart +++ b/lib/models/shopping_item.dart @@ -1,3 +1,7 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:nssl/helper/iterable_extensions.dart'; + class TestClass { int test; String? o; @@ -7,41 +11,98 @@ class TestClass { TestClass.intOnly(this.test); } +final shoppingItemsProvider = StateProvider>(((ref) => [])); + +final shoppingItemsPerListProvider = Provider.family, int>((ref, listId) { + var items = ref.watch(shoppingItemsProvider); + return items.where((element) => element.listId == listId).toList(); +}); + +final shoppingItemProvider = Provider.family((ref, itemId) { + var items = ref.watch(shoppingItemsProvider); + return items.firstOrNull((element) => element.id == itemId); +}); + +@immutable class ShoppingItem { - //extends JsonDecoder{ - int amount = 1; - String? name; - int? id; - DateTime? created; - DateTime? changed; - bool crossedOut = false; - int? sortOrder; + final int amount; + final String name; + final int id; + final DateTime? created; + final DateTime? changed; + final bool crossedOut; + final int sortOrder; + final int listId; - ShoppingItem(this.name); + int get sortWithOffset => sortOrder + (crossedOut ? 0xFFFFFFFF : 0); + + const ShoppingItem( + this.name, + this.listId, + this.sortOrder, { + this.amount = 1, + this.id = -1, + this.crossedOut = false, + this.created, + this.changed, + }); @override String toString() { - return name! + "\u{1F}" + amount.toString() + "\u{1F}" + id.toString(); + return name + "\u{1F}" + amount.toString() + "\u{1F}" + id.toString(); } /// Creates a copy, with only including [amount] and [name] ShoppingItem copy() { - return ShoppingItem(name)..amount = amount; + return ShoppingItem(name, listId, sortOrder, amount: amount); } /// Creates an identical clone, where all fields are the same as /// the parent item ShoppingItem clone() { - return ShoppingItem(name) - ..amount = amount - ..id = id - ..created = created - ..changed = changed - ..crossedOut = crossedOut - ..sortOrder = sortOrder; + return ShoppingItem(name, listId, sortOrder, + amount: amount, id: id, changed: changed, created: created, crossedOut: crossedOut); + } + + ShoppingItem cloneWith( + {String? newName, + int? newListId, + int? newAmount, + int? newId, + DateTime? newCreated, + DateTime? newChanged, + bool? newCrossedOut, + int? newSortOrder}) { + return ShoppingItem(newName ?? name, newListId ?? listId, newSortOrder ?? sortOrder, + amount: newAmount ?? amount, + id: newId ?? id, + changed: newChanged ?? changed, + created: newCreated ?? created, + crossedOut: newCrossedOut ?? crossedOut); } - ShoppingItem.fromJson(String s) : name = s; + // ShoppingItem.fromJson(String s) : name = s; Map toJson() => {'name': name}; + + @override + bool operator ==(final Object other) => + other is ShoppingItem && + other.name == name && + other.amount == amount && + other.id == id && + other.crossedOut == crossedOut && + other.sortOrder == sortOrder && + other.listId == listId; + + @override + int get hashCode => Object.hash(name, amount, id, crossedOut, sortOrder, listId); + + void exchange(ShoppingItem newItem, WidgetRef ref) { + var items = ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + newState.remove(this); + newState.add(newItem); + items.state = newState; + } } diff --git a/lib/models/shopping_list.dart b/lib/models/shopping_list.dart index e85d644..3916049 100644 --- a/lib/models/shopping_list.dart +++ b/lib/models/shopping_list.dart @@ -1,189 +1,314 @@ import 'package:flutter/material.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; -import 'package:nssl/models/shopping_item.dart'; +import 'package:nssl/helper/iterable_extensions.dart'; +import 'package:nssl/models/model_export.dart'; import 'package:nssl/manager/manager_export.dart'; -import 'package:nssl/models/user.dart'; import 'dart:async'; import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/server_communication/shopping_list_sync.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class ShoppingList { - static ShoppingList empty = ShoppingList.messaging(1, "", false); +final shoppingListsProvider = ChangeNotifierProvider((ref) { + var userId = ref.watch(userIdProvider); + if (userId == null) return ShoppingListController(ref, -1); + + var manager = ShoppingListController(ref, userId); + + return manager; +}); + +final listProvider = Provider.family((ref, indx) { + var shoppingListController = ref.watch(shoppingListsProvider); + if (indx + 1 > shoppingListController.shoppingLists.length) return null; + + return shoppingListController.shoppingLists[indx]; +}); + +final currentListProvider = Provider((ref) { + var index = ref.watch(currentListIndexProvider); + if (index == null) return null; + return ref.watch(listProvider.create(index)); +}); + +final currentShoppingItemsProvider = Provider>((ref) { + var list = ref.watch(currentListProvider); + if (list == null || list.id < 0) return []; + return ref.watch(shoppingItemsPerListProvider.create(list.id)); +}); + +final shoppingListByIndexProvider = Provider.family((ref, indx) { + var shoppingListController = ref.watch(shoppingListsProvider); + if (indx > shoppingListController.shoppingLists.length) return null; - int? id; + return shoppingListController.shoppingLists[indx]; +}); - String? name; - List? shoppingItems = []; - bool messagingEnabled = true; +final shoppingListByIdProvider = Provider.family((ref, id) { + var shoppingListController = ref.watch(shoppingListsProvider); - ShoppingList(this.id, this.name); + return shoppingListController.shoppingLists.firstOrNull((element) => element.id == id); +}); - ShoppingList.messaging(this.id, this.name, this.messagingEnabled); +class ShoppingListController with ChangeNotifier { + static late Ref _ref; + static late int _userId; + List shoppingLists = []; - Future save() async { + ShoppingListController(Ref ref, int userId) { + _ref = ref; + _userId = userId; + } + + Future save(ShoppingList list) async { await DatabaseManager.database.transaction((z) async { - await z.execute( - 'INSERT OR REPLACE INTO ShoppingLists(id, name, messaging, user_id) VALUES(?, ?, ?, ?)', - [id, name, messagingEnabled ? 1 : 0, User.ownId]); - - await z.rawDelete( - "DELETE FROM ShoppingItems WHERE res_list_id = ? and id not in (?)", - [id, shoppingItems!.map((e) => e!.id).join(",")]); - for (var item in shoppingItems!) { + await z.execute('INSERT OR REPLACE INTO ShoppingLists(id, name, messaging, user_id) VALUES(?, ?, ?, ?)', + [list.id, list.name, list.messagingEnabled ? 1 : 0, _userId]); + var shoppingItems = _ref.read(shoppingItemsPerListProvider.create(list.id)); + await z.rawDelete("DELETE FROM ShoppingItems WHERE res_list_id = ? and id not in (?)", + [list.id, shoppingItems.map((e) => e.id).join(",")]); + for (var item in shoppingItems) { await z.execute( "INSERT OR REPLACE INTO ShoppingItems(id, name, amount, crossed, res_list_id, sortorder) VALUES (?, ?, ?, ?, ?, ?)", - [ - item!.id, - item.name, - item.amount, - item.crossedOut ? 1 : 0, - id, - item.sortOrder - ]); + [item.id, item.name, item.amount, item.crossedOut ? 1 : 0, list.id, item.sortOrder]); } }); } - Future addSingleItem(ShoppingItem item, {int index = -1}) async { - if (index < 0) index = shoppingItems!.length; - shoppingItems!.insert(index, item); + Future addSingleItem(ShoppingList list, ShoppingItem item, {int index = -1}) async { + // var shoppingItems = _ref.read(shoppingItemsPerListProvider.create(list.id)); + // if (index < 0) index = shoppingItems.length; + // shoppingItems.insert(index, item); + + // var newList = ShoppingList(list.id, list.name, messagingEnabled: list.messagingEnabled); + // _exchangeLists(list, newList); + var sip = _ref.watch(shoppingItemsProvider.notifier); + var newState = sip.state.toList(); + newState.add(item); + sip.state = newState; + await DatabaseManager.database.execute( "INSERT OR REPLACE INTO ShoppingItems(id, name, amount, crossed, res_list_id, sortorder) VALUES (?, ?, ?, ?, ?, ?)", - [ - item.id, - item.name, - item.amount, - item.crossedOut ? 1 : 0, - id, - item.sortOrder - ]); - } - - Future deleteSingleItem(ShoppingItem item) async { - shoppingItems!.remove(item); - await DatabaseManager.database - .rawDelete("DELETE FROM ShoppingItems WHERE id = ?", [item.id]); - } - - static Future> load() async { - var lists = await DatabaseManager.database.rawQuery( - "SELECT * FROM ShoppingLists WHERE user_id = ?", [User.ownId]); - - var items = await DatabaseManager.database.rawQuery( - "SELECT * FROM ShoppingItems ORDER BY res_list_id, sortorder"); - - // TODO: if db ordering enough for us, or do we want to order by ourself in code? - // return lists - // .map((x) => ShoppingList() - // ..id = x["id"] - // ..messagingEnabled = x["messaging"] == 0 ? false : true - // ..name = x["name"] - // ..shoppingItems = (items - // .where((y) => y["res_list_id"] == x["id"]) - // .map((y) => ShoppingItem(y["name"]) - // ..amount = y["amount"] - // ..crossedOut = y["crossed"] == 0 ? false : true - // ..id = y["id"] - // ..sortOrder = y["sortorder"]) - // .toList() - // ..sort((a, b) => a.sortOrder?.compareTo(b.sortOrder)))) - // .toList(); - - return lists - .map((x) => ShoppingList(x["id"] as int?, x["name"] as String?) - ..messagingEnabled = x["messaging"] == 0 ? false : true - ..shoppingItems = items - .where((y) => y["res_list_id"] == x["id"]) - .map((y) => ShoppingItem(y["name"] as String?) - ..amount = y["amount"] as int - ..crossedOut = y["crossed"] == 0 ? false : true - ..id = y["id"] as int? - ..sortOrder = y["sortorder"] as int?) - .toList()) + [item.id, item.name, item.amount, item.crossedOut ? 1 : 0, list.id, item.sortOrder]); + save(list); + notifyListeners(); + } + + Future deleteSingleItemById(ShoppingList list, int itemId) async { + var sip = _ref.watch(shoppingItemsProvider.notifier); + var newState = sip.state.toList(); + newState.removeWhere((x) => x.id == itemId); + sip.state = newState; + // var newList = ShoppingList(list.id, list.name, list.shoppingItems.where((element) => element != item).toList(), + // messagingEnabled: list.messagingEnabled); + // _exchangeLists(list, newList); + await DatabaseManager.database.rawDelete("DELETE FROM ShoppingItems WHERE id = ?", [itemId]); + save(list); + } + + Future deleteSingleItem(ShoppingList list, ShoppingItem item) async { + var sip = _ref.watch(shoppingItemsProvider.notifier); + var newState = sip.state.toList(); + newState.remove(item); + sip.state = newState; + // var newList = ShoppingList(list.id, list.name, list.shoppingItems.where((element) => element != item).toList(), + // messagingEnabled: list.messagingEnabled); + // _exchangeLists(list, newList); + await DatabaseManager.database.rawDelete("DELETE FROM ShoppingItems WHERE id = ?", [item.id]); + save(list); + } + + Future> load() async { + var lists = await DatabaseManager.database.rawQuery("SELECT * FROM ShoppingLists WHERE user_id = ?", [_userId]); + + var items = await DatabaseManager.database.rawQuery("SELECT * FROM ShoppingItems ORDER BY res_list_id, sortorder"); + + int curSortOrder = 0; + var newShoppingItems = items.map( + (y) { + var sortOrder = y["sortorder"] as int?; + if (sortOrder != null) + curSortOrder = sortOrder; + else + curSortOrder++; + return ShoppingItem( + y["name"] as String, + y["res_list_id"] as int, + curSortOrder, + amount: y["amount"] as int, + crossedOut: y["crossed"] == 0 ? false : true, + id: y["id"] as int, + ); + }, + ).toList(); + + shoppingLists = lists + .map((x) => + ShoppingList(x["id"] as int, x["name"] as String, messagingEnabled: x["messaging"] == 0 ? false : true)) .toList(); + + var sip = _ref.watch(shoppingItemsProvider.notifier); + sip.state = newShoppingItems; + + notifyListeners(); + return shoppingLists; } - Future refresh([BuildContext? context]) async { - var res = await ShoppingListSync.getList(id, context); -// if (res.statusCode == 401) { -// showInSnackBar(loc.notLoggedInYet() + res.reasonPhrase); -// return; -// } -// if (res.statusCode != 200) { -// showInSnackBar(loc.genericErrorMessageSnackbar()); -// return; -// } - var newList = GetListResult.fromJson(res.body); - List> items; - items = (await DatabaseManager.database.rawQuery( - "SELECT id, crossed, sortorder FROM ShoppingItems WHERE res_list_id = ?", - [id])); - - shoppingItems!.clear(); - for (var item in newList.products!) - shoppingItems!.add(ShoppingItem(item.name) - ..id = item.id - ..amount = item.amount - ..changed = item.changed - ..created = item.created - ..crossedOut = (items.firstWhere((x) => x["id"] == item.id, - orElse: () => {"crossed": 0})["crossed"] == - 0 - ? false - : true) - ..sortOrder = item.sortOrder); - - shoppingItems!.sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); - save(); - } - - static Future reloadAllLists([BuildContext? cont]) async { - var result = - GetListsResult.fromJson((await ShoppingListSync.getLists(cont)).body); - User.shoppingLists.clear(); - - await DatabaseManager.database - .delete("ShoppingLists", where: "user_id = ?", whereArgs: [User.ownId]); - //await DatabaseManager.database.rawDelete("DELETE FROM ShoppingLists where user_id = ?", [User.ownId]); + Future refresh(ShoppingList list, [BuildContext? context]) async { + var res = await ShoppingListSync.getList(list.id, context); + var newListResult = GetListResult.fromJson(res.body); List> items; items = (await DatabaseManager.database - .rawQuery("SELECT id, crossed, sortorder FROM ShoppingItems")); + .rawQuery("SELECT id, crossed, sortorder FROM ShoppingItems WHERE res_list_id = ?", [list.id])); - for (var res in result.shoppingLists) { - var list = ShoppingList(res.id, res.name); + var shoppingItems = []; + var sip = _ref.watch(shoppingItemsProvider.notifier); + var newState = sip.state.toList(); + newState.removeWhere((item) => item.listId == list.id); - for (var item in res.products!) - list.shoppingItems!.add(ShoppingItem(item.name) - ..id = item.id - ..amount = item.amount - ..crossedOut = (items.firstWhere((x) => x["id"] == item.id, - orElse: () => {"crossed": 0})["crossed"] == - 0 - ? false - : true) - ..sortOrder = (items.firstWhere((x) => x["id"] == item.id, - orElse: () => {"sortorder": 0})["sortorder"])); + for (var item in newListResult.products!) + shoppingItems.add(ShoppingItem( + item.name, + list.id, + item.sortOrder, + id: item.id, + amount: item.amount, + changed: item.changed, + created: item.created, + crossedOut: + (items.firstWhere((x) => x["id"] == item.id, orElse: () => {"crossed": 0})["crossed"] == 0 ? false : true), + )); - if (list.shoppingItems!.any((element) => element!.sortOrder == null)) - for (int i = 0; i < list.shoppingItems!.length; i++) - list.shoppingItems![i]!.sortOrder = i; + shoppingItems.sort((a, b) => a.sortWithOffset.compareTo(b.sortWithOffset)); + newState.addAll(shoppingItems); + var newList = ShoppingList(list.id, list.name, messagingEnabled: list.messagingEnabled); + _exchangeLists(list, newList); + sip.state = newState; + save(newList); - list.shoppingItems! - .sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); - User.shoppingLists.add(list); + notifyListeners(); + } + + void _exchangeLists(ShoppingList list, ShoppingList newList) { + var index = shoppingLists.indexOf(list); + shoppingLists.remove(list); + shoppingLists.insert(index, newList); + } + Future reloadAllLists([BuildContext? cont]) async { + var res = (await ShoppingListSync.getLists(cont)); + if (res.statusCode != 200) return; + + // DatabaseManager.database.rawDelete("DELETE FROM ShoppingLists where user_id = ?", _ref.read())) //TODO Should everything be deleted from this user? + + var result = GetListsResult.fromJson(res.body); + shoppingLists.clear(); + await DatabaseManager.database.delete("ShoppingLists", where: "user_id = ?", whereArgs: [_userId]); + + List> items; + items = (await DatabaseManager.database.rawQuery("SELECT id, crossed, sortorder FROM ShoppingItems")); + + var shoppintItemsState = _ref.watch(shoppingItemsProvider.notifier); + var shoppingItems = []; + int currentSortOrder = 0; + for (var res in result.shoppingLists) { + for (var item in res.products) { + var order = + items.firstWhere((x) => x["id"] == item.id, orElse: () => {"sortorder": 0})["sortorder"] as int? ?? -1; + if (order == -1 || currentSortOrder == order) + order = ++currentSortOrder; + else + currentSortOrder = order; + shoppingItems.add(ShoppingItem( + item.name, + res.id, + order, + id: item.id, + amount: item.amount, + crossedOut: (items.firstWhere((x) => x["id"] == item.id, orElse: () => {"crossed": 0})["crossed"] == 0 + ? false + : true), + )); + } + + // if (shoppingItems.any((element) => element.sortOrder == null)) + // for (int i = 0; i < shoppingItems.length; i++) { + // var oldItem = shoppingItems[i]; + // shoppingItems.removeAt(i); + // shoppingItems.insert( + // i, + // ShoppingItem(oldItem.name, oldItem.listId, i, + // id: oldItem.id, + // crossedOut: oldItem.crossedOut, + // amount: oldItem.amount, + // changed: oldItem.changed, + // created: oldItem.created)); + // } + + var list = ShoppingList(res.id, res.name); + shoppingLists.add(list); list.subscribeForFirebaseMessaging(); - list.save(); + save(list); } + shoppingItems.sort((a, b) => a.sortWithOffset.compareTo(b.sortWithOffset)); + shoppintItemsState.state = shoppingItems; + notifyListeners(); + } + + void addList(ShoppingList shoppingList) { + shoppingLists.add(shoppingList); + shoppingList.subscribeForFirebaseMessaging(); + save(shoppingList); + notifyListeners(); + } + + void removeList(int listId) { + shoppingLists.removeWhere((x) => x.id == listId); + + firebaseMessaging?.unsubscribeFromTopic(listId.toString() + "shoppingListTopic"); + notifyListeners(); + } + + void saveAndNotify(ShoppingList list) { + save(list); + notifyListeners(); } + void toggleFirebaseMessaging(int listId) { + var list = shoppingLists.firstWhere((element) => element.id == listId); + var newList = ShoppingList(listId, list.name, messagingEnabled: !list.messagingEnabled); + newList.messagingEnabled ? list.unsubscribeFromFirebaseMessaging() : list.subscribeForFirebaseMessaging(); + _exchangeLists(list, newList); + save(newList); + } + + void rename(int id, String name) { + var list = shoppingLists.firstWhere((element) => element.id == id); + + var newList = ShoppingList(id, name, messagingEnabled: list.messagingEnabled); + _exchangeLists(list, newList); + saveAndNotify(list); + } +} + +@immutable +class ShoppingList { + static ShoppingList empty = const ShoppingList.messaging(1, "", false); + + final int id; + final String name; + // final List shoppingItems; + final bool messagingEnabled; + + const ShoppingList(this.id, this.name, /*this.shoppingItems,*/ {this.messagingEnabled = true}); + + const ShoppingList.messaging(this.id, this.name, /*this.shoppingItems,*/ this.messagingEnabled); + void subscribeForFirebaseMessaging() { firebaseMessaging?.subscribeToTopic(id.toString() + "shoppingListTopic"); } void unsubscribeFromFirebaseMessaging() { - firebaseMessaging - ?.unsubscribeFromTopic(id.toString() + "shoppingListTopic"); + firebaseMessaging?.unsubscribeFromTopic(id.toString() + "shoppingListTopic"); } } diff --git a/lib/models/user.dart b/lib/models/user.dart index 0b13ed2..59ec898 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -1,43 +1,101 @@ import 'dart:async'; +import 'package:flutter/cupertino.dart'; import 'package:nssl/manager/database_manager.dart'; -import 'package:nssl/models/shopping_list.dart'; import 'package:nssl/server_communication/jwt.dart'; +import 'package:riverpod/riverpod.dart'; -class User { - static String? username; - static String? eMail; - static List shoppingLists = []; - static String? token; - static int? currentListIndex; - static ShoppingList? currentList; - static int? ownId; - - static Future load() async { - var list = (await DatabaseManager.database.rawQuery("SELECT * FROM User LIMIT 1")); - if (list.length == 0) return; - var z = list.first; - User.username = z["username"] as String?; - User.eMail = z["email"] as String?; - User.token = z["token"] as String?; - User.currentListIndex = z["current_list_index"] as int?; - if (!z.containsKey("own_id")) { - await DatabaseManager.database.execute("DROP TABLE User"); - await DatabaseManager.database.execute( - "CREATE TABLE User (own_id INTEGER, username TEXT, email TEXT, token TEXT, current_list_index INTEGER)"); - User.ownId = await JWT.getIdFromToken(User.token); - await save(); - } else - User.ownId = z["own_id"] as int?; +final userFromDbProvider = FutureProvider((ref) async { + var list = (await DatabaseManager.database.rawQuery("SELECT * FROM User LIMIT 1")); + if (list.length == 0) return null; + var z = list.first; + var username = z["username"] as String; + var eMail = z["email"] as String; + var token = z["token"] as String; + var ownId = await JWT.getIdFromToken(token); + var currentListIndex = z["current_list_index"] as int; + var containsOwnId = z.containsKey("own_id"); + if (!containsOwnId) { + await DatabaseManager.database.execute("DROP TABLE User"); + await DatabaseManager.database.execute( + "CREATE TABLE User (own_id INTEGER, username TEXT, email TEXT, token TEXT, current_list_index INTEGER)"); + } else + ownId = z["own_id"] as int; + User.token = token; + var user = User(ownId, username, eMail); + ref.watch(currentListIndexProvider.notifier).state = currentListIndex; + + if (!containsOwnId) user.save(currentListIndex); + return user; +}); + +final userStateProvider = StateProvider((ref) { + return User.empty; +}); + +final userProvider = Provider((ref) { + var fromState = ref.watch(userStateProvider); + if (fromState.ownId == -1) { + var fromDb = ref.watch(userFromDbProvider); + if (!fromDb.hasError && fromDb.hasValue) { + return fromDb.valueOrNull ?? fromState; + } } + return fromState; +}); + +final userIdProvider = Provider((ref) { + return ref.watch(userProvider).ownId; +}); + +final currentListIndexProvider = StateProvider((ref) { + return null; +}); + +@immutable +class User { + static User empty = const User(-1, "", ""); + + final String username; + final String eMail; + // final List shoppingLists = []; + static String token = ""; + final int ownId; + + @override + bool operator ==(final Object other) => + other is User && other.username == username && other.eMail == eMail && other.ownId == ownId; + + @override + int get hashCode => Object.hash(username, eMail, ownId); + + const User(this.ownId, this.username, this.eMail); + + // static Future load() async { + // var list = (await DatabaseManager.database.rawQuery("SELECT * FROM User LIMIT 1")); + // if (list.length == 0) return; + // var z = list.first; + // User.username = z["username"] as String?; + // User.eMail = z["email"] as String?; + // User.token = z["token"] as String?; + // User.currentListIndex = z["current_list_index"] as int?; + // if (!z.containsKey("own_id")) { + // await DatabaseManager.database.execute("DROP TABLE User"); + // await DatabaseManager.database.execute( + // "CREATE TABLE User (own_id INTEGER, username TEXT, email TEXT, token TEXT, current_list_index INTEGER)"); + // User.ownId = await JWT.getIdFromToken(User.token); + // await save(); + // } else + // User.ownId = z["own_id"] as int?; + // } - static Future save() async { + Future save(int? currentListIndex) async { await DatabaseManager.database.rawDelete("DELETE FROM User"); await DatabaseManager.database.execute( "INSERT INTO User(own_id, username, email, token, current_list_index) VALUES(?, ?, ?, ?, ?)", - [User.ownId, User.username, User.eMail, User.token, User.currentListIndex]); + [ownId, username, eMail, token, currentListIndex]); } - static Future delete() async { + Future delete() async { await DatabaseManager.database.rawDelete("DELETE FROM User where own_id = ?", [ownId]); } } diff --git a/lib/models_json.dart b/lib/models_json.dart index 4e9f8f3..c73e053 100644 --- a/lib/models_json.dart +++ b/lib/models_json.dart @@ -6,8 +6,7 @@ class User { toJson() => {"username": username, "email": email, "pwhash": password}; - static User fromJson(Map data) => - User(data["username"], data["email"], data["pwhash"]); + static User fromJson(Map data) => User(data["username"], data["email"], data["pwhash"]); } class Product { @@ -26,50 +25,32 @@ class Product { } class ShoppingItem { - ShoppingItem(this.id, this.amount, this.name, this.changed, this.created, - this.sortOrder) - : super(); - int? id; + ShoppingItem(this.id, this.amount, this.name, this.changed, this.created, this.sortOrder) : super(); + int id; int amount; - String? name; + String name; DateTime? changed; DateTime? created; - int? sortOrder; + int sortOrder; - toJson() => { - "id": id, - "amount": amount, - "name": name, - "changed": changed, - "created": created, - "sortOrder": sortOrder - }; + toJson() => + {"id": id, "amount": amount, "name": name, "changed": changed, "created": created, "sortOrder": sortOrder}; - static ShoppingItem fromJson(Map data) => ShoppingItem( - data["id"], - data["amount"], - data["name"], - data["changed"], - data["created"], - data["sortOrder"]); + static ShoppingItem fromJson(Map data) => + ShoppingItem(data["id"], data["amount"], data["name"], data["changed"], data["created"], data["sortOrder"]); } class ShoppingList { - List? products; - int? id; - String? name; + List products; + int id; + String name; - toJson() => { - "products": products?.map((p) => p.toJson()).toList(growable: false), - "id": id, - "name": name - }; + ShoppingList(this.id, this.name, this.products); - static ShoppingList fromJson(Map data) => ShoppingList() - ..id = data["id"] - ..name = data["name"] - ..products = - (data["products"] as List).map(ShoppingItem.fromJson).toList(); + toJson() => {"products": products.map((p) => p.toJson()).toList(growable: false), "id": id, "name": name}; + + static ShoppingList fromJson(Map data) => ShoppingList( + data["id"] as int, data["name"] as String, (data["products"] as List).map(ShoppingItem.fromJson).toList()); } class Contributor { @@ -79,6 +60,5 @@ class Contributor { String? name; toJson() => {"id": id, "listId": listId, "name": name}; - static Contributor fromJson(Map data) => - Contributor(data["id"], data["listId"], data["name"]); + static Contributor fromJson(Map data) => Contributor(data["id"], data["listId"], data["name"]); } diff --git a/lib/options/themes.dart b/lib/options/themes.dart index 37dcb6d..9d34913 100644 --- a/lib/options/themes.dart +++ b/lib/options/themes.dart @@ -3,8 +3,18 @@ import 'package:flutter/material.dart'; import 'package:nssl/manager/database_manager.dart'; import 'package:nssl/models/user.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final themeProvider = ChangeNotifierProvider((ref) { + return Themes(ref); +}); + +class Themes with ChangeNotifier { + static late Ref _ref; + Themes(Ref ref) { + _ref = ref; + } -class Themes { static NSSLThemeData lightTheme = NSSLThemeData( ThemeData( primarySwatch: Colors.blue, @@ -47,27 +57,23 @@ class Themes { static Future saveTheme(ThemeData t, MaterialColor primary, MaterialAccentColor accent) async { // await DatabaseManager.database.rawDelete("DELETE FROM Themes"); - var id = ((t.brightness == Brightness.light ? 1 : 2) << 32) + User.ownId!; + var userId = _ref.watch(userIdProvider); + if (userId == null) return; + var id = ((t.brightness == Brightness.light ? 1 : 2) << 32) + userId; (await SharedPreferences.getInstance()).setInt("lastTheme", id); tm = t.brightness == Brightness.dark ? ThemeMode.dark : ThemeMode.light; await DatabaseManager.database.rawInsert( "INSERT OR REPLACE INTO Themes(id, primary_color, accent_color, brightness, accent_color_brightness, user_id) VALUES(?, ?, ?, ?, ?, ?)", - [ - id, - Colors.primaries.indexOf(primary), - Colors.accents.indexOf(accent), - t.brightness.toString(), - "", - User.ownId - ]); + [id, Colors.primaries.indexOf(primary), Colors.accents.indexOf(accent), t.brightness.toString(), "", userId]); } static Future loadTheme() async { late var t; var lastId = (await SharedPreferences.getInstance()).getInt("lastTheme") ?? 0; + var userId = _ref.watch(userIdProvider); try { - if (User.ownId != null) - t = (await DatabaseManager.database.rawQuery("SELECT * FROM Themes where user_id = ?", [User.ownId])); + if (userId != null) + t = (await DatabaseManager.database.rawQuery("SELECT * FROM Themes where user_id = ?", [userId])); } catch (e) { var temp = (await DatabaseManager.database.rawQuery("SELECT * FROM Themes")).first; diff --git a/lib/pages/about.dart b/lib/pages/about.dart index 2abb6fd..64ab408 100644 --- a/lib/pages/about.dart +++ b/lib/pages/about.dart @@ -82,9 +82,9 @@ class AboutPage extends StatelessWidget { ), title: Text(NSSLStrings.of(context).codeOnGithub()), onTap: () { - var urlString = "https://github.com/susch19/nssl"; - canLaunch(urlString).then((value) { - if (value) launch(urlString); + var urlString = Uri.parse("https://github.com/susch19/nssl"); + canLaunchUrl(urlString).then((value) { + if (value) launchUrl(urlString); }); }, ), @@ -93,9 +93,9 @@ class AboutPage extends StatelessWidget { leading: SvgPicture.asset("assets/vectors/nssl_icon.svg", alignment: Alignment.center, width: 32), title: Text(NSSLStrings.of(context).iconSource()), onTap: () { - var urlString = "https://www.flaticon.com/free-icon/check-list_306470"; - canLaunch(urlString).then((value) { - if (value) launch(urlString); + var urlString = Uri.parse("https://www.flaticon.com/free-icon/check-list_306470"); + canLaunchUrl(urlString).then((value) { + if (value) launchUrl(urlString); }); }, ), @@ -104,9 +104,9 @@ class AboutPage extends StatelessWidget { leading: SvgPicture.asset("assets/vectors/google_play.svg", alignment: Alignment.center, width: 32), title: Text(NSSLStrings.of(context).playstoreEntry()), onTap: () { - var urlString = "https://play.google.com/store/apps/details?id=de.susch19.nssl"; - canLaunch(urlString).then((value) { - if (value) launch(urlString); + var urlString = Uri.parse("https://play.google.com/store/apps/details?id=de.susch19.nssl"); + canLaunchUrl(urlString).then((value) { + if (value) launchUrl(urlString); }); }, ), @@ -115,9 +115,9 @@ class AboutPage extends StatelessWidget { leading: Image.asset("assets/images/scandit.png", alignment: Alignment.center, width: 128, color: iconColor), title: Text(NSSLStrings.of(context).scanditCredit()), onTap: () { - var urlString = "https://scandit.com"; - canLaunch(urlString).then((value) { - if (value) launch(urlString); + var urlString = Uri.parse("https://scandit.com"); + canLaunchUrl(urlString).then((value) { + if (value) launchUrl(urlString); }); }, ), diff --git a/lib/pages/bought_items.dart b/lib/pages/bought_items.dart index b3fd650..e764e70 100644 --- a/lib/pages/bought_items.dart +++ b/lib/pages/bought_items.dart @@ -4,8 +4,9 @@ import 'package:nssl/models/model_export.dart'; import 'package:nssl/server_communication//s_c.dart'; import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/helper/iterable_extensions.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class BoughtItemsPage extends StatefulWidget { +class BoughtItemsPage extends ConsumerStatefulWidget { BoughtItemsPage(this.listId, {Key? key, this.title}) : super(key: key); final String? title; final int listId; @@ -13,12 +14,10 @@ class BoughtItemsPage extends StatefulWidget { _BoughtItemsPagePageState createState() => new _BoughtItemsPagePageState(listId); } -class _BoughtItemsPagePageState extends State with SingleTickerProviderStateMixin { +class _BoughtItemsPagePageState extends ConsumerState with SingleTickerProviderStateMixin { final GlobalKey _mainScaffoldKey = GlobalKey(); var tec = TextEditingController(); - var shoppingItems = []; - var currentList = ShoppingList(0, "empty"); var shoppingItemsGrouped = new Map>(); int k = 1; int listId; @@ -35,39 +34,7 @@ class _BoughtItemsPagePageState extends State with SingleTicker super.dispose(); } - _BoughtItemsPagePageState(this.listId) { - currentList = User.shoppingLists.firstWhere((element) => element.id == listId); - - ShoppingListSync.getList(listId, null, bought: true).then((o) { - if (o.statusCode == 500) { - showInSnackBar("Internal Server Error"); - return; - } - var z = GetBoughtListResult.fromJson(o.body); - if (z.products.length <= 0) - showInSnackBar(NSSLStrings.of(context).nothingBoughtYet(), duration: Duration(seconds: 10)); - else { - shoppingItems.addAll(z.products.map((f) => ShoppingItem(f.name) - ..id = f.id - ..amount = f.amount - ..changed = f.changed - ..created = f.created - ..crossedOut = false)); - DateTime date; - shoppingItems.sort((x, y) => y.changed!.compareTo(x.changed!)); - for (var item in shoppingItems) { - date = dateTimeToDate(item.changed!); - if (!shoppingItemsGrouped.containsKey(dateTimeToDate(item.changed!))) - shoppingItemsGrouped[date] = []; - shoppingItemsGrouped[date]!.add(item); - } - } - - setState(() { - _controller = TabController(vsync: this, length: shoppingItemsGrouped.keys.length); - }); - }); - } + _BoughtItemsPagePageState(this.listId); DateTime dateTimeToDate(DateTime dateTime) { return DateTime.utc(dateTime.year, dateTime.month, dateTime.day); @@ -75,38 +42,68 @@ class _BoughtItemsPagePageState extends State with SingleTicker @override Widget build(BuildContext context) { - if (_controller == null) - return Scaffold( - appBar: AppBar( - title: Text(NSSLStrings.of(context).boughtProducts()), - actions: [], - ), - body: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - child: SizedBox(width: 40.0, height: 40.0, child: CircularProgressIndicator()), - padding: const EdgeInsets.only(top: 16.0), - ) - ], - )); - - return Scaffold( - key: _mainScaffoldKey, - appBar: AppBar( - title: Text(NSSLStrings.of(context).boughtProducts()), - bottom: TabBar( - controller: _controller, - isScrollable: true, - indicator: getIndicator(), - tabs: createTabs(), - ), - ), - body: TabBarView( - controller: _controller, - children: createChildren(), - ), - ); + return FutureBuilder( + builder: (c, t) { + if (t.connectionState == ConnectionState.done) { + return Scaffold( + key: _mainScaffoldKey, + appBar: AppBar( + title: Text(NSSLStrings.of(context).boughtProducts()), + bottom: TabBar( + controller: _controller, + isScrollable: true, + indicator: getIndicator(), + tabs: createTabs(), + ), + ), + body: TabBarView( + controller: _controller, + children: createChildren(), + ), + ); + } else { + return Scaffold( + appBar: AppBar( + title: Text(NSSLStrings.of(context).boughtProducts()), + actions: [], + ), + body: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: SizedBox(width: 40.0, height: 40.0, child: CircularProgressIndicator()), + padding: const EdgeInsets.only(top: 16.0), + ) + ], + )); + } + }, + future: ShoppingListSync.getList(listId, null, bought: true).then((o) { + if (o.statusCode == 500) { + showInSnackBar("Internal Server Error"); + return; + } + var z = GetBoughtListResult.fromJson(o.body); + if (z.products.length <= 0) + showInSnackBar(NSSLStrings.of(context).nothingBoughtYet(), duration: Duration(seconds: 10)); + else { + var shoppingItems = []; + + shoppingItems.addAll(z.products.map((f) => ShoppingItem(f.name, listId, f.sortOrder, + id: f.id, amount: f.amount, changed: f.changed, created: f.created, crossedOut: false))); + + DateTime date; + shoppingItems.sort((x, y) => y.changed!.compareTo(x.changed!)); + for (var item in shoppingItems) { + date = dateTimeToDate(item.changed!); + if (!shoppingItemsGrouped.containsKey(dateTimeToDate(item.changed!))) + shoppingItemsGrouped[date] = []; + shoppingItemsGrouped[date]!.add(item); + } + } + + _controller = TabController(vsync: this, length: shoppingItemsGrouped.keys.length); + })); } Decoration getIndicator() { @@ -141,7 +138,9 @@ class _BoughtItemsPagePageState extends State with SingleTicker } List createChildren() { + var currentList = ref.watch(currentListProvider); var children = []; + if (currentList == null) return children; for (var item in shoppingItemsGrouped.keys) { children.add(SafeArea( top: false, @@ -152,34 +151,38 @@ class _BoughtItemsPagePageState extends State with SingleTicker child: Card( child: Center( child: ListView( - children: shoppingItemsGrouped[item]! - .map( - (i) => ListTile( - title: Text(i.name!), - leading: Text(i.amount.toString() + "x"), - onTap: () async { - var existingItem = currentList.shoppingItems?.firstOrNull((item) => item?.name == i.name); - if (existingItem != null) { - var answer = await ShoppingListSync.changeProductAmount( - currentList.id!, existingItem.id, i.amount, context); - var p = ChangeListItemResult.fromJson((answer).body); - existingItem.amount = p.amount; - existingItem.changed = p.changed; - } else { - var p = AddListItemResult.fromJson( - (await ShoppingListSync.addProduct(listId, i.name, null, i.amount, context)).body); - var newItem = ShoppingItem(p.name) - ..amount = i.amount - ..id = p.productId; - - currentList.addSingleItem(newItem); - } - showInSnackBar( - "${i.amount}x ${i.name}${NSSLStrings.of(context).newProductAddedToList()}${currentList.name}"); - }, - ), - ) - .toList(growable: false), + children: shoppingItemsGrouped[item]!.map( + (i) { + return ListTile( + title: Text(i.name), + leading: Text(i.amount.toString() + "x"), + onTap: () async { + var shoppingItems = ref.read(currentShoppingItemsProvider); + var existingItem = shoppingItems.firstOrNull((item) => item.name == i.name); + var listsProvider = ref.read(shoppingListsProvider); + if (existingItem != null) { + var answer = await ShoppingListSync.changeProductAmount( + currentList.id, existingItem.id, i.amount, context); + var p = ChangeListItemResult.fromJson((answer).body); + listsProvider.addSingleItem( + currentList, existingItem.cloneWith(newAmount: p.amount, newChanged: p.changed)); + } else { + var p = AddListItemResult.fromJson( + (await ShoppingListSync.addProduct(listId, i.name, null, i.amount, context)).body); + int sortOrder = 0; + if (shoppingItems.length > 0) sortOrder = shoppingItems.last.sortOrder + 1; + var newItem = + ShoppingItem(p.name, currentList.id, sortOrder, amount: i.amount, id: p.productId); + + listsProvider.addSingleItem(currentList, newItem); + } + + showInSnackBar( + "${i.amount}x ${i.name}${NSSLStrings.of(context).newProductAddedToList()}${currentList.name}"); + }, + ); + }, + ).toList(growable: false), ), ), ), diff --git a/lib/pages/change_password.dart b/lib/pages/change_password.dart index 89c375e..20177d2 100644 --- a/lib/pages/change_password.dart +++ b/lib/pages/change_password.dart @@ -49,14 +49,12 @@ class ChangePasswordPageState extends State { errorText: NSSLStrings.of(context).passwordEmptyError()); error = true; } - setState(() => {}); if (error == true) return; if (newPwInput.textEditingController.text != newPw2Input.textEditingController.text) { newPw2Input.decoration = InputDecoration( labelText: newPw2Input.decoration!.labelText, helperText: newPw2Input.decoration!.helperText, errorText: NSSLStrings.of(context).passwordsDontMatchError()); - setState(() => {}); return; } _changePassword(); @@ -73,8 +71,8 @@ class ChangePasswordPageState extends State { return; } var obj = Result.fromJson(res.body); - if (!obj.success!) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(obj.error!), duration: Duration(seconds: 3))); + if (!obj.success) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(obj.error), duration: Duration(seconds: 3))); return; } var dialog = AlertDialog( diff --git a/lib/pages/contributors.dart b/lib/pages/contributors.dart index a8797ef..9044400 100644 --- a/lib/pages/contributors.dart +++ b/lib/pages/contributors.dart @@ -4,8 +4,9 @@ import 'package:nssl/models/model_export.dart'; import 'package:nssl/server_communication//s_c.dart'; import 'dart:async'; import 'package:nssl/server_communication/return_classes.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class ContributorsPage extends StatefulWidget { +class ContributorsPage extends ConsumerStatefulWidget { ContributorsPage(this.listId, {Key? key, this.title}) : super(key: key); final String? title; final int listId; @@ -13,7 +14,7 @@ class ContributorsPage extends StatefulWidget { _ContributorsPagePageState createState() => new _ContributorsPagePageState(listId); } -class _ContributorsPagePageState extends State { +class _ContributorsPagePageState extends ConsumerState { final GlobalKey _mainScaffoldKey = GlobalKey(); GlobalKey _iff = GlobalKey(); GlobalKey _ib = GlobalKey(); @@ -35,7 +36,7 @@ class _ContributorsPagePageState extends State { return; } GetContributorsResult z = GetContributorsResult.fromJson(o.body); - if (!z.success! || z.contributors.length <= 0) + if (!z.success || z.contributors.length <= 0) showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + o.reasonPhrase!, duration: Duration(seconds: 10)); else @@ -69,8 +70,8 @@ class _ContributorsPagePageState extends State { Future _addContributor(String value) async { var o = await ShoppingListSync.addContributor(listId, value, context); AddContributorResult z = AddContributorResult.fromJson(o.body); - if (!z.success!) - showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + z.error!, duration: Duration(seconds: 10)); + if (!z.success) + showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + z.error, duration: Duration(seconds: 10)); else setState(() => conList.add(ContributorResult() ..name = z.name @@ -81,7 +82,8 @@ class _ContributorsPagePageState extends State { Widget buildBody() { bool? isAdmin = false; if (conList.length > 0) { - isAdmin = conList.firstWhere((x) => x.name!.toLowerCase() == User.username!.toLowerCase()).isAdmin; + var user = ref.watch(userProvider); + isAdmin = conList.firstWhere((x) => x.name!.toLowerCase() == user.username.toLowerCase()).isAdmin; var listView = ListView.builder( itemBuilder: (c, i) { return ListTile( @@ -89,7 +91,7 @@ class _ContributorsPagePageState extends State { (conList[i].isAdmin! ? NSSLStrings.of(context).contributorAdmin() : NSSLStrings.of(context).contributorUser())), - trailing: isAdmin! && conList[i].name!.toLowerCase() != User.username!.toLowerCase() + trailing: isAdmin! && conList[i].name!.toLowerCase() != user.username.toLowerCase() ? PopupMenuButton( padding: EdgeInsets.zero, onSelected: popupMenuClicked, @@ -142,8 +144,8 @@ class _ContributorsPagePageState extends State { var userId = int.parse(splitted[0]); var res = await ShoppingListSync.deleteContributor(listId, userId, context); var enres = Result.fromJson(res.body); - if (!enres.success!) - showInSnackBar(enres.error!); + if (!enres.success) + showInSnackBar(enres.error); else { showInSnackBar(conList.firstWhere((x) => x.userId == userId).name! + " was removed successfully"); setState(() => conList.removeWhere((x) => x.userId == userId)); @@ -153,8 +155,8 @@ class _ContributorsPagePageState extends State { var userId = int.parse(splitted[0]); var res = await ShoppingListSync.changeRight(listId, userId, context); var enres = Result.fromJson(res.body); - if (!enres.success!) - showInSnackBar(enres.error!); + if (!enres.success) + showInSnackBar(enres.error); else { ShoppingListSync.getContributors(listId, context).then((o) { if (o.statusCode == 500) { @@ -162,8 +164,8 @@ class _ContributorsPagePageState extends State { return; } GetContributorsResult z = GetContributorsResult.fromJson(o.body); - if (!z.success! || z.contributors.length <= 0) - showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + z.error!, + if (!z.success || z.contributors.length <= 0) + showInSnackBar(NSSLStrings.of(context).genericErrorMessageSnackbar() + z.error, duration: Duration(seconds: 10)); else conList.clear(); diff --git a/lib/pages/login.dart b/lib/pages/login.dart index fe8f5ad..e3e3c8a 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -2,12 +2,12 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:nssl/localization/nssl_strings.dart'; -import 'package:nssl/main.dart'; import 'package:nssl/models/model_export.dart'; import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/server_communication/s_c.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class LoginPage extends StatefulWidget { +class LoginPage extends ConsumerStatefulWidget { LoginPage({Key? key, this.scaffoldKey}) : super(key: key); final GlobalKey? scaffoldKey; @@ -29,7 +29,7 @@ class ForInput { FocusNode focusNode = FocusNode(); } -class LoginPageState extends State { +class LoginPageState extends ConsumerState { LoginPageState() : super(); GlobalKey _scaffoldKey = GlobalKey(); final GlobalKey _formKey = GlobalKey(); @@ -71,33 +71,33 @@ class LoginPageState extends State { } Future _handleLoggedIn(LoginResult res) async { - if (!res.success!) { - showInSnackBar(res.error!); + if (!res.success) { + showInSnackBar(res.error); return; } showInSnackBar(NSSLStrings.of(context).loginSuccessfulMessage()); - bool firstBoot = User.username == null; + var curUser = ref.read(userProvider); + + var userState = ref.watch(userStateProvider.notifier); + // var + bool firstBoot = curUser.ownId >= 0; User.token = res.token; - User.username = res.username; - User.eMail = res.eMail; - User.ownId = res.id; - await User.save(); - firebaseMessaging?.subscribeToTopic(res.username! + "userTopic"); + var user = User(res.id, res.username, res.eMail); + + firebaseMessaging?.subscribeToTopic(res.username + "userTopic"); + + var listController = ref.read(shoppingListsProvider); + await listController.reloadAllLists(context); + if (firstBoot) { - await _getAllListsInit(); - if (User.shoppingLists.length > 0) { - User.currentList = User.shoppingLists.first; - User.currentListIndex = 1; - await User.save(); + if (listController.shoppingLists.length > 0) { + var curListState = ref.read(currentListIndexProvider.notifier); + curListState.state = 1; } - runApp(NSSL()); - } else - Navigator.pop(context); - } + } - Future _getAllListsInit() async { - await ShoppingList.reloadAllLists(context); - setState(() => {}); + user.save(1); + userState.state = user; } String? _validateName(String? value) { @@ -192,7 +192,8 @@ class LoginPageState extends State { padding: const EdgeInsets.only(top: 40.0), child: TextButton( onPressed: () { - User.username == null + var userId = ref.read(userIdProvider); + userId == null || userId < 0 ? Navigator.pushNamed(context, "/registration") : Navigator.popAndPushNamed(context, "/registration"); }, diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 949108a..c132a94 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -13,27 +13,23 @@ import 'package:nssl/helper/simple_dialog_single_input.dart'; import 'package:flutter/material.dart'; import 'dart:async'; import 'package:nssl/localization/nssl_strings.dart'; -import 'package:nssl/firebase/cloud_messsaging.dart'; - +import 'package:nssl/helper/iterable_extensions.dart'; import '../main.dart'; import 'barcode_scanner_page.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -class MainPage extends StatefulWidget { +class MainPage extends ConsumerStatefulWidget { @override MainPageState createState() => MainPageState(); } -class MainPageState extends State with TickerProviderStateMixin, WidgetsBindingObserver { - BuildContext? cont; - +class MainPageState extends ConsumerState with TickerProviderStateMixin, WidgetsBindingObserver { final ScrollController _mainController = ScrollController(); final ScrollController _drawerController = ScrollController(); String? ean = ""; bool performanceOverlay = false; bool materialGrid = false; - bool isReorderingItems = false; AnimationController? _controller; Animation? _drawerContentsOpacity; @@ -45,7 +41,7 @@ class MainPageState extends State with TickerProviderStateMixin, Widge @override Future didChangeAppLifecycleState(AppLifecycleState state) async { if (state.index == 0) { - await Startup.loadMessagesFromFolder(setState); + await Startup.loadMessagesFromFolder(ref); } } @@ -54,7 +50,7 @@ class MainPageState extends State with TickerProviderStateMixin, Widge super.initState(); WidgetsBinding.instance.addObserver(this); Startup.deleteMessagesFromFolder(); - Startup.initializeNewListsFromServer().then((value) => {if (value) setState(() {})}); + Startup.initializeNewListsFromServer(ref); _controller = AnimationController( vsync: this, @@ -75,73 +71,59 @@ class MainPageState extends State with TickerProviderStateMixin, Widge @override Widget build(BuildContext context) { + var currentList = ref.watch(currentListProvider); return Scaffold( appBar: AppBar( title: Text( - User.currentList?.name ?? NSSLStrings.of(context).noListLoaded(), + currentList?.name ?? NSSLStrings.of(context).noListLoaded(), ), actions: _getMainDropdownActions(context)), body: ShoppingListWidget(this), - floatingActionButton: isReorderingItems ? acceptReordingFAB() : null, + floatingActionButton: acceptReordingFAB(), drawer: _buildDrawer(context), - persistentFooterButtons: isReorderingItems + persistentFooterButtons: ref.watch(_isReorderingProvider) || currentList == null ? [] : [ TextButton( child: Text(NSSLStrings.of(context).addPB()), onPressed: () => _addWithoutSearchDialog(context)) ] + (Platform.isAndroid - ? [TextButton(child: Text(NSSLStrings.of(context).scanPB()), onPressed: _getEAN)] + ? [TextButton(child: Text(NSSLStrings.of(context).scanPB()), onPressed: () => _getEAN(currentList))] : []) + [TextButton(child: Text(NSSLStrings.of(context).searchPB()), onPressed: search)]); } void _onReorderItems(int oldIndex, int newIndex) { - if (User.currentList == null) return; - - ShoppingItem? item = User.currentList!.shoppingItems![oldIndex]; - if (item?.crossedOut ?? false) return; - setState( - () { - item!.sortOrder = newIndex; - for (var old = oldIndex + 1; old < newIndex; old++) { - item = User.currentList!.shoppingItems![old]; - if (!item!.crossedOut) - User.currentList!.shoppingItems![old]!.sortOrder = User.currentList!.shoppingItems![old]!.sortOrder! - 1; - } - for (var newI = newIndex; newI < oldIndex; newI++) { - item = User.currentList!.shoppingItems![newI]; - if (!item!.crossedOut) - User.currentList!.shoppingItems![newI]!.sortOrder = User.currentList!.shoppingItems![newI]!.sortOrder! - 1; - } - }, - ); - } + var currentList = ref.watch(currentShoppingItemsProvider); - void sortAndOrderCrossedOut() { - final crossedOffset = 0xFFFFFFFF; - // setState(() { - for (var crossedOut - in User.currentList?.shoppingItems?.where((x) => x!.crossedOut && x.sortOrder! < crossedOffset) ?? - []) { - crossedOut?.sortOrder = crossedOut.sortOrder! + crossedOffset; - } - for (var notCrossedOut - in User.currentList?.shoppingItems?.where((x) => !x!.crossedOut && x.sortOrder! > crossedOffset) ?? - []) { - notCrossedOut!.sortOrder = notCrossedOut.sortOrder! - crossedOffset; - } - // }); - } + if (currentList.isEmpty) return; + + ShoppingItem olditem = currentList[oldIndex]; + currentList.sort((a, b) => a.sortOrder.compareTo(b.sortOrder)); - void updateOrderIndiciesAndSave({bool syncToServer = false}) async { - var i = 1; - for (var item in User.currentList?.shoppingItems ?? []) { - item?.sortOrder = i; - i++; + currentList.remove(olditem); + if (newIndex > oldIndex) { + currentList.insert(newIndex - 1, olditem); + } else + currentList.insert(newIndex, olditem); + + var newList = []; + int currentSortOrder = 0; + for (int i = 0; i < currentList.length; i++) { + var currItem = currentList[i]; + if (i < oldIndex && i < newIndex) { + newList.add(currItem); + currentSortOrder = currentList[i].sortOrder; + } else if (i >= oldIndex || i >= newIndex) { + newList.add(currItem.cloneWith(newSortOrder: ++currentSortOrder)); + } } - sortAndOrderCrossedOut(); - User.currentList?.save(); + + var shoppingState = ref.watch(shoppingItemsProvider.notifier); + var newState = shoppingState.state.toList(); + newState.removeElements(currentList); + newState.addAll(newList); + shoppingState.state = newState; } void showInSnackBar(String value, {Duration? duration, SnackBarAction? action}) { @@ -154,33 +136,33 @@ class MainPageState extends State with TickerProviderStateMixin, Widge .showSnackBar(SnackBar(content: Text(value), duration: duration ?? Duration(seconds: 3), action: action)); } - Future register() => Navigator.pushNamed(cont!, "/registration"); + Future register() => Navigator.pushNamed(context, "/registration"); - Future search() => Navigator.pushNamed(cont!, "/search"); + Future search() => Navigator.pushNamed(context, "/search"); - Future login() => Navigator.pushNamed(cont!, "/login"); + Future login() => Navigator.pushNamed(context, "/login"); - Future addProduct() => Navigator.pushNamed(cont!, "/addProduct"); + Future addProduct() => Navigator.pushNamed(context, "/addProduct"); void handleDismissMain(DismissDirection dir, ShoppingItem s) async { - var list = User.currentList; + var list = ref.watch(currentListProvider); + + if (list == null) return; + var listProvider = ref.read(shoppingListsProvider); + final String action = (dir == DismissDirection.endToStart) ? NSSLStrings.of(context).archived() : NSSLStrings.of(context).deleted(); - var index = list!.shoppingItems!.indexOf(s); - await list.deleteSingleItem(s); - setState(() {}); + await listProvider.deleteSingleItem(list, s); + ShoppingListSync.deleteProduct(list.id, s.id, context); - updateOrderIndiciesAndSave(); + showInSnackBar(NSSLStrings.of(context).youHaveActionItemMessage() + "${s.name} $action", action: SnackBarAction( label: NSSLStrings.of(context).undo(), onPressed: () { - setState(() { - list.addSingleItem(s, index: index); - ShoppingListSync.changeProductAmount(list.id, s.id, s.amount, context); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - updateOrderIndiciesAndSave(); - }); + listProvider.addSingleItem(list, s); + ShoppingListSync.changeProductAmount(list.id, s.id, s.amount, context); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); }), duration: Duration(seconds: 10)); } @@ -190,11 +172,11 @@ class MainPageState extends State with TickerProviderStateMixin, Widge case "Login/Register": login(); break; - case "Options": + case "options": await Navigator.push( - cont!, + context, MaterialPageRoute( - builder: (BuildContext context) => CustomThemePage(), + builder: (BuildContext context) => SettingsPage(), fullscreenDialog: true, )) .whenComplete(() => AdaptiveTheme.of(context) @@ -214,28 +196,30 @@ class MainPageState extends State with TickerProviderStateMixin, Widge break; case "ChangePassword": Navigator.push( - cont!, + context, MaterialPageRoute( builder: (BuildContext context) => ChangePasswordPage(), fullscreenDialog: true, )); break; case "reorderItems": - setState(() => isReorderingItems = !isReorderingItems); + var reordering = ref.watch(_isReorderingProvider.notifier); + reordering.state = !reordering.state; break; } } - void changeCurrentList(int index) => setState(() { - setState(() => User.currentList = User.shoppingLists[index]); - User.currentListIndex = User.shoppingLists[index].id; - User.save(); - Navigator.of(context).pop(); - }); + void changeCurrentList(int index) { + var currList = ref.watch(currentListIndexProvider.notifier); + currList.state = index; + var currUser = ref.read(userProvider); + currUser.save(index); + Navigator.of(context).pop(); + } - Future _getEAN() async { + Future _getEAN(ShoppingList currentList) async { ean = await Navigator.push( - cont!, + context, MaterialPageRoute( builder: (BuildContext context) => BarcodeScannerScreen(), fullscreenDialog: true, @@ -243,34 +227,34 @@ class MainPageState extends State with TickerProviderStateMixin, Widge if (ean == null || ean == "" || ean == "Permissions denied") return; - var list = User.currentList; - var firstRequest = await ProductSync.getProduct(ean, cont); + var firstRequest = await ProductSync.getProduct(ean, context); var z = jsonDecode((firstRequest).body); var k = ProductAddPage.fromJson(z); - if (k.success!) { + if (k.success) { RegExp reg = RegExp("([0-9]+[.,]?[0-9]*(\\s)?[gkmlGKML]{1,2})"); String? name = reg.hasMatch(k.name!) ? k.name : "${k.name} ${k.quantity}${k.unit}"; - var item = list?.shoppingItems?.firstWhere((x) => x!.name == name, orElse: () => null); - ShoppingItem afterAdd; + var shoppingItems = ref.read(shoppingItemsPerListProvider.create(currentList.id)); + var item = shoppingItems.firstOrNull((x) => x.name == name); if (item != null) { - var answer = await ShoppingListSync.changeProductAmount(list!.id, item.id, 1, cont); + var answer = await ShoppingListSync.changeProductAmount(currentList.id, item.id, 1, context); var p = ChangeListItemResult.fromJson((answer).body); - setState(() { - item.amount = p.amount; - item.changed = p.changed; - }); + var newItem = item.cloneWith(newAmount: p.amount, newChanged: p.changed); + item.exchange(newItem, ref); } else { - var p = AddListItemResult.fromJson((await ShoppingListSync.addProduct(list!.id, name, '-', 1, cont)).body); - afterAdd = ShoppingItem("${p.name}") - ..amount = 1 - ..id = p.productId; - setState(() { - list.shoppingItems!.add(afterAdd); - updateOrderIndiciesAndSave(); - }); + var p = + AddListItemResult.fromJson((await ShoppingListSync.addProduct(currentList.id, name, '-', 1, context)).body); + + var items = ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + int sortOrder = 0; + if (shoppingItems.length > 0) sortOrder = shoppingItems.last.sortOrder + 1; + newState.add(ShoppingItem(p.name, currentList.id, sortOrder, amount: 1, id: p.productId)); + items.state = newState; } - list.save(); + var provider = ref.read(shoppingListsProvider); + provider.save(currentList); + return; } Navigator.push( @@ -287,12 +271,12 @@ class MainPageState extends State with TickerProviderStateMixin, Widge title: NSSLStrings.of(context).addNewListTitle(), context: context); - showDialog(builder: (BuildContext context) => sd, context: cont!, barrierDismissible: false); + showDialog(builder: (BuildContext context) => sd, context: context, barrierDismissible: false); } Future renameListDialog(int listId) { return showDialog( - context: cont!, + context: context, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogSingleInput.create( hintText: NSSLStrings.of(context).renameListHint(), @@ -303,23 +287,26 @@ class MainPageState extends State with TickerProviderStateMixin, Widge } Future createNewList(String listName) async { - var res = await ShoppingListSync.addList(listName, cont); + var provider = ref.read(shoppingListsProvider); + var currentListProvider = ref.watch(currentListIndexProvider.notifier); + var res = await ShoppingListSync.addList(listName, context); var newListRes = AddListResult.fromJson(res.body); var newList = ShoppingList(newListRes.id, newListRes.name); - setState(() => User.shoppingLists.add(newList)); - changeCurrentList(User.shoppingLists.indexOf(newList)); - firebaseMessaging?.subscribeToTopic(newList.id.toString() + "shoppingListTopic"); - newList.save(); + provider.addList(newList); + + currentListProvider.state = provider.shoppingLists.indexOf(newList); + provider.save(newList); } Widget _buildDrawer(BuildContext context) { + var user = ref.watch(userProvider); var isDarkTheme = AdaptiveTheme.of(context).mode == AdaptiveThemeMode.dark; var userheader = UserAccountsDrawerHeader( - accountName: Text(User.username ?? NSSLStrings.of(context).notLoggedInYet()), - accountEmail: Text(User.eMail ?? NSSLStrings.of(context).notLoggedInYet()), + accountName: Text(user.username == "" ? NSSLStrings.of(context).notLoggedInYet() : user.username), + accountEmail: Text(user.eMail == "" ? NSSLStrings.of(context).notLoggedInYet() : user.username), currentAccountPicture: CircleAvatar( child: Text( - User.username?.substring(0, 2).toUpperCase() ?? "", + user.username.substring(0, 2).toUpperCase(), style: TextStyle(color: isDarkTheme ? Colors.black : Colors.white), ), backgroundColor: isDarkTheme @@ -330,13 +317,13 @@ class MainPageState extends State with TickerProviderStateMixin, Widge _showDrawerContents ? _controller!.reverse() : _controller!.forward(); }, ); - - var list = User.shoppingLists.isNotEmpty - ? User.shoppingLists + var shoppingListsController = ref.watch(shoppingListsProvider); + var list = shoppingListsController.shoppingLists.isNotEmpty + ? shoppingListsController.shoppingLists .map((x) => ListTile( - title: Text(x.name ?? ""), - onTap: () => - changeCurrentList(User.shoppingLists.indexOf(User.shoppingLists.firstWhere((y) => y.id == x.id))), + title: Text(x.name), + onTap: () => changeCurrentList(shoppingListsController.shoppingLists + .indexOf(shoppingListsController.shoppingLists.firstWhere((y) => y.id == x.id))), trailing: PopupMenuButton( padding: EdgeInsets.zero, onSelected: (v) async => await drawerListItemMenuClicked(v), @@ -384,11 +371,13 @@ class MainPageState extends State with TickerProviderStateMixin, Widge : [ ListTile(title: Text(NSSLStrings.of(context).noListsInDrawerMessage())), ]; + var emptyListTiles = []; for (int i = 0; i < list.length - 2; i++) emptyListTiles.add(ListTile( title: const Text(("")), )); + var d = Scaffold( body: RefreshIndicator( child: ListView( @@ -448,11 +437,14 @@ class MainPageState extends State with TickerProviderStateMixin, Widge } Future _logout() async { - await User.delete(); - User.username = null; - User.eMail = null; - User.token = null; - runApp(NSSL()); + var user = ref.read(userProvider); + + await user.delete(); + var userState = ref.watch(userStateProvider.notifier); + userState.state = User.empty; + + var restartState = ref.watch(appRestartProvider.notifier); + restartState.state = restartState.state + 1; } Future drawerListItemMenuClicked(String value) async { @@ -467,71 +459,69 @@ class MainPageState extends State with TickerProviderStateMixin, Widge break; case "BoughtList": await Navigator.push( - cont!, + context, MaterialPageRoute( builder: (BuildContext context) => BoughtItemsPage(id), fullscreenDialog: true, )); - setState(() {}); break; case "Rename": renameListDialog(id); break; case "Remove": - var deleteList = User.shoppingLists.firstWhere((x) => x.id == id); + var deleteList = ref.read(shoppingListByIdProvider.create(id)); + if (deleteList == null) return; + var cont = context; showDialog( - context: cont!, + context: context, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogAcceptDeny.create( - title: NSSLStrings.of(context).deleteListTitle() + deleteList.name!, + title: NSSLStrings.of(context).deleteListTitle() + deleteList.name, text: NSSLStrings.of(context).deleteListText(), onSubmitted: (s) async { - var res = Result.fromJson((await ShoppingListSync.deleteList(id, cont)).body); - if (!(res.success ?? false)) - showInDrawerSnackBar(res.error!); + var res = Result.fromJson((await ShoppingListSync.deleteList(id, context)).body); + if (!(res.success)) + showInDrawerSnackBar(res.error); else { - if (User.currentList!.id! == id) { - changeCurrentList(User.shoppingLists.indexOf(User.shoppingLists.firstWhere((l) => l.id != id))); + var currentList = ref.read(currentListProvider)!; + var shoppingListController = ref.read(shoppingListsProvider); + if (currentList.id == id) { + changeCurrentList(shoppingListController.shoppingLists + .indexOf(shoppingListController.shoppingLists.firstWhere((l) => l.id != id))); } - setState(() => User.shoppingLists.removeWhere((x) => x.id == id)); - showInDrawerSnackBar(deleteList.name! + " " + NSSLStrings.of(cont!).removed()); + shoppingListController.removeList(deleteList.id); + showInDrawerSnackBar(deleteList.name + " " + NSSLStrings.of(cont).removed()); } }, context: context)); break; case "Auto-Sync": - var list = User.shoppingLists.firstWhere((x) => x.id == id); - list.messagingEnabled ? list.unsubscribeFromFirebaseMessaging() : list.subscribeForFirebaseMessaging(); - list.messagingEnabled = !list.messagingEnabled; - list.save(); + var shoppingListController = ref.read(shoppingListsProvider); + shoppingListController.toggleFirebaseMessaging(id); + break; case "ExportAsPdf": - ExportManager.exportAsPDF(User.shoppingLists.firstWhere((x) => x.id == id), context); + ExportManager.exportAsPDF( + ref.read(shoppingListByIdProvider.create(id))!, ref.read(shoppingItemsPerListProvider.create(id)), context); break; } } Future _handleDrawerRefresh() async { - await ShoppingList.reloadAllLists(context); - setState(() => {}); + await ref.read(shoppingListsProvider).reloadAllLists(); } - Future _handleMainListRefresh() => _handleListRefresh(User.currentList!.id); + Future _handleMainListRefresh(int id) => _handleListRefresh(id); - Future _handleListRefresh(int? listId) async { - await User.shoppingLists.firstWhere((s) => s.id == listId).refresh(cont); - setState(() {}); + Future _handleListRefresh(int listId) async { + await ref.read(shoppingListsProvider).refresh(ref.read(shoppingListByIdProvider.create(listId))!); } Future shoppingItemChange(ShoppingItem s, int change) async { var res = ChangeListItemResult.fromJson( - (await ShoppingListSync.changeProductAmount(User.currentList!.id!, s.id, change, cont)).body); - setState(() { - s.id = res.id; - s.amount = res.amount; - s.name = res.name; - s.changed = res.changed; - }); + (await ShoppingListSync.changeProductAmount(s.listId, s.id, change, context)).body); + if (!res.success) return; + s.exchange(s.cloneWith(newAmount: res.amount, newChanged: res.changed), ref); } var amountPopList = >[]; @@ -543,12 +533,11 @@ class MainPageState extends State with TickerProviderStateMixin, Widge } Future crossOutMainListItem(ShoppingItem x) async { - setState(() => x.crossedOut = !x.crossedOut); - await User.currentList?.save(); - - if (!isReorderingItems) { - sortAndOrderCrossedOut(); - } + var newItem = x.cloneWith(newCrossedOut: !x.crossedOut); + x.exchange(newItem, ref); + var provider = ref.read(shoppingListsProvider); + var currentList = ref.read(currentListProvider); + if (currentList != null) provider.save(currentList); } void _addWithoutSearchDialog(BuildContext extContext) { @@ -564,108 +553,136 @@ class MainPageState extends State with TickerProviderStateMixin, Widge } Future renameList(int id, String text) async { - var put = await ShoppingListSync.changeLName(id, text, cont); + var put = await ShoppingListSync.changeLName(id, text, context); showInDrawerSnackBar("${put.statusCode}" + put.reasonPhrase!); var res = Result.fromJson((put.body)); - if (!res.success!) showInDrawerSnackBar(res.error!); + if (!res.success) showInDrawerSnackBar(res.error); + var listsProvider = ref.read(shoppingListsProvider); + listsProvider.rename(id, text); } Future _addWithoutSearch(String value) async { - var list = User.currentList; - var same = list!.shoppingItems!.where((x) => x!.name!.toLowerCase() == value.toLowerCase()); - if (same.length > 0) { - var res = await ShoppingListSync.changeProductAmount(list.id, same.first!.id!, 1, cont); + var list = ref.read(currentListProvider); + if (list == null) return; + var shoppingItems = ref.read(currentShoppingItemsProvider); + + var same = shoppingItems.firstOrNull((x) => x.name.toLowerCase() == value.toLowerCase()); + if (same != null) { + var res = await ShoppingListSync.changeProductAmount(list.id, same.id, 1, context); if (res.statusCode != 200) showInSnackBar(res.reasonPhrase!); var product = ChangeListItemResult.fromJson(res.body); - if (!product.success!) showInSnackBar(product.error!); - setState(() { - same.first!.amount = product.amount; - same.first!.changed = product.changed; - }); - same.first; + if (!product.success) showInSnackBar(product.error); + same.exchange( + same.cloneWith( + newAmount: product.amount, + newChanged: product.changed, + newId: product.id, + newName: product.name, + newListId: product.listId), + ref); } else { - var res = await ShoppingListSync.addProduct(list.id, value, null, 1, cont); + var res = await ShoppingListSync.addProduct(list.id, value, null, 1, context); if (res.statusCode != 200) showInSnackBar(res.reasonPhrase!); var product = AddListItemResult.fromJson(res.body); - if (!product.success!) showInSnackBar(product.error!); - setState(() => list.shoppingItems!.add(ShoppingItem(product.name) - ..id = product.productId - ..amount = 1 - ..crossedOut = false)); - updateOrderIndiciesAndSave(); + if (!product.success) showInSnackBar(product.error); + var sips = ref.watch(shoppingItemsProvider.notifier); + var newState = sips.state.toList(); + var order = 0; + if (shoppingItems.length > 0) order = shoppingItems.last.sortOrder + 1; + + newState.add(ShoppingItem(product.name, list.id, order, id: product.productId, amount: 1, crossedOut: false)); + sips.state = newState; } + var listProv = ref.watch(shoppingListsProvider); + listProv.save(list); } Future _deleteCrossedOutItems() async { - var list = User.currentList; - var sublist = list!.shoppingItems!.where((s) => s!.crossedOut).toList(); - var res = await ShoppingListSync.deleteProducts(list.id, sublist.map((s) => s!.id).toList(), cont); - if (!Result.fromJson(res.body).success!) return; - setState(() { - for (var item in sublist) list.shoppingItems?.remove(item); - }); - updateOrderIndiciesAndSave(); + var list = ref.read(currentListProvider); + if (list == null) return; + var shoppingList = ref.read(currentShoppingItemsProvider); + + var sublist = shoppingList.where((s) => s.crossedOut).toList(); + var res = await ShoppingListSync.deleteProducts(list.id, sublist.map((s) => s.id).toList(), context); + if (!Result.fromJson(res.body).success) return; + var shoppingItemsState = ref.watch(shoppingItemsProvider.notifier); + var newState = shoppingItemsState.state.toList(); + + newState.removeElements(sublist); + + shoppingItemsState.state = newState; + var listProv = ref.watch(shoppingListsProvider); + listProv.save(list); showInSnackBar(NSSLStrings.of(context).messageDeleteAllCrossedOut(), duration: Duration(seconds: 10), action: SnackBarAction( label: NSSLStrings.of(context).undo(), onPressed: () async { var res = await ShoppingListSync.changeProducts( - list.id, sublist.map((s) => s!.id).toList(), sublist.map((s) => s!.amount).toList(), cont); + list.id, sublist.map((s) => s.id).toList(), sublist.map((s) => s.amount).toList(), context); var hashResult = HashResult.fromJson(res.body); int ownHash = 0; - for (var item in sublist) ownHash += item!.id! + item.amount; + for (var item in sublist) ownHash += item.id + item.amount; if (ownHash == hashResult.hash) { - setState(() => list.shoppingItems?.addAll(sublist)); - updateOrderIndiciesAndSave(); - list.save(); + var shoppingItemsState = ref.watch(shoppingItemsProvider.notifier); + var newState = shoppingItemsState.state.toList(); + newState.addAll(sublist); + shoppingItemsState.state = newState; + var listProv = ref.watch(shoppingListsProvider); + listProv.save(list); } else _handleListRefresh(list.id); })); } - renameListItem(ShoppingItem? x) { + renameListItem(ShoppingItem shoppingItem) { showDialog( - context: cont!, + context: context, barrierDismissible: false, builder: (BuildContext context) => SimpleDialogSingleInput.create( context: context, title: NSSLStrings.of(context).renameListItem(), hintText: NSSLStrings.of(context).renameListHint(), labelText: NSSLStrings.of(context).renameListItemLabel(), - defaultText: x?.name ?? "", + defaultText: shoppingItem.name, maxLines: 2, onSubmitted: (s) async { + var currentList = ref.read(currentListProvider); + if (currentList == null) return; + var res = ChangeListItemResult.fromJson( - (await ShoppingListSync.changeProductName(User.currentList!.id, x!.id, s, cont)).body); - setState(() { - x.id = res.id; - x.amount = res.amount; - x.name = res.name; - x.changed = res.changed; - }); + (await ShoppingListSync.changeProductName(currentList.id, shoppingItem.id, s, context)).body); + + var items = ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + var item = newState.firstWhere((x) => x.id == shoppingItem.id); + newState.remove(item); + newState.add( + item.cloneWith(newName: res.name), + ); + items.state = newState; })); } - Widget acceptReordingFAB() => FloatingActionButton( - child: Icon( - Icons.check, - ), - onPressed: () async { - var ids = []; - ids.addAll(User.currentList!.shoppingItems!.map((e) => e!.clone())); - ids.forEach((element) { - if (element.sortOrder! > 0xffffffff) element.sortOrder = element.sortOrder! - 0xffffffff; - }); - ids.sort((x, y) => x.sortOrder!.compareTo(y.sortOrder!)); - await ShoppingListSync.reorderProducts(User.currentList!.id, ids.map((e) => e.id).toList(), context); - setState(() { - isReorderingItems = false; - }); - }, - ); + Widget? acceptReordingFAB() { + var isReordering = ref.watch(_isReorderingProvider); + if (!isReordering) return null; + return FloatingActionButton( + child: Icon( + Icons.check, + ), + onPressed: () async { + var reorderingState = ref.watch(_isReorderingProvider.notifier); + reorderingState.state = false; + var currentList = ref.read(currentListProvider); + var ids = ref.read(currentShoppingItemsProvider); + await ShoppingListSync.reorderProducts(currentList!.id, ids.map((e) => e.id).toList(), context); + }, + ); + } List _getMainDropdownActions(BuildContext context) { + var isReorderingItems = ref.watch(_isReorderingProvider); if (isReorderingItems) return []; return [ @@ -719,17 +736,40 @@ class ShoppingListWidget extends ConsumerWidget { final MainPageState mainPageState; const ShoppingListWidget(this.mainPageState, {Key? key}) : super(key: key); + void updateOrderIndiciesAndSave(ShoppingList currentList, List shoppingItems, WidgetRef ref) async { + // var newItems = []; + // var curSortOrder = 0; + // for (var i = 0; i < shoppingItems.length; i++) { + // var curItem = shoppingItems[i]; + // if (curItem.sortWithOffset > curSortOrder) + // newItems.add(curItem); + // else + // newItems.add(curItem.cloneWith(newSortOrder: ++curSortOrder)); + // } + // var itemsState = ref.watch(shoppingItemsProvider.notifier); + // var newState = itemsState.state.toList(); + // newState.removeElements(shoppingItems); + // newState.addAll(newItems); + // itemsState.state = newState; + + // var listProvider = ref.read(shoppingListsProvider); + // listProvider.save(currentList); + } + @override Widget build(BuildContext context, WidgetRef ref) { - if (User.currentList == null || User.currentList!.shoppingItems == null) return const Text(""); - if (User.currentList!.shoppingItems!.any((item) => item?.sortOrder == null)) - mainPageState.updateOrderIndiciesAndSave(); + var currentList = ref.watch(currentListProvider); + if (currentList == null) return const Text(""); + var shoppingItems = ref.watch(currentShoppingItemsProvider); + if (shoppingItems.isEmpty) return const Text(""); + + if (shoppingItems.any((item) => item.sortOrder == -1)) updateOrderIndiciesAndSave(currentList, shoppingItems, ref); - User.currentList!.shoppingItems!.sort((a, b) => a!.sortOrder!.compareTo(b!.sortOrder!)); + shoppingItems.sort((a, b) => a.sortWithOffset.compareTo(b.sortWithOffset)); var lv; - if (User.currentList!.shoppingItems!.length > 0) { + if (shoppingItems.length > 0) { final isReorderingItems = ref.watch(_isReorderingProvider); - var mainList = User.currentList!.shoppingItems!.map((x) { + var mainList = shoppingItems.map((x) { return getListTileForShoppingItem(x, isReorderingItems, context); }).toList(growable: true); @@ -759,12 +799,12 @@ class ShoppingListWidget extends ConsumerWidget { ); return RefreshIndicator( child: lv, - onRefresh: mainPageState._handleMainListRefresh, + onRefresh: () => mainPageState._handleMainListRefresh(currentList.id), ); } Widget getListTileForShoppingItem(ShoppingItem? x, bool isReorderingItems, BuildContext context) { - if (x == null || x.name == null) return Text("Null"); + if (x == null || x.name == "") return Text("Null"); // return Text(x.name!); var lt = ListTile( @@ -772,7 +812,7 @@ class ShoppingListWidget extends ConsumerWidget { title: Wrap( children: [ Text( - x.name ?? "", + x.name, maxLines: 2, softWrap: true, style: TextStyle(decoration: x.crossedOut ? TextDecoration.lineThrough : TextDecoration.none), diff --git a/lib/pages/product_add_to_database.dart b/lib/pages/product_add_to_database.dart index 6de38f0..c0aa26c 100644 --- a/lib/pages/product_add_to_database.dart +++ b/lib/pages/product_add_to_database.dart @@ -4,9 +4,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/models/model_export.dart'; -import 'package:nssl/models/user.dart'; import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/server_communication/s_c.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; enum DismissDialogAction { cancel, @@ -14,7 +14,7 @@ enum DismissDialogAction { save, } -class AddProductToDatabase extends StatefulWidget { +class AddProductToDatabase extends ConsumerStatefulWidget { AddProductToDatabase(this.gtin); final String? gtin; @@ -22,7 +22,7 @@ class AddProductToDatabase extends StatefulWidget { AddProductToDatabaseState createState() => AddProductToDatabaseState(gtin); } -class AddProductToDatabaseState extends State { +class AddProductToDatabaseState extends ConsumerState { AddProductToDatabaseState(this.gtin); final GlobalKey _scaffoldKey = GlobalKey(); final GlobalKey _formKey = GlobalKey(); @@ -100,28 +100,31 @@ class AddProductToDatabaseState extends State { return false; } var res = ProductResult.fromJson(first.body); - if (!res.success!) - showInSnackBar(res.error!); + if (!res.success) + showInSnackBar(res.error); else { showInSnackBar(NSSLStrings.of(context).successful()); if (putInList) { - var list = User.currentList!; + var list = ref.read(currentListProvider)!; var pres = AddListItemResult.fromJson( (await ShoppingListSync.addProduct(list.id, "$productName $brandName $weight", gtin, 1, context)).body); - if (!pres.success!) - showInSnackBar(pres.error!); + if (!pres.success) + showInSnackBar(pres.error); else { - setState(() { - list.shoppingItems!.add(ShoppingItem(pres.name) - ..amount = 1 - ..id = pres.productId); - }); + var listController = ref.read(shoppingListsProvider); + var shoppingItems = ref.read(currentShoppingItemsProvider); + + int sortOrder = 0; + if (shoppingItems.length > 0) sortOrder = shoppingItems.last.sortOrder + 1; + + listController.addSingleItem( + list, ShoppingItem(pres.name, list.id, sortOrder, amount: 1, id: pres.productId)); } + _isSendToServer = false; + Navigator.of(context).pop(); } _isSendToServer = false; - Navigator.of(context).pop(); } - _isSendToServer = false; return true; } } diff --git a/lib/pages/registration.dart b/lib/pages/registration.dart index 3f0313a..67738fd 100644 --- a/lib/pages/registration.dart +++ b/lib/pages/registration.dart @@ -7,8 +7,9 @@ import 'package:nssl/server_communication/s_c.dart'; import 'package:flutter/material.dart'; import 'package:nssl/models/model_export.dart'; import 'login.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class Registration extends StatefulWidget { +class Registration extends ConsumerStatefulWidget { Registration({Key? key}) : super(key: key); static const String routeName = '/Registration'; @@ -17,7 +18,7 @@ class Registration extends StatefulWidget { RegistrationState createState() => RegistrationState(); } -class RegistrationState extends State { +class RegistrationState extends ConsumerState { final GlobalKey _scaffoldKey = GlobalKey(); final GlobalKey _formKey = GlobalKey(); @@ -49,8 +50,8 @@ class RegistrationState extends State { return; else { var response = LoginResult.fromJson(res.body); - if (!response.success!) { - showInSnackBar(response.error!); + if (!response.success) { + showInSnackBar(response.error); return; } showInSnackBar(NSSLStrings.of(context).registrationSuccessfulMessage()); @@ -61,21 +62,22 @@ class RegistrationState extends State { return; } var loginRes = LoginResult.fromJson(x.body); + var userState = ref.watch(userStateProvider.notifier); User.token = loginRes.token; - User.username = response.username; - User.eMail = response.eMail; + var user = User(loginRes.id, loginRes.username, loginRes.eMail); + userState.state = user; + await user.save(0); - await User.save(); - Navigator.pop(context); - runApp(NSSL()); + // Navigator.pop(context); + var restartState = ref.watch(appRestartProvider.notifier); + restartState.state = restartState.state + 1; } } String? _validateName(String? value) { if (value!.isEmpty) return NSSLStrings.of(context).usernameEmptyError(); - else if (value.length < 4) - return NSSLStrings.of(context).usernameToShortError(); + else if (value.length < 4) return NSSLStrings.of(context).usernameToShortError(); return null; } @@ -83,22 +85,18 @@ class RegistrationState extends State { if (value!.isEmpty) return NSSLStrings.of(context).emailEmptyError(); RegExp email = RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); - if (!email.hasMatch(value)) - return NSSLStrings.of(context).emailIncorrectFormatError(); + if (!email.hasMatch(value)) return NSSLStrings.of(context).emailIncorrectFormatError(); return null; } String? _validatePassword(String? value) { - if (pwInput.textEditingController.text.isEmpty) - return NSSLStrings.of(context).chooseAPasswordPrompt(); + if (pwInput.textEditingController.text.isEmpty) return NSSLStrings.of(context).chooseAPasswordPrompt(); return null; } String? _validatePassword2(String? value) { - if (pwInput.textEditingController.text.isEmpty) - return NSSLStrings.of(context).reenterPasswordPrompt(); - if (pwInput.textEditingController.text != value) - return NSSLStrings.of(context).passwordsDontMatchError(); + if (pwInput.textEditingController.text.isEmpty) return NSSLStrings.of(context).reenterPasswordPrompt(); + if (pwInput.textEditingController.text != value) return NSSLStrings.of(context).passwordsDontMatchError(); return null; } @@ -107,8 +105,7 @@ class RegistrationState extends State { _resetInput(); return Scaffold( key: _scaffoldKey, - appBar: AppBar( - title: Text(NSSLStrings.of(context).registrationTitle())), + appBar: AppBar(title: Text(NSSLStrings.of(context).registrationTitle())), body: Form( key: _formKey, autovalidateMode: validateMode, @@ -170,8 +167,7 @@ class RegistrationState extends State { alignment: const FractionalOffset(0.5, 0.5), child: ElevatedButton( child: Center( - child: Text( - NSSLStrings.of(context).registerButton()), + child: Text(NSSLStrings.of(context).registerButton()), ), onPressed: _handleSubmitted, ), @@ -198,16 +194,13 @@ class RegistrationState extends State { _resetInput() { nameInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context).usernameRegisterHint(), - labelText: NSSLStrings.of(context).username()); + helperText: NSSLStrings.of(context).usernameRegisterHint(), labelText: NSSLStrings.of(context).username()); emailInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context).emailRegisterHint(), - labelText: NSSLStrings.of(context).emailTitle()); + helperText: NSSLStrings.of(context).emailRegisterHint(), labelText: NSSLStrings.of(context).emailTitle()); pwInput.decoration = InputDecoration( - helperText: NSSLStrings.of(context).passwordRegisterHint(), - labelText: NSSLStrings.of(context).password()); + helperText: NSSLStrings.of(context).passwordRegisterHint(), labelText: NSSLStrings.of(context).password()); pw2Input.decoration = InputDecoration( helperText: NSSLStrings.of(context).retypePasswordHint(), diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 9fd7bb3..4a76c4f 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/options/themes.dart'; import 'package:nssl/pages/pages.dart'; -import 'package:nssl/pages/product_add_to_database.dart'; class SettingsPage extends StatefulWidget { SettingsPage(); diff --git a/lib/pages/shopping_item_search.dart b/lib/pages/shopping_item_search.dart index 24e8df4..12026a6 100644 --- a/lib/pages/shopping_item_search.dart +++ b/lib/pages/shopping_item_search.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:nssl/helper/iterable_extensions.dart'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/models/model_export.dart'; import 'package:nssl/server_communication//s_c.dart'; @@ -6,8 +7,9 @@ import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart'; import 'package:nssl/server_communication/return_classes.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class ProductAddPage extends StatefulWidget { +class ProductAddPage extends ConsumerStatefulWidget { ProductAddPage({Key? key, this.title}) : super(key: key); final String? title; @@ -27,7 +29,7 @@ class ProductAddPage extends StatefulWidget { } } -class _ProductAddPageState extends State { +class _ProductAddPageState extends ConsumerState { final GlobalKey _mainScaffoldKey = GlobalKey(); GlobalKey _iff = GlobalKey(); GlobalKey _ib = GlobalKey(); @@ -36,47 +38,48 @@ class _ProductAddPageState extends State { int k = 1; Future _addProductToList(String? name, String? gtin) async { - var list = User.currentList; + var list = ref.read(currentListProvider); if (list != null) { - if (list.shoppingItems == null) list.shoppingItems = []; - - var item = list.shoppingItems!.firstWhere((x) => x!.name == name, orElse: () => null); + var siState = ref.watch(shoppingItemsProvider.notifier); + var shoppingItems = siState.state.toList(); + var item = shoppingItems.firstOrNull((x) => x.name == name); ShoppingItem? afterAdd; if (item != null) { - var answer = await ShoppingListSync.changeProductAmount(list.id!, item.id!, 1, context); + var answer = await ShoppingListSync.changeProductAmount(list.id, item.id, 1, context); var p = ChangeListItemResult.fromJson((answer).body); - setState(() { - item.amount = p.amount; - item.changed = p.changed; - }); + shoppingItems.remove(item); + afterAdd = item.cloneWith(newAmount: p.amount, newChanged: p.changed); } else { var p = AddListItemResult.fromJson( - (await ShoppingListSync.addProduct(list.id!, name!, gtin ?? '-', 1, context)).body); - afterAdd = ShoppingItem(p.name) - ..amount = 1 - ..id = p.productId; - setState(() => list.shoppingItems!.add(afterAdd)); + (await ShoppingListSync.addProduct(list.id, name!, gtin ?? '-', 1, context)).body); + int sortOrder = 0; + if (shoppingItems.length > 0) sortOrder = shoppingItems.last.sortOrder + 1; + afterAdd = ShoppingItem(p.name, list.id, sortOrder, amount: 1, id: p.productId); } + shoppingItems.add(afterAdd); + siState.state = shoppingItems; + showInSnackBar( - item == null - ? NSSLStrings.of(context).addedProduct() + "$name" - : "$name" + NSSLStrings.of(context).productWasAlreadyInList(), - duration: Duration(seconds: item == null ? 2 : 4), - action: SnackBarAction( - label: NSSLStrings.of(context).undo(), - onPressed: () async { - var res = item == null - ? await ShoppingListSync.deleteProduct(list.id!, afterAdd!.id!, context) - : await ShoppingListSync.changeProductAmount(list.id!, item.id!, -1, context); - if (Result.fromJson(res.body).success!) { - if (item == null) - list.shoppingItems!.remove(afterAdd); - else - item.amount = item.amount - 1; - } - })); - list.save(); + item == null + ? NSSLStrings.of(context).addedProduct() + "$name" + : "$name" + NSSLStrings.of(context).productWasAlreadyInList(), + duration: Duration(seconds: item == null ? 2 : 4), + action: SnackBarAction( + label: NSSLStrings.of(context).undo(), + onPressed: () async { + var res = item == null + ? await ShoppingListSync.deleteProduct(list.id, afterAdd!.id, context) + : await ShoppingListSync.changeProductAmount(list.id, item.id, -1, context); + if (Result.fromJson(res.body).success) { + var newState = siState.state.toList(); + + newState.remove(afterAdd); + if (item != null) newState.add(item); + siState.state = newState; + } + }), + ); } } diff --git a/lib/server_communication/helper_methods.dart b/lib/server_communication/helper_methods.dart index c5c9d3f..8c80646 100644 --- a/lib/server_communication/helper_methods.dart +++ b/lib/server_communication/helper_methods.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'package:nssl/localization/nssl_strings.dart'; +import 'package:nssl/manager/database_manager.dart'; import 'dart:convert'; import 'dart:async'; import 'package:nssl/models/model_export.dart'; @@ -19,7 +20,7 @@ class HelperMethods { if (!skipTokenRefresh) await handleTokenRefresh(context); var res = await http.post(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), body: jsonEncode(body), - headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); + headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); return res; } @@ -27,7 +28,7 @@ class HelperMethods { static Future get(String path, BuildContext? context, [String query = ""]) async { await handleTokenRefresh(context); var res = await http.get(Uri(host: host, scheme: scheme, path: path, query: query /*, port: 4344*/), - headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); + headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); return res; } @@ -37,7 +38,7 @@ class HelperMethods { if (!skipTokenRefresh) await handleTokenRefresh(context); var res = await http.put(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), body: jsonEncode(body), - headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); + headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); return res; } @@ -45,7 +46,7 @@ class HelperMethods { static Future delete(String path, BuildContext? context) async { await handleTokenRefresh(context); var res = await http.delete(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), - headers: {"Content-Type": "application/json", User.token == null ? "X-foo" : "X-Token": User.token ?? ""}); + headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); return res; @@ -88,7 +89,7 @@ class HelperMethods { var m = jsonDecode(t.body); var to = m["token"]; User.token = to; - User.save(); + DatabaseManager.database.execute("Update User set token = ?", [to]); } } } diff --git a/lib/server_communication/jwt.dart b/lib/server_communication/jwt.dart index 1d1e4d7..8c0b762 100644 --- a/lib/server_communication/jwt.dart +++ b/lib/server_communication/jwt.dart @@ -5,26 +5,22 @@ import 'package:nssl/models/user.dart'; class JWT { static Future newToken() async { //JsonWebToken jwt = JsonWebToken.decode(User.token); - var jwt = jsonDecode(tokenToJson()); + var jwt = jsonDecode(tokenToJson(User.token)); - // var expiresEnd = jwt.indexOf('Z\",\n'); // if(expiresEnd == -1) // expiresEnd = jwt.indexOf('Z\",\r\n'); // var exp = jwt.substring(jwt.indexOf("expires"), jwt.indexOf('Z\",\n')); DateTime expires = DateTime.parse(jwt["expires"]); - if ((DateTime.now()).add(Duration(days: 29)).isAfter(expires)) - return true; + if ((DateTime.now()).add(Duration(days: 29)).isAfter(expires)) return true; return false; } - static String tokenToJson() { - var s = User.token!; - var temps = s - .substring(s.indexOf(".")+1, s.lastIndexOf(".")); - if(temps.length % 4 != 0) - temps = temps.padRight(temps.length+(4-temps.length%4), "="); + static String tokenToJson(String? token) { + if (token == null || token == "") return ""; + var temps = token.substring(token.indexOf(".") + 1, token.lastIndexOf(".")); + if (temps.length % 4 != 0) temps = temps.padRight(temps.length + (4 - temps.length % 4), "="); return Utf8Decoder().convert(Base64Codec().decode(temps)); } @@ -32,7 +28,7 @@ class JWT { //JsonWebToken jwt = JsonWebToken.decode(token); //var map = jwt.payload.toJson(); //return int.parse(map["id"]); - String jwt = tokenToJson(); + String jwt = tokenToJson(token); var exp = jwt.substring(jwt.indexOf("id"), jwt.indexOf(',\n', jwt.indexOf("id"))); return int.parse(exp.substring(5)); @@ -41,7 +37,5 @@ class JWT { // var s = codec.decode(User.token // .substring(User.token.indexOf("."), User.token.lastIndexOf("."))); // return 10; - - } } diff --git a/lib/server_communication/return_classes.dart b/lib/server_communication/return_classes.dart index 8440084..400d7e9 100644 --- a/lib/server_communication/return_classes.dart +++ b/lib/server_communication/return_classes.dart @@ -3,15 +3,14 @@ import 'dart:convert'; import 'package:nssl/models_json.dart'; class BaseResult { - bool? success; - String? error; - static BaseResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + late bool success; + late String error; + static BaseResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static BaseResult _fromJson(Map data) { var r = BaseResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; return r; } } @@ -20,13 +19,12 @@ class CreateResult extends BaseResult { int? id; String? username; String? eMail; - static CreateResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static CreateResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static CreateResult _fromJson(Map data) { var r = CreateResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.id = data["id"]; r.username = data["username"]; r.eMail = data["eMail"]; @@ -36,16 +34,15 @@ class CreateResult extends BaseResult { } class LoginResult extends BaseResult { - int? id; - String? username; - String? eMail; - String? token; - static LoginResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + late int id; + late String username; + late String eMail; + late String token; + static LoginResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static LoginResult _fromJson(Map data) { var r = LoginResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.id = data["id"]; r.username = data["username"]; r.eMail = data["eMail"]; @@ -57,13 +54,12 @@ class LoginResult extends BaseResult { class AddContributorResult extends BaseResult { String? name; int? id; - static AddContributorResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static AddContributorResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static AddContributorResult _fromJson(Map data) { var r = AddContributorResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.id = data["id"]; r.name = data["name"]; return r; @@ -79,13 +75,12 @@ class ContributorResult { class GetContributorsResult extends BaseResult { late List contributors; - static GetContributorsResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static GetContributorsResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static GetContributorsResult _fromJson(Map data) { var r = GetContributorsResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; List unMaped = data["contributors"] ?? []; r.contributors = unMaped .map((x) => ContributorResult() @@ -102,13 +97,12 @@ class ProductResult extends BaseResult { String? gtin; double? quantity; String? unit; - static ProductResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static ProductResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static ProductResult _fromJson(Map data) { var r = ProductResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.gtin = data["gtin"]; r.quantity = data["quantitity"]; r.unit = data["unit"]; @@ -118,16 +112,15 @@ class ProductResult extends BaseResult { } class AddListItemResult extends BaseResult { - int? productId; - String? name; + late int productId; + late String name; String? gtin; - static AddListItemResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static AddListItemResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static AddListItemResult _fromJson(Map data) { var r = AddListItemResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.productId = data["productId"]; r.gtin = data["gtin"]; r.name = data["name"]; @@ -136,18 +129,17 @@ class AddListItemResult extends BaseResult { } class ChangeListItemResult extends BaseResult { - String? name; - int? id; + late String name; + late int id; late int amount; - int? listId; - DateTime? changed; - static ChangeListItemResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + late int listId; + late DateTime? changed; + static ChangeListItemResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static ChangeListItemResult _fromJson(Map data) { var r = ChangeListItemResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.id = data["id"]; r.amount = data["amount"]; r.listId = data["listId"]; @@ -158,17 +150,16 @@ class ChangeListItemResult extends BaseResult { } class AddListResult extends BaseResult { - int? id; - String? name; - static AddListResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + int id; + String name; + AddListResult(this.id, this.name); + + static AddListResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static AddListResult _fromJson(Map data) { - var r = AddListResult(); + var r = AddListResult(data["id"], data["name"]); r.success = data["success"]; - r.error = data["error"]; - r.id = data["id"]; - r.name = data["name"]; + r.error = data["error"] as String? ?? ""; return r; } } @@ -183,8 +174,7 @@ class GetListResult { Iterable? products; String? contributors; - static GetListResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static GetListResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static GetListResult _fromJson(Map data) { var r = GetListResult(); @@ -193,13 +183,8 @@ class GetListResult { r.userId = data["userId"]; r.owner = data["owner"]; var unMaped = data["products"] ?? []; - r.products = unMaped.map((x) => ShoppingItem( - x["id"], - x["amount"], - x["name"], - DateTime.tryParse(x["changed"]), - DateTime.tryParse(x["created"]), - x["sortOrder"])); + r.products = unMaped.map((x) => ShoppingItem(x["id"], x["amount"], x["name"], + DateTime.tryParse(x["changed"]), DateTime.tryParse(x["created"]), x["sortOrder"])); r.contributors = data["contributors"]; @@ -210,26 +195,20 @@ class GetListResult { class GetListsResult { late Iterable shoppingLists; - static GetListsResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static GetListsResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static GetListsResult _fromJson(Map data) { var r = GetListsResult(); List unmappedShoppingLists = data["lists"]; - r.shoppingLists = unmappedShoppingLists.map((s) => ShoppingList() - ..products = s["products"] - .map((x) => ShoppingItem( - x["id"], - x["amount"], - x["name"], - DateTime.tryParse(x["changed"]), - DateTime.tryParse(x["created"]), - x["sortOrder"])) - .toList() - .cast() - ..id = s["id"] - ..name = s["name"]); + r.shoppingLists = unmappedShoppingLists.map((s) => ShoppingList( + s["id"], + s["name"], + s["products"] + .map((x) => ShoppingItem(x["id"], x["amount"], x["name"], DateTime.tryParse(x["changed"]), + DateTime.tryParse(x["created"]), x["sortOrder"] as int? ?? -1)) + .toList() + .cast())); return r; } @@ -240,21 +219,15 @@ class GetBoughtListResult { String? name; late Iterable products; - static GetBoughtListResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static GetBoughtListResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static GetBoughtListResult _fromJson(Map data) { var r = GetBoughtListResult(); r.id = data["id"]; r.name = data["name"]; List unMaped = data["products"] ?? []; - r.products = unMaped.map((x) => ShoppingItem( - x["id"], - x["boughtAmount"], - x["name"], - DateTime.tryParse(x["changed"]), - DateTime.tryParse(x["created"]), - x["sortOrder"])); + r.products = unMaped.map((x) => ShoppingItem(x["id"], x["boughtAmount"], x["name"], DateTime.tryParse(x["changed"]), + DateTime.tryParse(x["created"]), x["sortOrder"])); return r; } } @@ -264,8 +237,7 @@ class InfoResult { String? username; String? eMail; List? listIds; - static InfoResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static InfoResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static InfoResult _fromJson(Map data) { var r = InfoResult(); @@ -280,33 +252,30 @@ class InfoResult { class HashResult extends Result { int? hash; - static HashResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static HashResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static HashResult _fromJson(Map data) { var r = HashResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.hash = data["hash"]; return r; } } class Result extends BaseResult { - static Result fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static Result fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static Result _fromJson(Map data) { var r = Result(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; return r; } } class SessionRefreshResult { String? token; - static SessionRefreshResult fromJson(String dataString) => - _fromJson(jsonDecode(dataString)); + static SessionRefreshResult fromJson(String dataString) => _fromJson(jsonDecode(dataString)); static SessionRefreshResult _fromJson(Map data) { var r = SessionRefreshResult(); From 9a5b12065e8b88f6fbf68bac73ad2cc0c6e023bd Mon Sep 17 00:00:00 2001 From: susch19 Date: Mon, 6 Jun 2022 15:13:03 +0200 Subject: [PATCH 08/23] Fixed problems that occured during migration * load sortorder and order correctly from server, because the field sometimes is named order and sometimes sortOrder so we need to check for both, until the server uses only one name * fixed type for login successful message key * load only relevant records from sql database during reload all, because the data from the server is otherwise correct * delete shoppinglist and items from user on user delete, so we don't leave trash * listen correctly on user db provider, so we don't modify its state during creation of the merged user provider * reload user from db on app restart, so when the user is deleted, it gets removed from the cache --- lib/localization/nssl_messages_de.dart | 62 +-- lib/localization/nssl_strings.dart | 412 +++++++------------ lib/models/shopping_list.dart | 11 +- lib/models/user.dart | 13 +- lib/models_json.dart | 24 +- lib/pages/about.dart | 2 +- lib/pages/bought_items.dart | 2 +- lib/pages/login.dart | 13 +- lib/pages/registration.dart | 1 + lib/pages/shopping_item_search.dart | 2 +- lib/server_communication/return_classes.dart | 14 +- 11 files changed, 240 insertions(+), 316 deletions(-) diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index 4004f9d..f0e98c3 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -20,7 +20,8 @@ class MessageLookup extends MessageLookupByLibrary { "addProduct": MessageLookupByLibrary.simpleMessage("Artikel hinzufügen"), "addProductWithoutSearch": MessageLookupByLibrary.simpleMessage("Name des Artikels"), "productName": MessageLookupByLibrary.simpleMessage("Artikelname"), - "messageDeleteAllCrossedOut": MessageLookupByLibrary.simpleMessage("Alle durchgestrichenen Artikel wurden gelöscht"), + "messageDeleteAllCrossedOut": + MessageLookupByLibrary.simpleMessage("Alle durchgestrichenen Artikel wurden gelöscht"), "undo": MessageLookupByLibrary.simpleMessage("RÜCKG."), "removedShoppingListMessage": MessageLookupByLibrary.simpleMessage(" entfernt "), //\${User.shoppingLists} "noListsInDrawerMessage": MessageLookupByLibrary.simpleMessage(" Hier werden deine Listen angezeigt"), @@ -39,49 +40,60 @@ class MessageLookup extends MessageLookupByLibrary { "promoteMenu": MessageLookupByLibrary.simpleMessage("Befördern"), "contributorUser": MessageLookupByLibrary.simpleMessage(" - User"), "contributorAdmin": MessageLookupByLibrary.simpleMessage(" - Admin"), - "genericErrorMessageSnackbar": MessageLookupByLibrary.simpleMessage("Etwas Unerwartetes ist passiert!\n "), //\${z.error} + "genericErrorMessageSnackbar": + MessageLookupByLibrary.simpleMessage("Etwas Unerwartetes ist passiert!\n "), //\${z.error} "nameOfNewContributorHint": MessageLookupByLibrary.simpleMessage("Name des neuen Teilnehmers"), "wasRemovedSuccessfullyMessage": MessageLookupByLibrary.simpleMessage(" wurde erfolgreich gelöscht"), - "loginSuccessfulMessage": MessageLookupByLibrary.simpleMessage("Login erfolgreich"), + "loginSuccessfullMessage": MessageLookupByLibrary.simpleMessage("Login erfolgreich, die Listen werden geladen"), "nameEmailRequiredError": MessageLookupByLibrary.simpleMessage("Name oder EMail wird benötigt."), - "usernameToShortError": MessageLookupByLibrary.simpleMessage("Der Benutzername muss aus mindestens 4 Zeichen bestehen"), + "usernameToShortError": + MessageLookupByLibrary.simpleMessage("Der Benutzername muss aus mindestens 4 Zeichen bestehen"), "emailRequiredError": MessageLookupByLibrary.simpleMessage("EMail ist erforderlich"), - "emailIncorrectFormatError": MessageLookupByLibrary.simpleMessage("Die EMail-Adresse scheint ein falsches Format zu haben"), + "emailIncorrectFormatError": + MessageLookupByLibrary.simpleMessage("Die EMail-Adresse scheint ein falsches Format zu haben"), "chooseAPassword": MessageLookupByLibrary.simpleMessage("Bitte ein Passwort eingeben"), "login": MessageLookupByLibrary.simpleMessage("Login"), - "usernameOrEmailForLoginHint": MessageLookupByLibrary.simpleMessage("Benutzername oder EMail kann für's einloggen genutzt werden"), + "usernameOrEmailForLoginHint": + MessageLookupByLibrary.simpleMessage("Benutzername oder EMail kann für's einloggen genutzt werden"), "usernameOrEmailTitle": MessageLookupByLibrary.simpleMessage("Benutzername oder EMail"), "emailTitle": MessageLookupByLibrary.simpleMessage('EMail'), "choosenPasswordHint": MessageLookupByLibrary.simpleMessage("Dein gewähltes Passwort"), "password": MessageLookupByLibrary.simpleMessage("Passwort"), "loginButton": MessageLookupByLibrary.simpleMessage("LOGIN"), - "registerTextOnLogin": MessageLookupByLibrary.simpleMessage("Du hast noch keinen Account? Erstelle jetzt einen."), + "registerTextOnLogin": + MessageLookupByLibrary.simpleMessage("Du hast noch keinen Account? Erstelle jetzt einen."), "usernameEmptyError": MessageLookupByLibrary.simpleMessage("Benutzername muss ausgefüllt sein"), "passwordEmptyError": MessageLookupByLibrary.simpleMessage("Passwort muss ausgefüllt sein"), "emailEmptyError": MessageLookupByLibrary.simpleMessage("EMail muss ausgefüllt sein"), - "reenterPasswordError": MessageLookupByLibrary.simpleMessage("Die Passwörter stimmen nicht überein oder sind leer"), + "reenterPasswordError": + MessageLookupByLibrary.simpleMessage("Die Passwörter stimmen nicht überein oder sind leer"), "unknownUsernameError": MessageLookupByLibrary.simpleMessage("Es stimmt etwas mit deinem Benutzername nicht"), "unknownEmailError": MessageLookupByLibrary.simpleMessage("Es stimmt etwas mit deiner EMail nicht"), "unknownPasswordError": MessageLookupByLibrary.simpleMessage("Es stimmt etwas mit deinem Passwort nicht"), - "unknownReenterPasswordError": MessageLookupByLibrary.simpleMessage("Es stimmt etwas mit dem wiederholten Passwort nicht"), + "unknownReenterPasswordError": + MessageLookupByLibrary.simpleMessage("Es stimmt etwas mit dem wiederholten Passwort nicht"), "registrationSuccessfulMessage": MessageLookupByLibrary.simpleMessage("Registrierung erfolgreich"), "registrationTitle": MessageLookupByLibrary.simpleMessage("Registrierung"), "nameEmptyError": MessageLookupByLibrary.simpleMessage("Name ist erforderlich"), "chooseAPasswordPrompt": MessageLookupByLibrary.simpleMessage("Bitte gib ein Passwort ein"), "reenterPasswordPrompt": MessageLookupByLibrary.simpleMessage("Bitte gib dein Passwort erneut ein"), "passwordsDontMatchError": MessageLookupByLibrary.simpleMessage("Die Passwörter stimmen nicht überein"), - "usernameRegisterHint": MessageLookupByLibrary.simpleMessage("Kann zum einloggen und zum gefunden werden genutzt werden"), + "usernameRegisterHint": + MessageLookupByLibrary.simpleMessage("Kann zum einloggen und zum gefunden werden genutzt werden"), "username": MessageLookupByLibrary.simpleMessage("Benutzername"), - "emailRegisterHint": MessageLookupByLibrary.simpleMessage("Kann zum einloggen und zum gefunden werden genutzt werden"), + "emailRegisterHint": + MessageLookupByLibrary.simpleMessage("Kann zum einloggen und zum gefunden werden genutzt werden"), "passwordRegisterHint": MessageLookupByLibrary.simpleMessage("Das Passwort schützt deinen Account"), - "retypePasswordHint": MessageLookupByLibrary.simpleMessage("Bitte wiederhole dein Passwort um Fehler zu vermeiden"), + "retypePasswordHint": + MessageLookupByLibrary.simpleMessage("Bitte wiederhole dein Passwort um Fehler zu vermeiden"), "retypePasswordTitle": MessageLookupByLibrary.simpleMessage("Passwortwiederholung"), "registerButton": MessageLookupByLibrary.simpleMessage("REGISTRIEREN"), "discardNewProduct": MessageLookupByLibrary.simpleMessage("Änderungen verwerfen?"), "cancelButton": MessageLookupByLibrary.simpleMessage("ABBRECHEN"), "acceptButton": MessageLookupByLibrary.simpleMessage('ANNEHMEN'), "discardButton": MessageLookupByLibrary.simpleMessage("VERWERFEN"), - "fixErrorsBeforeSubmittingPrompt": MessageLookupByLibrary.simpleMessage("Bitte behebe die Fehler, gekennzeichnet in Rot"), + "fixErrorsBeforeSubmittingPrompt": + MessageLookupByLibrary.simpleMessage("Bitte behebe die Fehler, gekennzeichnet in Rot"), "newProductTitle": MessageLookupByLibrary.simpleMessage("Neues Produkt"), "saveButton": MessageLookupByLibrary.simpleMessage("SPEICHERN"), "newProductName": MessageLookupByLibrary.simpleMessage("Produktname *"), @@ -96,9 +108,11 @@ class MessageLookup extends MessageLookupByLibrary { "fieldRequiredError": MessageLookupByLibrary.simpleMessage("Dieses Feld wird benötigt!"), "newProductNameToShort": MessageLookupByLibrary.simpleMessage("Dieser Name scheint zu kurz zu sein"), "addedProduct": MessageLookupByLibrary.simpleMessage(' hinzugefügt'), //"\$name" - "productWasAlreadyInList": MessageLookupByLibrary.simpleMessage(' ist bereits in der Liste. Die Menge wurde um 1 erhöht'), //"\$name" ist + "productWasAlreadyInList": MessageLookupByLibrary.simpleMessage( + ' ist bereits in der Liste. Die Menge wurde um 1 erhöht'), //"\$name" ist "searchProductHint": MessageLookupByLibrary.simpleMessage("Produktsuche"), - "noMoreProductsMessage": MessageLookupByLibrary.simpleMessage("Es konnten keine weiteren Produkte mit dem Namen gefunden werden"), + "noMoreProductsMessage": + MessageLookupByLibrary.simpleMessage("Es konnten keine weiteren Produkte mit dem Namen gefunden werden"), "codeText": MessageLookupByLibrary.simpleMessage("Code: "), "removed": MessageLookupByLibrary.simpleMessage("entfernt"), "changePrimaryColor": MessageLookupByLibrary.simpleMessage("Hauptfarbe"), @@ -128,7 +142,8 @@ class MessageLookup extends MessageLookupByLibrary { "bePatient": MessageLookupByLibrary.simpleMessage('Der Server bearbeitet diese Anfrage bereits'), "logout": MessageLookupByLibrary.simpleMessage('Ausloggen'), "deleteListTitle": MessageLookupByLibrary.simpleMessage('Lösche Liste '), - "deleteListText": MessageLookupByLibrary.simpleMessage('Soll diese Liste wirklich gelöscht werden? Das kann NICHT rückgängig gemacht werden!'), + "deleteListText": MessageLookupByLibrary.simpleMessage( + 'Soll diese Liste wirklich gelöscht werden? Das kann NICHT rückgängig gemacht werden!'), "exportAsPdf": MessageLookupByLibrary.simpleMessage('Als PDF exportieren'), "boughtProducts": MessageLookupByLibrary.simpleMessage('Eingekauft'), "nothingBoughtYet": MessageLookupByLibrary.simpleMessage('Noch nichts eingekauft'), @@ -137,18 +152,19 @@ class MessageLookup extends MessageLookupByLibrary { "okayButton": MessageLookupByLibrary.simpleMessage('OKAY'), "requestPasswordResetButton": MessageLookupByLibrary.simpleMessage("PASSWORT ZURÜCKSETZUNG BEANTRAGEN"), "requestPasswordResetTitle": MessageLookupByLibrary.simpleMessage("Passwort zurücksetzen"), - "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage('Die Passwort zurücksetzen Email wurde erfolgreich an die Adresse gesendet, sollte diese existieren. Weitere Schritte für das abschließen des Resets sind in der Email enthalten.'), + "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage( + 'Die Passwort zurücksetzen Email wurde erfolgreich an die Adresse gesendet, sollte diese existieren. Weitere Schritte für das abschließen des Resets sind in der Email enthalten.'), "settings": MessageLookupByLibrary.simpleMessage('Einstellungen'), "about": MessageLookupByLibrary.simpleMessage('Über'), "codeOnGithub": MessageLookupByLibrary.simpleMessage('Schau doch mal in den Code auf GitHub rein'), "playstoreEntry": MessageLookupByLibrary.simpleMessage('Play Store Eintrag'), "iconSource": MessageLookupByLibrary.simpleMessage('Wer hat dieses schicke Icon gemacht? Finde es heraus!'), - "scanditCredit":MessageLookupByLibrary.simpleMessage('hat diesen super Scanner in der App zur Verfügung gestellt'), - "aboutText": MessageLookupByLibrary.simpleMessage('In jahrelanger Handarbeit geschmiedet mit dem einzigen Ziel, die Einkaufsplanung mit anderen zu vereinfachen und dabei seine Lieblingsprodukte blitzschnell per Kamera zu erfassen.'), + "scanditCredit": + MessageLookupByLibrary.simpleMessage('hat diesen super Scanner in der App zur Verfügung gestellt'), + "aboutText": MessageLookupByLibrary.simpleMessage( + 'In jahrelanger Handarbeit geschmiedet mit dem einzigen Ziel, die Einkaufsplanung mit anderen zu vereinfachen und dabei seine Lieblingsprodukte blitzschnell per Kamera zu erfassen.'), "freeText": MessageLookupByLibrary.simpleMessage('Kostenlos, Werbefrei, für immer!'), - "questionsErrors": MessageLookupByLibrary.simpleMessage('Bei Fragen, Anregungen, Fehlern oder sonstigen Belangen kann jederzeit auf GitHub vorbeigeschaut werden, um ein Issue zu eröffnen.'), - - - + "questionsErrors": MessageLookupByLibrary.simpleMessage( + 'Bei Fragen, Anregungen, Fehlern oder sonstigen Belangen kann jederzeit auf GitHub vorbeigeschaut werden, um ein Issue zu eröffnen.'), }; } diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index b7d0725..a2b911b 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -21,283 +21,176 @@ class NSSLStrings { } // static final NSSLStrings instance = NSSLStrings(); - String options() => - Intl.message('Options', name: 'options', locale: _localeName); - String changeTheme() => - Intl.message('Change Theme', name: 'changeTheme', locale: _localeName); + String options() => Intl.message('Options', name: 'options', locale: _localeName); + String changeTheme() => Intl.message('Change Theme', name: 'changeTheme', locale: _localeName); String scanPB() => Intl.message('SCAN', name: 'scanPB', locale: _localeName); String addPB() => Intl.message('ADD', name: 'addPB', locale: _localeName); - String searchPB() => - Intl.message('SEARCH', name: 'searchPB', locale: _localeName); - String deleteCrossedOutPB() => Intl.message('DELETE CROSSED OUT', - name: 'deleteCrossedOutPB', locale: _localeName); - String addListPB() => - Intl.message('ADD LIST', name: 'addListPB', locale: _localeName); - String contributors() => - Intl.message('Contributors', name: 'contributors', locale: _localeName); - String rename() => - Intl.message('Rename', name: 'rename', locale: _localeName); - String remove() => - Intl.message('Remove', name: 'remove', locale: _localeName); - String addProduct() => - Intl.message('Add Product', name: 'addProduct', locale: _localeName); - String addProductWithoutSearch() => Intl.message( - 'Insert the name of the product, without searching in the database', - name: 'addProductWithoutSearch', - locale: _localeName); - String productName() => - Intl.message('Product name', name: 'productName', locale: _localeName); + String searchPB() => Intl.message('SEARCH', name: 'searchPB', locale: _localeName); + String deleteCrossedOutPB() => Intl.message('DELETE CROSSED OUT', name: 'deleteCrossedOutPB', locale: _localeName); + String addListPB() => Intl.message('ADD LIST', name: 'addListPB', locale: _localeName); + String contributors() => Intl.message('Contributors', name: 'contributors', locale: _localeName); + String rename() => Intl.message('Rename', name: 'rename', locale: _localeName); + String remove() => Intl.message('Remove', name: 'remove', locale: _localeName); + String addProduct() => Intl.message('Add Product', name: 'addProduct', locale: _localeName); + String addProductWithoutSearch() => Intl.message('Insert the name of the product, without searching in the database', + name: 'addProductWithoutSearch', locale: _localeName); + String productName() => Intl.message('Product name', name: 'productName', locale: _localeName); String messageDeleteAllCrossedOut() => - Intl.message('You have deleted all crossed out items', - name: 'messageDeleteAllCrossedOut', locale: _localeName); + Intl.message('You have deleted all crossed out items', name: 'messageDeleteAllCrossedOut', locale: _localeName); String undo() => Intl.message('UNDO', name: 'undo', locale: _localeName); String noListsInDrawerMessage() => - Intl.message('Here is the place for your lists', - name: 'noListsInDrawerMessage', locale: _localeName); - String notLoggedInYet() => Intl.message('Not logged in yet', - name: 'notLoggedInYet', locale: _localeName); - String newNameOfListHint() => Intl.message('The new name of the new list', - name: 'newNameOfListHint', locale: _localeName); - String listName() => - Intl.message('Listname', name: 'listName', locale: _localeName); - String renameListTitle() => - Intl.message('Rename List', name: 'renameListTitle', locale: _localeName); - String renameListHint() => Intl.message('The name of the new list', - name: 'renameListHint', locale: _localeName); - String addNewListTitle() => Intl.message('Add new List', - name: 'addNewListTitle', locale: _localeName); - String youHaveActionItemMessage() => Intl.message('You have ', - name: 'youHaveActionItemMessage', locale: _localeName); - String archived() => - Intl.message('archived', name: 'archived', locale: _localeName); - String deleted() => - Intl.message('deleted', name: 'deleted', locale: _localeName); - String youHaveActionNameMessage() => Intl.message('You have ', - name: 'youHaveActionNameMessage', locale: _localeName); - String demoteMenu() => - Intl.message('Demote', name: 'demoteMenu', locale: _localeName); - String promoteMenu() => - Intl.message('Promote', name: 'promoteMenu', locale: _localeName); - String contributorUser() => - Intl.message(" - User", name: 'contributorUser', locale: _localeName); - String contributorAdmin() => - Intl.message(" - Admin", name: 'contributorAdmin', locale: _localeName); + Intl.message('Here is the place for your lists', name: 'noListsInDrawerMessage', locale: _localeName); + String notLoggedInYet() => Intl.message('Not logged in yet', name: 'notLoggedInYet', locale: _localeName); + String newNameOfListHint() => + Intl.message('The new name of the new list', name: 'newNameOfListHint', locale: _localeName); + String listName() => Intl.message('Listname', name: 'listName', locale: _localeName); + String renameListTitle() => Intl.message('Rename List', name: 'renameListTitle', locale: _localeName); + String renameListHint() => Intl.message('The name of the new list', name: 'renameListHint', locale: _localeName); + String addNewListTitle() => Intl.message('Add new List', name: 'addNewListTitle', locale: _localeName); + String youHaveActionItemMessage() => Intl.message('You have ', name: 'youHaveActionItemMessage', locale: _localeName); + String archived() => Intl.message('archived', name: 'archived', locale: _localeName); + String deleted() => Intl.message('deleted', name: 'deleted', locale: _localeName); + String youHaveActionNameMessage() => Intl.message('You have ', name: 'youHaveActionNameMessage', locale: _localeName); + String demoteMenu() => Intl.message('Demote', name: 'demoteMenu', locale: _localeName); + String promoteMenu() => Intl.message('Promote', name: 'promoteMenu', locale: _localeName); + String contributorUser() => Intl.message(" - User", name: 'contributorUser', locale: _localeName); + String contributorAdmin() => Intl.message(" - Admin", name: 'contributorAdmin', locale: _localeName); String genericErrorMessageSnackbar() => - Intl.message('Something went wrong!\n', - name: 'genericErrorMessageSnackbar', locale: _localeName); - String nameOfNewContributorHint() => Intl.message('Name of new Contributor', - name: 'nameOfNewContributorHint', locale: _localeName); + Intl.message('Something went wrong!\n', name: 'genericErrorMessageSnackbar', locale: _localeName); + String nameOfNewContributorHint() => + Intl.message('Name of new Contributor', name: 'nameOfNewContributorHint', locale: _localeName); String wasRemovedSuccessfullyMessage() => - Intl.message(' was removed successfully', - name: 'wasRemovedSuccessfullyMessage', locale: _localeName); - String loginSuccessfulMessage() => Intl.message('Login successfull.', - name: 'loginSuccessfullMessage', locale: _localeName); - String nameEmailRequiredError() => Intl.message('Name or Email is required.', - name: 'nameEmailRequiredError', locale: _localeName); - String usernameToShortError() => - Intl.message('Your username has to be at least 4 characters long', - name: 'usernameToShortError', locale: _localeName); - String emailRequiredError() => Intl.message('EMail is required.', - name: 'emailRequiredError', locale: _localeName); - String emailIncorrectFormatError() => - Intl.message('The email seems to be in the incorrect format.', - name: 'emailIncorrectFormatError', locale: _localeName); - String chooseAPassword() => Intl.message('Please choose a password.', - name: 'chooseAPassword', locale: _localeName); + Intl.message(' was removed successfully', name: 'wasRemovedSuccessfullyMessage', locale: _localeName); + String loginSuccessfulMessage() => + Intl.message('Login successfull, lists will be loaded.', name: 'loginSuccessfullMessage', locale: _localeName); + String nameEmailRequiredError() => + Intl.message('Name or Email is required.', name: 'nameEmailRequiredError', locale: _localeName); + String usernameToShortError() => Intl.message('Your username has to be at least 4 characters long', + name: 'usernameToShortError', locale: _localeName); + String emailRequiredError() => Intl.message('EMail is required.', name: 'emailRequiredError', locale: _localeName); + String emailIncorrectFormatError() => Intl.message('The email seems to be in the incorrect format.', + name: 'emailIncorrectFormatError', locale: _localeName); + String chooseAPassword() => Intl.message('Please choose a password.', name: 'chooseAPassword', locale: _localeName); String login() => Intl.message('Login', name: 'login', locale: _localeName); String usernameOrEmailForLoginHint() => - Intl.message('Username or email can be used to login', - name: 'usernameOrEmailForLoginHint', locale: _localeName); - String usernameOrEmailTitle() => Intl.message('Username or Email', - name: 'usernameOrEmailTitle', locale: _localeName); - String emailTitle() => - Intl.message('Email', name: 'emailTitle', locale: _localeName); - String choosenPasswordHint() => Intl.message('The password you have choosen', - name: 'choosenPasswordHint', locale: _localeName); - String password() => - Intl.message('Password', name: 'password', locale: _localeName); - String loginButton() => - Intl.message('LOGIN', name: 'loginButton', locale: _localeName); + Intl.message('Username or email can be used to login', name: 'usernameOrEmailForLoginHint', locale: _localeName); + String usernameOrEmailTitle() => Intl.message('Username or Email', name: 'usernameOrEmailTitle', locale: _localeName); + String emailTitle() => Intl.message('Email', name: 'emailTitle', locale: _localeName); + String choosenPasswordHint() => + Intl.message('The password you have choosen', name: 'choosenPasswordHint', locale: _localeName); + String password() => Intl.message('Password', name: 'password', locale: _localeName); + String loginButton() => Intl.message('LOGIN', name: 'loginButton', locale: _localeName); String registerTextOnLogin() => - Intl.message('Don\'t have an account? Create one now.', - name: 'registerTextOnLogin', locale: _localeName); - String usernameEmptyError() => Intl.message('Username has to be filled in', - name: 'usernameEmptyError', locale: _localeName); - String passwordEmptyError() => Intl.message('Password has to be filled in', - name: 'passwordEmptyError', locale: _localeName); - String emailEmptyError() => Intl.message('Email has to be filled in', - name: 'emailEmptyError', locale: _localeName); + Intl.message('Don\'t have an account? Create one now.', name: 'registerTextOnLogin', locale: _localeName); + String usernameEmptyError() => + Intl.message('Username has to be filled in', name: 'usernameEmptyError', locale: _localeName); + String passwordEmptyError() => + Intl.message('Password has to be filled in', name: 'passwordEmptyError', locale: _localeName); + String emailEmptyError() => Intl.message('Email has to be filled in', name: 'emailEmptyError', locale: _localeName); String reenterPasswordError() => - Intl.message('Passwords doesn\'t match or are empty', - name: 'reenterPasswordError', locale: _localeName); + Intl.message('Passwords doesn\'t match or are empty', name: 'reenterPasswordError', locale: _localeName); String unknownUsernameError() => - Intl.message('There is something wrong with your username', - name: 'unknownUsernameError', locale: _localeName); + Intl.message('There is something wrong with your username', name: 'unknownUsernameError', locale: _localeName); String unknownEmailError() => - Intl.message('There is something wrong with your email', - name: 'unknownEmailError', locale: _localeName); + Intl.message('There is something wrong with your email', name: 'unknownEmailError', locale: _localeName); String unknownPasswordError() => - Intl.message('There is something wrong with your password', - name: 'unknownPasswordError', locale: _localeName); - String unknownReenterPasswordError() => - Intl.message('There is something wrong with your password validation', - name: 'unknownReenterPasswordError', locale: _localeName); + Intl.message('There is something wrong with your password', name: 'unknownPasswordError', locale: _localeName); + String unknownReenterPasswordError() => Intl.message('There is something wrong with your password validation', + name: 'unknownReenterPasswordError', locale: _localeName); String registrationSuccessfulMessage() => - Intl.message('Registration successfull.', - name: 'registrationSuccessfullMessage', locale: _localeName); - String registrationTitle() => Intl.message('Registration', - name: 'registrationTitle', locale: _localeName); - String nameEmptyError() => Intl.message('Name is required.', - name: 'nameEmptyError', locale: _localeName); - String chooseAPasswordPrompt() => Intl.message('Please choose a password.', - name: 'chooseAPasswordPrompt', locale: _localeName); + Intl.message('Registration successfull.', name: 'registrationSuccessfullMessage', locale: _localeName); + String registrationTitle() => Intl.message('Registration', name: 'registrationTitle', locale: _localeName); + String nameEmptyError() => Intl.message('Name is required.', name: 'nameEmptyError', locale: _localeName); + String chooseAPasswordPrompt() => + Intl.message('Please choose a password.', name: 'chooseAPasswordPrompt', locale: _localeName); String reenterPasswordPrompt() => - Intl.message('Please reenter your password.', - name: 'reenterPasswordPromt', locale: _localeName); - String passwordsDontMatchError() => Intl.message('Passwords don\'t match', - name: 'passwordsDontMatchError', locale: _localeName); + Intl.message('Please reenter your password.', name: 'reenterPasswordPromt', locale: _localeName); + String passwordsDontMatchError() => + Intl.message('Passwords don\'t match', name: 'passwordsDontMatchError', locale: _localeName); String usernameRegisterHint() => - Intl.message('The name to login and to be found by others', - name: 'usernameRegisterHint', locale: _localeName); - String username() => - Intl.message('Username', name: 'username', locale: _localeName); + Intl.message('The name to login and to be found by others', name: 'usernameRegisterHint', locale: _localeName); + String username() => Intl.message('Username', name: 'username', locale: _localeName); String emailRegisterHint() => - Intl.message('The email to login and to be found by others', - name: 'emailRegisterHint', locale: _localeName); + Intl.message('The email to login and to be found by others', name: 'emailRegisterHint', locale: _localeName); String passwordRegisterHint() => - Intl.message('The password to secure your account', - name: 'passwordRegisterHint', locale: _localeName); + Intl.message('The password to secure your account', name: 'passwordRegisterHint', locale: _localeName); String retypePasswordHint() => - Intl.message('Re-type your password for validation', - name: 'retypePasswordHint', locale: _localeName); - String retypePasswordTitle() => Intl.message('Re-type Password', - name: 'retypePasswordTitle', locale: _localeName); - String registerButton() => - Intl.message('REGISTER', name: 'registerButton', locale: _localeName); - String discardNewProduct() => Intl.message('Discard new product?', - name: 'discardNewProduct', locale: _localeName); - String cancelButton() => - Intl.message('CANCEL', name: 'cancelButton', locale: _localeName); - String acceptButton() => - Intl.message('ACCEPT', name: 'acceptButton', locale: _localeName); - String discardButton() => - Intl.message('DISCARD', name: 'discardButton', locale: _localeName); - String fixErrorsBeforeSubmittingPrompt() => - Intl.message('Please fix the errors in red before submitting.', - name: 'fixErrorsBeforeSubmittingPrompt', locale: _localeName); - String newProductTitle() => - Intl.message('New Product', name: 'newProductTitle', locale: _localeName); - String saveButton() => - Intl.message('SAVE', name: 'saveButton', locale: _localeName); - String newProductName() => Intl.message('Product Name *', - name: 'newProductName', locale: _localeName); - String newProductNameHint() => Intl.message('How is this product called?', - name: 'newProductNameHint', locale: _localeName); - String newProductBrandName() => Intl.message('Brand Name *', - name: 'newProductBrandName', locale: _localeName); + Intl.message('Re-type your password for validation', name: 'retypePasswordHint', locale: _localeName); + String retypePasswordTitle() => Intl.message('Re-type Password', name: 'retypePasswordTitle', locale: _localeName); + String registerButton() => Intl.message('REGISTER', name: 'registerButton', locale: _localeName); + String discardNewProduct() => Intl.message('Discard new product?', name: 'discardNewProduct', locale: _localeName); + String cancelButton() => Intl.message('CANCEL', name: 'cancelButton', locale: _localeName); + String acceptButton() => Intl.message('ACCEPT', name: 'acceptButton', locale: _localeName); + String discardButton() => Intl.message('DISCARD', name: 'discardButton', locale: _localeName); + String fixErrorsBeforeSubmittingPrompt() => Intl.message('Please fix the errors in red before submitting.', + name: 'fixErrorsBeforeSubmittingPrompt', locale: _localeName); + String newProductTitle() => Intl.message('New Product', name: 'newProductTitle', locale: _localeName); + String saveButton() => Intl.message('SAVE', name: 'saveButton', locale: _localeName); + String newProductName() => Intl.message('Product Name *', name: 'newProductName', locale: _localeName); + String newProductNameHint() => + Intl.message('How is this product called?', name: 'newProductNameHint', locale: _localeName); + String newProductBrandName() => Intl.message('Brand Name *', name: 'newProductBrandName', locale: _localeName); String newProductBrandNameHint() => - Intl.message('Which company sells this product?', - name: 'newProductBrandNameHint', locale: _localeName); - String newProductWeight() => - Intl.message('Weight', name: 'newProductWeight', locale: _localeName); + Intl.message('Which company sells this product?', name: 'newProductBrandNameHint', locale: _localeName); + String newProductWeight() => Intl.message('Weight', name: 'newProductWeight', locale: _localeName); String newProductWeightHint() => - Intl.message('What is the normal packaging size?', - name: 'newProductWeightHint', locale: _localeName); - String newProductAddToList() => Intl.message('Add to current list', - name: 'newProductAddToList', locale: _localeName); - String newProductAddedToList() => Intl.message(' added to list ', - name: 'newProductAddedToList', locale: _localeName); + Intl.message('What is the normal packaging size?', name: 'newProductWeightHint', locale: _localeName); + String newProductAddToList() => Intl.message('Add to current list', name: 'newProductAddToList', locale: _localeName); + String newProductAddedToList() => Intl.message(' added to list ', name: 'newProductAddedToList', locale: _localeName); String newProductStarExplanation() => - Intl.message('* indicates required field', - name: 'newProductStarExplanation', locale: _localeName); - String fieldRequiredError() => Intl.message('This field is required!', - name: 'fieldRequiredError', locale: _localeName); + Intl.message('* indicates required field', name: 'newProductStarExplanation', locale: _localeName); + String fieldRequiredError() => + Intl.message('This field is required!', name: 'fieldRequiredError', locale: _localeName); String newProductNameToShort() => - Intl.message('This name seems to be to short', - name: 'newProductNameToShort', locale: _localeName); - String addedProduct() => - Intl.message(' added', name: 'addedProduct', locale: _localeName); - String productWasAlreadyInList() => - Intl.message(' was already in list. The amount was increased by 1', - name: 'productWasAlreadyInList', locale: _localeName); - String searchProductHint() => Intl.message('Search Product', - name: 'searchProductHint', locale: _localeName); - String noMoreProductsMessage() => Intl.message('No more products found!', - name: 'noMoreProductsMessage', locale: _localeName); - String codeText() => - Intl.message('Code: ', name: 'codeText', locale: _localeName); - String removed() => - Intl.message('removed', name: 'removed', locale: _localeName); - String changePrimaryColor() => Intl.message('Primary Color', - name: 'changePrimaryColor', locale: _localeName); - String changeAccentColor() => Intl.message('Accent Color', - name: 'changeAccentColor', locale: _localeName); - String changeDarkTheme() => - Intl.message('Dark Theme', name: 'changeDarkTheme', locale: _localeName); - String changeAccentTextColor() => Intl.message('Dark Icons', - name: 'changeAccentTextColor', locale: _localeName); - String autoSync() => - Intl.message('Auto-Sync', name: 'autoSync', locale: _localeName); - String changePasswordButton() => Intl.message('CHANGE PASSWORD', - name: 'changePasswordButton', locale: _localeName); - String oldPassword() => Intl.message('Current password', - name: 'currentPassword', locale: _localeName); + Intl.message('This name seems to be to short', name: 'newProductNameToShort', locale: _localeName); + String addedProduct() => Intl.message(' added', name: 'addedProduct', locale: _localeName); + String productWasAlreadyInList() => Intl.message(' was already in list. The amount was increased by 1', + name: 'productWasAlreadyInList', locale: _localeName); + String searchProductHint() => Intl.message('Search Product', name: 'searchProductHint', locale: _localeName); + String noMoreProductsMessage() => + Intl.message('No more products found!', name: 'noMoreProductsMessage', locale: _localeName); + String codeText() => Intl.message('Code: ', name: 'codeText', locale: _localeName); + String removed() => Intl.message('removed', name: 'removed', locale: _localeName); + String changePrimaryColor() => Intl.message('Primary Color', name: 'changePrimaryColor', locale: _localeName); + String changeAccentColor() => Intl.message('Accent Color', name: 'changeAccentColor', locale: _localeName); + String changeDarkTheme() => Intl.message('Dark Theme', name: 'changeDarkTheme', locale: _localeName); + String changeAccentTextColor() => Intl.message('Dark Icons', name: 'changeAccentTextColor', locale: _localeName); + String autoSync() => Intl.message('Auto-Sync', name: 'autoSync', locale: _localeName); + String changePasswordButton() => Intl.message('CHANGE PASSWORD', name: 'changePasswordButton', locale: _localeName); + String oldPassword() => Intl.message('Current password', name: 'currentPassword', locale: _localeName); String oldPasswordHint() => - Intl.message('Current password that should be changed', - name: 'currentPasswordHint', locale: _localeName); - String newPassword() => - Intl.message('New password', name: 'newPassword', locale: _localeName); - String newPasswordHint() => Intl.message('The new password you have chosen', - name: 'newPasswordHint', locale: _localeName); - String new2Password() => Intl.message('Repeat new password', - name: 'repeatNewPassword', locale: _localeName); + Intl.message('Current password that should be changed', name: 'currentPasswordHint', locale: _localeName); + String newPassword() => Intl.message('New password', name: 'newPassword', locale: _localeName); + String newPasswordHint() => + Intl.message('The new password you have chosen', name: 'newPasswordHint', locale: _localeName); + String new2Password() => Intl.message('Repeat new password', name: 'repeatNewPassword', locale: _localeName); String new2PasswordHint() => - Intl.message('repeat the new password you have chosen', - name: 'repeatNewPasswordHint', locale: _localeName); - String changePasswordPD() => Intl.message('Change Password', - name: 'changePasswordPD', locale: _localeName); - String successful() => - Intl.message('Successful', name: 'successful', locale: _localeName); - String passwordSet() => Intl.message('Your password has been set', - name: 'passwordSet', locale: _localeName); - String tokenExpired() => - Intl.message('Token expired', name: 'tokenExpired', locale: _localeName); + Intl.message('repeat the new password you have chosen', name: 'repeatNewPasswordHint', locale: _localeName); + String changePasswordPD() => Intl.message('Change Password', name: 'changePasswordPD', locale: _localeName); + String successful() => Intl.message('Successful', name: 'successful', locale: _localeName); + String passwordSet() => Intl.message('Your password has been set', name: 'passwordSet', locale: _localeName); + String tokenExpired() => Intl.message('Token expired', name: 'tokenExpired', locale: _localeName); String tokenExpiredExplanation() => Intl.message( 'Your token has expired. Login is required. If this happends multiple times per month, please contact us.', name: 'tokenExpiredExplanation', locale: _localeName); - String noListLoaded() => - Intl.message('No List Loaded', name: 'noListLoaded', locale: _localeName); - String renameListItem() => Intl.message('Rename Product', - name: 'renameListItem', locale: _localeName); - String renameListItemHint() => Intl.message('The new name of the product', - name: 'renameListItemHint', locale: _localeName); - String renameListItemLabel() => Intl.message('new product name', - name: 'renameListItemLabel', locale: _localeName); - String discardNewTheme() => Intl.message('Discard new theme?', - name: 'discardNewTheme', locale: _localeName); - String forgotPassword() => Intl.message('Forgot password?', - name: 'forgotPassword', locale: _localeName); - String bePatient() => Intl.message( - 'Please be patient, the server is processing your request already', - name: 'bePatient', - locale: _localeName); - String logout() => - Intl.message('Logout', name: 'logout', locale: _localeName); - String deleteListTitle() => - Intl.message('Delete List', name: 'deleteListTitle', locale: _localeName); - String deleteListText() => Intl.message( - 'Do you really want to delete the list? This CAN\'T be undone!', - name: 'deleteListText', - locale: _localeName); - String exportAsPdf() => - Intl.message('Export as PDF', name: 'exportAsPdf', locale: _localeName); - String boughtProducts() => Intl.message('Bought Products', - name: 'boughtProducts', locale: _localeName); - String nothingBoughtYet() => Intl.message('Nothing bought yet', - name: 'nothingBoughtYet', locale: _localeName); - String reorderItems() => - Intl.message('Reorder', name: 'reorderItems', locale: _localeName); + String noListLoaded() => Intl.message('No List Loaded', name: 'noListLoaded', locale: _localeName); + String renameListItem() => Intl.message('Rename Product', name: 'renameListItem', locale: _localeName); + String renameListItemHint() => + Intl.message('The new name of the product', name: 'renameListItemHint', locale: _localeName); + String renameListItemLabel() => Intl.message('new product name', name: 'renameListItemLabel', locale: _localeName); + String discardNewTheme() => Intl.message('Discard new theme?', name: 'discardNewTheme', locale: _localeName); + String forgotPassword() => Intl.message('Forgot password?', name: 'forgotPassword', locale: _localeName); + String bePatient() => Intl.message('Please be patient, the server is processing your request already', + name: 'bePatient', locale: _localeName); + String logout() => Intl.message('Logout', name: 'logout', locale: _localeName); + String deleteListTitle() => Intl.message('Delete List', name: 'deleteListTitle', locale: _localeName); + String deleteListText() => Intl.message('Do you really want to delete the list? This CAN\'T be undone!', + name: 'deleteListText', locale: _localeName); + String exportAsPdf() => Intl.message('Export as PDF', name: 'exportAsPdf', locale: _localeName); + String boughtProducts() => Intl.message('Bought Products', name: 'boughtProducts', locale: _localeName); + String nothingBoughtYet() => Intl.message('Nothing bought yet', name: 'nothingBoughtYet', locale: _localeName); + String reorderItems() => Intl.message('Reorder', name: 'reorderItems', locale: _localeName); String refresh() => Intl.message('Refresh', name: "refresh", locale: _localeName); String settings() => Intl.message('Settings', name: "settings", locale: _localeName); @@ -305,14 +198,25 @@ class NSSLStrings { String codeOnGithub() => Intl.message('View Source Code on GitHub', name: "codeOnGithub", locale: _localeName); String playstoreEntry() => Intl.message('Entry on Play Store', name: "playstoreEntry", locale: _localeName); String iconSource() => Intl.message('Source of the App Icon', name: "iconSource", locale: _localeName); - String scanditCredit() => Intl.message('has provided the Scanner for this App', name: "scanditCredit", locale: _localeName); - String aboutText() => Intl.message('Forged over many years with the only intention to make it easier for multiple people to plan their shopping and add their favorite products via camera in an unmatched speed.', name: "aboutText", locale: _localeName); - String freeText() => Intl.message('Free of charge, no Advertisments, forever!', name: "freeText", locale: _localeName); - String questionsErrors() => Intl.message('Questions, Errors or everything else can be send by a GitHub issue.', name: "questionsErrors", locale: _localeName); + String scanditCredit() => + Intl.message('has provided the Scanner for this App', name: "scanditCredit", locale: _localeName); + String aboutText() => Intl.message( + 'Forged over many years with the only intention to make it easier for multiple people to plan their shopping and add their favorite products via camera in an unmatched speed.', + name: "aboutText", + locale: _localeName); + String freeText() => + Intl.message('Free of charge, no Advertisments, forever!', name: "freeText", locale: _localeName); + String questionsErrors() => Intl.message('Questions, Errors or everything else can be send by a GitHub issue.', + name: "questionsErrors", locale: _localeName); String okayButton() => Intl.message('OKAY', name: "okayButton", locale: _localeName); - String requestPasswordResetButton() => Intl.message('REQUEST PASSWORD RESET', name: 'requestPasswordResetButton', locale: _localeName); - String requestPasswordResetTitle() => Intl.message('Password Reset', name: "requestPasswordResetTitle", locale: _localeName); - String requestPasswordResetSuccess() => Intl.message('If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.', name: "requestPasswordResetSuccess", locale: _localeName); + String requestPasswordResetButton() => + Intl.message('REQUEST PASSWORD RESET', name: 'requestPasswordResetButton', locale: _localeName); + String requestPasswordResetTitle() => + Intl.message('Password Reset', name: "requestPasswordResetTitle", locale: _localeName); + String requestPasswordResetSuccess() => Intl.message( + 'If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.', + name: "requestPasswordResetSuccess", + locale: _localeName); //String openAppDrawerTooltip() => Intl.message('Open navigation menu', name: 'openNavigationMenu', locale: _localeName); } diff --git a/lib/models/shopping_list.dart b/lib/models/shopping_list.dart index 3916049..e80c40b 100644 --- a/lib/models/shopping_list.dart +++ b/lib/models/shopping_list.dart @@ -206,15 +206,16 @@ class ShoppingListController with ChangeNotifier { await DatabaseManager.database.delete("ShoppingLists", where: "user_id = ?", whereArgs: [_userId]); List> items; - items = (await DatabaseManager.database.rawQuery("SELECT id, crossed, sortorder FROM ShoppingItems")); + items = (await DatabaseManager.database + .rawQuery("SELECT id, crossed, sortorder FROM ShoppingItems where crossed = 1 or sortorder > 0")); var shoppintItemsState = _ref.watch(shoppingItemsProvider.notifier); var shoppingItems = []; - int currentSortOrder = 0; for (var res in result.shoppingLists) { + int currentSortOrder = -1; for (var item in res.products) { - var order = - items.firstWhere((x) => x["id"] == item.id, orElse: () => {"sortorder": 0})["sortorder"] as int? ?? -1; + var order = items.firstWhere((x) => x["id"] == item.id, + orElse: () => {"sortorder": item.sortOrder})["sortorder"] as int; if (order == -1 || currentSortOrder == order) order = ++currentSortOrder; else @@ -225,6 +226,8 @@ class ShoppingListController with ChangeNotifier { order, id: item.id, amount: item.amount, + changed: item.changed, + created: item.created, crossedOut: (items.firstWhere((x) => x["id"] == item.id, orElse: () => {"crossed": 0})["crossed"] == 0 ? false : true), diff --git a/lib/models/user.dart b/lib/models/user.dart index 59ec898..b6ecabf 100644 --- a/lib/models/user.dart +++ b/lib/models/user.dart @@ -1,10 +1,12 @@ import 'dart:async'; import 'package:flutter/cupertino.dart'; +import 'package:nssl/main.dart'; import 'package:nssl/manager/database_manager.dart'; import 'package:nssl/server_communication/jwt.dart'; import 'package:riverpod/riverpod.dart'; final userFromDbProvider = FutureProvider((ref) async { + ref.watch(appRestartProvider); var list = (await DatabaseManager.database.rawQuery("SELECT * FROM User LIMIT 1")); if (list.length == 0) return null; var z = list.first; @@ -33,12 +35,10 @@ final userStateProvider = StateProvider((ref) { }); final userProvider = Provider((ref) { + var fromDb = ref.watch(userFromDbProvider); var fromState = ref.watch(userStateProvider); - if (fromState.ownId == -1) { - var fromDb = ref.watch(userFromDbProvider); - if (!fromDb.hasError && fromDb.hasValue) { - return fromDb.valueOrNull ?? fromState; - } + if (fromState.ownId == -1 && !fromDb.hasError && !fromDb.isLoading && fromDb.hasValue) { + return fromDb.valueOrNull ?? fromState; } return fromState; }); @@ -97,5 +97,8 @@ class User { Future delete() async { await DatabaseManager.database.rawDelete("DELETE FROM User where own_id = ?", [ownId]); + await DatabaseManager.database.rawDelete( + "DELETE FROM ShoppingItems where res_list_id in( SELECT id FROM ShoppingLists where user_id = ?)", [ownId]); + await DatabaseManager.database.rawDelete("DELETE FROM ShoppingLists where user_id = ?", [ownId]); } } diff --git a/lib/models_json.dart b/lib/models_json.dart index c73e053..0088db9 100644 --- a/lib/models_json.dart +++ b/lib/models_json.dart @@ -25,19 +25,33 @@ class Product { } class ShoppingItem { - ShoppingItem(this.id, this.amount, this.name, this.changed, this.created, this.sortOrder) : super(); + ShoppingItem(this.id, this.amount, this.name, this.changed, this.created, this.sortOrder, this.gtin) : super(); int id; int amount; String name; + String? gtin; DateTime? changed; DateTime? created; int sortOrder; - toJson() => - {"id": id, "amount": amount, "name": name, "changed": changed, "created": created, "sortOrder": sortOrder}; + toJson() => { + "id": id, + "amount": amount, + "name": name, + "changed": changed, + "created": created, + "sortOrder": sortOrder, + "gtin": gtin + }; - static ShoppingItem fromJson(Map data) => - ShoppingItem(data["id"], data["amount"], data["name"], data["changed"], data["created"], data["sortOrder"]); + static ShoppingItem fromJson(Map data) => ShoppingItem( + data["id"], + data["amount"], + data["name"], + DateTime.tryParse(data["changed"]), + DateTime.tryParse(data["created"]), + data["order"] ?? data["sortOrder"], + data["gtin"]); } class ShoppingList { diff --git a/lib/pages/about.dart b/lib/pages/about.dart index 64ab408..4d94a49 100644 --- a/lib/pages/about.dart +++ b/lib/pages/about.dart @@ -71,7 +71,7 @@ class AboutPage extends StatelessWidget { ), ), ListTile( - title: Text("Version 0.25"), + title: Text("Version 0.27"), ), Divider(), ListTile( diff --git a/lib/pages/bought_items.dart b/lib/pages/bought_items.dart index e764e70..b85b783 100644 --- a/lib/pages/bought_items.dart +++ b/lib/pages/bought_items.dart @@ -93,7 +93,7 @@ class _BoughtItemsPagePageState extends ConsumerState with Sing id: f.id, amount: f.amount, changed: f.changed, created: f.created, crossedOut: false))); DateTime date; - shoppingItems.sort((x, y) => y.changed!.compareTo(x.changed!)); + shoppingItems.sort((x, y) => x.changed!.compareTo(y.changed!)); for (var item in shoppingItems) { date = dateTimeToDate(item.changed!); if (!shoppingItemsGrouped.containsKey(dateTimeToDate(item.changed!))) diff --git a/lib/pages/login.dart b/lib/pages/login.dart index e3e3c8a..1f35724 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -76,11 +76,8 @@ class LoginPageState extends ConsumerState { return; } showInSnackBar(NSSLStrings.of(context).loginSuccessfulMessage()); - var curUser = ref.read(userProvider); var userState = ref.watch(userStateProvider.notifier); - // var - bool firstBoot = curUser.ownId >= 0; User.token = res.token; var user = User(res.id, res.username, res.eMail); @@ -89,14 +86,8 @@ class LoginPageState extends ConsumerState { var listController = ref.read(shoppingListsProvider); await listController.reloadAllLists(context); - if (firstBoot) { - if (listController.shoppingLists.length > 0) { - var curListState = ref.read(currentListIndexProvider.notifier); - curListState.state = 1; - } - } - - user.save(1); + user.save(0); + ref.watch(currentListIndexProvider.notifier).state = 0; userState.state = user; } diff --git a/lib/pages/registration.dart b/lib/pages/registration.dart index 67738fd..69b30b9 100644 --- a/lib/pages/registration.dart +++ b/lib/pages/registration.dart @@ -66,6 +66,7 @@ class RegistrationState extends ConsumerState { User.token = loginRes.token; var user = User(loginRes.id, loginRes.username, loginRes.eMail); userState.state = user; + ref.watch(currentListIndexProvider.notifier).state = 0; await user.save(0); // Navigator.pop(context); diff --git a/lib/pages/shopping_item_search.dart b/lib/pages/shopping_item_search.dart index 12026a6..67b7cee 100644 --- a/lib/pages/shopping_item_search.dart +++ b/lib/pages/shopping_item_search.dart @@ -19,7 +19,7 @@ class ProductAddPage extends ConsumerStatefulWidget { static ProductResult fromJson(Map data) { var r = ProductResult(); r.success = data["success"]; - r.error = data["error"]; + r.error = data["error"] as String? ?? ""; r.gtin = data["gtin"]; r.quantity = data["quantity"]; r.unit = data["unit"]; diff --git a/lib/server_communication/return_classes.dart b/lib/server_communication/return_classes.dart index 400d7e9..9d82a0f 100644 --- a/lib/server_communication/return_classes.dart +++ b/lib/server_communication/return_classes.dart @@ -183,8 +183,7 @@ class GetListResult { r.userId = data["userId"]; r.owner = data["owner"]; var unMaped = data["products"] ?? []; - r.products = unMaped.map((x) => ShoppingItem(x["id"], x["amount"], x["name"], - DateTime.tryParse(x["changed"]), DateTime.tryParse(x["created"]), x["sortOrder"])); + r.products = unMaped.map((x) => ShoppingItem.fromJson(x)); r.contributors = data["contributors"]; @@ -202,13 +201,7 @@ class GetListsResult { List unmappedShoppingLists = data["lists"]; r.shoppingLists = unmappedShoppingLists.map((s) => ShoppingList( - s["id"], - s["name"], - s["products"] - .map((x) => ShoppingItem(x["id"], x["amount"], x["name"], DateTime.tryParse(x["changed"]), - DateTime.tryParse(x["created"]), x["sortOrder"] as int? ?? -1)) - .toList() - .cast())); + s["id"], s["name"], s["products"].map((x) => ShoppingItem.fromJson(x)).toList().cast())); return r; } @@ -226,8 +219,7 @@ class GetBoughtListResult { r.id = data["id"]; r.name = data["name"]; List unMaped = data["products"] ?? []; - r.products = unMaped.map((x) => ShoppingItem(x["id"], x["boughtAmount"], x["name"], DateTime.tryParse(x["changed"]), - DateTime.tryParse(x["created"]), x["sortOrder"])); + r.products = unMaped.map((x) => ShoppingItem.fromJson(x)); return r; } } From b1e7433d6c8b2766f7507b2c38857174ac961f38 Mon Sep 17 00:00:00 2001 From: susch19 Date: Mon, 6 Jun 2022 18:48:59 +0200 Subject: [PATCH 09/23] Added password rules for change or registration * so that a very simple minimum of security is enforced * fixed errors not displayed on register and password change, because the decoration where always resettet on drawing, even though it should only be happening the first time to set the initial values * fixed currentlist throwing an exception when the last list was deleted, as the index of and firstWhere wasn't true * fixed list change beeing not notified to listeners and thefore toggling live updates wasn't reflected in ui --- lib/helper/password_service.dart | 15 +++ lib/localization/nssl_messages_de.dart | 4 + lib/localization/nssl_messages_en.dart | 37 ++++--- lib/localization/nssl_strings.dart | 6 ++ lib/models/shopping_list.dart | 3 +- lib/pages/change_password.dart | 105 ++++++++++++------- lib/pages/main_page.dart | 4 +- lib/pages/registration.dart | 76 +++++++------- lib/server_communication/return_classes.dart | 6 +- 9 files changed, 163 insertions(+), 93 deletions(-) create mode 100644 lib/helper/password_service.dart diff --git a/lib/helper/password_service.dart b/lib/helper/password_service.dart new file mode 100644 index 0000000..ce715ff --- /dev/null +++ b/lib/helper/password_service.dart @@ -0,0 +1,15 @@ +enum PasswordErrorCode { none, empty, tooShort, missingCharacters } + +class PasswordService { + static PasswordErrorCode checkNewPassword(String newPassword) { + if (newPassword.isEmpty) return PasswordErrorCode.empty; + if (newPassword.length < 6) return PasswordErrorCode.tooShort; + var containsChar = newPassword.contains(RegExp(r'[a-zA-ZäöüÄÖÜ]')); + var containsDigit = newPassword.contains(RegExp(r'[0-9]')); + var containsSpecialChar = newPassword.contains(RegExp(r'[^0-9a-zA-ZäöüÄÖÜ]')); + if (!containsChar && !containsSpecialChar || !containsDigit && !containsSpecialChar) + return PasswordErrorCode.missingCharacters; + + return PasswordErrorCode.none; + } +} diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index f0e98c3..485b97a 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -64,6 +64,10 @@ class MessageLookup extends MessageLookupByLibrary { MessageLookupByLibrary.simpleMessage("Du hast noch keinen Account? Erstelle jetzt einen."), "usernameEmptyError": MessageLookupByLibrary.simpleMessage("Benutzername muss ausgefüllt sein"), "passwordEmptyError": MessageLookupByLibrary.simpleMessage("Passwort muss ausgefüllt sein"), + "passwordTooShortError": MessageLookupByLibrary.simpleMessage("Passwort muss mindestens 6 Zeichen lang sein"), + "passwordMissingCharactersError": MessageLookupByLibrary.simpleMessage( + "Passwort muss mindestens ein spezielles Zeichen (Kann jedes Symbol/Emoji sein) und Buchstabe oder Zahl enthalten"), + "emailEmptyError": MessageLookupByLibrary.simpleMessage("EMail muss ausgefüllt sein"), "reenterPasswordError": MessageLookupByLibrary.simpleMessage("Die Passwörter stimmen nicht überein oder sind leer"), diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index cc4d6f5..355d667 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -18,11 +18,13 @@ class MessageLookup extends MessageLookupByLibrary { "rename": MessageLookupByLibrary.simpleMessage("Rename"), "remove": MessageLookupByLibrary.simpleMessage("Remove"), "addProduct": MessageLookupByLibrary.simpleMessage('Add Product'), - "addProductWithoutSearch": MessageLookupByLibrary.simpleMessage('Insert the name of the product, without searching in the database'), + "addProductWithoutSearch": + MessageLookupByLibrary.simpleMessage('Insert the name of the product, without searching in the database'), "productName": MessageLookupByLibrary.simpleMessage('product name'), "messageDeleteAllCrossedOut": MessageLookupByLibrary.simpleMessage("You have deleted all crossed out items"), "undo": MessageLookupByLibrary.simpleMessage("UNDO"), - "removedShoppingListMessage": MessageLookupByLibrary.simpleMessage(" removed"), //"Removed \${User.shoppingLists} " + "removedShoppingListMessage": + MessageLookupByLibrary.simpleMessage(" removed"), //"Removed \${User.shoppingLists} " "noListsInDrawerMessage": MessageLookupByLibrary.simpleMessage("here is the place for your lists"), "notLoggedInYet": MessageLookupByLibrary.simpleMessage("Not logged in yet"), "newNameOfListHint": MessageLookupByLibrary.simpleMessage('The new name of the new list'), @@ -43,9 +45,11 @@ class MessageLookup extends MessageLookupByLibrary { "wasRemovedSuccessfullyMessage": MessageLookupByLibrary.simpleMessage(" was removed successfully"), "loginSuccessfullMessage": MessageLookupByLibrary.simpleMessage("Login successfull."), "nameEmailRequiredError": MessageLookupByLibrary.simpleMessage('Name or Email is required.'), - "usernameToShortError": MessageLookupByLibrary.simpleMessage('Your username has to be at least 4 characters long'), + "usernameToShortError": + MessageLookupByLibrary.simpleMessage('Your username has to be at least 4 characters long'), "emailRequiredError": MessageLookupByLibrary.simpleMessage('EMail is required.'), - "emailIncorrectFormatError": MessageLookupByLibrary.simpleMessage('The email seems to be in the incorrect format.'), + "emailIncorrectFormatError": + MessageLookupByLibrary.simpleMessage('The email seems to be in the incorrect format.'), "chooseAPassword": MessageLookupByLibrary.simpleMessage('Please choose a password.'), "login": MessageLookupByLibrary.simpleMessage("Login"), "usernameOrEmailForLoginHint": MessageLookupByLibrary.simpleMessage('Username or email can be used to login'), @@ -57,12 +61,16 @@ class MessageLookup extends MessageLookupByLibrary { "registerTextOnLogin": MessageLookupByLibrary.simpleMessage("Don't have an account? Create one now."), "usernameEmptyError": MessageLookupByLibrary.simpleMessage("Username has to be filled in"), "passwordEmptyError": MessageLookupByLibrary.simpleMessage("Password has to be filled in"), + "passwordTooShortError": MessageLookupByLibrary.simpleMessage("Password has to be at least 6 charactes long"), + "passwordMissingCharactersError": MessageLookupByLibrary.simpleMessage( + "Password has to contain a special character (Can be emoji or any other symbol) and a letter or number"), "emailEmptyError": MessageLookupByLibrary.simpleMessage("Email has to be filled in"), "reenterPasswordError": MessageLookupByLibrary.simpleMessage("Passwords doesn't match or are empty"), "unknownUsernameError": MessageLookupByLibrary.simpleMessage("There is something wrong with your username"), "unknownEmailError": MessageLookupByLibrary.simpleMessage("There is something wrong with your email"), "unknownPasswordError": MessageLookupByLibrary.simpleMessage("There is something wrong with your password"), - "unknownReenterPasswordError": MessageLookupByLibrary.simpleMessage("There is something wrong with your password validation"), + "unknownReenterPasswordError": + MessageLookupByLibrary.simpleMessage("There is something wrong with your password validation"), "registrationSuccessfulMessage": MessageLookupByLibrary.simpleMessage("Registration successfull."), "registrationTitle": MessageLookupByLibrary.simpleMessage("Registration"), "nameEmptyError": MessageLookupByLibrary.simpleMessage('Name is required.'), @@ -80,7 +88,8 @@ class MessageLookup extends MessageLookupByLibrary { "cancelButton": MessageLookupByLibrary.simpleMessage('CANCEL'), "acceptButton": MessageLookupByLibrary.simpleMessage('ACCEPT'), "discardButton": MessageLookupByLibrary.simpleMessage('DISCARD'), - "fixErrorsBeforeSubmittingPrompt": MessageLookupByLibrary.simpleMessage('Please fix the errors in red before submitting.'), + "fixErrorsBeforeSubmittingPrompt": + MessageLookupByLibrary.simpleMessage('Please fix the errors in red before submitting.'), "newProductTitle": MessageLookupByLibrary.simpleMessage('New Product'), "saveButton": MessageLookupByLibrary.simpleMessage('SAVE'), "newProductName": MessageLookupByLibrary.simpleMessage("Product Name *"), @@ -95,7 +104,8 @@ class MessageLookup extends MessageLookupByLibrary { "fieldRequiredError": MessageLookupByLibrary.simpleMessage("This field is required!"), "newProductNameToShort": MessageLookupByLibrary.simpleMessage("This name seems to be to short"), "addedProduct": MessageLookupByLibrary.simpleMessage(' added'), //'Added "\$name"' - "productWasAlreadyInList": MessageLookupByLibrary.simpleMessage(' was already in list. The amount was increased by 1'), //"\$name" was + "productWasAlreadyInList": + MessageLookupByLibrary.simpleMessage(' was already in list. The amount was increased by 1'), //"\$name" was "searchProductHint": MessageLookupByLibrary.simpleMessage("Search Product"), "noMoreProductsMessage": MessageLookupByLibrary.simpleMessage("No more products found!}"), "codeText": MessageLookupByLibrary.simpleMessage("Code: "), @@ -116,18 +126,20 @@ class MessageLookup extends MessageLookupByLibrary { "successful": MessageLookupByLibrary.simpleMessage("Successful"), "passwordSet": MessageLookupByLibrary.simpleMessage("Your password has been set"), "tokenExpired": MessageLookupByLibrary.simpleMessage("Token expired"), - "tokenExpiredExplanation": - MessageLookupByLibrary.simpleMessage("Your token has expired. Login is required. If this happends multiple times per month, please contact us."), + "tokenExpiredExplanation": MessageLookupByLibrary.simpleMessage( + "Your token has expired. Login is required. If this happends multiple times per month, please contact us."), "noListLoaded": MessageLookupByLibrary.simpleMessage("No List Loaded"), "renameListItem": MessageLookupByLibrary.simpleMessage("Rename Product"), "renameListItemHint": MessageLookupByLibrary.simpleMessage("The new name of the product"), "renameListItemLabel": MessageLookupByLibrary.simpleMessage("new product name"), "discardNewTheme": MessageLookupByLibrary.simpleMessage('Discard new theme?'), "forgotPassword": MessageLookupByLibrary.simpleMessage('Forgot password?'), - "bePatient": MessageLookupByLibrary.simpleMessage('Please be patient, the server is processing your request already'), + "bePatient": + MessageLookupByLibrary.simpleMessage('Please be patient, the server is processing your request already'), "logout": MessageLookupByLibrary.simpleMessage('Logout'), "deleteListTitle": MessageLookupByLibrary.simpleMessage('Delete List '), - "deleteListText": MessageLookupByLibrary.simpleMessage('Do you really want to delete the list? This CAN\'T be undone!'), + "deleteListText": + MessageLookupByLibrary.simpleMessage('Do you really want to delete the list? This CAN\'T be undone!'), "exportAsPdf": MessageLookupByLibrary.simpleMessage('Export as PDF'), "boughtProducts": MessageLookupByLibrary.simpleMessage('Bought Products'), "nothingBoughtYet": MessageLookupByLibrary.simpleMessage('Nothing bought yet'), @@ -136,7 +148,8 @@ class MessageLookup extends MessageLookupByLibrary { "okayButton": MessageLookupByLibrary.simpleMessage('OKAY'), "requestPasswordResetButton": MessageLookupByLibrary.simpleMessage("REQUEST PASSWORD RESET"), "requestPasswordResetTitle": MessageLookupByLibrary.simpleMessage("Password Reset"), - "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage('If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.'), + "requestPasswordResetSuccess": MessageLookupByLibrary.simpleMessage( + 'If the email exists, the password request was successfully requested. Further instructions can be found in the email, that was send to the address.'), "settings": MessageLookupByLibrary.simpleMessage('Settings'), }; } diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index a2b911b..d51ba99 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -86,6 +86,12 @@ class NSSLStrings { Intl.message('Username has to be filled in', name: 'usernameEmptyError', locale: _localeName); String passwordEmptyError() => Intl.message('Password has to be filled in', name: 'passwordEmptyError', locale: _localeName); + String passwordTooShortError() => + Intl.message('Password has to be at least 6 charactes long', name: 'passwordTooShortError', locale: _localeName); + String passwordMissingCharactersError() => Intl.message( + 'Password has to contain a special character (Can be emoji or any other symbol) and a letter or number', + name: 'passwordMissingCharactersError', + locale: _localeName); String emailEmptyError() => Intl.message('Email has to be filled in', name: 'emailEmptyError', locale: _localeName); String reenterPasswordError() => Intl.message('Passwords doesn\'t match or are empty', name: 'reenterPasswordError', locale: _localeName); diff --git a/lib/models/shopping_list.dart b/lib/models/shopping_list.dart index e80c40b..d791038 100644 --- a/lib/models/shopping_list.dart +++ b/lib/models/shopping_list.dart @@ -193,6 +193,7 @@ class ShoppingListController with ChangeNotifier { var index = shoppingLists.indexOf(list); shoppingLists.remove(list); shoppingLists.insert(index, newList); + notifyListeners(); } Future reloadAllLists([BuildContext? cont]) async { @@ -280,7 +281,7 @@ class ShoppingListController with ChangeNotifier { void toggleFirebaseMessaging(int listId) { var list = shoppingLists.firstWhere((element) => element.id == listId); var newList = ShoppingList(listId, list.name, messagingEnabled: !list.messagingEnabled); - newList.messagingEnabled ? list.unsubscribeFromFirebaseMessaging() : list.subscribeForFirebaseMessaging(); + newList.messagingEnabled ? list.subscribeForFirebaseMessaging() : list.unsubscribeFromFirebaseMessaging(); _exchangeLists(list, newList); save(newList); } diff --git a/lib/pages/change_password.dart b/lib/pages/change_password.dart index 20177d2..97c622f 100644 --- a/lib/pages/change_password.dart +++ b/lib/pages/change_password.dart @@ -5,6 +5,8 @@ import 'package:nssl/pages/login.dart'; import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/server_communication/s_c.dart'; +import '../helper/password_service.dart'; + class ChangePasswordPage extends StatefulWidget { ChangePasswordPage({Key? key, this.scaffoldKey}) : super(key: key); @@ -16,9 +18,10 @@ class ChangePasswordPage extends StatefulWidget { class ChangePasswordPageState extends State { ChangePasswordPageState() : super(); GlobalKey _scaffoldKey = GlobalKey(); - var oldPwInput = ForInput(); - var newPwInput = ForInput(); - var newPw2Input = ForInput(); + var _oldPwInput = ForInput(); + var _newPwInput = ForInput(); + var _newPw2Input = ForInput(); + bool _initialized = false; void showInSnackBar(String value) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(value), duration: Duration(seconds: 3))); @@ -28,33 +31,54 @@ class ChangePasswordPageState extends State { bool error = false; _resetInput(); - if (_validateEmpty(oldPwInput.textEditingController)) { - oldPwInput.decoration = InputDecoration( - labelText: oldPwInput.decoration!.labelText, - helperText: oldPwInput.decoration!.helperText, + if (_validateEmpty(_oldPwInput.textEditingController)) { + _oldPwInput.decoration = InputDecoration( + labelText: _oldPwInput.decoration!.labelText, + helperText: _oldPwInput.decoration!.helperText, errorText: NSSLStrings.of(context).passwordEmptyError()); error = true; } - if (_validateEmpty(newPwInput.textEditingController)) { - newPwInput.decoration = InputDecoration( - labelText: newPwInput.decoration!.labelText, - helperText: newPwInput.decoration!.helperText, - errorText: NSSLStrings.of(context).passwordEmptyError()); + var errorCode = PasswordService.checkNewPassword(_newPwInput.textEditingController.text); + + if (errorCode != PasswordErrorCode.none) { + String errorText = ""; + switch (errorCode) { + case PasswordErrorCode.empty: + errorText = NSSLStrings.of(context).passwordEmptyError(); + break; + case PasswordErrorCode.none: + break; + case PasswordErrorCode.tooShort: + errorText = NSSLStrings.of(context).passwordTooShortError(); + break; + case PasswordErrorCode.missingCharacters: + errorText = NSSLStrings.of(context).passwordMissingCharactersError(); + break; + } + + _newPwInput.decoration = InputDecoration( + labelText: _newPwInput.decoration!.labelText, + helperText: _newPwInput.decoration!.helperText, + errorText: errorText); error = true; } - if (_validateEmpty(newPw2Input.textEditingController)) { - newPw2Input.decoration = InputDecoration( - labelText: newPw2Input.decoration!.labelText, - helperText: newPw2Input.decoration!.helperText, + if (_validateEmpty(_newPw2Input.textEditingController)) { + _newPw2Input.decoration = InputDecoration( + labelText: _newPw2Input.decoration!.labelText, + helperText: _newPw2Input.decoration!.helperText, errorText: NSSLStrings.of(context).passwordEmptyError()); error = true; } - if (error == true) return; - if (newPwInput.textEditingController.text != newPw2Input.textEditingController.text) { - newPw2Input.decoration = InputDecoration( - labelText: newPw2Input.decoration!.labelText, - helperText: newPw2Input.decoration!.helperText, + if (error == true) { + setState(() {}); + return; + } + if (_newPwInput.textEditingController.text != _newPw2Input.textEditingController.text) { + _newPw2Input.decoration = InputDecoration( + labelText: _newPw2Input.decoration!.labelText, + helperText: _newPw2Input.decoration!.helperText, errorText: NSSLStrings.of(context).passwordsDontMatchError()); + setState(() {}); return; } _changePassword(); @@ -64,7 +88,7 @@ class ChangePasswordPageState extends State { _changePassword() async { var res = await UserSync.changePassword( - oldPwInput.textEditingController.text, newPwInput.textEditingController.text, User.token, context); + _oldPwInput.textEditingController.text, _newPwInput.textEditingController.text, User.token, context); if (res.statusCode != 200) { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text(res.reasonPhrase!), duration: Duration(seconds: 3))); @@ -89,12 +113,13 @@ class ChangePasswordPageState extends State { } _resetInput() { - oldPwInput.decoration = InputDecoration( + _oldPwInput.decoration = InputDecoration( helperText: NSSLStrings.of(context).oldPasswordHint(), labelText: NSSLStrings.of(context).oldPassword()); - newPwInput.decoration = InputDecoration( + _newPwInput.decoration = InputDecoration( helperText: NSSLStrings.of(context).newPasswordHint(), labelText: NSSLStrings.of(context).newPassword()); - newPw2Input.decoration = InputDecoration( + _newPw2Input.decoration = InputDecoration( helperText: NSSLStrings.of(context).new2PasswordHint(), labelText: NSSLStrings.of(context).new2Password()); + _initialized = true; } @override @@ -104,7 +129,7 @@ class ChangePasswordPageState extends State { @override Widget build(BuildContext context) { - _resetInput(); + if (!_initialized) _resetInput(); return Scaffold( key: _scaffoldKey, resizeToAvoidBottomInset: false, @@ -114,35 +139,35 @@ class ChangePasswordPageState extends State { child: Column(mainAxisAlignment: MainAxisAlignment.start, children: [ Flexible( child: TextField( - key: oldPwInput.key, - decoration: oldPwInput.decoration, - focusNode: oldPwInput.focusNode, + key: _oldPwInput.key, + decoration: _oldPwInput.decoration, + focusNode: _oldPwInput.focusNode, obscureText: true, - controller: oldPwInput.textEditingController, + controller: _oldPwInput.textEditingController, onSubmitted: (val) { - FocusScope.of(context).requestFocus(newPwInput.focusNode); + FocusScope.of(context).requestFocus(_newPwInput.focusNode); }, ), ), Flexible( child: TextField( - key: newPwInput.key, - decoration: newPwInput.decoration, - focusNode: newPwInput.focusNode, + key: _newPwInput.key, + decoration: _newPwInput.decoration, + focusNode: _newPwInput.focusNode, obscureText: true, - controller: newPwInput.textEditingController, + controller: _newPwInput.textEditingController, onSubmitted: (val) { - FocusScope.of(context).requestFocus(newPw2Input.focusNode); + FocusScope.of(context).requestFocus(_newPw2Input.focusNode); }, ), ), Flexible( child: TextField( - key: newPw2Input.key, - decoration: newPw2Input.decoration, - focusNode: newPw2Input.focusNode, + key: _newPw2Input.key, + decoration: _newPw2Input.decoration, + focusNode: _newPw2Input.focusNode, obscureText: true, - controller: newPw2Input.textEditingController, + controller: _newPw2Input.textEditingController, onSubmitted: (val) { _handleSubmitted(); }, diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index c132a94..6c2f2af 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -486,8 +486,8 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi var currentList = ref.read(currentListProvider)!; var shoppingListController = ref.read(shoppingListsProvider); if (currentList.id == id) { - changeCurrentList(shoppingListController.shoppingLists - .indexOf(shoppingListController.shoppingLists.firstWhere((l) => l.id != id))); + var other = shoppingListController.shoppingLists.firstOrNull((l) => l.id != id); + if (other != null) changeCurrentList(shoppingListController.shoppingLists.indexOf(other)); } shoppingListController.removeList(deleteList.id); showInDrawerSnackBar(deleteList.name + " " + NSSLStrings.of(cont).removed()); diff --git a/lib/pages/registration.dart b/lib/pages/registration.dart index 69b30b9..0a5e463 100644 --- a/lib/pages/registration.dart +++ b/lib/pages/registration.dart @@ -6,6 +6,7 @@ import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/server_communication/s_c.dart'; import 'package:flutter/material.dart'; import 'package:nssl/models/model_export.dart'; +import '../helper/password_service.dart'; import 'login.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -28,6 +29,7 @@ class RegistrationState extends ConsumerState { var pw2Input = ForInput(); var submit = ForInput(); var validateMode = AutovalidateMode.disabled; + bool initialized = false; void showInSnackBar(String value) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(value), duration: Duration(seconds: 3))); @@ -91,8 +93,21 @@ class RegistrationState extends ConsumerState { } String? _validatePassword(String? value) { - if (pwInput.textEditingController.text.isEmpty) return NSSLStrings.of(context).chooseAPasswordPrompt(); - return null; + var errorCode = PasswordService.checkNewPassword(value ?? ""); + + if (errorCode != PasswordErrorCode.none) { + String errorText = ""; + switch (errorCode) { + case PasswordErrorCode.empty: + return NSSLStrings.of(context).passwordEmptyError(); + case PasswordErrorCode.none: + return null; + case PasswordErrorCode.tooShort: + return NSSLStrings.of(context).passwordTooShortError(); + case PasswordErrorCode.missingCharacters: + return NSSLStrings.of(context).passwordMissingCharactersError(); + } + } } String? _validatePassword2(String? value) { @@ -103,7 +118,7 @@ class RegistrationState extends ConsumerState { @override Widget build(BuildContext context) { - _resetInput(); + if (!initialized) _resetInput(); return Scaffold( key: _scaffoldKey, appBar: AppBar(title: Text(NSSLStrings.of(context).registrationTitle())), @@ -134,33 +149,28 @@ class RegistrationState extends ConsumerState { onSaved: (s) { FocusScope.of(context).requestFocus(pwInput.focusNode); }), - Row(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Flexible( - child: TextFormField( - key: pwInput.key, - decoration: pwInput.decoration, - controller: pwInput.textEditingController, - focusNode: pwInput.focusNode, - autocorrect: false, - obscureText: true, - validator: _validatePassword, - onSaved: (s) { - FocusScope.of(context).requestFocus(pw2Input.focusNode); - })), - SizedBox(width: 16.0), - Flexible( - child: TextFormField( - key: pw2Input.key, - decoration: pw2Input.decoration, - controller: pw2Input.textEditingController, - focusNode: pw2Input.focusNode, - autocorrect: false, - obscureText: true, - validator: _validatePassword2, - onSaved: (s) { - _handleSubmitted(); - })), - ]), + TextFormField( + key: pwInput.key, + decoration: pwInput.decoration, + controller: pwInput.textEditingController, + focusNode: pwInput.focusNode, + autocorrect: false, + obscureText: true, + validator: _validatePassword, + onSaved: (s) { + FocusScope.of(context).requestFocus(pw2Input.focusNode); + }), + TextFormField( + key: pw2Input.key, + decoration: pw2Input.decoration, + controller: pw2Input.textEditingController, + focusNode: pw2Input.focusNode, + autocorrect: false, + obscureText: true, + validator: _validatePassword2, + onSaved: (s) { + _handleSubmitted(); + }), Row(children: [ Flexible( child: Container( @@ -206,10 +216,6 @@ class RegistrationState extends ConsumerState { pw2Input.decoration = InputDecoration( helperText: NSSLStrings.of(context).retypePasswordHint(), labelText: NSSLStrings.of(context).retypePasswordTitle()); - } - - @override - initState() { - super.initState(); + initialized = true; } } diff --git a/lib/server_communication/return_classes.dart b/lib/server_communication/return_classes.dart index 9d82a0f..b4665a8 100644 --- a/lib/server_communication/return_classes.dart +++ b/lib/server_communication/return_classes.dart @@ -44,9 +44,9 @@ class LoginResult extends BaseResult { r.success = data["success"]; r.error = data["error"] as String? ?? ""; r.id = data["id"]; - r.username = data["username"]; - r.eMail = data["eMail"]; - r.token = data["token"]; + r.username = data["username"] as String? ?? ""; + r.eMail = data["eMail"] as String? ?? ""; + r.token = data["token"] as String? ?? ""; return r; } } From a92beeed3bb6cb53915de5fe119a2998e406f5db Mon Sep 17 00:00:00 2001 From: susch19 Date: Mon, 6 Jun 2022 19:25:46 +0200 Subject: [PATCH 10/23] Increased version to v0.30 --- android/app/src/main/AndroidManifest.xml | 2 +- lib/pages/about.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 30d8ad8..939f85c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + diff --git a/lib/pages/about.dart b/lib/pages/about.dart index 4d94a49..31bae0a 100644 --- a/lib/pages/about.dart +++ b/lib/pages/about.dart @@ -71,7 +71,7 @@ class AboutPage extends StatelessWidget { ), ), ListTile( - title: Text("Version 0.27"), + title: Text("Version 0.30"), ), Divider(), ListTile( From a00c4538048291072b04bc73c3a13f4b939461bc Mon Sep 17 00:00:00 2001 From: Daniel Henk Date: Sat, 25 Jun 2022 17:59:42 +0200 Subject: [PATCH 11/23] Adds function to add recipe ingredients When adding a new list, you can now choose if you want to add a new shopping list or a new chefkoch(recipe) list. When choosing recipe then you can enter a link or the id to the chefkoch recipe. Then a new shopping list with all ingredients will be added. --- lib/localization/nssl_messages_de.dart | 5 ++ lib/localization/nssl_messages_en.dart | 5 ++ lib/localization/nssl_strings.dart | 5 ++ lib/pages/main_page.dart | 62 ++++++++++++++++++- lib/server_communication/jwt.dart | 5 +- lib/server_communication/request_classes.dart | 16 ++--- .../shopping_list_sync.dart | 61 +++++++++--------- 7 files changed, 114 insertions(+), 45 deletions(-) diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index 485b97a..be23e91 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -31,6 +31,11 @@ class MessageLookup extends MessageLookupByLibrary { "renameListTitle": MessageLookupByLibrary.simpleMessage("Liste umbenennen"), "renameListHint": MessageLookupByLibrary.simpleMessage("Der neue Name der Liste"), "addNewListTitle": MessageLookupByLibrary.simpleMessage("Füge eine neue Liste hinzu"), + "recipeName": MessageLookupByLibrary.simpleMessage("Rezept"), + "recipeNameHint": MessageLookupByLibrary.simpleMessage("Rezept ID oder URL"), + "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Füge eine neues Rezept hinzu"), + "chooseAddListDialog": MessageLookupByLibrary.simpleMessage("Einkaufen"), + "chooseAddRecipeDialog": MessageLookupByLibrary.simpleMessage("Chefkoch"), "youHaveActionItemMessage": MessageLookupByLibrary.simpleMessage('Du hast '), //\$action \$item "archived": MessageLookupByLibrary.simpleMessage('archiviert'), "deleted": MessageLookupByLibrary.simpleMessage('gelöscht'), diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index 355d667..ad10d0b 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -32,6 +32,11 @@ class MessageLookup extends MessageLookupByLibrary { "renameListTitle": MessageLookupByLibrary.simpleMessage("Rename List"), "renameListHint": MessageLookupByLibrary.simpleMessage('The name of the new list'), "addNewListTitle": MessageLookupByLibrary.simpleMessage("Add new List"), + "recipeName": MessageLookupByLibrary.simpleMessage("Recipe"), + "recipeNameHint": MessageLookupByLibrary.simpleMessage("Recipe ID or URL"), + "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Add new recipe"), + "chooseAddListDialog": MessageLookupByLibrary.simpleMessage("Shopping"), + "chooseAddRecipeDialog": MessageLookupByLibrary.simpleMessage("Chefkoch"), "youHaveActionItemMessage": MessageLookupByLibrary.simpleMessage('You have '), //\$action \$item "archived": MessageLookupByLibrary.simpleMessage('archived'), "deleted": MessageLookupByLibrary.simpleMessage('deleted'), diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index d51ba99..deb5229 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -47,6 +47,11 @@ class NSSLStrings { String renameListTitle() => Intl.message('Rename List', name: 'renameListTitle', locale: _localeName); String renameListHint() => Intl.message('The name of the new list', name: 'renameListHint', locale: _localeName); String addNewListTitle() => Intl.message('Add new List', name: 'addNewListTitle', locale: _localeName); + String recipeName() => Intl.message('Recipe', name: 'recipeName', locale: _localeName); + String recipeNameHint() => Intl.message('Recipe ID or URL', name: 'recipeNameHint', locale: _localeName); + String addNewRecipeTitle() => Intl.message('Add new recipe', name: 'addNewRecipeTitle', locale: _localeName); + String chooseAddListDialog() => Intl.message('Shopping', name: 'chooseAddListDialog', locale: _localeName); + String chooseAddRecipeDialog() => Intl.message('Chefkoch', name: 'chooseAddRecipeDialog', locale: _localeName); String youHaveActionItemMessage() => Intl.message('You have ', name: 'youHaveActionItemMessage', locale: _localeName); String archived() => Intl.message('archived', name: 'archived', locale: _localeName); String deleted() => Intl.message('deleted', name: 'deleted', locale: _localeName); diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 6c2f2af..330f6ae 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -263,6 +263,31 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi builder: (BuildContext context) => AddProductToDatabase(ean), fullscreenDialog: true)); } + void chooseListToAddDialog() { + var dialog = AlertDialog( + title: Text("Was?"), + actions: [ + TextButton(child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () => Navigator.pop(context, "")), + TextButton( + child: Text(NSSLStrings.of(context).chooseAddListDialog()), + onPressed: () { + Navigator.pop(context, ""); + addListDialog(); + }, + ), + TextButton( + child: Text(NSSLStrings.of(context).chooseAddRecipeDialog()), + onPressed: () { + Navigator.pop(context, ""); + addRecipeDialog(); + }, + ), + ], + ); + + showDialog(builder: (BuildContext context) => dialog, context: context, barrierDismissible: false); + } + void addListDialog() { var sd = SimpleDialogSingleInput.create( hintText: NSSLStrings.of(context).newNameOfListHint(), @@ -274,6 +299,17 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi showDialog(builder: (BuildContext context) => sd, context: context, barrierDismissible: false); } + void addRecipeDialog() { + var sd = SimpleDialogSingleInput.create( + hintText: NSSLStrings.of(context).recipeNameHint(), + labelText: NSSLStrings.of(context).recipeName(), + onSubmitted: createNewRecipe, + title: NSSLStrings.of(context).addNewRecipeTitle(), + context: context); + + showDialog(builder: (BuildContext context) => sd, context: context, barrierDismissible: false); + } + Future renameListDialog(int listId) { return showDialog( context: context, @@ -286,6 +322,27 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi context: context)); } + Future createNewRecipe(String idOrUrl) async { + var provider = ref.read(shoppingListsProvider); + var indexProvider = ref.watch(currentListIndexProvider.notifier); + var res = await ShoppingListSync.addRecipe(idOrUrl, context); + var newListRes = GetListResult.fromJson(res.body); + var newList = ShoppingList(newListRes.id!, newListRes.name!); + + var items = ref.watch(shoppingItemsProvider.notifier); + var newState = items.state.toList(); + if (newListRes.products != null) + newState.addAll(newListRes.products!.map((e) => ShoppingItem(e.name, newList.id, e.sortOrder, + amount: e.amount, id: e.id, created: e.created, changed: e.changed))); + + items.state = newState; + + provider.addList(newList); + + indexProvider.state = provider.shoppingLists.indexOf(newList); + provider.save(newList); + } + Future createNewList(String listName) async { var provider = ref.read(shoppingListsProvider); var currentListProvider = ref.watch(currentListIndexProvider.notifier); @@ -430,7 +487,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi onRefresh: _handleDrawerRefresh, displacement: 1.0), persistentFooterButtons: [ - TextButton(child: Text(NSSLStrings.of(context).addListPB()), onPressed: addListDialog) + TextButton(child: Text(NSSLStrings.of(context).addListPB()), onPressed: chooseListToAddDialog) ]); return Drawer(child: d); @@ -483,7 +540,8 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi if (!(res.success)) showInDrawerSnackBar(res.error); else { - var currentList = ref.read(currentListProvider)!; + var currentList = ref.read(currentListProvider); + if (currentList == null) return; var shoppingListController = ref.read(shoppingListsProvider); if (currentList.id == id) { var other = shoppingListController.shoppingLists.firstOrNull((l) => l.id != id); diff --git a/lib/server_communication/jwt.dart b/lib/server_communication/jwt.dart index 8c0b762..8b41398 100644 --- a/lib/server_communication/jwt.dart +++ b/lib/server_communication/jwt.dart @@ -28,9 +28,8 @@ class JWT { //JsonWebToken jwt = JsonWebToken.decode(token); //var map = jwt.payload.toJson(); //return int.parse(map["id"]); - String jwt = tokenToJson(token); - var exp = jwt.substring(jwt.indexOf("id"), jwt.indexOf(',\n', jwt.indexOf("id"))); - return int.parse(exp.substring(5)); + var jwt = jsonDecode(tokenToJson(token)); + return jwt["id"]; // DateTime.parse("2018-07-07T10:49:56.9479953Z"); // var codec = Base64Codec.urlSafe(); diff --git a/lib/server_communication/request_classes.dart b/lib/server_communication/request_classes.dart index ecd8085..52d8b33 100644 --- a/lib/server_communication/request_classes.dart +++ b/lib/server_communication/request_classes.dart @@ -57,6 +57,12 @@ class AddListArgs { toJson() => {"name": "$name"}; } +class AddRecipeArgs { + AddRecipeArgs(this.idOrUrl); + String idOrUrl; + toJson() => {"idOrUrl": "$idOrUrl"}; +} + class DeleteProductArgs { DeleteProductArgs(this.listId, this.productId); int listId; @@ -68,8 +74,7 @@ class AddProductArgs { String? productName; String? gtin; int? amount; - toJson() => - {"productName": "$productName", "gtin": "$gtin", "amount": "$amount"}; + toJson() => {"productName": "$productName", "gtin": "$gtin", "amount": "$amount"}; } class AddNewProductArgs { @@ -78,12 +83,7 @@ class AddNewProductArgs { String? gtin; String? unit; double quantity; - toJson() => { - "name": "$name", - "gtin": "$gtin", - "unit": "$unit", - "quantity": "$quantity" - }; + toJson() => {"name": "$name", "gtin": "$gtin", "unit": "$unit", "quantity": "$quantity"}; } class GetProductsArgs { diff --git a/lib/server_communication/shopping_list_sync.dart b/lib/server_communication/shopping_list_sync.dart index 832a9f0..96fb7ed 100644 --- a/lib/server_communication/shopping_list_sync.dart +++ b/lib/server_communication/shopping_list_sync.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 's_c.dart'; @@ -8,67 +7,65 @@ import 'package:http/http.dart'; final String listpath = "shoppinglists"; class ShoppingListSync { - static Future getList(int? listId,BuildContext? context, {bool bought = false}) => + static Future getList(int? listId, BuildContext? context, {bool bought = false}) => HelperMethods.get("$listpath/$listId/$bought", context); - static Future getLists(BuildContext? context) => - HelperMethods.get("$listpath/batchaction/", context); + static Future getLists(BuildContext? context) => HelperMethods.get("$listpath/batchaction/", context); - static Future deleteList(int listId,BuildContext? context) => + static Future deleteList(int listId, BuildContext? context) => HelperMethods.delete("$listpath/$listId", context); - static Future changeLName(int listId, String newName,BuildContext? context) => + static Future changeLName(int listId, String newName, BuildContext? context) => HelperMethods.put("$listpath/$listId", context, ChangeListNameArgs(newName)); - static Future addList(String listName,BuildContext? context) => + static Future addList(String listName, BuildContext? context) => HelperMethods.post("$listpath", context, AddListArgs(listName)); - static Future deleteProduct(int? listId, int? productId,BuildContext context) => + static Future addRecipe(String idOrUrl, BuildContext? context) => + HelperMethods.post("recipe/CreateShoppingListForRecipe", context, AddRecipeArgs(idOrUrl)); + + static Future deleteProduct(int? listId, int? productId, BuildContext context) => HelperMethods.delete("$listpath/$listId/products/$productId", context); - static Future deleteProducts(int? listId, List productIds,BuildContext? context) => + static Future deleteProducts(int? listId, List productIds, BuildContext? context) => HelperMethods.post("$listpath/$listId/products/batchaction/delete", context, DeleteProductsArgs(productIds)); static Future addProduct( - int? listId, String? productName, String? gtin, int amount,BuildContext? context) => + int? listId, String? productName, String? gtin, int amount, BuildContext? context) => HelperMethods.post( - "$listpath/$listId/products/", context, + "$listpath/$listId/products/", + context, AddProductArgs() ..amount = amount ..gtin = gtin ..productName = productName); - static Future changeProductAmount( - int? listId, int? productId, int? change,BuildContext? context) => - HelperMethods.put("$listpath/$listId/products/$productId", context, - ChangeProductArgs(change: change, newName: "")); + static Future changeProductAmount(int? listId, int? productId, int? change, BuildContext? context) => + HelperMethods.put( + "$listpath/$listId/products/$productId", context, ChangeProductArgs(change: change, newName: "")); - static Future changeProductName( - int? listId, int? productId, String newName,BuildContext? context) => - HelperMethods.put("$listpath/$listId/products/$productId", context, - ChangeProductArgs(change: 0, newName: newName)); + static Future changeProductName(int? listId, int? productId, String newName, BuildContext? context) => + HelperMethods.put( + "$listpath/$listId/products/$productId", context, ChangeProductArgs(change: 0, newName: newName)); static Future changeProducts( - int? listId, List productIds, List amount,BuildContext? context) => - HelperMethods.post("$listpath/$listId/products/batchaction/change", context, - ChangeProductsArgs(productIds, amount)); + int? listId, List productIds, List amount, BuildContext? context) => + HelperMethods.post( + "$listpath/$listId/products/batchaction/change", context, ChangeProductsArgs(productIds, amount)); - static Future reorderProducts(int? listId, List productIds,BuildContext context) => + static Future reorderProducts(int? listId, List productIds, BuildContext context) => HelperMethods.post("$listpath/$listId/products/batchaction/order", context, DeleteProductsArgs(productIds)); - - static Future deleteContributor( - int listId, int userId,BuildContext context) //Wenn lokal gespeichert + static Future deleteContributor(int listId, int userId, BuildContext context) //Wenn lokal gespeichert => HelperMethods.delete("$listpath/$listId/contributors/$userId", context); - static Future addContributor(int listId, String contributorName,BuildContext context) => - HelperMethods.post("$listpath/$listId/contributors/", context, - AddContributorArgs(contributorName)); + static Future addContributor(int listId, String contributorName, BuildContext context) => + HelperMethods.post("$listpath/$listId/contributors/", context, AddContributorArgs(contributorName)); - static Future getContributors(int listId,BuildContext context) => + static Future getContributors(int listId, BuildContext context) => HelperMethods.get("$listpath/$listId/contributors/", context); - static Future changeRight(int listId, int changedUser,BuildContext context) - => HelperMethods.put("$listpath/$listId/contributors/$changedUser", context); + static Future changeRight(int listId, int changedUser, BuildContext context) => + HelperMethods.put("$listpath/$listId/contributors/$changedUser", context); } From d18d8c3282b8141e5c8eb7cfe55ccb0ef7e6f1d1 Mon Sep 17 00:00:00 2001 From: Daniel Henk Date: Sun, 26 Jun 2022 12:03:34 +0200 Subject: [PATCH 12/23] Fixes not deleting local shopping list When deleting all local lists we wouldn't delete them from the local db Co-Authored-By: Sascha <13682907+susch19@users.noreply.github.com> --- lib/pages/main_page.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 330f6ae..e1c7ad9 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -541,9 +541,8 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi showInDrawerSnackBar(res.error); else { var currentList = ref.read(currentListProvider); - if (currentList == null) return; var shoppingListController = ref.read(shoppingListsProvider); - if (currentList.id == id) { + if (currentList == null || currentList.id == id) { var other = shoppingListController.shoppingLists.firstOrNull((l) => l.id != id); if (other != null) changeCurrentList(shoppingListController.shoppingLists.indexOf(other)); } From 38eaf7b724ed5eee3513f568744edee490e42adb Mon Sep 17 00:00:00 2001 From: Daniel Henk Date: Sun, 26 Jun 2022 13:26:05 +0200 Subject: [PATCH 13/23] Makes the choose list dialog better We now use a Listview with ListTiles --- lib/localization/nssl_messages_de.dart | 1 + lib/localization/nssl_messages_en.dart | 1 + lib/localization/nssl_strings.dart | 2 ++ lib/pages/main_page.dart | 39 ++++++++++++++++---------- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index be23e91..da50444 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -30,6 +30,7 @@ class MessageLookup extends MessageLookupByLibrary { "listName": MessageLookupByLibrary.simpleMessage("Listenname"), "renameListTitle": MessageLookupByLibrary.simpleMessage("Liste umbenennen"), "renameListHint": MessageLookupByLibrary.simpleMessage("Der neue Name der Liste"), + "chooseListToAddTitle": MessageLookupByLibrary.simpleMessage("Welche Liste hinzufügen?"), "addNewListTitle": MessageLookupByLibrary.simpleMessage("Füge eine neue Liste hinzu"), "recipeName": MessageLookupByLibrary.simpleMessage("Rezept"), "recipeNameHint": MessageLookupByLibrary.simpleMessage("Rezept ID oder URL"), diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index ad10d0b..784b481 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -31,6 +31,7 @@ class MessageLookup extends MessageLookupByLibrary { "listName": MessageLookupByLibrary.simpleMessage('listname'), "renameListTitle": MessageLookupByLibrary.simpleMessage("Rename List"), "renameListHint": MessageLookupByLibrary.simpleMessage('The name of the new list'), + "chooseListToAddTitle": MessageLookupByLibrary.simpleMessage('Which list to add?'), "addNewListTitle": MessageLookupByLibrary.simpleMessage("Add new List"), "recipeName": MessageLookupByLibrary.simpleMessage("Recipe"), "recipeNameHint": MessageLookupByLibrary.simpleMessage("Recipe ID or URL"), diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index deb5229..6230a18 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -46,6 +46,8 @@ class NSSLStrings { String listName() => Intl.message('Listname', name: 'listName', locale: _localeName); String renameListTitle() => Intl.message('Rename List', name: 'renameListTitle', locale: _localeName); String renameListHint() => Intl.message('The name of the new list', name: 'renameListHint', locale: _localeName); + String chooseListToAddTitle() => + Intl.message('Which list to add?', name: 'chooseListToAddTitle', locale: _localeName); String addNewListTitle() => Intl.message('Add new List', name: 'addNewListTitle', locale: _localeName); String recipeName() => Intl.message('Recipe', name: 'recipeName', locale: _localeName); String recipeNameHint() => Intl.message('Recipe ID or URL', name: 'recipeNameHint', locale: _localeName); diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index e1c7ad9..308303d 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -265,23 +265,32 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi void chooseListToAddDialog() { var dialog = AlertDialog( - title: Text("Was?"), + title: Text(NSSLStrings.of(context).chooseListToAddTitle()), + content: Container( + width: 80, + child: ListView( + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: [ + ListTile( + title: Text(NSSLStrings.of(context).chooseAddListDialog()), + onTap: () { + Navigator.pop(context, ""); + addListDialog(); + }, + ), + ListTile( + title: Text(NSSLStrings.of(context).chooseAddRecipeDialog()), + onTap: () { + Navigator.pop(context, ""); + addRecipeDialog(); + }, + ), + ], + ), + ), actions: [ TextButton(child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () => Navigator.pop(context, "")), - TextButton( - child: Text(NSSLStrings.of(context).chooseAddListDialog()), - onPressed: () { - Navigator.pop(context, ""); - addListDialog(); - }, - ), - TextButton( - child: Text(NSSLStrings.of(context).chooseAddRecipeDialog()), - onPressed: () { - Navigator.pop(context, ""); - addRecipeDialog(); - }, - ), ], ); From ae46e76a9a04b9c3ac998fb0156b01ac79d37939 Mon Sep 17 00:00:00 2001 From: Daniel Henk Date: Sun, 26 Jun 2022 22:51:47 +0200 Subject: [PATCH 14/23] Adds possibility to import recipe into current list Also makes the choose new list dialog nicer --- lib/localization/nssl_messages_de.dart | 4 ++- lib/localization/nssl_messages_en.dart | 2 ++ lib/localization/nssl_strings.dart | 2 ++ lib/pages/main_page.dart | 28 ++++++++++++++++--- lib/server_communication/helper_methods.dart | 12 ++++---- .../shopping_list_sync.dart | 7 +++++ 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index da50444..ea08363 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -34,7 +34,9 @@ class MessageLookup extends MessageLookupByLibrary { "addNewListTitle": MessageLookupByLibrary.simpleMessage("Füge eine neue Liste hinzu"), "recipeName": MessageLookupByLibrary.simpleMessage("Rezept"), "recipeNameHint": MessageLookupByLibrary.simpleMessage("Rezept ID oder URL"), - "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Füge eine neues Rezept hinzu"), + "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Neues Rezept hinzufügen"), + "importNewRecipe": MessageLookupByLibrary.simpleMessage("Rezept importieren"), + "importNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Neues Rezept importieren"), "chooseAddListDialog": MessageLookupByLibrary.simpleMessage("Einkaufen"), "chooseAddRecipeDialog": MessageLookupByLibrary.simpleMessage("Chefkoch"), "youHaveActionItemMessage": MessageLookupByLibrary.simpleMessage('Du hast '), //\$action \$item diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index 784b481..5321c33 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -36,6 +36,8 @@ class MessageLookup extends MessageLookupByLibrary { "recipeName": MessageLookupByLibrary.simpleMessage("Recipe"), "recipeNameHint": MessageLookupByLibrary.simpleMessage("Recipe ID or URL"), "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Add new recipe"), + "importNewRecipe": MessageLookupByLibrary.simpleMessage("Import recipe"), + "importNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Import new recipe"), "chooseAddListDialog": MessageLookupByLibrary.simpleMessage("Shopping"), "chooseAddRecipeDialog": MessageLookupByLibrary.simpleMessage("Chefkoch"), "youHaveActionItemMessage": MessageLookupByLibrary.simpleMessage('You have '), //\$action \$item diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index 6230a18..2f9e403 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -52,6 +52,8 @@ class NSSLStrings { String recipeName() => Intl.message('Recipe', name: 'recipeName', locale: _localeName); String recipeNameHint() => Intl.message('Recipe ID or URL', name: 'recipeNameHint', locale: _localeName); String addNewRecipeTitle() => Intl.message('Add new recipe', name: 'addNewRecipeTitle', locale: _localeName); + String importNewRecipe() => Intl.message('Import recipe', name: 'importNewRecipe', locale: _localeName); + String importNewRecipeTitle() => Intl.message('Import new recipe', name: 'importNewRecipeTitle', locale: _localeName); String chooseAddListDialog() => Intl.message('Shopping', name: 'chooseAddListDialog', locale: _localeName); String chooseAddRecipeDialog() => Intl.message('Chefkoch', name: 'chooseAddRecipeDialog', locale: _localeName); String youHaveActionItemMessage() => Intl.message('You have ', name: 'youHaveActionItemMessage', locale: _localeName); diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 308303d..9dfa444 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -206,6 +206,9 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi var reordering = ref.watch(_isReorderingProvider.notifier); reordering.state = !reordering.state; break; + case "recipeImport": + addRecipeDialog(true); + break; } } @@ -283,7 +286,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi title: Text(NSSLStrings.of(context).chooseAddRecipeDialog()), onTap: () { Navigator.pop(context, ""); - addRecipeDialog(); + addRecipeDialog(false); }, ), ], @@ -308,12 +311,12 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi showDialog(builder: (BuildContext context) => sd, context: context, barrierDismissible: false); } - void addRecipeDialog() { + void addRecipeDialog(bool import) { var sd = SimpleDialogSingleInput.create( hintText: NSSLStrings.of(context).recipeNameHint(), labelText: NSSLStrings.of(context).recipeName(), - onSubmitted: createNewRecipe, - title: NSSLStrings.of(context).addNewRecipeTitle(), + onSubmitted: import ? importNewRecipe : createNewRecipe, + title: import ? NSSLStrings.of(context).importNewRecipeTitle() : NSSLStrings.of(context).addNewRecipeTitle(), context: context); showDialog(builder: (BuildContext context) => sd, context: context, barrierDismissible: false); @@ -335,6 +338,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi var provider = ref.read(shoppingListsProvider); var indexProvider = ref.watch(currentListIndexProvider.notifier); var res = await ShoppingListSync.addRecipe(idOrUrl, context); + if (res.statusCode >= 400) return; var newListRes = GetListResult.fromJson(res.body); var newList = ShoppingList(newListRes.id!, newListRes.name!); @@ -352,6 +356,18 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi provider.save(newList); } + Future importNewRecipe(String idOrUrl) async { + var list = ref.read(currentListProvider); + if (list == null) return; + + var provider = ref.read(shoppingListsProvider); + var res = await ShoppingListSync.importRecipe(idOrUrl, list.id, context); + + if (res.statusCode >= 400) return; + + provider.refresh(list); + } + Future createNewList(String listName) async { var provider = ref.read(shoppingListsProvider); var currentListProvider = ref.watch(currentListIndexProvider.notifier); @@ -777,6 +793,10 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi NSSLStrings.of(context).reorderItems(), ), ), + PopupMenuItem( + value: 'recipeImport', + child: Text(NSSLStrings.of(context).importNewRecipe()), + ), PopupMenuItem( value: 'options', child: Text( diff --git a/lib/server_communication/helper_methods.dart b/lib/server_communication/helper_methods.dart index 8c80646..a497cf7 100644 --- a/lib/server_communication/helper_methods.dart +++ b/lib/server_communication/helper_methods.dart @@ -11,14 +11,16 @@ import 'user_sync.dart'; class HelperMethods { static const String scheme = "https"; static const String host = "nssl.susch.eu"; + static const int port = 80; // static const String scheme = "http"; // static const String host = "192.168.49.22"; // static const String url = "http://192.168.49.22:4344"; static Future post(String path, BuildContext? context, - [Object? body, skipTokenRefresh = false]) async { + [Object? body, skipTokenRefresh = false, Map? query]) async { if (!skipTokenRefresh) await handleTokenRefresh(context); - var res = await http.post(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), + var res = await http.post( + Uri(host: host, scheme: scheme, path: path, port: port, queryParameters: query /*, port: 4344*/), body: jsonEncode(body), headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); @@ -27,7 +29,7 @@ class HelperMethods { static Future get(String path, BuildContext? context, [String query = ""]) async { await handleTokenRefresh(context); - var res = await http.get(Uri(host: host, scheme: scheme, path: path, query: query /*, port: 4344*/), + var res = await http.get(Uri(host: host, scheme: scheme, path: path, query: query, port: port /*, port: 4344*/), headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); return res; @@ -36,7 +38,7 @@ class HelperMethods { static Future put(String path, BuildContext? context, [Object? body, bool skipTokenRefresh = false]) async { if (!skipTokenRefresh) await handleTokenRefresh(context); - var res = await http.put(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), + var res = await http.put(Uri(host: host, scheme: scheme, path: path, port: port /*, port: 4344*/), body: jsonEncode(body), headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); @@ -45,7 +47,7 @@ class HelperMethods { static Future delete(String path, BuildContext? context) async { await handleTokenRefresh(context); - var res = await http.delete(Uri(host: host, scheme: scheme, path: path /*, port: 4344*/), + var res = await http.delete(Uri(host: host, scheme: scheme, path: path, port: port /*, port: 4344*/), headers: {"Content-Type": "application/json", User.token == "" ? "X-foo" : "X-Token": User.token}); reactToRespone(res, context); diff --git a/lib/server_communication/shopping_list_sync.dart b/lib/server_communication/shopping_list_sync.dart index 96fb7ed..1c404f3 100644 --- a/lib/server_communication/shopping_list_sync.dart +++ b/lib/server_communication/shopping_list_sync.dart @@ -24,6 +24,13 @@ class ShoppingListSync { static Future addRecipe(String idOrUrl, BuildContext? context) => HelperMethods.post("recipe/CreateShoppingListForRecipe", context, AddRecipeArgs(idOrUrl)); + static Future importRecipe(String idOrUrl, int listId, BuildContext? context) => HelperMethods.post( + "recipe/AddRecipeToList", + context, + AddRecipeArgs(idOrUrl), + false, + {"amountOfPeople": "4", "listId": listId.toString()}); + static Future deleteProduct(int? listId, int? productId, BuildContext context) => HelperMethods.delete("$listpath/$listId/products/$productId", context); From 8b848349e311455ffe31c56ea4f1217b96d93fe7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 27 Jun 2022 21:42:31 +0200 Subject: [PATCH 15/23] Use 443 port Co-authored-by: Sascha --- lib/server_communication/helper_methods.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/server_communication/helper_methods.dart b/lib/server_communication/helper_methods.dart index a497cf7..4638603 100644 --- a/lib/server_communication/helper_methods.dart +++ b/lib/server_communication/helper_methods.dart @@ -11,7 +11,7 @@ import 'user_sync.dart'; class HelperMethods { static const String scheme = "https"; static const String host = "nssl.susch.eu"; - static const int port = 80; + static const int port = 443; // static const String scheme = "http"; // static const String host = "192.168.49.22"; // static const String url = "http://192.168.49.22:4344"; From 06ca61ecc31c31d63f5dc9621e87fba691d7b1c6 Mon Sep 17 00:00:00 2001 From: susch19 Date: Sat, 2 Jul 2022 11:57:18 +0200 Subject: [PATCH 16/23] Updated the android dependency version * include the required export flag, so nssl can be launched from other applications by its name * increase the gradle version to the latest available, as the current version had problems during ci build --- android/app/src/main/AndroidManifest.xml | 2 +- android/build.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 939f85c..dd20825 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,7 +5,7 @@ - + diff --git a/android/build.gradle b/android/build.gradle index 0ac86c6..138d59a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,8 +8,8 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.3' - classpath 'com.google.gms:google-services:4.3.8' + classpath 'com.android.tools.build:gradle:7.2.1' + classpath 'com.google.gms:google-services:4.3.13' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } From 6cd70143494728fe0382044f5964c1c4ef6086f6 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 5 Jul 2022 22:28:29 +0200 Subject: [PATCH 17/23] Allow to share recipe to add (#18) - Share recipes from browser through the share link option - Clicking on the "Auf die Einkaufsliste setzen" will pring a popup if you want to open the url with nssl --- android/app/src/main/AndroidManifest.xml | 21 ++- lib/generated_plugin_registrant.dart | 1 + lib/helper/choose_dialog.dart | 42 +++++ lib/localization/nssl_messages_de.dart | 3 + lib/localization/nssl_messages_en.dart | 3 + lib/localization/nssl_strings.dart | 4 + lib/pages/main_page.dart | 144 ++++++++++++++---- .../shopping_list_sync.dart | 3 + pubspec.yaml | 1 + 9 files changed, 189 insertions(+), 33 deletions(-) create mode 100644 lib/helper/choose_dialog.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index dd20825..3325051 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,11 +5,30 @@ - + + + + + + + + + + + + + + + + + diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart index 1527a79..ef2492d 100644 --- a/lib/generated_plugin_registrant.dart +++ b/lib/generated_plugin_registrant.dart @@ -4,6 +4,7 @@ // ignore_for_file: directives_ordering // ignore_for_file: lines_longer_than_80_chars +// ignore_for_file: depend_on_referenced_packages import 'package:firebase_core_web/firebase_core_web.dart'; import 'package:firebase_messaging_web/firebase_messaging_web.dart'; diff --git a/lib/helper/choose_dialog.dart b/lib/helper/choose_dialog.dart new file mode 100644 index 0000000..5a4f446 --- /dev/null +++ b/lib/helper/choose_dialog.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:nssl/localization/nssl_strings.dart'; + +class ChooseDialog { + static AlertDialog create( + {String title = "", + String titleOption1 = "", + Function? onOption1, + String titleOption2 = "", + Function? onOption2, + required BuildContext context}) { + return AlertDialog( + title: Text(NSSLStrings.of(context).chooseListToAddTitle()), + content: Container( + width: 80, + child: ListView( + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: [ + ListTile( + title: Text(titleOption1), + onTap: () { + Navigator.pop(context, ""); + onOption1?.call(); + }, + ), + ListTile( + title: Text(titleOption2), + onTap: () { + Navigator.pop(context, ""); + onOption2?.call(); + }, + ), + ], + ), + ), + actions: [ + TextButton(child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () => Navigator.pop(context, "")), + ], + ); + } +} diff --git a/lib/localization/nssl_messages_de.dart b/lib/localization/nssl_messages_de.dart index ea08363..2c990f3 100644 --- a/lib/localization/nssl_messages_de.dart +++ b/lib/localization/nssl_messages_de.dart @@ -32,6 +32,9 @@ class MessageLookup extends MessageLookupByLibrary { "renameListHint": MessageLookupByLibrary.simpleMessage("Der neue Name der Liste"), "chooseListToAddTitle": MessageLookupByLibrary.simpleMessage("Welche Liste hinzufügen?"), "addNewListTitle": MessageLookupByLibrary.simpleMessage("Füge eine neue Liste hinzu"), + "recipeCreateError": MessageLookupByLibrary.simpleMessage("Konnte Rezept nicht erstellen"), + "recipeFromShareTitle": MessageLookupByLibrary.simpleMessage("Zu welcher Liste hinzufügen?"), + "recipeFromShareNew": MessageLookupByLibrary.simpleMessage("NEU"), "recipeName": MessageLookupByLibrary.simpleMessage("Rezept"), "recipeNameHint": MessageLookupByLibrary.simpleMessage("Rezept ID oder URL"), "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Neues Rezept hinzufügen"), diff --git a/lib/localization/nssl_messages_en.dart b/lib/localization/nssl_messages_en.dart index 5321c33..5c6cd0e 100644 --- a/lib/localization/nssl_messages_en.dart +++ b/lib/localization/nssl_messages_en.dart @@ -33,6 +33,9 @@ class MessageLookup extends MessageLookupByLibrary { "renameListHint": MessageLookupByLibrary.simpleMessage('The name of the new list'), "chooseListToAddTitle": MessageLookupByLibrary.simpleMessage('Which list to add?'), "addNewListTitle": MessageLookupByLibrary.simpleMessage("Add new List"), + "recipeCreateError": MessageLookupByLibrary.simpleMessage("Could not create recipe"), + "recipeFromShareTitle": MessageLookupByLibrary.simpleMessage("To which list to add?"), + "recipeFromShareNew": MessageLookupByLibrary.simpleMessage("NEW"), "recipeName": MessageLookupByLibrary.simpleMessage("Recipe"), "recipeNameHint": MessageLookupByLibrary.simpleMessage("Recipe ID or URL"), "addNewRecipeTitle": MessageLookupByLibrary.simpleMessage("Add new recipe"), diff --git a/lib/localization/nssl_strings.dart b/lib/localization/nssl_strings.dart index 2f9e403..fc17aa2 100644 --- a/lib/localization/nssl_strings.dart +++ b/lib/localization/nssl_strings.dart @@ -49,6 +49,10 @@ class NSSLStrings { String chooseListToAddTitle() => Intl.message('Which list to add?', name: 'chooseListToAddTitle', locale: _localeName); String addNewListTitle() => Intl.message('Add new List', name: 'addNewListTitle', locale: _localeName); + String recipeCreateError() => Intl.message('Could not create recipe', name: 'recipeCreateError', locale: _localeName); + String recipeFromShareTitle() => + Intl.message('To which list to add?', name: 'recipeFromShareTitle', locale: _localeName); + String recipeFromShareNew() => Intl.message('NEW', name: 'recipeFromShareNew', locale: _localeName); String recipeName() => Intl.message('Recipe', name: 'recipeName', locale: _localeName); String recipeNameHint() => Intl.message('Recipe ID or URL', name: 'recipeNameHint', locale: _localeName); String addNewRecipeTitle() => Intl.message('Add new recipe', name: 'addNewRecipeTitle', locale: _localeName); diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 9dfa444..dcf8b37 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:adaptive_theme/adaptive_theme.dart'; +import 'package:nssl/helper/choose_dialog.dart'; import 'package:nssl/helper/simple_dialog.dart'; import 'package:nssl/manager/export_manager.dart'; import 'package:nssl/options/themes.dart'; @@ -14,9 +15,11 @@ import 'package:flutter/material.dart'; import 'dart:async'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/helper/iterable_extensions.dart'; +import 'package:share_handler/share_handler.dart'; import '../main.dart'; import 'barcode_scanner_page.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter/services.dart' show PlatformException; class MainPage extends ConsumerStatefulWidget { @override @@ -37,6 +40,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi bool _showDrawerContents = true; bool insideSortAndOrderCrossedOut = false; bool insideUpdateOrderIndicies = false; + SharedMedia? media; @override Future didChangeAppLifecycleState(AppLifecycleState state) async { @@ -48,6 +52,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi @override void initState() { super.initState(); + initPlatformState(); WidgetsBinding.instance.addObserver(this); Startup.deleteMessagesFromFolder(); Startup.initializeNewListsFromServer(ref); @@ -267,36 +272,13 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi } void chooseListToAddDialog() { - var dialog = AlertDialog( - title: Text(NSSLStrings.of(context).chooseListToAddTitle()), - content: Container( - width: 80, - child: ListView( - shrinkWrap: true, - scrollDirection: Axis.vertical, - children: [ - ListTile( - title: Text(NSSLStrings.of(context).chooseAddListDialog()), - onTap: () { - Navigator.pop(context, ""); - addListDialog(); - }, - ), - ListTile( - title: Text(NSSLStrings.of(context).chooseAddRecipeDialog()), - onTap: () { - Navigator.pop(context, ""); - addRecipeDialog(false); - }, - ), - ], - ), - ), - actions: [ - TextButton(child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () => Navigator.pop(context, "")), - ], - ); - + var dialog = ChooseDialog.create( + context: context, + title: NSSLStrings.of(context).chooseListToAddTitle(), + titleOption1: NSSLStrings.of(context).chooseAddListDialog(), + onOption1: addListDialog, + titleOption2: NSSLStrings.of(context).chooseAddRecipeDialog(), + onOption2: () => addRecipeDialog(false)); showDialog(builder: (BuildContext context) => dialog, context: context, barrierDismissible: false); } @@ -338,7 +320,10 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi var provider = ref.read(shoppingListsProvider); var indexProvider = ref.watch(currentListIndexProvider.notifier); var res = await ShoppingListSync.addRecipe(idOrUrl, context); - if (res.statusCode >= 400) return; + if (res.statusCode >= 400) { + showInSnackBar(NSSLStrings.of(context).recipeCreateError() + (res.reasonPhrase ?? "")); + return; + } var newListRes = GetListResult.fromJson(res.body); var newList = ShoppingList(newListRes.id!, newListRes.name!); @@ -360,10 +345,19 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi var list = ref.read(currentListProvider); if (list == null) return; + importNewRecipeIntoList(list, idOrUrl); + } + + Future importNewRecipeIntoList(ShoppingList? list, String idOrUrl) async { + if (list == null) return; + var provider = ref.read(shoppingListsProvider); var res = await ShoppingListSync.importRecipe(idOrUrl, list.id, context); - if (res.statusCode >= 400) return; + if (res.statusCode >= 400) { + showInSnackBar(NSSLStrings.of(context).recipeCreateError() + (res.reasonPhrase ?? "")); + return; + } provider.refresh(list); } @@ -380,6 +374,92 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi provider.save(newList); } + Future initPlatformState() async { + final handler = ShareHandler.instance; + try { + media = await handler.getInitialSharedMedia(); + + handler.sharedMediaStream.listen((SharedMedia media) { + if (!mounted) return; + handleMediaFromShare(media); + }); + if (!mounted) return; + + handleMediaFromShare(media); + } on PlatformException {} + } + + void handleMediaFromShare(SharedMedia? media) { + if (media == null || media.content == null) return; + + var parsed = Uri.tryParse(media.content!); + + if (parsed == null) return; + + importRecipeFromSharedUri(parsed); + } + + Future importRecipeFromSharedUri(Uri uri) async { + var url = uri.toString(); + var result = await ShoppingListSync.checkRecipeInput(url, context); + + if (result.body != "true") { + showInSnackBar(NSSLStrings.of(context).recipeCreateError()); + return; + } + + var currList = ref.watch(currentListProvider); + var shoppingListsController = ref.watch(shoppingListsProvider); + var list = shoppingListsController.shoppingLists.copy(); + list.sort(((a, b) { + if (a.id == currList?.id) return -1; + if (b.id == currList?.id) return 1; + return 0; + })); + + var dialog = AlertDialog( + title: Text(NSSLStrings.of(context).recipeFromShareTitle()), + content: Container( + width: 80, + child: FractionallySizedBox( + heightFactor: 0.8, + child: ListView.builder( + padding: const EdgeInsets.all(8), + itemCount: list.length, + itemBuilder: (BuildContext context, int index) { + var currentSelected = list[index].id == currList?.id; + return Container( + height: 50, + child: ListTile( + onTap: () { + importNewRecipeIntoList(list[index], url); + Navigator.pop(context, ""); + }, + title: Text( + list[index].name, + style: TextStyle( + fontWeight: currentSelected ? FontWeight.bold : FontWeight.normal, + fontStyle: currentSelected ? FontStyle.italic : FontStyle.normal, + ), + ), + ), + ); + }), + ), + ), + actions: [ + TextButton(child: Text(NSSLStrings.of(context).cancelButton()), onPressed: () => Navigator.pop(context, "")), + TextButton( + child: Text(NSSLStrings.of(context).recipeFromShareNew()), + onPressed: () { + createNewRecipe(url); + Navigator.pop(context, ""); + }), + ], + ); + showDialog(builder: (BuildContext context) => dialog, context: context, barrierDismissible: false); + } + Widget _buildDrawer(BuildContext context) { var user = ref.watch(userProvider); var isDarkTheme = AdaptiveTheme.of(context).mode == AdaptiveThemeMode.dark; diff --git a/lib/server_communication/shopping_list_sync.dart b/lib/server_communication/shopping_list_sync.dart index 1c404f3..0221c6d 100644 --- a/lib/server_communication/shopping_list_sync.dart +++ b/lib/server_communication/shopping_list_sync.dart @@ -31,6 +31,9 @@ class ShoppingListSync { false, {"amountOfPeople": "4", "listId": listId.toString()}); + static Future checkRecipeInput(String idOrUrl, BuildContext? context) => + HelperMethods.post("recipe/IsValidIdOrUrl", context, AddRecipeArgs(idOrUrl)); + static Future deleteProduct(int? listId, int? productId, BuildContext context) => HelperMethods.delete("$listpath/$listId/products/$productId", context); diff --git a/pubspec.yaml b/pubspec.yaml index c63fc75..b67e9d0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,6 +36,7 @@ dependencies: # git: git://github.com/susch19/dart-json_web_token.git #jaguar_jwt: "^1.1.5" url_launcher: + share_handler: ^0.0.8 dev_dependencies: build_runner: ^2.0.6 From c67613b3abba45d6c3b072ccb50969d90f2d2888 Mon Sep 17 00:00:00 2001 From: Sascha Date: Thu, 7 Jul 2022 18:54:32 +0200 Subject: [PATCH 18/23] Added a new build for pull requests * which doesn't create a release, but attaches the builded outputs into the artifacts and should be able to validate if the code can build --- .github/workflows/build.yaml | 142 +++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 .github/workflows/build.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..3065cd1 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,142 @@ +name: Draft Github Release +on: + workflow_dispatch: + # Enable manual run + pull_request: + branches: [ "master", "develop" ] + +jobs: + + create-build: + name: Create ${{ matrix.target }} build + runs-on: ${{ matrix.os }} + strategy: + matrix: + target: [Android, Windows, Linux] + include: + - os: windows-2019 + target: Windows + build_target: windows + build_path: build\windows\runner\Release + asset_extension: .zip + asset_content_type: application/zip + - os: ubuntu-20.04 + target: Linux + build_target: linux + build_path: build/linux/x64/release/bundle + asset_extension: .tar.gz + asset_content_type: application/gzip + - os: ubuntu-20.04 + target: Android + build_target: apk + build_path: build/app/outputs/flutter-apk + asset_extension: .apk + asset_content_type: application/vnd.android.package-archive + # Disable fail-fast as we want results from all even if one fails. + fail-fast: false + needs: draft-release + steps: + # Set up Flutter. + - name: Clone Flutter repository with master channel + uses: subosito/flutter-action@4389e6cbc6cb8a4b18c628ff96ff90be0e926aa8 + with: + channel: master + + - name: Install Linux dependencies + if: matrix.target == 'Linux' + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libx11-dev pkg-config cmake ninja-build libblkid-dev + - name: Install Android dependencies + if: matrix.target == 'Android' + uses: actions/setup-java@v1 + with: + java-version: '12.x' + - name: Enable desktop support + if: matrix.target != 'Android' + run: | + flutter config --enable-linux-desktop + flutter config --enable-macos-desktop + flutter config --enable-windows-desktop + - run: flutter doctor -v + + + # Checkout NSSL code, recreate missing files, and get packages. + - name: Checkout NSSL code + uses: actions/checkout@v2 + - run: flutter create . --project-name nssl --org de.susch19 + - run: flutter pub get + - name: Configure Keystore for Android + if: matrix.target == 'Android' + run: | + echo "$KEY_STORE_FILE" | base64 --decode > app/nssl-keystore.jks + echo "storeFile=nssl-keystore.jks" >> key.properties + echo "keyAlias=$KEYSTORE_KEY_ALIAS" >> key.properties + echo "storePassword=$KEYSTORE_STORE_PASSWORD" >> key.properties + echo "keyPassword=$KEYSTORE_KEY_PASSWORD" >> key.properties + env: + KEY_STORE_FILE: ${{ secrets.KEY_STORE_FILE }} + KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }} + KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }} + KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }} + working-directory: android + + - name: Create License File Powershell + if: matrix.target == 'Windows' + run: | + [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("$Env:SCANDIT_LICENSE_FILE")) > .license.dart + working-directory: lib + env: + SCANDIT_LICENSE_FILE: ${{ secrets.SCANDIT_LICENSE_FILE }} + + - name: Create License File Bash + if: matrix.target != 'Windows' + run: | + echo "$SCANDIT_LICENSE_FILE" | base64 --decode > .license.dart + working-directory: lib + env: + SCANDIT_LICENSE_FILE: ${{ secrets.SCANDIT_LICENSE_FILE }} + + - name: Create Google Services Json File Bash + if: matrix.target != 'Windows' + run: | + echo "$GOOGLE_SERVICES_JSON" | base64 --decode > google-services.json + working-directory: android/app + env: + GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }} + + + # Build the application + - name: Build Flutter Application + run: flutter build -v ${{ matrix.build_target }} --release + + - name: Copy SQLite3 Dependency + if: matrix.target == 'Windows' + run: cp .\windows\libs\* ${{ matrix.build_path }} + + # Package the build. + - name: Copy VC redistributables to release directory for Windows + if: matrix.target == 'Windows' + run: | + Copy-Item (vswhere -latest -find 'VC\Redist\MSVC\*\x64\*\msvcp140.dll') . + Copy-Item (vswhere -latest -find 'VC\Redist\MSVC\*\x64\*\vcruntime140.dll') . + Copy-Item (vswhere -latest -find 'VC\Redist\MSVC\*\x64\*\vcruntime140_1.dll') . + - name: Rename build for Android + if: matrix.target == 'Android' + run: mv app-release.apk $GITHUB_WORKSPACE/nssl_${{ matrix.target }}.apk + working-directory: ${{ matrix.build_path }} + - name: Compress build for Linux + if: matrix.target == 'Linux' + run: tar czf $GITHUB_WORKSPACE/nssl_${{ matrix.target }}.tar.gz * + working-directory: ${{ matrix.build_path }} + - name: Compress build for Windows + if: matrix.target == 'Windows' + run: compress-archive -Path * -DestinationPath ${env:GITHUB_WORKSPACE}\nssl_${{ matrix.target }}.zip + working-directory: ${{ matrix.build_path }} + + # Upload the build. + - name: Add build into artifacts + uses: actions/upload-artifact@v2 + with: + name: nssl_${{ matrix.target }}${{ matrix.asset_extension }} + path: ./nssl_${{ matrix.target }}${{ matrix.asset_extension }} From 16559e3b5084597b0f086c6a5f222124f600fd70 Mon Sep 17 00:00:00 2001 From: Sascha Date: Thu, 7 Jul 2022 18:57:56 +0200 Subject: [PATCH 19/23] Remove requirement on create build * because it could never be satisfied, as there were no other jobs --- .github/workflows/build.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3065cd1..b40cdf6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -6,7 +6,6 @@ on: branches: [ "master", "develop" ] jobs: - create-build: name: Create ${{ matrix.target }} build runs-on: ${{ matrix.os }} @@ -34,7 +33,6 @@ jobs: asset_content_type: application/vnd.android.package-archive # Disable fail-fast as we want results from all even if one fails. fail-fast: false - needs: draft-release steps: # Set up Flutter. - name: Clone Flutter repository with master channel From 858bc32f410127581068780a7fba8a43366608df Mon Sep 17 00:00:00 2001 From: susch19 Date: Fri, 8 Jul 2022 22:49:37 +0200 Subject: [PATCH 20/23] Fixed ordering of tabs in history view * because having the most recent history at the front makes the most of sense and it was this way before the riverpod rework --- lib/pages/bought_items.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/bought_items.dart b/lib/pages/bought_items.dart index b85b783..e764e70 100644 --- a/lib/pages/bought_items.dart +++ b/lib/pages/bought_items.dart @@ -93,7 +93,7 @@ class _BoughtItemsPagePageState extends ConsumerState with Sing id: f.id, amount: f.amount, changed: f.changed, created: f.created, crossedOut: false))); DateTime date; - shoppingItems.sort((x, y) => x.changed!.compareTo(y.changed!)); + shoppingItems.sort((x, y) => y.changed!.compareTo(x.changed!)); for (var item in shoppingItems) { date = dateTimeToDate(item.changed!); if (!shoppingItemsGrouped.containsKey(dateTimeToDate(item.changed!))) From bc3ce59957feae0f77d561e546182f6af7217132 Mon Sep 17 00:00:00 2001 From: susch19 Date: Sat, 9 Jul 2022 12:31:06 +0200 Subject: [PATCH 21/23] Implemented new search in history * so that people can search for specific items that they bought in the past or even find out, when something was last bought * use riverpod for the history view, as this makes it easier to search and not reloading all items always from the server --- lib/pages/bought_items.dart | 259 ++++++++++++++++++++++++++---------- 1 file changed, 189 insertions(+), 70 deletions(-) diff --git a/lib/pages/bought_items.dart b/lib/pages/bought_items.dart index e764e70..cd0e257 100644 --- a/lib/pages/bought_items.dart +++ b/lib/pages/bought_items.dart @@ -1,3 +1,6 @@ +import 'dart:collection'; +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:nssl/localization/nssl_strings.dart'; import 'package:nssl/models/model_export.dart'; @@ -6,6 +9,86 @@ import 'package:nssl/server_communication/return_classes.dart'; import 'package:nssl/helper/iterable_extensions.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +final _historyDateTimesProvider = StateProvider>((ref) { + return []; +}); +final _shoppingItemsProvider = StateProvider>((ref) { + return []; +}); +final _searchModeProvider = StateProvider.autoDispose((ref) { + return false; +}); + +final _shoppingItemsGroupedProvider = Provider.family, DateTime>((ref, arg) { + var items = ref.watch(_shoppingItemsProvider); + + var forDate = DateTime.utc(arg.year, arg.month, arg.day); + return items.where((element) { + var changed = element.changed!; + var changedFormat = DateTime.utc(changed.year, changed.month, changed.day); + return changedFormat == forDate; + }); +}); + +final _filterProvider = StateProvider.autoDispose((ref) { + return ""; +}); +final _filterAsLowercaseProvider = Provider.autoDispose((ref) { + return ref.watch(_filterProvider).toLowerCase(); +}); + +final _filteredShoppingItemsGroupedProvider = Provider.family.autoDispose, DateTime>((ref, arg) { + var items = ref.watch(_shoppingItemsGroupedProvider(arg)); + var isFiltering = ref.watch(_searchModeProvider); + var filter = ref.watch(_filterAsLowercaseProvider); + return items.where((element) => !isFiltering || element.name.toLowerCase().contains(filter)); +}); + +final _filteredDateTimeProvider = Provider.autoDispose>( + (ref) { + var dates = ref.watch(_historyDateTimesProvider); + var isFiltering = ref.watch(_searchModeProvider); + var filter = ref.watch(_filterAsLowercaseProvider); + if (!isFiltering || filter.isEmpty) return dates; + + return dates.where((element) => ref + .read(_filteredShoppingItemsGroupedProvider(element)) + .any((element) => element.name.toLowerCase().contains(filter))); + }, +); + +final _tabCountProvider = Provider.autoDispose((ref) => ref.watch(_filteredDateTimeProvider).length); + +final _shoppingItemsFromServerProvider = + FutureProvider.autoDispose.family, int>((ref, listId) async { + var o = await ShoppingListSync.getList(listId, null, bought: true); + + if (o.statusCode == 500) { + return []; + } + + var z = GetBoughtListResult.fromJson(o.body); + + var shoppingItems = []; + + shoppingItems.addAll(z.products.map((f) => ShoppingItem(f.name, listId, f.sortOrder, + id: f.id, amount: f.amount, changed: f.changed, created: f.created, crossedOut: false))); + + ref.read(_shoppingItemsProvider.notifier).state = shoppingItems; + HashSet dates = HashSet(); + + DateTime dateTimeToDate(DateTime dateTime) { + return DateTime.utc(dateTime.year, dateTime.month, dateTime.day); + } + + for (var item in shoppingItems) dates.add(dateTimeToDate(item.changed!)); + var dateList = dates.toList(); + dateList.sort(((a, b) => b.compareTo(a))); + ref.read(_historyDateTimesProvider.notifier).state = dateList; + + return shoppingItems; +}); + class BoughtItemsPage extends ConsumerStatefulWidget { BoughtItemsPage(this.listId, {Key? key, this.title}) : super(key: key); final String? title; @@ -14,26 +97,49 @@ class BoughtItemsPage extends ConsumerStatefulWidget { _BoughtItemsPagePageState createState() => new _BoughtItemsPagePageState(listId); } -class _BoughtItemsPagePageState extends ConsumerState with SingleTickerProviderStateMixin { +class _BoughtItemsPagePageState extends ConsumerState with TickerProviderStateMixin { final GlobalKey _mainScaffoldKey = GlobalKey(); var tec = TextEditingController(); - var shoppingItemsGrouped = new Map>(); int k = 1; int listId; - TabController? _controller; + + late TabController _controller; @override void initState() { super.initState(); + _controller = TabController( + length: 0, + initialIndex: 0, + vsync: this, + ); + tec.addListener(() { + ref.read(_filterProvider.notifier).state = tec.text; + }); } @override void dispose() { - _controller!.dispose(); + _controller.dispose(); super.dispose(); } + void didUpdateWidget(covariant BoughtItemsPage oldWidget) { + super.didUpdateWidget(oldWidget); + + var count = ref.watch(_tabCountProvider); + if (count != _controller.length) { + final oldIndex = _controller.index; + _controller.dispose(); + _controller = TabController( + length: count, + initialIndex: max(0, min(oldIndex, count)), + vsync: this, + ); + } + } + _BoughtItemsPagePageState(this.listId); DateTime dateTimeToDate(DateTime dateTime) { @@ -42,68 +148,76 @@ class _BoughtItemsPagePageState extends ConsumerState with Sing @override Widget build(BuildContext context) { - return FutureBuilder( - builder: (c, t) { - if (t.connectionState == ConnectionState.done) { - return Scaffold( - key: _mainScaffoldKey, - appBar: AppBar( - title: Text(NSSLStrings.of(context).boughtProducts()), - bottom: TabBar( - controller: _controller, - isScrollable: true, - indicator: getIndicator(), - tabs: createTabs(), - ), - ), - body: TabBarView( - controller: _controller, - children: createChildren(), - ), - ); - } else { - return Scaffold( - appBar: AppBar( - title: Text(NSSLStrings.of(context).boughtProducts()), - actions: [], - ), - body: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - child: SizedBox(width: 40.0, height: 40.0, child: CircularProgressIndicator()), - padding: const EdgeInsets.only(top: 16.0), - ) - ], - )); - } - }, - future: ShoppingListSync.getList(listId, null, bought: true).then((o) { - if (o.statusCode == 500) { - showInSnackBar("Internal Server Error"); - return; - } - var z = GetBoughtListResult.fromJson(o.body); - if (z.products.length <= 0) - showInSnackBar(NSSLStrings.of(context).nothingBoughtYet(), duration: Duration(seconds: 10)); - else { - var shoppingItems = []; - - shoppingItems.addAll(z.products.map((f) => ShoppingItem(f.name, listId, f.sortOrder, - id: f.id, amount: f.amount, changed: f.changed, created: f.created, crossedOut: false))); - - DateTime date; - shoppingItems.sort((x, y) => y.changed!.compareTo(x.changed!)); - for (var item in shoppingItems) { - date = dateTimeToDate(item.changed!); - if (!shoppingItemsGrouped.containsKey(dateTimeToDate(item.changed!))) - shoppingItemsGrouped[date] = []; - shoppingItemsGrouped[date]!.add(item); - } - } - - _controller = TabController(vsync: this, length: shoppingItemsGrouped.keys.length); - })); + var fromServer = ref.watch(_shoppingItemsFromServerProvider(listId)); + + return fromServer.when( + loading: () { + return Scaffold( + appBar: AppBar( + title: Text(NSSLStrings.of(context).boughtProducts()), + actions: [], + ), + body: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + child: SizedBox(width: 40.0, height: 40.0, child: CircularProgressIndicator()), + padding: const EdgeInsets.only(top: 16.0), + ) + ], + )); + }, + data: (data) { + didUpdateWidget(this.widget); + return Scaffold( + key: _mainScaffoldKey, + appBar: AppBar( + title: !ref.watch(_searchModeProvider) + ? Text(NSSLStrings.of(context).boughtProducts()) + : TextField( + decoration: InputDecoration(hintText: NSSLStrings.of(context).searchProductHint()), + controller: tec, + maxLines: 1, + autofocus: true, + ), + bottom: TabBar( + controller: _controller, + isScrollable: true, + indicator: getIndicator(), + tabs: createTabs(), + ), + actions: [ + ref.watch(_searchModeProvider) + ? IconButton( + onPressed: () { + ref.read(_searchModeProvider.notifier).state = false; + }, + icon: Icon(Icons.search_off)) + : IconButton( + onPressed: () { + ref.read(_searchModeProvider.notifier).state = true; + }, + icon: Icon(Icons.search)) + ], + ), + body: TabBarView( + controller: _controller, + children: createChildren(), + ), + ); + }, + error: (error, stackTrace) { + return Scaffold( + appBar: AppBar( + title: Text(NSSLStrings.of(context).boughtProducts()), + actions: [], + ), + body: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [Text("An error occured $error")], + )); + }, + ); } Decoration getIndicator() { @@ -131,9 +245,12 @@ class _BoughtItemsPagePageState extends ConsumerState with Sing List createTabs() { var tabs = []; - for (var item in shoppingItemsGrouped.keys) { - tabs.add(Tab(text: "${item.year}-${item.month}-${item.day}")); + var dates = ref.watch(_filteredDateTimeProvider); + for (var item in dates) { + tabs.add( + Tab(text: "${item.year}-${item.month.toString().padLeft(2, '0')}-${item.day.toString().padLeft(2, '0')}")); } + return tabs; } @@ -141,7 +258,9 @@ class _BoughtItemsPagePageState extends ConsumerState with Sing var currentList = ref.watch(currentListProvider); var children = []; if (currentList == null) return children; - for (var item in shoppingItemsGrouped.keys) { + var dates = ref.watch(_filteredDateTimeProvider); + for (var item in dates) { + var items = ref.watch(_filteredShoppingItemsGroupedProvider(item)); children.add(SafeArea( top: false, bottom: false, @@ -151,7 +270,7 @@ class _BoughtItemsPagePageState extends ConsumerState with Sing child: Card( child: Center( child: ListView( - children: shoppingItemsGrouped[item]!.map( + children: items.map( (i) { return ListTile( title: Text(i.name), From afd94a6155959a2bebc1718595f78ae3ab91b242 Mon Sep 17 00:00:00 2001 From: Sascha Date: Thu, 29 Sep 2022 21:50:22 +0200 Subject: [PATCH 22/23] Web Support (#23) * Added initial web support by migrating to a sqlite plugin version, that support the sqlite wasm file * added more checks for kIsWeb, as Plattform is not supported in web and resulted in many exceptions * added a fake database, which was initialy used for web, so no storage at all and can maybe used for tests or other things in the future * Updated pacakges and firebase messagin to support more plattforms and have a more stable function * added theoretical support for firebase messaging in web, but subscribeToTopic doesn't work, so still need to figure out what to do * removed empty list entry in list at end in drawer --- .gitignore | 1 + android/app/build.gradle | 4 +- android/build.gradle | 2 +- ios/firebase_app_id_file.json | 7 ++ lib/firebase/cloud_messsaging.dart | 4 +- lib/firebase_options.dart | 87 ++++++++++++++++++++ lib/generated_plugin_registrant.dart | 23 ------ lib/main.dart | 7 +- lib/manager/database_manager.dart | 113 +++++++++++++++++++++++++- lib/manager/startup_manager.dart | 17 ++-- lib/models/shopping_list.dart | 3 + lib/pages/login.dart | 3 +- lib/pages/main_page.dart | 14 +--- macos/Runner/GoogleService-Info.plist | 36 ++++++++ macos/firebase_app_id_file.json | 7 ++ pubspec.yaml | 34 ++++---- web/firebase-messaging-sw.js | 21 +++++ web/index.html | 87 +++++++++++++++----- web/sqlite3.wasm | Bin 0 -> 1348108 bytes 19 files changed, 385 insertions(+), 85 deletions(-) create mode 100644 ios/firebase_app_id_file.json create mode 100644 lib/firebase_options.dart delete mode 100644 lib/generated_plugin_registrant.dart create mode 100644 macos/Runner/GoogleService-Info.plist create mode 100644 macos/firebase_app_id_file.json create mode 100644 web/firebase-messaging-sw.js create mode 100644 web/sqlite3.wasm diff --git a/.gitignore b/.gitignore index da3c53f..7475bf4 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ windows/flutter/generated_plugins.cmake .license.dart windows/sqlite3.dll android/java_pid62552.hprof +ios/Runner/GoogleService-Info.plist diff --git a/android/app/build.gradle b/android/app/build.gradle index d653868..4723113 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -22,7 +22,7 @@ apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" } android { - compileSdkVersion 31 + compileSdkVersion 33 lintOptions { checkReleaseBuilds false // Add this @@ -35,7 +35,7 @@ android { resValue "string", "app_name", "NSSL" multiDexEnabled true minSdkVersion 21 - targetSdkVersion 31 + targetSdkVersion 33 } signingConfigs { diff --git a/android/build.gradle b/android/build.gradle index 138d59a..aa52e33 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -9,7 +9,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:7.2.1' - classpath 'com.google.gms:google-services:4.3.13' + classpath 'com.google.gms:google-services:4.3.14' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/ios/firebase_app_id_file.json b/ios/firebase_app_id_file.json new file mode 100644 index 0000000..d45add8 --- /dev/null +++ b/ios/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:714311873087:ios:4c24043cc62e99464dbe8a", + "FIREBASE_PROJECT_ID": "nonsuckingshoppinglist", + "GCM_SENDER_ID": "714311873087" +} \ No newline at end of file diff --git a/lib/firebase/cloud_messsaging.dart b/lib/firebase/cloud_messsaging.dart index 89004b6..d207c89 100644 --- a/lib/firebase/cloud_messsaging.dart +++ b/lib/firebase/cloud_messsaging.dart @@ -2,11 +2,13 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; import 'package:nssl/helper/iterable_extensions.dart'; +import 'package:nssl/manager/startup_manager.dart'; import 'package:nssl/models/model_export.dart'; import 'package:riverpod/riverpod.dart'; -FirebaseMessaging? get firebaseMessaging => Platform.isAndroid ? FirebaseMessaging.instance : null; +FirebaseMessaging? get firebaseMessaging => Startup.firebaseSupported() ? FirebaseMessaging.instance : null; final cloudMessagingProvider = Provider((ref) { return CloudMessaging(ref); diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..3a4b2f3 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,87 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + return web; + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + return macos; + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions web = FirebaseOptions( + apiKey: 'AIzaSyD2AWdZaGet1YvVgck5gZ3mww9-6NDozek', + appId: '1:714311873087:web:7ff97d63debd5b364dbe8a', + messagingSenderId: '714311873087', + projectId: 'nonsuckingshoppinglist', + authDomain: 'nonsuckingshoppinglist.firebaseapp.com', + databaseURL: 'https://nonsuckingshoppinglist.firebaseio.com', + storageBucket: 'nonsuckingshoppinglist.appspot.com', + measurementId: 'G-55C6JSXQK6', + ); + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyBDY0v4Y8Ugdw0__eBIg0vA_oiVbIdPSWI', + appId: '1:714311873087:android:ca9c27dbc69e975a', + messagingSenderId: '714311873087', + projectId: 'nonsuckingshoppinglist', + databaseURL: 'https://nonsuckingshoppinglist.firebaseio.com', + storageBucket: 'nonsuckingshoppinglist.appspot.com', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCaNflc7mTb67r81IZP4Xpn6vkU8kto9Fc', + appId: '1:714311873087:ios:4c24043cc62e99464dbe8a', + messagingSenderId: '714311873087', + projectId: 'nonsuckingshoppinglist', + databaseURL: 'https://nonsuckingshoppinglist.firebaseio.com', + storageBucket: 'nonsuckingshoppinglist.appspot.com', + iosClientId: '714311873087-6830bbhihm6v74r3jvp0jfh2si59g1r9.apps.googleusercontent.com', + iosBundleId: 'com.yourcompany.testProject', + ); + + static const FirebaseOptions macos = FirebaseOptions( + apiKey: 'AIzaSyCaNflc7mTb67r81IZP4Xpn6vkU8kto9Fc', + appId: '1:714311873087:ios:293f27fa016b99dc4dbe8a', + messagingSenderId: '714311873087', + projectId: 'nonsuckingshoppinglist', + databaseURL: 'https://nonsuckingshoppinglist.firebaseio.com', + storageBucket: 'nonsuckingshoppinglist.appspot.com', + iosClientId: '714311873087-ch95nc16kbiuckgaogfg388vbhi3ka5n.apps.googleusercontent.com', + iosBundleId: 'de.susch19.nssl', + ); +} diff --git a/lib/generated_plugin_registrant.dart b/lib/generated_plugin_registrant.dart deleted file mode 100644 index ef2492d..0000000 --- a/lib/generated_plugin_registrant.dart +++ /dev/null @@ -1,23 +0,0 @@ -// -// Generated file. Do not edit. -// - -// ignore_for_file: directives_ordering -// ignore_for_file: lines_longer_than_80_chars -// ignore_for_file: depend_on_referenced_packages - -import 'package:firebase_core_web/firebase_core_web.dart'; -import 'package:firebase_messaging_web/firebase_messaging_web.dart'; -import 'package:shared_preferences_web/shared_preferences_web.dart'; -import 'package:url_launcher_web/url_launcher_web.dart'; - -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; - -// ignore: public_member_api_docs -void registerPlugins(Registrar registrar) { - FirebaseCoreWeb.registerWith(registrar); - FirebaseMessagingWeb.registerWith(registrar); - SharedPreferencesPlugin.registerWith(registrar); - UrlLauncherPlugin.registerWith(registrar); - registrar.registerMessageHandler(); -} diff --git a/lib/main.dart b/lib/main.dart index f9473ba..2d0492f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'dart:ui'; import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:nssl/options/themes.dart'; import 'package:nssl/pages/forgot_password.dart'; @@ -27,11 +28,9 @@ class CustomScrollBehavior extends MaterialScrollBehavior { }; } +@pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { - // If you're going to use other Firebase services in the background, such as Firestore, - // make sure you call `initializeApp` before using other Firebase services. await Startup.initializeMinFunction(); - //Startup.remoteMessages.add(message); var dir = await Startup.fs.systemTempDirectory.childDirectory("message").create(); var file = dir.childFile(DateTime.now().microsecondsSinceEpoch.toString()); await file.writeAsString(jsonEncode(message.data)); @@ -110,7 +109,7 @@ class _NSSLState extends ConsumerState { } Future subscribeFirebase(BuildContext context) async { - if (!Platform.isAndroid) return; + if (!Startup.firebaseSupported()) return; var initMessage = await FirebaseMessaging.instance.getInitialMessage(); diff --git a/lib/manager/database_manager.dart b/lib/manager/database_manager.dart index 7f47b50..671fedc 100644 --- a/lib/manager/database_manager.dart +++ b/lib/manager/database_manager.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:path_provider/path_provider.dart'; @@ -6,16 +7,122 @@ import 'package:path/path.dart' as path; import 'package:sqflite_common/sqlite_api.dart'; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +class FakeDatabase extends Database { + @override + Batch batch() { + throw UnimplementedError(); + } + + @override + Future close() { + return Future.value(null); + } + + @override + Future delete(String table, {String? where, List? whereArgs}) { + return Future.value(0); + } + + @override + Future devInvokeMethod(String method, [arguments]) { + return Future.value(null); + } + + @override + Future devInvokeSqlMethod(String method, String sql, [List? arguments]) { + return Future.value(null); + } + + @override + Future execute(String sql, [List? arguments]) { + return Future.value(null); + } + + @override + Future getVersion() { + return Future.value(10); + } + + @override + Future insert(String table, Map values, + {String? nullColumnHack, ConflictAlgorithm? conflictAlgorithm}) { + return Future.value(values.length); + } + + @override + bool get isOpen => true; + + @override + String get path => ""; + + @override + Future>> query(String table, + {bool? distinct, + List? columns, + String? where, + List? whereArgs, + String? groupBy, + String? having, + String? orderBy, + int? limit, + int? offset}) { + return Future.value([]); + } + + @override + Future rawDelete(String sql, [List? arguments]) { + return Future.value(0); + } + + @override + Future rawInsert(String sql, [List? arguments]) { + return Future.value(0); + } + + @override + Future>> rawQuery(String sql, [List? arguments]) { + return Future.value([]); + } + + @override + Future rawUpdate(String sql, [List? arguments]) { + return Future.value(0); + } + + @override + Future setVersion(int version) { + return Future.value(null); + } + + @override + Future transaction(Future Function(Transaction txn) action, {bool? exclusive}) { + // TODO: implement transaction + throw UnimplementedError(); + } + + @override + Future update(String table, Map values, + {String? where, List? whereArgs, ConflictAlgorithm? conflictAlgorithm}) { + return Future.value(0); + } +} + class DatabaseManager { - static late Database database; + static late Database database; // = FakeDatabase(); static int _version = 3; static Future initialize() async { + // if (kIsWeb) { + // return; + // } WidgetsFlutterBinding.ensureInitialized(); sqfliteFfiInit(); - - var dbPath = path.join((await getApplicationDocumentsDirectory()).path, "db.db"); + String dbPath; + if (kIsWeb) { + dbPath = "db.db"; + } else + dbPath = path.join((await getApplicationDocumentsDirectory()).path, "db.db"); database = await databaseFactoryFfi.openDatabase(dbPath, options: OpenDatabaseOptions( version: _version, diff --git a/lib/manager/startup_manager.dart b/lib/manager/startup_manager.dart index 0636d57..9d0ea08 100644 --- a/lib/manager/startup_manager.dart +++ b/lib/manager/startup_manager.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:nssl/manager/database_manager.dart'; @@ -12,17 +13,23 @@ import 'package:scandit_flutter_datacapture_barcode/scandit_flutter_datacapture_ import 'package:shared_preferences/shared_preferences.dart'; import 'package:file/local.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:nssl/firebase_options.dart'; class Startup { static SharedPreferences? sharedPreferences; static List remoteMessages = []; static const LocalFileSystem fs = const LocalFileSystem(); + static bool firebaseSupported() => kIsWeb || Platform.isAndroid || Platform.isIOS || Platform.isMacOS; static Future initializeMinFunction() async { - if (!Platform.isAndroid) return true; - return Firebase.initializeApp() - .then((value) async => await ScanditFlutterDataCaptureBarcode.initialize()) - .then((value) => true); + if (!firebaseSupported()) return true; + var initTask = Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + if (!kIsWeb && !Platform.isMacOS) + return initTask.then((value) async => await ScanditFlutterDataCaptureBarcode.initialize()).then((value) => true); + + return initTask.then((value) => true); } static Future loadMessagesFromFolder(WidgetRef ref) async { @@ -65,9 +72,9 @@ class Startup { await Themes.loadTheme(); var provider = ref.read(shoppingListsProvider); + await f1; await provider.load(); - await f1; return true; } diff --git a/lib/models/shopping_list.dart b/lib/models/shopping_list.dart index d791038..fc00296 100644 --- a/lib/models/shopping_list.dart +++ b/lib/models/shopping_list.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:nssl/helper/iterable_extensions.dart'; @@ -309,10 +310,12 @@ class ShoppingList { const ShoppingList.messaging(this.id, this.name, /*this.shoppingItems,*/ this.messagingEnabled); void subscribeForFirebaseMessaging() { + if (kIsWeb) return; firebaseMessaging?.subscribeToTopic(id.toString() + "shoppingListTopic"); } void unsubscribeFromFirebaseMessaging() { + if (kIsWeb) return; firebaseMessaging?.unsubscribeFromTopic(id.toString() + "shoppingListTopic"); } } diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 1f35724..8af6dcd 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:nssl/firebase/cloud_messsaging.dart'; import 'package:nssl/localization/nssl_strings.dart'; @@ -81,7 +82,7 @@ class LoginPageState extends ConsumerState { User.token = res.token; var user = User(res.id, res.username, res.eMail); - firebaseMessaging?.subscribeToTopic(res.username + "userTopic"); + if (!kIsWeb) firebaseMessaging?.subscribeToTopic(res.username + "userTopic"); var listController = ref.read(shoppingListsProvider); await listController.reloadAllLists(context); diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index dcf8b37..5841c56 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; import 'package:adaptive_theme/adaptive_theme.dart'; +import 'package:flutter/foundation.dart'; import 'package:nssl/helper/choose_dialog.dart'; import 'package:nssl/helper/simple_dialog.dart'; import 'package:nssl/manager/export_manager.dart'; @@ -54,7 +55,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi super.initState(); initPlatformState(); WidgetsBinding.instance.addObserver(this); - Startup.deleteMessagesFromFolder(); + if (!kIsWeb) Startup.deleteMessagesFromFolder(); Startup.initializeNewListsFromServer(ref); _controller = AnimationController( @@ -92,7 +93,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi TextButton( child: Text(NSSLStrings.of(context).addPB()), onPressed: () => _addWithoutSearchDialog(context)) ] + - (Platform.isAndroid + (!kIsWeb && Platform.isAndroid ? [TextButton(child: Text(NSSLStrings.of(context).scanPB()), onPressed: () => _getEAN(currentList))] : []) + [TextButton(child: Text(NSSLStrings.of(context).searchPB()), onPressed: search)]); @@ -534,12 +535,6 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi ListTile(title: Text(NSSLStrings.of(context).noListsInDrawerMessage())), ]; - var emptyListTiles = []; - for (int i = 0; i < list.length - 2; i++) - emptyListTiles.add(ListTile( - title: const Text(("")), - )); - var d = Scaffold( body: RefreshIndicator( child: ListView( @@ -578,8 +573,7 @@ class MainPageState extends ConsumerState with TickerProviderStateMixi onTap: () async { await _logout(); }, - ), - Column(children: emptyListTiles) + ) ], ), ), diff --git a/macos/Runner/GoogleService-Info.plist b/macos/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..1d04856 --- /dev/null +++ b/macos/Runner/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 714311873087-ch95nc16kbiuckgaogfg388vbhi3ka5n.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.714311873087-ch95nc16kbiuckgaogfg388vbhi3ka5n + API_KEY + AIzaSyCaNflc7mTb67r81IZP4Xpn6vkU8kto9Fc + GCM_SENDER_ID + 714311873087 + PLIST_VERSION + 1 + BUNDLE_ID + de.susch19.nssl + PROJECT_ID + nonsuckingshoppinglist + STORAGE_BUCKET + nonsuckingshoppinglist.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:714311873087:ios:293f27fa016b99dc4dbe8a + DATABASE_URL + https://nonsuckingshoppinglist.firebaseio.com + + \ No newline at end of file diff --git a/macos/firebase_app_id_file.json b/macos/firebase_app_id_file.json new file mode 100644 index 0000000..c674159 --- /dev/null +++ b/macos/firebase_app_id_file.json @@ -0,0 +1,7 @@ +{ + "file_generated_by": "FlutterFire CLI", + "purpose": "FirebaseAppID & ProjectID for this Firebase app in this directory", + "GOOGLE_APP_ID": "1:714311873087:ios:293f27fa016b99dc4dbe8a", + "FIREBASE_PROJECT_ID": "nonsuckingshoppinglist", + "GCM_SENDER_ID": "714311873087" +} \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index b67e9d0..768db1c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -9,25 +9,24 @@ dependencies: sdk: flutter flutter_localizations: sdk: flutter - path_provider: - intl: - file: - shared_preferences: + adaptive_theme: crypto: + file: firebase_core: - firebase_messaging: + firebase_messaging: + flutter_colorpicker: flutter_local_notifications: + flutter_svg: http: + intl: + path_provider: path: - sqlite3_flutter_libs: - sqflite_common_ffi: - process_run: - permission_handler: - scandit_flutter_datacapture_barcode: 6.13.0 pdf: - flutter_colorpicker: - adaptive_theme: - flutter_svg: + permission_handler: + process_run: + scandit_flutter_datacapture_barcode: 6.14.1 + shared_preferences: + sqlite3_flutter_libs: # scandit_flutter_datacapture_barcode: ^6.7.0 # scandit_flutter_datacapture_core: ^6.7.0 # flutter_scandit: ^0.1.0 @@ -40,9 +39,14 @@ dependencies: dev_dependencies: build_runner: ^2.0.6 - flutter_riverpod: ^2.0.0-dev.0 - flutter_lints: ^1.0.4 + flutter_riverpod: 2.0.0-dev.8 + flutter_lints: ^2.0.1 json_serializable: ^6.1.3 + sqflite_common_ffi: + git: + url: https://github.com/muhleder/sqflite.git + path: sqflite_common_ffi + ref: web #git: https://github.com/tekartik/sqflite.git diff --git a/web/firebase-messaging-sw.js b/web/firebase-messaging-sw.js new file mode 100644 index 0000000..339e505 --- /dev/null +++ b/web/firebase-messaging-sw.js @@ -0,0 +1,21 @@ +importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"); +importScripts("https://www.gstatic.com/firebasejs/8.10.0/firebase-messaging.js"); + +firebase.initializeApp({ + apiKey: 'AIzaSyD2AWdZaGet1YvVgck5gZ3mww9-6NDozek', + appId: '1:714311873087:web:7ff97d63debd5b364dbe8a', + messagingSenderId: '714311873087', + projectId: 'nonsuckingshoppinglist', + authDomain: 'nonsuckingshoppinglist.firebaseapp.com', + databaseURL: 'https://nonsuckingshoppinglist.firebaseio.com', + storageBucket: 'nonsuckingshoppinglist.appspot.com', + measurementId: 'G-55C6JSXQK6', +}); + +// Necessary to receive background messages: +const messaging = firebase.messaging(); + +// Optional: +messaging.onBackgroundMessage((m) => { + console.log("onBackgroundMessage", m); +}); diff --git a/web/index.html b/web/index.html index 7e35a75..9b9c5d0 100644 --- a/web/index.html +++ b/web/index.html @@ -1,33 +1,80 @@ + - - - - - - - - - - - - - nssl - + example + - + - + diff --git a/web/sqlite3.wasm b/web/sqlite3.wasm new file mode 100644 index 0000000000000000000000000000000000000000..faed541c065cfe57c51c2b5cbabd3d5f8aa15edf GIT binary patch literal 1348108 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%0DlM2qT|F-{ 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

fQ%*MQI{VN>U3fv|01Qo7jOG1oMwQ{;S!gzYe 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≈n1eEGM6?(gjd)OLGKsO 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�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
=f zPfD;ZHIEc`Wh&jP1E^>ShIChcKf&nF^jw6$K~FZI7dh>+-mE4%sioS~KO8B9p{OH+ z%p2s?qi!Mgv)|PYPZI8PmI4z>4~Aqi6#z#!MNLpef<=H~qeY>7q!2o)isve(N&}+l z689BtxF3aFbR<_~=VDYCD|{#vuq>y)n3pu%W!|BdoEWSW0z5!1mmN|=&%%}S1GU@; zBfSXS%^xs74BS|578UmkPYQX$qcA{?j<|~sm}gzZf9MKfsu9IwMseqBj6Hn}#ZcJ| z820?71LZMrI|s^3S&ZVC6H~G=KwPcPJT`^ASGMzSs8^~J9N8JF(*eM(8cI3SVfhO*xBUTIpxHr4{9(l68Qk~lbW;SqOvX(CzR%{y1Bpd0rvvYnLpxRgPIF2fI6#X`@7|hQ zmQ>)TfG1Aj`c{ck;2dXKRg0b=k~qcz^jjZDzx7MeujPoajssq9*05g9w5A~q#O2Ma zvw$Y&$jqCo>g$AS=`LI==U~BHSf~5(C12*z`sM)Bo3%9TMAdm76IH#J?C{B}CPLI< z{Eni+EzqOlh_fx4&CXz2!ORILYPwxhV>?p@7OgMU1q8(NJ%vm_ z212vR4h(1U(lSYzLWXu6tU|vtl>DHfq)`|v%EyD%ama8?axGS5*mvLE$48(rBnNJY z${Fe8PiUm>Q`XAigZ2D%$Y(&~y#v;C7_iSybw%JJxFRy0cn4Nwy1PF4n_+tK>2*g5 zn5ta}54mhZGv@_*&FbuE9 zKp#aXF>HG}A*!>|j5`+wK81s%pXGUO#|Txrb9MIIV>4)Z>Qfd9^8@nGN_T@y0eSw*g26tFX<=X*>K6~gdVvD2DD)l*bc>%A z375iI#6_e5-K6|_q5wonAOd#CAlYECfvw^o+{0G$Knh2&)on#nHIl>{Xbq>%cZ-#Y zks-PNMeqcw%O$)$8f5sRD?}P$#wFM53_sBQh)g=wH&H4jY93ey4W{bgXL03~60{sH zZQ2-M05D-%;dt`1&_%Zuy`felG}H<{rPvDJ)e7QW)fS)4IMYpbBFADkIc8G#y40r7 zwHne8bdE*N=e<*LH6GWG2gdIzg17Tp!|ZRPENy`=@=Sx=xMs8` z1SzF8xx>$LokN4{*wQr|nmJ{iv84;<#>1N6p4z<0>6Pj_cfzO)->xWL!a(O`yLU9f zEQL`E85nv_uBbiF!Bh^f@_ei^vE3@q6~b9Xdhw=FowtGQJvrQW@&nTh`6$8$+1XL* zs(ekR8uzIJzP0X`s_X)#j8b%*X6egS5YW&jhJ4_-By^#)D;F{e-}c-_j7W#|(EwI0(l|_=Xo1Oa+9l_L+?^N*ILHR3hL5U_jQqnGE$pMh%90R^Pn z#hw>-bhK@DI4FVv{W-#63Eg-P9F`TVo`(a`?KqmHmjMT6ttrbS2|gqU!pdg?0rSN< z-2p*5#6YVQqV*EXim2!a16$_;-QM>qI8p+fyucRbyjArtq(dC`zQ!8w=|M;;+Vjm#7fY||jSg!H6+;|ehlTUScJi3%e`Btl+=AC^E5Ob&J-SrE5eIfh>Nk%S=yu1Q@_qKxrv2>a zk}UoB6E-&zuO5*U%TTFf$w$3tqaXbn%IS51DgH`NKNK!{rmkE7AC`dQtNGRdYtU8m7iJfY+Sh=Pt(6nI;v#3gyt93xqO+yidoagtaDPL)Ooniq(bMopWXRd+xc4C z`IWp#<^h!N)8>7jF_Ol{~mqdqQEibkyaX5}cRC=*ld}xZ< zOCz!=bVe=f3ETRtRjP_T9EX0q%nJc^L+ry)3(O&+@yW3YQJ4$;B_rc@nUr{RRgdgV-c5NytY)YBjQ58!O6Pt|L{nR6iPtA`bBcxDErdl` zjv2=+Dk`GZ_OjNt3@gbC*A>D9=dfC@f2ZG;DWL`+_yx4pOU2#XTYnp{;!tLRF1Vk} zRSH&@EAe2Fg{0rd<3koY`u(_ZP+JzvLQ?2^Qt0(N1hn6xa2k4EbpxU7G0t09y$uMi zrJC7XnjKHlZC`~56v~!+TSSBljSu-i=DX8#vLE(5S9C(z-Q!7)RWP!1Jc;{+jcR1)CRC#+lJ=d1H2#rB!U@e?u^jS*aKH#de5`}&BEXPTD9Jdt5DF`) zr}@@3F#N8M=IcoWB65$y0Pli?*D*g~pcg6DLi`U5?DrxJyFrsGS4XdFN2kS&P5kpQGKOo@3iB*VbnUd0(_6@*@asmUz z1JGh0HGq&Bhu{%#+5v>pPyiPEQO3)@PHqSIb8B|M9KmYg;$m1c+?$%*Vp_B2y=;ep z;aNz=1rd=O`iG0m$nnG{Il3t@J-D29jCqh9?%aF|le&S0%rHwp)8=Cy-OHXsh8~<) zfN%<$xb&y^nIU9@>LNmB%N|(5x9AfYnx&x?$3&nZ0c1o@*5R4@C7!0&g{a&YPlJYA zpU6-wRL{-(MEo4eTYKu%@a3MGGwht2W0k!5V(Hwt$2E<-S@tg-=P0(8Pre_|*-2E_ zb5O$gxqh1pXm;mBLuN4$5G<6m)rbqO^N#2LF1 ztbwOoP4TqdX>Lo{xuVQi_zMsOK0;RV@sYcO2x2^C3qf4691~5r$`Pl5MC?_ZE_|59 z5lw*QM?i`#DfSS^%A*eqj&TW+{vanOj2=}$qvv8csD^q;>NqGr_>mP_lZT7eVFN-4 z%^-lYAF@fb)S)vkTi9ZE@UjJCbUc2hNLcLj$=mV~;TIdEdE?|_TFQD?$}3g^Q+g-8 zzq;H~g5>>=Dq5D;eBh(Hyw0 zEZ-F_D;IEiexN zlstR@Ky2ZVy>`LpFoHQ~g)p_5;Kh1D#vu~~X-Fx1o^uH0-314OomfyssK)7F##zX| z5E}MLuYm*g74`3Vf@*YW2X$3Wnc@nPIQR}i9w|NnUbC5>wMB*Dr7_7I6~qNJEWl$W zE`0~wl9}m{FSr{*fsTL{y43&L$E&KLxxBTL;n7S<`IOFTY+oQ-7QcYENrliL%16XN zo{8mlWKvnyg?&;Gi=>FFu}S2;(L#jB8M!t)bzY<`z1R;~-6AIdvtctn400qR{s%Qq z4G&??HbdEZ{mBpY1*DE-N`957Y==`b5rI)M#WORz+BWmFWYW+inXFh@GPT-vUy@1B zNiywut}B_kXJ#&RH$5$&cOA6psdHu~0eh`Mdt?I%-YV|Ohu5Ib8nBxwtbu*i8c*N? zJi{(|yQB_T1M5_24S3vZz?5b$x_Vr@22vvp3@1lGIH0)F(uLl_Y^uf@_d^(UWLY`> z*z)q>K0DFmo9gA@{gNBsSc{%YCfNolapg`uK`lA&JQN%(;I#A^?%tZ5Hsqi({lDIu zaOASKrAM{UX)GkRv^!%4++&fHY|BT)U_10ivz?yOZUgjqX5UUfC`k;P%{*w!k%u-i zi;GQ%f%i5Ka?I_YIQvq@dHC6`K8 zhy_(N;D(0C*QRS9@0*49vV~(D<_^z`m1;_(7>0_eRnVcTw|;dBm07Cwt0hS_?s>QO zHLZhC&MXqPuSp!-jT1h<9KhPzIb#c`lDSzMYpxZHmCU6BtjQW82a5;Pz47m= zIVJ}4uv)?6O7EQAB8`uFMOS4RhJmu7ixJxYct^D;>7cozA8F9_P+Z!kP&GzlG5F>f zG|G$JV8@z;mQ1riv)0OC4QdwgOsbf_3q>-px|DZH9ND8~#@%7|=Y~1LA*o@y0;f!S z{MI%TB&qPTiHABhH12UO^X8hzQDR4nWCZUIVT`0(!VFf2L?C7?1y;?Gj) zXYpuhP^5I+NxB+!SZ{a^6R?ynZ z3mIDbV$j-)=KIMMS?%}xiYmnaawbtUf1voZTti8joX97IR!H86z)_Nl$-vQ5SX~q) zUG+N8l1$}0!tWpif@>}TQB!KSFwX7Z1#Uhsw>?b-tF@=3R1pZ(A4_18mm7rAau+s1 z!Be#_S_eUa%{ibXxYfh+Sr)PcV3{Nal+F7|48VEMn|#weI5+Wre(|rAIbGJoG3bP| zi<`|qxJIQNCHv?WpD-{xQx#jIy%x;gW+PzJWB@f!0BUwl%RnjvsIwv)%>FCENTmWi zAg5Sqn8Oe6@wIy&(jXS^(aL*x%V0OD_08(n6Lu(}ZrFwTCvg{Fk^rD|Cs8N^br?fK7raW9ey&Mg=Ftx=Yg{_ zy|DaZcAZQ;rQI7*Scj}puH6~h>PPz!iAgi@6|Yq?55dqjnRkrHq|97gzgg-u8;Q~y z_E|e^_nEC>FRh_2$2CN=ulk)e^ai1@hT>BTo?&MV8K)-eJJf>>cCXg7f7tT%((?7= z@|Ad;mDScbQ5UVCXPjXn+SZ{I`!#hjuxPX`XXObpAJh^y*sBs8& zd~4ja7qGiI&ssB6o?fD%V)9Pg$&*^B&rJbd+zs{78z->_#bOJ=200-XVC%DCG7O3_ z+vH4w@zbY>vQXZE@;3xw$v*KjuQXS@4Y6T^BYY)udT>)r#qP!* z?(aEjl|IA&)7&7EVQe^Hj|Pvz95~qc!@7h#!!Tf5G1y3x4ebg7(}WtB({@-D9K*?A z%Vr};!pW0haM-1@r&PKQpogmf7Xl42QHdYv0D8WLqpN{{58MvV&JLjGfpB)UA9!9l zS~EA?=X3VFc=O)zYqbs-KM+3l_`|bDjK6EFeLmxFQM2D%#LyN}GWrbbCg30P4x~1- z**ho7*V|(j4bo#*ulGywxUeIN*LRN>|9ooKbAa%Y%(;*yKFb=9nd8h#sk>qy*yeI_ zXqBod8`SKc;Ky0-Jqug6P*sR4Kz8_Z02E?(CbLk0_M{QZ+ulhd4%=_HRqhq?-CzSc z)OBPUF$q{sBlZbKN2U?OTEaG1#w|5SAMl$!Io9Yi&@a9ZT?XX2D9J#uW0tmfF#WN;(wX5)_#D4)_lPkz^wK;Y4J)am3Wa$s)N4$lmTqy z4UTc`s@R4@SpT=SpiL9#7JZ|+v3DEQ;c;XUuN}0jLUyk?&vs1z?I)~N`mgpf;3Lq& zC`p+ip8rpFi1OFC3ZEQciBT-VQL;)o7}}%DZg;2D#N7*FQvFc$ygRQ$I7i?cgq8x| zI2iQa%n}$!0KHFSISBL}reT&bV;FOw7s_04L`GYbBWvi#6TWNP#v^82?_rKOsXh

$s9F{qnRT~=us)x8V9ZkPTo=H(uD`(ztfx7pz`hFtF2&4 z^^=0VUH&=PZoZvAF-0v(@)p1wJF=h(G4Z;OW`x^cn$c8+BTMNL(5IL{N4b487|U*;jE7&5E|T6!w1dKx#|!)lT_Lvu-fn5T66I<$IP9quT6?uR)$*oW-2= zOkNcmcG13>!@BqbEoX>lKyeTVG#Y~-n+JiQ6JG(GEg%fJ1ckDl0K2%t1h{n6=2cIC zDIhRC0R(BB0NoQCK5zo)`;8QhqIuZXjJ$3l)`^G!Vi+udV-+$-#{LV*Sc<+a)4?x)% z-L1Gx#txf*n_rC*pFTnUZuT;!bxm0cqkj30@ftl|EMmFRV3Bg!Iu34}^=A zy@BXJ7**7M#0I@A2n}$RIOPDyEv@nH$W36yhUbWVq%+G$?P14RKKrkbH4vgge7ser zv!L+j_5O2tfIU|(6;Gnzm(9B=OyfK|ckooRF@#H#?8m^$4|aATx;aD zmC3=%5Xyz*iui|Io{w_^bCKm(Hvjr}r33QiQ~rXj@B`m3rE}Cg)5nha-EX z#?4v$nayL@9~)KUug7%L`r^=RUVNl9@4=K}v9$`T&4+#tNrr7O`BDwSmoK)LFLF7J zj3{)Q<ptZip{v&EbLiQvvxr+xMTm0;AwoAeEBcAz&C=VT55r z1`Pg`q-5x0gEk-ootA*Sx+`~}F%iUw{swHSFU@DjOUY`6fX45xNf0DXWLhEsWXIF8 zC}@fOIm+d{1IVGvxVC_^X!S5Og<&sSdr7&6B1%#3YV)nX1TZIG+Q=IM=UX!^g47B% zhwTQ{Q1R4dh))}-8TSOIGL6A|`7vl#SvedHgSc!|Ub`*7xdCae;&r&0h}4B_l{5}{ z6u74%L&e+Qka0R}S&i?XuF(ebek(5wt^%+@Q@wdp_BhX?2!?hp73Z|nv_v6F8|{fC z_3q{7;fF*!aBcf#)bbi-H<-mdOYpJKik(Pu@gked^+BbjE~a$Nykq6~b&e<_0pF`@ z`7FLF5&(B6;&T(00WL%a9we6hq0AFn9{ilxfZ79_%u2?$g6MHedaYxo%S zo6I3FG9CyS(o6)Wx>1p>j+RNj0F@?J!paHTU z*b<=f?a$uw=ln$PiP;mtvGoK zA)K{CFK!*)F{WDhLuLv}3P;H($3J=YY)2nSyX(6Kqe zoVT({{5<^tF(G(2d*Xz%e6x0=0T+(f=wXF0iU@Era(Kr>L#F4QRYP2FO56^E=&NWDFU{9T5!0hI^{zj zl;(Sb{@%YSa?ps;SD4OeGV=0W7;^7^)rzC6)EPYUOx1H_u$t;bQ`I|u;{oD#Oz|( z7O7N=)$*f%dRf5~<-ozs0w847FfwSN#JJ%D@GNLsQ_1&Ym#ffsu5xlQJ%!CoQwYZv z9)sAWy$$`drGGB(0vF~1lf-+=_#W7lmL4utdoN7(T=4VLoOiD%6ofH@u&Wn@b~eNC z-N@+VK6^RX5sMrxVAhJa#4Zez2b7~ZH%o)wj|_=F2{!nOKp6>=^WX%aSVd;u< z%fQdP8s5cBh-pey<8?Nug0NiRG4wLH#z~JfuzS`k#1_O1G7`8cm%!iq;({%RDOmI2 z+nQL$8WYn?F%L~7#0rQF@Bz*l69~4Es=^Yoc#K=f!D8w{ed1APTr9fgRkd(yenNvh zA%&11ro8p|BQXvZj!}aOLX-9(ArL>pLth~ZTWBr|N6?Qh*K!GnT)|=zZKXC6{Mvp# zWAlRcPOzN?bY7&{UgO=+J?pUiLY=^j(g$V}U+%`LxkD{UzSy{0TRp1w>#<#yu2HI51WTePMgI=;DkD4PDu6U0wJXsyx>O& zDWO)UkP=Tiq{PIyMo1>cEcg*ZN`8Ql5}+3II9NQtY;`uwVGBaJ{)9CEF7SO|tSxXN zUdWVu5R`)gEmHWBeWA2z2~|q?fqX)!3LK;+pY;S!6X(c$$0;1mATeHvp2{*k0ODGg zDk$c_?^uAJf8}uar{_@hTGO+uAidlbi0!fJ2o0}&L>!f$56HmyW2I0g6A-8DA`Vvb z3oZx2Z3Z4I&hsN74i5yx5&UMu?pn;pDwEK)nB$UZ>C7NlK^Zut5y20_O?0gNtD_KW zJFOUEWvD5{%GVHLMUc-=D^`Hufix{1@U&(#>V_zfHKV!04>BBsL}%ErvqPw&w}&cv zUvR4EMXE5HtzfeUQ$^}np_Cx4giJ?J1#_x`)zwe=y@?}rcAmhL_UxvEHjxOOm*>N( zxadjqg&_SLDn{q=FBqAG?)Q^P!lyK$gi@UeA=&n9r2%uCu-s3(5fgHGCbAkd1^Bw2 zlWd%$o6ir+!lKH1js9hAaq_+W9tanlN0`Dp>08x)+i1T{+HZsKtx*{?WbW1uSub0t zJP1hpYAqoBO~!xDKj{u0N`7z5esk`NPG@TGvnx4A5lg>iI0Wkf-4+d8)j5J~Wl_Q4 zb7%rN=xi1<@T?Kw8tGk;iBs-}A&Ad&Pi4(|QSN(JMZ#t4#o2AyooK6#+^0OoD_9AG z@!v{`NkVfilIzdl0aXS~NUy1K$q;P8$=`yX`YY9X!V}gPd2`90Him}!LL*Hr8P_0b zHiM+!z^urv%;%*Tm>yCF4t9>EA{?lSIv-02x=)_6%~0%hNTP!jFEXR!8N-Nfxz=dp;CKk`Xrw2vf>l zlPOmkl;ROC&kpSSI$@UyPl#38DaN2Spj7;l74Bn{g3>R_C{$4fc64E=GMr(xBt@5= zmzp;|gq~_tB-CJi)6RM}k7y;r4z*lEQ5neVJvly59B;!igZMCDA`n0u#)9Q=TC_yj zc)FDP#C=ff7xFh6DEvW2gD?`WG+)?e@!JHjn^EHwZDrUNN~>n<4?m#K{w8K}*uJkl zexMxNcAD!{aKhREzHIf6SRyl?#$|{HOpUMYLRZpQ!+sfrEVkzY#Ck3p|Im%E*tgRA zd?j;F%zIbbXTgmZLz(Ml(cySem)7cx{yCvg1C)%L5Nu8*l?4QLj%(w|as^F=8q7S@ ztG!{1J-%Y1l9tNIq5yGo#^0#J>=g+WnTcDR;q{H?A7EQc=H9?I!%eK!N6Uw#YKs;0 z9@>=ChQ3Y{V*(vBIWgcxQ(wGwdNVE1(2WY`;nuN3MhL;Ci%|9!77q1k|4@aNUX5do zd{$DWBgpO6(=4aT;j_U^)uef$qJiL6Aub@ySZE#=OY+SvZnkkg;lq-mp{^sn?_C`5 zpLGc)fRZXrlX?mpkPXh7p3o};Oyzo`8EZ%zPj54qN2epX5vfcei@v$8G;7Fm0H5dT z$X-wa65G8eAh@y7X0$yCkzjnO;UT=8dIoQ2dWKi`c{^W&XGsNpq1{^`G8?_C`c>h4 zR`1g(U&7G>ljfG4X^qeOOLnHOFpzPVooN0kTV2jEC%l^0{K!IG!eev2P^uvIF?cUh zB5m`UrrV>=2bcl*hgR8JPsf~;nAeZ3vWcv|Vg#xQ(rJ4|5;WoBCesplWx*=G* z>(X$06&|p&e4M?DGIZeBUHL}E*6QjOiUuffM6P(maP8-L?$%V={etIs*ltP0R8-YiBcCP|+UOB`Wb(%zP5)ibt;P896X~^dy{}ajZDu_aL z%jsuOQ8tA*x`eM=c7dr0=N>oz^2@?*BYK5IJ22j|E%*(m)iOa$$(qe^YcRH`h0C4uLP)~vd zpQf|@AGzKW*ung25V{Hgr6SXfVUcy(9%3vGL@O%lnhmmv?`a+E4}+gV`)kd)@XWZW z?fUOkuD!U0u7uZV@}qrWawHqcQ}N*`kswxcVM-8lI#%RRI4-6OVhhtLK`zAB6(OOp z8+Av=f=kQ+F2t#*MU6F+Fd>*7Wr7u%a?2iLHEvEEHY&(WB7x|YCy@HHQZd*CIXybH zrT7rdt_UTq6L3l0FmU%K*-`h&8(~x4D+P7-Sw`M&g~Zq|gpJtGGI`0O17gyQ>>Pqg z2d?G1bSzZNa)xJLL41acv?1(aq1{*AJ4dM_WX&>ozNJ5n02T$|fV0TBQdbR6peYaYPqF__I#a*S# zI}&U$z>?h_t0p%$_r1HHGOF<7k+M}YZZ-t|>H$Mg+!`5SW5 zN2q3AD(wmMC57tm+XWT*mpoN=pFH4bhG3ydDK$-RNS~;YYZ=I1?DDzGPe9KcO^Qru zfibbM;MV+Nv-&nEI+I)Tt-r+cdVj}IO9D^gZWS0TB1j220OHEOZi&B$LsW|#%lvzV z)LB@W1!46H`F|IyT0s@jS-MUUrT8eitoM|#rq7x`2=ftX=#2ybuV2}1CVv?pbdtP| zD6kEUVYp4FSD|NfMs2vDPF$A+q@Ej*TODfni=qz^Rd{8gS<@@@DOdNf9T^veKxIYb z1G<&U%}39?t+d{=%e_YaWs1kHkN zJ+Bd{C0Oar_b~)-^!12t*NDj6&{YrTS@xA*H}5~u{FBTk3h@Em6^1#f4q?)Ku|SzL zin`B_mg1l{Q}>MZIt#>Bb$IGl)+!7iC8o=QVGfbawn$x*aS=6S3~cu=l&%+S`~;X` z*U0=4zZKlW8oW{n4!Dpn#YgFFD zcToDMx$=}&A^xTgMEI>|A<1#`TGW|zm#4{B`Z1mte@8m?#{aH2+-K`tL+fyY10vc6 zfcj1Q%)++0xX)}D_Kh_;DD282XCRMIS_H9>_KqPSq_^kZ`XA7)BAE@~k?OKpvly%$ z>d6q(fN-$hR76XX3bRC6@iKR3nw+1&LK2~;EdSq_sN7~PZ)`ALVt&F{rVN~@<8{PWN`?LG&B@k_(Z%B}z z^Z)PH1vU+CGB$l^l-dBhDIii7QdXvtj1Gm&qh_yDA}M` z4Hz1VAdEf&!fF;AwLObQQSVWEQ*QBaw_a4-Cu764j-QccX}fM_riptR)@4vN1xoQb zeGG&>i$KMpWYktwj~SyFOE9JLESPV5G7U%-xT`3GC=jy;&1l}J1k=q(6s?BiZz+xE zj7vPG1jA*diA*CeOxph@~AVw_JLzJmo#9@J+_g%F& z?xB`7${IJdmJ*P<1-Jh(tOj0^<4g`T^>-mFnhR9yVJXjsG1_zsS={Z)<)fJi73e;3{(O8>{}G#YBSt=?R=JAYI-(lloLCb;q2z_`Y;e z9WV@>@@nw=Jf=$ZOZ8n@mf5)Z9$MqCMvEq=Yb@OReBmvWNaC9xlv#Iq)*Y!_vfu$M zzHvq`$lyw(R)rhTKFT-g=Bo=*X>lszs3I7ID_Or;54oNd#czM(nkLs^_8T{LAy;*J z{-S9r5An|Cvmg82|A|~e zKs_G+XiTDyr@;v)ghz+$jda9Oo;YR9M6_Vu&MmC6Bheyz`Dl@SE@+X>)=9Zg0WCVg z$rddX*GOnlB(%`Qy=b9pz;hlgba5YA(4YA<2q2;dGV40`!D!)?coSFih!(0u4lcB4 zq5TNPmALE~7+_p!e>=L-qJ=graKA+h$syLnt5X+27(v7ADU&cNB#e*?m?udXiH20$ z2*0mT$KxfHh&GKnTo&r^2&jXCG5+OzZodUxfotp#7oV{6pP$*}18jOwg98H7<{6nx zG+LKo8O#&+^yN6_8b(~wj5bs+@PR)?l{TP9ZD;1g+nIYR;i&!hs?6tOgy{f!)ox~< zNxPX#4I70?4kkIKUBQvrXf4W6!4Y07IuBz(#IsA_-)*k%SC|gILXd;Wu|*sf@?_rp zO#rkxJx!C<&h&DyCO4vH1U6sX_7h=zn-M$L_09hne>yo3mIe1jo$3Vwyj z9yE|gWJ3l#G|N74AbZg;&hrt?6UM<1Lb<0Y)=3x-iYw)xu)g@&Tx%ZIdfbm`wj;KN zf(*P~`bA#K@uNW)bLF2RWUqKTV83Dq(*gVj#D|`axr_<%Bcn0ms~0%wr1{NA!N70} zFvIOnat~Mn_mc=zAfHLX%Ga!D;&H08f%{#0bLRnYNt7+H|6O%S5B}lGhX=Ai9Ab87GZyc2@ z|JbUKo}e{icxyUoLfcT*suK#VFq^COL?0IQ>o7SyWYj53tGP}zGN?s7^B_MY>e&G( zlJ&fOy<4Rg|5j9_WxQKRmYU zI31&sX|b96JbOC_}Byp(dZw+Z-ECFm5r$WnJGtMu+7Qq!mJ5D zjzy~rf#LGOG6G749eK^et5n@6fQ<07P%Xr%CnTYVHg~=HgbV#@J=$az3-_|)L6_Fz zF9PKJIuU=#W6-ZAt}V!5Mrw$^C-^&&9pc_$h|m;A1jH_RkjO)iSdugebO|WMbix^2 zd6)=jY0Pwhp?IJ$bUtHe68-jOxXIxRA=Pvm^9Nb*@GGEEwIW zF1sRwZF1hqm&Lb~X1M1$yc2C2?#j#o0#m^S67Aip52HG$n&`@`&b2`6weTVYJE2FY z%0t3s*L+gY4)PU$skb-Jl!NBPuCgTZhg5}$2}iDsk27*$YJp<}Teyj{^PTDKgVaFk1(=k2`E4VV*i41=t)l7x6$T_hrP`j8`YFDPH z%JFhV=W7Q>>DG?{3_$lM3xPQMYG@NK%%3RZ0h7l0x^L3)D5`xkM%fsD^z30rOoduU z?fyM-$v#m~Bj}vxew9@QYd3@GkNNK$7eNI#I_ti;y|Kriy3z5c4wB>ShU8Dx239C6 z`BPWt{Hbf~+#0;QUOmvCdP4rx6V>WBR%`O7vLkWkPaSj|XB3QgDPmA^zdseDq;;H) zlH*Jl_d3q}U~rpNeo+2YKUh)pNaBFhft~bikiJPh{suAK73I-?gS>1Tv$2gi6Pk=o z@bzW1LGc98aB=(W9yp)vzYHvd;Ko)U70zOv1%ihX@DS`4;H)~+J3Ik@Z8P&+ON9u9;Ktv*!SrWK4jVV=o2Q- zd*7#9_`3&h$ljx?P~;O#<0*e9$&Q2)4(%DaRuM|2RH)2TW-`wT?nzEE zB8*VmlKJ`qubuNRP)`>q=fI}pOT}AhULhRpsmbIW2oU3Tdvifc%8WKMaodrr zrRLjzjvqokdAmRddC~c>x!C8RcG7P?`&q=eO-2+51{stIxzc$sxzd*f(@C`){1?mH zKlRA<>z~lOA~4<&;-lV)AW`aa=~dpawTvrGJDcczIqgM>$GR+c)Lot7Cv{h%S;UKK z9ua#v?L~>ly5Jq(|6CWbyT`g5Yu8!lSQk$}OxmW00A|wzhAHJ2{Y<6@5CVr2e(OLR z)(ox{@Y`b-W~V<|BhHGTKunnz8BIy$Gk*A=#mRfInzeW&u}nVhB7vNz&hm;|9P4zo}K(EsIH-e-__)&`;(_%YDh9%KF1;9joAY%Kt*uX04h5Gn*8WXje@2= z*HJ(iUZVgC7Vu<{EvLfA=_GV|Z^*=#MEzQ1kb3e1a2QjivUBpuuQ3W{Kom}TG=za| zp1~-teI2dBPho~^q!mZH8&M|9LD8FX@{CjExh%ecVPW12m8c1^VNRRo!<4Q;D=5yiu zdE`B`!^3){7RL|YtH6#RYjXoiBZPg9W#R=<$dw&lpiGH*USJ^y)XKyQqL3?_d0yb> zI!Or3sMVpS$KnMYA!jS?obvKqW=mk3;-Vt*@?y3#K{=2<1Sok<9Lo~%D$v0fp$zu> zx2t!^m&t~%t>WGGkrQ0iehpuF#$RbPt7&v{O3N~EsFN?fkW&#)obwHFCe&58Zv(+m zOgasC$B`o6{DaTn+R+iD#GEs&nnAACUA?zGRck@s1}wi0$n{Gg=Os^u`;q;&r)n+8 z+o0zJ@;%RW+3!LJiP zZ6NP6%NHuoJ(iwC>b?%EOdlyq6B9G}$t0@Hn;N;)wlnvp)sA>Oi8r9K); zW(d$7yVZdn*FVU0(Qvx)L1$la1MO5`P1m1K*Pole{#>}Ork)KWcov)>jmX&c8D+mX&oXQ?#r8pEXxq)uC57w zkWXsPrM-t?ybIuw!kH*ef;!-ol8QFx%@IBNj(EY<+94+5;#z%NTB}b}@WYNp zS|vDmL~+I|nz0s&JQ0Y%3nl-$C{kreEf5(0+fP*+ih8QGWTq?d6 zoeVa@F~66Juc?H7!V9vkQD!a`e}#|SraT5dd#Z39ZNR~>jC7uu(4`Opf*B<0UMfDQ zhhB%3r%z1H=lIl9&vsu%0^@>E?_#83s{z&-rM?H#f*B!?wTC${6xHupY@Q`HS=!8$ ziccO^uqSJ!^Sbn;60lm6QwDIbWoxFuHj--eb{(0;yU$`NpQBSYkZ1skki|3pMhGk* z?=7+n8buImbwhZc!E8XiID6@^!0UYN$7%mB2t;u@J7g;modhP#jF=`f8JQeqe!^Q} zUn9>AWk>Tzy`4NIIx0y%Z2qBRVU$&qUBZX;&|&jYElM`iLqpX+>7hK6jLTBsCr?X+ zt3#BWu~G7_saFms`ga-?z8P8Axin{{$v(E60qpDbMb@8)qXN%PH8`?YX;R7#L$axJ zprY)sn8hJLVW5L}Ut^-(*VSj3AWPON+DCS!d8#Y==*;soVVO4^xM@uu0>^T>GXUKX>DiI!D?U-TJikG+M|6mq$=SLUm%6 z^FFvD&Wjtx9oXx-c&{lTloUt@q&hmH0tq_N9x=KmN+ebZ-kpGx7*zg{tDO0B4L+ob zl9Tt43C+60z}JncLem`OMrhic+nL^oy+s&&bg#C%F5dh0=@~wUyVFf5ld_@%Mt5q5 znruBnrSd;%r;ARC=H600V5~?^j_ZN0;rbe#g7Hv=_UCDXJjIk9x~Z3Wc6p{Uglzt$ zx78%p@*0hp>#p?j zYrgdls2Y*ol~LTcxqYYk_CFxnCS#8g;O703ou}*5iSdUXm6o2qA^hVw7TTT{0CT#Z zg#SVqrT21$0eH`&BF&Yc37e-|~wbJ>9VlJo(EJyR$H?eimJMrNta#XbmkEnq0wz;Q`ZLN<6 z38&*+`;dpCpB$(n0FDH}BbRX@4ECiKZeDi+#iTpQ1gj(@7OHh}38U`B78S1_vuwd< zxt$hewtNX$4qmbZzJ=y>f?irY+V%DZv{g|RV-fWDXu%_4E4mQ$(9*ckNnYOP@eyXH$fyLy10`wqCI0O@+gt(M1g_T~)go*-8yOg2?PNGbd zKqlE2eklVbbkiE$yEaGyB=4 zE-!nI9pH(TY3YW*cNnN(*fNnJ;vzAzVarg4EkhZ$3}qOYnCk}wCN|X4{l{Zs@mx}; znmOT9Obq=aF)=*kY3UAPV#9-%&faP--4Lqma*;!XQQ{)K7G_d96JJYQq}N;!7fJRX z?RGH_g;iX{dTSbfz&v=WLTm6k!XF(LJ;OXPH;>m$cMs+%ZKfwKvZAS+nc4N#=1P%g z*ct&h4=3v=e*0ndk@FI?FGb{0&@!JWXxRvuaFd+ron|j?9>Sr)&Dj6T6R;}E0&c>H zgMekrX<{q*7$RGl$%oH#Wdl>`ENxf3dhN8d`@}0tg(@EeM0e$*cvVCoEv*Fvs6YZx z6t5vwdZp+pl z&t_=s#2DoU5spX+2`?tZPGa<>ME8sU{z%NIr2z1eKRCT$z+qN$a7d)0=QDD9!?d^E zGY0u_Z;Wfs%7R-j$w*dWdGK=Ro9uAygq2#XNhL3bAQ8PBYFF+J>8diz)-_kRuFOo^ z_qvj_33TA3OSmr;?TLPkadk?GKc`63B7uFiVk^r|eS_6)ne`&IpheRj-$N!v^fxau z6PGevOpe!{{LRW0nq{}?m;BAaif2Baf@Zy#9Irk3oAum$cAHQhAkG}Gy^g>6SaIy$ z%-<}ZoE(t2X@H%UWv@Oz(p)hi?qd;8PGw4KyYlugsUWOk(nUa*LQ*DDvbOD|tBFq* z&Cdtqz&r_>dC_vyqLoShE2z`P(8 z>fh=p2aaaAR9r0BC|WJE@@M!|Vr{@JF=jkGFe0g{H4d=AhN>}A8W++h{zblX9#@e9 zTH29>*R1*H86|Z{YzAdXKPw>^F8e%PrJ2cQ9P%ZY{(@AEL)C+l~BRyCehN&JWfl!rUt7wk`VLVduKf;dDvGx3* zOySG4LdDDK9(M@fsmEltYJUJaGf?7Vj3p`u=vixhR^WMqG#j!RKq3|iT92_^RS%X$ zLA@@V@t2Cb{R>|tVOM30yPAh^PpcSArk1a)Oo$tcu^eDQCGPZ60_|h~Xlp={6a&{$ z?oJff=o$=Ih6|JX9^|!L?H%EN$_`*TfssyT^Rx5_%x%h zOa8iKhlEsP*`qNyihD3*=vyy^m!DO{Y28sVHrwfKeutgM`fZ^oHs6p@LCtfj zdeakf-l}?Dbz=N8(^JRt1KA%Gwm^=64)ecUpOJfx4F#9=bIUpLI9GK-OYcIq0kMtb zA!Kh+^bn4ki{#jJb}WQbLgXOikq5yE1*%QU5OE@D?^vMLm!>*sF0w38o%jG%Q-ml> zja{=NZ?!y8UICR|5JWmdtk&j)7^w;MNu3Q6vfoL!kj}s{2)*eN=&>3JUTi`Xwu-0Q z;R7Bd&_)(B+5Sq`h9&GGFPEsA8BgrkP#K)2|Mi6R*#<#r3I@6~ca1CENBn?@rhSP$ zBAT5xi=M(!PI-80X36nsZm`59yils;HDHEwZPA_IB@)5$(^`@hzqrJZU3X#>Cw%g@ z{2YTH?s`882V;a9Jp5wzCj_1DQr-Ulv-dvmmR(hy=lOI0y?5WATYr)iRfU{;yP_|q z3Il|Ylt|urT_yzq2L)`j=QG`Hfayq#+_`=*Cf0oDl3Tz?2;oNf>d6 zfEX1aVz5zR5)_nw0wOdGCS<<9we~*e-23kPQJM77PoE`?JD@6U?Ka6pXD|^-Tq2V@- zWZDo&FAqFx-65O>Q(@4?tDG`yi>=9gKPCJj>pda{ySGim7#Ea+rF35;q(YFkx}f}& z5g!xC2d}4MZP^f#Y_tp)b1@ifzEB)?l7DWm_-EvuBo(&6f@RXLj6<3}Eg1F31*H<) zTu>ss4iC>^Ngp9WdCoY?#3+F-PM>E&S>x<-yVxZuN6s!6!3HGAguJu^>zbtep@aoP zX^Be)#Wt60oR%Z0u}dvlHr*yA*u)qNng+H+IIahHPqMhcPR|iKD-V&i6(1tIQ>FFT z56g&3T6cxhRf}u;Vu~j_y~W)@wcJN&ad)g<-0f$uxZ5WeHyvBtpaTtei6q$tjKz{E z+H;Kx1X3Iepm1+)w4(-Ee-!iyb~9VU2G|65Qy$ZCngA67O*p*3jr&z)bvIP_a4QnK zA1=V9<5aOjfCE>f60u8E(P_|yDi0Qb8^iL5Y<&Pnm4QmuQ2>}-*s9pVIoKc#Vei?> zm8^pz=6D&!2t*%{3F4-_(8xo0ue4^xV@T}K4-!SPcVMD7k`LL$Mmn4smGlwG&9O{~ zMdQNjjVIEp=>t(TB16Po{}1Pi&dE&xH#zxz+WVTb0wq*pgaWoZX^WWHt)5{%_**Ld1eB99Xp)&)lLC^ZS->vT zjBdP)6%H{#JQou<#6sw_JSIV#l@ECIxIZsRGtjFn{E}8OGDF{XPot79mdYeWSR*v& zY6XyM$*2jO$06mmG+@I@uZB&969${8o<#lUafTBD3}BH)U?|~GjZfMnOn*2_GNM*E z_-Lum z+_hFpW(;5npM7N>-VYD?Ut50&Rl8*^W!s+@|40@7r3 z_R16R*!ubJ?r@&1T+a%k9fi$M2C^SV@@(a2#soYRABY}mQV@-*IhNRc(5g&hu4?(6 zph1^?IBMh|2_>D`5(p;;z~kIw0t*Q?Hcy@7TH!g2+V~tNTyuh?e(}F;D+CE>ev=vY z8B7B9k$~*rj+@eKbIh!Apm5@D!(E~V6Alzv`8ZJUF(b!upe(ur#b`b_L*zi2(Hon6 zv596L0vsq*l9KUoR&b!4GcExEz#dM3q>{5SRw{@GP=O9RAc8qeE$r?Qp?J98Qh}0_ zF3=S?T9Y-FiET{Tgg!c+h3p}jsFce6iL0*iJ1nUuZ}vHPxmY;8I=W~?92G=E$GqC( zQ!FEE`qp^g5n-l6j+qKMnp@-lVA~hf-nhoc{-caAAloap;PMx|6hkMoV@vS;GtCiP zLpInf#ptvrLFp_Y!*3Npks2!_vzNO)N!>w@`lY$bvcrZev3I3eWl#o;BCxwx5!(gw}xz<+dtX6E=Os+z})f2sa?h z$2k9ME(7liVLIY=aU5EnIF5=LMvR!Pf*EE*@k}Cad56D~Xi8+0_Puta)S!Vf0)f-E zU<^GS*HGBQ%J!-m_Np0%oOZg>hFW~$LTO6INj+$7*14tG3TQ;a08@-22FN0`6-B#p z#}6Mh26(&&yAxWCYRScH3uFX>o?)~2J6Jg`5;tk~{+N&<)702Jr&0tNv&CR6w~9Iv zeksM?CQ?rrsE4g5__{>RMlf(u6Q|D7%F7LGc`NH90b^!^QOA+X^pj~0Ro*;`7cIJ3 zReHon$KIaXS=*wNK}fSfN5!ciWzLpeiX*3%G90ioE@g1j&#jU&xJsK+h6WQ-hNG95 z0A1r}m6T~Wq|Dh|3Le`z*!fsr?xt6NJll{mXEVkzXRS$@ZPCu^A!VYY-om^wxCrn^ z%FI+!25B}+z<^5`_=HIr8-VCukyFSsjn<`%^zwL>tvP-FmNNs3AroU}yBr{fK-ifnLZz)n zt3eor%0_{(7K0Vx2WbSMqTEd0Z9;{Qif4?lM_?(a5Q>8}sPa+WF6N?85vMc$(VHq% z*b0$QS&TwOV&dthFFjnm()On-hOwvt_f!W+%En?fU>AYnRP5ZjSww(C6ns4sd`e0& z)|C^*;JjbofH`L-&AX8^uN~8*7%=O3Y4Lmcc(Q6I&nquv56!q(_&t15#k}@A=VAB7 z!16q(ttN~k2YyGD*kKN0@;5ZBBE_+g#J_{D=PCi9?a`DqGi$@jW&~?v(q>x-7E!P^ zHgB^PnShcF9zaNFZjWKO76Q0c*UiAWMwuaO=gZK?s==fIb*!w?j0Tp-&k)KgnW>}4 zu-2L$d;wTT+4t{lwc<9iArD(g@&F8eCS|&Y7#4Ek!D&^6nH)) z7U@QM3l=ZpYd{JCBU6M9RVPeBbALcVZmzVjAbBkY?>k7UjaL#nq76K8@G~v4m1$_$ zoesXhLhwkYR7f7f=&*KoC0B`RSsk@g5ouPjO0Z1_9EQSERfcVwJgMP$ifwFI$2>Jknh!S>PLS3yPxeY8GMJ0yqyxb^HM`V_*_+AD78o>s zX23^yEKFl8IeT@(dK%5_>`hIhnVk*SevuzApk=iYXgIc9Rz-ntRHBC0XOUG+Wyw)Ohf!xG)=~$reI^r}PmuAH*l5GS7X0LA4MP=QqEoOyCk~^F)m&YxGAMtnL z$cj453MtU0+=a8nTsoE_*yCkebb5(#S`z>5O^UYcV4}(6IpRDJ#d_eS(8YLWNiV{V zD5~I(Qn_jvnzC1`h0&>c~<@?d|FxPdLK<(Q=(Gh0gm=Sj?bYTa=iFi5gz%%g z$zm_%`~ME7Yw(5(o7h1%H@9vuUL#-83arK*u+|w_p(;pdMM;{H(_Tv0;$gN*I<@d* zB`hE@ml{GrAg1_^7J-bO)Q*#|Y)9N-WlX2-n5)=RFWD49y->YrO=Q%>50WsktD1zn z4t_}c6k=e23NbUg9ZaJebJp{t>6P;9f9JE3m2oOjloHr#Vh4df`T) zhivOaD@8Z_v}`^p6B0(b1Z<0EiS)*3CBs}S1ry0Lqhc{f)<2YWgnye5%Rn!wgZgOs zE|t`_AY$PQ4lPr!nV8mG1KMLV_}(E5E9?Jece09QIOcdJ`nq%Zc8K%60kXIgu-Wjx zE7h5HmmWEF<4Ho+n8;Xz)|1lSjVmd~8)Ho5l!{?ieu5${p1}>NI2d65?i7|RZQ4Ro z85x?Ie1qs2#W1&{mULX1G$_DB^srW!HfE#f^fGB}LL%k%pO7$9<~Ua%R-FgMoQd>f zbA*fNZ%1`BRIZQ^YoT2%)H=mG^6I4g(Co@_Vpfk2mX!z0lCTM@g)pX%=*(R(bQQ?SwoYXMid0fbartg36q%Veh|`1BJ`ZHDsAvp(@~MGELFGjRBPp zJP23z|BY{*cqym0-IiarOY4+AT_4vTF{<08v{^Z_i=gA8a=AO7$3dpYOQkZ+VU zi3AobBC)kIBH;o=qS@M^)wi89T}!lNYu~9#1N9muff$IMr~1dm{^7Ct1{5hYvR6g7!pId)_cav+}xBXA8q9s&ZPEYooGT9<|Ro zSKMTz^MecfVrxKDgATFczL;JbWY&FE+HUl35H!2M7iAZQ<>wcSn50u%=*}*bXM#3l zTkq9BPt`vc9~%5ky3or~`(ttKXoesYTuW!2JQ-LuHsRF3b&ES*7?{kH5YimXl3_rizl)@=x zpIE*TOs4A Z9+Ux9V9z=5_Z2s>@G7q%zasy`{rqOCiVZksw`)0h-ms$P><7+%4Mp@HA(_LdV z&qdSfH@K}$qYeB#*1Imb(ndeQI=tkWX2JZk?j8i^Ef|1;;kHUIVdOEp$}CDCp;vCXOJd!-f9fPr!$XdFFH8x z{2tcV>O%L$gfEalPBqqoCx7MNrQ9u4HCpT@m9s{~^ZvgD&$#H1h)aVOlLkSNRpvkq zMnO%uKMqZkpdT~rD;~|TG(9^}4vE`!3V4JS%ZjX}UinEX>}CmauKe3C!bw>3@_zfm zqWQuEi!W8@L;PQgo!yTIzV#P^Iy21PcQc8F&Ha%m;z3f{|i+ znv`Tt7NnNt_sH&{BU!h|EG5TRM^i{~j|C~M!2S4*Gac6L@5G27 zrf_a!hU8|#pww-mv2(B!(J3G!PnfyegCE&mo7l4r*_aYD)eOsAr!{25tlYzxt>_tI zSH07~v<_4!0vG8|>^OnPT5kC$;TIhk1Ho~_MhyZ-{2&(};SOcOLt#*U+>^;}hG(cW zqcaa0Q_eR$1SW8cI^v-!C_nD1+uc>Qqu67`M4H+oB{J*NSGsFR&4%_U@nNGi9*~*A z1omk?E$^Rs#uH)NHtF*+1!o9D5jQ*}z7N1aC@?@{w^$!|qInO9$$ZAVm3Tv(Kw5Gg z$f(e&00fyYqx7pCR+UW+DM;D+YJmrl%Ko9Eal8&OIc@udUANB=jX{_Z@jeCykn9MMjs;D)JvE0 zX>}Zt(fj0NX`LJ?Jx)53HU^Byjm0!y)RhPse^I!!$rk||A~&xgLUokis?rkn7tMf? zlK^j4Ck!$@w(`vfC?@}dM2J=BpEr)vVClkv8dpHg90P4d>LJ8I zg!U~YW6!t61Ex6!8ts{t5GTT;*l?1jgI9n{TqgHG(_Sn`0OdBD)NV`%rJwll@W#70_Ai^d>D&Km@gRj&+q znoYbiFa4Eri&R9Bg;#QXu`WiU;BEU8olC42WAAF0sT)T}gEUf9~Z3z68K z^3%!SI+)LU(lnLV3dpgFMt?zuq>>>9#-KHAx~jB26co@PKGISf{m6asc!s7Aj&rYQ zrztv4yQcJSwz{T`RK*&N4Gn$*AAFNhAW@A0X#uQAST@Fy!liLWfyTL-BW0|&+AmLkVC0pt07I3r0DqTV0RHPQ12lU9gTc)NsU2n*2#&Q$kOh+>HS} zVtBA7ZJN@fHcgeOV%vhQpHMG57abBaRqc-Q0K$1+l9-YtJ{vEfOf@zmjl1G(wP)e3 zMd#E?{z}AyOKjNRh1tuWC!{TjVZ@JB-gK|~_hrE^BBpq8x1q6OubU3XBi)mFSJdc? z^P#E&wy3m<**BC{N|QH~)_LrP?AB3t>REdWQd$>^?y+KCN-Jh!eFj`spT{PJ%H%x@ zv|4F3BLziO3#lz-Q(A3IV_Oj>GH6jLt$4H0Zq-oEu!9 zr@-`{S@AOxhBiA@)7)ZL0TkXNvSTsB%d*NT=7;U8O{~1;0iKN61+p94o!w99y97yZ(!|M4BQXG zC-tQ*tlwfQ=Eo=uMXW%PYgs@oVGYKDJoSy{@_#-#z?N# z_Wnmxk3BbG99JuL5mze-s|5pLwHh8;t(zvmdJ-%V z2+_0|ctE*0lz?)r2tq@-YOZ^1O&Q(}umt8h*wydHl1$Tq9YL?Q-Z- zu7|8Sf|QziNs=ZRDgJ5|gaN{-_RgDP1&x@!EIUkwLZw)l6v~5Ql?BC0n$OWbJ~R27 zz2iC(XRLEm`0O#^mg!5dk5pp;LLSDQx$B6JTth^FT5KUQ*QVx$(2&UDI^{CaSr%K@ zHlvq5CHnM~DOe*Mb5*pN>1yJ@Lul8!kwk{d(!&}%7pGH$lb!rn`nH;2@C}YHix^J- z?)ko1nU#DBzpiaENfYs=Vw%!Cnz?b}F0uVuMd8t@(fo}!NSMJ;4H8HiccG3gUyM_# z77*}3cqgQ4q%O+afK{z@w zxi#{^PuTkMLgdglAN(f{?R@v~BJ_~fS3(cib65h>2BZophRguHZg?b(Z59M&Y8u3l zVfqVbW-Tml+E&09D=wX29b zB?R+bo8S#C0eAP29$6_uT zW<@-Pt#l2R0F}T2hfXe721w<&Y2sC2*^l3WrAizFOSHKrEa8IzmNNMwEU_O9js)OL z5rKHNXxjv0J~(d5g_c`;SLxs-TKvu&haVa3wVZ`+!e*xPfJQP_0|G~$K5i_d#-`5V z0%sQqn{I22LB@@7??|xC_F);T9`w?qp@9~FnS>(v=3A0c!UALUCDJ0%io3Y26#SG7 zu_mMq%J>>)CAk$jgf9RQ^TRfkbY^lk+{Wo3266(-r7%)N`@7{VYTd> z6}}4hO$@Y~dQ-dF`7qu}2hE)ik`)Tu`QYUp_UWYUvjNih^-%Uf>TafNhuHgYma$O$ zpRc4;_L?fjW+o$dWoRHJ1}{PJcuBwiAF?Xb(LJZRZTzS1>@`tlUTDFF=>mD_0xij} zPJ>mnDmj7?W(omoDA52R%YkBj*g?fb(YC)Vxk5BQ?E7c&H9bfz#2_4H*bRvNl5-bkzkTl;qA)_ix9804s-5DnHp-0O zn>r&4O&$*8!onE+uwyUz^lh@%U?1{X6BYAVdGNvaCO;_8+)1LvbfEVUHUb~SzpSP7 zn$bA`6Jc_F@mY)k2Z)sC6Di?|2vUA^UdF2E3_!q?#kLRPE%8pO*4RVzGWW9bzR;Rq zJlp83G#%QSZGBn!rP!=~p_a#97#~uf98oylOY0D}f>DDnIJ+69)1q|IynFc85-~h@ zl~@|9VN5H!0SwG}#kB0q1|ZO6S|B{Sh{wV4p&(_DNG@kL7D#Re^IcaCv2muCh*y&E;UWXH%Iem)9%fG7}bR`lRo6n;4Bd-EnoK z`mUOf!aq=pI&x=y8+X6$;4Z$YUGj`wEWpHQl2Kr~)o9S+9%i_#G783waG!#&Q zO@d9j4{L{5!r(vTh=qI8tBW}uz-)F8X)fkjM7^G9)3G+Q3`C(fo)ln5qN#i9TwSv| z<6Vcdo#A1OtE+96`#W{mpFCMcQV%mRWor^sFjiTi&ATBz^1-&9oOMKE%GW2Rye6i6 z17Z?KJPl%+ftc7VolZ=%A|`gVjukVjh^e_*s)7$99v1#vLQI`UKQUnxD(os(*cJZ7 zA-Ih(=mpqw#azjIfMI~y@AM?^K@6W24MBT4j>Nt5A*|M~XS!~QL*wls9%4kzo8M?J zqmW3fKxcMNnCMq3Id3-u4MLyt^4dy6O+P&92HjmwJfprp?s$fK6l8IG4#y|HOYswv z7OpF=C6UgIh+zLK=__%Tr8nSvGZ`#G+Bo2VQFUU3Y;)sxTpn#mLX-z<#2XMSFA{1` zl}9roAqu7)D?00v5VpCKP(v-LK)>+uG#AEJgbnoF9$iS z*<9na)PD(^ZCErME6H=v+HtuTIj(~6C%OLEh%GklhD_5! zZ97gnUlm_y`*Cz^sqUYkFqrgEh!=qw_xYSwE6YxgXHD~n3oGeR@^|y*E7M#_pC^lG zj8KbQb6PJph{vjE_6DumW^NrD1gIy(ozX>B1+)Xb2CXW+H@$U~Po>q4XchiOyyGfb zod{@On^sBMt7x?qX;l{|X;s(2l5twqMbWCwves75j9S5r+TePG^+)Ygg0MnsX=m4^ z{dc8uoJ2vOkznO-5Ya+Fg=}p}4kYF}#+8Z9umSQ&?Em){fmeC|KM>2{!G?d#Y#^74 zMjf`vh;lhqPDz4akev!Mw9KiH)FJc`yE#Va)%}9zR7ir8B)|otRZdBXC*1pQnPZCY z_L^qW8pc2{41v;k(i#SWC#^wxhGQqo551R#8F2QIQ~zJjL|-VLt@JpPx-T)#Ljz)m zpR13HvS-^aUv_{c)k??`p+6XroXxngp9$xv{<^fcZOTc{SSw9(B?+gsyCVlM&RvYz zXdiG5H&PxTl*a@E2cO(X-AgQ>dHHa8$GuFC8#vL?1D-7>bxYq4RIYRV@XHeJA5~>R z8oEmWcO=O_&;K`iW?%9=tH-KohDQ?rzATdw4m_3$D@u()#Oow)@{sMr!8s#+#~|X& z3}kvy9>PRBtntcZZYIL!&DgYjjU2XS<~K`bGy5mmP|uS_IKI3aeTC<072pL)MQ;dTCqiWXPF~I0lLB=E|%Z% z-HG`8M?aY8OKLhg#AQw@*OMFmp0UY>(lES1#R_-@blum%rnXdn^z*DL`#eApnAoLn z`~tfE;Cv*ldxIhdi#dbtVH=6BR!|}!JL{!~eH%#-p);qASEfRJKxM1ScVo!4k6yk+ z0AL$h=C&}_Xa0=vSjisIF5UMh;g!qe3FLO^PXTRHKAzaB{B~?EvCv3lrCpwlL@D!|~2~bosTGeFj;ZcU+{# zu1y_01B!&;8GPRM0x(o>Ac(zd!rlgZWQbay-kxEyXB^``6aP3N!V@w)!1*)av4 zv#n)p&rVg~w@HEDR?Kb`-2W{ww#V!R7#@^r0DKhM+6;{dmBTu`>!1ZiSsH;P*>DT4 zjgBJI*|X1=9mhx^7$K&T5&74AC}M?zI+P#(8j&@UMC7&_6;s)j8+2ITVw5XEwx*XVhE0J?JRtSEiB!PSZynb>33+oJEVR8Ul@eZ*uFn`pL z@;SB{s6!G#)V{GeFZ_UfE@qFiCttjBrFhlR!IIQIlvnn*SB*a(reO}8?<*x>L32=K zkj!q&deNGXCBC3teTQTYnI7S*!Hbw5rMqW`N0~tg|ACn}L1e?wAXRg__5UtKvH^?J zFxq)`^9DQIZzY*#u>Y`D`s6SHU+NtUacG!A9UaZRn@(sC!>tGMeYL@dw;zzenM-y@ z(Sc3udR|b>4Ag^-455Di=X-MR2e-a`@|}sV-srV3o^HL-3%E+vn4H*yt@9y3Q;8Mn zBbR#Ke%JSfTa~Wcb;k!AeU+};H7E+NUDq{dYAfivgg;njMb~v*lUh_OIw`+Z9U|I0 zbt6%uqyDpP{}f2Bqw0ET-G;JDL}#V!O8X@wjUtUwmJ+*V+k%i25pWj!i5Y3CH7Pir z-~fFZ4TqQ3I>RcpQ?#qp0`=x$PuL9fN?uPmNE~OIlo675M45Qa>J%~_auyK_Y*rU= z&@}>nP=z5IQc?7*>C7F-j>1&O!}`%LaI8dH<(PUn(xg|g6r9LMGwg3DRhlUtq;3~4 zPrgs8tcVwR2jfrzo`P8z->Vqkvfu!(ghTaiJv!o8ryoM_w2K)cl~*W|sPiNAKU8G# zcC%`VD6||tZ(z4i9n&7Nyu%9od=Bh{uIMx+)JX|I^vM7Ii&_~cMQkmxUU(A8JI|ia z4E9yjxo!*gYGdq-J%;K6jJ64Tdx%g-8<<}I1FV3I64n&7WiR1YPKE9qQ}AiQ|IZ^V zfWMui>;>&2&FT775$Dud1sb6*=1e^Fsv(&&&}|H?U zp@B-a$jZ{9jhlAZpg^GPdFW8i_`p>;(^=Ok%_;pjo+ObexU~P?%tOD{n8R8)ma=|^ zVd*%A9RtI-g*;R=v6dXQ9rTJghtghiI171uxDf44hG>Rec(*H@XuPbWeYa2tA*6daOgRptM*MDF<)jude zqYz^i!5wuxyod=id@d=Ses#CBm$^G?Yn5f}nU=iXD%8LSA``%mZXRFd=oJ&%sA~oJ zw+7!PVb8K<*PI$GSs5|$03s{)Cu9eJ-v;}^}>)l5hF8uQ3Q$rFI|i& zLV&_VOb+yg1}4fgUnQV63e{i<1s}Cl zs)0-#nh&3gT1(2S&$4|c-i`Han^l~#P8^gsq82xw*Z@WNbLSGOi*m(HjAJ1nx$RIa!xuH$Sn z>Jgk!)FU4cDNHy;>sl4{D9mF1fOY_A&B+Co+45*fl6t#j0G?`@G)*t?@E5scGdQ=g zK#TK^nn4t3dT&4M?*iCb4UF->VyG@XE^|v*%<&c#DD|>Uf*_X#Tp88GzTk%nvK$+%b$jYD9wD_qM5o`B@6~kFiea_ay0Z< zaQ|2D7hD_TJ8gx&XlX(8>gP)xlbsB9mA4k~J z$!eQ^3dDe*#zE{*@b<+Vo!amj8;8HH=wM8!x41|sMT{Z@0oS-xEK6YQ<4Ea3t)7jbU?Mo5|zY971fQT&$IQbQ)`3p-NbMQ=`}FH!ks(o#KOl zX8rZDWG1U;cHojX{=hAl-TS&rZ}Ff1?f0(S`LX}_%;j79PcW{#Za*u(@Rv8;^4sse z>xMhE+1YZX`sDvWNn*?2myJN-*B12%Vj9X7g{KX0?QE&e4hGr<0BQ7%qyipkwpfV17-XOs{EaKa^*D|y(Iun>XC0Gt%h<93s~ zCdW57!?RY+@T}0q?$yIPd-d?brA-d+?9ewsX4=4RPJQd@zQd(W_PteoZ)4VeP}Eua zw*BOYokf!Jxy4bzKs-k56Kl*y9_z>!BrB_vFlI|m!hm}#5hl-3%fd+*9qx7DTvh;28aesvIo^lS!LFYb64Q!;$q|ahW#Wb*_wh7W?#S?$6nrHrP=!%b zgC*L?>$A~J@Px2KeEve7<_S`aa|!qIM(jIFa@Ii^>V|$V0+#Y+zMMzpxmP z+e=C%Lf1}T$_F3MccT58Hbz%yI<}zZ(m$Rr+jX7lrUWH@*dcQrlvAo-*qAvZ(V)k! zN)vi2^+y!hQug*tU9#Uo=LJh77`>gOIMn{?h(N{|aw{&MXX^&y)w1F|@TxVI)S)oG zIdx@GSJsuHl-M6MJB|atSr@(V4lG*ERhA{M1<|EUf&Pyhy< z2z}E?FC!1%#@QBLK0NPsh}(-GgTZH60=-m@d{A4k7Q)-sxY_Qkg%gj#LxC@BOr{!- z)=B3PgeAN~X>g*R05x1L?pw2ii{crtyzCdUZ^fI+bO`(%VL=Vefr;RdvU-cm(hw!p zv6gl`t>O*Nhx%qXKFek%3}m(0vxAYy<8%$?3Z_qWvzoV^pZNNW1B019XX`oAu!h1( z9=7Vl0aI1j{sMbJUv3~zh)4WW87g$oz;qR4!13$m@cJwR1hU`v}}(U2=Tn)z`7b1RGkA|;LKfdPNbOxhL0)ZKIozOHW9M)DqGfs9KeHG=> zKwnL^B0|kp>~N9@gSwm=B-7ndO?Pa~>*+FAEp^&l>R|T% z_dok3JHWlq0pKjq&Aw~YBn}Iy0WY{Kf*Xu1*=ts$Y_&ZDfxw@~34|74ZbTCC<_e(Q zfEtuOA=nG*@$-nq<4jBvPD6QKtGDks(sg0ZbxKC5-#IOwDH28zq8CvFQEW9uboIk1 zf&#KdQh#~T_^DQHv`{&Ki=pl;p)yj02lgdJ%3FAOg37#9~*b&!%HD47>CKVF{v7$%EhDu}!jJi3>9 zmG6axA(|s^MO&hoAn_J&otml?TYq>}YnrL`TfH@UUZZc0QJ?6WW@`O5Z=H{|{=HSL zX{Oe{=B?r5jlS<$)tY8%eXF-_kF{Ps5}K*?DR14WS{IjrgiUbJLd6jxfC>vU;xN-M z1NR*e-8=t^E!FLO`K>?U%An-4UmXjDbR+dfo!fD{Xnks=&Z{mN^I8I#Kv7ZwM>wfpC>cg7MabiE_vpu8Ek3|H8ca>?MS<;E!u^WGq@%tqijJb3=8I1OxIqgFEYYVFrP>{tXZ-*>adNCF~A_Uk9Q_R4{MkE!j4?IDC5YL z^2vTc%SCn^i^g3rd~lXjZjgr%9F+P1Ijz$UVx_YqSA%_}p%e5C_KRpy*|7&i3cg>) zHD12kf^PF=hGuFz>jX^cFvW2qsP3@~HcGFNAtj+PUhsbKjyBqiG5QScfUcyp@FtrT zyn+ttX^C(&DcMU6wYIWyt;PL2ab-iw6_0$p#e?l@g)~{tQU$ z0TKof8k`O1f|xVKIPF5@Qc!TR5?bM}QnV%s#K)KDKD;qB-6yj90nUJAkUcOuW$t z>4MzI6Sok4wG4FZgmoD83=(jbo^clX76iNxTfCmm_{K%soKpmmzY_6&wIYysHq3(A zWh@w?TQ9c*ZUgt!G7*+8f0e`uenCOS=3I*~$*V7`n8aYcq5oBPt(|<(D%65uTFc3R2 zJk=)eDhBY7hf+~VV<37}MHZhafA8x*+Q9^9ee?k8m=V>dk>E4v0Qrq_=xS@F-MmV!o%n4$1rN7G#qk-qkK!cBRMst@M(>s?1rJL6Q+;xV5)ElDv8K6mf0sJ1KBtQ+?y6&MdEC>Wt(8%aLi zc*!R;@azl8DFY822PMV!BWOqn5;qLM9R8TdADWA;*&YXva?{xx;9nwh3QpI5>q2vb zTAR`FuYZqM_;kB`fkoH0M_!ko9Bu(SxRf<6&G(D>Qz)m1SNGnrX9K@ptUF>+hZOg?5JtcC)@#XM94X{knP+q+5kcaX9TBT% zi$Sb_)u_lgt5a<2syYHz;#Q|okx`ys zD1hSd%{D4vQ4yj6%-NILnL)g8;xKL$4+ET~$k+-c z#s(|-wQB*BHdU3Pad>tb@FbCH0-hSun(!orxtLiCp64jZ`5YxVZ(9Y=na#peuE7Y; zZmd$Ii<4D~tfAK^Dy*SSFtdgRt&X6zK4=Bh*^_D~FXQ0kq2YEu=W&FoJVt+b7QeD$ zp0M(vaYFo}VC+2QI)*!7h#lXqni+MCKWaY#28+_dKUXMQk6+X#FpUIdRMstaIQwdN zl6ah$FWo1P&h0)`;I20l)X8urP+SXqD5#{5Q+Q@yg8wGepL~BpCM1Jja5OA1=<8pXO{-F8sn`QfBJgY29FyI-U{dpRt>kY^kk7z0syr(e`qxC@L-f`gCV740x>Soro8v8^8qZw>B}tzO58HW&;OZJhJgS)-QD z*g0<|%-8?Q5I^MO~V6=xYwvAkKjX6LaX-l{SZ< zYJH}Cvc??xjp%O{n6MIjJPn{Mo^FSWjSdk|<{Inv-)9FtAs$^2w)YTX4Fiy)f`zuD z*w{U+Gmmi-g!C9BZzy;JsNNzgwoE;-ie$XD*61+9%YXdvmtK=!4uszPOLu)S zyWG!88(i%wE$S(AKTG-S`h^8xskq5H*mu*cnR0p8tA6P= zog)r-&EEy0gmZiYWUDi517w@$_@)d_kd?dYiZ_6k>2w6T?U@z+GeAvdCS{+w7c)mXR~j7Va9Wl`X-J1Wju& z!I_$s%5eDCoT;@2XKGd|6CX8R3bj6kgd&Zbi4>;NPoD_p>82;*ZP%Fy9-XNr*G_vP z0=ZVPf_cDIA8J5Uez-Ki23bM`I7mTImj+y8r~y6s5n)b)379vD{NwoWa=1;E)t_8e3MJ$kfuJ#z^6qOMmfy8 zrVD=f8kq~&*9bNe*NEFSI`PBT$Qn$nQIjstpn~7L#6e;Kh8lXKBI-j~`~r(#>)wCc z*7`7QH*TX*>$3byL|x}twM>!!iXmx%66+Fo5`88D6}Q_w8Vnk4q`pc8!@JSQ{|mBR zOA*gCZIh4g26neUSDKem42A@iF=eD= z%Z(|E57Sn(?V(K#V9r%+Q(i%Y1=~4?6n)HBeH@gIiwW=>Qmpdwsj-=M{VtUJyC{1u z*FVR@7x4LcKKF8&Qke<+Qp@)BK2k<$x5Q5zZ*(|^0sl1x%b`J^mlq>UegaYoPBhRH zOW6l3u$1qeeaZQRXjrb$43RfjYkO@Rd*V3Q*wRom@VGaraicGq{A~m=Yfxb%Xf@Uq zSE%63rX26QL7{s&@g{c1;+TEkZAGCn&z8w{xdQ1xXjLTXgy2uBufx2FzVnzmEZyEn zFlS}ceA(taFEezc-2#uGT$IH~y&t{z^O=wtl@~miml!1i!XrRYQ;p=%f4OSmqC#ec z+BpiCt!SMbl!9!FaZnJab|fYz#a|UzRPE;z@YvkhXChVLnT+*dp35LsOhTsdXEA0w zj$Cu_0D^8c2kGU{Ewr&v!Oy~x)sx)vbk?nBN*!0t#zMCZZgP{=V{C*2su-z{k;A%0 z4xHy~|FwZuI`F=Oxw@p#?=&=~pqR5`rW#5cviM1JDj{>QG zMx(&6_NBiYk_geHhIlcW)QRApOimS+CE!wHEzHBvz$Y9k6+S(8DSN6I#SVgFYp4et z>ROzFuyq{jRbO&27SD!#&_eOh+AI|B8)>)N05DytOl|jNA{Gb|E<8Xbv(zwSe;lN(@M?4@HfkY1 zW8-Y8D#il2$~L?RA4ne?BK4cU!MQ*8s{LH^D%DQRy)xi4T^## z7#}k(t{r#zJj~i-RmJ0Ff5-)ZqY)RIp2YqHg3W-Yw^?l`W(_Anze^Oy#6TNSNMUk% zo46RENOr{{jTpKWb4U?}Fd5BgA{>b)n&C*MXvpjrb~VG1Y<_VPproPZ9MchomXv!c zlm370>A0=8x1kXFp z9)>{3N{#U*lHVGGZMx_3N`(g{2VUIX-E&ZglwL0sZrH5Bb{iRsrs0M%iXme$TpAy2 z&~wHIt1^nF^!mwA43E<>hpOsQuvcfWfD1`4u=6t?eDHs}9;W3EEWFEbYBWpBX#?G9 zPAl}l6P@dCpqYCZq~^28ecdRoe>Qy~F~CrCCa?|lu*?)j*REpJ+La!tWEs~DskfvU zHKdIOrd=}L4ifLhV~F-gk9)xpJ`U_+snMDEN`4&s#MKWGtDcS$%vuby+M19{zKU^! zi+Cu`lrT5Q8HOQVR0Iv3*7DP_KbSJr4Ccc$;Z{N#^#oNZX0&B&2;PFvPN1HNryoP% zBY>`tISIwCK*QtcUX?mka0=MHcAyF>fba|DPw_!~WENb`o6*NXx6EFXRWYNqV%xyp zq0R|~S0i;^X$|#jtn)^%VvdK0Ex^Eh%j6ln6YYYDDnJ#^1!t?GAjd`CN~*(z&AIB8 zzgJR_LLiatR~YdGDyhQRzh7Jo-z3yxwKZ`XYsnsv5~?rXv@f@re0WXQ3zv%DMD8Ph zxVTQ!h7Kkt7PLqwls=Hq9a?GqP#Qs1?ywibrEz=F1AHg4-P@2(N7SwGJYz+hG-(z0 z9oU&b33Y2FPDU<)>sRB<8g^|s0-$Nv>e31`00G9wYKS#y+h#Ua(P8};&Z2-OVP~)` zp1DWZ&-!H^(UTdWp2bR)LH%z8Qr!p=}(N;2GHuBic5e*CY^!=G0nz7}tt z54IBQYb|XFSz%;gs8&zBw5uPQie&(#SuU`Ok|34VXcpx34BU|=f-s_6T{ff4gMg5e z&^m+gc?UlU`!LjGfMDuD(GwjISm_+viyzU22+_AM`8H=i3wV*R8rISR;q`vFv5-#R z_bN);Z}DmrC#craM#{aHDWg@?XwK!95u}$kin^09-_jVEeIt!Qzc!V|Ag)`~CHRFz z1XIY74gV83(JZLsY(-s&XL$Q}u^t}Ikc8bcdF5)q>q9DRMBjlLIqlJ?@%q`O77*!i zS|x#QtpSK)DxX#?$YY95B@h93*ssdReOgn=ZtXr?sCyrQ?Cek{3}+HzOH&u&sYi$t z;nIL8d2M5HMH{a(?$_zauVaSn878KSSn%t>F@@>rrHT^n}fbkxAqeKqqh#*0i z}{172dBz-f_YAGvE*kn&;0LA8Ex^*5(;Xev}iiF40ESD=p&_f z7to?FN!#gp<-AgR$jR}^4bmJEf#DjRo#;x=){Ao7zFLmW^IP5LZ>Jw z$qtELsS7G3rwA)t3!=?ip?~f+@{8#zcy#Cq-J#Ae)}(l48uE+%90cB0)cM6TF~3;3 zEzFM*bQB#{ze>spaS>pYqMG#LD!+IsyUn2IlV~Pzhpe`TI@#NNvX%2;GL@BcMq(duUILN>s7R&O>z$R`l$&W9MOzKb<+D1H9LRmRx2rAK~M2PLtV&$ATK55O- z?P!*n_R&d~?DhM{)*aXQbH>i3_Mym9qgb`!t$04iZUcR0IN{n}5pf{*%;z_p5h*^WdsI`)*0C)aQBvg8gs=%HB zQsL(wD)5;Jq3K1W-J^t5c)hV4j&QV75DF_#+`n+MNF?BEC4@#V6x26eJlTfcd#6pH z9`QKrBRBNQ*gmvBPfu@g9Y%@OXLpFj!zeNt2)P>w%HuU%&?~EDX2$ph83tfBTvyP8 zU+9P1|Cy`8NY#D)QA@aphVVT1sT+Ra!Ds~GlyCS0*E|)51LQULiZ}dX)-elAULRou zi_70Y6ftc$mSv210k?zEn6bhPU`SpaTCB$6vILA6=_m!=x=_(pph= z&~cna*qzft$4Fndv*%m=@gA5reOSBgs| zHOmM8AU_g4)!E>-gB(&zMK!HWTc0Kz2XEX23twEH-ww6`|6_Y;bWrLT1Ttdfw{}0=~ z`Jj_K&AmkbYrbJHrk@BH)|w|wVfKQHDrhQx#fw*aoK@^VR)!t8=$@!>NlaYy<4hbs zjDCzeapiHgVggo`vg*C+Owu5PNytY#Ud=K1wB=YI?=`$qwLd#=EIL0zXyUa+=M4uE z`*YtvzY+@V+(zHVW##ofahx3c!mKpd3&#N$&zGKV-)Aa}JL@4RH>oBKYWJ6=j zi9=h2IwFhJ%&Bd+D&{1sx?)aPJ0cWJz}3u2PLnCjiOUsplK;?fJEGvDsW4Frilua{-2wWkEcPG;(9&vrEGwL-$MDw z9@{h&b#L+DRn@(v`%h#tdLC-CgCM{`uCc^v|L4rVl1B=HNhlM5o@ET~*%y+pqgDp=F;; zepFh=P5F!cVg2~!~UO*Fjp4X-b6(YOES3vYYcdu|@J$0bI4Qew#Z zK#9R4Cq84F<~z#!?#ZtbJhqo7KK@tfRfle6{OoNOE_{}McKMbK`{h)oqgCH~t#765 z?1j{*dhnf6oAid=_O4rxSyRO1I}d#Ana3ad*}pvav|Es6>!>tt*;zGiy1YQOgZ}gx z=Lk>u>qWWs&9|oN-@4-09HVZ+joI77#N*1H=8_w#frDV7O4w+`xQv#vm+IS~+)lIu z-lwGeJ=-H;XDJ(|Z1ZpvuU{dt*en0@w(=W)mXvRjGTu9~i+@{6;78XTZYjU{B$D1Q z;-Q8)*vQF{)38%-Dl~&+Pd6<>B?3`$mq&BjB+l@y4KtgVR)N9t??_5(nc-*^&o~&O z96;@4OXj3kFuQp0__AFrGLWao$>TM8j=JMW*_}j6P!e2_-%TVvr=1q_WzM12K+wQN zgT?g=aj`q(dR{V`mtEfCti$rAkkpnQE>o`#9+bQJP=P(@WAkh4WAi~Dqx`Jw_hQ}^ z8Xf*bFrHq09>d~H@uKKDT_lu*RuMD(Dt`L-bITVgfXq37H>rq|7WZ9x^B5dtkHQ|^rXfeU_g8%@Rp8t z0O^VsaKcRqrsWJ=03yFmgVGl27yawJ_DVQF!6^|~H7HR-gAx_OM^*le&BO*JUNA<9 zLYH0iYLs}PQ6WqQLYyBX#Ch{Z%PUh5vDzTS`9_}Erm`yL>pU~z_8RS0$_HC$Tlx6TLn1(NLuiX@ z+gLp|&(7gv$D!d4J_t5{3?EB}hLnLAZVyDuo8qWoU zA{3r(1j*JG5e;Ovi(Ttsi(L|}aM~7w^v8A7N~_!=2c=uSTX6I$#)DH;sX!st0;w7M z7g9a6zaCgqMJSi&A6|G?@7&(G=k}^U=Wgy#7Mtbgw)|^yZu{KyTnht1V06k?{sjfM z=61ykt@7kYb>XowU5f9*Oc(fQUtvNUHe>88-)?K;8Z+octqr*%cWB*0v} z3?_Eo+&@$LaUe>1smSwOMF?1st!E^JV%erSjf8DCzy14PbMQS^&X0tUC*ECrGHeV!ErQr5br51S&$b@!n5jECCl*=|&=+HFTrx z&XI|)SYI{zXAhHVwAPZ3)`iW2U{ka_$_$L_R2X;j#~nfzcW%M#pc?LfR|Zm)+A7{Do$TMj6Zm)m=bfs}zT`SwwL9rqAjO!SQ4EM1vpSpsW0u_&FOXikH?ULIf@|4ZGHWeQg{ELj%oJ=Pym0z+7aq63B)#aDC{EL}M!fZyE8iI06?`>~Z1cf8@e>qc|OiaB7m@3LLm z;-A~r2Q$zI7K~4*xM=xlp>Dt;D$fW>K+n6tBDKBln_$sg`9;HT5!9?<(TBjIbgnP; z5G7vSd{Wwhb>l7GM+dWXzj@{q|SF?L6G3mMw3XDSy>(0}q=B zA&E9sL83dyj#Rt+_i8ayetn|SE>;3kZ!|gZ% z>iW*l00&z9wWxN!{F^}99R6X0pic0-l2rc2Zvz0M{5;$i0CfA4ej5PT?N+!g0OimTGQ}R%gw0Ay%F!|(b70o1pSKQOWSe%Bue@IE#E0OZnq zgWvTB0=$2{egN>DRfErOfOwPo!P#6QL;bBP!3-i(U$s`45xuA?{29Eq{d+HjDOJBp z94Qt1X+ARJEXf)!<7445>d-?qi>6^Gy2iuK7Mc%Y-FWX8b)WX07ZRtR)ej|HTj7m; zF_2l)FJ?;d4(i`y^}{BAL+l}Kh-@zs4wjhq@|%7eE^6dU@~zRUTn$oge#>veTmoewilqvmkolZW0 z2ZQhCMl$<_Cb{ej{4FbY|Llnq1A%U9p_;ul?d%YptA=Wgh|@FVYDw+Eod;l?0an}eibB<4xS zg?@N6bNhiycmK~n`6It`^QE^m+;6ML&>?91$5@qxgS!}kd#qGKtNX?S|K_;@2NnpPm#_bq<~y2+lgiwIb42NnaCcfV>^u`cJcMy^@1IQYw4CC9PI zn@nqv#^9j5?&R$U?tkk)eE3;E^6U+U-Y#$2{bG$-G3nsdl~?gMv_ZmgrYc?2QzrcFZ<0&p#w4^qie4u<0) z(`cP(|6$pvN|frrU*h&3I{W-A zMKa}%w7bv~-|DqfZpfJM3S7sTCOY#fVFssTv!Ww+X7~m^_%~x&3f#dCdqid3ql+PJ zTGmZtNM|hT)?i2k4@$gAS19a5X8_1()^_kxbjc!)WIWD5=>Ps>?jo}z(nt|8M|DNr z5J}LNM5N6fp}L2={_wPWFkey}!6|p2`T%%8>g$yE zIR77-;(uS7V(=cDD2bkA_jm<9`})8A9@kxuuXL}Y0xrAwMeEdPt~hI@dyF%-`0|`x z?hm`xoL~qyq(Ni`<}H^F|G}TKyldac=**|Kx4YJU0vlUAGHpMhSbINVkMAdtQ@Q?r z0>|mxPT+Q+#apl|4X52vA1~c(*B>e8jGmHv#Hr874N&@tcjm~~b{(N^Io4G#U+R%Ya zK-CZhqv1gAtnEN1ps(pb*0Q<-xl=iimC?uar#g^3j}`~=DS_qTb0D8O)-TRFHkvyL zM&VL_I+knPtUyoe7h9{94Q6&;uuvQlS1s_?YJs;_3!H0#_en=0=)!i14vmP|N4XR( z$xW>tUXbeXLMnNuAN(h`|9?;g+|4Q*L9Aep(&tbG#-0QkrhfyU`He|wM|ik((x@2@9)|Q+>AkY%0XWy zN|_qT71n^WL~lmK*)J!E3e@1XAtZ2UA(xp{T9`%xSU?5!S z#w(bo$O0N%b=X?Wss*Xh@i#GeO#N{`K1v0HLqEoBaPXD0FD);)dVd0N=VjhH zc)^e2UI&HZ>IFQasxqor??X)BZ+S`GbE=*jqVp@gx}3EOnvG68>A%aeRD|du zrnEwJ9yj*rh%Qg8VeogW|MT+;WcZNv?U=sD5z87}tOnq(6++2)iuC~V_Y3nw95ZTx z5r(P}O~x@t5(;t5m$)LUI_^WQyEO0ZIDML<3ryZ)cqT^|5s>ESvLGFWFSqcarqR(gYF(0F zp!f4)q4|D8bA322HgQ|1mkHZ@5!(|R>Usk*dYOssMIB9Q0G$xVbQh>a=#C~;{q7n% z_r|gJFG9(Xh`)hhgTr?x7HAL7Ml?n<7QYrQJ_B52g2YS>Q^)Fqeg(i#!8GnJEE(RY zIB9o+6;szQa^U5|@!PumS&a(b`9ZytevJv!ZIcPNrZeF>{@oV2-DJX;3W}qTOqd>~ zIfK{ffdFaPC0(rN3T`*q>CCuHm}v}0Jb^6>)ei@ZbiB@s2`CirZaMG9^(x1j?==wT zXKa{IGDRjD6ZU1g!kN#qi`k2v`CQmwKF0l6F*{?UWhH>Np3gyIhT&Y2-jE5=^yo=RhsF+95P}F$CU@9H@n>eMBi_;K-%2Fp;c9+Y2f+C9!dqG2XOj@2AadE= z1=}a}f^8LNCDDGFOTfR^$oesy1Y9ZwvdKX`CQ} zm#`7`D~cdKji6n52^9N}hcpqlCTI<80qgVf&NMP@`B>kjz-JOMIUCzPZ{t&Z^(~SW zRnYj$FUsDo2A`GdLEQec*!ac@q>J!Z*FH^Qd5yCO2?vy4Ssdb22%O=r6v0-p2E-rr zsEPm6=iO;w4xgb|G^#u|#i2gUD`i*91U@*LJq%8HRGF?=RN3q*!X_MiZnaYY(>1SB zq`w>GQxey=WL}6`9GRgSyK0KhGR2L>b|tzR2gm5dC?`hta<@wIJ1Az zSJeD@yc0&uPb!L|dwAIpetbHu#OHnW*N@g;@8WCN;x~k_EOjllCLwTt!HpT~8usvc zT?Ruw%O_6aoO1zua-?P1$f$xiA;LEt10#--UBlt!=nmBwzF;9Y4TGx5A~C4ekmWTj zja_yc!V@z9oUaY4HDviZJ)q1;mQ#ypJYs;J>TTUlQ88DG98 zf{x4Zy4NX48D;oA^im7)R6-ov;-k7s{4P>FlO2)ThWUN&1uv7T`n?wq&B}8Xo|UmU zV)N33iMUxV5CPAE_oMEsJR;P4M>SKTS1>b$|gU?$2)l1AZ!*t5m-p3?lWj_fR z8c-IjJ?ELACKW#E^4G3oinvniR&3_M&_ADwQpMPZ_WLs_`{?#ALQR3m$5O(3`6TQO zHAsDu(&OZ|kWm{(&sLNs`G=RAW>6WC1AAhI@lIWy^~h-nXf!DoZz`{H8(Qso?m4kb8ZAHzLP@?EWLLSh1PHjqPKH8B5TW0q!#r@RTgn45@W84 zg(e=@t+LTV(e<63<0psk=JLN-0<07~S`YxOEuoV{+8-*rFZPo!w3@z7B-&N0sdX|$ zv$HUS!R3Fl#UxF!YGfIrwk(bO;Y;#oht>bhdxaxtX7v+}RAPD;W&e5%N$zVlBl0&$ z`-?~eYZfe=?-6fA2^s0`mOG1JD?s2!fJ4#~yR{B>puRhqIJ? z*(WR>0y!CPfI`F_;0*{LwWDl{pRKEKFoVxsfbr%y%s1Kk+}s={p_Q8&4scJ38DPNCf-DI3d zEoYoT32ZXX8T<&`HpU4{co*~!umM(8C^6ZW08ldUtSaq{^HU~kC3mv~o_{~F<1?_3 z^7i-fgvAO|>m*l7SU1Wc^5WlB?zjYmt(fw&Qzpuf zw=g2{d(yV;9H^8{zOxlEmB#b>5(yD4Z+%{$e%*}>QP#JB$wPejQy;Zc{R#>w_)|Jn zZlWF0N7ZiWL#cLa>O+{DLDeRwS=|A$Lq@C3r_yw4)Q(r9si6E;) z_e6NJ1ecaOt|@o?_#ti%rT_3Saup(^v_OG7k$}A+|Bw}~$E~eu3vkXn=i-*HzCTmV z*k^F1&APYkO{7=ptW|0RQ)dA?SD}EaC8Kksg|992BE$`2VCTw*(zcz{R{xZ3X1Y<1 zuhV_?8T*{n8K4xcv;}>;fNy)Kkqow%Z}|#$r8kffpRs+q6Ob`qrL8d{wcbnXfwd(G z?RTs>$_UNbZOwMl1&P1d*P{N%TcP%S$qc%ZLrbqfYs*7G&X+D#s$kI$KlhLTn%JL% zcizmL3_iEtj9nh2bwUg2DNJ(&%1Z~M-`S@NurzwJ1rP9wwuX?&_}^>%Re{FP3UOCO zD&Spc_1yIB0>uZz0rh>a1qMqX(6y~7uW4yAW7&G@k)C&#$8~sS{HrB6tRW>z_s!EJ zV@!!fG5#e{j9{N60{llXycigwmh$bXd}Gyk`Zj?wfE_s6I4{<)o?1TjD!dz4ji^Gm zn}$rz&OZXDat$^DW7QxrMc5Lzx$tfV12#&3ksm#|oJ7bn=^LEvF#Ej!q1;Q5g#u)D z76|LOq+Lt?QgN=XF9RQnMi#CV)pxD6KRH(hEE*qklwsFnq}_tWNflsEc9;z01Wb$H zVwoA8N)xZe_zfULeHp^e?8{P-puhnj`A%?(b}QvlRVD%JYNseRRd-VHl=Zxx<~hB* zOkUZ*rgi44v`(*{x6jMVFhzE)T>s=-v%E|)US4LSe(UlwfYZv$zz&tn%7@C!B-lB; zA(ofX?sWg{gRK=mj83_@_Yt?NE56W%FSOwW4*PbsR5}JBUW;p_!*;_peNa?_5DOv5 z|4ZJxM_YDPb^iNtp7)${Yu|b#H>rZ`bGp%rc$-{*^jl?nrpu2TyrTyhxpS6KlZg(e)|WnUA+FDxBc0j&(RVK zumR+mB+rUEI@_hP62M5r1$MxRIV|8g7gVrFG!hav1U#6vAZP0YW&86Z!*<~?6vqSk z%%M-;JCq-w6J6msz5=+lltSooJiuQkmQL3iF>+F_)t$CjXcia`gg>*$qB>sIVrDA2 zQIbXtp?>f;BrgB z^y6%e_RuuKxdGK$1dD>|W?NATN(xj>58v; zy_3(C_WHE7dJ%Z~;OvsH2JL}+D`ghYGt-N>qdm%rN=lIQ zQg9-nn2_wT9n?AYUy}a^bh_=~-m=c0zkM>t^julY1Eo)V{#xM@PyPPj7kCI)%`&Gv zGphnEv^-mUlm#jF$d?j5a{FMp_>x-5mX6V>#QL&$V|v}8@euI-nm3q$RNVS;V8kg} zORsqS$5T~^kEBP`*Wuwb74T+8!%jSm8ez9cMB6;uipT@6h67{I?0PAndZ| z<#W%YKhdQJRn#N_w#Bbr%LgHIzV)7jb!^46QLoUMfK_@({ujW}t$-ob4-=aXNT;T> zQUO4h;D7KFKt=Jn9e8Sp$mGLY0TEBJp#_~9E)%#JZ3myVx=_(@yqnPEFG{HsL+AWT z9O2-AY*ysPk2~vX759F%Rs1M-V6SjL6cDqQWkwc%`jxtvrbm{L#|S=sgO<>L{2+|kEibPuHat6&p*1LIYhrAGFzuOTJCZ?Tlopgl*)*X;ZYuq3T+Lsa3krv)5PJB1f z(h8Xd%H!bXvOP}=copOxmNkVqVG@>=gYDzOX+VyH9$H<82oo^`B$+Q87i}J3A6D7q z1SGvwu6l(!bgVNrt9%;6*D>;P_C$D~q+*!>Wk}Aier~t16M*(#!&ZW{GT-_D;Gk9eiK_yKL2T_)}f#g={EzWx)mG%FCfuD?)XUDx( z^|h`A+lL-0MHViT%Hk&ctpz6^4FDy*-c zsQgw!{00p!vF6y*7yc=?qXwh4Ulh+a{+s&IxW4A8KdgVt*Ze$=2#wHwT$#o_e1#)j zBERJGw#I_8ci|GArq!2NsL;G5zc8^9g2 zirAXv%B5nkoOk3PZet+#iZ|U$j&kXFg;Q;jUq#|TugO@aJ)?q9;3L=hSBstK9h+5*Z@zXQ2R7fPTw z4ShEbGb2uUrSuk_DFOj3))Ntlkc~`Bif#vF8l!(Ry+SDr@aj!wy^Raa7;(Fx@&Z5q zjvd8iHi_^OBX$&~V)y=0Pcn<4Ya4ep)Cpdwm{#bX>9}Er7(~KT13qg`%rHE*Y&ZF7 zy(SUTTiv2_Ph6s*zhPI)$JM z+Y$r@1WsJCT~BFjhD`Q2r-xq#wjp5#uSsKz2M`-+;r9dmF@X~BLd*pp3(`ry1dE-@ z!JxxD;EERmjzGS#xXJ5Vut-%#N;i8w)a8xK4yqFRn#i;7!50>x$*N+}aAS)C60 zA2yd%F}x z3(ne5Z1b)5n4;KG~iDW0ZX7M-7Hk*UUepcUL2 zbeGPgj}pQ~`?6l=D)tIa2}FE;9D%LUn?9{R0;-trtkYX~Xyk^HFcbWiIlnlNds=WI*7#)&j|)-Xi)8!2I%|- z3{d(=#t631-=ryli)wE#xi8qkQwOS=y-4#+e_gz`7UNg35!c`l|HMDD-9vK1hJWMYhiU5*K3WY6(y`p{6!T_9rS1xd@4 zsM&9Gp*MEY{a8WwLwx|koLX;sfY87Lx&R3W*~5z z654oM<;r0m1(#uF98K$5aCX~lE2vUrVk){%)?W)hiCAL{Zunb3WXWDE%)jKpRX%!X zU{@cnuceAChmZFa-dFZ@&EBdfSOIk(87f5v@Wzw(xZ6B20PU*j{z_GK4}#aa#EB9@1Qe^H9G;~&xxbTU0{BHyJ;i4KpK;toei z@)IuUnAOP|OOvGvOsz~Fyk*p{V!xG3$uLrwF=0CZ?dVw35%MXF70M>SDzr%*ZRiJd zgaj>LgaMk1G!5i5^{#1&>~JMQLQQt`q|KpH%}VsNZH);^$u0$S;F1xKzI13nG}zWz zG)yguY2Q!DWzjCt!4$X(Ja72ie~@y@Inn|CP8zL2-&9d|;^Gm{`vSj6C&w9|eT(gw z_#n)E8wxenBmQ#@R!58X#(8f*2%7H*T;;dk___Z;;hpkZ<`(N3jF|072xaPm-T{|l zKEf1+k8@Uj+?3>=?(LYQFC?ypVat9v9{t2}l-jJDkSWF+;~~t)-xqE#yHs}Q#?>7n zbUNK3zwiV*gh5V+I&`SORMv^Ldg`7Tn3&^M@t?d`!XYYT1E$p9=K}Z!^9UCjy<++T zm^f>KsnFsK^SJJqv;cq)&q2haJD{9YAZh_3{t84)BLEK5o5y4uOCIi!8%zAZUyPTI zqYSj^2tSRFrA;d#t=!wjHz9zAdmEF$dJ_aRpYdHF!QLk;pp~x(<(?#<ytBzMKx)K}W5}0Ru zdM6PDdt%ykic^q91TBvP*va4{beo0&49**fTE%#|AdAgxNK-*N25!@aP6oGWLsQ^( zZAi5C&j4!COyWkVdNLhNuppUyQfq5R8}jzYO>ciSj}}ZI1ecxB)@8?Mbzj?0G&0ey z`|2o|_Z1~=SA;}lsQB7%oQv)c+I%_6ZUTLwT4T==uy7}1lC3ov^BC7^Z}7`~Rm&*< zXl39^QmqUuY_lb4rEm;+yi4(I%s&Wk6WgNnI#Rd3P8cTmfFf}wt0nN&{nV{&c{kn5 zQCd>LV1h_aGN@E#RJj1=5{)gZk?oeCivRvP`i8~?`y|vs`lTocKsAdr4LvJja8U zZ;{VQqfrA3dIGcYMwRNYz~xQx1`J1KXiLlceUi&uLqd+qNNa{SwX(1=2DC36RUm>( z413#VDVWozLIP|kCMFov4U1Tztz;iGK$$w`%ov_lxJtXU1+H;JI|8 zW-u=soiZnb`5H1Zh?3)z_Mx8vj^aoj)JWxVz|=alICDtHQ#c)34W~oPoer|A7Eq1c z>EJ;QHNM*EK#7BCr-Ql1I&w9@Ud%yZZV~zcxt{ELFl9Yy>NbgV8(j`@iJ;rWrRxD~ z4dNC&{6Et5@SagtiJhu~O}J9m0+C;>wKEbWul^&aNd(2nvzoR#-7ZYV06lGz0cb@m zc@phW;lwqbS=9FJx>wq5i`u_k6=K(VIMT!1s~(0&N2;p{=CHXZy_)pdS;N9;Fj&+^ zUDE!c7KbEyi8+GiW>H8>1m_moY` zo=svomV3t+A5m78{)-Nwqr-~n3elxC2cpC|`|q$uWI!T(MKHUOy{Dl`Q8-S2X2>JM z3Sl(kas>3C?i23cMRbyDu@q7)gtfkzcl9a3s~iB<*Ho zmnR7iWcg$UtpwQ*;z=J}o@^=-7B+C+A&axH05Z2oYFwHOHM^;&S8%7DOJ(So4XK|+ z5B;1=P4vx4Bjh_1Op1Y{%jZb|+1hEh+cAIjU&7zC-HLz=X&M$r=Hpt4RrIe^g59PA zMel0utfDp5(>F*W9A148FBuk}y_wbzq)V!^{7`)0ATEG`NABr;)d2T5aS!#8nbz_K zB`G`>Nv{&GV&?d{$$sWDOJEmoo`{LcMF1b1mPWxAm@9`5j#JW0+Pq;fTzQ0G=*n%j zv12dK@Sw18)2ihPa`ww(!4HRDzy?xEiNaTXYpZXTFtX~Zk4SgoRd*apMw6?dBp4k$ z$n)N{JFIIFg930=?(ZI8Br{iY_qhiS;wquicv@_}2GH4H6DEZR=$l4cUIV#^w=}Os z%J2Xmih)4cu3^(M*yQ1ZB*iw`FsRn;;>BA9*p!z^W|04pP~;2;++ZUP$)M=Fn~{Tv zi8)Gba%3?^R4o?;Ogiu&#cH@M6CN3Z*&Y>LEoU>$Orb)YtQM@0or)6LG6hl@n5_`Z z&=aOPq7j)d5;K8o2RuuBCyX5rHOaleJy85Ry>Ld;l&dMX|Z3xPg67 zX?V~>As-n{r-jK}y3Hd$>V07unRLp`CHNoIYWj3>(>cZG=kP2^^MB9N&^k_C=#{lF zXQa@ptZ8X|GS|#HGf!jFtIG5=JdM&z&6SFhYf3NNEUgxwq<9~M3TU8p&Zy&t^lGVJ za_^+XQr(GRGOFZzQZRR#GXtc-nUSKH3n!Hs1>Yc-SDdid@L>Q_xd*w82gBVTFkvc4 zvmK(V%vz~HvZ(3ztjQzOhJHxD@5rOt3;Ml0%m^*UiPKPuJtRQwnsdd2vmer!@$qHa zwu9(NtbLS zQ$(faBf-U6wk)DAGKH;^YHnxHB=<5UD~PjGHbd$6kNwgCB`is=*-S7^uY1EiIcP+B zE4h-9p@PHbN-&_wc)0}F@cum29AY_|U?4LZilHvwg~=YoNy_RqOC1o+JU@69NSkK8 zr)*cU<_dEu?B9q-!Gwd2{7F&GQ!5;7!k%)TO`WQCQ?N2)Qknd(Jh7umJTXu2!NZ`)eg}+cvT~MN3sx< zXc;grGWj;iO3*t(ijb0o6nYBF-W9DQ%Th@xK>9RuN7R;UOuvbHITW4aNX;6?ijObi zV7?uEgq}`3ISsxOb##A1C9a6P!Gq7pU63IT^tnb81WwaE)0GQjHY!>7Ev+s%=+Up>`L0M@$3swGQcVcC8A zv$n;G!Ka2_iBdKEltGF6LhvhE%a0F21XD;-l1oS+OioHt!vBMWTnCjlkfh`w6o#z{ z2(NYn=U_Dy+!F;k2FqfwOf+#Vk;wEXg9*3h`-Z6}J0gwultO-|<3Y6fVGKh^xxi#HN&HkGM}_o1;wF10Z7Gwb)kOLtu0wr>Sg?8HPF`TgO>CwR^_4eY zHB3Yzl07F!eRbKr2E1qnHokz685|7k*bQtB9$@E{G6Rk)o&gsXRR$br-OPaFhiAZn zYh{4lu2}}0$kQ4Ly2jKRGFkr%>suZh%885WNGdK}%|s5cQDrGXqDr#Na;Z;P^hL1O z{Chf*324hlYUb$RQwsCXgEs%bP9;&3dj8824br^J`7g_8go>IN3UO}pKU9~rO28&x z6Tg*w$kh`sgWM*bh?SP8G(!H4C95YMY4xvn;!m-5@JUWQHjyUYQjM}RidJeiL#_jD zCuHGPFZ&;zi4=xd3bXD&UoUYSyqtp;k?!YaT>OnJr;BCpvG&*9YM{W+n&)~!Z!T~b zd+u_xoVfLpCuTW4DXNEzPus0Va9Z*@q}9|^Z^4zPnzGlm%bo=KXo7d!q@Gc{DH%hJ zm9V4I5dve9su))exAj@cKMOqRTDdmF99roUO=_V?L7kpV#**2hZ|DpfvA{AJg`=f* z6kX-7Bw>XGu&9;>b>-R=~|b;xu1 z$QGA-1PbbAWnxE+pvwc6%42FJo%Nyca^BUdTn=JQl$4PFCzC^w*{6$C&$JHG1@EPT zPM(`ex{tbss)$n0ZTIZU%Rgq_F?znnY_Y2nCcFwsnv8=Q(Q4>5CnyFwl#64r4dFr` z#`!7nY~E09G<)x7_!1oQV36N1{xYZ zz^eDlsDYlMN=Z@D4CY8ktG6A(=)}r@1AHUGz&bY%zI}!l*b|wEU8z zOU6?24F-K+10+7s8GJ6$vPJ&z-O$HmRUf0!MFAC1!5En%3y*o)rS%xlokMyRYv1U; z!KQ4+{AZTPr^{pWGBOQK{|POJG(PM)5su8eC%r&{$yDjElNKnLGnp{}BtD40I0xKJ ztF#}5*%-q7c2y>(cjRK~@o>{F=7}I1Ukd|r5NSRhz(=PP;MYP|-Dz-*!gBXt^)cbaL&%ErK zHvH`HB=VGB207r#)Cf`abc|^eC6F{29?Qv!(h_F^2nEe?MeF(P0SdVC(txZ1lE;XD0yE>Z1l_-xwG^^BQ^feZ863q(hxtTif1ZB4( z`MWxUzkX6A?@=#@!oNLQe>Ld4aZ(4!_YP*9uTKAK))A($+dzGgKr+V?a#Bc~-{GDN zCejNcUGqOs3uSNcWvado*4rl`Nr+V}z$$b1f6R7kqJ9ZwJfUc8F5J_Xjh#*!ZtJ`mU^rE=79}rT5aK!Ad?Y@{8|pytO$?yMUOrSjmlbA9>RC)dC|D)? zVc1t-Xpgg^wc{&V&6>5^4M17eE^mej<@4wi&l}-I(Ol9+mxVf<rjg226)ywn@`xFu^HrE$0puxlOWCftY`%jtYlZ^fdR5o)8&SMXH6OWGxkMTlCCR96ZlhlC?3xUA9I#P8G_AR$wb%n z<_QgxTS@Fr-I;WSBAkdKtg4h(Nk^{9G1Erd02hTZ|4vfI@Vg@#=$k`JA7JgJuxCW# zEx9v%TnkmLXLy2;*4Mb`WB%#WC|}z>L_NB$Pjt@)DMaI|n&>uO4>bqLfH#_Kh`=<5 zgc}!_pUtyzN%tm$9iI!2rbZyzGjD3}5YOWe9?&V7kHa!mscIlFpHNUm=fJ@xzH5k` z2>YC$fQ3d-LnA0v=IaND$YsOqKny^?bznPm%b=hmfr$+SL?e7NAIiD2hF_)zQ=kVM zE#x|4kHP2hPlf%Z8%pWx1u`E-io>j{)Lh|4c-DN38-fXjEHUA)G1G;=_bdmY1fgadMVL;qEN+~oU7^_curx-483Kl`bgIXel0Rn*) zK4pTz=hqhfu5zIIryx2$78k#V_MNJ-UaU-38%pJ&ooXM0tsaU{M)*^;-@u<$L%~{P zP#Q=22-$a-uLhB$j(wPmblu z2jM#Kd}=v@lFZ9MY;6)-k>$Y)%_P9{OC_+F90bf(9CF!LSyTirgT}|?L`%3PVMq_9 zYOn+t%Fi|zk&F<9hj1B3gBd}*x14>gH@LZ9ZU<`i@U-5>FXjI6#Tome5=d?3lHQ)o zl4{4NQ~KZu_-V0EkrtIsX15N2ZncJ}q2c&!y{B!TYB`W&LI_{NuX#;O|Lpo~?# zx_v$B-%#;zJ+4l%A&uIVU8yg$)O4qK)Y?+34>en5kWjO|#TYc6b;n?hc_*PweZt1k zDy}=AuK*Y#4-#ZaIeZO>bmyt@GBvP!dLu5(+IUXXmUU991Zt`5xHhw+fup)g7vZox z9??_M4r8tIQ3Q>4S)hFlucTKOH-5RbbP3k13^#_Zf!_b6mi`LV*X8YBqL(JWxhsmd zF_`hkJM&W472wkAi4=AFKw3Ov?>`?$mWu>?S#Rm_Vk>bXnn%P${G!xC`HN8sRYaid zk=I7gZ9Ymp9_7e@1h^L@cQ%O$aa3A%*$+y8$TfD;LjaKQjO`SMX~AVSBdXmKXbo&#cZ zi(fsT;9p=95>>qpQ7Dt!^iTvVITqRr>6*q9@ z?mILqa421P9T#}ZF6EIew4nyrbUTB4!lpVEA58YCCC%-gD~k_COUJUprY2lv8DgsM zUCx2KZS`sZ8BDY@lo%OG{j=i<2a?^}LOoO+(bO)stK$q9dsPn~*FPX}RghKY@J&X<+ceFQ&X#R{OR%__QNVR=9G3|>) z#u8!%P68ajC}Ys_nL%^%I?eFY0ogUoYGl>cP^ZEEH+g8RR#(?1(cz|pIF%q6;ErZ}TmQ`Wv zilj@TRRdkkFMnv87svA~@m#2o-j^ zvW9jELKGasoI$d4d9Nmnw=PWfil}%#vI-NR>@9|}dHh0F=^qW}sMW>0?3^X1oan`f zmW=s-gJ=|gh36iPItI1y*DinpJX+kQcZ!?r;(jjJM;qB4?cxzy;V&<-Nuge;5T&Ug zwwtjpf9`Q=UC<)MGi-$3Jw9#dV>O<@QGt8URYU^hoPiO^W1?$2P?Lm1!B4`Kc{Bu< zIfMw@W0b$dVslp z^%>RB5M8SzC?v$$?g_X(i)Lkn0sS#o6>TUeVzgnBat+!LJ;3Y4(Ky>cc~wWL z1d0&lcnb_ec+@D>2rN*l-rs7fZAE4b$jHpN^b;ksq)BEH|01!|CbOhTW?tiQO)`7p z7;AIiBs0y6PZNw}ApQf6?1sT|fL5fT#M$@dk?gm>;7F~V1LRF8-ela5ffqO0 znO+#`pWf1bF2W)i4&14@&q{7;M`K!O;|>$_cy13J6I(`nuM*^>sF@)5m9lzrW*te6 z2u}A2fSFV+1SF^6y-V@|9gtway8_1L$s{r`D)&gT{Hc=U$T3NBgb9+Ipp{Q{`L9O4 z)ygU2f!nPB^MqPIvw(pcuoV-QORRi(l0cRzs4o~7aA=h1HI9K5p+bFAN~I=0p9x$* zFcg$H8cGG8GsP6RH!nDs49HN7i{xHQ&Xg!76G8*YkV#B6!;_$90s;r2g&?STS30Te zi&9W)o7z%PYopszP{+nWY$6S}AD4sZQ4`eBDnUIhG#Y~1#eKy=rk{JFNh%DMwRZw% z&?Ag)_kx4imSP>L)bKEVGdci!kv^XlvDXR0lseASJy=D!fsS7%1w+5ay+ztQwm9>u zYX@?u=kf9DctZPX^?n)+n8@_vcfa%4W8I$-=xagQxpl&F4NoSGqA?R+95b>6(R5}M z0$mpOJV1OI&*P#B`AR$a_soz!5FeX#uBFt9$l2|Sd;QVj<*)`e^}3cG*n%>9LeNJM zD{d>lsde>iRB}HERVzyR4G4%KYqD;#9_5h|PC55JO(g?`2jAa#kaK@f5}B-VgH+zR zwfSWwlk4*s?De-{a?HbCV8Nkh8>ZP6tlwXlzzMw$3Qw7P#hfOF_&dO45MO&+aTxN; z?F4?yG+}&NsgI(Cem0H}+MiDJ+9-vxj3|Mc82K z%9s!q!yNW9#4Nbe1T$ts-4+O}&rt<}h!NqS)j)U9SB2%9gF3xHAe9K$o6}Js}7*&O4cH4Uxh7K*R@67wEm_kH|ou=T1%2h}Q z|1%9a1j#<40OCiYJ!4fORUBDD*R95o)f3mCI13t7!VDro^pXnT+dx{zI~l!!N1ya= z$<}cVD&cGRKV<^*NrqmrKp<8tQUB+%z%hF_h$Pt~T?oI`CY}rt)MkOwlu49WP4_&A z;dsPt-UC~p4S@_)(R+hm3NB~O9Xkx`uxH}Je(dvumIm`G=f^c%)&z$6iTyv;LK?}0X8JiF4BilzRwh!NS>>U_+5bo7CER6gFjIxQ z6!bp6IDcr;3l)BgE?Pd(_q=y2EA;ZBAC6EsK?+FReww`wS7}yvkT&TWzN!0V}e?2m+k|-?mr@Rzn! zWDXh?ICxre)6E}`k?A253NVVdR-FT;) zsqcm}f^}M>+$PEgIbE12^@76{K!wFKp86!paF+1)6Lkp>eH3_^pU7+K@DA1l9pu>c6^sgiffQ_qmQ$^Kq)6FHT<$&b zt%7LFAes}6d4Xt0NHGsmOwOhB;TG69dUf$&Wbz`POQLqs)q-{&S7Aq@Q@3g>>*7AF zoE^rm_;K$PCR|S6&!KguyT6#fYB7KH_-UFz{%$f3+{rgzss?}DgOFhGOK60{<$S!8 z@8HMByaT)DFy30^xX`JEYZw`4jcQz4~WAqbXh+N_oKM^DV&RT%;MG z(d{ui5>uN}kB_&};GU)N(>YwUG~Ujz&*JaMBkf&im*fyhI6Ekni(hP`e2fW16lzq0 zJNCul@eKV?5P~uAO?|hYZ##Bq%!oZ;@=P!z*>IVqn>vYJpuHP-@#iM2(X>Ksnl5AtC_%7NAqQznZcj#I z&5%7t%vebpy1C5O2KKE1nRXJ@3o6N?BCnHjcU&MIA5_z=k)fN zS)bLc_rt7n@%_3uSek6rv~SC|meW2gr~O=?=55=R&&P%iw!`&pq^p3Wf)b_h;Biti zX?TWkZSjarRv7hUmf&$W-=s;Xrp-V%%e-~Nyzw%`NOP$4bm~evNsH&eQn_UIj<+A< z8!|z~zwh+HiZ?J-Htkm&_sWS}v>NgRHzo*q>l^yPE0ki`A6T<_pU2SY^ zH6C!|s+#=iEf<7x3(3pH1UQ0t{ClVE{rgV- zEtm-Y3JJyAH6h%8lik09{%PlW1C3ttr~&ui72|M;OebGRXhzk{yx$QMBacZnBf-Gf z$`xpF-e)Icb}$!E?S;%!a|(X>g5Roz$lkFR=zr+UG1mO*eN(89+4L1%_1-*Wu8}Ee zOxgq11-#@7l>JTOgud|zYjqB*04o(;|Nbk;N}4JjwG$!^H@_tY8C%7X7W?xRfAB#m zLu@fh-aL*e*|JAgj?Cnd5?twh1Xn8VyWSRiDZ3UvVCCB)ws$mO9s_Pjvoquv-qLJp zOT+Hn(4HJyn)WOc`E%wzKU009M2giI_>+!Xt*FsR;d>%ep~3I8NLMS(58XMXH1m+z zizg|ymgYXK)P_sbDwyHYT1qWNq)cBamGFJb<=I6`JRgP+!p*Dr(QJ0~F{g@iQA z5+O=xvB*N6R_S#?*OJ-=bvyg!6U_QPSC&P4;>UUvihKjfwOldMx5qBF>(ku9nY)p# z8Zz`zllvPC;o|l9!DVg&GgeVK>_9?B>>6H;eSVpUTU6|f!8&qTpy@!c5@<$Lmz`0> zHN|~R&JmT;tmGh3466{&umaHH8SL3<#jWXBo8@)2&D=|QSKyL^*^r#+$c zBtUN~$!$mrZTXD4@)@x(MqY@F!;EH*Unm~w)i_hx|Bi3Z8)gmlJrdI8o8qDZ51_kD z0$rrEIV%p|tAFR;`;H$;wKl*DRC>RNK_TI^8ov0db$^d+kTy1m-q1f-oY%hh;>iBH z@3}|wO^qM#$llmTk4GUUPD_dOi(mhx-#_}TyKZ|9r~XD1{rq+c)T1ktY&$?BMj}uQ z0?~|slxk%bz(w9&1PW<}c)E0;ocPtUI0*RCKiBeQDG+@fo3w^lAncYYCxz*Y)*#xV zfyO|gfe9X_D%$p2heF35dakD}lB$MyrrbU~!>h}8CuU~TVOj7!EO==F1Gn&dSorVd zcQrb07zdQS?WR2CSkwx?&CbtuYhyVp%rdXZoAj*Bynht1KuZiJ4->^;_5-7!ZVn7Y znEvI=`gEJI#|y9$0g0%i48E#A?rXr^c>vW0@XY_g#UHc(9(?ZG^WpcWy?3CWE0=Q| z(E`tr)!KL&0{5lNWZ;flt8U~oXu-bBOnZa@nTv0Ji~fuEy`5g$mC5Ms`RL*ww*USD zY?(d!j=a6&lz^nNDA4l1vJv{>EgnSwER1ZizMFsojSEC>y1`qaztNePUzfXL# zQbq`qTPLh8ZtTRR*tKX)t0txQGOgJzzaScux$3SnE2}_ythvrulVkK2XBP}^g&cqm zigTgrK>9>0`z3R=DIvptdnw*z-903UDA?EKDZr^)FV~f3lzZN9BC&7gGi!Axy`m*+ z6IKdpLIyTLP<&w}PgUV4VFQbUvi6dFi}Nsj+mZ05_p+azhL>tF&Q=}7?bAiusN}?Z zKK^XEuv4UmTm)*(w$P~B14Pj8)%u#e0ZcEWhszGRj1Oa!qD7!wzgH$d@ge*Zfv9Sc)Z zk6CDUL4-I9n8NY|q+`k|PIHl@1*oFc2hN-glld5ddENE(Nesu8|$>JaWfl^uosSr7u2 z85M8)Ky6PE1r&>e|HMwJOHf=Mi|n8zNLFvG5=CTuPnREQ5wj>)-$~dvL15@Zel~>LfGpD!Ir*EoHUss*#xg+o-<^Qbch*B?4 z5wXgbt8W)XKRxM-S;19aeG}|df3iDcWhx(q%rH<%=TRaL4VV+`!sIHxOF*i4^G9h= zPNeKsUk1wPZj$>X&aT3vnX`wJ6=zo?seDKU)%V265H&~3HhNP9~)z<(x_i_Y_bLtlol_uJOM34|SVrswi*ZjM^RDP}Ce=TF1DF7St4^FN31u@K>w*{`P zZ=ufv7u1h0b_O51xVfcZrC~QTZ)w{%YGLZm2&FSe>6|sHK?msime#W{rYItaW1clT zv)ave))RZz}*dT+dg(96!NlJJ|WGDuFIf62q>d#l#3ZW!V5uJA^<7BiVU4eztPfWn%|7x ztcS5KO|w!nQym{~##x~X2D|9wW_)S%s|#6fhSd0AoYGM)#rbAgDYgmy?XUDb5C-US z(pe4F`(>&Po`jHeLu5`}_GOPW{ScOX@rvg%x`$Fc_w>0C;iFgzh7Lg@RB71;ne9B-(XDd?i!1tdojS$Y?)RJ;dhH1&Ml7JEq?UU$w-jHymL1P zNe|yhB^vD#Aousw#-v}pXx4#$RT%OJU+)zwt?<=Ktu7)aORsJp(;`hjnohc-?-xlw zLqA_ftA5eEi_)N{9`nh4-st?{GZYnYzSJbzff22S@{LtpF%PBwQLZ-@94ri&tl2rxD124X zz+R4ya*z7asu9VzVEl5pAQ$Sud>mDV9-ray z9c<)D3Aslj*sadwOlA#H&9p$&z#fO+#~bnk7d-us1T1!FZu?F?%VzW%{TUrK32@gX zc^}`1KZuIepRtZ zqzkh%hJAcO-O5)@&H@MLB=RLOP0+#b$s)+lQbsH)J2eBDl~Uf`_~@ zJXc-mTFz0X7l8fT^F~k0x1w7zbfMk2yBLkL1XMKikp>6DS9G(_6WOh1P|eA(7>%U4 z$%dF2o=p-_KqJ}+s4L%1*+}tyG_e{j0h{)pqU}L(!WkPJ4cgB8umCX%jgm7HO2!xQ zymE6ql9m`}@99oP_Qo7NGo(~ZW27+MHt8dqpl}zH`6l(NUrd%~JFzOQ#2{&(0&e_{ zV*ZN^-aLhM=ulI-Ayu_dSM(g^9$_dbQBKb&QzWwhd~=IlO1j&OC}Wd4oexxY4WAGg zpt6pPfg4_s$VWr)$ewf$m)$m9h-4tqO}rK`HMNIGncI|a6L74UnVgruUNHf6k15ui z?9}GNTWt-D-$`$wUOwID00c&);Iqi}f^;Et;|r79Q5q$pZcAaXrdAbyjrX8e+y>V; zg3#K@eKdxZ*2E>)(;5@uQ}CPLG*-*uRFm*_zrEfpyu)v=Hx2Lf+w0B4Z%sG8dLsU7 zv+*@&;#Pm+v(AidKE!PUBYv0Pb^XrSZQ#XH@x;u3+n*@qOh4Q%<;?H+?QdE0I4;BO zzY1^vuHP;t#UR`+CB-qn{e|%MFx>uNc>B2B28~9>%PKiA6x!rcz1HCRLV^Xuns=X! zYhVooE~x-7GvjRF9A2C#@0$%K<|z+2Xv1d~z!=mOdvQu-8A@x?UB@0!xUV!({v3v& z^KA;<&J}NQY0W{l6S=ZbV$3R8bnQYgb2s3QH~tsp18?&O9?%1hI{tv>&ssR@ z5B#GZ@Cu#&fCRlg@SFa?-&qIxp#x$vcK7Xemv=2-rfQCZvGQ1F))M7nxBcR~0B*OK zF69y+h>Tp`JqeL%S-adP-_b*#=_>g;#d9}iXP}7iY|#Rrd>^lGrvLc z8oynVY!Yrea~l+|_1m8dSeu61AFyu>ir4w=66agtw&VPuc)j0#FudIkw>8~L+S1Q=Zd6q=jr1!uMCh#?cwUdKm%*ucY8q*)cQ#W0G8CfRnj`xd(QA6aX_^{`djo za36d?Uw5+}bpD`NC$j&9RIS&3LQL~SP_=5d4Mor&%>veBKxdk+B;R-><da#sNObX3bqLpTuw$SW{!qfPB7IF$;p(?TbIO+62l0)cwjAEvdLVR?ovaG<{ zhc!Jmfd6Js$v31cWJh zjZ_P6+l#aEhYidJhgGc?d1}@BnJ~1{i=;69RmIzA(nZZIY=G&N5uvpIp3?h|rh2jX zEgA4fMXLfYN@fdu#+ik%TLv5Y%KztTPbu3n?PuWHistNuUiMBS1rfLxA0{pZ&VDo3KU*PD8Hz?ODj#pg2C_j_Uc}n6(urkfUksTY1 zw>%*T#?J|}-73HcFo)9$bCl3wm?H~SCg|hig+S@}Q~@16OeBt%F}ccptrj~j zj^7v2Wp3}%ZY(T5Tn`YrXqo~;Z@eru0IMOD!$*UCPk-sz^e9>z3gVyK? zYt+#a!xFT)XZo?fxL!cG#~zbbs}E`+LuG~9S{knAxCJ6Pn*g8eAk~*~BnCyqtc*!5 zNbBW1`zjt+^Q#UiFQ^#tJO`>Q3it*b$(hA_<>s@+s;t2wt3_`!(vZ6+*x|{NuZ5Q( zF!>Ts@EkL0Rofi`c>Zpar@}^G-1{1x-Db0DRk18|tEJ>x5Xwa8LrefeiU@(1I8q!X zmjob;?IGX$F&teTJ4}Mq9BcTYhKV?V{R2oLY0y{U56J;tugPyp4S`bL-A7a z#hb%GZy#Kk+%JIr{q08w&oxTsw7^ij5Z?R#oe!`@$8x7lB%^d z&KA0G*$Nk$Y&k)s5SLmWDP;Faqs|jR@R?YlTp7#F1vf?<^HpQW(-RG01g@vBYmL#r zPDuS-nj5g6g)TPDMS;DMU!k)|LeHxymiE{*v&d zAQOaW;0hkMmVTb!wDZyuV9HBr(1l(+Gb5FlWT@+nk^GLD{(t4Oba6k=z8kghG9MyX z*&O1&<;NM}MLccoAP_Xd-Q@_${&>m;2uT+I@aJe6MJxNQZXo+4dnl0oRug$X%Sf8T zVL*Re=F$(rhsl&e+W@9{F{Z6n;u8>wHK<2Y9xW#Ra z|FQuqi%l9b6M zCmnqm%z*q7D@8k;0L6V`&Bf=wNUK6&w0q$bH-@+i$h|2r*MYS}Nqi9fP;~>S5HBO3 ztRs}{^GCF-K`-;(5=&@@TEITuT(soB(nhv=ie=18csg3k(n%s|M*8DX6jsBTElTz8 zOD9{<%%Xgxb(sqK$&Vq;lx}i~H==w_ilJ{=Gdm=#3_O-FzZBt(Su&BR7ryVAZhYKS z*nyBN<35f(dqTo*srb;Z$i)P9n(Rrb*NJ!(s#A6w>ri6Ig1V5P$B^X`s(O{EJL*@Y z9AC^TkuS}J3*mv2F%p*dO9*0~?` z5y5c0M~(i3G15l7c=Lz9{kso-?yh%z1g(3)-!xcQNil2aV^Q%TrA&W-pp*Q#1`PHF zSq%t-!Z=#vdt{~w!w@u4h8IKf?7bu9YKt;R^n8L){L+KK(h?~kTxu&VM&x>O#O+bnA*@M znkph-g@s)Xj-uZwnUmx0aNHA)7lq^AaJ)DihYlVlgIsL^0=f%)nereZ$xPb z(O7r7x%z;>W9_l&tYf7$Rv+YvRn!%DhL#MgJY3G$=DqUM zUG)RI>(f2;snv({XZO}u_lY(8RV2Kh*ND;_$A;XGQ{y<%E$g=hegcmRL=B?v1^9C@ zo*B+@DK?Sgv}ctp(=*y0QlO-<7!ym0~M?g6!$cbk~=kqQyKr-hmKB zP_k*q;$2#QYRgXCV|R%s))>JgiAtB1uGKTj6<@GR)~#T}0V_ zny*9Dd%hG=uV}mOx(5y`W{Oo$*HVa_k_n021S>a zQ9L=7X=>$Xc@45-q027=8sT>KdW`m+4Na(tvQJc0tCQ-tmv>e=iaB|QsMUj3~yyLBRe}$>qnn#Kz?dHlW zzMDQfzB%T?^@Vm<631hBr+KQ+@dxEplH<+|M z#po50lqg!6QKy4iGVs3GZ%7fx7{IcSTyX{^p4y`@MROWYOQQj|XmPjkfFc1t;;Fhc zU$jXI&>0meFU8QYM0YB5+n#PBVL??Au}Km!Bmq$!#E>-Jh9s=XLA!!N4sk^eaZL_( zZ@<4(kwdC7hmry>!wca~ML7es4A9i+pk>n!uGC0(1^_Zo2p9Io=uuZhlMJ?({i7k4 zmBp>U))XHblA%rUQ8#m1omNMGURdFDuCfB^uGC9FFC^)c|o+7W%7bMAK8Bf8&`XmIkHz|f0~e25hWuV3>Rf3$fFc+pO3N9yOgzC zD@=MwyBLa7o#o5wK9xwS=Gw{x{zP=be%oqxei8jQ4(3`WEHEr*yf?h{!tmDJCqLKB z*EucjhE5`yOHelNvxxuT&hIHJF4q;6Yv=u1*Q&c{At=~GSFocAxlh9hQHd+YJ3LEa z4@`;Q^77A3dHJbd1^GvU_`GIvo+pgm&)5ATj68=DIANjp6+BAK*mE@jP~E#c`^;9_F8@n(lEmfDQyn9;h!zzGPTi;lG*lvslN+Rv5kV*N5a(`!w&*>_w+w}F&l+t=peE2@|_1kv(yvTt`LZK~W;Cn6f3 zwR)HScT|%&&YT^`{>X~Y)yG+VinraojDdzv9En7Rwr&=}s!c;51p@G!P z_rcNVAlFN8Ys4xZCrAFeT#_< zIwenxUEl4f#;ry{n&Niwp67_tEm4PoU>p!L15j&<#vm|1i;3`7kCaUj_5suSD%aW0 z`}(}zW$N{9TZm{4c0*fa4659}etKJ-sx4F>Zt)#;z!E&RhnK8_gIqsXcYvKntpnCa zWuCIvPTvHlb@J^eqGvN=Yr3l;pKYLR6UipA_zb}>2x-zjMmT5l&oYwD zdGA`Qha_<8g*MoCjIoFrIvI-P?w+(~ zlZ548`Y{}zr7TLVI~61h;8b0vhV{ttT|66<7f-hAvONU>mUgXWj2dBy4Y}V(4L2cl zG|-yYnpcjuNLn_2pQkT3elz>+@g_@llio(`wJ#}QdK*XN?-^5@>p`B5SRGO>j(FQ1 zC=2F^Sft?N3}SHx2`5`eXI3mB^|+q&XU^;Z#+-}NU`r6iHprx8SK18prW6;r!w)Jh z@((uc`^ex``9+%S@g4$&!Z%u(3HmHVmO?Ec6UDucXA6^zc(&LB z?W!R`olTngn1mar`Yxy0w|j_MyP@~3Mm5_VTgo6a1HUa&=``))(1G#UMbG7nJ~=9S z%X*Lc!AqPnERCId;`LPvzT4IE!TKqfLU`A_6M8BX_B$K;A{@>dLI0@-iidDgU}vvus~evRi1rMwx%+fX`i zBZ{Xvq24S**Mb`ha5_om?GY7TC`3+Ca<_a@pb&nnH6^gvy=KBYJMt}go^RQXoZph4 zr<0U<#N)sCSot69o=djLcAC8d*$G7RR60wmu_=Y2#`HD{x+GzNM{l}@uT^7B*VsmZ z?vhG_i)2wALi_J9(RNjZ#O)E2{^#H4Oy5ua`-wKi@LjmQu3utx{p^x`Keg}kk_UU0 z6QUnp-7g{b2@YUsUSJh>|3wGBFgVW8NNvYM7fs^qpQK1dA~tJJz}Fi7YCo|*;?ew(XxiALzc zbFUxRvP{ZYwD>!J8U7s3xBYP3^Wt*pxt=sM)aDvPO0Z;)0w^k;x9KMW#VZ(a)uT0T1TZ zvfN0!vPsnj-^txdor1UxnHGrF(I&Z{PaI z^f5#&kQ5M*Fb`D@*FeyrINhm>oeQE1JZhmgJ!+v>s;C8^^JFlgBII$nxE|EyJ6mZ9 z$M~epoVd3=`+a&J6@SXtc7J`1x3} z>|Y7LVYLQSyi>f6?M5IAP4lNeL)NE)D!PJ~L)TE$hdexAbc!}2T$d6ghn2p7Amzjz za~~o_4@T3Az*>NGPWBzKTCm?)KU6BPf^N*!I0jJcMF7>s`IhWxe6D6uKLp0?ZLw$a zpl$MdLBE-U?7K|9*wj#LC@cQv*>EZ%nHP?EO^D1Kk$J{5W?58=K`+(btC3n_iNiia z87|0hYSy3u$)s)WTi%nP4EtmB$-cFd13WBeqonWr03RjPssv|!3n=D0@CeCLv7lvp z@W5oQj`^;42A{Z(pk^OThi?cj5Ty=%nqd>k;S$O?Kbg;V!Wx?Q_iF>& z(o|W{suIv6^xI>77{?vdd*U3~M-eU=%(TBRMcJCLY%1Ny48#{;$ajjq_S`x9g^&|- zb#?J;D=RH?kxIFv6c^J%u!jj6pexNXXqefl{)k`6fk4X?0{OZAK>v-RPP^5$)9_E) z{ISk?Z=LIQnb;xQ`wYgj_)D-NW`}gJ$AOD&4(vlV;=pc0vm99ex`_i0ln#gXpcryc zlu4_201DQ5Jn0n^6&aBsj?H4Wxo#v}CbZYlO3xmW92A#=)n4Lzmd;gBEJSsgBp!^=r1CSI9=iVfo91VXq9i>(Z|uGlNL&UH{Z;5 zr_9@kc^b+ZYBZ&}EasMHdr=g{agwCWGd2E+es?rAI+e$~kvt871m+a2(CpKZWys%)<~f*A! zhIqbF5MhBmrAEv#L8h>~zX6_YDn9RfeJ30`J&IsLQm?h-ZSG=(Sk; zHpR#Vk6xO807se31r}xydw?v(bPP(*1m+)KQuPoq68i-1AaLoP(9++sjUDU3kdA;Sy zoIRxHr=Oc>W!#3~tz`@A!FvlGID_!sQo(!6KQFxJ9M~u*1~edB!gV#=1YZikoO%K% zO`=J&88YRb83N^luPvemSbg8P&8qunh5JH6uv+hqS-}sZk?7!F<*6qMU#6Db~NeAMJ}EuerXPOs~nU(BEp*AFPA=4Q?e}O&wE5sX4M5^|yq+ zZxUd@Z~?}OAFwn7(}qFXaG`xQz|$SzCJHHR%{6B`KrC$>utW4PCPp*hXi(ML?6(NN z!NDgB5$X=D2sri(d<9^ty2MmdssjNfYV#%D&#VzOO#W041?uq2mW0j|F%Bv;;QBXj z==9fYiZ+Q4TgNvsfuIg=xPvwtQgA}0KPXlK(P`x7xNQyR_~`UidZ}3j0X4V{&8o(= z@mU=|reukUJ+mg_eQpt%=3R z(}$fFrCU=5OWLJrdsb1xG(jw!`1yWWkTC@W6Q}>^oB354z(pc_Hh>Y^Q}z@n_UEY3QC}Z}xF*S3<)(InZRzTaG6f zjHW7qL+GNgzWtb5v*hHp37bi?ViYM2uIg|d31~*VHl)TiB3`DnNEyl#g--N!EM^Wb zlEO+h=AyQKw`vT1#bNfFT|{l@D9U4*+Mpf}Jv zq;g|SRKbm=g1ezy|E7W)MuAzv5L(5&YISJl8l$jI!H$v6HuPfCs_LBSy^RV-tO{RuR0SpIk1ej4QwEN>?yU@uz=Y=Ke_Cg@DID7 z5@dYvav2aZ^S#xM+?g}w`H=jI@_gsgWGKiN@)yD$a+KGvi`H?OSpfq? zfqucHIp|B8N}ysVmn)~Jo{`guI9e#2OkI79Pk>?KPS9(NZ5St+?;iURAso$PM;atlVHPuv?KCkX)K{xNUVvh(q;poybKP4?dl&%G1OfCB>Y8 zC$<+9Wp)?Rxm*(>og1eT!rbjH&gLzdO^#uIH!bb9qX%H*>{bU zIsH<~oSe-bWNGYdXv~lpx(q?aXH_WzNE|Py;AT_(yn% z=ULT4xWK(j*;^|giJAy9N#s)cCj0X)3{Tr;vM2}R5odS5AT)xai2)j8M>83~WClx#EC1LB)o4FWT5*g2 zBBXdkJ0I$5Sf;IO6{%SUiZm)uR(lK@hQN)?6vWF%$7Ku{$mKRsAIQJQ;fzdRcyeG1 zQfm9|&~{#eBq8%>yeLYhFAT~!s^l-CMivToc`ANfogP-|i z->C4!+M|ikq-~5uq$qsWFqXC0Dr!K`z;>W!l>{L`Eu!aQbWGN;o>qbiRK&*FE~)7| zej*^%Dk$;xhzf$Uo!hc49tQWSF|^cwB+(^6%u$JE7El}+>w3@e#Q7>Z3g$0ki-C`N zSOZtH5iMGK&=7r6Wp1(!z*Z#XI1&i;9Pet_Brf_}XzAVs^xE^uhNKukjPuZnu2ZNCbt!?%bswFDD;&fEt(nIGFEnM(`4XwTl+>#ttK0TSQC zfq`jp0*=TNXhIMm@8R)Ri|9z<%la;U3G2WD5gvcy?&4vx6G4Fqj{XBQ-S;f19xpJ`fs&;L;0##2ym;rmkACiJ zum0%Uc1i6Gl`Kr$A_hn~09!f$RlD!TSM#>LcIUm8Xh;Y?)V;tKv`4L1@j=J}3(nL! zI0Sp08bGe#FnVVC($xS#rPI)A4XD>}gKo$tPw}2V5PM@qg617aiZO|^PJ`Y;hD@cg z0zoVw36?BEXde*MR$jnYkgx?~*CQN?tz$og5G#<_@jfWN(ktH`+8c!nYkVec;O}n7B9#JBX z1i3PO;7N8rMnVh0=||ZC8lv}myszHVpBzA407_Xd|LO1nhUghS%?C{%2;juEVF^Hz znR)Br2q+Nqb_@eR(!4}(HivWy3=f^+tVee==ZJVQwpAnlsUWfP?u!jYOtY3;RNqeO zPL+w|>YTNfmIZslc;d3BmWg5YglLQZ(H{k*l6bhXn?3Z#Kr&nwh0wh(M2Mo$1FP0z z{UAG7z(8d|v`e!nmqKd0FmSkSIBWs(1-M|f46^Mw%vOs5hubv{+r9lf4dM%jTQv@2 zsb??qH8ZvbHqe++SPv#-1|oB8Nj}nLRI6(z7Y2{8T~oE%Wc3+R$+4ce>P(O`0OBGm zfCDtZglcm)rWz|Gf|Y4oT_-4r?pHRsT-vhcEiT#Xc ziM}h6Pn=b5dAHZG1?0cgt`pK2*pnQyl3hbUPnl9q88gCi*b4&+GanCT{2p0$gF6Uo zO(TI8CHcZ6sV4YDsVb(Xv^vCXTm(y%!ZttY7ODJ)@D-UOko!JB4y8+7Z0wL4v7+LL zDVtq#B_?f>Qv(|gYu6Y}uxj?PKIZ7M9hI`BK$uKf` zhHdGy|DU_J54J433j5B-efQq??tT4k&vei9Ot++SFDOS`BAJg2adjst0vN}3GERaGjfROV0t-a63d;NOmH9go>o}TV|?>YPIv-jF-ukW=sDFt4vGAR}P9^_Y) zZHawQq4#5Ime7NqXZ(lYwhzq^!_ZUXXq75yV8EKV!#qvJ^lgkjamdm-NY<=<9>MnX z4S-(VT<<|#cQ%}b_c4Csx_Kuwb@g)AMc)@D1UKIDIYXQv&tz-3huW`(IT|j4c+-}y z2-o_H+`jgPBDf5Z(4hL0Hj8)j$c@!6vRmoO?SROJZ7zrm>X>0AYS?e%JNWYuTem_$ zDHiJB2^Q7|#`H(SIdTdyT9Azo&oF1OSfvkL0BY3a{A{`U1jCw2|K6+Q%B@Gk%;M&b zXgbYwiEnW4ZDA~7k`b&J5N?0}b$lW&QKm4e3IOLbX;VfQ*c@3_UYFwsU63Rmjl{UI zspCi)p(9gA6RIqD=K^o4bSi7$eG^fjl0yi5m?7Rtvl>j>L=glPH>D^b;$$BK%!<4i z9*H7!j_-+(9T3i%2u7DFr9TGx!n?7MLd3#y;OcX6tL};NbqJiy3YzWfzlEn2$_=HxbParHpggtq=ayFVxrC>&=sFY2Yns-fgNB3|(xF^`zNDml)YG+yd!* zSO)eOcoP~DSS80)U)KKd*3TdquQxsqN>|3(jiwq`4{M89>cN;|HU%f|*nreV#uK|0{BAt;0h3K6haLAbDpxl+^#i7RTw8;nSP zOvNI4(B3sQ!V@dpuSZT4>(hq?3PA^%NG0V)Vk1h_3?c`>g$fkEk-bg6w*%PyCAAyuV2A2ts_8?D5cmTR*^^zwi!vVFZ_nG zFHwF52-PxN$pL!7wupy?7|EfI0l+cS0!0FTi2VV7!O$@rEMXFcZD+at!VE`X(3*us zUJ1T4Tw%_5TbT(-hOE#evmaPn&wjX;*pK`!vmd`6U_V?+?1!!ZkC7b`4paQZ8^A_v zZ$fkNDGz31d`d27al=R zPAMRuzgsRmKw}=e%#?YU9l`D^L$;Z%J}BvC*Db*4vqdvmd|~ULIVmK!Y)&E;*98PG z!a}+&$uhc}nyrjIesz$TZ)Vuer7ftYO^NKHy=pKj2+ldN$-nXcwKrgV#Ib45?*;cUxcG>_WA9 z2Lf-g!FB$22Bo^i3;A5;&-qmhl`&wpG+QIcqz{(ypaMOzoPXbOTE!s}{*kg}E<4PG z-Mt*W|67~+X$jbTH!)LI2#_pSUr=TwsC2&3b zpYz2(pA2=FR7q4nQXMAdb^-Z-F|bY-m<8%ri1kr^C9X!~KHG@~v5hG(sff$UXt%@O zV+6ncb)5}td1$>$8M6bRT5_t+k^{lbuSz^ukifRd>grT^eyGY$E%K~Yxb^+|1J7NQ?_2J_59OOkGo3aR-A zN;+VmPvDpwXOB7ErW7ug2dGqg5p=D^wGy?wThN?V6m>Ifcg z-+#>{FNnz}t2N50ATOK%H#IPU*BzkvA)x*=NJHZDd3Y7R*52`N#j^tFlQTnE^WU!1!0N zn%t_p-}K0k!)5#LT)VlMrNqE}`GPw@7)sDoR~U=!C$^v3{u9qd z0%Dl1IPJa9Rh;y>io87KDy~tCZ49kp7gB?Qd^(E|LTL=&fp%*1-~;OA#K4A0`_bP_ zM`{xwfY=93Pa-__I2&I2`Op8|4;<{zGYqy8Nk5Jb%ETa2 zJ6XiuW403{&oYlc!@PX3#hwNUrd9_Aq6c9k07!o^OaGPcqs-O+26=AFw?v*IhXp>5 z&=8&hRRo$so8Qy^&Toc3v!3qjd;#m?(PZ{nrWEJx1Q)P-nI^q`VA9K+Vy%SYq+?%h z=SgQ17dF+`Y9#3=%`V9^ZYcvDYeRzdW~cp6uEn&}WmsCW%0yInFdzIL)^L(WmsgF^ zO%7j@E&;q-l8Ed$xFnM_x~&7_({FbcMG&}k14p`CeFB3D2*VCLp)3h}R(~O{UW^bB zh-H5YBfKpH%)~hWfqW^YzrX10k13EOFoTiDEUA*G92=6NY|1OzOkFs`>CUEbI$$Oo zu`euz zQJJ8iN!efD!v{GX`0jf6tuG!<`SKXxaR&_-2gmUHa6!j#kaoUk4(C z7q8}TNyZh?ek`Z(!uz^d>rleW9-q5DfbU%9z z7)mxVV^bB99fHUV4uS$Z{H@(7Q3y4eE+uqTbLPtWULos?tO{!VDnudU24=WqeHqX3 zy7Rz>^Jz$s{Z0Zsd=VE@(Cww`9zWj~p+%>J`?Uo|Mg~j>Z?MmVg!DDRZsUwL_y5_X zhbo(Mf#h@%L)%q10<55~Pp>iUp?eLq@Ie2va7+lA1VhVk+wdmD%IjrP0l>D-K+0Bc z&pnY0-pS8VB`YZ(tB2u;j!}X-e__c%Yem#4%Yp+e9T4$Oom)B9kki(C3#zVhEU0_E zbE`pl(8-1}!h=A7C=K+a7WTvt|3$1jW!2}$ci1g51)7{sGD!{90>GaPS^r^z>&?ZG z8s6mK4$SlrcZ)t#CfoS zI_<7 zU-1;w7Fy@{=sn+eT=8^V0GLb;_+V3?&ZG)^2$bl%lz9kImrhiWK>iZ(!X_vDHk(M? zY?7}CKRLzGSL<4R)&XMpWp9bqqW0V2kA|4hS;O{e!mRXI1g&t49J7b7uKr>OS*Zie zhujV~U~HvL+Ij8>Np^np<`?-rJX_xKth87iz~hFr2%Oa}d2#&;o`Q=C#je9lW$#)2 zrP;=6kM|(ZFas2-zQ}Q0YMA_~=4&E$UH9VVm2?ecc%(v#U%v`eUDL)l0+(0$k;&<| zSE#YgIv%C43kPMm)DNo0z1n7YAB~H$Y@BspRFQ)NtlH1~s5>O$l&W9``i6z0RI7=1 zae)Eka@Jee8e~3}w9Yj=Re%{<%4P^Nu89f5&KbMq?lb~fD)sH^5ey<`gp1}J^b;%k z{eWWLF*}Yv%-kV@)7at+0b(z?$CKYNig_2+;EafBU=hvZ0|_a$DVTdtT1XlyBZ5Lo zs1bkJUN@G2fp7_0YK}qVSsA58fe3Et5rD$OvR41`ZiQPJRWv#PXz`RjKpNO*{Eicl z_zF*IzxqcXxTdiXq^D{PK0BV-ma*7UjW)(GXuSBBvXq_g)1Cl?;9HOy72cTOInV_! zd7A6A=UI9j;aNmCB(L8K!U}=qFldc9YMpI#lYUgP5TB|64RG`)45`jgWLk>#sQ9#D z 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 literal 0 HcmV?d00001 From 38120dc648ddb4cc72b53c4acbe2fe927ecfef2e Mon Sep 17 00:00:00 2001 From: susch19 Date: Thu, 29 Sep 2022 22:04:57 +0200 Subject: [PATCH 23/23] Bump version to v0.40.0 * this way we can have smaller build numbers and bigger version numbers until a non beta release which will be v 1.0.0 in the future --- android/app/src/main/AndroidManifest.xml | 2 +- lib/pages/about.dart | 2 +- pubspec.yaml | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 3325051..a357075 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,4 @@ - + diff --git a/lib/pages/about.dart b/lib/pages/about.dart index 31bae0a..0e51b23 100644 --- a/lib/pages/about.dart +++ b/lib/pages/about.dart @@ -71,7 +71,7 @@ class AboutPage extends StatelessWidget { ), ), ListTile( - title: Text("Version 0.30"), + title: Text("Version 0.40.0"), ), Divider(), ListTile( diff --git a/pubspec.yaml b/pubspec.yaml index 768db1c..947e625 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,8 @@ name: nssl description: An app for handling shopping lists +version: 0.40.0+0 + environment: sdk: '>=2.12.0'