Improve the reset identity password field (#7850)

Use the password keyboard type, mark the field as a password for
autofill, and submit the reset with the IME "Done" action, matching
the login password field.
This commit is contained in:
Bardi Harborow
2026-10-05 18:38:32 +11:00
committed by GitHub
parent a6d9d27c68
commit 48d6b5cadf
@@ -9,14 +9,21 @@
package io.element.android.features.securebackup.impl.reset.password package io.element.android.features.securebackup.impl.reset.password
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.ContentType
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentType
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
@@ -42,6 +49,11 @@ fun ResetIdentityPasswordView(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val passwordState = textFieldState(stateValue = "") val passwordState = textFieldState(stateValue = "")
val submit = {
if (passwordState.value.isNotEmpty()) {
state.eventSink(ResetIdentityPasswordEvent.Reset(passwordState.value))
}
}
FlowStepPage( FlowStepPage(
modifier = modifier, modifier = modifier,
iconStyle = BigIcon.Style.Default(CompoundIcons.LockSolid()), iconStyle = BigIcon.Style.Default(CompoundIcons.LockSolid()),
@@ -58,13 +70,14 @@ fun ResetIdentityPasswordView(
passwordState.value = newText passwordState.value = newText
}, },
hasError = state.resetAction.isFailure(), hasError = state.resetAction.isFailure(),
onSubmit = submit,
) )
}, },
buttons = { buttons = {
Button( Button(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
text = stringResource(CommonStrings.action_reset_identity), text = stringResource(CommonStrings.action_reset_identity),
onClick = { state.eventSink(ResetIdentityPasswordEvent.Reset(passwordState.value)) }, onClick = submit,
destructive = true, destructive = true,
enabled = passwordState.value.isNotEmpty(), enabled = passwordState.value.isNotEmpty(),
) )
@@ -78,12 +91,20 @@ fun ResetIdentityPasswordView(
} }
@Composable @Composable
private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Boolean) { private fun Content(
text: String,
onTextChange: (String) -> Unit,
hasError: Boolean,
onSubmit: () -> Unit,
) {
var showPassword by remember { mutableStateOf(false) } var showPassword by remember { mutableStateOf(false) }
TextField( TextField(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.onTabOrEnterKeyFocusNext(LocalFocusManager.current), .onTabOrEnterKeyFocusNext(LocalFocusManager.current)
.semantics {
contentType = ContentType.Password
},
value = text, value = text,
onValueChange = onTextChange, onValueChange = onTextChange,
placeholder = stringResource(CommonStrings.common_password), placeholder = stringResource(CommonStrings.common_password),
@@ -95,6 +116,13 @@ private fun Content(text: String, onTextChange: (String) -> Unit, hasError: Bool
onToggle = { showPassword = !showPassword }, onToggle = { showPassword = !showPassword },
) )
}, },
keyboardOptions = KeyboardOptions(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(
onDone = { onSubmit() }
),
validity = if (hasError) TextFieldValidity.Invalid else TextFieldValidity.None, validity = if (hasError) TextFieldValidity.Invalid else TextFieldValidity.None,
supportingText = if (hasError) { supportingText = if (hasError) {
stringResource(R.string.screen_reset_encryption_password_error) stringResource(R.string.screen_reset_encryption_password_error)