diff --git a/lib/widgets/nutrition/widgets.dart b/lib/widgets/nutrition/widgets.dart index 2da1593d0..c307bb0e0 100644 --- a/lib/widgets/nutrition/widgets.dart +++ b/lib/widgets/nutrition/widgets.dart @@ -35,14 +35,18 @@ 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); + // 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); }, ), ); @@ -52,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, @@ -73,21 +74,29 @@ 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 { - String scannedcode; try { - scannedcode = - await Navigator.of(context).push(MaterialPageRoute(builder: (context) => ScanReader())); + 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 @@ -164,15 +173,22 @@ class _IngredientTypeaheadState extends State { Widget scanButton() { return IconButton( key: const Key('scan-button'), + icon: const FaIcon(FontAwesomeIcons.barcode), 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; + } if (result != null) { showDialog( @@ -209,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( @@ -225,15 +241,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), ); } }