- BottomDrawer: shift drawer up when keyboard opens using Keyboard events,
add ScrollView for content overflow
- NewWorktreeModal: replace FlatList with plain map to avoid nested
VirtualizedList error
- Home: replace Server icon with Monitor, hide IP from cards (show in
action sheet), add connection status subtitle, update hero copy
- About: remove redundant link labels, use neutral text color for URLs
Co-authored-by: Orca <help@stably.ai>
Remove duplicate onPtyData call in pty.ts that caused every daemon-backed
PTY data event to be dispatched twice through dataListeners, doubling all
terminal output sent to mobile clients.
Also: clean up registerSubscriptionCleanup to evict stale listeners on
reconnect, add regression tests, fix CI lint/type errors, add mobile UX
improvements (worktree creation, settings, about screen).
Co-authored-by: Orca <help@stably.ai>
- Add shared BottomDrawer component with pan gesture tracking via reanimated
- Drawer follows finger on swipe down, dismisses past threshold or on velocity
- Rubber-band resistance on upward pull for tactile feel
- Migrate all 5 modal components to use BottomDrawer
- Replace plain text QR instructions with numbered steps with icons
Co-authored-by: Orca <help@stably.ai>
Use performAndroidHapticsAsync on Android which uses HapticFeedbackConstants
instead of the Vibrator API. This fixes haptics not working on Android and
removes the VIBRATE permission requirement.
Co-authored-by: Orca <help@stably.ai>
- Add expo-haptics medium impact feedback on all long-press interactions
(terminal tabs, worktree cards, host cards)
- Add "Sleep" option with Moon icon to worktree action sheet, calling
worktree.sleep RPC method
- Change send button from bright blue (accentBlue) to subtle dark
(bgRaised) background with textSecondary icon color
Co-authored-by: Orca <help@stably.ai>
Replace the disabled TLS cert pinning approach with application-layer
E2EE using tweetnacl (Curve25519 ECDH + XSalsa20-Poly1305). The
WebSocket stays plain ws:// but all RPC traffic is encrypted after
a one-round-trip handshake.
Desktop: generate persistent Curve25519 keypair, E2EE channel module
handles handshake state machine and transparent encrypt/decrypt.
Mobile: ephemeral keypair per connection for forward secrecy, expo-crypto
PRNG polyfill for Hermes compatibility.
Pairing schema updated from v1 (certFingerprint) to v2 (publicKeyB64).
Mock server updated with E2EE support. 24 tests covering crypto,
channel handshake, and integration.
Co-authored-by: Orca <help@stably.ai>
Add module-level Map to persist which terminals have been phone-fitted,
so navigating away and back auto-refits them instead of reverting to
desktop dimensions. Also adds fitPendingRef to prevent duplicate fits.
Co-authored-by: Orca <help@stably.ai>
Replace native WebView scroll/zoom with custom touch handlers that
work correctly with the CSS scale transform:
- Single-finger scroll with scale-compensated sensitivity and momentum
- Pinch-to-zoom (1x-5x) centered on pinch point, with pan when zoomed
- Tap/click suppression to prevent cursor jumping
- Row fill: resize xterm viewport to fill WebView height (display-only)
- Disable native zoom (user-scalable=no) since custom handler replaces it
Co-authored-by: Orca <help@stably.ai>
Add end-to-end mobile-fit override system that lets a phone client resize
a PTY to phone dimensions and restore to desktop dimensions on disconnect
or user request.
Key changes:
- Runtime: resizeForClient() manages override lifecycle with ownership,
clamping, and auto-restore on client disconnect. Always resizes PTY
directly on restore instead of relying on fragile renderer chain.
- RPC: terminal.resizeForClient method for mobile clients via WebSocket.
- Renderer: safeFit() respects active overrides, desktop banner with
Restore button, override change listener with rAF + fallback safety net.
- Mobile: fit-to-phone with CSS scale zoom, auto-fit only for terminals
created during the mobile session (not existing desktop terminals).
- Tests: 14 unit tests + 3 integration tests for override lifecycle.
Co-authored-by: Orca <help@stably.ai>
Use the WebView's native viewport scaling and pinch-to-zoom instead of
custom CSS transforms and touch handlers. The terminal renders at
desktop dimensions with initial-scale=0.5 for a readable default, and
the browser's built-in zoom handles pinch correctly (center point,
scroll directions, no swipe conflicts).
Co-authored-by: Orca <help@stably.ai>
Adds the Orca Mobile companion app (Expo SDK 55 / React Native 0.83) with:
- QR code pairing flow: scan orca://pair# URL, validate auth, save host profile
- WebSocket RPC client with auto-reconnect, exponential backoff, streaming support
- Three screens: host list, worktree list, terminal session with live output
- Mock WebSocket server for development without a running Orca desktop instance
- Desktop-side: TLS certificate management, device registry, mobile IPC handlers,
WebSocket transport layer, and pairing offer encode/decode with Zod validation
- Unit tests for WebSocket transport and pairing codec
Co-authored-by: Orca <help@stably.ai>