Skip to content

Commit

Permalink
Refactor FormUI for Link use (#4942)
Browse files Browse the repository at this point in the history
  • Loading branch information
brnunes-stripe authored May 3, 2022
1 parent 2586024 commit 1d5408b
Show file tree
Hide file tree
Showing 18 changed files with 364 additions and 288 deletions.
35 changes: 35 additions & 0 deletions payments-ui-core/api/payments-ui-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ public final class com/stripe/android/ui/core/BuildConfig {
public fun <init> ()V
}

public final class com/stripe/android/ui/core/FieldValuesToParamsMapConverter$Companion {
public final fun transformToPaymentMethodCreateParams (Ljava/util/Map;Lcom/stripe/android/model/PaymentMethod$Type;)Lcom/stripe/android/model/PaymentMethodCreateParams;
}

public final class com/stripe/android/ui/core/FormUIKt {
}

public final class com/stripe/android/ui/core/MeasureComposableWidthKt {
}

Expand Down Expand Up @@ -115,6 +122,14 @@ public final class com/stripe/android/ui/core/elements/IdentifierSpec$CardBrand
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class com/stripe/android/ui/core/elements/IdentifierSpec$CardCvc : com/stripe/android/ui/core/elements/IdentifierSpec {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
public static final field INSTANCE Lcom/stripe/android/ui/core/elements/IdentifierSpec$CardCvc;
public fun describeContents ()I
public fun writeToParcel (Landroid/os/Parcel;I)V
}

public final class com/stripe/android/ui/core/elements/IdentifierSpec$CardNumber : com/stripe/android/ui/core/elements/IdentifierSpec {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
Expand Down Expand Up @@ -268,6 +283,7 @@ public final class com/stripe/android/ui/core/forms/BancontactSpecKt {

public final class com/stripe/android/ui/core/forms/CardSpecKt {
public static final fun getCardForm ()Lcom/stripe/android/ui/core/elements/LayoutSpec;
public static final fun getLinkCardForm ()Lcom/stripe/android/ui/core/elements/LayoutSpec;
}

public final class com/stripe/android/ui/core/forms/EpsSpecKt {
Expand Down Expand Up @@ -320,3 +336,22 @@ public final class com/stripe/android/ui/core/forms/resources/AsyncResourceRepos
public static fun newInstance (Landroid/content/res/Resources;Lkotlin/coroutines/CoroutineContext;Ljava/util/Locale;)Lcom/stripe/android/ui/core/forms/resources/AsyncResourceRepository;
}

public abstract class com/stripe/android/ui/core/forms/resources/injection/ResourceRepositoryModule {
public static final field $stable I
public static final field Companion Lcom/stripe/android/ui/core/forms/resources/injection/ResourceRepositoryModule$Companion;
public fun <init> ()V
public abstract fun bindsResourceRepository (Lcom/stripe/android/ui/core/forms/resources/AsyncResourceRepository;)Lcom/stripe/android/ui/core/forms/resources/ResourceRepository;
}

public final class com/stripe/android/ui/core/forms/resources/injection/ResourceRepositoryModule$Companion {
public final fun provideResources (Landroid/content/Context;)Landroid/content/res/Resources;
}

public final class com/stripe/android/ui/core/forms/resources/injection/ResourceRepositoryModule_Companion_ProvideResourcesFactory : dagger/internal/Factory {
public fun <init> (Ljavax/inject/Provider;)V
public static fun create (Ljavax/inject/Provider;)Lcom/stripe/android/ui/core/forms/resources/injection/ResourceRepositoryModule_Companion_ProvideResourcesFactory;
public fun get ()Landroid/content/res/Resources;
public synthetic fun get ()Ljava/lang/Object;
public static fun provideResources (Landroid/content/Context;)Landroid/content/res/Resources;
}

Original file line number Diff line number Diff line change
@@ -1,58 +1,59 @@
package com.stripe.android.paymentsheet.paymentdatacollection
package com.stripe.android.ui.core

import androidx.annotation.RestrictTo
import androidx.annotation.VisibleForTesting
import com.stripe.android.model.PaymentMethod
import com.stripe.android.model.PaymentMethodCreateParams
import com.stripe.android.paymentsheet.forms.FormFieldValues
import com.stripe.android.ui.core.elements.IdentifierSpec
import com.stripe.android.ui.core.forms.FormFieldEntry

/**
* This class will transform the fields in a form into a structure as defined by a map.
* This class converts the fields in a form into a structure as defined by a map.
*/
internal class TransformToPaymentMethodCreateParams {
/**
* This function will convert formFieldValue to PaymentMethodCreateParams.
*/
fun transform(
formFieldValues: FormFieldValues,
type: PaymentMethod.Type
) = transformToPaymentMethodCreateParamsMap(
formFieldValues,
type
)
.filterOutNullValues()
.toMap()
.run {
PaymentMethodCreateParams.createWithOverride(
type,
overrideParamMap = this,
productUsage = setOf("PaymentSheet")
)
}
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
class FieldValuesToParamsMapConverter {
companion object {
/**
* This function will convert fieldValuePairs to PaymentMethodCreateParams.
*/
fun transformToPaymentMethodCreateParams(
fieldValuePairs: Map<IdentifierSpec, FormFieldEntry>,
type: PaymentMethod.Type
) = transformToParamsMap(
fieldValuePairs,
type
)
.filterOutNullValues()
.toMap()
.run {
PaymentMethodCreateParams.createWithOverride(
type,
overrideParamMap = this,
productUsage = setOf("PaymentSheet")
)
}

/**
* This function will put the field values as defined in the formFieldValues into a map
* according to the mapLayout structure.
*
* @param: mapLayout: This is a map of keys (strings) and their values (String or another map). This defines
* how the resulting map should look with no values in it.
* @param: formFieldValues: These are the fields and their values and based on the algorithm of this function
* will be put into a map according to the mapStructure
*/
private fun transformToPaymentMethodCreateParamsMap(
formFieldValues: FormFieldValues,
type: PaymentMethod.Type,
): MutableMap<String, Any?> {
val destMap = mutableMapOf<String, Any?>()
/**
* This function will put the field values as defined in the fieldValuePairs into a map
* according to their keys.
*
* @param: formFieldValues: These are the fields and their values and based on the algorithm of this function
* will be put into a map according to the IdentifierSpec keys.
*/
private fun transformToParamsMap(
fieldValuePairs: Map<IdentifierSpec, FormFieldEntry>,
type: PaymentMethod.Type,
): MutableMap<String, Any?> {
val destMap = mutableMapOf<String, Any?>()

val formKeyValueMap = formFieldValues.fieldValuePairs
.mapValues { entry -> entry.value.value }
.mapKeys { it.key.v1 }
val formKeyValueMap = fieldValuePairs
.mapValues { entry -> entry.value.value }
.mapKeys { it.key.v1 }

createMap(type, destMap, formKeyValueMap)
return destMap
}
createMap(type, destMap, formKeyValueMap)
return destMap
}

companion object {
/**
* This function will take the identifier from the form field entry, separate it on
* square braces and construct a map from it.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.stripe.android.ui.core

import androidx.annotation.RestrictTo
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import com.stripe.android.ui.core.elements.AffirmElementUI
import com.stripe.android.ui.core.elements.AffirmHeaderElement
import com.stripe.android.ui.core.elements.AfterpayClearpayElementUI
import com.stripe.android.ui.core.elements.AfterpayClearpayHeaderElement
import com.stripe.android.ui.core.elements.AuBecsDebitMandateElementUI
import com.stripe.android.ui.core.elements.AuBecsDebitMandateTextElement
import com.stripe.android.ui.core.elements.BsbElement
import com.stripe.android.ui.core.elements.BsbElementUI
import com.stripe.android.ui.core.elements.CardDetailsSectionElement
import com.stripe.android.ui.core.elements.CardDetailsSectionElementUI
import com.stripe.android.ui.core.elements.EmptyFormElement
import com.stripe.android.ui.core.elements.FormElement
import com.stripe.android.ui.core.elements.IdentifierSpec
import com.stripe.android.ui.core.elements.MandateTextElement
import com.stripe.android.ui.core.elements.MandateTextUI
import com.stripe.android.ui.core.elements.SaveForFutureUseElement
import com.stripe.android.ui.core.elements.SaveForFutureUseElementUI
import com.stripe.android.ui.core.elements.SectionElement
import com.stripe.android.ui.core.elements.SectionElementUI
import com.stripe.android.ui.core.elements.StaticElementUI
import com.stripe.android.ui.core.elements.StaticTextElement
import kotlinx.coroutines.flow.Flow

@Composable
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
fun FormUI(
hiddenIdentifiersFlow: Flow<List<IdentifierSpec>>,
enabledFlow: Flow<Boolean>,
elementsFlow: Flow<List<FormElement>?>,
lastTextFieldIdentifierFlow: Flow<IdentifierSpec?>,
loadingComposable: @Composable ColumnScope.() -> Unit
) {
val hiddenIdentifiers by hiddenIdentifiersFlow.collectAsState(emptyList())
val enabled by enabledFlow.collectAsState(true)
val elements by elementsFlow.collectAsState(null)
val lastTextFieldIdentifier by lastTextFieldIdentifierFlow.collectAsState(null)

Column(
modifier = Modifier.fillMaxWidth(1f)
) {
elements?.let {
it.forEachIndexed { _, element ->
if (!hiddenIdentifiers.contains(element.identifier)) {
when (element) {
is SectionElement -> SectionElementUI(
enabled,
element,
hiddenIdentifiers,
lastTextFieldIdentifier
)
is StaticTextElement -> StaticElementUI(element)
is SaveForFutureUseElement -> SaveForFutureUseElementUI(enabled, element)
is AfterpayClearpayHeaderElement -> AfterpayClearpayElementUI(
enabled,
element
)
is AuBecsDebitMandateTextElement -> AuBecsDebitMandateElementUI(element)
is AffirmHeaderElement -> AffirmElementUI()
is MandateTextElement -> MandateTextUI(element)
is CardDetailsSectionElement -> CardDetailsSectionElementUI(
enabled, element.controller, hiddenIdentifiers
)
is BsbElement -> BsbElementUI(enabled, element, lastTextFieldIdentifier)
is EmptyFormElement -> {}
}
}
}
} ?: loadingComposable()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ internal class CardDetailsController constructor(
)

val cvcElement = CvcElement(
IdentifierSpec.Generic("card[cvc]"),
IdentifierSpec.CardCvc,
CvcController(
CvcConfig(),
numberElement.controller.cardBrandFlow,
initialValue = initialValues[IdentifierSpec.Generic("card[cvc]")]
initialValue = initialValues[IdentifierSpec.CardCvc]
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ sealed class IdentifierSpec(val v1: String) : Parcelable {
@Parcelize
object CardNumber : IdentifierSpec("card[number]")

@Parcelize
object CardCvc : IdentifierSpec("card[cvc]")

@Parcelize
object Email : IdentifierSpec("billing_details[email]")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.stripe.android.ui.core.elements

import android.util.Log
import android.view.KeyEvent
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxWidth
Expand Down Expand Up @@ -47,8 +46,6 @@ internal fun TextField(
imeAction: ImeAction,
enabled: Boolean
) {
Log.d("Construct", "SimpleTextFieldElement ${textFieldController.debugLabel}")

val focusManager = LocalFocusManager.current
val value by textFieldController.fieldValue.collectAsState("")
val trailingIcon by textFieldController.trailingIcon.collectAsState(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import com.stripe.android.ui.core.elements.SaveForFutureUseSpec
import com.stripe.android.ui.core.elements.SectionSpec
import com.stripe.android.ui.core.elements.supportedBillingCountries

internal val creditBillingSection = SectionSpec(
IdentifierSpec.Generic("credit_billing_section"),
internal val cardBillingSection = SectionSpec(
IdentifierSpec.Generic("card_billing_section"),
CardBillingSpec(
countryCodes = supportedBillingCountries
),
Expand All @@ -20,7 +20,13 @@ internal val creditBillingSection = SectionSpec(

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
val CardForm = LayoutSpec.create(
CardDetailsSectionSpec(IdentifierSpec.Generic("credit_details_section")),
creditBillingSection,
CardDetailsSectionSpec(IdentifierSpec.Generic("card_details_section")),
cardBillingSection,
SaveForFutureUseSpec(emptyList())
)

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
val LinkCardForm = LayoutSpec.create(
CardDetailsSectionSpec(IdentifierSpec.Generic("card_details_section")),
cardBillingSection
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.stripe.android.ui.core.forms.resources.injection

import android.content.Context
import android.content.res.Resources
import com.stripe.android.ui.core.forms.resources.AsyncResourceRepository
import com.stripe.android.ui.core.forms.resources.ResourceRepository
import dagger.Binds
import dagger.Module
import dagger.Provides
import javax.inject.Singleton

@Module
abstract class ResourceRepositoryModule {
@Binds
abstract fun bindsResourceRepository(asyncResourceRepository: AsyncResourceRepository):
ResourceRepository

companion object {

@Provides
@Singleton
fun provideResources(context: Context): Resources {
return context.resources
}
}
}
Loading

0 comments on commit 1d5408b

Please sign in to comment.