feat(android): typed-confirm on AdminUsers delete (audit v3 §4.20)
Delete-user was a plain Delete/Cancel AlertDialog — too permissive for an irreversible action. Now mirrors Flutter's TypedConfirmSheet: an OutlinedTextField where the admin must type "DELETE" before the Delete button enables (case-insensitive). The button stays disabled and muted until the word matches. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -512,18 +512,41 @@ private fun DeleteConfirmDialog(
|
|||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
onConfirm: () -> Unit,
|
onConfirm: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
var typed by remember { mutableStateOf("") }
|
||||||
|
val confirmed = typed.trim().equals(DELETE_CONFIRM_WORD, ignoreCase = true)
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
title = { Text("Delete user?") },
|
title = { Text("Delete user?") },
|
||||||
text = {
|
text = {
|
||||||
Text("Delete @${user.username}? This removes the account and all their data.")
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
|
Text(
|
||||||
|
"Delete @${user.username}? This removes the account and all " +
|
||||||
|
"their data. Type $DELETE_CONFIRM_WORD to confirm.",
|
||||||
|
)
|
||||||
|
OutlinedTextField(
|
||||||
|
value = typed,
|
||||||
|
onValueChange = { typed = it },
|
||||||
|
label = { Text("Type $DELETE_CONFIRM_WORD") },
|
||||||
|
singleLine = true,
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = onConfirm) {
|
TextButton(onClick = onConfirm, enabled = confirmed) {
|
||||||
Text("Delete", color = MaterialTheme.colorScheme.error)
|
Text(
|
||||||
|
"Delete",
|
||||||
|
color = if (confirmed) {
|
||||||
|
MaterialTheme.colorScheme.error
|
||||||
|
} else {
|
||||||
|
MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } },
|
dismissButton = { TextButton(onClick = onDismiss) { Text("Cancel") } },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val DELETE_CONFIRM_WORD = "DELETE"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user