Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b94815a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add ability to show/hide password"

parents d2515411 3086498f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -13,6 +13,10 @@
  <string name="string_more_options">More options</string>
  <!-- This is a label for a button that links to additional information about passkeys. [CHAR LIMIT=20] -->
  <string name="string_learn_more">Learn more</string>
  <!-- This is a label for content description for show password icon button. -->
  <string name="content_description_show_password">Show password</string>
  <!-- This is a label for content description for hide password icon button. -->
  <string name="content_description_hide_password">Hide password</string>
  <!-- This string introduces passkeys to the users for the first time they use this method. Tip: to avoid gendered language patterns, this header could be translated as if the original string were "More safety with passkeys". [CHAR LIMIT=200] -->
  <string name="passkey_creation_intro_title">Safer with passkeys</string>
  <!-- This string highlight passkey benefits related with the password. [CHAR LIMIT=200] -->
+1 −1
Original line number Diff line number Diff line
@@ -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 ->
+35 −0
Original line number Diff line number Diff line
@@ -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) {
@@ -33,3 +45,26 @@ 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<Boolean> = 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
+39 −5
Original line number Diff line number Diff line
@@ -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 ?: "",
                            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(bottom = 16.dp, start = 5.dp),
                                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) {