-
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
[MBL-1210] Fix logged out and login flow for post campaign checkout #1991
Conversation
login 2
payment methods respond to login
|
||
// MARK: - Public functions | ||
|
||
func cancelPaymentSheetAppearance() { |
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 have no idea why this function used to live in a "delegate" (it was called a delegate, but it didn't behave like one). I've updated this to just be a public function, and because it can now be called before the view model is configured, I've correspondingly updated the view model to ignore changes here until it is configured.
f4f5494
to
a445140
Compare
// MARK: - Public functions | ||
|
||
func setShouldCancelPaymentSheetAppearance(hidden: Bool) { | ||
self.viewModel.inputs.shouldCancelPaymentSheetAppearance(state: hidden) |
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.
Nit: This method name isn't totally clear to me on first read. So it means the payment sheet normally would pop up, but now it won't? Appearance
makes me assume it's something like a modal.
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, or is this more like a dismissal?
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 this name is more clear than it was before but you're right - when I named it, I didn't know what it did either 😭. You're pretty much correct, though. Basically when you add a new card to the payment sheet, there's a loading indicator for a bit before the sheet pops up. Setting this to false (the only way it's used outside of tests) cancels that pop up (usually because we've presented a different modal instead). I think it might also dismiss the sheet itself if it's already presented by the time this is called, but I'm not sure about that one since that would only happen as a race condition. If you have any ideas for a different name, though, let me know!
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.
Hmmm...what about something like dontShowPaymentSheet
?
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'm just going to name it cancelModalPresentation
I think. That's clear enough while still being general enough that you don't need to understand the paymentMethodsVC to understand what the goal is.
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.
Sounds good to me!
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.
Some nits and commentary, but nothing blocking. Otherwise LGTM.
// MARK: - Public functions | ||
|
||
func setShouldCancelPaymentSheetAppearance(hidden: Bool) { | ||
self.viewModel.inputs.shouldCancelPaymentSheetAppearance(state: hidden) |
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, or is this more like a dismissal?
@@ -79,6 +81,10 @@ final class PostCampaignCheckoutViewController: UIViewController { | |||
self.viewModel.inputs.viewDidLoad() | |||
} | |||
|
|||
deinit { | |||
self.sessionStartedObserver.doIfSome(NotificationCenter.default.removeObserver) |
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.
Nifty, first time I've seen this in this codebase. Some kind of fancy RAC unsubscribe?
self.shouldCancelPaymentSheetAppearance.signal, | ||
configureWithValue | ||
) | ||
.map(first) |
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.
Nit: Most patterns I've seen in our codebase call configureWithValue
very early, like in onAppear
. When does this issue happen? Just seems a bit odd to need the protection.
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.
It happens in the logged out state! If the user is logged out, the payment sheet doesn't actually get configured, but we still say "hey, please don't show that extra modal" if the user interacts with the pledge cta (ex: if they want to log in). Leaving it as it was causes the app to crash when that happens.
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.
Aha, that makes sense! This would be a good comment, actually.
.compactMap { data -> PledgePaymentMethodsValue? in | ||
guard let user = AppEnvironment.current.currentUser else { return nil } | ||
guard let reward = data.rewards.first else { return nil } | ||
|
||
return (user, data.project, reward, data.context, data.refTag) | ||
} | ||
|
||
// TODO: Respond to login flow. | ||
let isLoggedIn = initialData.ignoreValues() | ||
self.goToLoginSignup = Signal.combineLatest(initialData, self.goToLoginSignupSignal) |
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 Signal.combineLatest(a, b).map(first)
effectively just a takeWhen
? If so, I find takeWhen
clearer.
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.
Nah, you're right, it's not any clearer, then. I guess it would be nice to have an operator like take(value: someSignal, whenAnyChange: [someSignal, anotherSignal, aThirdSignal])
but that is vastly out of scope here.
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.
Good point! I'm actually not sure if it would behave differently if b emits before a, but it's not like that should happen here, anyways. Fixed
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.
You were right about this one, actually! I just mixed up use-cases and made us both confused 😅
} | ||
|
||
self.showWebHelp = self.pledgeDisclaimerViewDidTapLearnMoreSignal.mapConst(.trust) | ||
self.paymentMethodsViewHidden = Signal.combineLatest(isLoggedIn, context) | ||
.map { !$0 || $1.paymentMethodsViewHidden } |
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.
Nit: Slightly hard to read with $0
, would prefer that these variables were named so we had !isLoggedIn || context.paymentMethodsViewHidden
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.
Good point, I'll update it!
@@ -101,12 +124,27 @@ public class PostCampaignCheckoutViewModel: PostCampaignCheckoutViewModelType, | |||
self.configureWithDataProperty.value = data | |||
} | |||
|
|||
private let (goToLoginSignupSignal, goToLoginSignupObserver) = Signal<Void, Never>.pipe() |
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.
First time I've seen this, what's the goal of using Signal<Void, Never>.pipe()
?
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, to be honest, this is also just copy-pasted from the standard pledge version of this VC/VM. But I think the point is that we want to react to button clicks - so we want to track whenever new events happen but we don't actually need it to pass along any data.
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.
Aah, gotcha. I think we mix Void
and ()
throughout the codebase. Seems fine.
d689535
to
23001d5
Compare
📲 What
Make "continue" button launch the login flow. Payment methods sheet should be hidden in logged out case and show up again once the user is logged in.
This makes the checkout VC a delegate of the pledge CTA and implements methods other than those corresponding to the "pledge" and "apple pay" buttons.
Note: This still hasn't added the extra warning to the pledge CTA. Since that can probably be added without touching the checkout VC, I'm going to do that in another pr to minimize merge conflicts.
👀 See
Jira
✅ Acceptance criteria