Skip to content

feat(mobile): preview native iPhone Duo workspace - #12557

Draft
juliusmarminge wants to merge 9 commits into
mobile/sdk58-upgradefrom
build-iphone-duo-app
Draft

juliusmarminge wants to merge 9 commits into
mobile/sdk58-upgradefrom
build-iphone-duo-app

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Sep 19, 2026 •

Copy link
Copy Markdown
Member

T3 Code's existing Expo app now runs with a native iPhone Duo workspace: a thread sidebar beside the conversation on the inner display, compact navigation on the outer display, and system toolbar placement that follows the available space.

This is a draft progress snapshot, not ready to ship. It is based on the Expo SDK 58 / React Native 0.88 upgrade in #12045. The current base uses Expo 58.0.0-preview.3 and React Native 0.88.0-rc.0. Expect the Expo integration, dependency versions, and temporary native patches to change before release.

Current behavior

  • Uses UIKit split columns for the sidebar, conversation, and inspector. Both main columns stay mounted when the layout collapses.
  • Keeps the sidebar trigger in the content header and the compact T3 Code / connection header in the sidebar.
  • Uses native toolbar groups, search placement, and overflow menus. Terminal, Git, and files remain available as the toolbar compresses.
  • Animates the sidebar with the chat's theme background and clips the content during the native column transition to keep markdown and the composer out of the toolbar.
  • Reads live native column geometry, safe-area insets, and active fold / occlusion regions for the composer and content layout.
  • Insets folded thread lists and sheet bodies around the native toolbar. Fixes duplicate compact Back controls and the filter menu requesting a software keyboard.

Where the native changes live

Layer Changes
react-native-screens@4.27.0 patch Extends native header item groups, axis preferences, pinned actions, and toolbar search placement. Adapts the experimental split controllers for iPhone, compact navigation ownership, bar refreshes, and column transition clipping.
@react-navigation/native-stack@7.17.6 patch Passes the native search-placement item through its toolbar adapter and exposes axis / pinned item options.
App-local t3-native-controls Reports UIKit size classes, vertical bar edge, safe areas, and active reserved regions. Keeps the hardware-shortcut responder from requesting a software keyboard.
Expo config and app layout Enables the screens experimental split implementation with RNS_GAMMA_ENABLED, supports rotation, and connects native columns / geometry to the existing app.
App-local markdown view Resizes its TextKit view during native layout so pane expansion does not leave text clipped to its previous drawing width.

Duo-specific APIs have compiler / availability guards. This remains the same Expo application, with the existing layout path retained where native workspace columns are unavailable. This branch does not yet migrate to react-native-screens v5.

The layout follows Apple's iPhone Duo design guide: adapt through native containers and available geometry while maintaining the same information hierarchy and task state.

Verification so far

  • Xcode simulator build passed, installed on iPhone Duo / iOS 27.1.
  • Mobile TypeScript check passed.
  • 47 focused layout / reserved-region tests passed.
  • Exercised unfolded sidebar toggles, background and toolbar clipping, folded Back navigation, search and filtering, sheet content insets, filter submenus, and composer keyboard focus.
  • The existing draft was retained through the tested transitions.

This publishes the current work without the full audit / readiness loop. Prior React Doctor runs reported existing findings; they have not been resolved as part of this snapshot.

Remaining work

  • Complete the portrait, tabletop, and system Split View matrix, including T3 Code on either side of another app.
  • Continue checking live geometry through fold / unfold and rotation without reloads.
  • Investigate the first keyboard-focus scroll jump in long conversations.
  • Revisit temporary screens / navigation patches against react-native-screens v5 and upcoming Expo support.
  • Verify iPad, ordinary iPhone, and Android behavior before shipping.
  • Add full Device Hub captures and transition recordings. Baseline comparison evidence is still pending.
  • Run the full review and release checks once the implementation and dependencies settle.

Progress captures

Unfolded

CleanShot 2026-09-19 at 00 29 15@2x

Partially folded

CleanShot 2026-09-19 at 00 29 26@2x

Folded

CleanShot 2026-09-19 at 00 29 47@2x CleanShot 2026-09-19 at 00 29 31@2x

Multi-tasking

