Add BitwardenPasswordField (#82)

This commit is contained in:
Brian Yencho 2023-10-02 15:37:23 -05:00 committed by Álison Fernandes
parent 60b004eb30
commit 9d9ee38070
3 changed files with 143 additions and 0 deletions

View file

@ -0,0 +1,119 @@
package com.x8bit.bitwarden.ui.platform.components
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
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.res.painterResource
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
import com.x8bit.bitwarden.R
/**
* Represents a Bitwarden-styled password field that manages the state of a show/hide indicator
* internally.
*
* @param label Label for the text field.
* @param value Current next on the text field.
* @param onValueChange Callback that is triggered when the password changes.
* @param modifier Modifier for the composable.
* @param initialShowPassword The initial state of the show/hide password control. A value of
* `false` (the default) indicates that that password should begin in the hidden state.
*/
@Composable
fun BitwardenPasswordField(
label: String,
value: String,
onValueChange: (String) -> Unit,
modifier: Modifier = Modifier,
initialShowPassword: Boolean = false,
) {
var showPassword by rememberSaveable { mutableStateOf(initialShowPassword) }
OutlinedTextField(
modifier = modifier,
textStyle = MaterialTheme.typography.bodyLarge,
label = { Text(text = label) },
value = value,
onValueChange = onValueChange,
visualTransformation = if (showPassword) {
VisualTransformation.None
} else {
PasswordVisualTransformation()
},
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
trailingIcon = {
IconButton(
onClick = { showPassword = !showPassword },
) {
if (showPassword) {
Icon(
painter = painterResource(id = R.drawable.ic_visibility_off),
contentDescription = stringResource(id = R.string.hide),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
} else {
Icon(
painter = painterResource(id = R.drawable.ic_visibility),
contentDescription = stringResource(id = R.string.show),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
},
)
}
@Preview
@Composable
private fun BitwardenPasswordField_preview_withInput_hidePassword() {
BitwardenPasswordField(
label = "Label",
value = "Password",
onValueChange = {},
initialShowPassword = false,
)
}
@Preview
@Composable
private fun BitwardenPasswordField_preview_withInput_showPassword() {
BitwardenPasswordField(
label = "Label",
value = "Password",
onValueChange = {},
initialShowPassword = true,
)
}
@Preview
@Composable
private fun BitwardenPasswordField_preview_withoutInput_hidePassword() {
BitwardenPasswordField(
label = "Label",
value = "",
onValueChange = {},
initialShowPassword = false,
)
}
@Preview
@Composable
private fun BitwardenPasswordField_preview_withoutInput_showPassword() {
BitwardenPasswordField(
label = "Label",
value = "",
onValueChange = {},
initialShowPassword = true,
)
}

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,7.625C8.12,7.625 5.607,10.043 4.289,11.671C4.133,11.864 4.133,12.136 4.289,12.329C5.607,13.957 8.12,16.375 12,16.375C15.88,16.375 18.392,13.957 19.711,12.329C19.867,12.136 19.867,11.864 19.711,11.671C18.392,10.043 15.88,7.625 12,7.625ZM3.318,10.884C4.718,9.155 7.551,6.375 12,6.375C16.449,6.375 19.282,9.155 20.682,10.884C21.21,11.536 21.21,12.464 20.682,13.116C19.282,14.845 16.449,17.625 12,17.625C7.551,17.625 4.718,14.845 3.318,13.116C2.79,12.464 2.79,11.536 3.318,10.884Z"
android:fillColor="#45464F"
android:fillType="evenOdd"/>
<path
android:pathData="M12,10.125C10.964,10.125 10.125,10.965 10.125,12C10.125,13.035 10.964,13.875 12,13.875C13.035,13.875 13.875,13.035 13.875,12C13.875,10.965 13.035,10.125 12,10.125ZM8.875,12C8.875,10.274 10.274,8.875 12,8.875C13.726,8.875 15.125,10.274 15.125,12C15.125,13.726 13.726,15.125 12,15.125C10.274,15.125 8.875,13.726 8.875,12Z"
android:fillColor="#45464F"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M2.058,17.424C1.814,17.668 1.814,18.064 2.058,18.308C2.302,18.552 2.698,18.552 2.942,18.308L6.315,14.935C7.391,15.357 8.618,15.625 10,15.625C14.449,15.625 17.282,12.845 18.682,11.116C19.21,10.464 19.21,9.536 18.682,8.884C17.961,7.994 16.859,6.823 15.351,5.898L18.308,2.942C18.552,2.698 18.552,2.302 18.308,2.058C18.064,1.814 17.668,1.814 17.424,2.058L14.199,5.283C13.004,4.738 11.608,4.375 10,4.375C5.551,4.375 2.718,7.155 1.318,8.884C0.79,9.536 0.79,10.464 1.318,11.116C2.111,12.095 3.365,13.413 5.112,14.37L2.058,17.424ZM7.294,13.956C8.109,14.217 9.01,14.375 10,14.375C13.88,14.375 16.392,11.957 17.711,10.329C17.867,10.136 17.867,9.864 17.711,9.671C16.988,8.779 15.907,7.65 14.439,6.811L12.745,8.505C12.987,8.949 13.125,9.458 13.125,10C13.125,11.726 11.726,13.125 10,13.125C9.458,13.125 8.949,12.987 8.505,12.745L7.294,13.956ZM7.546,11.936L6.038,13.444C4.325,12.591 3.088,11.315 2.289,10.329C2.133,10.136 2.133,9.864 2.289,9.671C3.607,8.043 6.12,5.625 10,5.625C11.214,5.625 12.294,5.862 13.245,6.237L11.936,7.547C11.403,7.126 10.731,6.875 10,6.875C8.274,6.875 6.875,8.274 6.875,10C6.875,10.731 7.126,11.403 7.546,11.936ZM9.455,11.795C9.628,11.847 9.811,11.875 10,11.875C11.035,11.875 11.875,11.035 11.875,10C11.875,9.811 11.847,9.628 11.795,9.455L9.455,11.795ZM11.042,8.441L8.441,11.042C8.241,10.744 8.125,10.385 8.125,10C8.125,8.964 8.964,8.125 10,8.125C10.385,8.125 10.744,8.241 11.042,8.441Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>