Skip to content

Commit

Permalink
Provide countries and initiallySelectedCountry from the delegate
Browse files Browse the repository at this point in the history
COAND-935
  • Loading branch information
araratthehero committed Jan 21, 2025
1 parent 7c01931 commit 6b47508
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ import androidx.annotation.StringRes
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
data class ComponentFieldViewState<T>(
val value: T,
@StringRes val errorMessageId: Int? = null
@StringRes val errorMessageId: Int? = null,
)
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ internal class DefaultMBWayDelegate(
private val validationRegistry: FieldValidatorRegistry<MBWayFieldId>,
) : MBWayDelegate {

private var state = MutableStateFlow(MBWayDelegateState())
private var state = MutableStateFlow(MBWayDelegateState(
countries = getSupportedCountries(),
initiallySelectedCountry = getInitiallySelectedCountry()
))

private val _componentStateFlow = MutableStateFlow(createComponentState())
override val componentStateFlow: Flow<MBWayComponentState> = _componentStateFlow
Expand Down Expand Up @@ -139,7 +142,6 @@ internal class DefaultMBWayDelegate(
MBWayFieldId.COUNTRY_CODE -> state.value.countryCodeFieldState.value
MBWayFieldId.LOCAL_PHONE_NUMBER -> state.value.localPhoneNumberFieldState.value
}
// TODO: Update only the fields which are not validated yet.
updateField(fieldId, value = value, isValidationErrorCheckForced = true)
}
}
Expand Down Expand Up @@ -220,10 +222,10 @@ internal class DefaultMBWayDelegate(
_componentStateFlow.tryEmit(componentState)
}

override fun getSupportedCountries(): List<CountryModel> =
private fun getSupportedCountries(): List<CountryModel> =
CountryUtils.getLocalizedCountries(componentParams.shopperLocale, SUPPORTED_COUNTRIES)

