fix(wallet): photo QR decode uses native BarcodeDetector first — dense Lightning invoices scan reliably
Some checks failed
Demo images / Build & push demo images (push) Failing after 33s

On the companion (plain-http LAN = no secure context = no live camera)
the photo path IS the scanner, and qr-scanner's single wasm pass often
misses the dense QR of a full BOLT11 invoice. Android WebView's native
BarcodeDetector handles them easily — try it first, wasm as fallback,
plus a 'Reading photo…' status.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
archipelago 2026-07-22 20:16:35 -04:00
parent bfd8bc5b9a
commit cbb108a636

View File

@ -363,9 +363,10 @@ async function onPhotoPicked(e: Event) {
const input = e.target as HTMLInputElement
const file = input.files?.[0]
if (!file) return
scanStatusIsError.value = false
scanStatus.value = 'Reading photo…'
try {
const result = await QrScanner.scanImage(file, { returnDetailedScanResult: true })
handleScanned(result.data)
handleScanned(await decodePhotoRobust(file))
} catch {
scanStatusIsError.value = true
scanStatus.value = 'No QR code found in that photo — try again, closer and well-lit'
@ -374,6 +375,28 @@ async function onPhotoPicked(e: Event) {
}
}
/** Decode a QR photo with every engine we have. On the companion app the
* photo path IS the scan path (plain-http LAN = no secure context = no
* live camera), and Lightning invoices make DENSE codes that the wasm
* engine's single pass often misses (reported 2026-07-22: "camera not
* picking up the invoice"). Android WebView's native BarcodeDetector is
* far stronger on dense codes, so try it first; fall back to qr-scanner. */
async function decodePhotoRobust(file: File): Promise<string> {
try {
const Detector = (window as unknown as { BarcodeDetector?: new (opts: { formats: string[] }) => { detect(src: ImageBitmap): Promise<Array<{ rawValue: string }>> } }).BarcodeDetector
if (Detector) {
const bmp = await createImageBitmap(file)
const codes = await new Detector({ formats: ['qr_code'] }).detect(bmp)
const hit = codes.find(c => c.rawValue)
if (hit) return hit.rawValue
}
} catch {
// Native detector unavailable/failed wasm engine below.
}
const result = await QrScanner.scanImage(file, { returnDetailedScanResult: true })
return result.data
}
// --- Detection (ported from k484's scanner) ---
const rail = ref<Rail>('lightning')
const action = ref<Action>('pay-invoice')