From 4afb3ca3199f69145e8862c5361767c96bcc179a Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 7 Sep 2024 00:02:01 +0200 Subject: [PATCH] Make it work with relying the data for 'EnterFoodWidget' onto the InheritedWidget --- android/app/build.gradle | 4 +- android/app/src/main/AndroidManifest.xml | 4 +- .../com/example/calorimeter/MainActivity.kt | 2 +- ios/Runner.xcodeproj/project.pbxproj | 12 +- lib/food_entry/enter_food_widget.dart | 167 +++++++++--------- lib/food_entry/food_entry_widget.dart | 1 + lib/food_scan/food_fact_lookup.dart | 8 +- lib/perdate/perdate_widget.dart | 89 ++++++---- linux/CMakeLists.txt | 2 +- macos/Runner.xcodeproj/project.pbxproj | 6 +- macos/Runner/Configs/AppInfo.xcconfig | 2 +- pubspec.lock | 18 +- pubspec.yaml | 2 + 13 files changed, 181 insertions(+), 136 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 4b88a8a..ab6d58c 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -6,7 +6,7 @@ plugins { } android { - namespace = "com.example.calorimeter" + namespace = "de.swgross.calorimeter" compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion @@ -21,7 +21,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "com.example.calorimeter" + applicationId = "de.swgross.calorimeter" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = flutter.minSdkVersion diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 7671d3a..9807c71 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + + { - String perFoodresult = "dings"; - TextEditingController nameController = TextEditingController(); - TextEditingController massController = TextEditingController(); - TextEditingController kcalPerMassController = TextEditingController(); - Map suggestions = {}; + late TextEditingController nameController; + late TextEditingController massController; + late TextEditingController kcalPerMassController; + late Map suggestions; @override void initState() { + nameController = TextEditingController(); + massController = TextEditingController(); + kcalPerMassController = TextEditingController(); suggestions = FoodStorage.getInstance().getFoodEntryLookupDatabase; + super.initState(); } @override Widget build(BuildContext context) { - var nameWidget = Autocomplete( - optionsViewOpenDirection: OptionsViewOpenDirection.down, - fieldViewBuilder: (context, controller, focusNode, onSubmitted) { - nameController = controller; - return TextFormField( - controller: controller, - focusNode: focusNode, - decoration: const InputDecoration( - label: Text("Name"), + return Consumer( + builder: (context, food, child) { + nameController.text = food.name; + kcalPerMassController.text = food.kcalPer100g; + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + child: RowWidget( + Autocomplete( + optionsViewOpenDirection: OptionsViewOpenDirection.down, + fieldViewBuilder: + (context, controller, focusNode, onSubmitted) { + nameController = controller; + return TextFormField( + controller: controller, + focusNode: focusNode, + decoration: const InputDecoration( + label: Text("Name"), + ), + ); + }, + optionsBuilder: (TextEditingValue textEditingValue) { + if (textEditingValue.text == '') { + return const Iterable.empty(); + } + + return suggestions.keys.where( + (name) { + return name + .toLowerCase() + .contains(textEditingValue.text.toLowerCase()); + }, + ); + }, + onSelected: (selectedFood) { + double kcalPerMassForSelectedFood = + suggestions[selectedFood]!; + context + .read() + .set(selectedFood, kcalPerMassForSelectedFood.toString()); + }), + TextField( + textAlign: TextAlign.end, + decoration: const InputDecoration( + label: Align( + alignment: Alignment.centerRight, child: Text("Menge")), + ), + keyboardType: TextInputType.number, + controller: massController, + onSubmitted: (value) => onSubmitAction(), ), - ); - }, - optionsBuilder: (TextEditingValue textEditingValue) { - if (textEditingValue.text == '') { - return const Iterable.empty(); - } - - return suggestions.keys.where( - (name) { - return name - .toLowerCase() - .contains(textEditingValue.text.toLowerCase()); - }, - ); - }, - onSelected: (selectedFood) { - double kcalPerMassForSelectedFood = suggestions[selectedFood]!; - setState(() { - kcalPerMassController.text = kcalPerMassForSelectedFood.toString(); - }); - }); - - var massWidget = TextField( - textAlign: TextAlign.end, - decoration: const InputDecoration( - label: Align(alignment: Alignment.centerRight, child: Text("Menge")), - ), - keyboardType: TextInputType.number, - controller: massController, - onSubmitted: (value) => onSubmitAction(), - ); - - var kcalPerMassWidget = TextField( - textAlign: TextAlign.end, - decoration: const InputDecoration( - label: - Align(alignment: Alignment.centerRight, child: Text("kcal pro"))), - keyboardType: TextInputType.number, - controller: kcalPerMassController, - onSubmitted: (value) => onSubmitAction(), - ); - - var enterButton = ElevatedButton( - style: ElevatedButton.styleFrom( - padding: EdgeInsets.zero, - ), - onPressed: () => onSubmitAction(), - child: const Icon(Icons.add)); - - return Padding( - padding: const EdgeInsets.only(left: 8.0, right: 4.0), - child: RowWidget( - nameWidget, - massWidget, - kcalPerMassWidget, - Padding( - padding: const EdgeInsets.only(left: 16.0), - child: enterButton, - ), - ), + TextField( + textAlign: TextAlign.end, + decoration: const InputDecoration( + label: Align( + alignment: Alignment.centerRight, + child: Text("kcal pro"))), + keyboardType: TextInputType.number, + controller: kcalPerMassController, + onSubmitted: (value) => onSubmitAction(), + ), + Padding( + padding: const EdgeInsets.only(left: 16.0), + child: ElevatedButton( + style: ElevatedButton.styleFrom( + padding: EdgeInsets.zero, + ), + onPressed: () => onSubmitAction(), + child: const Icon(Icons.add)), + ), + ), + ); + }, ); } @@ -123,14 +133,6 @@ class _EnterFoodWidgetState extends State { ScaffoldMessenger.of(context).showSnackBar(snackbar); return; } - try { - massAsNumber = double.parse(massController.text.replaceAll(",", ".")); - } catch (e) { - var snackbar = const SnackBar(content: Text("Menge muss eine Zahl sein")); - ScaffoldMessenger.of(context).clearSnackBars(); - ScaffoldMessenger.of(context).showSnackBar(snackbar); - return; - } var entry = FoodEntry( name: nameController.text, @@ -138,5 +140,6 @@ class _EnterFoodWidgetState extends State { kcalPerMass: kcalPerMassAsNumber); widget.onAdd(context, entry); + context.read().set("", ""); } } diff --git a/lib/food_entry/food_entry_widget.dart b/lib/food_entry/food_entry_widget.dart index 88e64b8..49760ee 100644 --- a/lib/food_entry/food_entry_widget.dart +++ b/lib/food_entry/food_entry_widget.dart @@ -15,6 +15,7 @@ class FoodEntryWidget extends StatefulWidget { class _FoodEntryWidgetState extends State { late bool showCancelAndDelete; + @override void initState() { showCancelAndDelete = false; diff --git a/lib/food_scan/food_fact_lookup.dart b/lib/food_scan/food_fact_lookup.dart index db4e0b2..8369a55 100644 --- a/lib/food_scan/food_fact_lookup.dart +++ b/lib/food_scan/food_fact_lookup.dart @@ -23,11 +23,13 @@ class FoodFactLookupClient { class FoodFactModel { final String name; + final int kcalPer100g; - FoodFactModel({required this.name}); + FoodFactModel({required this.name, required this.kcalPer100g}); factory FoodFactModel.fromJson(Map json) { - log("key product.product_name: ${json['product']['product_name']}"); - return FoodFactModel(name: json['product']['product_name']); + return FoodFactModel( + name: json['product']['product_name'], + kcalPer100g: json['product']['nutriments']['energy-kcal_100g']); } } diff --git a/lib/perdate/perdate_widget.dart b/lib/perdate/perdate_widget.dart index b5a7d45..7e6cb69 100644 --- a/lib/perdate/perdate_widget.dart +++ b/lib/perdate/perdate_widget.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:barcode_scan2/barcode_scan2.dart'; import 'package:calorimeter/food_scan/food_fact_lookup.dart'; import 'package:calorimeter/utils/app_drawer.dart'; import 'package:calorimeter/food_entry/food_entry_bloc.dart'; @@ -10,9 +11,9 @@ import 'package:calorimeter/utils/rectangular_notch_shape.dart'; import 'package:calorimeter/utils/sum_widget.dart'; import 'package:calorimeter/utils/theme_switcher_button.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; class PerDateWidget extends StatefulWidget { final DateTime date; @@ -48,43 +49,61 @@ class _PerDateWidgetState extends State { if (snapshot.connectionState != ConnectionState.done) { return const Center(child: CircularProgressIndicator()); } else { - return BlocProvider( - create: (context) => FoodEntryBloc( - initialState: FoodEntryState(foodEntries: entries), - storage: storage, - forDate: widget.date), - child: BlocBuilder( - builder: (context, state) { - return Scaffold( - appBar: AppBar( - title: Text(formattedDate), - actions: const [ThemeSwitcherButton()], - ), - body: FoodEntryList(entries: state.foodEntries), - bottomNavigationBar: BottomAppBar( - shape: const RectangularNotchShape(), - color: Theme.of(context).colorScheme.secondary, - child: SumWidget(foodEntries: state.foodEntries)), - drawer: const AppDrawer(), - floatingActionButton: OverflowBar(children: [ - FloatingActionButton( - child: const Icon(Icons.barcode_reader), - onPressed: () async { - String ean = await FlutterBarcodeScanner.scanBarcode( - "#ffffff", "hallo", true, ScanMode.BARCODE); - client.retrieveFoodInfo(ean).then((val) { - log(val.name); - }); - }, + return ChangeNotifierProvider( + create: (context) => ScannedFood(), + child: BlocProvider( + create: (context) => FoodEntryBloc( + initialState: FoodEntryState(foodEntries: entries), + storage: storage, + forDate: widget.date), + child: BlocBuilder( + builder: (context, state) { + return Scaffold( + appBar: AppBar( + title: Text(formattedDate), + actions: const [ThemeSwitcherButton()], ), - const SizedBox(width: 8), - CalendarFloatingButton(date: widget.date), - ]), - floatingActionButtonLocation: - FloatingActionButtonLocation.endDocked); - }), + body: FoodEntryList(entries: state.foodEntries), + bottomNavigationBar: BottomAppBar( + shape: const RectangularNotchShape(), + color: Theme.of(context).colorScheme.secondary, + child: SumWidget(foodEntries: state.foodEntries)), + drawer: const AppDrawer(), + floatingActionButton: OverflowBar(children: [ + FloatingActionButton( + child: const Icon(Icons.barcode_reader), + onPressed: () async { + var scanResult = await BarcodeScanner.scan(); + var food = await client + .retrieveFoodInfo(scanResult.rawContent); + + if (!context.mounted) return; + + context + .read() + .set(food.name, food.kcalPer100g.toString()); + }, + ), + const SizedBox(width: 8), + CalendarFloatingButton(date: widget.date), + ]), + floatingActionButtonLocation: + FloatingActionButtonLocation.endDocked); + }), + ), ); } }); } } + +class ScannedFood extends ChangeNotifier { + String name = ""; + String kcalPer100g = ""; + + void set(String newName, String newKcal) { + name = newName; + kcalPer100g = newKcal; + notifyListeners(); + } +} diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index 4d549fe..ee5e255 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -7,7 +7,7 @@ project(runner LANGUAGES CXX) set(BINARY_NAME "calorimeter") # The unique GTK application identifier for this application. See: # https://wiki.gnome.org/HowDoI/ChooseApplicationID -set(APPLICATION_ID "com.example.calorimeter") +set(APPLICATION_ID "de.swgross.calorimeter") # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index c9e9af8..bdd5955 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -385,7 +385,7 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.calorimeter.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = de.swgross.calorimeter.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/calorimeter.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/calorimeter"; @@ -399,7 +399,7 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.calorimeter.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = de.swgross.calorimeter.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/calorimeter.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/calorimeter"; @@ -413,7 +413,7 @@ CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.example.calorimeter.RunnerTests; + PRODUCT_BUNDLE_IDENTIFIER = de.swgross.calorimeter.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/calorimeter.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/calorimeter"; diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig index 578df72..2fd1f63 100644 --- a/macos/Runner/Configs/AppInfo.xcconfig +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -8,7 +8,7 @@ PRODUCT_NAME = calorimeter // The application's bundle identifier -PRODUCT_BUNDLE_IDENTIFIER = com.example.calorimeter +PRODUCT_BUNDLE_IDENTIFIER = de.swgross.calorimeter // The copyright displayed in application information PRODUCT_COPYRIGHT = Copyright © 2024 com.example. All rights reserved. diff --git a/pubspec.lock b/pubspec.lock index 47aaaf4..127bd0c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + barcode_scan2: + dependency: "direct main" + description: + name: barcode_scan2 + sha256: a2ab566027cd57b2795ea42aa26835dbaa8fe70bcc1aff54942a14d3705dff97 + url: "https://pub.dev" + source: hosted + version: "4.3.3" bloc: dependency: transitive description: @@ -277,8 +285,16 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - provider: + protobuf: dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + provider: + dependency: "direct main" description: name: provider sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c diff --git a/pubspec.yaml b/pubspec.yaml index a891c1f..a7b1cc7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,6 +18,8 @@ dependencies: settings_ui: ^2.0.2 universal_platform: ^1.1.0 uuid: ^4.5.0 + barcode_scan2: ^4.3.3 + provider: ^6.1.2 dev_dependencies: flutter_test: