PM-26594: Move the QrCodeAnalyzer to the UI module (#5980)

This commit is contained in:
David Perez
2025-10-07 12:04:16 -05:00
committed by GitHub
parent cd9c7f98e7
commit 7849bbbb0a
13 changed files with 19 additions and 126 deletions

View File

@@ -271,7 +271,6 @@ dependencies {
implementation(platform(libs.square.retrofit.bom))
implementation(libs.square.retrofit)
implementation(libs.timber)
implementation(libs.zxing.zxing.core)
// For now we are restricted to running Compose tests for debug builds only
debugImplementation(libs.androidx.compose.ui.test.manifest)

View File

@@ -55,6 +55,8 @@ import com.bitwarden.ui.platform.base.util.annotatedStringResource
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzer
import com.bitwarden.ui.platform.feature.qrcodescan.util.QrCodeAnalyzerImpl
import com.bitwarden.ui.platform.model.WindowSize
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
@@ -62,8 +64,6 @@ import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.bitwarden.ui.platform.theme.LocalBitwardenColorScheme
import com.bitwarden.ui.platform.theme.color.darkBitwardenColorScheme
import com.bitwarden.ui.platform.util.rememberWindowSize
import com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util.QrCodeAnalyzer
import com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util.QrCodeAnalyzerImpl
import java.util.concurrent.Executors
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

View File

@@ -1,16 +0,0 @@
package com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util
import androidx.camera.core.ImageAnalysis
import androidx.compose.runtime.Stable
/**
* An interface that is used to help scan QR codes.
*/
@Stable
interface QrCodeAnalyzer : ImageAnalysis.Analyzer {
/**
* The method that is called once the code is scanned.
*/
var onQrCodeScanned: (String) -> Unit
}

View File

@@ -1,73 +0,0 @@
package com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util
import androidx.camera.core.ImageProxy
import com.bitwarden.annotation.OmitFromCoverage
import com.google.zxing.BarcodeFormat
import com.google.zxing.BinaryBitmap
import com.google.zxing.DecodeHintType
import com.google.zxing.MultiFormatReader
import com.google.zxing.NotFoundException
import com.google.zxing.PlanarYUVLuminanceSource
import com.google.zxing.common.HybridBinarizer
import java.nio.ByteBuffer
/**
* A class setup to handle image analysis so that we can use the Zxing library
* to scan QR codes and convert them to a string.
*/
@OmitFromCoverage
class QrCodeAnalyzerImpl : QrCodeAnalyzer {
/**
* This will ensure the result is only sent once as multiple images with a valid
* QR code can be sent for analysis.
*/
private var qrCodeRead = false
override lateinit var onQrCodeScanned: (String) -> Unit
override fun analyze(image: ImageProxy) {
if (qrCodeRead) {
return
}
val source = PlanarYUVLuminanceSource(
image.planes[0].buffer.toByteArray(),
image.width,
image.height,
0,
0,
image.width,
image.height,
false,
)
val binaryBitmap = BinaryBitmap(HybridBinarizer(source))
try {
val result = MultiFormatReader()
.apply {
setHints(
mapOf(
DecodeHintType.POSSIBLE_FORMATS to arrayListOf(
BarcodeFormat.QR_CODE,
),
),
)
}
.decode(binaryBitmap)
qrCodeRead = true
onQrCodeScanned(result.text)
} catch (e: NotFoundException) {
return
} finally {
image.close()
}
}
}
/**
* This function helps us prepare the byte buffer to be read.
*/
@OmitFromCoverage
private fun ByteBuffer.toByteArray(): ByteArray =
ByteArray(rewind().remaining()).also { get(it) }

View File

@@ -3,9 +3,9 @@ package com.x8bit.bitwarden.ui.vault.feature.qrcodescan
import androidx.camera.core.ImageProxy
import androidx.compose.ui.test.onNodeWithText
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.ui.platform.feature.qrcodescan.util.FakeQrCodeAnalyzer
import com.bitwarden.ui.util.performCustomAccessibilityAction
import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
import com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util.FakeQrCodeAnalyzer
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify

View File

@@ -1,21 +0,0 @@
package com.x8bit.bitwarden.ui.vault.feature.qrcodescan.util
import androidx.camera.core.ImageProxy
/**
* A helper class that helps test scan outcomes.
*/
class FakeQrCodeAnalyzer : QrCodeAnalyzer {
override lateinit var onQrCodeScanned: (String) -> Unit
/**
* The result of the scan that will be sent to the ViewModel (or `null` to indicate a
* scanning error.
*/
var scanResult: String? = null
override fun analyze(image: ImageProxy) {
scanResult?.let { onQrCodeScanned.invoke(it) }
}
}