diff --git a/AGENTS.md b/AGENTS.md index 79aced0..c2750ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -152,6 +152,13 @@ Established 2026-08-25, and it decides more than it looks like: `"""\n-----BEGIN CERTIFICATE-----` costs Android's `CertificateFactory` its preamble sniff, so it tries DER instead and fails at runtime with `ASN.1 ... DECODE_ERROR` — nowhere near the code that produced it. +- **ZXing only looks for a dark code on a light ground.** The enrollment + QR is block characters in the terminal's foreground colour, so a + dark-themed terminal renders it as a negative and the in-app scanner + silently never matches — while the phone's own camera app, which tries + both, does. The scanner asks for `Intents.Scan.MIXED_SCAN`, which + alternates normal and inverted frames; keep it that way rather than + making the server dictate the colours. - **AGP 9 refuses `Provider`s in the source-set API**: generated sources go through `androidComponents.onVariants { it.sources.java?.addGenerated SourceDirectory(task, Task::outputDir) }`, which also carries the task diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/SettingsScreen.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/SettingsScreen.kt index 0c0b4b1..af406b9 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/SettingsScreen.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/SettingsScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp import androidx.activity.compose.rememberLauncherForActivityResult +import com.google.zxing.client.android.Intents import com.journeyapps.barcodescanner.ScanContract import com.journeyapps.barcodescanner.ScanIntentResult import com.journeyapps.barcodescanner.ScanOptions @@ -82,7 +83,22 @@ fun SettingsScreen( Spacer(Modifier.height(16.dp)) OutlinedButton( - onClick = { scanLauncher.launch(ScanOptions().setDesiredBarcodeFormats(ScanOptions.QR_CODE)) }, + onClick = { + scanLauncher.launch( + ScanOptions() + .setDesiredBarcodeFormats(ScanOptions.QR_CODE) + // Decode both polarities: ZXing otherwise looks only for a + // dark code on a light ground, and ai-server's QR is block + // characters in the terminal's foreground colour -- so on a + // dark-themed terminal it comes out as a photographic + // negative that the scanner silently never matches. Which + // way round it renders is the terminal's business, not + // something this app should depend on. MIXED_SCAN alternates + // normal and inverted frames, so it costs half the frame + // rate at each polarity and nothing else. + .addExtra(Intents.Scan.SCAN_TYPE, Intents.Scan.MIXED_SCAN) + ) + }, modifier = Modifier.fillMaxWidth(), ) { Text("Scan QR code") } Spacer(Modifier.height(16.dp))