fix usage share crash null GlobalKey context before tab renders#7509
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Greptile SummaryFixes a production crash in
Confidence Score: 4/5Safe to merge — the change is narrowly scoped to the crash path and does not alter any existing behavior beyond preventing the null dereference. The root cause of the Crashlytics crash is correctly addressed. The only remaining observations are that findRenderObject() still uses a forced cast (rather than a null-safe one) and that !mounted guards are absent from the later async gaps — neither of which can cause the original crash or introduce new widget-tree errors given that context is captured before the first await. No files require special attention; all changes are contained within app/lib/pages/settings/usage_page.dart. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User taps Share button] --> B{captureContext == null?}
B -- yes --> C[return early — no crash]
B -- no --> D{!mounted?}
D -- yes --> C
D -- no --> E[findRenderObject as RenderRepaintBoundary]
E --> F[await boundary.toImage]
F --> G{!mounted?}
G -- yes --> C
G -- no --> H[await rootBundle.load logo\nawait instantiateImageCodec\nawait getNextFrame]
H --> I[Draw watermark on canvas]
I --> J[await toImage + toByteData]
J --> K{byteData == null?}
K -- yes --> L{mounted?}
L -- yes --> M[show SnackBar]
L -- no --> C
K -- no --> N[await getTemporaryDirectory\nawait file.create\nawait file.writeAsBytes]
N --> O[await SharePlus.share]
|
| _screenshotKeys[_tabController.index].currentContext!.findRenderObject() as RenderRepaintBoundary; | ||
| final captureContext = _screenshotKeys[_tabController.index].currentContext; | ||
| if (captureContext == null || !mounted) return; | ||
| final RenderRepaintBoundary boundary = captureContext.findRenderObject() as RenderRepaintBoundary; |
There was a problem hiding this comment.
findRenderObject() returns RenderObject?, so the forced cast can still throw a TypeError if the render object is unexpectedly absent (e.g., the key was attached before the first frame completed). A null-safe cast makes this defensive and consistent with the null guard added just above it.
| final RenderRepaintBoundary boundary = captureContext.findRenderObject() as RenderRepaintBoundary; | |
| final boundary = captureContext.findRenderObject() as RenderRepaintBoundary?; | |
| if (boundary == null) return; |
Crash
_UsagePageState._shareUsageError:
FlutterError - Null check operator used on a null valuepackage:omi/pages/settings/usage_page.dart:172Crashlytics: https://console.firebase.google.com/u/0/project/based-hardware/crashlytics/app/ios:com.friend-app-with-wearable.ios12/issues/85cdd34aeecb1d6a0b50cdc14083ef78?time=7d&types=crash&sessionEventKey=16956422ab7248b6940d706ae0b6eb02_2222284095727765224
Logs:
Fix
_screenshotKeys[index].currentContext!crashed when the tab's widget hadn't rendered yet — theGlobalKeyhas no context until the tab is visited. Replaced the force-unwrap with a null guard that returns early, and added a!mountedcheck after the firstawaitto bail if the widget is disposed during image capture.🤖 Generated with Claude Code