diff --git a/Android/app/src/main/java/com/archipelago/app/ui/components/QrScannerOverlay.kt b/Android/app/src/main/java/com/archipelago/app/ui/components/QrScannerOverlay.kt index 644524ed..e6d531e3 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/components/QrScannerOverlay.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/components/QrScannerOverlay.kt @@ -217,13 +217,20 @@ fun QrScannerOverlay( } } +/** Shared by the pairing scanner and the wallet scan modal. */ @Composable -private fun CameraQrPreview(onDecoded: (String) -> Unit) { +internal fun CameraQrPreview(onDecoded: (String) -> Unit) { val context = LocalContext.current val lifecycleOwner = LocalLifecycleOwner.current val currentOnDecoded by rememberUpdatedState(onDecoded) val previewView = remember { - PreviewView(context).apply { scaleType = PreviewView.ScaleType.FILL_CENTER } + PreviewView(context).apply { + scaleType = PreviewView.ScaleType.FILL_CENTER + // TextureView, not the SurfaceView default: SurfaceView punches a + // hole in the window, which black-flashes inside Compose fades and + // ignores rounded-corner clipping (wallet modal). + implementationMode = PreviewView.ImplementationMode.COMPATIBLE + } } DisposableEffect(Unit) { @@ -282,7 +289,19 @@ private class QrCodeAnalyzer(private val onDecoded: (String) -> Unit) : ImageAna ) } + private var lastAttempt = 0L + override fun analyze(image: ImageProxy) { + // Decode ~7x/s, not on every frame: TRY_HARDER (plus the inverted + // retry) pegs a core when run at camera rate, and that CPU contention + // is what made the preview itself stutter. KEEP_ONLY_LATEST means the + // frames skipped here are simply dropped, so decodes stay current. + val now = System.currentTimeMillis() + if (now - lastAttempt < 140) { + image.close() + return + } + lastAttempt = now try { val plane = image.planes[0] val buffer = plane.buffer