Repository navigation
Add unified mobile onboarding for session view and notifications - #9478
Conversation
Mirror the notifications one-time opt-in for the native-chat default view. After pairing, a full-screen modal (modeled on notification-opt-in) lets the user choose whether supported agent sessions open in the terminal or in native chat, then persists the choice to the existing orca:defaultSessionView key. - Expose readDefaultSessionViewPreference() (tri-state; absent key = undecided) so the gate can prompt exactly once; loadDefaultSessionView() is unchanged. - shouldPresentSessionViewOptIn() gates the screen; the home focus effect shows it after the notification opt-in. - Settings -> Native chat toggle (already shipped) remains the recovery path.
📝 WalkthroughWalkthroughAdds a unified mobile onboarding flow for session-view and notification preferences. Structured preference reads distinguish missing, invalid, and unreadable storage. A step planner evaluates eligible prompts and builds routes. New onboarding pages and a carousel persist choices, handle permissions, support reduced motion, and block back navigation. Startup, notification completion, and pairing flows now route through the onboarding destination. Tests cover planning, rendering, persistence failures, accessibility, animation, and navigation. 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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)
mobile/app/notification-opt-in.tsx (1)
53-61: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winAwait
continueToApp()to handle potential promise rejections.Since
continueToAppwas refactored into an asynchronous function, it must be awaited here. If it throws (for example, if a storage error bubbles up while evaluatingshouldPresentSessionViewOptIn()), calling it withoutawaitwill result in an unhandled promise rejection. Thecatchblock will not execute, leavingchoiceInFlightRef.currentstuck astrueand the UI permanently locked with a disabled spinner state.🐛 Proposed fix to await the async routing function
try { const enabled = choice === 'enable' ? await ensureNotificationPermissions() : false await savePushNotificationsEnabled(enabled) - continueToApp() + await continueToApp() } catch { setError('Notification settings could not be updated. Try again.') setBusyChoice(null) choiceInFlightRef.current = false }
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 7b9b0cb5-220d-4b23-bab1-5cca052a2e02
📒 Files selected for processing (11)
mobile/app/index.tsxmobile/app/notification-opt-in.tsxmobile/app/pair-confirm.tsxmobile/app/pair-scan.tsxmobile/app/session-view-opt-in.tsxmobile/src/onboarding/mobile-onboarding-prompt.test.tsmobile/src/onboarding/mobile-onboarding-prompt.tsmobile/src/session/session-view-opt-in-gate.test.tsmobile/src/session/session-view-opt-in-gate.tsmobile/src/storage/preferences.test.tsmobile/src/storage/session-view-preferences.ts
🚧 Files skipped from review as they are similar to previous changes (6)
- mobile/src/session/session-view-opt-in-gate.ts
- mobile/src/session/session-view-opt-in-gate.test.ts
- mobile/src/storage/preferences.test.ts
- mobile/app/session-view-opt-in.tsx
- mobile/src/storage/session-view-preferences.ts
- mobile/app/index.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 15a71b0b-f738-4557-a0d8-5359fd523789
📒 Files selected for processing (12)
mobile/app/_layout.tsxmobile/app/index.tsxmobile/app/mobile-onboarding.tsxmobile/app/notification-opt-in.tsxmobile/app/pair-confirm.tsxmobile/app/pair-scan.tsxmobile/src/onboarding/MobileOnboardingPage.test.tsmobile/src/onboarding/MobileOnboardingPage.tsxmobile/src/onboarding/mobile-onboarding-plan.test.tsmobile/src/onboarding/mobile-onboarding-plan.tsmobile/src/onboarding/mobile-onboarding-screen.test.tsmobile/src/onboarding/mobile-onboarding-styles.ts
💤 Files with no reviewable changes (1)
- mobile/app/notification-opt-in.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- mobile/app/pair-scan.tsx
- mobile/app/pair-confirm.tsx
…blyai#9478) * Add a mobile native-chat opt-in so users pick terminal vs chat once Mirror the notifications one-time opt-in for the native-chat default view. After pairing, a full-screen modal (modeled on notification-opt-in) lets the user choose whether supported agent sessions open in the terminal or in native chat, then persists the choice to the existing orca:defaultSessionView key. - Expose readDefaultSessionViewPreference() (tri-state; absent key = undecided) so the gate can prompt exactly once; loadDefaultSessionView() is unchanged. - shouldPresentSessionViewOptIn() gates the screen; the home focus effect shows it after the notification opt-in. - Settings -> Native chat toggle (already shipped) remains the recovery path. * fix(mobile): preserve onboarding flow after pairing * refine mobile session view opt-in copy * Unify mobile onboarding prompts
What
Combines the mobile native-chat and notification opt-ins into one controlled onboarding flow.
New users with both decisions outstanding see a two-step carousel:
Existing users see only the decision they have not already made, without progress dots. Completing the flow opens Home or returns to the newly paired host.
Why
Native chat already had a per-tab long-press toggle and a Settings → Native chat default-view switch (#9084), but new users had no clear place to discover the choice. Notifications had a related one-time prompt. Presenting the outstanding decisions as one short onboarding sequence makes both choices understandable without stacking separate modal screens.
How
mobile-onboardingmodal while preserving the paired host destination.Step n of 2, and the transition honors Reduce Motion.Tests
tsc --noEmit,oxlint, and formatting checks pass for the PR files.Manual QA — iPhone 17 Pro simulator
Drove the real native flow end-to-end and verified that only the active page appears in the accessibility tree.
1. Session-view choice
2. Notifications choice