* build(mobile): upgrade to Expo SDK 58 and React Native 0.88
Expo 58 drops Zod from @expo/cli, which clears the last Zod 3 advisory
(GHSA-mrhx-c7xc-m3w5) in mobile along with its local patch and override.
- Expo 55 -> 58, React Native 0.83 -> 0.88, React 19.3, gesture-handler 3,
webview 14, reanimated 4.7, worklets 0.13 (SDK 58 bundled versions,
pinned below today's batch to respect minimumReleaseAge).
- Port the react-native and react-native-webview patches unchanged; drop
expo-constants, expo-notifications, @expo/cli, expo-router, zod and
query-string patches plus the zod/query-string/xcode>uuid overrides,
which upstream fixed or no longer need.
- iOS minimum rises to 16.4 (Expo 58 / RN 0.88 requirement).
- Migrate to RN 0.88 strict types: instance ref types, NamedStyles,
AppState.currentState, list header/footer nulls.
- Replace removed runtime APIs: InteractionManager -> idle callback with a
macrotask fallback; StyleSheet.absoluteFillObject -> absoluteFill;
FileHandle.readBytes -> readBytesSync (it became async).
- Resolve react-native/asset-registry for shared assets in Metro and alias
the old registry path for react-native-svg in the desktop mobile-web bundle.
- Reduce the iOS scene plugin to the reconnect override; Expo 58's template
now ships the scene delegate itself.
* fix(mobile): bridge react-native-svg web imports and libsodium runtime for RN 0.88
- Share react-native-svg web shims between the mobile-web build and its render
checks: map the old asset-registry path to react-native-web's registry and stub
the Android-only touch-sound TurboModule.
- Patch react-native-libsodium 1.7.0 to read the JSI runtime from the bridge proxy;
RN 0.88 removed RCTCxxBridge.runtime.
* fix(mobile): use Expo 58's legacy promise resolver for audio permissions
* fix(mobile): skip null handles in the RPC recording timer shims for RN 0.88 types
* style(mobile): format MobilePRSidebar after rebase
* fix(mobile): name RN 0.88 text input refs for declarations; allow queued back in stack render check
- Type text input refs with an exported interface so declaration emit can name hook results
(RN 0.88 aliases TextInputInstance to an unexported class).
- Expo Router 58 drains back() after a commit; check the interrupted push's exit from the
frame it starts, bounded to three frames of lag.
* chore(mobile): justify the text input handle interface for React Doctor
* chore(mobile): use a nameable intersection alias for text input refs
* fix(mobile): use sync expo-file-system writes, copies and moves on Expo 58
Expo 58 made File.write/copy/move and FileHandle.writeBytes return promises.
Our callers never awaited them, so failures escaped their try/catch and the
store's tmp-then-move and PDF writes could race their close or rename.
* build(mobile): raise the page bundle budget to 10 MiB for Expo 58
Expo 58 adds about 310 KB to the page: expo-router (+258 KB, now carrying
React Navigation, net about +110 KB) and Reanimated 4.7 (+152 KB). Main had
85 KB of headroom left. 10 MiB still stays within the 10 MiB per-asset contract.
* fix(mobile): drop the window-metrics seed RN 0.88 removed from Android
RN 0.88 no longer holds window metrics: DeviceInfoModule reads the activity's
WindowMetrics on demand and setWindowDisplayMetrics is gone, so MainActivity
no longer compiled. Layout scale still comes from the screen metrics we reseed.
---------
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
A keyboard's mic button switches to a separate voice IME, which closes the keyboard and opens the voice panel about 250 ms later. The page read every Android keyboard close as Back and blurred the field at once, so the voice IME's text had nowhere to go. Blur only once the keyboard stays closed for a second; a reopen within that window keeps focus.
* test: remove 60 low-value cases and orphaned conversion fixtures
* docs(ci): list supported Windows SSH host cells
* test: recognize direct Windows orcad server entry
---------
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
* fix(native-chat): answer Claude/Codex folder-trust dialog from a chat card
* fix(native-chat): show a chat card for Claude/Codex startup menus
* fix(native-chat): keep startup-menu cards holding Send; drop hand-typed identify retries
Startup-menu cards now hold the composer like the folder-trust card, so collapsing one can't free a Send whose Return would pick the highlighted choice.
The hand-typed agent probe retries and agentless hold are left out; Orca-launched panes already know their agent, and hand-typed native Claude identification predates this fix.
* fix(native-chat): read the whole screen for a tall startup dialog's heading
* fix(native-chat): drop the unreachable cwd prompt from startup-menu reasons
* fix(native-chat): show startup-menu warning text and give its choices no default
A startup-menu card now carries the dialog's body (Claude's bypass, API key, MCP and import warnings) under its heading, and its choices render as equals on desktop and mobile so Orca never nudges a consent choice. Long mobile option labels wrap inside their button.
---------
Co-authored-by: Kooooojun <edisonhuang1122@gmail.com>
* fix(mobile): show Loading for a new Tasks search instead of the previous search's rows
A new filter or search with no kept rows kept the same provider's rows on screen until the host's read landed, so a slow host looked like search did nothing. Only a re-read of the same list now stands on its rows; desktop already shows its load skeleton here.
* test(mobile): re-record Tasks list goldens for the new-filter spinner
* fix(mobile): hold Tasks paging while a new filter loads
* test(mobile): type the new-search spinner test's GitHub row fully
The phone's stale-resize filter took the binary scrollback frame's seq as
its layout high-water mark, but that seq counts output bytes, not layout
changes. A Desktop/Phone toggle on a terminal with little output then
looked older than the mark and was dropped, so the phone never resized
and kept showing the old mode. Seed the mark from the subscribed frame's
layout seq and leave scrollback out of it.
Co-authored-by: zhangxaochen <3416677+zhangxaochen@users.noreply.github.com>
* fix(native-chat): show session skill argument hints in the picker
Claude Code reports argument-hint on skill commands. The native chat skill row kept only the name and description, while built-in commands in the same picker still showed their hint.
* fix(native-chat): keep a skill's hint before Claude classifies its catalog
Before the first stream init, Claude lists skills as unclassified commands.
A scanned skill of the same name replaces that row and dropped its hint.
Fold the three hint tests into one shared-layer test and show a skill hint
in the picker fixture.
---------
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
* feat(mobile): pick the PR glyph from PR state
Workspace rows always drew the open-PR glyph and only changed its color,
and the PR tab's state badge had no glyph. Both now show merged, closed and
draft glyphs, from one prStateIcon mapping that the details sheet and task
rows also use.
* feat(mobile): show the PR state on the session header's source-control button
The button always drew a branch glyph. When the worktree's catalog row has a
linked PR it now draws that PR's state glyph in its state colour, read from
the host list's worktree.ps query in its own component.
* fix(mobile): read the header's PR state from the catalog cache only
Opening a session must not request worktree.ps before its first paint, so the
source-control button reads what the host list last loaded instead of
fetching it.
* feat(appearance): let app chrome follow the terminal theme
Add an "App Chrome Appearance" setting (Default / Match Terminal) next to
Left Sidebar Appearance. In match-terminal mode the terminal theme's
background/foreground are written as document-root CSS variables
(--bg-titlebar, --background/--card/--popover/..., both sidebar token
families), so the tab strip, status bar, side panels, full-page views and
popovers all follow the terminal instead of the app theme. Left-sidebar
modes still win because they scope their own variables below the root.
The terminal color pair and token derivation move into
terminal-surface-colors.ts and are shared with the sidebar resolver.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(status-bar): configurable usage format template
Add Settings → Appearance → Status Bar → "Usage format": a template that
replaces the built-in per-provider usage text when non-empty. Placeholders
cover {provider}, {plan}, the 5h/7d/fable/30d windows as percentages
(following Used/Remaining), {x.reset} countdowns, {x.resetAt} clock times
and Gemini {buckets}; "[...]" groups drop out when a placeholder inside is
empty so one template works across providers with different windows.
Whitespace is rendered as authored (whitespace-pre).
Persisted as PersistedUIState.statusBarUsageFormat with a byProvider
override map reserved for later; the RPC UI-update schema gains the
optional field.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(appearance): document touched functions; surface usage format in search
Add one-line JSDoc to every function this branch adds or edits so the
review docstring gate passes. Include the usage-format entry in the
Status Bar section's search match so searching "template" or
"placeholder" no longer hides the parent row, and mention popovers in
the App Chrome Appearance descriptions since the setting styles them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(appearance): let file editors follow the terminal theme in match-terminal mode
With App Chrome Appearance = Match Terminal, the tab strip, status bar and
side panels took the terminal palette but every file pane kept the stock app
theme: Monaco (code, plain text, diffs, notebooks, markdown source) was
hard-wired to `vs`/`vs-dark`, and the markdown preview / rich editor painted
the fixed `--editor-surface` with GitHub-colored hljs tokens.
- `terminal-editor-palette.ts` derives an editor palette from the active
terminal theme (background/foreground/cursor/selection + syntax roles mapped
onto the ANSI slots) and builds a Monaco theme (`orca-terminal`) from it;
light/dark is rated by the terminal background, so a light terminal theme
under a dark OS setting still gets light styling.
- match-terminal chrome variables now include `--editor-surface` and
`--syntax-*`; the hljs stylesheets read those ahead of their defaults.
- `useEditorSurfaceAppearance` / `useMonacoEditorTheme` replace the inline
`isDark ? 'vs-dark' : 'vs'` computations; the diff-section chain passes the
Monaco theme name instead of a dark flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99
(cherry picked from commit dc85fadee0a2664adbf55a49dd3c97c9b10fc111)
* fix(status-bar): honor the usage template in compact usage mode
ProviderSegment only rendered a user template on the verbose branch, so
switching usage mode to compact silently fell back to the built-in
tightest-window label. A non-empty template now replaces the built-in
text in both modes; the mini bar stays verbose-only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99
* docs(appearance): document remaining functions touched by the diff
Adds one-line JSDoc to the editor surfaces, diff viewers, palette helpers
and UI-slice entry points this branch modifies so the diff's docstring
coverage clears the pre-merge threshold.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99
* fix(editor): keep Monaco theme registration and preview clock out of render
The upgraded oxlint React rules flag reassigning a module variable during
render and calling Date.now() inside useMemo. Move the terminal Monaco
theme's signature cache into ensureTerminalMonacoTheme() and pin the
usage-format preview clock with a lazy useState initializer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VbWbChctXeMvaR2zdbFY99
* localization: complete Brazilian Portuguese catalogs
* fix(i18n): localize remaining hard-coded UI copy and complete Simplified Chinese coverage
Route the English literals and shared English labels that ignored the UI
language through the existing catalog: host labels, plugin cards and consent,
CLI and SSH errors, the checks pill, browser profile labels, shortcut groups,
app and context menus, and the macOS computer-use permission window. Shared
labels are translated where they render, so src/shared stays English for
mobile, CLI and older paired hosts.
- en.json gains 314 keys bootstrapped from inline fallbacks; four duplicate
"Unassigned" keys collapse into translateUnassignedLabel()
- zh gains 337 entries and refreshes existing ones; the other nine locales get
the newly extracted keys
- joinSentences ends a CJK sentence that has no final stop with 。 before the
next one
- the desktop caller passes the computer-use helper its locale; orcad and the
CLI stay Electron-free
- three files the copy pushed past max-lines each shed a focused module
* test: expect labeled roles in the editable context menu
The edit menu now passes explicit Cut, Copy and Select All labels so the roles render in the UI language; the upstream template assertion still expected bare roles.
* fix(i18n): key translated memos on the UI language without bare void reads
Upstream's React Compiler ratchet rejects `void language;`, which the compiler drops, and treats a react-hooks lint suppression as a bailout. The two host-label hooks now pass the language through readUiLanguageMemoInput so it stays a real memo input. ContextualTourOverlay drops its language key: getContextualTour is a static lookup, and step copy is localized at render.
* fix(i18n): translate editor theme settings
* Fix reactive localization and catalog extraction
* Fix combined localization validation
* Localize nested import failures and refine catalogs
* Handle older nested import responses
* Fix localized merge prompts and quota windows
* Address localization and runtime review feedback
* Keep host search and configuration examples usable
* Preserve configured names in add-project host selector
* Preserve host label origins across views
* Use localized fallback for missing local host
* Preserve custom names and refresh localized host labels
* Refresh task host labels without repeating searches
* Preserve Portuguese mobile tab translations
* Address localization review feedback
* fix(status-bar): import window visibility interval from its new path (#40951)
---------
Co-authored-by: lisi <lisi.see@bytedance.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: marlico77 <marlonssoficial@gmail.com>
Co-authored-by: x-Ai <5061489+x-Ai@users.noreply.github.com>
Co-authored-by: Kelvin Amoaba <97001695+AmoabaKelvin@users.noreply.github.com>
Reverts #40592 (12e809c755). The session bar goes back to the scrolling strip of tab cells, the + menu goes back to the action sheet, and the header subtitle shows the tab count again.
* Show Source Control menu rows on one line with a short status
* Keep Push and Force Push clickable; force push shows remote-only commits it replaces
* Match Force Push description to remote-only commits; list review blockers exhaustively
* Show short statuses for every blocked review action
* fix(mobile): tell Android users which WebView to update when it is too old
The page shell needs androidx's DOCUMENT_START_SCRIPT:1, which stable
WebView only reports from Chromium 101; the comments claimed 83/88.
Name the required WebView and the one installed, and how to switch it.
* fix(mobile): read the WebView provider through the shell module index
Tests stub the module index; a direct file import loaded expo-modules-core unstubbed.
* fix(mobile): save the downloaded desktop page on Android 7
Below API 26, expo-file-system 55 moves a directory with File.copyTo, which
creates an empty directory, so committing a downloaded page build always
failed with cache-write-failed. Copy the tree recursively and delete the
source there instead.
* fix(mobile): remove a partial copy when an Android 7 page move fails
* Show phone option preview thumbnails with a full-height viewer
* Use typed renderer host queries in preview interaction coverage
* Register phone preview viewer labels in the mobile catalog
* Keep phone preview thumbnails within the compact frame
* Count supplementary wide characters in phone option previews
* Keep the readable option preview subscribed to theme changes
* Correct mobile preview test typing and positional page identity
* Explain the immutable answer identity used to reset preview scrolling
* Preserve native preview text and measure thumbnail bounds
* fix(mobile): measure preview text at its intrinsic web width
* chore(mobile): document the web-only intrinsic width boundary
* feat(mobile): show the open tab as one pill with a tabs sheet
The phone copied desktop's tab strip, which fits about three tabs cut to
~95 pt and hides a tab that needs you behind an edge dot. The bar now shows
only the tab you're in, at full width, with the tab count. Tapping it opens
a sheet of every tab grouped by what needs you, with each tab's state and
last activity; swiping it steps to the next tab. The + sheet shows agents as
a grid above Terminal, Browser and Markdown note, and the header names the
branch instead of the tab count.
* feat(mobile): pair the tab count with + and open tab actions from the pill
The count and its chevron inside the pill read like a menu and hid the
"another tab needs you" dot. The count now shares a capsule with +, the
way phone browsers put the tab-count button beside new tab, and tapping
the pill opens the tab's own actions.
* feat(mobile): give the tab count its own button beside +
The shared capsule made each half a small target. The count is now a
round nav button like +, lined up under the header's buttons.
* feat(mobile): draw the tab bar as the strip's square cells
The rounded pill and round buttons read as a different control from the
strip people know. The open tab is now the strip's raised, underlined cell
from the screen edge, with the count and + as square cells in the same
row, which also gives them 46x44 pt targets.
* fix(mobile): keep a hairline after the tab bar's last cell in the top bar
* refactor: finish terminal and Mobile defining-owner imports
* fix: retain completion coordinator type binding
* refactor: consolidate direct terminal tree imports
* refactor(renderer): import typography from defining owners
* refactor(mobile): group host catalog credentials descriptors and connection history
* refactor(mobile): import RPC sender and result types from defining owners
* refactor(mobile): colocate push delivery with registration operations
* refactor(mobile): point push recordings at delivery owner
* fix(i18n): update permission and mobile task translations
* fix(i18n): retain community Portuguese pagination copy
Adopt the matching translations from #39124, also carried by #40456.
Co-authored-by: marlico77 <marlonssoficial@gmail.com>
---------
Co-authored-by: marlico77 <marlonssoficial@gmail.com>