Farhazul Mullick
12/06/2023, 4:09 PMModifier.onKeyEvent { keyEvent ->
    Napier.d(tag = "OTPVerification") { "Keyboard button clicked ${keyEvent.key}" }
    if (keyEvent.type == KeyEventType.KeyUp && keyEvent.key == Key.Backspace) {
        // code...
    }
    true
}Alexander Maryanovsky
12/06/2023, 7:14 PMAlexander Maryanovsky
12/06/2023, 7:20 PMFarhazul Mullick
12/07/2023, 4:44 AMFarhazul Mullick
12/07/2023, 4:46 AMMofe Ejegi
02/16/2024, 5:56 PMFarhazul Mullick
02/17/2024, 12:48 PMMofe Ejegi
02/17/2024, 6:41 PMFarhazul Mullick
02/19/2024, 12:51 PMMofe Ejegi
02/19/2024, 12:54 PMAlexander Maryanovsky
02/19/2024, 12:56 PMonPreviewKeyEventMofe Ejegi
02/19/2024, 12:57 PMFarhazul Mullick
02/19/2024, 1:05 PMFarhazul Mullick
02/19/2024, 1:07 PMMofe Ejegi
02/19/2024, 1:08 PMFarhazul Mullick
02/19/2024, 1:18 PM@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun OTPInputField(
    modifier: Modifier = Modifier,
    otpText: String,
    maxOTPCount: Int = 6,
    isError: Boolean = false,
    errorMsg: String = String.EMPTY,
    onOtpTextChange: (String) -> Unit,
    onOTPFilled: (String) -> Unit
) {
    val keyboardController = LocalSoftwareKeyboardController.current
    val focusManager = LocalFocusManager.current
    Column {
        BasicTextField(
            value = TextFieldValue(otpText, selection = TextRange(otpText.length)),
            onValueChange = {textField ->
                if (textField.text.length <= maxOTPCount) {
                    val otpFilled: Boolean =  textField.text.length == maxOTPCount
                    Napier.d { "Line68: onValueChange, text: ${textField.text}" }
                    onOtpTextChange.invoke(textField.text)
                   
                    if (otpFilled) {
                        onOTPFilled.invoke(textField.text)
                    }
                }
            },
            decorationBox = {
                Row(
                    horizontalArrangement = Arrangement.Center,
                ) {
                    repeat(maxOTPCount) { index ->
                        val char = when {
                            index >= otpText.length -> ""
                            else -> otpText[index].toString()
                        }
                        val check1: Boolean = char.isEmpty() && index == otpText.length
                        val filledBox: Boolean = index < otpText.length
                        var check2: Boolean by remember { mutableStateOf(false) }
                        LaunchedEffect(key1 = check2) {
                            delay(500)
                            check2 = !check2
                        }
                        Box(contentAlignment = Alignment.Center) {
                            Text(
                                modifier = Modifier
                                    .size(54.dp)
                                    .border(
                                        width = 1.dp,
                                        color = if (isError) LocalThemeColors.current.errorColors.error_500
                                        else if (filledBox) LocalThemeColors.current.primaryColor.primary_500
                                        else LocalThemeColors.current.greyPaletteColors.grey_300,
                                        shape = RoundedCornerShape(8.dp)
                                    )
                                    .padding(vertical = 13.dp),
                                text = char,
                                textAlign = TextAlign.Center,
                                style = LocalTextStyles.current.H3Bold
                            )
                            if (check1 and check2) {
                                Box(
                                    modifier = Modifier.width(2.dp)
                                        .height(LocalDimensions.current.dp20)
                                        .background(color = LocalThemeColors.current.greyPaletteColors.grey_900)
                                )
                            }
                        }
                        HSpacer(LocalDimensions.current.dp8)
                    }
                }
            },
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Number,
                imeAction = ImeAction.Done
            ),
            keyboardActions = KeyboardActions(
                onDone = {
                    keyboardController?.hide()
                    focusManager.clearFocus()
                }
            ),
            singleLine = true
        )
        if (isError) ErrorIconLabel(errorText = errorMsg)
    }
}Farhazul Mullick
02/19/2024, 1:19 PM// Four digit OTP-BOX
var otpText: String by remember { mutableStateOf(String.EMPTY) }
OTPInputField(
    otpText = otpText,
    maxOTPCount = 4,
    onOtpTextChange = {newOTP: String ->
        otpText = newOTP
    },
    isError = isError,
    errorMsg = errorText,
    onOTPFilled = {otp: String ->
        // otp string is complete otp.
        // callback trigurred when all boxes are filled.
    }
)Mofe Ejegi
02/19/2024, 1:33 PM