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

[MBL-1210] Fix logged out and login flow for post campaign checkout #1991

Merged
merged 10 commits into from
Mar 21, 2024

Conversation

ifosli
Copy link
Contributor

@ifosli ifosli commented Mar 20, 2024

📲 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

Simulator Screen Recording - iPhone 15 Pro Max - 2024-03-20 at 16 02 58

✅ Acceptance criteria

  • Checkout screen looks good when the user is logged out
  • Checkout screen is back to normal when the user logs in by hitting "continue" button

@ifosli ifosli self-assigned this Mar 20, 2024

// MARK: - Public functions

func cancelPaymentSheetAppearance() {
Copy link
Contributor Author

@ifosli ifosli Mar 20, 2024

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.

@ifosli ifosli force-pushed the loginFlowPostCampaign branch from f4f5494 to a445140 Compare March 20, 2024 22:25
@ifosli ifosli marked this pull request as ready for review March 20, 2024 22:28
@ifosli ifosli requested review from a team and amy-at-kickstarter and removed request for a team March 20, 2024 22:28
// MARK: - Public functions

func setShouldCancelPaymentSheetAppearance(hidden: Bool) {
self.viewModel.inputs.shouldCancelPaymentSheetAppearance(state: hidden)
Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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!

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good to me!

Copy link
Contributor

@amy-at-kickstarter amy-at-kickstarter left a 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)
Copy link
Contributor

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)
Copy link
Contributor

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)
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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)
Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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

Copy link
Contributor Author

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 }
Copy link
Contributor

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

Copy link
Contributor Author

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()
Copy link
Contributor

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()?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@ifosli ifosli force-pushed the loginFlowPostCampaign branch from d689535 to 23001d5 Compare March 21, 2024 15:59
@ifosli ifosli merged commit d696e55 into main Mar 21, 2024
5 checks passed
@ifosli ifosli deleted the loginFlowPostCampaign branch March 21, 2024 18:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants