fix: address use_build_context_synchronously warnings in UI components#624
fix: address use_build_context_synchronously warnings in UI components#624itsofficially-sreyash wants to merge 2 commits intoCCExtractor:mainfrom
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds explicit Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Comment Tip You can make CodeRabbit's review stricter and more nitpicky using the `assertive` profile, if that's what you prefer.Change the |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
lib/app/modules/profile/views/deleteprofiledialog.dart (1)
20-24:⚠️ Potential issue | 🟠 MajorUse a stable parent context for post-pop Snackbar.
Line 70 pops the dialog, then Line 71 uses the same dialog
contextforScaffoldMessengerwithout a mounted check. Thebuild()method parameter shadows the field, so the code uses the dialog's own context after it's been dismissed. Use the parent context field instead for both the mounted check at line 62 and the SnackBar call at line 71, making the success path consistent with the error handling at lines 81–82.Suggested fix
class DeleteProfileDialog extends StatelessWidget { const DeleteProfileDialog({ required this.profile, - required this.context, + required this.parentContext, required this.profiles, required this.profileName, super.key, }); final String profile; - final BuildContext context; + final BuildContext parentContext; final RxMap<dynamic, dynamic> profiles; final String? profileName; `@override` Widget build(BuildContext context) { @@ var splashController = Get.find<SplashController>(); await splashController.deleteProfile(profile); - if (!context.mounted) return; + if (!parentContext.mounted) return; @@ Get.back(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( + ScaffoldMessenger.of(parentContext).showSnackBar(SnackBar( @@ } catch (e) { - if (!context.mounted) return; - ScaffoldMessenger.of(context).showSnackBar(SnackBar( + if (!parentContext.mounted) return; + ScaffoldMessenger.of(parentContext).showSnackBar(SnackBar(🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/app/modules/profile/views/deleteprofiledialog.dart` around lines 20 - 24, The dialog is using the build() parameter `context` (which shadows the field) for the post-pop SnackBar and mounted check; change those uses to the stable parent `context` field instead. Concretely, in the success path after calling `Navigator.pop(context)` and before/when calling `ScaffoldMessenger.of(...).showSnackBar(...)`, replace the build parameter `context` with the widget field `context` (e.g., `this.context`) and use that same field for the mounted check that currently references the build `context`, so the mounted check and `ScaffoldMessenger.of(...)` both use the stable parent `context` (leaving error-path usage that already uses the field unchanged).
🧹 Nitpick comments (1)
lib/app/modules/home/views/add_task_bottom_sheet_new.dart (1)
399-423: Pre-existing pattern: SnackBar shown after navigation.The
ScaffoldMessenger.of(context).showSnackBar()at lines 408-423 is called afterGet.back()at line 399. While this typically works becauseScaffoldMessengerresolves from the parentScaffold(still mounted), showing feedback after closing the bottom sheet is an unusual pattern. The same applies toonSaveButtonClickedForReplica(lines 480-503).Consider moving the SnackBar display before
Get.back(), or using a callback/event-based approach to show feedback from the parent widget.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/app/modules/home/views/add_task_bottom_sheet_new.dart` around lines 399 - 423, The SnackBar is shown after navigating back via Get.back(), which can be fragile; change both places (the Get.back() call and the matching ScaffoldMessenger.of(context).showSnackBar(...) block) so the SnackBar is displayed before calling Get.back(), or alternatively move the showSnackBar logic out of this bottom-sheet view and trigger it via a callback/event to the parent (see onSaveButtonClickedForReplica as another occurrence); ensure you call ScaffoldMessenger.of(context).showSnackBar(...) while the bottom-sheet’s Scaffold context is still valid or invoke a parent callback that the parent uses to show the SnackBar and then call Get.back().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@lib/app/modules/profile/views/deleteprofiledialog.dart`:
- Around line 20-24: The dialog is using the build() parameter `context` (which
shadows the field) for the post-pop SnackBar and mounted check; change those
uses to the stable parent `context` field instead. Concretely, in the success
path after calling `Navigator.pop(context)` and before/when calling
`ScaffoldMessenger.of(...).showSnackBar(...)`, replace the build parameter
`context` with the widget field `context` (e.g., `this.context`) and use that
same field for the mounted check that currently references the build `context`,
so the mounted check and `ScaffoldMessenger.of(...)` both use the stable parent
`context` (leaving error-path usage that already uses the field unchanged).
---
Nitpick comments:
In `@lib/app/modules/home/views/add_task_bottom_sheet_new.dart`:
- Around line 399-423: The SnackBar is shown after navigating back via
Get.back(), which can be fragile; change both places (the Get.back() call and
the matching ScaffoldMessenger.of(context).showSnackBar(...) block) so the
SnackBar is displayed before calling Get.back(), or alternatively move the
showSnackBar logic out of this bottom-sheet view and trigger it via a
callback/event to the parent (see onSaveButtonClickedForReplica as another
occurrence); ensure you call ScaffoldMessenger.of(context).showSnackBar(...)
while the bottom-sheet’s Scaffold context is still valid or invoke a parent
callback that the parent uses to show the SnackBar and then call Get.back().
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7e2a0ed9-0778-49a1-98de-84160ef64e6b
📒 Files selected for processing (9)
lib/app/modules/detailRoute/controllers/detail_route_controller.dartlib/app/modules/home/views/add_task_bottom_sheet_new.dartlib/app/modules/home/views/home_page_floating_action_button.dartlib/app/modules/manage_task_champion_creds/views/manage_task_champion_creds_view.dartlib/app/modules/profile/controllers/profile_controller.dartlib/app/modules/profile/views/deleteprofiledialog.dartlib/app/modules/profile/views/profile_view.dartlib/app/modules/reports/controllers/reports_controller.dartlib/app/utils/add_task_dialogue/date_picker_input.dart
Overview
Hey team! While performing a code audit and running flutter analyze, I identified several instances where BuildContext was being accessed across asynchronous
gaps.
In Flutter, accessing a BuildContext after an await call without checking if the widget is still "mounted" (active on the screen) is a common source of
unexpected crashes and "silent" errors. If a user navigates away from a page while a background task (like saving a task or fetching a profile) is running, the
app might try to show a SnackBar or pop a dialog using an invalid context.
This PR adds surgical stability checks (if (!context.mounted) return;) across 9 files to ensure the app remains rock-solid during async operations.
What’s Changed?
I’ve updated the "Add Task" bottom sheets and "Profile" views. Now, if a user hits "Save" and then quickly closes the sheet or switches tabs before the database/sync completes, the app will safely cancel the subsequent UI updates instead of trying to interact with a dead context.
I refactored the navigation callbacks in the Floating Action Button and the Manage Credentials view. This ensures that the app won't try to trigger sync processes or navigate "Back" if the underlying widget has already been disposed.
The "Tutorial Coach Mark" logic in the Home, Profile, and Reports modules was triggering after a 500ms delay. I added guards here to prevent the tour from attempting to start if the user has already navigated away from the page during that half-second window.
Technical Details
1 await someAsyncOperation();
2 if (!context.mounted) return; // Guard against unmounted context
3 showSnackBar();
Happy to discuss these changes or jump into the next set of linting fixes!
Summary by CodeRabbit
Bug Fixes
Chores