-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Display a “default” badge for the default PM #4333
Changes from 81 commits
1403094
71c5516
e3ecc2c
fb86faa
b283446
9ed5ed2
e689449
3c36c97
c749e6e
aac6ae1
90e15a4
b25eb4b
16e6b0c
5936f96
5cd59d6
54a8073
0fca0dc
c8bd06b
c226e09
4d146b6
f858536
8d1c90b
c70c6a1
d999b9e
ac5189a
ffcf6e4
403fdcb
c8fbfef
2f515cd
0a92c87
a89890c
bd51b31
3c69384
f239d20
5fad2d3
4da3034
f83164f
05407cc
60cd77c
fe79f55
ea5228f
eaae456
623ffe3
7022a11
f5fbd58
05a0a04
1794106
cb12138
efb682f
b592b55
74c9db8
a28440e
b6d712e
d4dedf5
f9d0996
0c52f28
8f30c22
d6ea0c6
04b187d
8d7509c
afcfc48
b88ce62
6dba918
626f4d5
734345e
f6844ec
063fcb1
3867417
6670834
f05cdcb
ff08f77
53b894a
8382a93
22e2b02
6bcc425
304aa41
9dd0cfb
10de2e9
d27f4c8
9d16dec
bdda2bb
9048ed0
dd6dedb
238e94e
9b76fa9
53a55c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ import UIKit | |
// MARK: - Constants | ||
/// Entire cell size | ||
private let cellSize: CGSize = CGSize(width: 106, height: 94) | ||
private let cellSizeWithDefaultBadge: CGSize = CGSize(width: 106, height: 112) | ||
Comment on lines
18
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the harm in making all the cells the new size to account for the possible default badge? What happens if we use the old size? Would be preferred if we can avoid swapping sizes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main issue there is that in the Figma, the height of the sheet changes when edit mode is on, but if we just increase the size of the cells constantly, then there will just be extra space under the PMs and the height won't change. |
||
/// Size of the rounded rectangle that contains the PM logo | ||
let roundedRectangleSize = CGSize(width: 100, height: 64) | ||
private let paymentMethodLogoSize: CGSize = CGSize(width: 54, height: 40) | ||
|
@@ -24,12 +25,13 @@ private let paymentMethodLogoSize: CGSize = CGSize(width: 54, height: 40) | |
/// For internal SDK use only | ||
@objc(STP_Internal_SavedPaymentMethodCollectionView) | ||
class SavedPaymentMethodCollectionView: UICollectionView { | ||
init(appearance: PaymentSheet.Appearance) { | ||
init(appearance: PaymentSheet.Appearance, needsVerticalPaddingForBadge: Bool = false) { | ||
let layout = UICollectionViewFlowLayout() | ||
layout.scrollDirection = .horizontal | ||
layout.sectionInset = UIEdgeInsets( | ||
top: -6, left: PaymentSheetUI.defaultPadding, bottom: 0, | ||
right: PaymentSheetUI.defaultPadding) | ||
self.needsVerticalPaddingForBadge = needsVerticalPaddingForBadge | ||
layout.itemSize = cellSize | ||
layout.minimumInteritemSpacing = 12 | ||
layout.minimumLineSpacing = 4 | ||
|
@@ -43,13 +45,23 @@ class SavedPaymentMethodCollectionView: UICollectionView { | |
} | ||
|
||
var isRemovingPaymentMethods: Bool = false | ||
let needsVerticalPaddingForBadge: Bool | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
override var intrinsicContentSize: CGSize { | ||
return CGSize(width: UIView.noIntrinsicMetric, height: 100) | ||
return needsVerticalPaddingForBadge && isRemovingPaymentMethods ? CGSize(width: UIView.noIntrinsicMetric, height: 118) : CGSize(width: UIView.noIntrinsicMetric, height: 100) | ||
} | ||
|
||
func updateLayout() { | ||
guard let layout = collectionViewLayout as? UICollectionViewFlowLayout else { return } | ||
let newCellSize = needsVerticalPaddingForBadge && isRemovingPaymentMethods ? cellSizeWithDefaultBadge : cellSize | ||
guard newCellSize != layout.itemSize else { return } | ||
layout.itemSize = newCellSize | ||
collectionViewLayout.invalidateLayout() | ||
invalidateIntrinsicContentSize() | ||
} | ||
} | ||
|
||
|
@@ -91,11 +103,30 @@ extension SavedPaymentMethodCollectionView { | |
button.accessibilityLabel = String.Localized.edit | ||
return button | ||
}() | ||
lazy var defaultBadge: UILabel = { | ||
let label = UILabel() | ||
label.font = appearance.scaledFont(for: appearance.font.base.medium, style: .caption1, maximumPointSize: 20) | ||
label.textColor = appearance.colors.textSecondary | ||
label.adjustsFontForContentSizeCategory = true | ||
label.text = String.Localized.default_text | ||
label.isHidden = true | ||
return label | ||
}() | ||
|
||
fileprivate var viewModel: SavedPaymentOptionsViewController.Selection? | ||
|
||
var isRemovingPaymentMethods: Bool = false { | ||
didSet { | ||
if needsVerticalPaddingForBadge { | ||
joyceqin-stripe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if isRemovingPaymentMethods { | ||
activateDefaultBadgeConstraints() | ||
defaultBadge.setHiddenIfNecessary(!showDefaultPMBadge) | ||
} | ||
else { | ||
deactivateDefaultBadgeConstraints() | ||
defaultBadge.setHiddenIfNecessary(true) | ||
} | ||
} | ||
update() | ||
} | ||
} | ||
|
@@ -110,14 +141,17 @@ extension SavedPaymentMethodCollectionView { | |
|
||
var cbcEligible: Bool = false | ||
var allowsPaymentMethodRemoval: Bool = true | ||
var allowsSetAsDefaultPM: Bool = false | ||
var needsVerticalPaddingForBadge: Bool = false | ||
var showDefaultPMBadge: Bool = false | ||
|
||
/// Indicates whether the cell for a saved payment method should display the edit icon. | ||
/// True if payment methods can be removed or edited (will update this to include allowing set as default) | ||
/// True if payment methods can be removed or edited | ||
var showEditIcon: Bool { | ||
guard UpdatePaymentMethodViewModel.supportedPaymentMethods.contains(where: { viewModel?.savedPaymentMethod?.type == $0 }) else { | ||
fatalError("Payment method does not match supported saved payment methods.") | ||
} | ||
return allowsPaymentMethodRemoval || (viewModel?.savedPaymentMethod?.isCoBrandedCard ?? false && cbcEligible) | ||
return allowsSetAsDefaultPM || allowsPaymentMethodRemoval || (viewModel?.savedPaymentMethod?.isCoBrandedCard ?? false && cbcEligible) | ||
} | ||
|
||
// MARK: - UICollectionViewCell | ||
|
@@ -142,7 +176,7 @@ extension SavedPaymentMethodCollectionView { | |
paymentMethodLogo.contentMode = .scaleAspectFit | ||
accessoryButton.addTarget(self, action: #selector(didSelectAccessory), for: .touchUpInside) | ||
let views = [ | ||
label, shadowRoundedRectangle, paymentMethodLogo, plus, selectedIcon, accessoryButton, | ||
label, shadowRoundedRectangle, paymentMethodLogo, plus, selectedIcon, accessoryButton, defaultBadge | ||
] | ||
views.forEach { | ||
$0.translatesAutoresizingMaskIntoConstraints = false | ||
|
@@ -159,7 +193,7 @@ extension SavedPaymentMethodCollectionView { | |
|
||
label.topAnchor.constraint( | ||
equalTo: shadowRoundedRectangle.bottomAnchor, constant: 4), | ||
label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), | ||
labelBottomConstraint, | ||
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 2), | ||
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), | ||
|
||
|
@@ -188,6 +222,7 @@ extension SavedPaymentMethodCollectionView { | |
equalTo: contentView.trailingAnchor, constant: 0), | ||
accessoryButton.topAnchor.constraint( | ||
equalTo: contentView.topAnchor, constant: 0), | ||
|
||
]) | ||
} | ||
|
||
|
@@ -208,15 +243,33 @@ extension SavedPaymentMethodCollectionView { | |
} | ||
} | ||
|
||
// MARK: - Internal Methods | ||
private lazy var labelBottomConstraint: NSLayoutConstraint = { | ||
return label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) | ||
}() | ||
private lazy var labelHeightConstraint: NSLayoutConstraint = { | ||
return label.heightAnchor.constraint(equalToConstant: 20) | ||
}() | ||
private lazy var defaultBadgeConstraints: [NSLayoutConstraint] = { | ||
return [ | ||
defaultBadge.topAnchor.constraint( | ||
equalTo: label.bottomAnchor, constant: 4), | ||
defaultBadge.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), | ||
defaultBadge.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 2), | ||
defaultBadge.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) | ||
] | ||
}() | ||
|
||
func setViewModel(_ viewModel: SavedPaymentOptionsViewController.Selection, cbcEligible: Bool, allowsPaymentMethodRemoval: Bool) { | ||
// MARK: - Internal Methods | ||
func setViewModel(_ viewModel: SavedPaymentOptionsViewController.Selection, cbcEligible: Bool, allowsPaymentMethodRemoval: Bool, allowsSetAsDefaultPM: Bool = false, needsVerticalPaddingForBadge: Bool = false, showDefaultPMBadge: Bool = false) { | ||
paymentMethodLogo.isHidden = false | ||
plus.isHidden = true | ||
shadowRoundedRectangle.isHidden = false | ||
self.viewModel = viewModel | ||
self.cbcEligible = cbcEligible | ||
self.allowsPaymentMethodRemoval = allowsPaymentMethodRemoval | ||
self.allowsSetAsDefaultPM = allowsSetAsDefaultPM | ||
self.needsVerticalPaddingForBadge = needsVerticalPaddingForBadge | ||
self.showDefaultPMBadge = showDefaultPMBadge | ||
update() | ||
} | ||
|
||
|
@@ -372,6 +425,17 @@ extension SavedPaymentMethodCollectionView { | |
}() | ||
} | ||
} | ||
|
||
private func activateDefaultBadgeConstraints() { | ||
NSLayoutConstraint.deactivate([labelBottomConstraint]) | ||
NSLayoutConstraint.activate([labelHeightConstraint] + defaultBadgeConstraints) | ||
} | ||
|
||
private func deactivateDefaultBadgeConstraints() { | ||
NSLayoutConstraint.deactivate(defaultBadgeConstraints + [labelHeightConstraint]) | ||
NSLayoutConstraint.activate([labelBottomConstraint]) | ||
} | ||
|
||
} | ||
|
||
// A circle with an image in the middle | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in PaymentSheetVerticalViewController, we have this logic for the initialSelection
This seems to indicate that the first payment method can become the default. Is this true? Ultimately, i'm trying to wrap my head around when we would access defaultPaymentMethod vs defaultOrFirst.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding, the selected payment method should be the default if it exists or the first payment method in the customer's list of saved payment methods. However, the default badge itself should only be displayed if there is a set default in the elementsSession customer.
So we access defaultOrFirst when trying to determine the selected payment method, while we access defaultPaymentMethod to determine if the default badge should be shown and which payment method to show it on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah thanks for the explanation!