mirror of
https://github.com/bitwarden/android.git
synced 2025-03-16 19:28:44 +03:00
Add BitwardenPasswordField (#82)
This commit is contained in:
parent
60b004eb30
commit
9d9ee38070
3 changed files with 143 additions and 0 deletions
|
@ -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,
|
||||
)
|
||||
}
|
14
app/src/main/res/drawable/ic_visibility.xml
Normal file
14
app/src/main/res/drawable/ic_visibility.xml
Normal 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>
|
10
app/src/main/res/drawable/ic_visibility_off.xml
Normal file
10
app/src/main/res/drawable/ic_visibility_off.xml
Normal 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>
|
Loading…
Add table
Reference in a new issue