10 KiB
06 — Mobile App (React Native) Map
Surface:
apps/mobile-rn(ACTIVE product mobile app) Stack: React Native 0.85 + React 19 (CLI) + Supabase + Google Play Billing + AdMob The Expo legacy skeleton (apps/mobile) was removed 2026-09-13;apps/mobile-rnis the only mobile runtime. Authoritative checklist:docs/v3/MOBILE_APP_COMPLETION_SSOT.md
1. Navigation structure
Root stack (App.tsx RootNavigator) branches on auth/onboarding:
recovery→UpdatePasswordonboarding→ Onboarding + InviteAccept + Login- unauthenticated → Login, SignUp, ForgotPassword, InviteAccept
- authenticated →
Main(TabNavigator) + 23 stack screens
Bottom tabs (TabNavigator.tsx): Home / Records / Meetings / More. Record remains a hidden tab route so an active recording stays mounted; it never occupies a visible tab slot. A floating RecordFab appears on Home/Records/Meetings (not More/Record) and routes dictation → Record, meeting recording → Meetings + createRequest, audio import → Record + importRequest. Android back, scrim press, and action selection close its menu; tab back behavior is history-based.
Home opens UnifiedSearch on the root stack. New and converted v4 flows use the app-level ScreenHeader with a 48dp back action; tab roots such as Records and Meetings show a title without a back action. Historical stack screens that were not part of this conversion may still use their own header.
Deep links: d3ro-voice:// and https://d3ro.chanpaca.net (accept-invite).
Provider stack: GestureHandlerRootView → SafeAreaProvider → AuthProvider → EntitlementProvider → BillingProvider → MobileAdsProvider → MobilePreferencesProvider → DeviceProvider → LocalizedApplication (I18n + StatusBar).
2. Screens (src/screens/: 31 active source files)
| Screen | Feature |
|---|---|
HomeScreen |
Today summary, recent 5 records / 3 meetings, unified-search entry, Free plan entry |
MoreScreen |
Tools and account routes; Admin entry is role-gated |
UnifiedSearchScreen |
Authenticated record+meeting search, newest-first merged results, source-aware detail navigation |
RecordScreen |
Recording + local-whisper/cloud transcription, import audio, share; entered from the hidden Record route/FAB |
TalkScreen |
Voice/text AI chat: STT, LLM streaming, TTS; opened from More on the root stack |
HistoryScreen / HistoryDetailScreen |
History list/detail: sync, search, filters, audio playback, edit/share/favorite/delete |
MeetingsScreen / MeetingDetailScreen |
Meeting workspaces: create/rename/delete, transcript, memos, documents, export, content report |
MemosScreen |
Memos: list, tags, search, share |
TemplatesScreen |
Dictation/meeting document templates CRUD |
KnowledgeScreen |
Knowledge docs: create/import/index/merge/delete/search |
CommandsScreen |
Custom instruction CRUD/reorder/activate/execute |
ActionsScreen |
Voice-action parse/confirm/execute + history |
DictionaryScreen |
Dictionary CRUD/search/filters |
TeamsScreen / TeamDetailScreen |
Teams: create, members, invites, rename, leave, meetings, activity feed/comments |
DevicesScreen |
Registered devices (phones, web, desktop apps), platform label, revoke/remove — revoking a desktop signs it out |
NotificationsScreen |
Notification list, permission, deep-link nav |
AccountScreen |
Profile, identities, data export/delete, logout |
DataPortabilityScreen |
Export/import archive, dictionary, history, meeting docs |
AdminScreen / AdminUserDetailScreen |
Role-gated admin: users, subscriptions, audit, role/tier edits |
ProPaywallScreen |
Pro/Pro+ paywall: Play IAP, restore, rewarded ads |
OnboardingScreen |
First-run audience/theme/locale |
SettingsScreen |
Preferences, locale/theme, privacy links, logout; opened from More on the root stack |
LoginScreen / SignUpScreen / ForgotPasswordScreen / UpdatePasswordScreen / InviteAcceptScreen |
Auth flows |
3. Features (src/features/, 23 modules)
| Module | Purpose |
|---|---|
recording/ |
Durable offline recording queue, retry processing, language handling |
audio/ |
Linked recording/audio cleanup |
import/ |
Audio pick/decode/validate, local Whisper fallback, resumable multipart upload, Android share-intent intake |
history/ |
History service + local cache + sync hook |
meetings/ |
Meeting workspace CRUD, realtime channels, processing jobs, transcripts/memos/docs |
memos/ |
Memo CRUD, tags, search, realtime, share |
talk/ |
Streaming LLM, transcription, TTS playback |
teams/ |
Team CRUD/members/invites/realtime, pending invite, listTeamActivities/createTeamActivity (activity feed) |
knowledge/ |
Knowledge docs CRUD/index/merge/search + file picker |
commands/ |
Custom command client |
actions/ |
Voice-action parse/execute + side effects |
dictionary/ |
Dictionary CRUD/pagination/search |
devices/ |
Device registration/list/revoke |
dashboard/ |
Dashboard stats + recent entries |
templates/ |
Templates + generation idempotency |
auth/ |
OAuth sign-in (in-app browser, PKCE) + identity linking |
account/ |
Account deletion service and server-confirmed exit boundary |
admin/ |
Admin user/subscription/audit APIs + session/role |
data-portability/ |
Canonical JSON export/import, schema validation, legacy import, meeting export, file sharing |
chat/ |
Chat LLM normalization/streaming, reportable generation IDs |
notifications/ |
Notification contract/native registration/service/runtime hook |
reporting/ |
AI content reporting (reason codes, Edge calls, idempotency) |
search/ |
User-scoped record title/original/polished/summary + meeting title/raw/edited transcript search; sanitization, parallel queries, newest-first merge |
Core libs (src/lib/): auth-context, auth-redirect, auth-capabilities, secure-auth-storage (Keychain + legacy migration), logout, account-exit, account-local-data (central purge), supabase, billing-context (Play/App Store IAP), entitlement-context, device-context, preferences-context, mobile-ads-context (UMP consent + rewarded), native-config, pkce-s256, random-id, audio-recorder, e2e-runtime-bootstrap.
4. Mobile status summary
Source of truth for status is docs/v3/MOBILE_APP_COMPLETION_SSOT.md sections 0.1, 2.1, 4. Current condensed state:
| Area | Status |
|---|---|
| Auth / account | [~] Implemented + Jest GREEN; external OAuth consent→callback and logout/delete/provider device E2E pending |
| Onboarding | [x] previous first-run device journey GREEN; this does not verify the new v4 shell on every viewport/theme |
| v4 shell / theme / accessibility | [x] shell journey at 320dp dark and 411dp light; [~] broader design-system/a11y proof because TalkBack/font-scale/rotation remain |
| Recording / transcription / Talk | [x] core path GREEN on API 34 (FGS, recovery, local Whisper, cloud fail-closed, TTS) |
| Data portability | [x] export/restore + share E2E GREEN |
| History / meetings | [x] real data + meeting creation contract GREEN; audio timestamp/speaker + cross-app E2E pending |
| Record+meeting unified search | [~] service/row tests and both canonical runtime journeys (both source results → details) GREEN; mobile raw-text overfetch/no cancellation and FTS/index/large-data performance remain unproved |
| Teams / push | [~] teams GREEN; real FCM delivery needs Firebase/FCM credentials |
| Billing / ads | [~] test ads + Google Play verification code GREEN; live store purchase/restore/settlement and production AdMob serving RED (external) |
| Admin | [x] mobile admin role E2E GREEN (ordinary/manager/admin/super_admin, stale JWT) |
| Quality / distribution | [~] lint/typecheck/Jest GREEN; production signed AAB + Play submission RED (external gates) |
External blockers (do not treat as code gaps): production Firebase project, AdMob live serving, Play Billing license tester, CI secret injection, signed production AAB, Play closed test (0/12, 14 days), production access approval. See SSOT §0, §6.
5. Legacy removal
The Expo skeleton (apps/mobile) was deleted on 2026-09-13: it duplicated auth/data logic, shipped a dev-bypass login, and was outside the workspace and CI. scripts/ci/sync-version.mjs and package-lock.json no longer reference it. apps/mobile-rn is the sole mobile runtime; git history retains the old app.
The v4 shell also removed DashScreen and WorksHubScreen. Home replaces the dashboard entry; first-class tabs and More preserve the former WorksHub destinations. The WorksHub-only local tool filter and pinning were intentionally retired to avoid a second navigation taxonomy and local ordering state. This removed navigation UI, not record/meeting/tool content; an unused works-hub-pins.v1 AsyncStorage key may remain on upgraded installs.
6. Tests & evidence
- Jest:
npm --prefix apps/mobile-rn test— current full tree 86 suites / 589 tests PASS (2026-09-28). v4-focused coverage includesnavigation-shell.test.tsx,screen-header.test.tsx,theme-parity.test.ts,ui-native-theme.test.tsx,unified-search-service.test.ts, andunified-search-result-row.test.tsx. - Maestro E2E:
apps/mobile-rn/.maestro/+ evidence in.maestro-output/. - v4 local runtime:
apps/mobile-rn/.maestro/navigation-shell-search-local.yaml; 320dp dark 1/1 PASS, 88 s atscratch/design-audit/wave45/navigation-shell-search-320-dark-verified.xml, and 411dp light 1/1 PASS, 100 s atscratch/design-audit/wave45/navigation-shell-search-411-light-verified.xml. - Runtime APK:
com.d3ro.voice, versionName1.9.0-e2e.20260928.2, versionCode202609282, 147063583 bytes, SHA-25696EBA2A47E54033EB0DEFCE4E4D282F1D06F162A5F7DF9457E99609D98745D58. This is a local E2E artifact, not a production-signed APK/AAB or Play release. - Committed evidence summary:
docs/evidence/wave45-mobile-shell-search-2026-09-28.md. - Android instrumentation:
apps/mobile-rn/android/app/src/androidTest(CSPRNG + incoming share). - Build verifiers:
scripts/ci/verify-android-artifact.mjs,verify-android-app-links.mjs,verify-mobile-build-config.mjs,verify-mobile-release-boundary.mjs.