-
Notifications
You must be signed in to change notification settings - Fork 68
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #679 from Adyen/feature/full-address-form
Full Address Form
- Loading branch information
Showing
75 changed files
with
2,858 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
card/src/main/java/com/adyen/checkout/card/AddressConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package com.adyen.checkout.card | ||
|
||
import android.os.Parcel | ||
import android.os.Parcelable | ||
|
||
/** | ||
* Configuration class for Address Form in Card Component. This class can be used define the | ||
* visibility of the address form. | ||
*/ | ||
sealed class AddressConfiguration : Parcelable { | ||
|
||
/** | ||
* Address Form will be hidden. | ||
*/ | ||
object None : AddressConfiguration() { | ||
@JvmField | ||
val CREATOR = object : Parcelable.Creator<None> { | ||
override fun createFromParcel(source: Parcel?) = None | ||
override fun newArray(size: Int) = arrayOfNulls<None>(size) | ||
} | ||
override fun describeContents() = Parcelable.CONTENTS_FILE_DESCRIPTOR | ||
override fun writeToParcel(dest: Parcel?, flags: Int) { | ||
// no ops | ||
} | ||
} | ||
|
||
/** | ||
* Only postal code will be shown as part of the card component. | ||
*/ | ||
object PostalCode : AddressConfiguration() { | ||
@JvmField | ||
val CREATOR = object : Parcelable.Creator<PostalCode> { | ||
override fun createFromParcel(source: Parcel?) = PostalCode | ||
override fun newArray(size: Int) = arrayOfNulls<PostalCode>(size) | ||
} | ||
override fun describeContents() = Parcelable.CONTENTS_FILE_DESCRIPTOR | ||
override fun writeToParcel(dest: Parcel?, flags: Int) { | ||
// no ops | ||
} | ||
} | ||
|
||
/** | ||
* Full Address Form will be shown as part of the card component. | ||
* | ||
* @param defaultCountryCode Default country to be selected while initializing the form. | ||
* @param supportedCountryCodes Supported country codes to be filtered from the available country | ||
* options. | ||
*/ | ||
data class FullAddress( | ||
val defaultCountryCode: String? = null, | ||
val supportedCountryCodes: List<String> = emptyList() | ||
) : AddressConfiguration() { | ||
companion object { | ||
@JvmField | ||
val CREATOR = object : Parcelable.Creator<FullAddress> { | ||
@Suppress("UNCHECKED_CAST") | ||
override fun createFromParcel(source: Parcel) = FullAddress( | ||
defaultCountryCode = source.readString(), | ||
supportedCountryCodes = source.readArrayList(String::class.java.classLoader) as List<String> | ||
) | ||
override fun newArray(size: Int) = arrayOfNulls<FullAddress>(size) | ||
} | ||
} | ||
|
||
override fun describeContents() = Parcelable.CONTENTS_FILE_DESCRIPTOR | ||
override fun writeToParcel(dest: Parcel, flags: Int) { | ||
dest.writeString(defaultCountryCode) | ||
dest.writeList(supportedCountryCodes) | ||
} | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
card/src/main/java/com/adyen/checkout/card/AddressDelegate.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright (c) 2022 Adyen N.V. | ||
* | ||
* This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
* | ||
* Created by ozgur on 18/3/2022. | ||
*/ | ||
|
||
package com.adyen.checkout.card | ||
|
||
import android.util.LruCache | ||
import com.adyen.checkout.card.api.AddressDataType | ||
import com.adyen.checkout.card.api.model.AddressItem | ||
import com.adyen.checkout.card.repository.AddressRepository | ||
import com.adyen.checkout.card.ui.AddressFormInput | ||
import com.adyen.checkout.components.base.Configuration | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.flow.Flow | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.launch | ||
|
||
class AddressDelegate( | ||
private val addressRepository: AddressRepository | ||
) { | ||
|
||
private val _statesFlow: MutableStateFlow<List<AddressItem>> = MutableStateFlow(emptyList()) | ||
internal val statesFlow: Flow<List<AddressItem>> = _statesFlow | ||
|
||
private val cache: LruCache<String, List<AddressItem>> = LruCache<String, List<AddressItem>>(CACHE_ENTRY_SIZE) | ||
|
||
fun getStateList( | ||
configuration: Configuration, | ||
countryCode: String?, | ||
coroutineScope: CoroutineScope | ||
) { | ||
val addressSpecification = AddressFormInput.AddressSpecification.fromString(countryCode) | ||
val needsStates = COUNTRIES_WITH_STATES.contains(addressSpecification) | ||
if (!countryCode.isNullOrEmpty() && needsStates) { | ||
cache[countryCode]?.let { | ||
_statesFlow.tryEmit(it) | ||
} ?: coroutineScope.launch { | ||
val states = addressRepository.getAddressData( | ||
environment = configuration.environment, | ||
dataType = AddressDataType.STATE, | ||
localeString = configuration.shopperLocale.toLanguageTag(), | ||
countryCode = countryCode | ||
) | ||
if (states.isNotEmpty()) { | ||
cache.put(countryCode, states) | ||
} | ||
_statesFlow.tryEmit(states) | ||
} | ||
} else { | ||
_statesFlow.tryEmit(emptyList()) | ||
} | ||
} | ||
|
||
suspend fun getCountryList(configuration: Configuration): List<AddressItem> { | ||
return cache[COUNTRIES_CACHE_KEY] ?: run { | ||
val countries = addressRepository.getAddressData( | ||
environment = configuration.environment, | ||
dataType = AddressDataType.COUNTRY, | ||
localeString = configuration.shopperLocale.toLanguageTag() | ||
) | ||
if (countries.isNotEmpty()) { | ||
cache.put(COUNTRIES_CACHE_KEY, countries) | ||
} | ||
countries | ||
} | ||
} | ||
|
||
companion object { | ||
private val COUNTRIES_WITH_STATES = listOf( | ||
AddressFormInput.AddressSpecification.BR, | ||
AddressFormInput.AddressSpecification.CA, | ||
AddressFormInput.AddressSpecification.US | ||
) | ||
// Only US, CA and BR has states and there's only one countries list. | ||
private val CACHE_ENTRY_SIZE = COUNTRIES_WITH_STATES.size + 1 | ||
private const val COUNTRIES_CACHE_KEY = "countries" | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
card/src/main/java/com/adyen/checkout/card/AddressFormUIState.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.adyen.checkout.card | ||
|
||
import com.adyen.checkout.components.base.AddressVisibility | ||
|
||
enum class AddressFormUIState { | ||
NONE, POSTAL_CODE, FULL_ADDRESS; | ||
|
||
companion object { | ||
fun fromAddressConfiguration(addressConfiguration: AddressConfiguration): AddressFormUIState { | ||
return when (addressConfiguration) { | ||
is AddressConfiguration.FullAddress -> FULL_ADDRESS | ||
is AddressConfiguration.PostalCode -> POSTAL_CODE | ||
is AddressConfiguration.None -> NONE | ||
} | ||
} | ||
|
||
fun fromAddressVisibility(addressVisibility: AddressVisibility): AddressFormUIState { | ||
return when (addressVisibility) { | ||
AddressVisibility.POSTAL_CODE -> POSTAL_CODE | ||
AddressVisibility.NONE -> NONE | ||
} | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
card/src/main/java/com/adyen/checkout/card/AddressInputModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright (c) 2022 Adyen N.V. | ||
* | ||
* This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
* | ||
* Created by ozgur on 8/3/2022. | ||
*/ | ||
|
||
package com.adyen.checkout.card | ||
|
||
data class AddressInputModel( | ||
var postalCode: String = "", | ||
var street: String = "", | ||
var stateOrProvince: String = "", | ||
var houseNumberOrName: String = "", | ||
var apartmentSuite: String = "", | ||
var city: String = "", | ||
var country: String = "", | ||
) { | ||
/** | ||
* Reset the data. | ||
* | ||
* Note: This method is called when country is changed and that's the reason [country] field | ||
* does not get reset. | ||
*/ | ||
fun reset() { | ||
postalCode = "" | ||
street = "" | ||
stateOrProvince = "" | ||
houseNumberOrName = "" | ||
apartmentSuite = "" | ||
city = "" | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
card/src/main/java/com/adyen/checkout/card/AddressOutputData.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright (c) 2022 Adyen N.V. | ||
* | ||
* This file is open source and available under the MIT license. See the LICENSE file for more info. | ||
* | ||
* Created by ozgur on 8/3/2022. | ||
*/ | ||
|
||
package com.adyen.checkout.card | ||
|
||
import com.adyen.checkout.components.base.OutputData | ||
import com.adyen.checkout.components.ui.FieldState | ||
|
||
data class AddressOutputData( | ||
val postalCode: FieldState<String>, | ||
val street: FieldState<String>, | ||
val stateOrProvince: FieldState<String>, | ||
val houseNumberOrName: FieldState<String>, | ||
val apartmentSuite: FieldState<String>, | ||
val city: FieldState<String>, | ||
val country: FieldState<String> | ||
) : OutputData { | ||
override fun isValid(): Boolean { | ||
return postalCode.validation.isValid() && | ||
street.validation.isValid() && | ||
stateOrProvince.validation.isValid() && | ||
houseNumberOrName.validation.isValid() && | ||
apartmentSuite.validation.isValid() && | ||
city.validation.isValid() && | ||
country.validation.isValid() | ||
} | ||
} |
Oops, something went wrong.