--- type: work-item project: fidelity status: in-progress ticket: PDIAP-12284 title: "Remove UIKit wrapping from XFlow" systems: [xflowsdk, xflowviewmaker] workstreams: [xflow-swiftui-migration, consumer-integration] people: [jeff-dewitte] related: [pdiap-15836, pdiap-15838] updated: 2026-05-14 tags: - work-item - fidelity - swiftui - xflow --- # PDIAP-12284 - Remove UIKit wrapping from XFlow ## Status - Reopened after rollback and moved to In Progress on May 12. - Jeff directed David to do this UIKit-removal work and `PDIAP-15836` dismissal/lifecycle work in the same branch because both are disruptive enough to require consumer testing. - Current implementation direction is to avoid Fid4-owned per-flow host-mode mapping and evaluate XFlowViewMaker-owned global host-mode resolution. - David continued the implementation/validation loop on May 11; current simulator log review is promising for the SwiftUI-host dismissal sequencing in the tested run. - Jeff confirmed on May 11 that the feature flag strategy (host-mode resolution centralized in XFlowViewMaker) should be implemented as part of this branch's work. - May 12 implementation pass resolved several earlier concerns: host-mode API appears branch-local/new, enum cases were renamed to neutral `swiftUIHost` / `uiKitHost`, the final flag key is `iOS-XflowUIKitHostEnabled`, missing/false/unavailable flag values default to SwiftUI, and `AnyView` was removed from `buildFlow` internals while remaining only at the existing public `FlowViewMaker` boundary. - Current validation blocker appears to be dependency alignment rather than host-mode code correctness: XFlowViewMaker is resolving `XFlowSDK 2.8.48` from its podspec, which does not expose the new host-mode API needed by the branch. - After manual dependency/build handling, Fid4 now compiles with the latest `FlowViewBuilder` shape. Next validation should be runtime evidence: first verify a representative flow selects the default SwiftUI host path, then simulate/force `iOS-XflowUIKitHostEnabled == true` to verify the temporary UIKit host path and dismissal behavior. - Quy confirmed on May 13 that this story and `PDIAP-15836` can both remain In Progress together, so no immediate Jira restructuring is required. - May 13 AccountLink runtime validation looks good in both host modes. The SwiftUI-default path and forced UIKit-host path selected the expected branch and preserved dismissal sequencing; no AccountLink issue was observed in either mode during these runs. - Before push, cleanup should remove temporary `XFlow-DISMISS-DEBUG` prints and consider moving dismissal-specific helper types out of `XFlowManager.swift` into a dedicated dismissal file. - Follow-up SampleApp validation found a likely host-mode mismatch regression introduced by the branch: `initialViewController(...)` still represents the UIKit presentation path, but manager state could remain on SwiftUI host mode and route `endActivity` through the SwiftUI dismissal subject without an active `XFlowDismissalHost`. The minimal fix should preserve existing behavior by forcing/setting UIKit host mode for `initialViewController(...)` and SwiftUI host mode for `makeInitialFlowView(...)`. - SampleApp should be updated to support explicit validation of both UIKit-host and SwiftUI-host modes. The SDK should choose the appropriate dismissal mechanism from the active integration path, not from stale/default host-mode state. - May 14 SampleApp iteration updated the sample to exercise both host scenarios explicitly: UIKit-host through `initialViewController(...)` and SwiftUI-host through `makeInitialFlowView(...)`, selected by the existing `Use SwiftUI` / feature-toggle path. XFlowSDK entrypoints should prepare their own matching dismissal mechanism so `endActivity` cannot route to the SwiftUI subject unless the SwiftUI host is actually active. - The SampleApp SwiftUI-host rendering was refined to avoid storing `AnyView` in state; SwiftUI-host content now lives behind a `ViewBuilder` / `flowContent` rendering path. This keeps local SampleApp code aligned with the branch goal of avoiding unnecessary `AnyView`, while preserving type erasure only at true public boundaries such as the existing XFlowViewMaker boundary if still required. - Jeff recommended expanding validation before review: test as many current Fid4 XFlow entry and dismissal points as possible in both default SwiftUI-host and forced UIKit-host modes, with particular attention to AO flows. Use the prior Confluence entry-point list as a starting point, but verify it against current code and temporary runtime logs before treating it as complete. - May 20 status: validation sessions 004 and 005 confirmed SwiftUI-host load, dismissal, and delegate cleanup for HybridBrokerageAccountOpening and accountlink, but HybridYouthAccountOpening needs complete dismissal coverage. Gaps remain in AO deep-link coverage, launch wrappers, common-launch, HybridBloomAccountOpening, and explicit UIKit-host validation. Plan to open a draft PR today while continuing validation. --- ## Context - This is the original story for removing the UIKit wrapping. - Current relationship to track: `PDIAP-12284` should be handled with `PDIAP-15836` in the same implementation branch. David identified a possible minimal `PDIAP-15836` fix path that does not require removing `UIHostingController`, but Jeff prefers combined branch work because both changes require consumer testing. - Desired host-mode model: SwiftUI host is the default, missing or unknown feature configuration should also default to SwiftUI, and `UIHostingController` should remain only as an explicit temporary fallback while consumers validate the migration. - XFlowSDK should not be coupled directly to LaunchDarkly, Flagship, or app-specific feature-flag clients; it should receive an already-resolved host-mode decision. - If `hostMode` must be passed through `FlowConfig` or a similar object, keep it as adapter/internal plumbing rather than a new consumer-facing per-flow responsibility. - The latest tested run reported the expected dismissal order for the SwiftUI-host path, but the branch still needs review of the shared host-mode routing and any required broader validation before story closure. - Resolved implementation-shape decisions from the May 12 pass: keep two host-mode enum types to preserve the boundary where XFlowViewMaker owns host-selection policy and XFlowSDK owns presentation mechanics, keep the single conversion point in `FlowViewBuilder`, use neutral enum names, and keep SwiftUI as default unless `iOS-XflowUIKitHostEnabled` is explicitly true. - SampleApp-specific rendering should not reintroduce `AnyView` just to switch between validation paths. Prefer view-builder composition plus state that represents the selected host path, plugins, and controller. - Fid4 validation for this branch should go beyond AccountLink: inventory current entry points, confirm which older Confluence-listed entries are still valid, and temporarily log entry path, resolved host mode, dismissal mechanism, delegate callbacks, and session cleanup. Remove those logs before PR publication. --- ## Historical Slack Context - November 21, 2025 Slack context says David created `PDIAP-12284` and `PDIAP-12285` to cover remaining UIKit-removal work inside XFlow after reviewing open Sendable and XFlowViewMaker-track stories. - That same backlog refinement closed out pending XFlowViewMaker stories that were no longer needed. - Current Mattermost context supersedes the old standalone refinement framing: this story is now reopened after rollback and should be handled together with `PDIAP-15836`. --- ## Sequencing - Work can begin, but merge/release should wait until the REST-transition consumer-validation window has completed. - Keep the implementation branch up to date with `main` while waiting for approval to work with consumers and merge. - Before implementation is treated as settled, confirm through product-code inspection whether XFlowViewMaker can resolve host mode using existing `FeatureEnabling` / `Featuring` abstractions or whether a small dependency-injection path is needed.