From 5596d5652560e475ecfe9777859a78ae6de61734 Mon Sep 17 00:00:00 2001 From: AbronStudio Date: Sun, 24 Aug 2025 12:54:45 +0330 Subject: [PATCH] Refactor: Improve password input in RegisterDetailsScreen - Set softInputMode to SOFT_INPUT_ADJUST_PAN to prevent keyboard from obscuring UI elements. - Use `SecureTextField` for password input to provide obfuscation and a toggle to show/hide password. - Make the screen vertically scrollable. --- .../screens/register/RegisterDetailsScreen.kt | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/chat/peptide/screens/register/RegisterDetailsScreen.kt b/app/src/main/java/chat/peptide/screens/register/RegisterDetailsScreen.kt index a5f3f96e..d0e7c3f7 100644 --- a/app/src/main/java/chat/peptide/screens/register/RegisterDetailsScreen.kt +++ b/app/src/main/java/chat/peptide/screens/register/RegisterDetailsScreen.kt @@ -1,6 +1,8 @@ package chat.peptide.screens.register import android.content.Context +import android.app.Activity +import android.view.WindowManager import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -13,17 +15,26 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.input.TextObfuscationMode +import androidx.compose.foundation.text.input.rememberTextFieldState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.SecureTextField import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -51,6 +62,7 @@ import chat.peptide.api.routes.account.register import chat.peptide.api.routes.misc.getRootRoute import chat.peptide.composables.generic.FormTextField import chat.peptide.composables.generic.SquareButton +import chat.peptide.ui.theme.FragmentMono import com.hcaptcha.sdk.HCaptcha import com.hcaptcha.sdk.HCaptchaConfig import com.hcaptcha.sdk.HCaptchaSize @@ -126,6 +138,18 @@ fun RegisterDetailsScreen( navController: NavController, viewModel: RegisterDetailsScreenViewModel = viewModel() ) { + val context = LocalContext.current + DisposableEffect(Unit) { + val window = (context as Activity).window + val previousMode = window.attributes.softInputMode + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) + onDispose { window.setSoftInputMode(previousMode) } + } + val passwordTextFieldState = rememberTextFieldState() + LaunchedEffect(passwordTextFieldState.text) { + viewModel.password = passwordTextFieldState.text.toString() + } + val showPassword = remember { mutableStateOf(false) } Scaffold( topBar = { Column { @@ -167,6 +191,7 @@ fun RegisterDetailsScreen( modifier = Modifier .padding(innerPadding) .fillMaxSize() + .verticalScroll(rememberScrollState()) .padding(vertical = 20.dp, horizontal = 16.dp) .imePadding(), verticalArrangement = Arrangement.Top, @@ -225,20 +250,49 @@ fun RegisterDetailsScreen( .semantics { contentType = ContentType.EmailAddress } ) Spacer(modifier = Modifier.height(16.dp)) - FormTextField( - value = viewModel.password, - onChange = { viewModel.password = it }, - label = stringResource(R.string.register_password), - type = KeyboardType.Email, - action = ImeAction.Next, + SecureTextField( + passwordTextFieldState, + label = { Text(stringResource(R.string.password)) }, + textObfuscationMode = if (showPassword.value) { + TextObfuscationMode.Visible + } else { + TextObfuscationMode.RevealLastTyped + }, + textStyle = if (showPassword.value) LocalTextStyle.current else LocalTextStyle.current.copy( + fontFamily = FragmentMono + ), + trailingIcon = { + IconButton( + onClick = { + showPassword.value = !showPassword.value + } + ) { + when { + + showPassword.value -> { + Icon( + painter = painterResource(R.drawable.icn_visibility_off_24dp), + contentDescription = stringResource(R.string.hide_password) + ) + } + + else -> { + Icon( + painter = painterResource(R.drawable.icn_visibility_24dp), + contentDescription = stringResource(R.string.show_password) + ) + } + } + } + }, modifier = Modifier .fillMaxWidth() - .semantics { contentType = ContentType.EmailAddress } + .semantics { + contentType = ContentType.Password + } ) Spacer(modifier = Modifier.height(32.dp)) - val context = LocalContext.current - SquareButton( onClick = { viewModel.initCaptcha(context) {