From 8912618a67af63be6ab8ec91c6a13096b33dcc7a Mon Sep 17 00:00:00 2001 From: TheCryptoDonkey Date: Sat, 26 Sep 2026 01:33:53 +0100 Subject: [PATCH 1/2] fix: keep the check code visible on the Done screen The check code was cleared as soon as finishEnrolment ran, before the owner had necessarily finished comparing it with Sapwood or the board's own card. It now stays labelled and visible on the Done screen, with a reminder of what it should match, until the owner leaves. --- CHANGELOG.md | 6 +++++ .../cambium/unlock/UnlockEnrolActivity.kt | 18 +++++++++---- .../main/res/layout/activity_unlock_enrol.xml | 26 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 ++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f173dae..50951d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +- The check code stays on screen once enrolment finishes, labelled and with a reminder that it + should match what Sapwood shows, instead of disappearing as soon as the board's answer is + confirmed. It clears when the owner leaves the screen. + ## 0.7.0 (2026-09-26) - Adding a phone now scans Sapwood's own invite QR instead of the other way round: "Add a phone" diff --git a/app/src/main/kotlin/dev/forgesworn/cambium/unlock/UnlockEnrolActivity.kt b/app/src/main/kotlin/dev/forgesworn/cambium/unlock/UnlockEnrolActivity.kt index 9a147f4..958f1f1 100644 --- a/app/src/main/kotlin/dev/forgesworn/cambium/unlock/UnlockEnrolActivity.kt +++ b/app/src/main/kotlin/dev/forgesworn/cambium/unlock/UnlockEnrolActivity.kt @@ -285,7 +285,7 @@ class UnlockEnrolActivity : AppCompatActivity() { conflicted = true binding.enrolBatteryButton.isVisible = false binding.enrolStatus.text = getString(R.string.enrol_conflict_after, storedId, handOff.id) - binding.enrolCheckCode.isVisible = false + showCheckCode(false) } handOff.wipe() return @@ -300,7 +300,7 @@ class UnlockEnrolActivity : AppCompatActivity() { enrolSecretHex = null binding.enrolConfirmButton.isVisible = false binding.enrolStatus.text = getString(R.string.enrol_conflict, first.id, handOff.id) - binding.enrolCheckCode.isVisible = false + showCheckCode(false) } handOff.wipe() return @@ -319,7 +319,7 @@ class UnlockEnrolActivity : AppCompatActivity() { binding.enrolRetryButton.isVisible = false binding.enrolStatus.text = getString(R.string.enrol_received) binding.enrolCheckCode.text = checkCode(envelope.ephemeralPubkeyHex).orEmpty() - binding.enrolCheckCode.isVisible = true + showCheckCode(true) binding.enrolConfirmButton.isVisible = true lifecycleScope.launch { delay(PENDING_TIMEOUT_MILLIS) @@ -330,7 +330,7 @@ class UnlockEnrolActivity : AppCompatActivity() { enrolSecretHex = null binding.enrolConfirmButton.isVisible = false binding.enrolStatus.text = getString(R.string.enrol_timed_out, handOff.id) - binding.enrolCheckCode.isVisible = false + showCheckCode(false) } } promptSeal() @@ -393,8 +393,9 @@ class UnlockEnrolActivity : AppCompatActivity() { PairingStore(this).setKeepAliveEnabled(true) HeartwoodKeepAliveService.start(this) + // Left showing on Done: the owner may still be comparing it with Sapwood or the board's + // own card at this point, and it stays harmless to see once the slot secret is sealed. binding.enrolConfirmButton.isVisible = false - binding.enrolCheckCode.isVisible = false binding.enrolStatus.text = getString(R.string.enrol_done, handOff.id) binding.enrolBatteryButton.isVisible = !isIgnoringBatteryOptimisations(this) binding.enrolDoneButton.setText(R.string.enrol_finished) @@ -412,6 +413,13 @@ class UnlockEnrolActivity : AppCompatActivity() { private fun shortLabel(pairing: Pairing): String = pairing.label?.takeIf { it.isNotBlank() } ?: pairing.displayLabel().let { if (it.length > 20) it.take(12) + "…" else it } + /** The check code and its label/hint always show or hide together. */ + private fun showCheckCode(visible: Boolean) { + binding.enrolCheckCodeLabel.isVisible = visible + binding.enrolCheckCode.isVisible = visible + binding.enrolCheckCodeHint.isVisible = visible + } + private fun showOnly(message: String) { binding.enrolBody.isVisible = false binding.enrolScanButton.isVisible = false diff --git a/app/src/main/res/layout/activity_unlock_enrol.xml b/app/src/main/res/layout/activity_unlock_enrol.xml index 6c20b18..c6129b5 100644 --- a/app/src/main/res/layout/activity_unlock_enrol.xml +++ b/app/src/main/res/layout/activity_unlock_enrol.xml @@ -140,12 +140,24 @@ android:textColor="@color/on_background" tools:text="Waiting for the board…" /> + + + +