Skip to content

Commit c9919fc

Browse files
authored
feat: Improve app password required dialog (#22196)
* refactor: Relocate ApplicationPasswordReauthenticateDialogPreview Remove from abstract class to fix Jetpack Compose preview error: "render error." * refactor: Extract ApplicationPasswordDialog for Jetpack Compose preview Preview the actual UI code used by the app, rather than a copy of the dialog composition. * feat: Add ApplicationPasswordDialog dismiss button Communicate the dialog may be dismissed. * fix: Use consistent punctuation While Material's guidelines state to avoid unnecessary punctuation, all examples that have one more than one sentence use punctuation for all sentences.
1 parent 23d3eba commit c9919fc

File tree

2 files changed

+89
-93
lines changed

2 files changed

+89
-93
lines changed

WordPress/src/main/java/org/wordpress/android/ui/accounts/login/applicationpassword/ApplicationPasswordDialogActivity.kt

Lines changed: 88 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import androidx.compose.material.icons.Icons
88
import androidx.compose.material.icons.outlined.Lock
99
import androidx.compose.material3.AlertDialog
1010
import androidx.compose.material3.Button
11+
import androidx.compose.material3.TextButton
1112
import androidx.compose.foundation.layout.Column
1213
import androidx.compose.foundation.layout.size
1314
import androidx.compose.foundation.rememberScrollState
@@ -17,8 +18,6 @@ import androidx.compose.material3.Icon
1718
import androidx.compose.material3.Text
1819
import androidx.compose.runtime.Composable
1920
import androidx.compose.runtime.collectAsState
20-
import androidx.compose.runtime.mutableStateOf
21-
import androidx.compose.runtime.remember
2221
import androidx.compose.ui.unit.dp
2322
import androidx.compose.ui.res.stringResource
2423
import androidx.compose.ui.tooling.preview.Preview
@@ -69,8 +68,12 @@ abstract class ApplicationPasswordDialogActivity : ComponentActivity() {
6968

7069
setContent {
7170
AppThemeM3 {
72-
ApplicationPasswordReauthenticateDialog(
73-
viewModel = viewModel,
71+
val isLoading = viewModel.isLoading.collectAsState()
72+
ApplicationPasswordDialog(
73+
title = stringResource(getTitleResource()),
74+
description = getDescriptionString(),
75+
buttonText = getButtonTextResource(),
76+
isLoading = isLoading.value,
7477
onDismiss = {
7578
finish()
7679
},
@@ -86,100 +89,93 @@ abstract class ApplicationPasswordDialogActivity : ComponentActivity() {
8689
protected abstract fun getDescriptionString(): String
8790
protected abstract fun getButtonTextResource(): Int
8891

89-
@Composable
90-
fun ApplicationPasswordReauthenticateDialog(
91-
viewModel: ApplicationPasswordDialogViewModel,
92-
onDismiss: () -> Unit,
93-
onConfirm: () -> Unit,
94-
) {
95-
val isLoading = viewModel.isLoading.collectAsState()
96-
AlertDialog(
97-
onDismissRequest = onDismiss,
98-
icon = {
99-
Icon(
100-
imageVector = Icons.Outlined.Lock,
101-
contentDescription = null
102-
)
103-
},
104-
title = { Text(text = stringResource(getTitleResource())) },
105-
text = {
106-
Column(
107-
modifier = androidx.compose.ui.Modifier.verticalScroll(rememberScrollState())
108-
) {
109-
Text(text = getDescriptionString())
110-
}
111-
},
112-
confirmButton = {
113-
Button(
114-
onClick = {
115-
onConfirm()
116-
},
117-
enabled = !isLoading.value
118-
) {
119-
if (isLoading.value) {
120-
CircularProgressIndicator(
121-
modifier = androidx.compose.ui.Modifier.size(16.dp),
122-
strokeWidth = 2.dp
123-
)
124-
} else {
125-
Text(text = stringResource(getButtonTextResource()))
126-
}
127-
}
128-
}
129-
)
130-
}
131-
132-
@Preview
133-
@Preview(uiMode = UI_MODE_NIGHT_YES)
134-
@Composable
135-
fun ApplicationPasswordReauthenticateDialogPreview() {
136-
AppThemeM3 {
137-
ApplicationPasswordReauthenticateDialogPreviewContent()
138-
}
92+
companion object {
93+
const val EXTRA_SITE_URL = "site_url_arg"
13994
}
95+
}
14096

141-
@Composable
142-
private fun ApplicationPasswordReauthenticateDialogPreviewContent() {
143-
val isLoading = remember { mutableStateOf(false) }
144-
145-
AlertDialog(
146-
onDismissRequest = {},
147-
icon = {
148-
Icon(
149-
imageVector = Icons.Outlined.Lock,
150-
contentDescription = null
151-
)
152-
},
153-
title = { Text(text = stringResource(R.string.application_password_invalid)) },
154-
text = {
155-
Column(
156-
modifier = androidx.compose.ui.Modifier.verticalScroll(rememberScrollState())
157-
) {
158-
Text(text = stringResource(R.string.application_password_invalid_description))
159-
}
160-
},
161-
confirmButton = {
162-
Button(
163-
onClick = {
164-
isLoading.value = !isLoading.value
165-
},
166-
enabled = !isLoading.value
167-
) {
168-
if (isLoading.value) {
169-
CircularProgressIndicator(
170-
modifier = androidx.compose.ui.Modifier.size(16.dp),
171-
strokeWidth = 2.dp
172-
)
173-
} else {
174-
Text(text = stringResource(R.string.log_in))
175-
}
97+
@Composable
98+
fun ApplicationPasswordDialog(
99+
title: String,
100+
description: String,
101+
buttonText: Int,
102+
isLoading: Boolean,
103+
onDismiss: () -> Unit,
104+
onConfirm: () -> Unit,
105+
) {
106+
AlertDialog(
107+
onDismissRequest = onDismiss,
108+
icon = {
109+
Icon(
110+
imageVector = Icons.Outlined.Lock,
111+
contentDescription = null
112+
)
113+
},
114+
title = { Text(text = title) },
115+
text = {
116+
Column(
117+
modifier = androidx.compose.ui.Modifier.verticalScroll(rememberScrollState())
118+
) {
119+
Text(text = description)
120+
}
121+
},
122+
dismissButton = {
123+
TextButton(
124+
onClick = onDismiss,
125+
enabled = !isLoading
126+
) {
127+
Text(text = stringResource(R.string.cancel))
128+
}
129+
},
130+
confirmButton = {
131+
Button(
132+
onClick = {
133+
onConfirm()
134+
},
135+
enabled = !isLoading
136+
) {
137+
if (isLoading) {
138+
CircularProgressIndicator(
139+
modifier = androidx.compose.ui.Modifier.size(16.dp),
140+
strokeWidth = 2.dp
141+
)
142+
} else {
143+
Text(text = stringResource(buttonText))
176144
}
177145
}
146+
}
147+
)
148+
}
149+
150+
@Preview(showBackground = true)
151+
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
152+
@Composable
153+
fun ApplicationPasswordDialogPreview() {
154+
AppThemeM3 {
155+
ApplicationPasswordDialog(
156+
title = "Application Password Required",
157+
description = "To use this feature, you need to create an application password. " +
158+
"This is a secure way to authenticate without using your main password.",
159+
buttonText = R.string.get_started,
160+
isLoading = false,
161+
onDismiss = {},
162+
onConfirm = {}
178163
)
179164
}
165+
}
180166

181-
companion object {
182-
const val EXTRA_SITE_URL = "site_url_arg"
167+
@Preview(showBackground = true)
168+
@Composable
169+
fun ApplicationPasswordDialogLoadingPreview() {
170+
AppThemeM3 {
171+
ApplicationPasswordDialog(
172+
title = "Application Password Required",
173+
description = "To use this feature, you need to create an application password. " +
174+
"This is a secure way to authenticate without using your main password.",
175+
buttonText = R.string.get_started,
176+
isLoading = true,
177+
onDismiss = {},
178+
onConfirm = {}
179+
)
183180
}
184181
}
185-

WordPress/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5058,7 +5058,7 @@ translators: %s: Select control option value e.g: "Auto, 25%". -->
50585058
<string name="application_password_title">Authenticate using Application Password</string>
50595059
<string name="application_password_not_supported_error" a8c-src-lib="module:login">The provided site does not support Application Password authentication.</string>
50605060
<string name="application_password_invalid">Invalid Application Password</string>
5061-
<string name="application_password_invalid_description">Your application password no longer exists. Please sign in again to create a new application password </string>
5061+
<string name="application_password_invalid_description">Your application password no longer exists. Please sign in again to create a new application password.</string>
50625062
<string name="application_password_required">Application Password Required</string>
50635063
<string name="application_password_required_description">Application passwords are a more secure way to connect to your self-hosted site, and enable support for features like %1$s.</string>
50645064
<string name="application_password_required_block_editor">Block Editor</string>

0 commit comments

Comments
 (0)