CleanShot 2026-09-19 at 00 30 25@2x CleanShot 2026-09-19 at 00 30 29@2x

Model: GPT-6. Harness: Codex.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). 📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. labels Sep 19, 2026
@github-actions

github-actions Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 13.5 KiB — 15.1 KiB ✅
Codex Thread snapshot wire — 7.1 KiB — 7.3 KiB ✅
Codex Live turn WebSocket wire — 6.4 KiB — 7.8 KiB ✅
Codex Live turn WebSocket decoded — 56.2 KiB — 66.4 KiB ✅
Codex Live turn messages — 9 — 21 ✅
Claude Total thread wire — 13.5 KiB — 15.1 KiB ✅
Claude Thread snapshot wire — 7.1 KiB — 7.3 KiB ✅
Claude Live turn WebSocket wire — 6.4 KiB — 7.8 KiB ✅
Claude Live turn WebSocket decoded — 57.0 KiB — 66.4 KiB ✅
Claude Live turn messages — 9 — 21 ✅

Baseline: unavailable · PR result: 7506cb8 · Source CI: failure

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.9 KiB
  • Claude decoded thread snapshot: 114.7 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

juliusmarminge and others added 9 commits September 19, 2026 00:16
Bump every Expo package to the SDK 58 line (expo@58.0.0-preview.2,
react-native@0.88.0-rc.0, gesture-handler 3.x, reanimated 4.6, screens 4.27)
and absorb the breaking changes:

- iOS scene lifecycle: the SDK 58 prebuild template now generates
  SceneDelegate.swift and the scene manifest itself, so the custom
  withIosSceneLifecycle plugin (and its regex surgery on AppDelegate) is
  deleted. Expo forwards URL, user-activity, and quick-action events to the
  app delegate under the scene lifecycle.
- React Native strict TypeScript API: host-component refs use the new
  ViewInstance/TextInstance/TextInputInstance types, the codegen specs import
  codegenNativeComponent and CodegenTypes from the react-native root, and the
  removed StatusBar `translucent` prop is dropped. expo-blur and
  expo-glass-effect still type refs as Ref<View>, so both get a types-only
  pnpm patch until upstream adopts ViewInstance.
- expo-file-system: File.write, readBytes and writeBytes are async; call
  sites await them so the atomic rename and upload ordering hold.
- expo-notifications now shows foreground notifications by default. A
  notification handler suppresses the banner only when it targets the thread
  already on screen and lets everything else through.
- gesture-handler 3.x: ReanimatedSwipeable's simultaneousWithExternalGesture
  became simultaneousWith and dragOffsetFromRightEdge became
  dragOffsetFromRight, with Gesture.Native() swapped for useNativeGesture.
- Patches re-targeted to the new versions (metro-config source-map sanitizer,
  gesture-handler swipeable extensions, screens header bar items, expo-audio
  recorder error state, expo-sharing Android originalName, expo-widgets
  Live Activity environment). The reanimated layout-animation backport is
  upstream in 4.6.0 and its patch is removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…arkdown module

React Native 0.88 ships React-Core prebuilt, so quoted header imports no longer
resolve. The unused RCTBridge import is dropped and the Fabric plugin header is
imported through <React/...> like every other Fabric component.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… patch

React Native 0.88 ships React-Core prebuilt, so @react-native-menu/menu's
quoted RCTBridge.h import no longer resolves. Fold the fix into the existing
menu patch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two patches for third-party packages that AGP 9 exposes:

- expo-widgets resolves its layout registry script through a pnpm symlink,
  so the "am I the main module" path check never matched and the registry
  resource was silently skipped; comparing real paths lets it run.
- @clerk/expo imports LocalSavedStateRegistryOwner and the Compose
  LocalLifecycleOwner but only got those artifacts transitively through
  navigation3; AGP 9 no longer leaks runtime constraints onto the compile
  classpath, so the module declares them itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
expo 58 depends on the noxcturnal Rust transformer and its platform
binaries even when the experiment is off. The packages declare MIT but ship
no license file, which fails strict third-party license generation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

📱 Native Change Changes the native fingerprint; merging blocks production OTAs until a new store build ships. size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant