Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Implement new dismissal mechanisms for Drop-In #1039

Merged
merged 5 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 43 additions & 13 deletions Debug App/Resources/Localized Views/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class MerchantSessionAndSettingsViewController: UIViewController {
@IBOutlet weak var vaultPaymentsSwitch: UISwitch!
@IBOutlet weak var disableSuccessScreenSwitch: UISwitch!
@IBOutlet weak var disableErrorScreenSwitch: UISwitch!
@IBOutlet weak var gesturesDismissalSwitch: UISwitch!
@IBOutlet weak var closeButtonDismissalSwitch: UISwitch!
@IBOutlet weak var disableInitScreenSwitch: UISwitch!
@IBOutlet weak var enableCVVRecaptureFlowSwitch: UISwitch!

Expand Down Expand Up @@ -293,6 +295,9 @@ class MerchantSessionAndSettingsViewController: UIViewController {
}
}

gesturesDismissalSwitch.isOn = true // Default value
closeButtonDismissalSwitch.isOn = false // Default false

lineItemsStackView.removeAllArrangedSubviews()
lineItemsStackView.alignment = .fill
lineItemsStackView.distribution = .fill
Expand Down Expand Up @@ -621,10 +626,22 @@ class MerchantSessionAndSettingsViewController: UIViewController {
@IBAction func primerSDKButtonTapped(_ sender: Any) {
customDefinedApiKey = (apiKeyTextField.text ?? "").isEmpty ? nil : apiKeyTextField.text

let selectedDismissalMechanisms: [DismissalMechanism] = {
var mechanisms = [DismissalMechanism]()
if gesturesDismissalSwitch.isOn {
mechanisms.append(.gestures)
}
if closeButtonDismissalSwitch.isOn {
mechanisms.append(.closeButton)
}
return mechanisms
}()

let uiOptions = PrimerUIOptions(
isInitScreenEnabled: !disableInitScreenSwitch.isOn,
isSuccessScreenEnabled: !disableSuccessScreenSwitch.isOn,
isErrorScreenEnabled: !disableErrorScreenSwitch.isOn,
dismissalMechanism: selectedDismissalMechanisms,
theme: applyThemingSwitch.isOn ? CheckoutTheme.tropical : nil)

let mandateData = PrimerStripeOptions.MandateData.templateMandate(merchantName: "Primer Inc.")
Expand Down
12 changes: 11 additions & 1 deletion Sources/PrimerSDK/Classes/Data Models/PrimerSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
showApplePayForUnsupportedDevice: Bool = true,
checkProvidedNetworks: Bool = true) {
self.merchantIdentifier = merchantIdentifier
self.merchantName = merchantName

Check warning on line 161 in Sources/PrimerSDK/Classes/Data Models/PrimerSettings.swift

View workflow job for this annotation

GitHub Actions / Unit Tests - SDK

'merchantName' is deprecated: Use Client Session API to provide merchant name value: https://primer.io/docs/payment-methods/apple-pay/direct-integration#prepare-the-client-session
self.isCaptureBillingAddressEnabled = isCaptureBillingAddressEnabled
self.shippingOptions = nil
self.showApplePayForUnsupportedDevice = showApplePayForUnsupportedDevice
Expand All @@ -172,7 +172,7 @@
checkProvidedNetworks: Bool = true,
shippingOptions: ShippingOptions? = nil) {
self.merchantIdentifier = merchantIdentifier
self.merchantName = merchantName

Check warning on line 175 in Sources/PrimerSDK/Classes/Data Models/PrimerSettings.swift

View workflow job for this annotation

GitHub Actions / Unit Tests - SDK

'merchantName' is deprecated: Use Client Session API to provide merchant name value: https://primer.io/docs/payment-methods/apple-pay/direct-integration#prepare-the-client-session
self.isCaptureBillingAddressEnabled = isCaptureBillingAddressEnabled
self.shippingOptions = shippingOptions
self.showApplePayForUnsupportedDevice = showApplePayForUnsupportedDevice
Expand Down Expand Up @@ -245,10 +245,15 @@

// MARK: - UI OPTIONS

public enum DismissalMechanism: Codable {
case gestures, closeButton
}

internal protocol PrimerUIOptionsProtocol {
var isInitScreenEnabled: Bool { get } // Default: true
var isSuccessScreenEnabled: Bool { get } // Default: true
var isErrorScreenEnabled: Bool { get } // Default: true
var dismissalMechanism: [DismissalMechanism] { get } // Default: .gestures
var theme: PrimerTheme { get }
}

Expand All @@ -257,21 +262,24 @@
public internal(set) var isInitScreenEnabled: Bool
public internal(set) var isSuccessScreenEnabled: Bool
public internal(set) var isErrorScreenEnabled: Bool
public internal(set) var dismissalMechanism: [DismissalMechanism]
public let theme: PrimerTheme

private enum CodingKeys: String, CodingKey {
case isInitScreenEnabled, isSuccessScreenEnabled, isErrorScreenEnabled, theme
case isInitScreenEnabled, isSuccessScreenEnabled, isErrorScreenEnabled, dismissalMechanism, theme
}

public init(
isInitScreenEnabled: Bool? = nil,
isSuccessScreenEnabled: Bool? = nil,
isErrorScreenEnabled: Bool? = nil,
dismissalMechanism: [DismissalMechanism]? = [.gestures],
theme: PrimerTheme? = nil
) {
self.isInitScreenEnabled = isInitScreenEnabled != nil ? isInitScreenEnabled! : true
self.isSuccessScreenEnabled = isSuccessScreenEnabled != nil ? isSuccessScreenEnabled! : true
self.isErrorScreenEnabled = isErrorScreenEnabled != nil ? isErrorScreenEnabled! : true
self.dismissalMechanism = dismissalMechanism ?? [.gestures]
self.theme = theme ?? PrimerTheme()
}

Expand All @@ -280,6 +288,7 @@
self.isInitScreenEnabled = try container.decode(Bool.self, forKey: .isInitScreenEnabled)
self.isSuccessScreenEnabled = try container.decode(Bool.self, forKey: .isSuccessScreenEnabled)
self.isErrorScreenEnabled = try container.decode(Bool.self, forKey: .isErrorScreenEnabled)
self.dismissalMechanism = try container.decode([DismissalMechanism].self, forKey: .dismissalMechanism)
self.theme = PrimerTheme()
}

Expand All @@ -288,6 +297,7 @@
try container.encode(isInitScreenEnabled, forKey: .isInitScreenEnabled)
try container.encode(isSuccessScreenEnabled, forKey: .isSuccessScreenEnabled)
try container.encode(isErrorScreenEnabled, forKey: .isErrorScreenEnabled)
try container.encode(dismissalMechanism, forKey: .dismissalMechanism)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class PrimerContainerViewController: PrimerViewController {
mockedNavigationBar.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
mockedNavigationBar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
mockedNavigationBar.heightAnchor.constraint(equalToConstant: 44).isActive = true
mockedNavigationBar.addCancelButton()

addChild(childViewController)
scrollView.bounces = false
Expand Down Expand Up @@ -102,5 +103,4 @@ extension UIView {
leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: leading).isActive = true
trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: trailing).isActive = true
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,44 @@ class PrimerNavigationBar: PrimerView {
didSet {
rightBarButton?.tintColor = theme.text.system.color
rightBarButton?.setTitleColor(theme.text.system.color, for: .normal)
rightBarButton?.frame = CGRect(
x: 0, y: 0, width: rightView.bounds.size.width, height: rightView.bounds.size.height
)
NQuinn27 marked this conversation as resolved.
Show resolved Hide resolved

// Remove any existing subviews from rightView
rightView.subviews.forEach { view in
view.removeFromSuperview()
}

if let rightBarButton = rightBarButton {
rightView.addSubview(rightBarButton)
rightBarButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
rightBarButton.leadingAnchor.constraint(equalTo: rightView.leadingAnchor),
rightBarButton.trailingAnchor.constraint(equalTo: rightView.trailingAnchor),
rightBarButton.topAnchor.constraint(equalTo: rightView.topAnchor),
rightBarButton.bottomAnchor.constraint(equalTo: rightView.bottomAnchor)
])
}
}
}

