Skip to content

Commit

Permalink
Update promo in MPE after bank flow
Browse files Browse the repository at this point in the history
  • Loading branch information
tillh-stripe committed Dec 20, 2024
1 parent b83e20a commit 2ed15ab
Show file tree
Hide file tree
Showing 7 changed files with 108 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ extension AddPaymentMethodViewController: PaymentMethodTypeCollectionViewDelegat
extension AddPaymentMethodViewController: PaymentMethodFormViewControllerDelegate {
func didUpdate(_ viewController: PaymentMethodFormViewController) {
delegate?.didUpdate(self)

if let instantDebitsFormElement = viewController.form as? InstantDebitsPaymentMethodElement {
let incentive = instantDebitsFormElement.displayableIncentive
paymentMethodTypesView.setIncentive(incentive)
}
}

func updateErrorLabel(for error: Swift.Error?) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,18 @@ class PaymentMethodTypeCollectionView: UICollectionView {
override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric, height: PaymentMethodTypeCollectionView.cellHeight)
}

func setIncentive(_ incentive: PaymentMethodIncentive?) {
guard self.incentive != incentive, let index = self.indexPathsForSelectedItems?.first else {
return
}

self.incentive = incentive

// Prevent the selected cell from being unselected following the reload
reloadItems(at: [index])
selectItem(at: index, animated: false, scrollPosition: [])
}
}

// MARK: - UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import Foundation
@_spi(STP) import StripePayments

