Repository navigation
Open
Description
Problem / Motivation
The app does not lay itself out for the iPhone Duo. The TestFlight builds are made with Xcode 26.6 (the 0.1.94 run), and iOS shows an app built with that SDK at a reduced size: on the outer display it is an inset card beside the status column instead of the whole screen.
Building with Xcode 27.1, which has the Duo's SDK, is not a one-line change either. The unchanged project dies at launch on iOS 27:
Application failed to launch: UIScene life cycle is required for apps built with this SDK.
Expo ships a scene delegate only from SDK 57.0.23, and the app is on SDK 54.
Proposed Solution
In steps, the first of which is draft PR #146:
- A scene life cycle config plugin (
plugins/ios-scene-lifecycle), off unlessIOS_SCENE_LIFECYCLE=1is set at prebuild, so today's builds do not change. With it an Xcode 27.1 build on Expo 54 starts on the Duo simulator and fills the outer display (right-hand screenshot below). - The release build on Xcode 27.1 (GitHub's
xcode-27runner) with the plugin on. That is your call and wants a TestFlight round first: links that start the app (mailto, webmail pairing) and push have not been run under scenes. - Layout, following Apple's Designing for iPhone Duo:
- Inner display upright (669 pt wide): list and message side by side, as Apple's Mail does. Today
mailLayoutForgives one pane there: a 320 pt list leaves 349 pt, underREADING_PANE_MIN(360). - Bars on the side: on the outer display, and on the inner one in landscape, iOS moves tab bars and toolbars to the trailing edge. It does that for UIKit bars only; the app draws its own, so it needs a side layout of its tab bar and headers there.
- The fold and the cameras: content should keep clear of the fold when the phone is half open. iOS 27.1 reports these as reserved regions, which React Native does not pass on; a small native module would.
- The same state on both displays: an open message stays open when the phone is opened or closed.
- Inner display upright (669 pt wide): list and message side by side, as Apple's Mail does. Today
Alternatives Considered
- Upgrading Expo to 57 or later first: it brings the scene delegate, but it is three major versions and a new React Native. The plugin gets a Duo build without it and can go once the app is on such an SDK.
- Leaving the app in the reduced size: it works, but it wastes the outer display and never gets the two-pane inner layout.
Feature Area
Mobile / Responsive
Mockups / Examples
The outer display of the iPhone Duo simulator (iOS 27.1). Left: main built with Xcode 26.6, as released. Right: the same code built with Xcode 27.1 and the plugin.
Additional Context
- Status: unfinished and paused. Step 1 is as far as this got. The Duo simulator exists only in Xcode 27.1 on Apple silicon; I ran it on GitHub's
xcode-27runner, where it starts closed, and the command-line tools have no way to open, fold or rotate it (those controls are in Xcode's Device Hub window). So the inner display has not been seen at all, and step 3 is written from the code and Apple's page, not from a device. It picks up again when the simulator can be driven from a script, or with access to an Apple silicon Mac or a Duo. - Measured on the simulator: outer display 466 x 678 pt, inner display 669 x 951 pt, both @3x.
- Seen so far: the sign-in screen only, device closed, no account signed in.
- To reproduce: the branch
spike/iphone-duoon my fork has the workflow and script that build the three variants and photograph them (.github/workflows/duo-spike.yml,scripts/duo/probe.sh). They are not part of the PR. - The plugin follows the workaround in [iOS 27][Xcode 27] Working SceneDelegate workaround for the UIScene launch crash (#46664 is locked) expo/expo#50179.
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
No labels

Activity