Skip to content

Commit

Permalink
Add Link warmup pane for deferred intents
Browse files Browse the repository at this point in the history
  • Loading branch information
tillh-stripe committed Nov 15, 2024
1 parent 475ad81 commit a11abfb
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ protocol ConsentDataSource: AnyObject {
var merchantLogo: [String]? { get }
var analyticsClient: FinancialConnectionsAnalyticsClient { get }

func markConsentAcquired() -> Promise<FinancialConnectionsSessionManifest>
func markConsentAcquired() -> Future<ConsentAcquiredResult>
}

struct ConsentAcquiredResult {
var manifest: FinancialConnectionsSessionManifest
var customNextPane: FinancialConnectionsSessionManifest.NextPane?
}

final class ConsentDataSourceImplementation: ConsentDataSource {
Expand All @@ -25,24 +30,66 @@ final class ConsentDataSourceImplementation: ConsentDataSource {
private let apiClient: FinancialConnectionsAPIClient
private let clientSecret: String
let analyticsClient: FinancialConnectionsAnalyticsClient
private let elementsSessionContext: ElementsSessionContext?

private var isLinkWithStripe: Bool {
manifest.isLinkWithStripe ?? false
}

init(
manifest: FinancialConnectionsSessionManifest,
consent: FinancialConnectionsConsent,
merchantLogo: [String]?,
apiClient: FinancialConnectionsAPIClient,
clientSecret: String,
analyticsClient: FinancialConnectionsAnalyticsClient
analyticsClient: FinancialConnectionsAnalyticsClient,
elementsSessionContext: ElementsSessionContext?
) {
self.manifest = manifest
self.consent = consent
self.merchantLogo = merchantLogo
self.apiClient = apiClient
self.clientSecret = clientSecret
self.analyticsClient = analyticsClient
self.elementsSessionContext = elementsSessionContext
}

func markConsentAcquired() -> Promise<FinancialConnectionsSessionManifest> {
return apiClient.markConsentAcquired(clientSecret: clientSecret)
func markConsentAcquired() -> Future<ConsentAcquiredResult> {
return apiClient.markConsentAcquired(clientSecret: clientSecret).chained { [weak self] manifest in
let promise = Promise<ConsentAcquiredResult>()

guard let self, self.isLinkWithStripe, self.manifest.accountholderCustomerEmailAddress == nil else {
let result = ConsentAcquiredResult(manifest: manifest, customNextPane: nil)
return Promise(value: result)
}

guard let email = elementsSessionContext?.prefillDetails?.email else {
let result = ConsentAcquiredResult(manifest: manifest, customNextPane: nil)
return Promise(value: result)
}

apiClient.consumerSessionLookup(
emailAddress: email,
clientSecret: clientSecret
).observe { lookupResult in
let customNextPane = lookupResult.hasConsumer ? FinancialConnectionsSessionManifest.NextPane.networkingLinkLoginWarmup : nil
let result = ConsentAcquiredResult(manifest: manifest, customNextPane: customNextPane)
promise.resolve(with: result)
}

return promise
}
}
}

private extension Swift.Result<LookupConsumerSessionResponse, any Error> {

var hasConsumer: Bool {
switch self {
case .success(let lookup):
return lookup.exists
case .failure:
return false
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ protocol ConsentViewControllerDelegate: AnyObject {
)
func consentViewController(
_ viewController: ConsentViewController,
didConsentWithManifest manifest: FinancialConnectionsSessionManifest
didConsentWithManifest manifest: FinancialConnectionsSessionManifest,
customNextPane: FinancialConnectionsSessionManifest.NextPane?
)
}

Expand Down Expand Up @@ -146,8 +147,8 @@ class ConsentViewController: UIViewController {
.observe(on: .main) { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let manifest):
self.delegate?.consentViewController(self, didConsentWithManifest: manifest)
case .success(let result):
self.delegate?.consentViewController(self, didConsentWithManifest: result.manifest, customNextPane: result.customNextPane)
case .failure(let error):
// we display no errors on failure
self.dataSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,8 @@ extension NativeFlowController: ConsentViewControllerDelegate {

func consentViewController(
_ viewController: ConsentViewController,
didConsentWithManifest manifest: FinancialConnectionsSessionManifest
didConsentWithManifest manifest: FinancialConnectionsSessionManifest,
customNextPane: FinancialConnectionsSessionManifest.NextPane?
) {
delegate?.nativeFlowController(
self,
Expand All @@ -623,7 +624,7 @@ extension NativeFlowController: ConsentViewControllerDelegate {

dataManager.manifest = manifest

let nextPane = manifest.nextPane
let nextPane = customNextPane ?? manifest.nextPane
if nextPane == .networkingLinkLoginWarmup {
presentPaneAsSheet(nextPane)
} else {
Expand Down Expand Up @@ -1279,7 +1280,8 @@ private func CreatePaneViewController(
merchantLogo: dataManager.merchantLogo,
apiClient: dataManager.apiClient,
clientSecret: dataManager.clientSecret,
analyticsClient: dataManager.analyticsClient
analyticsClient: dataManager.analyticsClient,
elementsSessionContext: dataManager.elementsSessionContext
)
let consentViewController = ConsentViewController(dataSource: consentDataSource)
consentViewController.delegate = nativeFlowController
Expand Down Expand Up @@ -1366,9 +1368,10 @@ private func CreatePaneViewController(
case .networkingLinkVerification:
let accountholderCustomerEmailAddress = dataManager.manifest.accountholderCustomerEmailAddress
let consumerSessionEmailAddress = dataManager.consumerSession?.emailAddress
if let accountholderCustomerEmailAddress = consumerSessionEmailAddress ?? accountholderCustomerEmailAddress {
let prefillEmailAddress = dataManager.elementsSessionContext?.prefillDetails?.email
if let email = consumerSessionEmailAddress ?? accountholderCustomerEmailAddress ?? prefillEmailAddress {
let networkingLinkVerificationDataSource = NetworkingLinkVerificationDataSourceImplementation(
accountholderCustomerEmailAddress: accountholderCustomerEmailAddress,
accountholderCustomerEmailAddress: email,
manifest: dataManager.manifest,
apiClient: dataManager.apiClient,
clientSecret: dataManager.clientSecret,
Expand Down Expand Up @@ -1492,7 +1495,8 @@ private func CreatePaneViewController(
apiClient: dataManager.apiClient,
clientSecret: dataManager.clientSecret,
analyticsClient: dataManager.analyticsClient,
nextPaneOrDrawerOnSecondaryCta: parameters?.nextPaneOrDrawerOnSecondaryCta
nextPaneOrDrawerOnSecondaryCta: parameters?.nextPaneOrDrawerOnSecondaryCta,
elementsSessionContext: dataManager.elementsSessionContext
)
let networkingLinkWarmupViewController = NetworkingLinkLoginWarmupViewController(
dataSource: networkingLinkWarmupDataSource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Foundation
protocol NetworkingLinkLoginWarmupDataSource: AnyObject {
var manifest: FinancialConnectionsSessionManifest { get }
var analyticsClient: FinancialConnectionsAnalyticsClient { get }
var email: String? { get }

func disableNetworking() -> Future<FinancialConnectionsSessionManifest>
}
Expand All @@ -22,19 +23,26 @@ final class NetworkingLinkLoginWarmupDataSourceImplementation: NetworkingLinkLog
private let clientSecret: String
let analyticsClient: FinancialConnectionsAnalyticsClient
private let nextPaneOrDrawerOnSecondaryCta: String?
private let elementsSessionContext: ElementsSessionContext?

var email: String? {
manifest.accountholderCustomerEmailAddress ?? elementsSessionContext?.prefillDetails?.email
}

init(
manifest: FinancialConnectionsSessionManifest,
apiClient: FinancialConnectionsAPIClient,
clientSecret: String,
analyticsClient: FinancialConnectionsAnalyticsClient,
nextPaneOrDrawerOnSecondaryCta: String?
nextPaneOrDrawerOnSecondaryCta: String?,
elementsSessionContext: ElementsSessionContext?
) {
self.manifest = manifest
self.apiClient = apiClient
self.clientSecret = clientSecret
self.analyticsClient = analyticsClient
self.nextPaneOrDrawerOnSecondaryCta = nextPaneOrDrawerOnSecondaryCta
self.elementsSessionContext = elementsSessionContext
}

func disableNetworking() -> Future<FinancialConnectionsSessionManifest> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,8 @@ final class NetworkingLinkLoginWarmupViewController: SheetViewController {
"The subtitle/description of a screen where users are informed that they can sign-in-to Link."
),
contentView: NetworkingLinkLoginWarmupBodyView(
// `accountholderCustomerEmailAddress` should always be non-null, and
// since the email is only used as a visual, it's not worth to throw an error
// if it is null
email: dataSource.manifest.accountholderCustomerEmailAddress ?? "you"
// `email` should always be non-null, and since the email is only used as a visual, it's not worth to throw an error if it is null
email: dataSource.email ?? "you"
)
),
footerView: PaneLayoutView.createFooterView(
Expand Down

0 comments on commit a11abfb

Please sign in to comment.