Skip to content

[Feature]: iPhone Duo support (needs an Xcode 27.1 build and the scene life cycle; layout work paused) #145

Open

Description

@wmcparla

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:

  1. A scene life cycle config plugin (plugins/ios-scene-lifecycle), off unless IOS_SCENE_LIFECYCLE=1 is 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).
  2. The release build on Xcode 27.1 (GitHub's xcode-27 runner) 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.
  3. 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 mailLayoutFor gives one pane there: a 320 pt list leaves 349 pt, under READING_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.

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-27 runner, 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-duo on 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

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions