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

Fix don't keep activities on add fragment. #4466

Merged
merged 39 commits into from
Feb 8, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
834e92c
Works for card element
michelleb-stripe Dec 13, 2021
167eb4a
Fix add fragment save card.
michelleb-stripe Dec 13, 2021
e67917f
Fix up comments explaing the why
michelleb-stripe Dec 13, 2021
f83fc1d
Cleanup code
michelleb-stripe Dec 13, 2021
5919b77
Add a note on the save customer card flow.
michelleb-stripe Dec 15, 2021
0e1f842
Add in SaveStateHandle
michelleb-stripe Dec 17, 2021
d6c2321
Working version with lots of extra log statements.
michelleb-stripe Dec 17, 2021
e421f0e
Remove log statements
michelleb-stripe Dec 17, 2021
f33bd72
Save the selected item
michelleb-stripe Dec 17, 2021
9c6bf52
Add savedHandleState to PaymentOptionsViewModel.
michelleb-stripe Dec 17, 2021
105e4eb
Returning user, on authentication screen, home, recent activities, Ca…
michelleb-stripe Dec 17, 2021
a54bbc5
Guest, Complete, home, recent, makes so not in processing state
michelleb-stripe Dec 17, 2021
110cf4b
PaymentSheet Complete working.
michelleb-stripe Dec 18, 2021
27fb25d
Fix problem in options flow
michelleb-stripe Dec 18, 2021
430175a
Merge branch 'master' into michelleb/dka-add-fragment
michelleb-stripe Dec 20, 2021
3ec4d42
All working.
michelleb-stripe Dec 21, 2021
a8558c1
Cleanup event reporter and other code.
michelleb-stripe Dec 21, 2021
1b5a9a6
Working on unit tests.
michelleb-stripe Dec 21, 2021
2bd6640
Unit tests passing and manual testing complete
michelleb-stripe Dec 22, 2021
6251944
Undo weak registry map changes.
michelleb-stripe Dec 22, 2021
4b6d36c
Add injection and injection fallback tests.
michelleb-stripe Dec 22, 2021
fb63654
format and apiDump
michelleb-stripe Dec 22, 2021
97ffad6
format and apiDump
michelleb-stripe Dec 22, 2021
53c68b0
Fix intermittent failures
michelleb-stripe Dec 22, 2021
a1823a6
Merge with master
michelleb-stripe Jan 10, 2022
281158e
format
michelleb-stripe Jan 10, 2022
bcfb35c
Merge remote-tracking branch 'origin/master' into michelleb/dka-add-f…
michelleb-stripe Jan 31, 2022
040b914
Fix bug launching google pay.
michelleb-stripe Jan 31, 2022
78d1113
Fix bug on add button.
michelleb-stripe Feb 2, 2022
a67a496
Fix bug launching google pay.
michelleb-stripe Feb 3, 2022
ce57694
Update payments-core/src/test/java/com/stripe/android/googlepaylaunch…
michelleb-stripe Feb 7, 2022
2734828
Merge with master
michelleb-stripe Feb 7, 2022
ec9fd9b
Merge branch 'michelleb/dka-add-fragment' of github.com:stripe/stripe…
michelleb-stripe Feb 7, 2022
40bf19b
Remove parcelable on TransitionTarget and fix test dispatcher class.
michelleb-stripe Feb 7, 2022
fb1bb27
Cleanup
michelleb-stripe Feb 7, 2022
57607bd
Update paymentsheet/src/main/java/com/stripe/android/paymentsheet/Pay…
michelleb-stripe Feb 8, 2022
7cb4342
Update paymentsheet/src/main/java/com/stripe/android/paymentsheet/Pay…
michelleb-stripe Feb 8, 2022
314f5a3
Remove println
michelleb-stripe Feb 8, 2022
f0a9994
Merge branch 'michelleb/dka-add-fragment' of github.com:stripe/stripe…
michelleb-stripe Feb 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import androidx.fragment.app.commit
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.stripe.android.model.StripeIntent
import com.stripe.android.core.injection.InjectorKey
import com.stripe.android.model.StripeIntent
import com.stripe.android.paymentsheet.analytics.EventReporter
import com.stripe.android.paymentsheet.databinding.FragmentPaymentsheetAddPaymentMethodBinding
import com.stripe.android.paymentsheet.forms.FormFieldValues
import com.stripe.android.ui.core.Amount
import com.stripe.android.paymentsheet.model.PaymentSelection
import com.stripe.android.paymentsheet.model.SupportedPaymentMethod
import com.stripe.android.paymentsheet.paymentdatacollection.CardDataCollectionFragment
Expand All @@ -30,6 +29,7 @@ import com.stripe.android.paymentsheet.paymentdatacollection.TransformToPaymentM
import com.stripe.android.paymentsheet.ui.AddPaymentMethodsFragmentFactory
import com.stripe.android.paymentsheet.ui.AnimationConstants
import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel
import com.stripe.android.ui.core.Amount
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

Expand Down Expand Up @@ -93,32 +93,48 @@ internal abstract class BaseAddPaymentMethodFragment(
}

if (paymentMethods.isNotEmpty()) {
replacePaymentMethodFragment(paymentMethods[selectedPaymentMethodIndex])
// If the activity is destroyed and recreated, then the fragment is already present
// and doesn't need to be replaced, only the selected payment method needs to be set
if (savedInstanceState == null) {
replacePaymentMethodFragment(paymentMethods[selectedPaymentMethodIndex])
} else {
selectedPaymentMethod = paymentMethods[selectedPaymentMethodIndex]
}
}

