Skip to content

Native Mobile Interface

This section covers the native Capacitor features that make DreamStream feel like a true native app, not just a web wrapper.


At a glance

Feature Purpose Web Native
Authentication Google, Apple, Magic Link, Email/Password โœ… OAuth โœ… Native
App Shortcuts Long-press icon โ†’ "Record Dream" โŒ โœ…
Siri Shortcuts Voice command: "Hey Siri, record dream" โŒ โš ๏ธ Deprecated
Haptic Feedback Tactile response on key actions โŒ โœ…
Biometric Lock Face ID / Fingerprint to unlock app โŒ โœ…
Pull-to-Refresh Native-feel refresh on journal Degraded โœ…
Network Detection Offline banner + auto-recovery โœ… โœ…
Native Camera Photo picker for Digital Twin โŒ โœ…
Native Share Share images to other apps โŒ โœ…
Inโ€‘App Review Prompt Native App Store rating sheet (requested at delight moments) โŒ โœ… iOS
OTA Updates Silent app updates via Capgo โŒ โœ…

1) Authentication

DreamStream supports multiple authentication methods, with behavior that varies by platform.

Available Methods

Method Web Android iOS
Google OAuth redirect OAuth (in-app browser) OAuth (in-app browser)
Apple OAuth redirect OAuth redirect Native FaceID/TouchID
Magic Link โœ… Email link โœ… Email link โœ… Email link
Email/Password โœ… โœ… โœ…

Native Apple Sign-In (iOS Only)

On iOS devices, Apple Sign-In uses the native authentication sheet instead of a web redirect. This provides:

  • FaceID/TouchID authentication (same as App Store purchases)
  • No browser popup or redirect
  • Faster, more seamless experience

First-login name capture

Apple only sends the user's full name on the first sign-in. DreamStream automatically captures and saves this to user metadata. Subsequent logins return null for name fields.

Hide My Email (Apple)

Apple users can choose to hide their email address during sign-up. When this happens:

  • Apple generates a proxy email (e.g., xyz123@privaterelay.appleid.com)
  • This email forwards to the user's real address
  • DreamStream allows these users to authenticate normally

Platform Behavior

flowchart TD
    A[User taps Sign In] --> B{Platform?}
    B -->|iOS + Apple| C[Native FaceID/TouchID sheet]
    B -->|Web/Android + Apple| D[OAuth browser redirect]
    B -->|All + Google| E[OAuth browser redirect]
    C --> F[Identity token โ†’ Supabase]
    D --> F
    E --> F
    F --> G[User authenticated]

Implementation

Technical: Code locations
  • Native Apple Sign-In: src/services/nativeService.ts โ†’ signInWithApple()
  • Auth UI component: src/components/Auth.tsx โ†’ handleSocialLogin()
  • Supabase client: src/lib/supabase.ts

2) App Shortcuts (Long-Press Launcher Icon)

What users see

When users long-press the DreamStream app icon, they see a quick action:

  • "Record Dream" โ€“ Tapping this opens the app directly into Quick Capture recording mode

Behavior

  • The shortcut dispatches a shortcut:record event
  • The app listens for this event and opens the Quick Capture overlay with recording auto-started
  • Works on both Android and iOS

The app also responds to a deep link that triggers the same Quick Capture flow (examples: dreamstream://record or dreamstream://shortcut/record).

flowchart TD
    A[Long-press app icon] --> B[Tap 'Record Dream']
    B --> C[App opens with Quick Capture overlay]
    C --> D[Recording starts automatically]

3) Siri Shortcuts (iOS Only)

Deprecated

Siri Shortcuts support is currently disabled due to plugin incompatibility with newer Capacitor/iOS tooling. Users can use the App Shortcut (โ€œRecord Dreamโ€) instead.

Siri voice phrases like โ€œHey Siri, record dreamโ€ are not currently supported in production builds. If this is re-enabled in the future, it should launch the same Quick Capture experience as the app shortcut.

Technical: Siri Setup

Historical notes may exist in docs/NATIVE_SIRI_SETUP.md, but the current app does not rely on this path in production.


4) Haptic Feedback

DreamStream uses haptics to create a premium tactile experience.

Where haptics are used

Action Haptic Type Location
Dream saved successfully Success notification Save button
Save failed Error notification Save button
Share button tapped Light impact Dream Detail
Streak milestone reached Strong notification Celebration modal
Pull-to-refresh threshold Selection Journal scroll
Pull-to-refresh complete Medium impact Journal scroll
Tab navigation Light impact Bottom nav
Create button Medium impact Bottom nav

Why it matters

Haptics differentiate DreamStream from web apps. Users subconsciously feel the app is "real" because their device responds physically to interactions.



5) Biometric Lock (Face ID / Fingerprint)

What users see

In Settings โ†’ Preferences, users can toggle:

  • Biometric Lock โ€“ When enabled, the app requires Face ID or fingerprint to unlock

When biometric prompt appears

  • When the app returns from background (user switches back to DreamStream)
  • On app cold start if the setting is enabled

What happens if authentication fails

  • The user stays on a locked screen
  • They can retry authentication
  • The app does not unlock without successful biometrics

Device storage

Device-only setting

The biometric lock preference is stored on-device only (not synced to cloud). If a user switches devices, they'll need to re-enable this setting.

  • Key: localStorage['biometric_lock_enabled']

