From 3086498fe6668855bc2ac9d6f71260030b992138 Mon Sep 17 00:00:00 2001 From: Harsh Lal Date: Fri, 3 Feb 2023 20:40:24 +0000 Subject: [PATCH] Add ability to show/hide password Bug: 266571936 Fix: 266571936 Test: local deployment Change-Id: Ic4ca64091fcec98806315e1ffbf42a111799a16d --- .../CredentialManager/res/values/strings.xml | 4 ++ .../CredentialManagerRepo.kt | 2 +- .../common/ui/ActionButton.kt | 35 +++++++++++++++ .../createflow/CreateCredentialComponents.kt | 44 ++++++++++++++++--- 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml index d690971997128..49ac482699cfb 100644 --- a/packages/CredentialManager/res/values/strings.xml +++ b/packages/CredentialManager/res/values/strings.xml @@ -13,6 +13,10 @@ More options Learn more + + Show password + + Hide password Safer with passkeys diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt index c66ea5e1af9e0..6ea1d8d522f93 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt @@ -64,7 +64,7 @@ class CredentialManagerRepo( requestInfo = intent.extras?.getParcelable( RequestInfo.EXTRA_REQUEST_INFO, RequestInfo::class.java - ) ?: testCreatePasskeyRequestInfo() + ) ?: testCreatePasswordRequestInfo() providerEnabledList = when (requestInfo.type) { RequestInfo.TYPE_CREATE -> diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt index d0271abccabda..984057a1c9600 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt @@ -16,11 +16,23 @@ package com.android.credentialmanager.common.ui +import com.android.credentialmanager.R +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Visibility +import androidx.compose.material.icons.outlined.VisibilityOff import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme @Composable fun ActionButton(text: String, onClick: () -> Unit) { @@ -32,4 +44,27 @@ fun ActionButton(text: String, onClick: () -> Unit) { ) { Text(text = text) } +} + +@Composable +fun ToggleVisibilityButton(modifier: Modifier = Modifier, onToggle: (Boolean) -> Unit) { + // default state is visibility off + val toggleState: MutableState = remember { mutableStateOf(false) } + + IconButton( + modifier = modifier, + onClick = { + toggleState.value = !toggleState.value + onToggle(toggleState.value) + } + ) { + Icon( + imageVector = if (toggleState.value) + Icons.Outlined.Visibility else Icons.Outlined.VisibilityOff, + contentDescription = if (toggleState.value) + stringResource(R.string.content_description_show_password) else + stringResource(R.string.content_description_hide_password), + tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant + ) + } } \ No newline at end of file diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt index f8d008e3e4afc..0b9e57821d12c 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt @@ -10,6 +10,8 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn @@ -26,12 +28,17 @@ import androidx.compose.material.icons.outlined.NewReleases import androidx.compose.material.icons.filled.Add import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.core.graphics.drawable.toBitmap @@ -48,6 +55,7 @@ import com.android.credentialmanager.common.ui.TextOnSurface import com.android.credentialmanager.common.ui.TextSecondary import com.android.credentialmanager.common.ui.TextOnSurfaceVariant import com.android.credentialmanager.common.ui.ContainerCard +import com.android.credentialmanager.common.ui.ToggleVisibilityButton import com.android.credentialmanager.ui.theme.EntryShape import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme @@ -851,12 +859,38 @@ fun PrimaryCreateOptionRow( style = MaterialTheme.typography.titleLarge, modifier = Modifier.padding(top = 16.dp, start = 5.dp), ) - TextSecondary( + Row(modifier = Modifier.fillMaxWidth().padding(top = 4.dp, bottom = 16.dp, + start = 5.dp), + verticalAlignment = Alignment.CenterVertically) { + val visualTransformation = remember { PasswordVisualTransformation() } // This subtitle would never be null for create password - text = requestDisplayInfo.subtitle ?: "", - style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.padding(bottom = 16.dp, start = 5.dp), - ) + val originalPassword by remember { + mutableStateOf(requestDisplayInfo.subtitle ?: "") + } + val displayedPassword = remember { + mutableStateOf( + visualTransformation.filter( + AnnotatedString(originalPassword) + ).text.text + ) + } + TextSecondary( + text = displayedPassword.value, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(top = 4.dp, bottom = 4.dp), + ) + + ToggleVisibilityButton(modifier = Modifier.padding(start = 4.dp) + .height(24.dp).width(24.dp), onToggle = { + if (it) { + displayedPassword.value = originalPassword + } else { + displayedPassword.value = visualTransformation.filter( + AnnotatedString(originalPassword) + ).text.text + } + }) + } } CredentialType.UNKNOWN -> { if (requestDisplayInfo.subtitle != null) {