-
Notifications
You must be signed in to change notification settings - Fork 1.3k
feat: Improve app password required dialog #22196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8693c4f
ab7e479
a54593e
fe69565
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ import androidx.compose.material.icons.Icons | |
| import androidx.compose.material.icons.outlined.Lock | ||
| import androidx.compose.material3.AlertDialog | ||
| import androidx.compose.material3.Button | ||
| import androidx.compose.material3.TextButton | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.size | ||
| import androidx.compose.foundation.rememberScrollState | ||
|
|
@@ -17,8 +18,6 @@ import androidx.compose.material3.Icon | |
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.collectAsState | ||
| import androidx.compose.runtime.mutableStateOf | ||
| import androidx.compose.runtime.remember | ||
| import androidx.compose.ui.unit.dp | ||
| import androidx.compose.ui.res.stringResource | ||
| import androidx.compose.ui.tooling.preview.Preview | ||
|
|
@@ -69,8 +68,12 @@ abstract class ApplicationPasswordDialogActivity : ComponentActivity() { | |
|
|
||
| setContent { | ||
| AppThemeM3 { | ||
| ApplicationPasswordReauthenticateDialog( | ||
| viewModel = viewModel, | ||
| val isLoading = viewModel.isLoading.collectAsState() | ||
| ApplicationPasswordDialog( | ||
| title = stringResource(getTitleResource()), | ||
| description = getDescriptionString(), | ||
| buttonText = getButtonTextResource(), | ||
| isLoading = isLoading.value, | ||
| onDismiss = { | ||
| finish() | ||
| }, | ||
|
|
@@ -86,100 +89,93 @@ abstract class ApplicationPasswordDialogActivity : ComponentActivity() { | |
| protected abstract fun getDescriptionString(): String | ||
| protected abstract fun getButtonTextResource(): Int | ||
|
|
||
| @Composable | ||
| fun ApplicationPasswordReauthenticateDialog( | ||
| viewModel: ApplicationPasswordDialogViewModel, | ||
| onDismiss: () -> Unit, | ||
| onConfirm: () -> Unit, | ||
| ) { | ||
| val isLoading = viewModel.isLoading.collectAsState() | ||
| AlertDialog( | ||
| onDismissRequest = onDismiss, | ||
| icon = { | ||
| Icon( | ||
| imageVector = Icons.Outlined.Lock, | ||
| contentDescription = null | ||
| ) | ||
| }, | ||
| title = { Text(text = stringResource(getTitleResource())) }, | ||
| text = { | ||
| Column( | ||
| modifier = androidx.compose.ui.Modifier.verticalScroll(rememberScrollState()) | ||
| ) { | ||
| Text(text = getDescriptionString()) | ||
| } | ||
| }, | ||
| confirmButton = { | ||
| Button( | ||
| onClick = { | ||
| onConfirm() | ||
| }, | ||
| enabled = !isLoading.value | ||
| ) { | ||
| if (isLoading.value) { | ||
| CircularProgressIndicator( | ||
| modifier = androidx.compose.ui.Modifier.size(16.dp), | ||
| strokeWidth = 2.dp | ||
| ) | ||
| } else { | ||
| Text(text = stringResource(getButtonTextResource())) | ||
| } | ||
| } | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| @Preview | ||
| @Preview(uiMode = UI_MODE_NIGHT_YES) | ||
| @Composable | ||
| fun ApplicationPasswordReauthenticateDialogPreview() { | ||
| AppThemeM3 { | ||
| ApplicationPasswordReauthenticateDialogPreviewContent() | ||
| } | ||
| companion object { | ||
| const val EXTRA_SITE_URL = "site_url_arg" | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| private fun ApplicationPasswordReauthenticateDialogPreviewContent() { | ||
| val isLoading = remember { mutableStateOf(false) } | ||
|
|
||
| AlertDialog( | ||
|
Comment on lines
-142
to
-145
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replaced explicit "preview" component with preview of the actual UI code used by the application. |
||
| onDismissRequest = {}, | ||
| icon = { | ||
| Icon( | ||
| imageVector = Icons.Outlined.Lock, | ||
| contentDescription = null | ||
| ) | ||
| }, | ||
| title = { Text(text = stringResource(R.string.application_password_invalid)) }, | ||
| text = { | ||
| Column( | ||
| modifier = androidx.compose.ui.Modifier.verticalScroll(rememberScrollState()) | ||
| ) { | ||
| Text(text = stringResource(R.string.application_password_invalid_description)) | ||
| } | ||
| }, | ||
| confirmButton = { | ||
| Button( | ||
| onClick = { | ||
| isLoading.value = !isLoading.value | ||
| }, | ||
| enabled = !isLoading.value | ||
| ) { | ||
| if (isLoading.value) { | ||
| CircularProgressIndicator( | ||
| modifier = androidx.compose.ui.Modifier.size(16.dp), | ||
| strokeWidth = 2.dp | ||
| ) | ||
| } else { | ||
| Text(text = stringResource(R.string.log_in)) | ||
| } | ||
| @Composable | ||
| fun ApplicationPasswordDialog( | ||
| title: String, | ||
| description: String, | ||
| buttonText: Int, | ||
| isLoading: Boolean, | ||
| onDismiss: () -> Unit, | ||
| onConfirm: () -> Unit, | ||
| ) { | ||
| AlertDialog( | ||
| onDismissRequest = onDismiss, | ||
| icon = { | ||
| Icon( | ||
| imageVector = Icons.Outlined.Lock, | ||
| contentDescription = null | ||
| ) | ||
| }, | ||
| title = { Text(text = title) }, | ||
| text = { | ||
| Column( | ||
| modifier = androidx.compose.ui.Modifier.verticalScroll(rememberScrollState()) | ||
| ) { | ||
| Text(text = description) | ||
| } | ||
| }, | ||
| dismissButton = { | ||
| TextButton( | ||
| onClick = onDismiss, | ||
| enabled = !isLoading | ||
| ) { | ||
| Text(text = stringResource(R.string.cancel)) | ||
| } | ||
| }, | ||
| confirmButton = { | ||
| Button( | ||
| onClick = { | ||
| onConfirm() | ||
| }, | ||
| enabled = !isLoading | ||
| ) { | ||
| if (isLoading) { | ||
| CircularProgressIndicator( | ||
| modifier = androidx.compose.ui.Modifier.size(16.dp), | ||
| strokeWidth = 2.dp | ||
| ) | ||
| } else { | ||
| Text(text = stringResource(buttonText)) | ||
| } | ||
| } | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| @Preview(showBackground = true) | ||
| @Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES) | ||
| @Composable | ||
| fun ApplicationPasswordDialogPreview() { | ||
| AppThemeM3 { | ||
| ApplicationPasswordDialog( | ||
| title = "Application Password Required", | ||
| description = "To use this feature, you need to create an application password. " + | ||
| "This is a secure way to authenticate without using your main password.", | ||
| buttonText = R.string.get_started, | ||
| isLoading = false, | ||
| onDismiss = {}, | ||
| onConfirm = {} | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| companion object { | ||
| const val EXTRA_SITE_URL = "site_url_arg" | ||
| @Preview(showBackground = true) | ||
| @Composable | ||
| fun ApplicationPasswordDialogLoadingPreview() { | ||
| AppThemeM3 { | ||
| ApplicationPasswordDialog( | ||
| title = "Application Password Required", | ||
| description = "To use this feature, you need to create an application password. " + | ||
| "This is a secure way to authenticate without using your main password.", | ||
| buttonText = R.string.get_started, | ||
| isLoading = true, | ||
| onDismiss = {}, | ||
| onConfirm = {} | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5058,7 +5058,7 @@ translators: %s: Select control option value e.g: "Auto, 25%". --> | |
| <string name="application_password_title">Authenticate using Application Password</string> | ||
| <string name="application_password_not_supported_error" a8c-src-lib="module:login">The provided site does not support Application Password authentication.</string> | ||
| <string name="application_password_invalid">Invalid Application Password</string> | ||
| <string name="application_password_invalid_description">Your application password no longer exists. Please sign in again to create a new application password </string> | ||
| <string name="application_password_invalid_description">Your application password no longer exists. Please sign in again to create a new application password.</string> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While Material guidelines suggest avoiding unnecessary punctuation, all examples with multiple sentences punctuate all sentences. |
||
| <string name="application_password_required">Application Password Required</string> | ||
| <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> | ||
| <string name="application_password_required_block_editor">Block Editor</string> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hoisted ViewModel to simplify Jetpack Compose component arguments and preview.