iOS
iOS packages the shared Angular renderer in a Capacitor WebView. Building or launching the native project requires macOS and Xcode; device work can also require signing.
Synchronize and open
Section titled “Synchronize and open”pnpm ios:syncpnpm ios:openpnpm ios:runSynchronization builds the shared production renderer, copies www/, and refreshes native plugin wiring. Review generated project changes when plugin or Capacitor configuration changes.
Validate the host
Section titled “Validate the host”pnpm ios:verifypnpm nx run trinity-ios:verify-nativepnpm nx run trinity-ios:test-pushpnpm ios:buildThe static verifier checks shared host contracts on any supported development machine. verify-native performs an unsigned simulator build and requires macOS and Xcode. A successful unsigned simulator build does not prove device signing, App Store packaging, notification delivery, Keychain behavior on a device, or production lifecycle.
Run the installed-app suite
Section titled “Run the installed-app suite”TRINITY_E2E_HOMESERVER=synapse TRINITY_E2E_HOMESERVER_RUNTIME=native TRINITY_E2E_SSO_PROVIDER=mock pnpm e2e:mobile:iosThe WebdriverIO and Appium suite drives the simulator build through the XCUITest driver. It needs macOS, Xcode, the pinned iOS Simulator runtime, caddy on PATH, and a Python 3 new enough for the pinned Synapse (the system Python 3.9 is too old); Synapse runs from a venv instead of Docker, without a second homeserver; with dex on PATH and TRINITY_E2E_SSO_PROVIDER=mock, the SSO spec signs in through Dex’s form-free mock connector, and skips otherwise. Read desktop and native tests for what simulator evidence does and does not prove.
Push extension and configuration
Section titled “Push extension and configuration”The Xcode project has two targets: App and the NotificationService app extension (dev.trinityproject.trinity.NotificationService), which renders push notifications while Trinity is closed. The extension links the TrinityPush Swift package in libs/native/capacitor-push/ios/TrinityPush; the app reaches it through the PushHandoff plugin, the Swift package TrinityCapacitorPush that synchronization adds to CapApp-SPM from the workspace package @trinity/capacitor-push. Run the TrinityPush tests with pnpm nx run trinity-ios:test-push; it runs swift test and precedes the native builds in verify-native and CI’s prebuilt build. The targets share the app group group.dev.trinityproject.trinity and a keychain access group, declared in App/App.entitlements and NotificationService/NotificationService.entitlements together with the push capability.
Debug and Release builds both sign with those entitlements, so a free personal team cannot sign the app: running on a device needs a paid team with both App IDs (dev.trinityproject.trinity and dev.trinityproject.trinity.NotificationService) registered for Push Notifications, App Groups and Keychain Sharing. The installed-app suite signs its simulator build with App/App.e2e.entitlements (push environment included) instead.
Firebase Messaging is a Swift package of the App target, pinned to 12.17.0, the last release whose FCM-token API is not deprecated; FirebaseAppDelegateProxyEnabled is NO because AppDelegate forwards the APNs token itself. Push on a device needs a git-ignored ios/App/App/GoogleService-Info.plist; the file is optional for building. Without it the app reports the APNs token, which the Trinity gateway does not accept, so no push arrives. The Firebase, APNs key and App ID setup is tracked in #1152.
The installed-app suite cannot show the extension launching: the Simulator does not start notification service extensions for simulated pushes. push-render-ios.e2e.mts drives the same rendering path through a debug-only probe in the app. It also stores an already expired token through the plugin and checks that the push reads “Open Trinity to read this message” without any read. A real FCM token, the extension on a device, locked-phone rendering, closed-app delivery and tap-to-open need a physical device.
Respect native ownership
Section titled “Respect native ownership”Keep plugin access in libs/platform-native adapters and local plugin packages such as @trinity/capacitor-push, and consume shared host operations from application code. Test safe areas, keyboard resizing, system browser authentication, deep links, lifecycle, secure storage, notification activation, and Back behavior in the environment whose behavior changed.
Record iOS checks as unavailable when the required Apple environment is missing. Read host capabilities and desktop and native tests.
App icons and splash screens are generated from shared sources; see application icons.