var leftBarButton: UIButton? {
didSet {
leftBarButton?.tintColor = theme.text.system.color
leftBarButton?.setTitleColor(theme.text.system.color, for: .normal)

// Remove any existing subviews from rightView
leftView.subviews.forEach { view in
view.removeFromSuperview()
}

if let rightBarButton = leftBarButton {
NQuinn27 marked this conversation as resolved.
Show resolved Hide resolved
leftView.addSubview(rightBarButton)
rightBarButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
rightBarButton.leadingAnchor.constraint(equalTo: leftView.leadingAnchor),
rightBarButton.trailingAnchor.constraint(equalTo: leftView.trailingAnchor),
rightBarButton.topAnchor.constraint(equalTo: leftView.topAnchor),
rightBarButton.bottomAnchor.constraint(equalTo: leftView.bottomAnchor)
])
}
}
}
Expand Down Expand Up @@ -91,6 +119,21 @@ class PrimerNavigationBar: PrimerView {
PrimerUIManager.primerRootViewController?.popViewController()
}

func addCancelButton() {
// Add Close button to navigation bar
if PrimerSettings.current.uiOptions.dismissalMechanism.contains(.closeButton) {
let cancelButton = UIButton(type: .system)
cancelButton.setTitle(Strings.Generic.close, for: .normal)
cancelButton.setTitleColor(UIColor.gray, for: .disabled)
cancelButton.addTarget(self, action: #selector(didTapCloseButton), for: .touchUpInside)
rightBarButton = cancelButton
}
}

@objc private func didTapCloseButton() {
PrimerInternal.shared.dismiss()
}

private func setup() {
translatesAutoresizingMaskIntoConstraints = false
heightAnchor.constraint(equalToConstant: PrimerDimensions.NavigationBar.default).isActive = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ internal class PrimerRootViewController: PrimerViewController {
}

private func setupGestureRecognizers() {
guard PrimerSettings.current.uiOptions.dismissalMechanism.contains(.gestures) else { return }
self.tapGesture = UITapGestureRecognizer(
target: self,
action: #selector(dismissGestureRecognizerAction))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ internal class PrimerVoucherInfoPaymentViewController: PrimerFormViewController

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
(parent as? PrimerContainerViewController)?.mockedNavigationBar.rightBarButton = shareButton
(parent as? PrimerContainerViewController)?.mockedNavigationBar.leftBarButton = shareButton
}

}
Expand Down
Loading