feat: show the group's key in full, with a copy button

The shared-key screen showed `thresholdPublicKey.take(16)` followed by an
ellipsis. A 16-character prefix is enough to recognise a key you already know and
not enough for the one thing this key is for.

Members compare it out of band to confirm every device finished the ceremony on
the same key. That is the check that catches a device which quietly ended up
elsewhere -- and it cannot be done against a prefix, or from a screen the value
cannot be copied off. Both halves of that were missing.

The whole 66-character key now renders, wrapping rather than ellipsised, in a
monospaced face so a character-by-character comparison lines up instead of drifting
under proportional spacing. A FilledIconButton beside it copies the key via
LocalClipboardManager, the same way ShareProfileScreen and the image viewers
already do it. The "Key: " prefix became a label above so the key gets the full
width.

No copied-confirmation toast, matching ShareProfileScreen: Android shows its own
clipboard notice on 13+, and a snackbar here would double up.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kgothatso Ngako
2026-09-05 13:45:34 +02:00
parent cae50ce359
commit b200916844

View File

@@ -14,6 +14,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.ErrorOutline
import androidx.compose.material.icons.filled.Key
import androidx.compose.material.icons.filled.RadioButtonUnchecked
@@ -43,6 +44,9 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import press.mantra.compose.database.model.ChatRoom
@@ -393,10 +397,38 @@ private fun RitualProgress(
}
session.thresholdPublicKey?.let { thresholdPublicKey ->
Text(
text = "Key: ${thresholdPublicKey.take(16)}",
style = MaterialTheme.typography.bodyMedium
)
val clipboardManager = LocalClipboardManager.current
Text(text = "Key", style = MaterialTheme.typography.labelMedium)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
// In full, and wrapping rather than ellipsised. This is the
// group's key: it is what members compare out of band to
// check every device ended the ceremony on the same one, and
// a truncated key cannot be compared. Monospaced so the
// comparison is character by character.
Text(
text = thresholdPublicKey,
style = MaterialTheme.typography.bodySmall,
fontFamily = FontFamily.Monospace,
modifier = Modifier.weight(1f)
)
FilledIconButton(
onClick = {
clipboardManager.setText(AnnotatedString(thresholdPublicKey))
}
) {
Icon(
imageVector = Icons.Default.ContentCopy,
contentDescription = "Copy the group's key"
)
}
}
}
Text(