Skip to content

Commit

Permalink
feat: Add autofill for email+password
Browse files Browse the repository at this point in the history
  • Loading branch information
thgoebel authored and LeanderBB committed Feb 23, 2024
1 parent 3cb826c commit 7fdfb91
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.AutofillType
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.TextFieldValue
import androidx.compose.ui.text.input.VisualTransformation
import dev.lbeernaert.youhavemail.ui.AutoFillRequestHandler
import dev.lbeernaert.youhavemail.ui.autofill


@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun PasswordField(
placeHolder: String,
Expand All @@ -31,8 +36,15 @@ fun PasswordField(
val showPassword = remember {
mutableStateOf(false)
}
val autoFillHandler = AutoFillRequestHandler(
autofillTypes = listOf(AutofillType.Password),
onFill = { state.value = TextFieldValue(it) }
)

TextField(
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.fillMaxWidth()
.autofill(handler = autoFillHandler),
label = { Text(text = placeHolder) },
value = state.value,
singleLine = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.autofill.AutofillType
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
Expand All @@ -25,16 +27,19 @@ import dev.lbeernaert.youhavemail.R
import dev.lbeernaert.youhavemail.components.ActionButton
import dev.lbeernaert.youhavemail.components.AsyncScreen
import dev.lbeernaert.youhavemail.components.PasswordField
import dev.lbeernaert.youhavemail.ui.AutoFillRequestHandler
import dev.lbeernaert.youhavemail.ui.autofill


@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun Login(
backendName: String,
accountEmail: String,
onBackClicked: () -> Unit,
onLoginClicked: suspend (email: String, password: String) -> Unit
) {
var email = rememberSaveable(stateSaver = TextFieldValue.Saver) {
val email = rememberSaveable(stateSaver = TextFieldValue.Saver) {
mutableStateOf(
TextFieldValue(accountEmail)
)
Expand All @@ -53,6 +58,10 @@ fun Login(
onLoginClicked(email.value.text, password.value.text)
}
}
val autoFillHandler = AutoFillRequestHandler(
autofillTypes = listOf(AutofillType.EmailAddress),
onFill = { email.value = TextFieldValue(it) }
)

Column(
modifier = Modifier
Expand All @@ -68,7 +77,8 @@ fun Login(
Spacer(modifier = Modifier.height(20.dp))

TextField(
modifier = Modifier.fillMaxWidth(),
modifier = Modifier.fillMaxWidth()
.autofill(handler = autoFillHandler),
label = { Text(text = "Email") },
singleLine = true,
value = email.value,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package dev.lbeernaert.youhavemail.ui

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
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

// This file is adapted from https://medium.com/@bagadeshrp/compose-ui-textfield-autofill-6e2ac434e380

// The autofill modifier internally adds two modifiers:
// one to setup the layout, and one to listen for focus events.
@OptIn(ExperimentalComposeUiApi::class)
fun Modifier.autofill(handler: AutoFillHandler): Modifier {
return this.then(
onGloballyPositioned {
handler.autoFillNode.boundingBox = it.boundsInWindow()
}
).then(
onFocusChanged {
if (it.isFocused) {
handler.request()
} else {
handler.cancel()
}
}
)
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun AutoFillRequestHandler(
autofillTypes: List<AutofillType> = listOf(),
onFill: (String) -> Unit,
): AutoFillHandler {
val autoFillNode = remember {
AutofillNode(
autofillTypes = autofillTypes,
onFill = { onFill(it) }
)
}
val autofill = LocalAutofill.current
LocalAutofillTree.current += autoFillNode
return remember {
object : AutoFillHandler {
override val autoFillNode: AutofillNode
get() = autoFillNode

override fun request() {
autofill?.requestAutofillForNode(autofillNode = autoFillNode)
}

override fun cancel() {
autofill?.cancelAutofillForNode(autofillNode = autoFillNode)
}
}
}
}

@OptIn(ExperimentalComposeUiApi::class)
interface AutoFillHandler {
val autoFillNode: AutofillNode
fun request()
fun cancel()
}

0 comments on commit 7fdfb91

Please sign in to comment.