struct PaymentMethodIncentive {
struct PaymentMethodIncentive: Equatable {

let identifier: String
let displayText: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,21 @@ final class InstantDebitsPaymentMethodElement: ContainerElement {
let emailElement: TextFieldElement?
let phoneElement: PhoneNumberElement?
let addressElement: AddressSectionElement?
private let promoDisclaimerElement: StaticElement?

private var linkedBankElements: [Element] {
return [linkedBankInfoSectionElement]
}
private let linkedBankInfoSectionElement: SectionElement
private let linkedBankInfoView: BankAccountInfoView
private var linkedBank: InstantDebitsLinkedBank?
private var linkedBank: InstantDebitsLinkedBank? {
didSet {
updateLinkedBank(linkedBank)
}
}
private let theme: ElementsAppearance
var presentingViewControllerDelegate: PresentingViewControllerDelegate?
var incentive: PaymentMethodIncentive?
private let incentive: PaymentMethodIncentive?

var delegate: ElementDelegate?
var view: UIView {
Expand Down Expand Up @@ -164,6 +169,11 @@ final class InstantDebitsPaymentMethodElement: ContainerElement {

return nameValid && emailValid && phoneValid && addressValid
}

var displayableIncentive: PaymentMethodIncentive? {
let canShowIncentive = linkedBank?.incentiveEligible ?? true
return canShowIncentive ? incentive : nil
}

init(
configuration: PaymentSheetFormFactoryConfig,
Expand Down Expand Up @@ -196,7 +206,7 @@ final class InstantDebitsPaymentMethodElement: ContainerElement {
self.incentive = incentive
self.theme = theme

let promoDisclaimerElement = incentive.flatMap {
self.promoDisclaimerElement = incentive.flatMap {
let label = ElementsUI.makeNoticeTextField(theme: theme)
label.attributedText = $0.promoDisclaimerText(with: theme, isPaymentIntent: isPaymentIntent)
label.textContainerInset = .zero
Expand Down Expand Up @@ -224,18 +234,33 @@ final class InstantDebitsPaymentMethodElement: ContainerElement {

func setLinkedBank(_ linkedBank: InstantDebitsLinkedBank) {
self.linkedBank = linkedBank
if let last4ofBankAccount = linkedBank.last4, let bankName = linkedBank.bankName {
self.delegate?.didUpdate(element: self)
}

fileprivate func updateLinkedBank(_ linkedBank: InstantDebitsLinkedBank?) {
let hideLinkedBank = linkedBank == nil

if let last4ofBankAccount = linkedBank?.last4, let bankName = linkedBank?.bankName {
linkedBankInfoView.setBankName(text: bankName)
linkedBankInfoView.setLastFourOfBank(text: "•••• \(last4ofBankAccount)")
// TODO: Take the eligibility from the linked bank
linkedBankInfoView.setIncentiveEligible(false)
}

formElement.toggleElements(
linkedBankElements,
hidden: hideLinkedBank,
animated: true
)

if let promoDisclaimerElement {
let hidePromoBadge = incentive == nil || linkedBank?.incentiveEligible == false
formElement.toggleElements(
linkedBankElements,
hidden: false,
[promoDisclaimerElement],
hidden: hidePromoBadge,
animated: true
)
}
self.delegate?.didUpdate(element: self)
}

func getLinkedBank() -> InstantDebitsLinkedBank? {
Expand All @@ -249,11 +274,6 @@ extension InstantDebitsPaymentMethodElement: BankAccountInfoViewDelegate {

func didTapXIcon() {
let hideLinkedBankElement = {
self.formElement.toggleElements(
self.linkedBankElements,
hidden: true,
animated: true
)
self.linkedBank = nil
self.delegate?.didUpdate(element: self)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ class VerticalPaymentMethodListViewController: UIViewController {
private(set) var currentSelection: VerticalPaymentMethodListSelection?
let stackView = UIStackView()
let appearance: PaymentSheet.Appearance
private var incentive: PaymentMethodIncentive?
weak var delegate: VerticalPaymentMethodListViewControllerDelegate?

private var refreshContent: () -> Void = {}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
Expand All @@ -43,16 +46,47 @@ class VerticalPaymentMethodListViewController: UIViewController {
incentive: PaymentMethodIncentive?,
delegate: VerticalPaymentMethodListViewControllerDelegate
) {
self.delegate = delegate
self.appearance = appearance
self.incentive = incentive
self.delegate = delegate
super.init(nibName: nil, bundle: nil)


self.refreshContent = { [weak self] in
guard let self else {
return
}

stackView.arrangedSubviews.forEach { subview in
subview.removeFromSuperview()
}

renderContent(
overrideHeaderView: overrideHeaderView,
savedPaymentMethod: savedPaymentMethod,
initialSelection: initialSelection,
savedPaymentMethodAccessoryType: savedPaymentMethodAccessoryType,
shouldShowApplePay: shouldShowApplePay,
shouldShowLink: shouldShowLink,
paymentMethodTypes: paymentMethodTypes
)
}
self.refreshContent()
}

private func renderContent(
overrideHeaderView: UIView?,
savedPaymentMethod: STPPaymentMethod?,
initialSelection: VerticalPaymentMethodListSelection?,
savedPaymentMethodAccessoryType: RowButton.RightAccessoryButton.AccessoryType?,
shouldShowApplePay: Bool,
shouldShowLink: Bool,
paymentMethodTypes: [PaymentSheet.PaymentMethodType]
) {
// Add the header - either the passed in `header` or "Select payment method"
let header = overrideHeaderView ?? PaymentSheetUI.makeHeaderLabel(title: .Localized.select_payment_method, appearance: appearance)
stackView.addArrangedSubview(header)
stackView.setCustomSpacing(24, after: header)

// Create stack view views after super.init so that we can reference `self`
var views = [UIView]()
// Saved payment method:
Expand All @@ -65,7 +99,7 @@ class VerticalPaymentMethodListViewController: UIViewController {
return nil
}
}()

let savedPaymentMethodButton = RowButton.makeForSavedPaymentMethod(paymentMethod: savedPaymentMethod, appearance: appearance, rightAccessoryView: accessoryButton) { [weak self] in
self?.didTap(rowButton: $0, selection: selection)
}
Expand All @@ -80,7 +114,7 @@ class VerticalPaymentMethodListViewController: UIViewController {
Self.makeSectionLabel(text: .Localized.new_payment_method, appearance: appearance),
]
}

// Build Apple Pay and Link rows
let applePay: RowButton? = {
guard shouldShowApplePay else { return nil }
Expand All @@ -106,7 +140,7 @@ class VerticalPaymentMethodListViewController: UIViewController {
}
return rowButton
}()

// Payment methods
var indexAfterCards: Int?
let paymentMethodTypes = paymentMethodTypes
Expand All @@ -119,7 +153,7 @@ class VerticalPaymentMethodListViewController: UIViewController {
promoText: incentive?.takeIfAppliesTo(paymentMethodType)?.displayText,
appearance: appearance,
// Enable press animation if tapping this transitions the screen to a form instead of becoming selected
shouldAnimateOnPress: !delegate.shouldSelectPaymentMethod(selection)
shouldAnimateOnPress: delegate?.shouldSelectPaymentMethod(selection) == true
) { [weak self] in
self?.didTap(rowButton: $0, selection: selection)
}
Expand All @@ -132,10 +166,10 @@ class VerticalPaymentMethodListViewController: UIViewController {
currentSelection = selection
}
}

// Insert Apple Pay/Link after card or, if cards aren't present, first
views.insert(contentsOf: [applePay, link].compactMap({ $0 }), at: indexAfterCards ?? 0)

for view in views {
stackView.addArrangedSubview(view)
}
Expand Down Expand Up @@ -170,6 +204,15 @@ class VerticalPaymentMethodListViewController: UIViewController {
@objc func didTapAccessoryButton() {
delegate?.didTapSavedPaymentMethodAccessoryButton()
}

func setIncentive(_ incentive: PaymentMethodIncentive?) {
guard self.incentive != incentive else {
return
}

self.incentive = incentive
self.refreshContent()
}

static func makeSectionLabel(text: String, appearance: PaymentSheet.Appearance) -> UILabel {
let label = UILabel()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ extension PaymentMethodFormViewController {
intentId: intentId,
linkMode: linkMode,
billingDetails: billingDetails,
eligibleForIncentive: instantDebitsFormElement?.incentive != nil
eligibleForIncentive: instantDebitsFormElement?.displayableIncentive != nil
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,11 @@ extension PaymentSheetVerticalViewController: PaymentMethodFormViewControllerDel
if viewController.paymentOption != nil {
analyticsHelper.logFormCompleted(paymentMethodTypeIdentifier: viewController.paymentMethodType.identifier)
}

if let instantDebitsFormElement = viewController.form as? InstantDebitsPaymentMethodElement {
let incentive = instantDebitsFormElement.displayableIncentive
paymentMethodListViewController?.setIncentive(incentive)
}
}

func updateErrorLabel(for error: Swift.Error?) {
Expand Down

0 comments on commit 2ed15ab

Please sign in to comment.