From 721dd5e2983a99d186a392c8b23311f51a671a4e Mon Sep 17 00:00:00 2001 From: Dieter Plaetinck Date: Tue, 21 May 2024 14:58:06 +0200 Subject: [PATCH 1/5] fix async gap --- lib/widgets/nutrition/widgets.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index 2da1593d0..9843aa538 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -173,6 +173,9 @@ class _IngredientTypeaheadState extends State { if (widget.barcode!.isNotEmpty) { final result = await Provider.of(context, listen: false) .searchIngredientWithCode(widget.barcode!); + if (!mounted) { + return; + } if (result != null) { showDialog( From abd531be1f55cb8decbd3bd9bf45a4cb218b8a62 Mon Sep 17 00:00:00 2001 From: Dieter Plaetinck Date: Tue, 21 May 2024 15:14:04 +0200 Subject: [PATCH 2/5] bugfix: show error message when scan fails due to the extra Navigator.pop(), we would immediately close the error dialog after opening it, rendering it practically invisible. to handle back button in non-error cases, we now simply accept the null value --- lib/widgets/nutrition/widgets.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index 9843aa538..68be4f9a1 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -75,10 +75,13 @@ class _IngredientTypeaheadState extends State { var _searchEnglish = true; Future readerscan(BuildContext context) async { - String scannedcode; + String? scannedcode; try { scannedcode = await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ScanReader())); + if (scannedcode == null) { + return ''; + } if (scannedcode.compareTo('-1') == 0) { return ''; @@ -164,6 +167,7 @@ class _IngredientTypeaheadState extends State { Widget scanButton() { return IconButton( key: const Key('scan-button'), + icon: const FaIcon(FontAwesomeIcons.barcode), onPressed: () async { try { if (!widget.test!) { @@ -228,15 +232,11 @@ class _IngredientTypeaheadState extends State { } } } catch (e) { - if (context.mounted) { + if (mounted) { showErrorDialog(e, context); - // Need to pop back since reader scan is a widget - // otherwise returns null when back button is pressed - return Navigator.pop(context); } } }, - icon: const FaIcon(FontAwesomeIcons.barcode), ); } } From cb696cc585ae6593dff5a44c14f754bfda9b2203 Mon Sep 17 00:00:00 2001 From: Dieter Plaetinck Date: Tue, 21 May 2024 15:36:27 +0200 Subject: [PATCH 3/5] fix non-final field on immutable class --- lib/widgets/nutrition/widgets.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index 68be4f9a1..f5a5a82b0 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -35,14 +35,11 @@ import 'package:wger/widgets/core/core.dart'; import 'package:wger/widgets/nutrition/helpers.dart'; class ScanReader extends StatelessWidget { - String? scannedr; - @override Widget build(BuildContext context) => Scaffold( body: ReaderWidget( onScan: (result) { - scannedr = result.text; - Navigator.pop(context, scannedr); + Navigator.pop(context, result.text); }, ), ); From d896fab4ad73f52d1c63bb9283d9e260ab833def Mon Sep 17 00:00:00 2001 From: Dieter Plaetinck Date: Tue, 21 May 2024 15:50:26 +0200 Subject: [PATCH 4/5] cleanup --- lib/widgets/nutrition/widgets.dart | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index f5a5a82b0..ddd490c02 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -39,6 +39,13 @@ class ScanReader extends StatelessWidget { Widget build(BuildContext context) => Scaffold( body: ReaderWidget( onScan: (result) { + // notes: + // 1. even if result.isValid, result.error is always non-null (and set to "") + // 2. i've never encountered scan errors to see when they occur, and + // i wouldn't know what to do about them anyway, so we simply return + // result.text in such case (which presumably will be null, or "") + // 3. when user cancels (swipe left / back button) this code is no longer + // run and the caller receives null Navigator.pop(context, result.text); }, ), @@ -72,22 +79,20 @@ class _IngredientTypeaheadState extends State { var _searchEnglish = true; Future readerscan(BuildContext context) async { - String? scannedcode; try { - scannedcode = - await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ScanReader())); - if (scannedcode == null) { + final code = await Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => ScanReader())); + if (code == null) { return ''; } - if (scannedcode.compareTo('-1') == 0) { + if (code.compareTo('-1') == 0) { return ''; } + return code; } on PlatformException { return ''; } - - return scannedcode; } @override From c8dbb8971e6566940b9acf224ea8805d441c37ca Mon Sep 17 00:00:00 2001 From: Dieter Plaetinck Date: Tue, 21 May 2024 15:54:43 +0200 Subject: [PATCH 5/5] fix various lint issues --- lib/widgets/nutrition/widgets.dart | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index ddd490c02..c307bb0e0 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -56,14 +56,11 @@ class IngredientTypeahead extends StatefulWidget { final TextEditingController _ingredientController; final TextEditingController _ingredientIdController; - String? barcode = ''; - - //Code? result; - - late final bool? test; + final String barcode; + final bool? test; final bool showScanner; - IngredientTypeahead( + const IngredientTypeahead( this._ingredientIdController, this._ingredientController, { this.showScanner = true, @@ -77,6 +74,13 @@ class IngredientTypeahead extends StatefulWidget { class _IngredientTypeaheadState extends State { var _searchEnglish = true; + late String barcode; + + @override + void initState() { + super.initState(); + barcode = widget.barcode; // for unit tests + } Future readerscan(BuildContext context) async { try { @@ -173,12 +177,15 @@ class _IngredientTypeaheadState extends State { onPressed: () async { try { if (!widget.test!) { - widget.barcode = await readerscan(context); + barcode = await readerscan(context); } - if (widget.barcode!.isNotEmpty) { + if (barcode.isNotEmpty) { + if (!mounted) { + return; + } final result = await Provider.of(context, listen: false) - .searchIngredientWithCode(widget.barcode!); + .searchIngredientWithCode(barcode); if (!mounted) { return; } @@ -218,7 +225,7 @@ class _IngredientTypeaheadState extends State { key: const Key('notFound-dialog'), title: Text(AppLocalizations.of(context).productNotFound), content: Text( - AppLocalizations.of(context).productNotFoundDescription(widget.barcode!), + AppLocalizations.of(context).productNotFoundDescription(barcode), ), actions: [ TextButton(