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 2 commits
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
8 changes: 4 additions & 4 deletions Debug App/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ PODS:
- PrimerIPay88MYSDK (0.1.7)
- PrimerKlarnaSDK (1.1.1)
- PrimerNolPaySDK (1.0.1)
- PrimerSDK (2.31.2):
- PrimerSDK/Core (= 2.31.2)
- PrimerSDK/Core (2.31.2)
- PrimerSDK (2.31.3):
- PrimerSDK/Core (= 2.31.3)
- PrimerSDK/Core (2.31.3)
- PrimerStripeSDK (1.0.0)

DEPENDENCIES:
Expand Down Expand Up @@ -37,7 +37,7 @@ SPEC CHECKSUMS:
PrimerIPay88MYSDK: 436ee0be7e2c97e4e81456ccddee20175e9e3c4d
PrimerKlarnaSDK: 564105170cc7b467bf95c31851813ea41c468f8b
PrimerNolPaySDK: 08b140ed39b378a0b33b4f8746544a402175c0cc
PrimerSDK: b7d56fb276e17b5225c934b15c6aa25975d2db65
PrimerSDK: 97197b708f58d992aaa40163bc3f3ba58fa8a2e6
PrimerStripeSDK: c37d4e7c1b5256d67d4890c4cc4b38ddc9427489

PODFILE CHECKSUM: fa17ead44d40b0b09abc2f30a5cc3d8aefe389e1
Expand Down
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 / Optional SDK Tests (3DS, Package.3DS.swift)

'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 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.addDismissButton()

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 addDismissButton() {
// Add Close button to navigation bar
if PrimerSettings.current.uiOptions.dismissalMechanism.contains(.closeButton) {
let dismissButton = UIButton(type: .system)
dismissButton.setTitle(Strings.Generic.close, for: .normal)
dismissButton.setTitleColor(UIColor.gray, for: .disabled)
dismissButton.addTarget(self, action: #selector(didTapCloseButton), for: .touchUpInside)
rightBarButton = dismissButton
}
}

@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