From 346c6e30c4931afe54eb0fcc6335fd9e270624d8 Mon Sep 17 00:00:00 2001 From: monsieurtanuki Date: Wed, 15 Nov 2023 11:50:00 +0100 Subject: [PATCH] fix: 1815 - around context.mounted (#4768) * fix: 1815 - around context.mounted The PR is about two related topics: * Removing all the `ignore: use_build_context_synchronously` * Replacing all the `State widget` by `BuildContext context`, now that it's possible in flutter * Update packages/smooth_app/lib/pages/onboarding/permissions_page.dart * format fix --- .../lib/background/background_task.dart | 31 +++++----- .../lib/background/background_task_crop.dart | 9 ++- .../background/background_task_details.dart | 9 ++- .../background_task_full_refresh.dart | 9 ++- .../background_task_hunger_games.dart | 9 ++- .../lib/background/background_task_image.dart | 9 ++- .../background/background_task_offline.dart | 9 ++- .../background/background_task_unselect.dart | 9 ++- .../product_image_carousel_item.dart | 2 +- .../lib/data_models/onboarding_loader.dart | 4 +- .../knowledge_panel_page.dart | 2 +- packages/smooth_app/lib/pages/crop_page.dart | 56 ++++++++++--------- .../lib/pages/hunger_games/congrats.dart | 4 +- .../lib/pages/hunger_games/question_page.dart | 2 +- .../smooth_app/lib/pages/image_crop_page.dart | 39 +++++++------ .../lib/pages/offline_data_page.dart | 4 +- .../onboarding/consent_analytics_page.dart | 9 ++- .../lib/pages/onboarding/next_button.dart | 11 ++-- .../pages/onboarding/permissions_page.dart | 6 +- .../preferences/user_preferences_connect.dart | 4 +- .../user_preferences_dev_mode.dart | 21 ++++--- .../preferences/user_preferences_faq.dart | 4 +- .../preferences/user_preferences_food.dart | 5 +- .../pages/product/add_basic_details_page.dart | 6 +- .../pages/product/add_new_product_page.dart | 2 +- .../pages/product/add_other_details_page.dart | 2 +- .../product/common/product_list_page.dart | 5 +- .../common/product_query_page_helper.dart | 4 +- .../product/common/product_refresher.dart | 17 +++--- .../pages/product/edit_new_packagings.dart | 4 +- .../lib/pages/product/edit_ocr_page.dart | 7 ++- .../lib/pages/product/edit_product_page.dart | 13 ++++- .../lib/pages/product/new_product_page.dart | 2 +- .../pages/product/nutrition_page_loaded.dart | 2 +- .../product/ordered_nutrients_cache.dart | 12 ++-- .../pages/product/product_field_editor.dart | 17 ++++-- .../product/product_image_gallery_view.dart | 4 +- .../product/product_image_local_button.dart | 2 +- .../pages/product/product_image_viewer.dart | 36 +++++++----- .../lib/pages/product/simple_input_page.dart | 2 +- .../product_list_user_dialog_helper.dart | 9 ++- .../lib/pages/scan/search_page.dart | 17 +++--- .../lib/pages/user_management/login_page.dart | 8 ++- .../pages/user_management/sign_up_page.dart | 10 ++-- 44 files changed, 271 insertions(+), 177 deletions(-) diff --git a/packages/smooth_app/lib/background/background_task.dart b/packages/smooth_app/lib/background/background_task.dart index 1e81fd8d777..30378ac07f3 100644 --- a/packages/smooth_app/lib/background/background_task.dart +++ b/packages/smooth_app/lib/background/background_task.dart @@ -111,31 +111,30 @@ abstract class BackgroundTask { @protected Future addToManager( final LocalDatabase localDatabase, { - final State? widget, + final BuildContext? context, final bool showSnackBar = true, }) async { await BackgroundTaskManager.getInstance(localDatabase).add(this); - if (widget == null || !widget.mounted) { + if (context == null || !context.mounted) { return; } if (!showSnackBar) { return; } - if (widget.context.mounted) { - // ignore: use_build_context_synchronously - if (getFloatingMessage(AppLocalizations.of(widget.context)) - case ( - final String message, - final AlignmentGeometry alignment, - )) { - // ignore: use_build_context_synchronously - SmoothFloatingMessage(message: message).show( - widget.context, - duration: SnackBarDuration.medium, - alignment: alignment, - ); - } + if (!context.mounted) { + return; + } + if (getFloatingMessage(AppLocalizations.of(context)) + case ( + final String message, + final AlignmentGeometry alignment, + )) { + SmoothFloatingMessage(message: message).show( + context, + duration: SnackBarDuration.medium, + alignment: alignment, + ); } } diff --git a/packages/smooth_app/lib/background/background_task_crop.dart b/packages/smooth_app/lib/background/background_task_crop.dart index e6e69b43d76..205bea134b7 100644 --- a/packages/smooth_app/lib/background/background_task_crop.dart +++ b/packages/smooth_app/lib/background/background_task_crop.dart @@ -61,9 +61,9 @@ class BackgroundTaskCrop extends BackgroundTaskUpload { required final int y1, required final int x2, required final int y2, - required final State widget, + required final BuildContext context, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, barcode: barcode, @@ -81,7 +81,10 @@ class BackgroundTaskCrop extends BackgroundTaskUpload { x2, y2, ); - await task.addToManager(localDatabase, widget: widget); + if (!context.mounted) { + return; + } + await task.addToManager(localDatabase, context: context); } @override diff --git a/packages/smooth_app/lib/background/background_task_details.dart b/packages/smooth_app/lib/background/background_task_details.dart index e2fa4c9f969..41decc5bc0e 100644 --- a/packages/smooth_app/lib/background/background_task_details.dart +++ b/packages/smooth_app/lib/background/background_task_details.dart @@ -69,11 +69,11 @@ class BackgroundTaskDetails extends BackgroundTaskBarcode { /// Adds the background task about changing a product. static Future addTask( final Product minimalistProduct, { - required final State widget, + required final BuildContext context, required final BackgroundTaskDetailsStamp stamp, final bool showSnackBar = true, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, barcode: minimalistProduct.barcode, @@ -83,9 +83,12 @@ class BackgroundTaskDetails extends BackgroundTaskBarcode { uniqueId, stamp, ); + if (!context.mounted) { + return; + } await task.addToManager( localDatabase, - widget: widget, + context: context, showSnackBar: showSnackBar, ); } diff --git a/packages/smooth_app/lib/background/background_task_full_refresh.dart b/packages/smooth_app/lib/background/background_task_full_refresh.dart index 671864af84f..2daf3d01dcc 100644 --- a/packages/smooth_app/lib/background/background_task_full_refresh.dart +++ b/packages/smooth_app/lib/background/background_task_full_refresh.dart @@ -32,10 +32,10 @@ class BackgroundTaskFullRefresh extends BackgroundTaskPaged { static const OperationType _operationType = OperationType.fullRefresh; static Future addTask({ - required final State widget, + required final BuildContext context, required final int pageSize, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, ); @@ -43,7 +43,10 @@ class BackgroundTaskFullRefresh extends BackgroundTaskPaged { uniqueId, pageSize, ); - await task.addToManager(localDatabase, widget: widget); + if (!context.mounted) { + return; + } + await task.addToManager(localDatabase, context: context); } @override diff --git a/packages/smooth_app/lib/background/background_task_hunger_games.dart b/packages/smooth_app/lib/background/background_task_hunger_games.dart index 070bb72124e..ea4d98d5555 100644 --- a/packages/smooth_app/lib/background/background_task_hunger_games.dart +++ b/packages/smooth_app/lib/background/background_task_hunger_games.dart @@ -50,9 +50,9 @@ class BackgroundTaskHungerGames extends BackgroundTaskBarcode { required final String barcode, required final String insightId, required final InsightAnnotation insightAnnotation, - required final State widget, + required final BuildContext context, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, barcode: barcode, @@ -63,7 +63,10 @@ class BackgroundTaskHungerGames extends BackgroundTaskBarcode { insightAnnotation.value, uniqueId, ); - await task.addToManager(localDatabase, widget: widget); + if (!context.mounted) { + return; + } + await task.addToManager(localDatabase, context: context); } @override diff --git a/packages/smooth_app/lib/background/background_task_image.dart b/packages/smooth_app/lib/background/background_task_image.dart index 5f594e8689f..d3ee6c938ba 100644 --- a/packages/smooth_app/lib/background/background_task_image.dart +++ b/packages/smooth_app/lib/background/background_task_image.dart @@ -71,9 +71,9 @@ class BackgroundTaskImage extends BackgroundTaskUpload { required final int y1, required final int x2, required final int y2, - required final State widget, + required final BuildContext context, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, barcode: barcode, @@ -91,7 +91,10 @@ class BackgroundTaskImage extends BackgroundTaskUpload { x2, y2, ); - await task.addToManager(localDatabase, widget: widget); + if (!context.mounted) { + return; + } + await task.addToManager(localDatabase, context: context); } @override diff --git a/packages/smooth_app/lib/background/background_task_offline.dart b/packages/smooth_app/lib/background/background_task_offline.dart index 683c9c9f476..5537a19fd6b 100644 --- a/packages/smooth_app/lib/background/background_task_offline.dart +++ b/packages/smooth_app/lib/background/background_task_offline.dart @@ -31,11 +31,11 @@ class BackgroundTaskOffline extends BackgroundTaskProgressing { static const OperationType _operationType = OperationType.offline; static Future addTask({ - required final State widget, + required final BuildContext context, required final int pageSize, required final int totalSize, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, totalSize: totalSize, @@ -47,7 +47,10 @@ class BackgroundTaskOffline extends BackgroundTaskProgressing { pageSize, totalSize, ); - await task.addToManager(localDatabase, widget: widget); + if (!context.mounted) { + return; + } + await task.addToManager(localDatabase, context: context); } @override diff --git a/packages/smooth_app/lib/background/background_task_unselect.dart b/packages/smooth_app/lib/background/background_task_unselect.dart index 0c87dd6cc78..8a683013456 100644 --- a/packages/smooth_app/lib/background/background_task_unselect.dart +++ b/packages/smooth_app/lib/background/background_task_unselect.dart @@ -47,10 +47,10 @@ class BackgroundTaskUnselect extends BackgroundTaskBarcode { static Future addTask( final String barcode, { required final ImageField imageField, - required final State widget, + required final BuildContext context, required final OpenFoodFactsLanguage language, }) async { - final LocalDatabase localDatabase = widget.context.read(); + final LocalDatabase localDatabase = context.read(); final String uniqueId = await _operationType.getNewKey( localDatabase, barcode: barcode, @@ -61,7 +61,10 @@ class BackgroundTaskUnselect extends BackgroundTaskBarcode { uniqueId, language, ); - await task.addToManager(localDatabase, widget: widget); + if (!context.mounted) { + return; + } + await task.addToManager(localDatabase, context: context); } @override diff --git a/packages/smooth_app/lib/cards/data_cards/product_image_carousel_item.dart b/packages/smooth_app/lib/cards/data_cards/product_image_carousel_item.dart index 7cce067953e..029b4b8d458 100644 --- a/packages/smooth_app/lib/cards/data_cards/product_image_carousel_item.dart +++ b/packages/smooth_app/lib/cards/data_cards/product_image_carousel_item.dart @@ -43,7 +43,7 @@ class _ProductImageCarouselItemState extends State { if (imageProvider == null) { return ElevatedButton.icon( onPressed: () async => confirmAndUploadNewPicture( - this, + context, barcode: widget.product.barcode!, imageField: widget.productImageData.imageField, language: ProductQuery.getLanguage(), diff --git a/packages/smooth_app/lib/data_models/onboarding_loader.dart b/packages/smooth_app/lib/data_models/onboarding_loader.dart index 282adf9df5a..9ba991956e8 100644 --- a/packages/smooth_app/lib/data_models/onboarding_loader.dart +++ b/packages/smooth_app/lib/data_models/onboarding_loader.dart @@ -30,7 +30,9 @@ class OnboardingLoader { dismissible: false, ); if (downloaded != true) { - //ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(appLocalizations.onboarding_welcome_loading_error), diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart index 1cf95147a66..217a9fd127b 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart @@ -103,7 +103,7 @@ class _KnowledgePanelPageState extends State } await ProductRefresher().fetchAndRefresh( barcode: barcode ?? '', - widget: this, + context: context, ); } catch (e) { //no refreshing during onboarding diff --git a/packages/smooth_app/lib/pages/crop_page.dart b/packages/smooth_app/lib/pages/crop_page.dart index 63a22dc7156..77977549798 100644 --- a/packages/smooth_app/lib/pages/crop_page.dart +++ b/packages/smooth_app/lib/pages/crop_page.dart @@ -339,38 +339,42 @@ class _CropPageState extends State { sequenceNumber, ); final Rect cropRect = _getLocalCropRect(); - await BackgroundTaskImage.addTask( - widget.barcode, - language: widget.language, - imageField: widget.imageField, - fullFile: fullFile, - croppedFile: croppedFile, - rotation: _controller.rotation.degrees, - x1: cropRect.left.ceil(), - y1: cropRect.top.ceil(), - x2: cropRect.right.floor(), - y2: cropRect.bottom.floor(), - widget: this, - ); + if (context.mounted) { + await BackgroundTaskImage.addTask( + widget.barcode, + language: widget.language, + imageField: widget.imageField, + fullFile: fullFile, + croppedFile: croppedFile, + rotation: _controller.rotation.degrees, + x1: cropRect.left.ceil(), + y1: cropRect.top.ceil(), + x2: cropRect.right.floor(), + y2: cropRect.bottom.floor(), + context: context, + ); + } } else { // in this case, it's an existing picture, with crop parameters. // we let the server do everything: better performance, and no privacy // issue here (we're cropping from an allegedly already privacy compliant // picture). final Rect cropRect = _getServerCropRect(); - await BackgroundTaskCrop.addTask( - widget.barcode, - language: widget.language, - imageField: widget.imageField, - imageId: widget.imageId!, - croppedFile: croppedFile, - rotation: _controller.rotation.degrees, - x1: cropRect.left.ceil(), - y1: cropRect.top.ceil(), - x2: cropRect.right.floor(), - y2: cropRect.bottom.floor(), - widget: this, - ); + if (context.mounted) { + await BackgroundTaskCrop.addTask( + widget.barcode, + language: widget.language, + imageField: widget.imageField, + imageId: widget.imageId!, + croppedFile: croppedFile, + rotation: _controller.rotation.degrees, + x1: cropRect.left.ceil(), + y1: cropRect.top.ceil(), + x2: cropRect.right.floor(), + y2: cropRect.bottom.floor(), + context: context, + ); + } } localDatabase.notifyListeners(); if (!mounted) { diff --git a/packages/smooth_app/lib/pages/hunger_games/congrats.dart b/packages/smooth_app/lib/pages/hunger_games/congrats.dart index bfafb205618..5d6ea5e5bfb 100644 --- a/packages/smooth_app/lib/pages/hunger_games/congrats.dart +++ b/packages/smooth_app/lib/pages/hunger_games/congrats.dart @@ -111,7 +111,9 @@ class CongratsWidget extends StatelessWidget { ), ); if (OpenFoodAPIConfiguration.globalUser != null) { - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } LoadingDialog.run( context: context, title: appLocalizations.saving_answer, diff --git a/packages/smooth_app/lib/pages/hunger_games/question_page.dart b/packages/smooth_app/lib/pages/hunger_games/question_page.dart index 28788647866..ab99ceff207 100755 --- a/packages/smooth_app/lib/pages/hunger_games/question_page.dart +++ b/packages/smooth_app/lib/pages/hunger_games/question_page.dart @@ -310,7 +310,7 @@ class _QuestionPageState extends State<_QuestionPage> barcode: barcode, insightId: insightId, insightAnnotation: insightAnnotation, - widget: this, + context: context, ); } diff --git a/packages/smooth_app/lib/pages/image_crop_page.dart b/packages/smooth_app/lib/pages/image_crop_page.dart index 2ed5d1481d6..e97216fcbaa 100644 --- a/packages/smooth_app/lib/pages/image_crop_page.dart +++ b/packages/smooth_app/lib/pages/image_crop_page.dart @@ -22,10 +22,10 @@ import 'package:smooth_app/pages/crop_page.dart'; /// Picks an image file from gallery or camera. Future pickImageFile( - final State widget, { + final BuildContext context, { bool ignorePlatformException = false, }) async { - final UserPictureSource? source = await _getUserPictureSource(widget.context); + final UserPictureSource? source = await _getUserPictureSource(context); if (source == null) { return null; } @@ -228,7 +228,7 @@ class _ImageSourceButton extends StatelessWidget { /// Lets the user pick a picture, crop it, and save it. Future confirmAndUploadNewPicture( - final State widget, { + final BuildContext context, { required final ImageField imageField, required final String barcode, required final OpenFoodFactsLanguage language, @@ -236,13 +236,19 @@ Future confirmAndUploadNewPicture( }) async { XFile? croppedPhoto; try { - croppedPhoto = await pickImageFile(widget); + croppedPhoto = await pickImageFile(context); } on PhotoAccessDenied catch (_) { - final bool? res = await _onGalleryAccessDenied(widget); + if (!context.mounted) { + return null; + } + final bool? res = await _onGalleryAccessDenied(context); if (res == true) { // Let's retry + if (!context.mounted) { + return null; + } croppedPhoto = await pickImageFile( - widget, + context, ignorePlatformException: true, ); } @@ -251,11 +257,11 @@ Future confirmAndUploadNewPicture( if (croppedPhoto == null) { return null; } - if (!widget.mounted) { + if (!context.mounted) { return null; } return Navigator.push( - widget.context, + context, MaterialPageRoute( builder: (BuildContext context) => CropPage( barcode: barcode, @@ -270,9 +276,9 @@ Future confirmAndUploadNewPicture( ); } -Future _onGalleryAccessDenied(State widget) { +Future _onGalleryAccessDenied(final BuildContext context) { return showDialog( - context: widget.context, + context: context, builder: (BuildContext context) { final AppLocalizations appLocalizations = AppLocalizations.of(context); return SmoothSimpleErrorAlertDialog( @@ -283,7 +289,7 @@ Future _onGalleryAccessDenied(State widget) { text: appLocalizations.gallery_source_access_denied_dialog_button, onPressed: () { AppSettings.openAppSettings(callback: () { - if (widget.mounted) { + if (context.mounted) { Navigator.of(context).maybePop(true); } }); @@ -321,11 +327,12 @@ Future downloadImageUrl( ); if (imageFile == null) { - // ignore: use_build_context_synchronously - await LoadingDialog.error( - context: context, - title: appLocalizations.image_download_error, - ); + if (context.mounted) { + await LoadingDialog.error( + context: context, + title: appLocalizations.image_download_error, + ); + } } return imageFile; } diff --git a/packages/smooth_app/lib/pages/offline_data_page.dart b/packages/smooth_app/lib/pages/offline_data_page.dart index 6aa8572c6c6..8ef915aeded 100644 --- a/packages/smooth_app/lib/pages/offline_data_page.dart +++ b/packages/smooth_app/lib/pages/offline_data_page.dart @@ -61,7 +61,7 @@ class _OfflineDataPageState extends State { title: appLocalizations.download_data, subtitle: appLocalizations.download_top_n_products(_topNSize), onTap: () async => BackgroundTaskOffline.addTask( - widget: this, + context: context, pageSize: _pageSize, totalSize: _topNSize, ), @@ -72,7 +72,7 @@ class _OfflineDataPageState extends State { subtitle: appLocalizations.update_local_database_sub, trailing: const Icon(Icons.refresh), onTap: () async => BackgroundTaskFullRefresh.addTask( - widget: this, + context: context, pageSize: _pageSize, ), ), diff --git a/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart b/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart index 30d4dd22ff5..226e9f7a2b3 100644 --- a/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/consent_analytics_page.dart @@ -106,12 +106,17 @@ class ConsentAnalyticsPage extends StatelessWidget { await userPreferences.setUserTracking(accept); themeProvider.finishOnboarding(); - //ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await OnboardingLoader(localDatabase).runAtNextTime( _onboardingPage, context, ); - //ignore: use_build_context_synchronously + + if (!context.mounted) { + return; + } await OnboardingFlowNavigator(userPreferences).navigateToPage( context, _onboardingPage.getNextPage(), diff --git a/packages/smooth_app/lib/pages/onboarding/next_button.dart b/packages/smooth_app/lib/pages/onboarding/next_button.dart index 855996d2ba2..81e48e248dd 100644 --- a/packages/smooth_app/lib/pages/onboarding/next_button.dart +++ b/packages/smooth_app/lib/pages/onboarding/next_button.dart @@ -54,11 +54,12 @@ class NextButton extends StatelessWidget { onPressed: () async { await OnboardingLoader(localDatabase) .runAtNextTime(currentPage, context); - //ignore: use_build_context_synchronously - await navigator.navigateToPage( - context, - currentPage.getNextPage(), - ); + if (context.mounted) { + await navigator.navigateToPage( + context, + currentPage.getNextPage(), + ); + } }, backgroundColor: Colors.black, foregroundColor: Colors.white, diff --git a/packages/smooth_app/lib/pages/onboarding/permissions_page.dart b/packages/smooth_app/lib/pages/onboarding/permissions_page.dart index dbf21daf407..9897ed0e180 100644 --- a/packages/smooth_app/lib/pages/onboarding/permissions_page.dart +++ b/packages/smooth_app/lib/pages/onboarding/permissions_page.dart @@ -117,8 +117,10 @@ class _PermissionsPageState extends State { context, ); - // ignore: use_build_context_synchronously - return OnboardingFlowNavigator(context.read()) + if (!context.mounted) { + return; + } + await OnboardingFlowNavigator(context.read()) .navigateToPage( context, _onboardingPage.getNextPage(), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart index 4e61ab665c5..35859af54be 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_connect.dart @@ -246,7 +246,9 @@ class UserPreferencesConnect extends AbstractUserPreferences { return; } // No email client installed on the device - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await showDialog( context: context, builder: (BuildContext context) => ScaffoldMessenger( diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart index 00777d3e7e2..4ccea926329 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_dev_mode.dart @@ -193,7 +193,9 @@ class UserPreferencesDevMode extends AbstractUserPreferences { ); } - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await showDialog( context: context, builder: (BuildContext context) => SmoothAlertDialog( @@ -258,15 +260,16 @@ class UserPreferencesDevMode extends AbstractUserPreferences { ProductListImportExport.TMP_IMPORT, localDatabase, ); - //ignore: use_build_context_synchronously - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - appLocalizations - .dev_preferences_import_history_result_success, + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + appLocalizations + .dev_preferences_import_history_result_success, + ), ), - ), - ); + ); + } localDatabase.notifyListeners(); }, ), diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart index 8e79aa8caef..710e1daf5d1 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_faq.dart @@ -205,7 +205,9 @@ class UserPreferencesFaq extends AbstractUserPreferences { Future _about() async { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } showDialog( context: context, builder: (BuildContext context) { diff --git a/packages/smooth_app/lib/pages/preferences/user_preferences_food.dart b/packages/smooth_app/lib/pages/preferences/user_preferences_food.dart index dadbf644cb9..75d0d4b1517 100644 --- a/packages/smooth_app/lib/pages/preferences/user_preferences_food.dart +++ b/packages/smooth_app/lib/pages/preferences/user_preferences_food.dart @@ -92,8 +92,9 @@ class UserPreferencesFood extends AbstractUserPreferences { text: appLocalizations.yes, onPressed: () async { await context.read().resetImportances(); - //ignore: use_build_context_synchronously - Navigator.pop(context); + if (context.mounted) { + Navigator.pop(context); + } }, ), negativeAction: SmoothActionButton( diff --git a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart index fced223cea3..3e745dfa4d4 100644 --- a/packages/smooth_app/lib/pages/product/add_basic_details_page.dart +++ b/packages/smooth_app/lib/pages/product/add_basic_details_page.dart @@ -206,6 +206,10 @@ class _AddBasicDetailsPageState extends State { return false; } + if (!context.mounted) { + return false; + } + AnalyticsHelper.trackProductEdit( AnalyticsEditEvents.basicDetails, _product.barcode!, @@ -213,7 +217,7 @@ class _AddBasicDetailsPageState extends State { ); await BackgroundTaskDetails.addTask( minimalistProduct, - widget: this, + context: context, stamp: BackgroundTaskDetailsStamp.basicDetails, ); diff --git a/packages/smooth_app/lib/pages/product/add_new_product_page.dart b/packages/smooth_app/lib/pages/product/add_new_product_page.dart index f5fb3e83a12..c8c3f084429 100644 --- a/packages/smooth_app/lib/pages/product/add_new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/add_new_product_page.dart @@ -409,7 +409,7 @@ class _AddNewProductPageState extends State : AddNewProductButton.cameraIconData, () async { final File? finalPhoto = await confirmAndUploadNewPicture( - this, + context, barcode: barcode, imageField: ImageField.OTHER, language: ProductQuery.getLanguage(), diff --git a/packages/smooth_app/lib/pages/product/add_other_details_page.dart b/packages/smooth_app/lib/pages/product/add_other_details_page.dart index 4eb9ea7712e..e82eb340665 100644 --- a/packages/smooth_app/lib/pages/product/add_other_details_page.dart +++ b/packages/smooth_app/lib/pages/product/add_other_details_page.dart @@ -150,7 +150,7 @@ class _AddOtherDetailsPageState extends State { ); await BackgroundTaskDetails.addTask( _getMinimalistProduct(), - widget: this, + context: context, stamp: BackgroundTaskDetailsStamp.otherDetails, ); diff --git a/packages/smooth_app/lib/pages/product/common/product_list_page.dart b/packages/smooth_app/lib/pages/product/common/product_list_page.dart index cd3dbbbe0df..b3262a50b75 100644 --- a/packages/smooth_app/lib/pages/product/common/product_list_page.dart +++ b/packages/smooth_app/lib/pages/product/common/product_list_page.dart @@ -468,8 +468,9 @@ class _ProductListPageState extends State setState(() {}); return; case false: - // ignore: use_build_context_synchronously - LoadingDialog.error(context: context); + if (context.mounted) { + LoadingDialog.error(context: context); + } return; } } diff --git a/packages/smooth_app/lib/pages/product/common/product_query_page_helper.dart b/packages/smooth_app/lib/pages/product/common/product_query_page_helper.dart index 32ea7334887..5d7b0a02d68 100644 --- a/packages/smooth_app/lib/pages/product/common/product_query_page_helper.dart +++ b/packages/smooth_app/lib/pages/product/common/product_query_page_helper.dart @@ -23,8 +23,10 @@ class ProductQueryPageHelper { productQuery, localDatabase, ); + if (!context.mounted) { + return; + } final ProductQueryPageResult? result = - // ignore: use_build_context_synchronously await Navigator.push( context, MaterialPageRoute( diff --git a/packages/smooth_app/lib/pages/product/common/product_refresher.dart b/packages/smooth_app/lib/pages/product/common/product_refresher.dart index 537c411dfda..5b5a815cce6 100644 --- a/packages/smooth_app/lib/pages/product/common/product_refresher.dart +++ b/packages/smooth_app/lib/pages/product/common/product_refresher.dart @@ -114,18 +114,17 @@ class ProductRefresher { /// Returns true if successful. Future fetchAndRefresh({ required final String barcode, - required final State widget, + required final BuildContext context, }) async { - final LocalDatabase localDatabase = widget.context.read(); - final AppLocalizations appLocalizations = - AppLocalizations.of(widget.context); + final LocalDatabase localDatabase = context.read(); + final AppLocalizations appLocalizations = AppLocalizations.of(context); final FetchedProduct? fetchAndRefreshed = await LoadingDialog.run( future: silentFetchAndRefresh( localDatabase: localDatabase, barcode: barcode, ), - context: widget.context, + context: context, title: appLocalizations.refreshing_product, ); if (fetchAndRefreshed == null) { @@ -133,16 +132,16 @@ class ProductRefresher { return false; } if (fetchAndRefreshed.product == null) { - if (widget.mounted) { + if (context.mounted) { await LoadingDialog.error( - context: widget.context, + context: context, title: fetchAndRefreshed.getErrorTitle(appLocalizations), ); } return false; } - if (widget.mounted) { - ScaffoldMessenger.of(widget.context).showSnackBar( + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(appLocalizations.product_refreshed), duration: SnackBarDuration.short, diff --git a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart index 4e04c59e48b..2f68aeb3680 100644 --- a/packages/smooth_app/lib/pages/product/edit_new_packagings.dart +++ b/packages/smooth_app/lib/pages/product/edit_new_packagings.dart @@ -172,7 +172,7 @@ class _EditNewPackagingsState extends State child: addPanelButton( appLocalizations.add_packaging_photo_button_label.toUpperCase(), onPressed: () async => confirmAndUploadNewPicture( - this, + context, imageField: ImageField.OTHER, barcode: barcode, language: ProductQuery.getLanguage(), @@ -297,7 +297,7 @@ class _EditNewPackagingsState extends State await BackgroundTaskDetails.addTask( changedProduct, - widget: this, + context: context, stamp: BackgroundTaskDetailsStamp.structuredPackaging, ); return true; diff --git a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart b/packages/smooth_app/lib/pages/product/edit_ocr_page.dart index 229e429d7e5..428ad4e2f2a 100644 --- a/packages/smooth_app/lib/pages/product/edit_ocr_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_ocr_page.dart @@ -104,6 +104,9 @@ class _EditOcrPageState extends State with UpToDateMixin { )) { return; } + if (!context.mounted) { + return; + } AnalyticsHelper.trackProductEdit( _helper.getEditEventAnalyticsTag(), barcode, @@ -111,7 +114,7 @@ class _EditOcrPageState extends State with UpToDateMixin { ); await BackgroundTaskDetails.addTask( changedProduct, - widget: this, + context: context, stamp: _helper.getStamp(), ); return; @@ -322,7 +325,7 @@ class _EditOcrPageState extends State with UpToDateMixin { appLocalizations.add_packaging_photo_button_label .toUpperCase(), onPressed: () async => confirmAndUploadNewPicture( - this, + context, imageField: ImageField.OTHER, barcode: widget.product.barcode!, language: language, diff --git a/packages/smooth_app/lib/pages/product/edit_product_page.dart b/packages/smooth_app/lib/pages/product/edit_product_page.dart index c28ef8b804e..bdadb818d30 100644 --- a/packages/smooth_app/lib/pages/product/edit_product_page.dart +++ b/packages/smooth_app/lib/pages/product/edit_product_page.dart @@ -1,5 +1,3 @@ -// ignore_for_file: use_build_context_synchronously - import 'package:auto_size_text/auto_size_text.dart'; import 'package:barcode_widget/barcode_widget.dart'; import 'package:flutter/material.dart'; @@ -120,7 +118,7 @@ class _EditProductPageState extends State with UpToDateMixin { body: RefreshIndicator( onRefresh: () async => ProductRefresher().fetchAndRefresh( barcode: barcode, - widget: this, + context: context, ), child: Scrollbar( controller: _controller, @@ -199,6 +197,9 @@ class _EditProductPageState extends State with UpToDateMixin { AnalyticsEditEvents.nutrition_Facts, barcode, ); + if (!context.mounted) { + return; + } await NutritionPageLoaded.showNutritionPage( product: upToDateProduct, isLoggedInMandatory: true, @@ -238,6 +239,9 @@ class _EditProductPageState extends State with UpToDateMixin { )) { return; } + if (!context.mounted) { + return; + } AnalyticsHelper.trackProductEdit( AnalyticsEditEvents.otherDetails, barcode, @@ -290,6 +294,9 @@ class _EditProductPageState extends State with UpToDateMixin { )) { return; } + if (!context.mounted) { + return; + } AnalyticsHelper.trackProductEdit( AnalyticsEditEvents.powerEditScreen, barcode, diff --git a/packages/smooth_app/lib/pages/product/new_product_page.dart b/packages/smooth_app/lib/pages/product/new_product_page.dart index e361f5d8dff..67659a57688 100644 --- a/packages/smooth_app/lib/pages/product/new_product_page.dart +++ b/packages/smooth_app/lib/pages/product/new_product_page.dart @@ -174,7 +174,7 @@ class _ProductPageState extends State return RefreshIndicator( onRefresh: () async => ProductRefresher().fetchAndRefresh( barcode: barcode, - widget: this, + context: context, ), child: ListView( // /!\ Smart Dart diff --git a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart index e242ea435d7..59419aacb05 100644 --- a/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart +++ b/packages/smooth_app/lib/pages/product/nutrition_page_loaded.dart @@ -426,7 +426,7 @@ class _NutritionPageLoadedState extends State ); await BackgroundTaskDetails.addTask( changedProduct, - widget: this, + context: context, stamp: BackgroundTaskDetailsStamp.nutrition, ); return true; diff --git a/packages/smooth_app/lib/pages/product/ordered_nutrients_cache.dart b/packages/smooth_app/lib/pages/product/ordered_nutrients_cache.dart index dc8ffacdd1c..26815d4989f 100644 --- a/packages/smooth_app/lib/pages/product/ordered_nutrients_cache.dart +++ b/packages/smooth_app/lib/pages/product/ordered_nutrients_cache.dart @@ -21,15 +21,19 @@ class OrderedNutrientsCache { final BuildContext context, ) async { final OrderedNutrientsCache cache = OrderedNutrientsCache._(); - cache._orderedNutrients = await cache._get() ?? - // ignore: use_build_context_synchronously + cache._orderedNutrients = await cache._get(); + if (cache._orderedNutrients == null) { + if (context.mounted) { await LoadingDialog.run( context: context, future: cache._download(), ); + } + } if (cache._orderedNutrients == null) { - // ignore: use_build_context_synchronously - await LoadingDialog.error(context: context); + if (context.mounted) { + await LoadingDialog.error(context: context); + } return null; } return cache; diff --git a/packages/smooth_app/lib/pages/product/product_field_editor.dart b/packages/smooth_app/lib/pages/product/product_field_editor.dart index a2e143f75a8..8cbafdf1291 100644 --- a/packages/smooth_app/lib/pages/product/product_field_editor.dart +++ b/packages/smooth_app/lib/pages/product/product_field_editor.dart @@ -62,7 +62,9 @@ class ProductFieldSimpleEditor extends ProductFieldEditor { product.barcode!, ); - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await Navigator.push( context, MaterialPageRoute( @@ -109,7 +111,9 @@ class ProductFieldDetailsEditor extends ProductFieldEditor { product.barcode!, ); - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await Navigator.push( context, MaterialPageRoute( @@ -137,7 +141,6 @@ class ProductFieldPackagingEditor extends ProductFieldEditor { required final Product product, final bool isLoggedInMandatory = true, }) async { - // ignore: use_build_context_synchronously if (!await ProductRefresher().checkIfLoggedIn( context, isLoggedInMandatory: isLoggedInMandatory, @@ -150,7 +153,9 @@ class ProductFieldPackagingEditor extends ProductFieldEditor { product.barcode!, ); - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await Navigator.push( context, MaterialPageRoute( @@ -213,7 +218,9 @@ abstract class ProductFieldOcrEditor extends ProductFieldEditor { product.barcode!, ); - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await Navigator.push( context, MaterialPageRoute( diff --git a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart index ce3c3853bc0..821b3b8721a 100644 --- a/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart +++ b/packages/smooth_app/lib/pages/product/product_image_gallery_view.dart @@ -61,7 +61,7 @@ class _ProductImageGalleryViewState extends State true, ); await confirmAndUploadNewPicture( - this, + context, imageField: ImageField.OTHER, barcode: barcode, language: ProductQuery.getLanguage(), @@ -74,7 +74,7 @@ class _ProductImageGalleryViewState extends State body: RefreshIndicator( onRefresh: () async => ProductRefresher().fetchAndRefresh( barcode: barcode, - widget: this, + context: context, ), child: SingleChildScrollView( child: Column( diff --git a/packages/smooth_app/lib/pages/product/product_image_local_button.dart b/packages/smooth_app/lib/pages/product/product_image_local_button.dart index 744d9139a14..abe3f793586 100644 --- a/packages/smooth_app/lib/pages/product/product_image_local_button.dart +++ b/packages/smooth_app/lib/pages/product/product_image_local_button.dart @@ -53,7 +53,7 @@ class _ProductImageLocalButtonState extends State { return; } await confirmAndUploadNewPicture( - this, + context, imageField: widget.imageField, barcode: widget.barcode, language: widget.language, diff --git a/packages/smooth_app/lib/pages/product/product_image_viewer.dart b/packages/smooth_app/lib/pages/product/product_image_viewer.dart index 34cc36d134e..766bb09a771 100644 --- a/packages/smooth_app/lib/pages/product/product_image_viewer.dart +++ b/packages/smooth_app/lib/pages/product/product_image_viewer.dart @@ -1,5 +1,3 @@ -// ignore_for_file: use_build_context_synchronously - import 'dart:io'; import 'package:crop_image/crop_image.dart'; @@ -269,11 +267,13 @@ class _ProductImageViewerState extends State // but if not possible, get the best picture from the server. final String? imageUrl = _imageData.getImageUrl(ImageSize.ORIGINAL); - imageFile = await downloadImageUrl( - context, - imageUrl, - DaoInt(context.read()), - ); + if (context.mounted) { + imageFile = await downloadImageUrl( + context, + imageUrl, + DaoInt(context.read()), + ); + } if (imageFile != null) { return _openCropPage(navigatorState, imageFile); } @@ -297,6 +297,9 @@ class _ProductImageViewerState extends State return; } + if (!context.mounted) { + return; + } final bool? confirmed = await showDialog( context: context, builder: (BuildContext context) { @@ -318,14 +321,17 @@ class _ProductImageViewerState extends State }, ); if (confirmed == true) { - await BackgroundTaskUnselect.addTask( - barcode, - imageField: widget.imageField, - widget: this, - language: widget.language, - ); - context.read().notifyListeners(); - navigatorState.pop(); + if (context.mounted) { + final LocalDatabase localDatabase = context.read(); + await BackgroundTaskUnselect.addTask( + barcode, + imageField: widget.imageField, + context: context, + language: widget.language, + ); + localDatabase.notifyListeners(); + navigatorState.pop(); + } } } diff --git a/packages/smooth_app/lib/pages/product/simple_input_page.dart b/packages/smooth_app/lib/pages/product/simple_input_page.dart index 0094e9ef841..d982e62810c 100644 --- a/packages/smooth_app/lib/pages/product/simple_input_page.dart +++ b/packages/smooth_app/lib/pages/product/simple_input_page.dart @@ -187,7 +187,7 @@ class _SimpleInputPageState extends State { in changedProducts.entries) { await BackgroundTaskDetails.addTask( entry.value, - widget: this, + context: context, stamp: entry.key, showSnackBar: first, ); diff --git a/packages/smooth_app/lib/pages/product_list_user_dialog_helper.dart b/packages/smooth_app/lib/pages/product_list_user_dialog_helper.dart index 3cab0f5e632..f55eca30576 100644 --- a/packages/smooth_app/lib/pages/product_list_user_dialog_helper.dart +++ b/packages/smooth_app/lib/pages/product_list_user_dialog_helper.dart @@ -1,5 +1,3 @@ -// ignore_for_file: use_build_context_synchronously - import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -200,7 +198,9 @@ class ProductListUserDialogHelper { builder: (BuildContext context) => _UserEmptyLists(daoProductList), ); if (newListCreated != null && newListCreated) { - return showUserAddProductsDialog(context, barcodes); + if (context.mounted) { + return showUserAddProductsDialog(context, barcodes); + } } return false; } @@ -210,6 +210,9 @@ class ProductListUserDialogHelper { barcodes.toList(growable: false), ); + if (!context.mounted) { + return null; + } return showDialog( context: context, builder: (BuildContext context) => _UserLists( diff --git a/packages/smooth_app/lib/pages/scan/search_page.dart b/packages/smooth_app/lib/pages/scan/search_page.dart index 25882098749..f0dac94eddd 100644 --- a/packages/smooth_app/lib/pages/scan/search_page.dart +++ b/packages/smooth_app/lib/pages/scan/search_page.dart @@ -63,14 +63,15 @@ Future _onSubmittedBarcode( searchCategory: 'barcode', searchCount: 1, ); - //ignore: use_build_context_synchronously - AppNavigator.of(context).push( - AppRoutes.PRODUCT( - fetchedProduct.product!.barcode!, - heroTag: 'search_${fetchedProduct.product!.barcode!}', - ), - extra: fetchedProduct.product, - ); + if (context.mounted) { + AppNavigator.of(context).push( + AppRoutes.PRODUCT( + fetchedProduct.product!.barcode!, + heroTag: 'search_${fetchedProduct.product!.barcode!}', + ), + extra: fetchedProduct.product, + ); + } } else { AnalyticsHelper.trackSearch( search: value, diff --git a/packages/smooth_app/lib/pages/user_management/login_page.dart b/packages/smooth_app/lib/pages/user_management/login_page.dart index fa38054779f..508feb4128c 100644 --- a/packages/smooth_app/lib/pages/user_management/login_page.dart +++ b/packages/smooth_app/lib/pages/user_management/login_page.dart @@ -373,7 +373,9 @@ class _LoginPageState extends State with TraceableClientMixin { }, ); if (enjoyingApp != null && !enjoyingApp) { - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await showDialog( context: context, builder: (BuildContext context) { @@ -402,7 +404,9 @@ class _LoginPageState extends State with TraceableClientMixin { } bool? userRatedApp; if (enjoyingApp != null && enjoyingApp) { - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } userRatedApp = await showDialog( context: context, builder: (BuildContext context) { diff --git a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart index fdae0e3d1d9..b44f7ab04c9 100644 --- a/packages/smooth_app/lib/pages/user_management/sign_up_page.dart +++ b/packages/smooth_app/lib/pages/user_management/sign_up_page.dart @@ -397,9 +397,9 @@ class _SignUpPageState extends State with TraceableClientMixin { } } - // ignore: use_build_context_synchronously - await LoadingDialog.error(context: context, title: errorMessage); - + if (context.mounted) { + await LoadingDialog.error(context: context, title: errorMessage); + } return; } AnalyticsHelper.trackEvent(AnalyticsEvent.registerAction); @@ -407,7 +407,9 @@ class _SignUpPageState extends State with TraceableClientMixin { return; } await context.read().putUser(user); - // ignore: use_build_context_synchronously + if (!context.mounted) { + return; + } await showDialog( context: context, builder: (BuildContext context) => SmoothAlertDialog(