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

Migrate PaymentMethodsActivity to use Activity Result API #3205

Merged
merged 3 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ ext {
ktlintVersion = '0.40.0'
materialVersion = '1.2.1'

fragmentVersion = '1.2.5'
fragmentVersion = '1.3.0-rc01'

androidTestVersion = '1.3.0'
}
Expand Down
3 changes: 2 additions & 1 deletion stripe/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation "androidx.fragment:fragment-ktx:$fragmentVersion"
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.activity:activity-ktx:1.2.0-rc01"

implementation 'com.google.android.gms:play-services-wallet:18.1.2'

Expand Down Expand Up @@ -58,7 +59,7 @@ dependencies {
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutinesVersion"
testImplementation 'com.google.truth:truth:1.1'
testImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "androidx.fragment:fragment-testing:$fragmentVersion"
testImplementation "androidx.fragment:fragment-testing:1.2.5"

androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
androidTestImplementation "androidx.test:rules:$androidTestVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ internal abstract class SheetViewModel<TransitionTargetType, ViewStateType>(
protected val mutablePaymentMethods = MutableLiveData<List<PaymentMethod>>()
internal val paymentMethods: LiveData<List<PaymentMethod>> = mutablePaymentMethods

private val mutableTransition = MutableLiveData<TransitionTargetType>()
internal val transition: LiveData<TransitionTargetType> = mutableTransition
private val mutableTransition = MutableLiveData<TransitionTargetType?>(null)
internal val transition: LiveData<TransitionTargetType?> = mutableTransition

private val mutableSelection = MutableLiveData<PaymentSelection?>()
internal val selection: LiveData<PaymentSelection?> = mutableSelection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.stripe.android.view

import android.content.Context
import android.content.Intent
import androidx.activity.result.contract.ActivityResultContract

internal class AddPaymentMethodContract :
ActivityResultContract<AddPaymentMethodActivityStarter.Args, AddPaymentMethodActivityStarter.Result>() {

override fun createIntent(
context: Context,
input: AddPaymentMethodActivityStarter.Args?
): Intent {
return Intent(context, AddPaymentMethodActivity::class.java)
.putExtra(ActivityStarter.Args.EXTRA, input)
}

override fun parseResult(
resultCode: Int,
mshafrir-stripe marked this conversation as resolved.
Show resolved Hide resolved
intent: Intent?
): AddPaymentMethodActivityStarter.Result {
return AddPaymentMethodActivityStarter.Result.fromIntent(intent)
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
package com.stripe.android.view

import android.app.Activity
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.annotation.IdRes
import androidx.annotation.StringRes
import com.stripe.android.R
import com.stripe.android.databinding.AddPaymentMethodRowBinding
import com.stripe.android.model.PaymentMethod

@SuppressWarnings("ViewConstructor")
internal class AddPaymentMethodRowView private constructor(
context: Context,
@IdRes idRes: Int,
@StringRes private val labelRes: Int,
private val args: AddPaymentMethodActivityStarter.Args
context: Context
) : FrameLayout(context) {

private val viewBinding = AddPaymentMethodRowBinding.inflate(
Expand All @@ -25,62 +16,11 @@ internal class AddPaymentMethodRowView private constructor(
true
)

internal val label = viewBinding.label

init {
id = idRes
layoutParams = ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)

isFocusable = true
isClickable = true

contentDescription = context.getString(labelRes)
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewBinding.label.setText(labelRes)

(context as? Activity)?.let { activity ->
setOnClickListener {
AddPaymentMethodActivityStarter(activity).startForResult(args)
}
}
}

internal companion object {
internal fun createCard(
activity: Activity,
args: PaymentMethodsActivityStarter.Args
): AddPaymentMethodRowView {
return AddPaymentMethodRowView(
activity,
R.id.stripe_payment_methods_add_card,
R.string.payment_method_add_new_card,
AddPaymentMethodActivityStarter.Args.Builder()
.setBillingAddressFields(args.billingAddressFields)
.setShouldAttachToCustomer(true)
.setIsPaymentSessionActive(args.isPaymentSessionActive)
.setPaymentMethodType(PaymentMethod.Type.Card)
.setAddPaymentMethodFooter(args.addPaymentMethodFooterLayoutId)
.setPaymentConfiguration(args.paymentConfiguration)
.setWindowFlags(args.windowFlags)
.build()
)
}

internal fun createFpx(
activity: Activity,
args: PaymentMethodsActivityStarter.Args
): AddPaymentMethodRowView {
return AddPaymentMethodRowView(
activity,
R.id.stripe_payment_methods_add_fpx,
R.string.payment_method_add_new_fpx,
AddPaymentMethodActivityStarter.Args.Builder()
.setIsPaymentSessionActive(args.isPaymentSessionActive)
.setPaymentMethodType(PaymentMethod.Type.Fpx)
.setPaymentConfiguration(args.paymentConfiguration)
.build()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.activity.viewModels
import androidx.annotation.VisibleForTesting
import androidx.appcompat.app.AppCompatActivity
import androidx.core.text.util.LinkifyCompat
import androidx.core.view.ViewCompat
Expand Down Expand Up @@ -91,27 +92,31 @@ class PaymentMethodsActivity : AppCompatActivity() {
window.addFlags(it)
}

viewModel.snackbarData.observe(
this,
{ snackbarText ->
snackbarText?.let {
Snackbar.make(viewBinding.coordinator, it, Snackbar.LENGTH_SHORT).show()
}
viewModel.snackbarData.observe(this) { snackbarText ->
snackbarText?.let {
Snackbar.make(viewBinding.coordinator, it, Snackbar.LENGTH_SHORT).show()
}
)
viewModel.progressData.observe(
this,
{
viewBinding.progressBar.visibility = if (it) {
View.VISIBLE
} else {
View.GONE
}
}
viewModel.progressData.observe(this) {
viewBinding.progressBar.visibility = if (it) {
View.VISIBLE
} else {
View.GONE
}
)
}

setupRecyclerView()

val addPaymentMethodLauncher = registerForActivityResult(
AddPaymentMethodContract(),
::onAddPaymentMethodResult
)
adapter.addPaymentMethodArgs.observe(this) { args ->
if (args != null) {
addPaymentMethodLauncher.launch(args)
}
}

setSupportActionBar(viewBinding.toolbar)

supportActionBar?.apply {
Expand Down Expand Up @@ -171,36 +176,24 @@ class PaymentMethodsActivity : AppCompatActivity() {
}
}

public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == AddPaymentMethodActivityStarter.REQUEST_CODE &&
resultCode == Activity.RESULT_OK
) {
onPaymentMethodCreated(data)
}
}

override fun onSupportNavigateUp(): Boolean {
finishWithResult(adapter.selectedPaymentMethod, Activity.RESULT_CANCELED)
return true
}

private fun onPaymentMethodCreated(data: Intent?) {
data?.let {
val result =
AddPaymentMethodActivityStarter.Result.fromIntent(data)
when (result) {
is AddPaymentMethodActivityStarter.Result.Success -> {
onAddedPaymentMethod(result.paymentMethod)
}
is AddPaymentMethodActivityStarter.Result.Failure -> {
// TODO(mshafrir-stripe): notify user that payment method can not be added at this time
}
else -> {
// no-op
}
@VisibleForTesting
internal fun onAddPaymentMethodResult(result: AddPaymentMethodActivityStarter.Result) {
when (result) {
is AddPaymentMethodActivityStarter.Result.Success -> {
onAddedPaymentMethod(result.paymentMethod)
}
is AddPaymentMethodActivityStarter.Result.Failure -> {
// TODO(mshafrir-stripe): notify user that payment method can not be added at this time
}
} ?: fetchCustomerPaymentMethods()
else -> {
// no-op
}
}
}

private fun onAddedPaymentMethod(paymentMethod: PaymentMethod) {
Expand All @@ -221,27 +214,24 @@ class PaymentMethodsActivity : AppCompatActivity() {
}

private fun fetchCustomerPaymentMethods() {
viewModel.getPaymentMethods().observe(
this,
{ result ->
result.fold(
onSuccess = { adapter.setPaymentMethods(it) },
onFailure = {
alertDisplayer.show(
when (it) {
is StripeException -> {
TranslatorManager.getErrorMessageTranslator()
.translate(it.statusCode, it.message, it.stripeError)
}
else -> {
it.message.orEmpty()
}
viewModel.getPaymentMethods().observe(this) { result ->
result.fold(
onSuccess = { adapter.setPaymentMethods(it) },
onFailure = {
alertDisplayer.show(
when (it) {
is StripeException -> {
TranslatorManager.getErrorMessageTranslator()
.translate(it.statusCode, it.message, it.stripeError)
}
)
}
)
}
)
else -> {
it.message.orEmpty()
}
}
)
}
)
}
}

private fun finishWithGooglePay() {
Expand Down
Loading