Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPENSOURCE-73 :: Adding a KMP QRCode library #87

Draft
wants to merge 5 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ dependencies {

implementation libs.biometric

implementation libs.zxing.android.embedded

implementation(libs.qr.chaintech)
implementation libs.room.runtime
implementation libs.room.ktx
ksp libs.room.compiler
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
Expand All @@ -16,6 +17,9 @@
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="false" />

<!-- Legacy permissions on older devices -->
<uses-permission
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import android.util.AttributeSet
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.AbstractComposeView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.algorand.common.qr.presentation.view.QrScanner
import com.algorand.common.qr.presentation.view.PeraQrScanner
import com.algorand.common.qr.presentation.view.QrScannerViewEvent
import kotlinx.coroutines.flow.MutableStateFlow

Expand All @@ -41,7 +41,7 @@ class QrScannerView(context: Context, attrs: AttributeSet? = null) : AbstractCom

@Composable
override fun Content() {
QrScanner(
PeraQrScanner(
viewEvent = qrScannerViewEventFlow.collectAsStateWithLifecycle(),
onQrScanned = onQrScanned
)
Expand Down
8 changes: 5 additions & 3 deletions app/src/main/java/com/algorand/android/utils/QrUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import com.algorand.android.BuildConfig
import com.algorand.android.R
import com.algorand.android.models.DecodedQrCode
import com.algorand.android.utils.walletconnect.WALLET_CONNECT_URL_PREFIX
import com.google.zxing.BarcodeFormat
import com.journeyapps.barcodescanner.BarcodeEncoder
import java.math.BigInteger

private const val MNEMONIC_KEY = "mnemonic"
Expand All @@ -39,7 +37,11 @@ private const val QUERY_INDEX = 1
fun getQrCodeBitmap(size: Int, qrContent: String): Bitmap? {
return try {
// The QR code has self padding about 28dp.
BarcodeEncoder().encodeBitmap(qrContent, BarcodeFormat.QR_CODE, size, size)
// TODO still need to generate a bitmap of a qrcode or change the current UI to be compose ready
// val qrPainter = QrPainter(qrContent, QrKitOptions())
// BitmapPainter(qrPainter.)
// BarcodeEncoder().encodeBitmap(qrContent, BarcodeFormat.QR_CODE, size, size)
null
} catch (e: Exception) {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fun CoreActionsBottomSheet(
ModalBottomSheet(
onDismissRequest = { isVisible.value = false },
sheetState = sheetState,
windowInsets = WindowInsets(bottom = paddingValues.calculateBottomPadding()),
contentWindowInsets = { WindowInsets(bottom = paddingValues.calculateBottomPadding()) },
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.algorand.common.qr.presentation.view.QrScanner
import com.algorand.common.qr.presentation.view.PeraQrScanner
import com.algorand.common.qr.presentation.view.QrScannerViewEvent
import com.algorand.common.ui.theme.PeraTheme
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -66,7 +66,7 @@ fun QrScannerScreen() {
)
},
) {
QrScanner(
PeraQrScanner(
viewEvent = cameraState
) {
scannedQr = it
Expand Down
6 changes: 4 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,15 @@ navigation = "2.8.4"
navigation-compose = "2.8.0-alpha10"
okhttp = "4.12.0"
paging = "3.3.4"
qrKit = "3.0.5"
retrofit = "2.11.0"
review = "2.0.2"
room = "2.7.0-alpha11"
sqlite = "1.0.0"
runner = "1.6.2"
safeargs = "2.8.4"
tink = "1.14.0"
walletConnectBom = "1.34.1"
zxing = "4.3.0"

[libraries]
agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
Expand Down Expand Up @@ -167,8 +168,10 @@ navigation-safe-args-gradle-plugin = { module = "androidx.navigation:navigation-
navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" }
paging-runtime-ktx = { module = "androidx.paging:paging-runtime-ktx", version.ref = "paging" }
perf-plugin = { module = "com.google.firebase:perf-plugin", version.ref = "firebasePerformance" }
qr-chaintech = { module = "network.chaintech:qr-kit", version.ref = "qrKit" }
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
review-ktx = { module = "com.google.android.play:review-ktx", version.ref = "review" }
sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
room-gradle-plugin = { module = "androidx.room:room-gradle-plugin", version.ref = "room" }
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
Expand All @@ -180,7 +183,6 @@ tink-android = { module = "com.google.crypto.tink:tink-android", version.ref = "
walletconnect = { module = "com.walletconnect:android-bom", version.ref = "walletConnectBom" }
walletconnect-android-core = { module = "com.walletconnect:android-core" }
web3wallet = { module = "com.walletconnect:web3wallet" }
zxing-android-embedded = { module = "com.journeyapps:zxing-android-embedded", version.ref = "zxing" }


[bundles]
Expand Down
2 changes: 2 additions & 0 deletions iosTestApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
DEVELOPMENT_TEAM = 29ZZ2VDM4M;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
Expand Down Expand Up @@ -325,6 +326,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
DEVELOPMENT_TEAM = 29ZZ2VDM4M;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = iosApp/Info.plist;
Expand Down
2 changes: 2 additions & 0 deletions iosTestApp/iosApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key><string>Pera Wallet camera description.</string>
<key>NSPhotoLibraryUsageDescription</key><string>Pera Wallet photos description.</string>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
</dict>
Expand Down
3 changes: 2 additions & 1 deletion wallet-sdk/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ kotlin {
implementation(libs.ktor.client.okhttp)
implementation(compose.uiTooling)
implementation(compose.components.uiToolingPreview)
implementation(libs.zxing.android.embedded)
implementation(project.dependencies.platform(libs.firebase.bom))
implementation(libs.firebase.analytics)
implementation(libs.firebase.config)
Expand All @@ -93,6 +92,8 @@ kotlin {
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.client.core)
implementation(libs.room.runtime)
implementation(libs.sqlite.bundled)
implementation(libs.qr.chaintech)
}
iosMain.dependencies {
implementation(libs.ktor.client.darwin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package com.algorand.common.account.local.data.database
import android.content.Context
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import kotlinx.coroutines.Dispatchers

internal fun getAccountDatabase(ctx: Context): AccountDatabase {
Expand All @@ -28,4 +29,5 @@ internal fun getDatabaseBuilder(ctx: Context): RoomDatabase.Builder<AccountDatab
context = appContext,
name = dbFile.absolutePath
).setQueryCoroutineContext(Dispatchers.IO)
.setDriver(BundledSQLiteDriver())
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@

package com.algorand.common.qr.presentation.view

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
Expand All @@ -24,6 +21,7 @@ import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Paint
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
Expand All @@ -36,12 +34,7 @@ import com.algorand.common.qr.presentation.view.CornerStrokePosition.TopRight
private val TRANSPARENT_AREA_SIZE = 250.dp

@Composable
internal fun CameraOverlay(
modifier: Modifier = Modifier,
) {
Canvas(
modifier = modifier.fillMaxSize()
) {
fun cameraOverlay(): ContentDrawScope.() -> Unit = {
drawIntoCanvas { it.saveLayer(Rect(Offset.Zero, size), Paint()) }
drawRect(
color = Color.Black.copy(alpha = 0.64f),
Expand All @@ -58,12 +51,10 @@ internal fun CameraOverlay(
size = Size(TRANSPARENT_AREA_SIZE.toPx(), TRANSPARENT_AREA_SIZE.toPx()),
topLeft = transparentAreaOffset
)

drawCornerStroke(transparentAreaOffset, TopLeft)
drawCornerStroke(transparentAreaOffset, TopRight)
drawCornerStroke(transparentAreaOffset, BottomLeft)
drawCornerStroke(transparentAreaOffset, BottomRight)
}
}

private fun DrawScope.drawCornerStroke(offset: Offset, position: CornerStrokePosition) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,34 @@

package com.algorand.common.qr.presentation.view

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import kotlinx.serialization.Serializable

@Serializable
data object QrScannerNavigation
import qrscanner.CameraLens
import qrscanner.QrScanner

sealed interface QrScannerViewEvent {
data object PauseCamera : QrScannerViewEvent
data object ResumeCamera : QrScannerViewEvent
}

@Composable
fun QrScanner(
fun PeraQrScanner(
viewEvent: State<QrScannerViewEvent>,
modifier: Modifier = Modifier,
onQrScanned: (String) -> Unit
) {
Box(modifier = modifier.fillMaxSize()) {
BarcodeScanner(viewEvent = viewEvent) { result ->
result.getDataOrNull()?.let(onQrScanned)
}
CameraOverlay()
}
QrScanner(
modifier = modifier.fillMaxSize(),
flashlightOn = false,
cameraLens = CameraLens.Back,
openImagePicker = false,
onCompletion = onQrScanned,
imagePickerHandler = { },
onFailure = { },
customOverlay = cameraOverlay()
)
}


Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ package com.algorand.common.account.local.data.database

import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import kotlinx.cinterop.ExperimentalForeignApi
import platform.Foundation.NSDocumentDirectory
import platform.Foundation.NSFileManager
Expand All @@ -27,7 +28,7 @@ internal fun createAccountDatabase(): RoomDatabase.Builder<AccountDatabase> {
val dbFilePath = documentDirectory() + "/${AccountDatabase.DATABASE_NAME}.db"
return Room.databaseBuilder<AccountDatabase>(
name = dbFilePath,
)
).setDriver(BundledSQLiteDriver())
}

@OptIn(ExperimentalForeignApi::class)
Expand Down
Loading
Loading