fix(agentic-cli): open settings on any Android deny after Turn on - #33744
Conversation
…anent deny Android Notifee reports DENIED for both first-time and permanently blocked push permission, so request OS permission first and deep-link to notification settings when the request returns without showing a dialog. Co-authored-by: Cursor <cursoragent@cursor.com>
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
PR template — items to address before "Ready for review"Warnings — informational, address before merging:
See docs/readme/ready-for-review.md for the full Definition of Ready for Review. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit ff87ff2. Configure here.
Replace elapsed-time heuristic for detecting permanent notification denial with PermissionsAndroid.request() and NEVER_ASK_AGAIN result, which is the authoritative signal that the OS dialog can no longer be shown. Also handle Android < 13 by opening settings directly. Fixes Bugbot finding: Android elapsed time misclassifies deny. Co-authored-by: Cursor <cursoragent@cursor.com>
Android 13+ may return DENIED (not NEVER_ASK_AGAIN) when the OS dialog is skipped after permanent denial. Treat fast PermissionsAndroid.request completion as a no-dialog denial and deep-link to notification settings. Co-authored-by: Cursor <cursoragent@cursor.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #33744 +/- ##
========================================
Coverage 84.75% 84.76%
========================================
Files 6223 6226 +3
Lines 167061 167338 +277
Branches 40853 40935 +82
========================================
+ Hits 141596 141845 +249
- Misses 15797 15801 +4
- Partials 9668 9692 +24 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Replace elapsed-time heuristic with shouldShowRequestPermissionRationale after DENIED to distinguish dialog dismissal from silent permanent deny without misclassifying a quick in-dialog deny. Co-authored-by: Cursor <cursoragent@cursor.com>
Wrap shouldShowRequestPermissionRationale in a typed helper because RN PermissionsAndroidStatic typings omit the runtime API. Also fix no-void lint. Co-authored-by: Cursor <cursoragent@cursor.com>
Simplify Android push nudge logic: once the user taps Turn on, any OS permission denial opens notification settings instead of dismissing the toast. Removes shouldShowRequestPermissionRationale branching. Co-authored-by: Cursor <cursoragent@cursor.com>
Use jest.SpyInstance for PermissionsAndroid.request spy to satisfy lint:tsc. Co-authored-by: Cursor <cursoragent@cursor.com>
Extract granted, Android, and iOS permission flows into dedicated callbacks so the tap handler is a thin orchestrator, resolving the SonarCloud cognitive-complexity warning. Behavior is unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
… defer Android loading toast - Move inFlightRef release before NotificationService.openSystemSettings() so a throw can't leave "Turn on" permanently locked (iOS + Android consistent). - Defer the Android loading toast to after RESULTS.GRANTED so it no longer sits behind the OS permission dialog. Co-authored-by: Cursor <cursoragent@cursor.com>
🔍 Smart E2E Test Selection
click to see 🤖 AI reasoning detailsE2E Test Selection:
No E2E smoke tests are relevant because:
Performance tests are also not warranted as this is a UI hook for a notification nudge with no impact on app launch, login, asset loading, or any other performance-sensitive flow. Performance Test Selection: |
|




Description
Follow-up to #33688 (MMAI-925: Agentic CLI login push-permission nudge, toast variant).
On Android 13+, tapping Turn on on the nudge calls
PermissionsAndroid.request(POST_NOTIFICATIONS)instead of relying on Notifee'sisPushPermissionPromptable(), which reportsDENIEDfor both first-time and permanently blocked states and can leave the nudge in a no-op path.enableNotifications()and close the toastAndroid < 13 has no runtime permission dialog; tapping Turn on opens notification settings directly.
iOS is unchanged: when the OS can still show its dialog,
enableNotifications()runs and a denial closes the toast without opening Settings; when the OS can no longer prompt, MetaMask deep-links to notification settings.This simplifies earlier iterations by removing denial counters, elapsed-time heuristics, and
shouldShowRequestPermissionRationalebranching.Video
Screen.Recording.2026-07-24.at.4.51.14.PM.mov
Changelog
CHANGELOG entry: null
Related issues
Refs: MMAI-925
Manual testing steps
Screenshots/Recordings
Before
N/A
After
N/A — verified manually on physical Android device (SM_A336E).
Pre-merge author checklist
Performance checks (if applicable)
trace()for usage andaddTokenfor an exampleFor performance guidelines and tooling, see the Performance Guide.
Pre-merge reviewer checklist
Note
Medium Risk
Touches post-login notification permission UX on Android (runtime permission + settings deep link) with moderate refactor of async flow guards; iOS path is mostly extracted, not redesigned.
Overview
Android “Turn on” on the CLI login push nudge no longer relies on Notifee promptability (which couldn’t distinguish first ask vs blocked). The hook now branches by platform after checking whether push is already granted.
On Android 13+, it calls
PermissionsAndroid.request(POST_NOTIFICATIONS): granted runs the existing enable flow and closes the toast; denied or never ask again closes the toast, opens notification settings, and retries enable when the app returns to foreground if OS permission was granted. On Android < 13, Turn on skips a runtime dialog and goes straight to settings with the same foreground retry.iOS behavior is unchanged but shares a new
openSettingsAndScheduleRetryhelper with Android. The Turn on handler is refactored into smaller flows, the in-flight guard is released before opening settings, and foreground retry handlers swallow promise rejections.Tests add Android 13+ and pre-13 cases with
PermissionsAndroid/Platformmocks.Reviewed by Cursor Bugbot for commit 4a35570. Bugbot is set up for automated code reviews on this repo. Configure here.