Updated on 2026-08-14
This commit is contained in:
commit
38c6cbf632
4 changed files with 75 additions and 17 deletions
|
|
@ -5,6 +5,7 @@ import com.tangem.common.extensions.toHexString
|
|||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.datasource.local.visa.VisaAuthTokenStorage
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.visa.SetVisaPinCodeUseCase
|
||||
|
|
@ -57,24 +58,28 @@ internal class OnboardingVisaPinCodeModel @Inject constructor(
|
|||
}
|
||||
|
||||
private fun onPinCodeChange(pin: String) {
|
||||
if (pin.all { it.isDigit() }) {
|
||||
if (PinCodeValidation.validateAllDigits(pin)) {
|
||||
val isError = PinCodeValidation.validateLength(pin) && PinCodeValidation.validate(pin).not()
|
||||
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
pinCode = pin,
|
||||
submitButtonEnabled = checkPinCode(pin),
|
||||
submitButtonEnabled = PinCodeValidation.validate(pin),
|
||||
error = if (isError) stringReference("Invalid PIN: avoid sequences or repeats") else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onSubmitClick() {
|
||||
if (checkPinCode(_uiState.value.pinCode).not()) return
|
||||
val pinCode = _uiState.value.pinCode
|
||||
if (PinCodeValidation.validate(pinCode).not()) return
|
||||
|
||||
modelScope.launch {
|
||||
loading(true)
|
||||
|
||||
setVisaPinCodeUseCase(
|
||||
pinCode = _uiState.value.pinCode,
|
||||
pinCode = pinCode,
|
||||
visaCardId = visaCardId,
|
||||
activationOrderId = params.activationOrderInfo.orderId,
|
||||
).onLeft {
|
||||
|
|
@ -88,10 +93,6 @@ internal class OnboardingVisaPinCodeModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun checkPinCode(pin: String): Boolean {
|
||||
return pin.length == PIN_CODE_LENGTH
|
||||
}
|
||||
|
||||
private fun loading(state: Boolean) {
|
||||
_uiState.update { it.copy(submitButtonLoading = state) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.tangem.features.onboarding.v2.visa.impl.child.pincode.model
|
||||
|
||||
internal object PinCodeValidation {
|
||||
|
||||
private const val PIN_CODE_LENGTH = 4
|
||||
|
||||
fun validate(pinCode: String): Boolean {
|
||||
return sequenceOf(
|
||||
::validateAllDigits,
|
||||
::validateLength,
|
||||
::validateNoRepeatedDigits,
|
||||
::validateNoConsecutiveDigits,
|
||||
).all { it(pinCode) }
|
||||
}
|
||||
|
||||
fun validateAllDigits(pinCode: String): Boolean {
|
||||
return pinCode.all { it.isDigit() }
|
||||
}
|
||||
|
||||
fun validateLength(pinCode: String): Boolean {
|
||||
return pinCode.length == PIN_CODE_LENGTH
|
||||
}
|
||||
|
||||
private fun validateNoRepeatedDigits(pinCode: String): Boolean {
|
||||
return pinCode.toSet().size == PIN_CODE_LENGTH
|
||||
}
|
||||
|
||||
private fun validateNoConsecutiveDigits(pinCode: String): Boolean {
|
||||
return pinCode.windowed(2).all { it[0] + 1 == it[1] }.not()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.onboarding.v2.visa.impl.child.pincode.ui
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
|
|
@ -31,7 +32,10 @@ import com.tangem.common.ui.navigationButtons.NavigationButton
|
|||
import com.tangem.common.ui.navigationButtons.NavigationPrimaryButton
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerH16
|
||||
import com.tangem.core.ui.components.SpacerH4
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.features.onboarding.v2.visa.impl.child.pincode.ui.state.OnboardingVisaPinCodeUM
|
||||
|
|
@ -91,13 +95,29 @@ internal fun OnboardingVisaPinCode(state: OnboardingVisaPinCodeUM, modifier: Mod
|
|||
@Composable
|
||||
private fun PinCodeSection(state: OnboardingVisaPinCodeUM, modifier: Modifier = Modifier) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
PinCode(
|
||||
modifier = modifier,
|
||||
value = state.pinCode,
|
||||
onValueChange = state.onPinCodeChange,
|
||||
focusRequester = focusRequester,
|
||||
)
|
||||
|
||||
PinCode(
|
||||
modifier = modifier,
|
||||
value = state.pinCode,
|
||||
onValueChange = state.onPinCodeChange,
|
||||
focusRequester = focusRequester,
|
||||
)
|
||||
AnimatedVisibility(
|
||||
visible = state.error != null,
|
||||
) {
|
||||
val error = remember(this) { requireNotNull(state.error) }
|
||||
Column {
|
||||
SpacerH4()
|
||||
Text(
|
||||
text = error.resolveReference(),
|
||||
style = TangemTheme.typography.caption2,
|
||||
color = TangemTheme.colors.text.warning,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
delay(timeMillis = 300)
|
||||
|
|
@ -134,9 +154,11 @@ private fun PinCode(
|
|||
keyboardType = KeyboardType.Number,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(onDone = {
|
||||
keyboardController?.hide()
|
||||
},),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = {
|
||||
keyboardController?.hide()
|
||||
},
|
||||
),
|
||||
modifier = Modifier
|
||||
.alpha(alpha = 0.01f)
|
||||
.focusRequester(focusRequester),
|
||||
|
|
@ -194,6 +216,7 @@ private fun Preview() {
|
|||
OnboardingVisaPinCode(
|
||||
state = OnboardingVisaPinCodeUM(
|
||||
pinCode = "1234",
|
||||
error = stringReference("PIN Code error"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package com.tangem.features.onboarding.v2.visa.impl.child.pincode.ui.state
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
|
||||
internal data class OnboardingVisaPinCodeUM(
|
||||
val pinCode: String = "",
|
||||
val error: TextReference? = null,
|
||||
val onPinCodeChange: (String) -> Unit = {},
|
||||
val submitButtonLoading: Boolean = false,
|
||||
val submitButtonEnabled: Boolean = true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue