Skip to content

Commit

Permalink
[feat] Add "checkValidOnLastCellInput" option to only check the valid…
Browse files Browse the repository at this point in the history
… input on the last cell input
  • Loading branch information
luongvo committed Aug 29, 2024
1 parent 4610946 commit 526b7ab
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ private const val NOT_ENTERED_VALUE = '₺'
* Whenever the user edits the text, [onValueChange] is called with the most up to date state
* including the empty values that represented by [OhTeePeeConfigurations.placeHolder].
*
* When the user fills all the cells, [onValueChange]'s isValid parameter will be `true`,
* When the user fills all the cells, [onValueChange]'s isValid parameter will be `true`
* (if the [OhTeePeeConfigurations.checkValidOnLastCellInput] is `false` or if the last cell is just filled),
* otherwise it will be `false`.
*
* To customize the appearance of cells you can pass [configurations] parameter with
Expand Down Expand Up @@ -180,6 +181,7 @@ fun OhTeePeeInput(
horizontalArrangement = horizontalArrangement,
onCellInputChange = { currentCellIndex, newValue ->
handleCellInputChange(
checkValidOnLastCellInput = configurations.checkValidOnLastCellInput,
otpValueCharArray = otpValueCharArray,
currentCellIndex = currentCellIndex,
newValue = newValue,
Expand Down Expand Up @@ -280,6 +282,7 @@ private fun getOtpValueCharArray(
}

private fun handleCellInputChange(
checkValidOnLastCellInput: Boolean,
otpValueCharArray: CharArray,
currentCellIndex: Int,
newValue: String,
Expand All @@ -304,20 +307,26 @@ private fun handleCellInputChange(
return
}

var focusTargetIndex = 0
if (formattedNewValue.isNotEmpty()) {
otpValueCharArray[currentCellIndex] = formattedNewValue.last()
moveFocus(currentCellIndex, currentCellIndex + 1)
focusTargetIndex = currentCellIndex + 1
moveFocus(currentCellIndex, focusTargetIndex)
} else if (currentCellText != NOT_ENTERED_VALUE.toString()) {
otpValueCharArray[currentCellIndex] = NOT_ENTERED_VALUE
} else {
val previousIndex = (currentCellIndex - 1).coerceIn(0, cellsCount)
otpValueCharArray[previousIndex] = NOT_ENTERED_VALUE
moveFocus(currentCellIndex, previousIndex)
focusTargetIndex = (currentCellIndex - 1).coerceIn(0, cellsCount)
otpValueCharArray[focusTargetIndex] = NOT_ENTERED_VALUE
moveFocus(currentCellIndex, focusTargetIndex)
}
val otpValueAsString = otpValueCharArray.joinToString(String.EMPTY) {
if (it == NOT_ENTERED_VALUE) " " else it.toString()
}
onValueChange(otpValueAsString, otpValueAsString.none { it == placeHolderAsChar })
onValueChange(
otpValueAsString,
otpValueAsString.none { it == placeHolderAsChar }
&& (!checkValidOnLastCellInput || focusTargetIndex == cellsCount),
)
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ private const val DEFAULT_PLACE_HOLDER = " "
* @param errorCellConfig [OhTeePeeCellConfiguration] cell ui configuration when an error occurred.
* @param emptyCellConfig [OhTeePeeCellConfiguration] cell ui configuration when it's empty & not focused.
* @param filledCellConfig [OhTeePeeCellConfiguration] cell ui configuration when it's filled.
* @param checkValidOnLastCellInput when set to `true`, the valid input value will be checked only
* when the last cell is filled.
* @param clearInputOnError when set to `true`, the input will be cleared and the focus will be reset to the first char
* when an error occurred.
* @param enableBottomLine when set to `true`, a bottom line will be drawn for each
Expand All @@ -55,6 +57,7 @@ data class OhTeePeeConfigurations(
val errorCellConfig: OhTeePeeCellConfiguration,
val emptyCellConfig: OhTeePeeCellConfiguration,
val filledCellConfig: OhTeePeeCellConfiguration,
val checkValidOnLastCellInput: Boolean,
val clearInputOnError: Boolean,
val enableBottomLine: Boolean,
val errorAnimationConfig: OhTeePeeErrorAnimationConfig?,
Expand All @@ -77,6 +80,7 @@ data class OhTeePeeConfigurations(
elevation: Dp = 0.dp,
cursorColor: Color = Color.Transparent,
clearInputOnError: Boolean = true,
checkValidOnLastCellInput: Boolean = false,
enableBottomLine: Boolean = false,
obscureText: String = String.EMPTY,
placeHolder: String = DEFAULT_PLACE_HOLDER,
Expand All @@ -89,6 +93,7 @@ data class OhTeePeeConfigurations(
emptyCellConfig = emptyCellConfig,
filledCellConfig = filledCellConfig,
cursorColor = cursorColor,
checkValidOnLastCellInput = checkValidOnLastCellInput,
clearInputOnError = clearInputOnError,
enableBottomLine = enableBottomLine,
placeHolder = placeHolder,
Expand Down
11 changes: 9 additions & 2 deletions sample/src/main/java/com/composeuisuite/ohteepee/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.composeuisuite.ohteepee

import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.ExperimentalFoundationApi
Expand Down Expand Up @@ -40,6 +41,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RadialGradientShader
import androidx.compose.ui.graphics.Shader
import androidx.compose.ui.graphics.ShaderBrush
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
Expand Down Expand Up @@ -306,6 +308,7 @@ private fun Sample1(
private fun Sample2(
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val backgroundColor = Color(0xFF1A1E22)
var otpValue: String by remember { mutableStateOf("") }
val defaultConfig = OhTeePeeCellConfiguration.withDefaults(
Expand Down Expand Up @@ -339,7 +342,7 @@ private fun Sample2(
Spacer(modifier = Modifier.height(16.dp))

Text(
text = "(Keep input on error)",
text = "(Keep input on error + Check Valid on last input)",
color = Color.White,
textAlign = TextAlign.Center,
)
Expand All @@ -354,8 +357,11 @@ private fun Sample2(

OhTeePeeInput(
value = otpValue,
onValueChange = { newValue, _ ->
onValueChange = { newValue, isValid ->
otpValue = newValue
if (isValid) {
Toast.makeText(context, "Validate the value here...", Toast.LENGTH_SHORT).show()
}
},
isValueInvalid = otpValue == "1111",
configurations = OhTeePeeConfigurations.withDefaults(
Expand All @@ -365,6 +371,7 @@ private fun Sample2(
cellModifier = Modifier
.padding(horizontal = 4.dp)
.size(48.dp),
checkValidOnLastCellInput = true,
clearInputOnError = false,
),
autoFocusByDefault = false,
Expand Down

0 comments on commit 526b7ab

Please sign in to comment.