From b35e1915a01c8d5536fc95d05dc14675379884f0 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 29 May 2024 03:52:05 +0200 Subject: [PATCH] Add autofill to the `LoginForm` --- .../steffo/twom/login/components/LoginForm.kt | 53 ++++++++++++++++++- .../twom/login/components/PasswordField.kt | 7 +++ 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/eu/steffo/twom/login/components/LoginForm.kt b/app/src/main/java/eu/steffo/twom/login/components/LoginForm.kt index ff20ead..22240fe 100644 --- a/app/src/main/java/eu/steffo/twom/login/components/LoginForm.kt +++ b/app/src/main/java/eu/steffo/twom/login/components/LoginForm.kt @@ -15,7 +15,15 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.autofill.AutofillNode +import androidx.compose.ui.autofill.AutofillType +import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.layout.boundsInWindow +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalAutofill +import androidx.compose.ui.platform.LocalAutofillTree import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import eu.steffo.twom.R @@ -28,6 +36,7 @@ import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session +@OptIn(ExperimentalComposeUiApi::class) @Composable @Preview(showBackground = true) fun LoginForm( @@ -35,6 +44,8 @@ fun LoginForm( onLogin: (session: Session) -> Unit = {}, ) { val scope = rememberCoroutineScope() + val autofill = LocalAutofill.current + val autofillTree = LocalAutofillTree.current var username by rememberSaveable { mutableStateOf("") } var password by rememberSaveable { mutableStateOf("") } @@ -55,8 +66,27 @@ fun LoginForm( Text(stringResource(R.string.login_intro_text)) } Row(Modifier.basePadding()) { + val autofillNode = AutofillNode( + autofillTypes = listOf(AutofillType.Username), + onFill = { username = it } + ) + autofillTree += autofillNode TextField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .onGloballyPositioned { + autofillNode.boundingBox = it.boundsInWindow() + } + .onFocusChanged { + autofill?.run { + if (it.isFocused) { + requestAutofillForNode(autofillNode) + } + else { + cancelAutofillForNode(autofillNode) + } + } + }, singleLine = true, value = username, onValueChange = { username = it }, @@ -72,8 +102,27 @@ fun LoginForm( ) } Row(Modifier.basePadding()) { + val autofillNode = AutofillNode( + autofillTypes = listOf(AutofillType.Password), + onFill = { password = it } + ) + autofillTree += autofillNode PasswordField( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .onGloballyPositioned { + autofillNode.boundingBox = it.boundsInWindow() + } + .onFocusChanged { + autofill?.run { + if (it.isFocused) { + requestAutofillForNode(autofillNode) + } + else { + cancelAutofillForNode(autofillNode) + } + } + }, value = password, onValueChange = { password = it }, label = { diff --git a/app/src/main/java/eu/steffo/twom/login/components/PasswordField.kt b/app/src/main/java/eu/steffo/twom/login/components/PasswordField.kt index 18a1606..9c85c67 100644 --- a/app/src/main/java/eu/steffo/twom/login/components/PasswordField.kt +++ b/app/src/main/java/eu/steffo/twom/login/components/PasswordField.kt @@ -1,5 +1,6 @@ package eu.steffo.twom.login.components +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.RemoveRedEye import androidx.compose.material.icons.outlined.RemoveRedEye @@ -12,7 +13,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.autofill.AutofillNode +import androidx.compose.ui.autofill.AutofillType import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.tooling.preview.Preview @@ -38,6 +42,9 @@ fun PasswordField( placeholder = placeholder, supportingText = supportingText, singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Password, + ), visualTransformation = if (showPassword) VisualTransformation.None else PasswordVisualTransformation(),