fix: reveal screen UX and rules hardening (batch v1.0.20)
This commit is contained in:
parent
737514d18f
commit
9c1fbf60a0
|
|
@ -187,7 +187,8 @@ private fun AnswerRevealContent(
|
|||
partnerAnswer = state.partnerAnswer,
|
||||
question = state.question,
|
||||
onHistory = onHistory,
|
||||
onHome = onHome
|
||||
onHome = onHome,
|
||||
wasSealed = state.answer.schemaVersion == 3
|
||||
)
|
||||
if (state.followUpOptions.isNotEmpty()) {
|
||||
FollowUpSection(
|
||||
|
|
@ -436,7 +437,7 @@ private fun WaitingForPartnerState(
|
|||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(
|
||||
text = "Your answer key is released. Once your partner opens their reveal, both answers will appear here.",
|
||||
text = "Your answer key is released. You'll get a notification when your partner completes the reveal — no need to keep checking.",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
maxLines = 4,
|
||||
|
|
@ -480,12 +481,19 @@ private fun LostLocalKeyState(onHome: () -> Unit) {
|
|||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(
|
||||
text = "The sealed answer key was stored on the device you originally answered on. Open the app on that device to complete the reveal.",
|
||||
text = "The sealed answer key is stored on the device you originally answered on. Open the app on that device to complete the reveal.",
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
maxLines = 5,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Text(
|
||||
text = "If you no longer have that device, this answer cannot be recovered.",
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
color = MaterialTheme.colorScheme.error.copy(alpha = 0.75f),
|
||||
maxLines = 3,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
OutlinedButton(
|
||||
onClick = onHome,
|
||||
modifier = Modifier.fillMaxWidth().heightIn(min = 48.dp),
|
||||
|
|
@ -503,12 +511,13 @@ private fun RevealedState(
|
|||
partnerAnswer: LocalAnswer?,
|
||||
question: Question?,
|
||||
onHistory: () -> Unit,
|
||||
onHome: () -> Unit
|
||||
onHome: () -> Unit,
|
||||
wasSealed: Boolean = false
|
||||
) {
|
||||
RevealMessageCard {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(14.dp)) {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
RevealPill("Revealed")
|
||||
RevealPill(if (wasSealed) "Sealed reveal" else "Revealed")
|
||||
RevealPill(answer.category.displayCategoryName())
|
||||
RevealPill(answer.answerType.displayQuestionType())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,15 +72,18 @@ service cloud.firestore {
|
|||
// Sealed-answer helpers (schemaVersion 3, partner-proof reveal).
|
||||
|
||||
function isSealedPayload(value) {
|
||||
return value is string && value.matches('^sealed:v1:');
|
||||
// sealed:v1: + URL-safe base64 no-padding body; 80 chars minimum rules out trivially short values
|
||||
return value is string && value.matches('^sealed:v1:[A-Za-z0-9_-]{80,}$');
|
||||
}
|
||||
|
||||
function isKeybox(value) {
|
||||
return value is string && value.matches('^keybox:v1:');
|
||||
// keybox:v1: + URL-safe base64 no-padding; ECIES-P256 wrapping a 32-byte key is ~174 chars
|
||||
return value is string && value.matches('^keybox:v1:[A-Za-z0-9_-]{120,}$');
|
||||
}
|
||||
|
||||
function isCommitmentHash(value) {
|
||||
return value is string && value.matches('^sha256:');
|
||||
// sha256: + URL-safe base64 no-padding of a 32-byte digest = exactly 43 chars
|
||||
return value is string && value.matches('^sha256:[A-Za-z0-9_-]{43}$');
|
||||
}
|
||||
|
||||
// Returns true when the incoming data satisfies the sealed-answer create shape.
|
||||
|
|
|
|||
Loading…
Reference in New Issue