sheetViewModel.processing.observe(viewLifecycleOwner) { isProcessing ->
(getFragment() as? ComposeFormDataCollectionFragment)?.setProcessing(isProcessing)
}

// If the activity was destroyed and recreated then we need to re-attach the fragment,
// as attach will not be called again.
childFragmentManager.fragments.forEach { fragment ->
attachComposeFragmentViewModel(fragment)
}

childFragmentManager.addFragmentOnAttachListener { _, fragment ->
(fragment as? ComposeFormDataCollectionFragment)?.let { formFragment ->
// Need to access the formViewModel so it is constructed.
val formViewModel = formFragment.formViewModel
viewLifecycleOwner.lifecycleScope.launch {
formViewModel.completeFormValues.collect { formFieldValues ->
sheetViewModel.updateSelection(
transformToPaymentSelection(
formFieldValues,
formFragment.paramKeySpec,
selectedPaymentMethod
)
attachComposeFragmentViewModel(fragment)
}

eventReporter.onShowNewPaymentOptionForm()
}

private fun attachComposeFragmentViewModel(fragment: Fragment) {
(fragment as? ComposeFormDataCollectionFragment)?.let { formFragment ->
// Need to access the formViewModel so it is constructed.
val formViewModel = formFragment.formViewModel
viewLifecycleOwner.lifecycleScope.launch {
formViewModel.completeFormValues.collect { formFieldValues ->
sheetViewModel.updateSelection(
transformToPaymentSelection(
formFieldValues,
formFragment.paramKeySpec,
selectedPaymentMethod
)
}
)
Copy link
Contributor

Choose a reason for hiding this comment

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

Unrelated to this change, but what we're doing here can be achieved with launchIn: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/launch-in.html

}
}
}

eventReporter.onShowNewPaymentOptionForm()
}

private fun setupRecyclerView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ import androidx.lifecycle.lifecycleScope
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.appbar.MaterialToolbar
import com.stripe.android.googlepaylauncher.GooglePayPaymentMethodLauncherContract
import com.stripe.android.model.PaymentIntent
import com.stripe.android.model.SetupIntent
import com.stripe.android.paymentsheet.PaymentSheetViewModel.CheckoutIdentifier
import com.stripe.android.paymentsheet.databinding.ActivityPaymentSheetBinding
import com.stripe.android.ui.core.Amount
import com.stripe.android.paymentsheet.model.PaymentSelection
import com.stripe.android.paymentsheet.model.PaymentSheetViewState
import com.stripe.android.paymentsheet.ui.AnimationConstants
import com.stripe.android.paymentsheet.ui.BaseSheetActivity
import com.stripe.android.paymentsheet.viewmodels.BaseSheetViewModel
import com.stripe.android.ui.core.Amount
import com.stripe.android.ui.core.CurrencyFormatter
import kotlinx.coroutines.launch
import java.security.InvalidParameterException
Expand Down Expand Up @@ -106,7 +108,22 @@ internal class PaymentSheetActivity : BaseSheetActivity<PaymentSheetResult>() {
viewModel::onGooglePayResult
)
)
viewModel.maybeFetchStripeIntent()

// If the activity was destroyed we need to restore the payment intent without triggering
// the transition (which would replace the existing fragment). The button container
// and buy button visibility must be visible again.
when (savedInstanceState?.getBoolean(SAVE_IS_PAYMENT_INTENT_TYPE)) {
true -> savedInstanceState.getParcelable<PaymentIntent>(SAVE_STRIPE_INTENT)
false -> savedInstanceState.getParcelable<SetupIntent>(SAVE_STRIPE_INTENT)
null -> null
}?.let {
// The buy btton needs to be made visible since it is gone in the xml
michelleb-stripe marked this conversation as resolved.
Show resolved Hide resolved
viewModel.setStripeIntent(it)
buttonContainer.isVisible = true
viewBinding.buyButton.isVisible = true
} ?: run {
viewModel.maybeFetchStripeIntent()
}

starterArgs.statusBarColor?.let {
window.statusBarColor = it
Expand Down Expand Up @@ -176,6 +193,12 @@ internal class PaymentSheetActivity : BaseSheetActivity<PaymentSheetResult>() {
super.onBackPressed()
}

override fun onSaveInstanceState(outState: Bundle) {
outState.putParcelable(SAVE_STRIPE_INTENT, viewModel.stripeIntent.value)
outState.putBoolean(SAVE_IS_PAYMENT_INTENT_TYPE, viewModel.isProcessingPaymentIntent)
super.onSaveInstanceState(outState)
}

private fun updateErrorMessage(userMessage: BaseSheetViewModel.UserErrorMessage? = null) {
messageView.isVisible = userMessage != null
messageView.text = userMessage?.message
Expand Down Expand Up @@ -306,6 +329,11 @@ internal class PaymentSheetActivity : BaseSheetActivity<PaymentSheetResult>() {
}

internal companion object {

private const val SAVE_STRIPE_INTENT =
"com.stripe.android.paymentsheet.paymentsheetactivity.save_stripe_intent"
private const val SAVE_IS_PAYMENT_INTENT_TYPE =
"com.stripe.android.paymentsheet.paymentsheetactivity.save_stripe_intent_type"
internal const val EXTRA_FRAGMENT_CONFIG = BaseSheetActivity.EXTRA_FRAGMENT_CONFIG
internal const val EXTRA_STARTER_ARGS = BaseSheetActivity.EXTRA_STARTER_ARGS
}
Expand Down