Applies the HealthChat product identity through the fork seams upstream already
provides, so no upstream logic files are touched and merges stay clean.
- Variants/HealthChat/healthchat.yml holds the identity scalars (display name,
bundle id ch.healthchat.element, app group, development team) and is included
permanently from project.yml. APP_NAME stays ElementX so the module name and
@testable import ElementX keep working.
- ElementX/Sources/AppHooks/HealthChat/ registers an AppSettings hook pinning
accountProviders to healthchat.ch with other providers disabled, push through
sygnal.healthchat.ch and a custom-scheme OIDC redirect; plus a Compound hook
recolouring the accent token family to the HealthChat blue.
- Entitlements are edited directly in ElementX/SupportingFiles/target.yml rather
than in the variant, because XcodeGen concatenates arrays on include-merge and
a variant can override scalars but cannot remove array entries. Drops the
Element Classic app group and keychain group, and narrows associated domains
to app.healthchat.ch, keeping matrix.to for permalinks.
- Info.plist CFBundleName now follows APP_DISPLAY_NAME — it, not
CFBundleDisplayName, is what the web authentication sign-in alert shows.
- App logo and app icon assets swapped in place; the onboarding welcome title
moves to a new screen_onboarding_welcome_title_ios untranslated string.
Add the element-call-ios dependency and a developer option for native calls
The package carries the call UI and the matrix-rust-rtc media stack, pinned by
exact version the way the SDK is, with the local path kept commented out for
working against a checkout. Its media xcframework has no Intel simulator slice
and a package cannot say so for the projects that consume it, hence the
excluded architecture at the project level.
The developer option is off by default and nothing reads it yet. It is placed
next to the Element Call URL override, which only applies to the web view that
native calls replace.
Continue grouping the standalone modules under Components. Updates the
preview asset paths and the media resource references in the app and unit
test targets.
Continue grouping the standalone modules under Components. Updates the
Secrets.swift references in the app, NSE and Share Extension targets along
with the SwiftLint, SwiftFormat, gitignore, post-checkout hook and forking
documentation paths.
MapLibre ships as a dynamic framework, so being named in the app's load
commands means dyld loads it before main runs on every launch: 7.3 MB paged in,
133 C++ static initialisers run and its classes registered, all for a map that
only appears once a location screen is opened.
Measured on an iPhone 17 Pro with two otherwise identical probe apps launched
alternately, linking MapLibre takes pre-main from 11.1 ms to 23.2 ms, and on a
cold launch from 32.9 ms to 60.7 ms. Loading it on demand brings pre-main back
to the 11.1 ms baseline and moves the roughly 11 ms it costs to dlopen to the
moment the map first appears.
MapLibreShim is now embedded but not linked, and the app resolves the shim
through the ObjC runtime after dlopen-ing it. MapLibre stays in the bundle as
an embed-only framework reference so the shim's load command can resolve
against it, expressed as an implicit framework because xcodegen can't describe
embed-without-link for a package product.
Timeline location messages already use the static tile view, which never
touched MapLibre, so the shim only loads for interactive maps.
Second step towards loading MapLibre on demand: everything that touches it now
lives in one framework, so that framework can later be left unlinked.
The interactive map view, its annotation view and the coordinate animator move
into MapLibreShim, which reaches the app through MapLibreShimProtocol. The app
side keeps its MapLibreMapView call site and becomes a thin wrapper that builds
a MapViewConfiguration, passing the app-only pieces (map style URLs, marker
views, tint colour) across as closures so the shim needs nothing from the app.
LocationAnnotation loses its MapLibre conformance and becomes a plain struct,
with the shim mapping it onto its own annotation type. MapLibre's log
forwarding moves into the shim as well, since TargetConfiguration can no longer
reach it.
Groundwork for loading MapLibre on demand. The map view is about to move into
its own framework, and both sides need to agree on the types that cross the
boundary, so ShowUserLocationMode and MapLibreError move out of the app into a
small framework that the app links.
* Allow the AppIconBanner tool to be called with purely the build number.
And use that for the Element Pro Nightly.
* Use a build setting to determine Nightly builds.
* Enable Swift 6.2 with default main actor isolation for the app target
Turn on SWIFT_VERSION 6.2, SWIFT_APPROACHABLE_CONCURRENCY and SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor for the ElementX target, matching the NSE and Share Extension (which already use 6.2 without the main actor default).
# Conflicts:
# ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
* Update the code generation templates for Swift 6
Emit nonisolated/@unchecked Sendable mocks and nonisolated string enums, and mark async mock methods @concurrent so they keep suspending like the real implementations (otherwise intermediate states are unobservable in tests). Includes the regenerated mocks and strings.
# Conflicts:
# ElementX/Sources/Mocks/Generated/GeneratedMocks.swift
* Make the data layer and services nonisolated and Sendable
Annotate the value-type models, Rust SDK proxy wrappers, timeline item graph, settings, logging and NSE-shared types as nonisolated, and conform the service protocols to Sendable so their existentials can cross isolation boundaries. These types run off the main actor and no longer inherit the target's default main actor isolation.
* Adopt the new isolation across call sites, mocks and signatures
Update call sites, closure signatures and mock configuration helpers to match the nonisolated/Sendable data layer, including the main actor isolated mock inits and the @Sendable filter on recentlyVisitedRooms.
^ Conflicts:
^ ElementX/Sources/Services/SecureBackup/SecureBackupController.swift
* Remove redundant @MainActor annotations
With the app target defaulting to main actor isolation, the explicit @MainActor on view models, coordinators, views and their protocols is no longer required.
* Fix concurrency hotspots surfaced by the migration
Resolve the room summary main-thread deadlock by moving diff processing onto AsyncStreams, add the SDKListener.onMainActor FIFO bridge for SDK callbacks, hop KVO/timer/UIKit callbacks to the main actor via assumeIsolated, add isolated deinits, and apply the few justified nonisolated(unsafe) escapes for queue-confined Apple APIs.
* Fix the unit tests for Swift 6 concurrency
Hop the waitForConfirmation body onto the caller's actor (Swift Testing runs confirmation closures off-actor), and adjust the affected suites and async signatures.
* offload diffs on concurrent threads instead of main actor
* make room info protocols sendable
* use a task group for fetching data so that everything runs concurrently in the TextRoomTimelineView when getting the preview.
* use the generic onMainActor implementation, which already makes a stream and send the continuation on the main actor.
* small pr comments issues being addressed
* update enterprise
* Update StaticCode to 1.1.0 and specify the required Swift isolation.
* fix ElementCallServiceTests
* update enterprise
* re-generate mocks
* update enterprise
* enterprise new code conformed to swift 6
---------
Co-authored-by: Doug <douglase@element.io>
* Remove support for handling SPA call links.
They were a stop-gap solution whilst we were building support for embedded room calling.
* Simplify ElementCallConfiguration now that there is only 1 type of call to handle.
* Remove the unused overlayModule from NavigationRoomCoordinator.
* Read and import the secrets from ClassicAppAccounts.
* Record snapshots.
* Add some documentation, tidy up tests and fix the dismissal of the backup instructions.
* Workaround flakey tests (the fulfilments weren't always firing).
* Allow a custom Classic App deep link URL to be configured.
Once the app starts the WindowManager is configured with SwiftUI's environment OpenWindowAction. It can then be used to register coordinators (that provide the toPresentable view) and an optional flow coordinator (as most of the screens are part of a flow, especially rooms).
Once a coordinator is registed, the WindowManager invokes the OpenWindowAction which in turn makes the Application call its newly introduced WindowManagerWindowType WindowGroup's block to instantiate a new visual window rooting that view.
The WindowManager is also responsible for wrapping the presentable in a disappearance block and clean up the coordinator stack.
# Conflicts:
# ElementX/Sources/Application/AppCoordinator.swift
* improved defer fullfillment
* applied also for async streams
* fix xcodeproject
* better documentation
* restict deferFulfillment only for Publisher which can never fail
* Add an initial implementation of the receivedWhileOfflineNotification.
* Only deliver a single receivedWhileOffline notification per boot and clarify the API.
* Add a 15-minute threshold for the receiveWhileOfflineNotification.
* Remove `eraseToStream` now that `any AsyncSequence` is available to us.
* Remove the now unnecessary backport of Mutex.
* Silence a couple more deprecation warnings.
* Listen to call decline to stop ringing when declined from other device
* MSC4075 Use expirationTS to define the call ringing window
* Implement ElementCallService tests.
* Update acknowledgements.