override fun getInitiallySelectedCountry(): CountryModel? {
private fun getInitiallySelectedCountry(): CountryModel? {
val countries = getSupportedCountries()
return countries.firstOrNull { it.isoCode == ISO_CODE_PORTUGAL } ?: countries.firstOrNull()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import com.adyen.checkout.mbway.internal.ui.model.MBWayViewState
import com.adyen.checkout.ui.core.internal.ui.ButtonDelegate
import com.adyen.checkout.ui.core.internal.ui.UIStateDelegate
import com.adyen.checkout.ui.core.internal.ui.ViewProvidingDelegate
import com.adyen.checkout.ui.core.internal.ui.model.CountryModel
import kotlinx.coroutines.flow.Flow

internal interface MBWayDelegate :
Expand All @@ -28,10 +27,6 @@ internal interface MBWayDelegate :

val componentStateFlow: Flow<MBWayComponentState>

fun getSupportedCountries(): List<CountryModel>

fun getInitiallySelectedCountry(): CountryModel?

fun onFieldValueChanged(fieldId: MBWayFieldId, value: String)

fun onFieldFocusChanged(fieldId: MBWayFieldId, hasFocus: Boolean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,31 @@ package com.adyen.checkout.mbway.internal.ui.model
import com.adyen.checkout.components.core.internal.ui.model.ComponentFieldDelegateState
import com.adyen.checkout.components.core.internal.ui.model.ComponentFieldViewState
import com.adyen.checkout.components.core.internal.ui.model.Validation
import com.adyen.checkout.ui.core.internal.ui.model.CountryModel

internal data class MBWayDelegateState(
val countryCodeFieldState: ComponentFieldDelegateState<String> = ComponentFieldDelegateState(
value = "",
validation = Validation.Valid,
),
val countries: List<CountryModel>,
val initiallySelectedCountry: CountryModel?,
val countryCodeFieldState: ComponentFieldDelegateState<String> = ComponentFieldDelegateState(value = ""),
val localPhoneNumberFieldState: ComponentFieldDelegateState<String> = ComponentFieldDelegateState(value = ""),
) {
val isValid: Boolean
get() =
countryCodeFieldState.validation?.isValid() == true &&
localPhoneNumberFieldState.validation?.isValid() == true
get() = countryCodeFieldState.validation?.isValid() == true &&
localPhoneNumberFieldState.validation?.isValid() == true
}

internal fun MBWayDelegateState.toViewState() = MBWayViewState(
phoneNumberFieldState = ComponentFieldViewState(
value = this.localPhoneNumberFieldState.value,
errorMessageId = this.localPhoneNumberFieldState.takeIf { fieldState ->
fieldState.shouldShowValidationError()
}?.validation.let { it as? Validation.Invalid }?.reason,
),
countries = this.countries,
initiallySelectedCountry = initiallySelectedCountry,
phoneNumberFieldState = with(this.localPhoneNumberFieldState) {
ComponentFieldViewState(
value = value,
errorMessageId = takeIf { fieldState ->
fieldState.shouldShowValidationError()
}?.validation.let { it as? Validation.Invalid }?.reason,
)
},
)

internal fun <T> ComponentFieldDelegateState<T>.shouldShowValidationError() = !this.hasFocus || this.isValidationErrorCheckForced
internal fun <T> ComponentFieldDelegateState<T>.shouldShowValidationError() =
!this.hasFocus || this.isValidationErrorCheckForced
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
package com.adyen.checkout.mbway.internal.ui.model

import com.adyen.checkout.components.core.internal.ui.model.ComponentFieldViewState
import com.adyen.checkout.ui.core.internal.ui.model.CountryModel

internal data class MBWayViewState(
val countries: List<CountryModel>,
val initiallySelectedCountry: CountryModel?,
val phoneNumberFieldState: ComponentFieldViewState<String>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.adyen.checkout.components.core.internal.ui.model.ComponentFieldViewSt
import com.adyen.checkout.mbway.databinding.MbwayViewBinding
import com.adyen.checkout.mbway.internal.ui.MBWayDelegate
import com.adyen.checkout.mbway.internal.ui.model.MBWayFieldId
import com.adyen.checkout.mbway.internal.ui.model.MBWayViewState
import com.adyen.checkout.ui.core.internal.ui.ComponentView
import com.adyen.checkout.ui.core.internal.ui.CountryAdapter
import com.adyen.checkout.ui.core.internal.ui.model.CountryModel
Expand All @@ -42,6 +43,8 @@ internal class MbWayView @JvmOverloads constructor(

private lateinit var delegate: MBWayDelegate

private lateinit var countryAdapter: CountryAdapter

init {
orientation = VERTICAL

Expand All @@ -54,17 +57,23 @@ internal class MbWayView @JvmOverloads constructor(
this.delegate = delegate
this.localizedContext = localizedContext

observeDelegate(delegate, coroutineScope)

initMobileNumberInput()
initCountryInput()
}

observeDelegate(delegate, coroutineScope)
}

private fun observeDelegate(delegate: MBWayDelegate, coroutineScope: CoroutineScope) {
delegate.viewStateFlow
.onEach { updateMobileNumberInput(it.phoneNumberFieldState) }
.launchIn(coroutineScope)
private fun initCountryInput() {
countryAdapter = CountryAdapter(context, localizedContext)
binding.autoCompleteTextViewCountry.apply {
// disable editing and hide cursor
inputType = 0
setAdapter(countryAdapter)
setOnItemClickListener { _, _, position, _ ->
val country = countryAdapter.getItem(position)
onCountrySelected(country)
}
}
}

private fun initMobileNumberInput() {
Expand All @@ -76,6 +85,17 @@ internal class MbWayView @JvmOverloads constructor(
}
}

private fun observeDelegate(delegate: MBWayDelegate, coroutineScope: CoroutineScope) {
delegate.viewStateFlow
.onEach { viewStateUpdated(it) }
.launchIn(coroutineScope)
}

private fun viewStateUpdated(mbWayViewState: MBWayViewState) {
updateMobileNumberInput(mbWayViewState.phoneNumberFieldState)
updateCountryInput(mbWayViewState.countries, mbWayViewState.initiallySelectedCountry)
}

private fun updateMobileNumberInput(phoneNumberFieldState: ComponentFieldViewState<String>) {
phoneNumberFieldState.errorMessageId?.let { errorMessageId ->
binding.textInputLayoutMobileNumber.showError(
Expand All @@ -86,23 +106,15 @@ internal class MbWayView @JvmOverloads constructor(
}
}

private fun initCountryInput() {
val countries = delegate.getSupportedCountries()
val adapter = CountryAdapter(context, localizedContext)
adapter.setItems(countries)
binding.autoCompleteTextViewCountry.apply {
// disable editing and hide cursor
inputType = 0
setAdapter(adapter)
setOnItemClickListener { _, _, position, _ ->
val country = adapter.getItem(position)
onCountrySelected(country)
private fun updateCountryInput(countries: List<CountryModel>, initiallySelectedCountry: CountryModel?) {
if (countryAdapter.isEmpty) {
initiallySelectedCountry?.let {
binding.autoCompleteTextViewCountry.setText(initiallySelectedCountry.toShortString())
onCountrySelected(initiallySelectedCountry)
}
}
delegate.getInitiallySelectedCountry()?.let {
binding.autoCompleteTextViewCountry.setText(it.toShortString())
onCountrySelected(it)
}

countryAdapter.setItems(countries)
}

override fun highlightValidationErrors() {
Expand Down

0 comments on commit 6b47508

Please sign in to comment.