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

Show payment methods in vertical saved list #3573

Merged
merged 23 commits into from May 10, 2024
Merged

Conversation

porter-stripe
Copy link
Collaborator

@porter-stripe porter-stripe commented May 9, 2024

Summary

  • Adds ability to display and select payment methods in the VerticalSavedPaymentOptionsViewController
  • Adds delegates to communicate between the new PaymentMethodRowButton <> VerticalSavedPaymentOptionsViewController <> PaymentSheetVerticalViewController
  • Still grappling with the janky push animation, will fix later.
Simulator.Screen.Recording.-.iPhone.15.Plus.-.2024-05-09.at.14.50.26.mp4

Motivation

https://jira.corp.stripe.com/browse/MOBILESDK-2024

Testing

  • Manual
  • Snapshots

Changelog

N/A

@porter-stripe porter-stripe changed the title Porter/mobilesdk 2024 Show payment methods in vertical saved list May 9, 2024
@stripe stripe deleted a comment from github-actions bot May 9, 2024
import UIKit

/// Draws a circle with the desired fill color with a white checkmark in the center
final class CheckmarkCircleView: UIView {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omitted snapshot tests for this class and relying on the VerticalSavedPaymentOptionsViewControllerSnapshotTests. Can add them if we feel they will be useful.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I don't think this needs its own tests

// TODO(porter) Add did delete and did update
}

final class PaymentMethodRowButton: UIView {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, omitted snapshot tests for this view and relied on VerticalSavedPaymentOptionsViewControllerSnapshotTests.

return label
}()

private lazy var paymentMethodRows: [(paymentMethod: STPPaymentMethod, button: PaymentMethodRowButton)] = {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how I feel about this. It's tricky to associate a STPPaymentMethod with a PaymentMethodRowButton when:

  1. Not using a table/collection view
  2. Not muddying up the PaymentMethodRowButton.ViewModel with an STPPaymentMethod.

Open to suggestions

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have strong ideas either. Why not have the payment method as a property of the view (either in the viewmodel or just directly)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just felt like the PaymentMethodRowButton and PaymentMethodRowButton.ViewModel shouldn't know about an entire STPPaymentMethod and it should just know the data it needs to draw itself, no other reason.

@porter-stripe porter-stripe marked this pull request as ready for review May 9, 2024 20:51
@porter-stripe porter-stripe requested review from a team as code owners May 9, 2024 20:51
@@ -1,91 +0,0 @@
//
// VerticalSavedPaymentOptionsViewController.swift
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ooof, git doesn't recognize it was moved :(

Copy link
Collaborator

@yuki-stripe yuki-stripe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome!

Comment on lines +21 to +26
struct ViewModel {
let appearance: PaymentSheet.Appearance
let text: String
let image: UIImage
// TODO(porter) Add can remove and can update
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the idea behind putting this in a struct ViewModel rather than just making these properties on the PaymentMethodRowButton class directly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably not totally needed right now, but I anticipate this will scale better and am hoping in the future to create view models for PaymentMethodRowButton from a STPPaymentMethod. Mainly trying to keep the size of PaymentMethodRowButton.init down and offload the injection building somewhere else. Not totally needed but kinda like the direction.

extension STPPaymentMethod {
   var rowButtonViewModel: PaymentMethodRowButton.ViewModel {...}
}

// Somewhere else
let rowButtons = savedPaymentMethods.map{PaymentMethodRowButton(appearance: appearance, viewModel: $0.rowButtonViewModel)}

Comment on lines +101 to +102
/// Returns an image to display inside a row representing the given payment option in the saved PM row view
func makeSavedPaymentMethodRowImage() -> UIImage {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not reuse makeSavedPaymentMethodCellImage?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makeSavedPaymentMethodCellImage uses carousel images for card brands and for SEPA. We need the images that are used in the PAN field for card brand rather than the carousel images. Here the diff if we use makeSavedPaymentMethodCellImage, notice visa & SEPA look a little different than what is laid out in the mocks. The differences would be more sark in dark mode but I don't think we have mocks for dark mode.
CleanShot 2024-05-09 at 17 57 13

Mock

CleanShot 2024-05-09 at 17 58 11

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh right, we have 'carousel' versions of these. I guess we can delete those once we finish LPM visibility and the horizontal saved pm carousel goes away.

import UIKit

/// Draws a circle with the desired fill color with a white checkmark in the center
final class CheckmarkCircleView: UIView {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I don't think this needs its own tests

shadowRoundedRect.leadingAnchor.constraint(equalTo: leadingAnchor),
shadowRoundedRect.trailingAnchor.constraint(equalTo: trailingAnchor),
shadowRoundedRect.bottomAnchor.constraint(equalTo: bottomAnchor),
shadowRoundedRect.heightAnchor.constraint(equalToConstant: height),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without explicitly setting the height of the shadowRect it is just sized the minimum to fit the content. Is there a better way to do this?

Removing the shadowRoundedRect.heightAnchor.constraint(equalToConstant: height):
CleanShot 2024-05-09 at 18 11 17

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the stack view doesn't have top or bottom margins.

stackView.directionalLayoutMargins = PaymentSheetUI.defaultMargins

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good catch, ty!

return label
}()

private lazy var paymentMethodRows: [(paymentMethod: STPPaymentMethod, button: PaymentMethodRowButton)] = {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have strong ideas either. Why not have the payment method as a property of the view (either in the viewmodel or just directly)?

Comment on lines 42 to 46
return [STPFixtures.paymentMethod(),
STPFixtures.usBankAccountPaymentMethod(),
STPFixtures.usBankAccountPaymentMethod(bankName: "BANK OF AMERICA"),
STPFixtures.usBankAccountPaymentMethod(bankName: "STRIPE"),
STPFixtures.sepaDebitPaymentMethod(), ]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have two ways to provide fixtures unfortunately. THe old Obj-C way is static methods on STPFixtures class. THe new way is to provide extensions on the thing. See STPFixtures+PaymentSheet.swift. It already has STPPaymentMethod._testSEPA and I think it's a more ergonomic and scalable way we should use going forward.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably make a ticket to migrate us off of STPFixtures

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed here!. I'll leave as-is for now but I'll pick this up next time I'm on run.

@porter-stripe porter-stripe merged commit a5b1726 into master May 10, 2024
4 checks passed
@porter-stripe porter-stripe deleted the porter/MOBILESDK-2024 branch May 10, 2024 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants