From 109d3e23de6653752355120b87f3c9b526c0886e Mon Sep 17 00:00:00 2001 From: Marco Date: Fri, 13 Sep 2024 16:49:38 +0200 Subject: [PATCH] Fix bug that left PerDate widget empty when popped to. Previously, when you would navigate to a PerDate widget that already exists on the Navigation stack, a food that is entered will not be visible when popping to the PerDate widget with the same date. This is because the state is not updated (the BLoC exists per PerDate widget, and a change in one widget does not cause firing an event in the previous widget's BLoC). With this fix, we call setState() and update the entries for the widget from storage. --- lib/perdate/perdate_widget.dart | 176 +++++++++++++++++--------------- 1 file changed, 96 insertions(+), 80 deletions(-) diff --git a/lib/perdate/perdate_widget.dart b/lib/perdate/perdate_widget.dart index 2dfd4e8..f649070 100644 --- a/lib/perdate/perdate_widget.dart +++ b/lib/perdate/perdate_widget.dart @@ -41,24 +41,24 @@ class _PerDateWidgetState extends State { @override Widget build(BuildContext context) { return FutureBuilder( - future: entriesFuture, - builder: (context, snapshot) { - return snapshot.connectionState != ConnectionState.done - ? const Center(child: CircularProgressIndicator()) - : MultiProvider( - providers: [ - ChangeNotifierProvider( - create: (context) => EnterFoodController()), - BlocProvider( - create: (context) => FoodEntryBloc( - initialState: FoodEntryState(foodEntries: entries), - storage: storage, - forDate: widget.date, - ), - ) - ], - child: BlocBuilder( - builder: (context, state) { + future: entriesFuture, + builder: (context, snapshot) { + return snapshot.connectionState != ConnectionState.done + ? const Center(child: CircularProgressIndicator()) + : MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (context) => EnterFoodController()), + BlocProvider( + create: (context) => FoodEntryBloc( + initialState: FoodEntryState(foodEntries: entries), + storage: storage, + forDate: widget.date, + ), + ) + ], + child: BlocBuilder( + builder: (context, state) { return Scaffold( appBar: AppBar( title: @@ -71,76 +71,92 @@ class _PerDateWidgetState extends State { color: Theme.of(context).colorScheme.secondary, child: SumWidget(foodEntries: state.foodEntries)), drawer: const AppDrawer(), - floatingActionButton: OverflowBar(children: [ - ScanFoodFloatingButton( - onPressed: () async { - var client = FoodFactLookupClient(); - - var scanResult = await BarcodeScanner.scan(); - - if (scanResult.type == ResultType.Cancelled) { - return; - } - - if (!context.mounted) return; - - if (scanResult.type == ResultType.Error) { - showNewSnackbarWith(context, - "Fehler beim Scannen des Barcodes."); - } - var response = await client - .retrieveFoodInfo(scanResult.rawContent); - - if (!context.mounted) return; - - if (response.status == - FoodFactResponseStatus.barcodeNotFound) { - showNewSnackbarWith(context, - "Barcode konnte nicht gefunden werden."); - return; - } - - if (response.status == - FoodFactResponseStatus - .foodFactServerNotReachable) { - showNewSnackbarWith(context, - "OpenFoodFacts-Server konnte nicht erreicht werden."); - return; - } - - context.read().set( - response.food!.name, - response.food!.kcalPer100g.toString(), - ); - }, - ), - const SizedBox(width: 8), - CalendarFloatingButton( - startFromDate: widget.date, - onDateSelected: (dateSelected) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) { - return PerDateWidget(date: dateSelected); - }, - ), - ); - }, - ), - ]), + floatingActionButton: OverflowBar( + children: [ + ScanFoodFloatingButton(onPressed: () { + _onScanButtonPressed(context); + }), + const SizedBox(width: 8), + CalendarFloatingButton( + startFromDate: widget.date, + onDateSelected: (dateSelected) { + _onDateSelected(dateSelected); + }, + ), + ], + ), floatingActionButtonLocation: FloatingActionButtonLocation.endDocked); - }), - ); - }); + }, + ), + ); + }, + ); } void showNewSnackbarWith(BuildContext context, String text) { var snackbar = ErrorSnackbar(colorScheme: Theme.of(context).colorScheme, text: text); - ScaffoldMessenger.of(context).clearSnackBars(); - ScaffoldMessenger.of(context).showSnackBar(snackbar); + ScaffoldMessenger.of(context) + ..removeCurrentSnackBar() + ..showSnackBar(snackbar); + } + + void _onDateSelected(DateTime date) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) { + return PerDateWidget(date: date); + }, + ), + ).then((val) { + setState( + () { + entriesFuture = storage.getEntriesForDate(widget.date); + entriesFuture.then( + (val) { + entries = val; + }, + ); + }, + ); + }); + } + + void _onScanButtonPressed(BuildContext context) async { + var client = FoodFactLookupClient(); + + var scanResult = await BarcodeScanner.scan(); + + if (scanResult.type == ResultType.Cancelled) { + return; + } + + if (!context.mounted) return; + + if (scanResult.type == ResultType.Error) { + showNewSnackbarWith(context, "Fehler beim Scannen des Barcodes."); + } + var response = await client.retrieveFoodInfo(scanResult.rawContent); + + if (!context.mounted) return; + + if (response.status == FoodFactResponseStatus.barcodeNotFound) { + showNewSnackbarWith(context, "Barcode konnte nicht gefunden werden."); + return; + } + + if (response.status == FoodFactResponseStatus.foodFactServerNotReachable) { + showNewSnackbarWith( + context, "OpenFoodFacts-Server konnte nicht erreicht werden."); + return; + } + + context.read().set( + response.food!.name, + response.food!.kcalPer100g.toString(), + ); } }