Skip to content
This repository was archived by the owner on Oct 15, 2024. It is now read-only.

Commit 9bdbd55

Browse files
committed
feat(ui-compose): add a PasswordField composable and switch decrypt screen to it
1 parent 662be13 commit 9bdbd55

File tree

4 files changed

+84
-8
lines changed

4 files changed

+84
-8
lines changed

app/src/main/java/app/passwordstore/ui/crypto/DecryptScreen.kt

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp
2424
import app.passwordstore.R
2525
import app.passwordstore.data.passfile.PasswordEntry
2626
import app.passwordstore.ui.APSAppBar
27+
import app.passwordstore.ui.compose.PasswordField
2728
import app.passwordstore.ui.compose.theme.APSThemePreview
2829
import app.passwordstore.util.time.UserClock
2930
import app.passwordstore.util.totp.UriTotpFinder
@@ -56,13 +57,7 @@ fun PasswordEntryScreen(
5657
style = MaterialTheme.typography.headlineSmall,
5758
)
5859
if (entry.password != null) {
59-
TextField(
60-
value = entry.password!!,
61-
onValueChange = {},
62-
readOnly = true,
63-
label = { Text("Password") },
64-
trailingIcon = { CopyButton { clipboard.setText(AnnotatedString(entry.password!!)) } },
65-
)
60+
PasswordField(value = entry.password!!, label = "Password", initialVisibility = false)
6661
}
6762
if (entry.hasTotp()) {
6863
val totp by entry.totp.collectAsState(runBlocking { entry.totp.first() })
@@ -97,7 +92,7 @@ private fun PasswordEntryPreview() {
9792
APSThemePreview { PasswordEntryScreen("Test Entry", createTestEntry()) }
9893
}
9994

100-
fun createTestEntry() =
95+
private fun createTestEntry() =
10196
PasswordEntry(
10297
UserClock(),
10398
UriTotpFinder(),
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package app.passwordstore.ui.compose
2+
3+
import androidx.compose.material3.ExperimentalMaterial3Api
4+
import androidx.compose.material3.Icon
5+
import androidx.compose.material3.IconButton
6+
import androidx.compose.material3.Text
7+
import androidx.compose.material3.TextField
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.getValue
10+
import androidx.compose.runtime.mutableStateOf
11+
import androidx.compose.runtime.remember
12+
import androidx.compose.runtime.setValue
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.res.painterResource
15+
import androidx.compose.ui.text.input.PasswordVisualTransformation
16+
import androidx.compose.ui.text.input.VisualTransformation
17+
18+
@OptIn(ExperimentalMaterial3Api::class)
19+
@Composable
20+
public fun PasswordField(
21+
value: String,
22+
label: String,
23+
initialVisibility: Boolean,
24+
modifier: Modifier = Modifier,
25+
) {
26+
var visible by remember { mutableStateOf(initialVisibility) }
27+
TextField(
28+
value = value,
29+
onValueChange = {},
30+
readOnly = true,
31+
label = { Text(label) },
32+
visualTransformation =
33+
if (visible) VisualTransformation.None else PasswordVisualTransformation(),
34+
trailingIcon = {
35+
ToggleButton(
36+
visible = visible,
37+
contentDescription = "Toggle password visibility",
38+
onButtonClick = { visible = !visible },
39+
)
40+
},
41+
modifier = modifier,
42+
)
43+
}
44+
45+
@Composable
46+
private fun ToggleButton(
47+
visible: Boolean,
48+
contentDescription: String,
49+
onButtonClick: () -> Unit,
50+
modifier: Modifier = Modifier,
51+
) {
52+
IconButton(onClick = onButtonClick, modifier = modifier) {
53+
val icon =
54+
if (visible) painterResource(id = R.drawable.baseline_visibility_off_24)
55+
else painterResource(id = R.drawable.baseline_visibility_24)
56+
Icon(
57+
painter = icon,
58+
contentDescription = contentDescription,
59+
)
60+
}
61+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:tint="#000000"
5+
android:viewportWidth="24"
6+
android:viewportHeight="24">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z" />
10+
</vector>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:tint="#000000"
5+
android:viewportWidth="24"
6+
android:viewportHeight="24">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z" />
10+
</vector>

0 commit comments

Comments
 (0)