6) Pull-to-Refresh

What users see

On the Dream Journal and Home Dashboard, users can pull down to refresh content.

Behavior

  • A haptic "selection" fires when crossing the refresh threshold
  • A spinner appears during the refresh
  • A haptic "medium impact" fires on completion
  • Smooth spring animations throughout

Implementation

  • Uses a custom PullToRefresh component with GPU-accelerated transforms
  • Respects touch-action: pan-y for native-like scroll behavior
  • Many screens also use โ€œnative-feelโ€ scroll containers for iOS momentum scrolling.

Native-feel scrolling (momentum + overscroll)

DreamStream uses CSS utilities (see src/index.css) for scroll containers that should feel native on iOS:

  • .native-scroll: vertical momentum scrolling via -webkit-overflow-scrolling: touch
  • .native-scroll-contained: same, plus overscroll-behavior: contain to prevent scroll chaining (useful for modals/nested lists)
  • .native-scroll-x: horizontal scroll areas (carousels/tabs) with gesture-friendly touch-action

These utilities should be applied to containers with a constrained height (e.g., Settings, modals, tab panels). iOS โ€œrubber-bandโ€/elastic overscroll still appears when the container hits its edge; containment prevents accidentally scrolling the background.


7) Network Detection & Offline Banner

What users see

When the device loses connectivity:

  • An Offline Banner appears at the top of the screen
  • The banner reads: "You're offline. Some features may be limited."
  • When connectivity returns, the banner disappears automatically

Graceful degradation

  • Dreams and quick-capture drafts that fail cloud save due to connectivity are placed in the Offline Queue (see Capture & Offline Sync)
  • Cached dream and profile data remain accessible
  • AI generation and chat require connectivity

8) Native Camera Picker

Where it's used

  • Digital Twin photo capture (Settings โ†’ Dream Persona)
  • Known People reference photos (Settings โ†’ Dream Persona)

What users see

When tapping to add/change a photo, the native action sheet appears:

  • Take Photo โ€“ Opens device camera
  • From Gallery โ€“ Opens photo library
  • Cancel โ€“ Dismisses without action

This is a native picker, not a web file input.


9) Native Share

What users can share

From Dream Detail, users can share:

  • Dream Image โ€“ The main AI visualization
  • Comic โ€“ The 9-panel comic
  • Insight Lens โ€“ The decoded/annotated image

What users see

Tapping the share button opens the native share sheet, allowing sharing to any app (Messages, Instagram, Save to Files, etc.).


10) Inโ€‘App Review Prompt (iOS Only)

What users see

DreamStream may occasionally request the native iOS rating/review sheet.

Important: iOS may choose not to display it even when requested.

When we request it

We only request a review after โ€œdelightโ€ moments (not during onboarding), such as:

  • After a user has logged multiple dreams
  • After a share/download action
  • After a streak milestone

Implementation

Technical: Code locations
  • Gating rules: src/services/ratingPromptService.ts
  • Request call: src/services/nativeService.ts โ†’ requestInAppReview()
  • Trigger points: App.tsx

11) OTA Updates (Capgo)

What happens (invisible to users)

DreamStream uses Capgo for over-the-air updates:

  • On app launch, the app checks for updates
  • If an update is available, it downloads in the background
  • On next app restart, the update is applied seamlessly
  • Users never need to visit the App Store for non-native updates

User-visible behavior

  • Updates happen silently
  • The app may show a brief "Updating..." message in rare cases

12) Status Bar & Screen Orientation

Status bar

  • Matches app theme automatically (light text on dark background)
  • Hides during fullscreen lightbox viewing
  • Returns when lightbox closes

Screen orientation

  • App is portrait-locked by default
  • Lightbox allows landscape rotation for viewing images
  • When lightbox closes, app returns to portrait

13) In-App Browser

Where it's used

  • Legal links (Terms of Service, Privacy Policy)
  • Help links (if applicable)

What users see

External links open in an in-app browser modal instead of kicking users to Safari/Chrome. This keeps users in the DreamStream experience.


14) Text-to-Speech (Read Aloud)

Where it's used

  • Dream Insights โ€“ Tap "Read Aloud" to hear analysis spoken
  • IRT Wizard โ€“ Rescripted endings can be read aloud for rehearsal

Behavior

  • Uses native TTS engine on device
  • On web, falls back to Web Speech API
  • Tapping again stops playback

See also: Chat & Audio Experiences for Read Aloud details.


15) Offline Caching

Text data cache

When online, DreamStream caches:

  • Dreams list
  • User profile

On subsequent app opens, the cached data loads instantly while fresh data fetches in background.

Image cache

  • Dream images are cached to device storage (native only) for faster reloads
  • Images older than 7 days are automatically cleared on app startup
  • Cache is cleared on logout to prevent cross-user data leakage on shared devices
  • If an image is not cached and the device is offline, a placeholder appears

Implementation map (for accuracy checks)

Component files
  • Native service wrapper: src/services/nativeService.ts
  • Shortcut configuration: nativeService.configureShortcuts()
  • Biometric auth: nativeService.authenticate()
  • Pull-to-refresh: components/PullToRefresh.tsx
  • Offline banner: components/OfflineBanner.tsx
  • Network context: src/contexts/NetworkStatusContext.tsx
  • Lightbox orientation: components/Lightbox.tsx


โ† Home ยท Chat & Audio โ†’