-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[NT-357][NT-358] Change Payment Method UI #887
Conversation
# Conflicts: # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_de_device_pad@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_de_device_phone4_7inch@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_es_device_pad@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_es_device_phone4_7inch@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_fr_device_pad@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_fr_device_phone4_7inch@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_ja_device_pad@2x.png # Screenshots/_64/Kickstarter_Framework_iOSTests.PledgeViewControllerTests/testView_UpdateContext_lang_ja_device_phone4_7inch@2x.png
import Prelude_UIKit | ||
import UIKit | ||
|
||
final class PledgeAmountSummaryViewController: UIViewController { |
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.
This is just copy-pasting the required views from ManagePledgeSummaryView
.
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.
As discussed on Zoom, I'll create a follow-up PR to incorporate this as as subview of ManagePledgeSummaryViewController
to promote reuse.
@@ -68,19 +59,12 @@ final class PledgePaymentMethodsViewController: UIViewController { | |||
action: #selector(PledgePaymentMethodsViewController.applePayButtonTapped), | |||
for: .touchUpInside | |||
) | |||
|
|||
self.pledgeButton.addTarget( |
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.
This is replaced by submitButton
in PledgeViewController
.
@@ -60,6 +59,10 @@ final class PledgeViewController: UIViewController, MessageBannerViewControllerP | |||
|
|||
internal var messageBannerViewController: MessageBannerViewController? | |||
|
|||
private lazy var pledgeAmountSummaryViewController: PledgeAmountSummaryViewController = { | |||
PledgeAmountSummaryViewController.instantiate() |
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.
Not the most amazing name for this VC, open to suggestions.
case update | ||
case changePaymentMethod | ||
|
||
var confirmationLabelHidden: Bool { |
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.
These booleans basically map directly in PledgeViewModel
, it just helped for readability to do this here. They're tested in both places.
paymentSourceValid: Bool, | ||
context: PledgeViewContext | ||
) -> Bool { | ||
if context.isUpdating { |
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 an updating context we enable the submit button if anything has changed and his valid. In a creating context we require all values to be valid.
Generated by 🚫 Danger |
Kickstarter-iOS/Views/Controllers/PledgeViewControllerTests.swift
Outdated
Show resolved
Hide resolved
@@ -392,8 +392,6 @@ internal final class AddNewCardViewModelTests: TestCase { | |||
} | |||
|
|||
func testUnsupportedCardMessage_hidesWithValidCardBrand_AndExistingCardNumber_withSettingsIntent() { | |||
let project = Project.template |
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.
Ty 🙏
self.vm.inputs.viewDidLoad() | ||
|
||
self.goToChangePaymentMethod.assertDidNotEmitValue() | ||
self.goToChangePaymentMethodProject.assertDidNotEmitValue() |
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.
Should we add aself.goToChangePaymentMethodReward.assertDidNotEmitValue()
here too?
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 yes, thanks!
self.shippingAmountText = project | ||
.combineLatest(with: shippingAmount) | ||
.map { project, shippingAmount in | ||
shippingValue(with: project, with: shippingAmount) |
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.
Hmm this function name looks a bit strange. Maybe shippingValue(with project: Project, shippingAmount: Double)
?
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.
Oh, sure, this was a copy-paste 😄
) | ||
.map(first) | ||
|
||
let backing = project |
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.
Something you might consider doing is configuring this view with a project and a backing:
func configureWith(project: Project, backing: Backing)
It would simplify a few things in this view model.
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.
I think seeing as the Backing
is from the Project
I'm going to leave it as is for now.
let _ = backing.locationName else { | ||
return true | ||
} | ||
if let reward = backing.reward { |
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.
This is interesting. Do you think we need this extra layer of logic? I'd imagine if the backing.locationName
and backing.locationId
are not nil that you could assume that the backing was created with a shipping address. 🤔
I wonder if this could cause a bug in a situation where the reward's shipping eligibility is modified by the creator after the user has created a pledge (not sure if that's even possible).
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.
Another copy-paste, I'll check it out, thanks!
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.
Confirmed with team R&F that this cannot occur, so checking that locationId
is not nil
on the Backing
is sufficient. Good catch!
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.
Had a first run through this and mostly no red flags..
A11y
Do we want the space here? I believe our formatter returns empty nbsp
space at the beginning of the string which is fairly visible when the stack view is aligned vertically.
Changing font size crashes the screen (even after adding the following workaround)...wonder what's the real problem here.
DispatchQueue.main.async {
self.viewModel.inputs.traitCollectionDidChange()
}
|
||
_ = self.pledgeAmountStackView | ||
|> checkoutAdaptableStackViewStyle( | ||
self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory |
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.
Can we declare local variable and reuse it (since we're using it twice here)?
let isAccessibilityCategory = self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory
...
checkoutAdaptableStackViewStyle(isAccessibilityCategory)
|
||
private let amountLabelStyle: LabelStyle = { label in | ||
label | ||
|> \.adjustsFontForContentSizeCategory .~ true |
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.
Do we also need to set font? 🤔
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.
pledgeAmountLabel
uses an attributed string so the font setting isn't necessary here.
@@ -182,20 +153,12 @@ final class PledgePaymentMethodsViewController: UIViewController { | |||
self.viewModel.inputs.configureWith(pledgePaymentMethodsValue) | |||
} | |||
|
|||
// MARK: - Accessors | |||
// MARK: - Actions |
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.
@@ -11,10 +11,9 @@ protocol PledgeViewControllerDelegate: AnyObject { | |||
final class PledgeViewController: UIViewController, MessageBannerViewControllerPresenting { | |||
// MARK: - Properties | |||
|
|||
private lazy var confirmButton: UIButton = { UIButton(type: .custom) }() |
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.
Yeah this will really mess up my loading button but it should be fairly simple to fix
@@ -75,8 +78,14 @@ final class PledgeViewController: UIViewController, MessageBannerViewControllerP | |||
|> \.delegate .~ self | |||
}() | |||
|
|||
private lazy var submitButton: UIButton = { UIButton(type: .custom) }() |
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.
Is init with type
the designated initializer?
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.
Yeah we want this to be a custom
button to not have the highlight animation that system
buttons get.
@@ -40,7 +36,8 @@ public final class PledgePaymentMethodsViewModel: PledgePaymentMethodsViewModelT | |||
let configureWithValue = Signal.combineLatest( | |||
self.viewDidLoadProperty.signal, | |||
self.configureWithValueProperty.signal.skipNil() | |||
).map(second) | |||
) | |||
.map(second) |
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.
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.
super.viewDidLoad() | ||
|
||
self.configureSubviews() | ||
self.bindViewModel() |
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.
Isn't this happening through our swizzle thingys? 🤔
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.
Indeed, thanks.
@dusi Good catch on the snapshots - This is because the template |
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.
I can approve this if @ifbarrera is fine with this!
🚢 🚢 🚢
🚢 🚢 🚢
🚢 🚢 🚢
* Wire up change payment method to mutation for payment source and Apple Pay * Remove payment method when backing with Apple Pay and vice versa * Update tests for apple pay sheet race condition fixes * Replace zip with simpler signals * Add Stripe token error test * Move signals around, improve tests
📲 What
An unfortunately large PR that adds Change payment method UI to
PledgeViewController
.Note: This is UI-only, we'll add the mutation request in a subsequent PR, as well as the ability to update Apple Pay.
🤔 Why
Allows us to update the payment method for a pledge.
🛠 How
This repurposes the
PledgeViewController
to configure its views based on a thirdPledgeViewContext
,.changedPaymentMethod
. It also removes the pledge button fromPledgePaymentMethodsViewController
so that there is a singlesubmitButton
which triggers different events based on the context. We could consider doing this for the continue button too.changePaymentMethod
case toPledgeViewContext
enum.PledgeViewContext
which can be more easily map'd over inPledgeViewModel
.PledgeViewContext
.PledgeViewModel
for the new context.👀 See
✅ Acceptance criteria
Navigate to Manage Pledge on a project that you've backed, select
Change payment method
from the context menu.⏰ TODO
submitButton
to perform theupdateBacking
mutation in a subsequent PR.