Commit Graph
9 Commits
Author SHA1 Message Date
JinjingandOrca 2e48495273 Prevent mobile screen locking during voice dictation. (#7746)
* Prevent mobile screen locking during voice dictation

Integrate expo-keep-awake to prevent the mobile device from locking or
sleeping while a voice dictation session is active.

- Modularize useMobileDictation logic into separate helper files for
  keep-awake, audio chunking, session state, and desktop startup.
- Acquire keep-awake lock only after successfully establishing a
  desktop session to avoid locking on stale start attempts.
- Release the keep-awake lock on all completion, cancellation, error,
  and unmount paths.
- Add source invariant unit tests to verify keep-awake ownership and
  strict cleanup ordering.

* serialize keep-awake operations and avoid stale dictation start races

- Implement a global execution queue and tag tracking for keep-awake
  operations to prevent concurrent races and stale deactivations.
- Track failed native deactivations and retry them when a replacement
  hook owner mounts or starts a new dictation session.
- Ensure stale or canceled desktop dictation starts do not reset the
  UI state or propagate outdated start/keep-awake failures.
- Reuse the audio chunk queue wiring in useMobileDictation to avoid
  allocating new closure objects on the high-frequency microphone path.
- Add comprehensive unit tests for the keep-awake and desktop start hooks.

* Commit native recording during dictation session startup

Commit native recording in the same continuation as the final session
stale check. This prevents a queued cancellation from resurrecting the
microphone recording after cleanup has already run. If microphone
initialization fails or throws, acquired resources (like keep-awake
locks and the remote desktop session) are properly rolled back.

* Make keep-awake acquisition best-effort with a bounded startup timeout

- Recording start no longer blocks (or fails) on keep-awake acquisition:
  a hung or failing native call is capped at a short budget and logged
  instead of delaying or aborting dictation.
- Add native-call timeouts, orphan-tag tracking, and reacquire/drain
  logic in mobile-dictation-keep-awake.ts so Activity recreation on
  Android and stale tags no longer wedge the keep-awake queue.
- Add useMobileDictationForegroundKeepAwake to refresh the wake tag on
  Android foreground and retry failed refreshes/deactivations.
- Hold the wake tag through chunk drain and the finish RPC so a screen
  lock can't suspend the app before the transcript arrives, and keep
  cleanup running even if native recording shutdown throws.
- Loosen expo-keep-awake to a caret range to unblock the patch pulling
  in these native fixes.

* Fix cancellation races in mobile dictation keep-awake handling

- Run wake-lock release and dictation cancel concurrently on stale
  starts so a hung acquisition no longer delays the native cancel
- Guard foreground reacquire retries with a run token so a stale
  retry chain can't deactivate a wake lock reacquired by a newer
  AppState transition

* Update source invariant test for concurrent stale-start cleanup

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-07-10 23:31:56 -07:00
NeilandOrca e33b2006f4 Remove stale max-lines lint disables from files under the limit (#7548)
110 files carried an eslint/oxlint-disable max-lines directive but are
already under the default max-lines budget (300 .ts / 400 .tsx / 600 .mjs
/ 800 test), so the suppression is dead. Removing it restores real
max-lines coverage on these files with zero behavior change.

Each removed directive had max-lines as its only rule; verified via a
full oxlint run (0 max-lines violations, 0 new errors). Diff is pure
deletions (200 lines, 0 additions) — no code touched.

Co-authored-by: Orca <help@stably.ai>
2026-07-06 02:12:32 -07:00
JinjingandOrca f6db7897d7 fix(mobile): import Buffer from 'buffer', not 'node:buffer'
The oxlint 1.71 upgrade (#6841) autofixed these imports to the node:
protocol, which Metro can't resolve in a React Native bundle, breaking
the Android release build ("Unable to resolve module node:buffer").
Revert to the npm 'buffer' polyfill and disable prefer-node-protocol for
the mobile package so the autofix can't reintroduce the regression.

Co-authored-by: Orca <help@stably.ai>
2026-06-30 01:15:56 -07:00
NeilandOrca 46646d7ff1 chore(lint): upgrade oxlint to 1.71 + enable 7 new rules (autofixed backlog) (#6841)
* chore(lint): upgrade oxlint to 1.71 and enable 7 new rules

Upgrade oxlint 1.67.0 -> 1.71.0 (1.72 was blocked by the repo's 3-day
minimum-release-age supply-chain guard; nothing here needs it). The
bump is a no-op on the existing config.

Enable 3 error rules (backlog autofixed to zero in this commit) and
4 warn rules (surface signal without gating CI):

error (autofixed, behavior-preserving):
- unicorn/prefer-node-protocol        (~1531 sites: bare builtin -> node:)
- typescript/no-import-type-side-effects (~36: all-inline-type -> import type)
- unicorn/no-array-reverse            (19: copy-then-reverse -> toReversed)

warn (real signal, current fires are test-only/correct):
- unicorn/no-array-fill-with-reference-type  (aliasing footgun guard)
- typescript/no-unsafe-function-type         (bans bare Function type)
- unicorn/prefer-array-flat-map              (map().flat() -> flatMap())
- unicorn/prefer-regexp-test                 (.match() in bool ctx -> .test())

mobile/.oxlintrc.json extends root, so it inherits all 7; the autofix
ran from root and covered mobile/ too.

Verification (all green): oxlint 0 errors (root+mobile+aux configs),
oxfmt clean, typecheck (node+cli+web), vitest 22795 passed / 0 failed,
builds (electron-vite + web + cli) succeed. node: rewrites confirmed to
skip embedded SSH/CLI string payloads (AST-only); all toReversed sites
verified to operate on fresh copies or write-once locals.

* chore(lint): bump mobile oxlint to 1.71 so inherited rules parse

mobile/ is a standalone pnpm project pinning its own oxlint@1.67, which
lacks unicorn/no-array-fill-with-reference-type (needs >=1.70). Since
mobile/.oxlintrc.json extends the root config, mobile CI's 'cd mobile &&
oxlint' failed to parse the new rule. Bump mobile to match root (1.71).

Verified in mobile/: oxlint 0 errors, oxfmt --check clean, tsc --noEmit
pass, vitest 978 passed / 0 failed.

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Orca <help@stably.ai>
2026-06-29 22:38:29 -07:00
Jinwoo HongandOrca e3bf7d8614 feat(mobile): pickers, workspace parity, active-workspace focus, tap-to-open, source-control parity, artifact viewing (#5330)
Co-authored-by: Orca <help@stably.ai>
2026-06-15 22:02:51 -07:00
Neil 49153d933f perf: cap mobile dictation audio backlog (#4078) 2026-05-31 03:33:00 -07:00
2c55de5589 Move mobile dictation ref mirrors out of effect (#3234)
* Move mobile dictation refs out of effect

* Guard mobile dictation option refs

Co-authored-by: Orca <help@stably.ai>

---------

Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
2026-05-30 19:19:17 -07:00
Neil 9b2c05fa77 Fix keyboard layout shortcut dispatch
Fix shortcut dispatch so app commands follow the produced logical key for the active keyboard layout, while preserving intentional physical-code fallbacks for terminal byte paths and unavailable logical keys.\n\nCloses #2858
2026-05-26 18:28:55 -07:00
Jinwoo HongandOrca 151040f05f Add desktop-backed mobile voice dictation (#1869)
Co-authored-by: Orca <help@stably.ai>
2026-05-14 14:36:44 -07:00