diff --git a/CHANGELOG.md b/CHANGELOG.md index f173dae..a92ec64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## Unreleased + +- The check code stays on screen once enrolment finishes, labelled and with a reminder that it + should match the board and Sapwood, instead of disappearing as soon as the board's answer is + confirmed. It clears when the owner leaves the screen. +- Release builds no longer embed git metadata, so the APK built by F-Droid matches the one + published here whatever checkout it was built from. + ## 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/build.gradle.kts b/app/build.gradle.kts index e138cdc..1c9f176 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -49,6 +49,10 @@ android { buildTypes { release { isMinifyEnabled = false + // Keep git metadata out of the APK: a build from a worktree or a tarball records + // NO_VALID_GIT_FOUND where F-Droid's clone records the commit, and that one file was + // enough to fail F-Droid's reproducible-build check for 0.5.0. + vcsInfo.include = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") if (releaseSigning.getProperty("storeFile") != null) { signingConfig = signingConfigs.getByName("release") 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…" /> + + + +