wifi icon + qrcode stamps

This commit is contained in:
Hadrian Burkhardt
2026-02-26 05:29:45 +01:00
parent 5d83ff4a6d
commit 229244d878
5 changed files with 52 additions and 9 deletions
@@ -5,6 +5,7 @@ import android.os.SystemClock
import androidx.camera.core.ImageAnalysis import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy import androidx.camera.core.ImageProxy
import com.clean.scanner.domain.ScanResult import com.clean.scanner.domain.ScanResult
import com.clean.scanner.util.readablePayload
import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.BarcodeScannerOptions import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.barcode.common.Barcode
@@ -116,7 +117,7 @@ class MlKitBarcodeAnalyzer(
scanner.process(image) scanner.process(image)
.addOnSuccessListener { barcodes -> .addOnSuccessListener { barcodes ->
val readable = barcodes.firstOrNull { !it.rawValue.isNullOrBlank() } val readable = barcodes.firstOrNull { it.readablePayload() != null }
val boxes = barcodes.mapNotNull { barcode -> val boxes = barcodes.mapNotNull { barcode ->
val bounds = barcode.boundingBox ?: return@mapNotNull null val bounds = barcode.boundingBox ?: return@mapNotNull null
val normalized = normalizeBoundingBox( val normalized = normalizeBoundingBox(
@@ -164,7 +165,7 @@ class MlKitBarcodeAnalyzer(
} }
onDetected( onDetected(
ScanResult( ScanResult(
content = readable.rawValue.orEmpty(), content = readable.readablePayload().orEmpty(),
type = readable.valueType.toHumanType() type = readable.valueType.toHumanType()
), ),
gatedReadableBox, gatedReadableBox,
@@ -54,6 +54,7 @@ import com.clean.scanner.R
import com.clean.scanner.data.scanner.DetectionBox import com.clean.scanner.data.scanner.DetectionBox
import com.clean.scanner.data.scanner.DetectionPoint import com.clean.scanner.data.scanner.DetectionPoint
import com.clean.scanner.domain.ScanResult import com.clean.scanner.domain.ScanResult
import com.clean.scanner.util.readablePayload
import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.BarcodeScanner import com.google.mlkit.vision.barcode.BarcodeScanner
import com.google.mlkit.vision.barcode.BarcodeScannerOptions import com.google.mlkit.vision.barcode.BarcodeScannerOptions
@@ -174,7 +175,7 @@ internal fun GalleryScanPreviewDialog(
} }
val live = barcodes.mapNotNull { barcode -> val live = barcodes.mapNotNull { barcode ->
val raw = barcode.rawValue?.takeIf { it.isNotBlank() } ?: return@mapNotNull null val raw = barcode.readablePayload() ?: return@mapNotNull null
val normalizedBox = barcode.boundingBox?.let { bounds -> val normalizedBox = barcode.boundingBox?.let { bounds ->
val leftN = ((bounds.left + cropLeft) / imgW).coerceIn(0f, 1f) val leftN = ((bounds.left + cropLeft) / imgW).coerceIn(0f, 1f)
val topN = ((bounds.top + cropTop) / imgH).coerceIn(0f, 1f) val topN = ((bounds.top + cropTop) / imgH).coerceIn(0f, 1f)
@@ -8,8 +8,11 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Wifi
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -57,10 +60,27 @@ internal fun ResultVisualCard(
modifier = Modifier.padding(14.dp), modifier = Modifier.padding(14.dp),
verticalArrangement = Arrangement.spacedBy(8.dp) verticalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
Text( if (result.type == "WiFi") {
text = result.type, Row(
style = MaterialTheme.typography.titleMedium horizontalArrangement = Arrangement.spacedBy(8.dp),
) verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Default.Wifi,
contentDescription = null,
tint = Color(0xFF1D4ED8)
)
Text(
text = "Wi-Fi",
style = MaterialTheme.typography.titleMedium
)
}
} else {
Text(
text = result.type,
style = MaterialTheme.typography.titleMedium
)
}
if (fields.isEmpty()) { if (fields.isEmpty()) {
Text( Text(
text = result.content, text = result.content,
@@ -80,6 +80,7 @@ import com.clean.scanner.util.ClipboardUtil
import com.clean.scanner.util.Intents import com.clean.scanner.util.Intents
import com.clean.scanner.util.ScanContentParsers import com.clean.scanner.util.ScanContentParsers
import com.clean.scanner.util.UrlRiskScorer import com.clean.scanner.util.UrlRiskScorer
import com.clean.scanner.util.readablePayload
import com.google.mlkit.vision.barcode.BarcodeScanning import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.BarcodeScannerOptions import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.common.Barcode import com.google.mlkit.vision.barcode.common.Barcode
@@ -172,7 +173,7 @@ fun ScannerScreen(
imageScanner.process(image) imageScanner.process(image)
.addOnSuccessListener { barcodes -> .addOnSuccessListener { barcodes ->
val candidates = barcodes.mapNotNull { barcode -> val candidates = barcodes.mapNotNull { barcode ->
val raw = barcode.rawValue?.takeIf { it.isNotBlank() } ?: return@mapNotNull null val raw = barcode.readablePayload() ?: return@mapNotNull null
val normalizedBox = barcode.boundingBox?.let { bounds -> val normalizedBox = barcode.boundingBox?.let { bounds ->
val corners = barcode.cornerPoints?.map { p -> val corners = barcode.cornerPoints?.map { p ->
DetectionPoint( DetectionPoint(
@@ -469,7 +470,7 @@ fun ScannerScreen(
.padding(16.dp), .padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp) verticalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
if (parsedContact == null) { if (parsedContact == null && lastResult.type != "WiFi") {
Text(text = "${stringResource(R.string.content_type)}: ${lastResult.type}") Text(text = "${stringResource(R.string.content_type)}: ${lastResult.type}")
} }
ResultVisualCard(result = lastResult) ResultVisualCard(result = lastResult)
@@ -0,0 +1,20 @@
package com.clean.scanner.util
import com.google.mlkit.vision.barcode.common.Barcode
fun Barcode.readablePayload(): String? {
rawValue?.trim()?.takeIf { it.isNotBlank() }?.let { return it }
displayValue?.trim()?.takeIf { it.isNotBlank() }?.let { return it }
val bytes = rawBytes?.takeIf { it.isNotEmpty() } ?: return null
val utf8 = bytes.toString(Charsets.UTF_8).trim()
if (utf8.isLikelyHumanReadable()) return utf8
return bytes.joinToString(separator = "") { byte -> "%02X".format(byte) }
}
private fun String.isLikelyHumanReadable(): Boolean {
if (isBlank()) return false
val controlChars = count { it.isISOControl() && it != '\n' && it != '\r' && it != '\t' }
return controlChars == 0
}