Commit Graph
19 Commits
Author SHA1 Message Date
Jinwoo-HandOrca 86cb99cad8 Improve mobile UI polish
- 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>
2026-04-30 18:03:54 -04:00
Jinwoo-HandOrca 14a314a29d fix: terminal output duplication on mobile
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>
2026-04-30 18:03:54 -04:00
Jinwoo-HandOrca 92aeac9692 feat(mobile): interactive swipe-to-dismiss drawers and improved QR instructions
- 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>
2026-04-30 18:03:54 -04:00
Jinwoo-HandOrca 3bed9df9bc fix(mobile): use Android-native haptics API instead of Vibrator
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>
2026-04-30 18:03:54 -04:00
Jinwoo-HandOrca e6f9cdc90b Improve mobile terminal UX and unify modal design language
- Add custom keyboard shortcuts (Ctrl+Key, Alt+Key, text macros) with persistent storage
- Add built-in terminal shortcuts (Ctrl+L/Z/R/A/E/W/U) and resize toggle
- Allow sending Enter on empty input for terminal convenience
- Fix delete worktree: correct RPC method (worktree.rm) with optimistic UI
- Fix modal transition flicker between action sheet and confirm dialog
- Unify all modals to consistent bottom drawer pattern with inner action groups

Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:54 -04:00
Jinwoo-HandOrca d2ce1c5ff1 fix mobile terminal replay row mismatch
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:53 -04:00
Jinwoo-HandOrca 11f45095cd fix zsh startup command double echo
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:53 -04:00
Jinwoo-HandOrca 2c6f710b56 checkpoint mobile terminal streaming work
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:53 -04:00
Jinwoo-HandOrca 42e9ed2ca1 Add haptic feedback, sleep action, and fix send button styling
- 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>
2026-04-30 18:03:24 -04:00
Jinwoo-HandOrca fc75b28f7d Add end-to-end encryption for mobile WebSocket transport
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>
2026-04-30 18:03:24 -04:00
Jinwoo-HandOrca cd340227ad Persist terminal fit state across session remounts
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>
2026-04-30 18:03:24 -04:00
Jinwoo-HandOrca 67d4f56ddb Improve mobile terminal touch handling and display
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>
2026-04-30 18:03:24 -04:00
Jinwoo-HandOrca 466b2659a8 Implement mobile terminal fit-to-phone with robust restore
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>
2026-04-30 18:03:24 -04:00
Jinwoo-HandOrca d50022ce61 Improve mobile terminal tab actions
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:24 -04:00
Jinwoo-HandOrca c1e8623e5f Improve mobile worktree and terminal UX
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:23 -04:00
Jinwoo-HandOrca 544b86fcb0 fix(mobile): simplify terminal WebView rendering and fix display issues
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>
2026-04-30 18:03:23 -04:00
Jinwoo-HandOrca 4fe89e656a fix mobile terminal geometry sync
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:23 -04:00
Jinwoo-HandOrca 5f8c9ef312 fix mobile terminal streaming
Co-authored-by: Orca <help@stably.ai>
2026-04-30 18:03:23 -04:00
Jinwoo-HandOrca 95324c686e feat(mobile): add Expo mobile app with QR pairing and WebSocket RPC transport
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>
2026-04-30 18:03:22 -04:00