diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 4e3d9f4..d3c35bb 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -26,6 +26,7 @@ kotlin { implementation("io.coil-kt.coil3:coil-compose:3.4.0") implementation("io.coil-kt.coil3:coil-network-okhttp:3.4.0") implementation("su.reya:nostr-sdk-kmp:0.2.3") + implementation("io.github.kalinjul.easyqrscan:scanner:0.7.0") } commonMain.dependencies { implementation(libs.compose.runtime) diff --git a/composeApp/src/androidMain/AndroidManifest.xml b/composeApp/src/androidMain/AndroidManifest.xml index 26403a7..c58475d 100644 --- a/composeApp/src/androidMain/AndroidManifest.xml +++ b/composeApp/src/androidMain/AndroidManifest.xml @@ -1,6 +1,13 @@ + + + + + + android:name=".MainActivity" + android:exported="true"> - diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ImportScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ImportScreen.kt index 9078a4e..d0a91d0 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ImportScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ImportScreen.kt @@ -52,7 +52,12 @@ fun ImportScreen( snackbarHost = { SnackbarHost(snackbarHostState) }, topBar = { TopAppBar( - title = { Text("Import") }, + title = { + Text( + text = "Import", + style = MaterialTheme.typography.titleMediumEmphasized + ) + }, navigationIcon = { IconButton(onClick = onBack) { Icon( diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt index ca02941..d1f2d4f 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/NewIdentityScreen.kt @@ -70,7 +70,12 @@ fun NewIdentityScreen( snackbarHost = { SnackbarHost(snackbarHostState) }, topBar = { TopAppBar( - title = { Text("Create a new identity") }, + title = { + Text( + text = "Create a new identity", + style = MaterialTheme.typography.titleMediumEmphasized + ) + }, navigationIcon = { IconButton(onClick = onBack) { Icon( diff --git a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt index 041da7e..3aa05ab 100644 --- a/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt +++ b/composeApp/src/androidMain/kotlin/su/reya/coop/screens/ScanScreen.kt @@ -1,25 +1,46 @@ package su.reya.coop.screens +import android.annotation.SuppressLint +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.BlendMode +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp import coop.composeapp.generated.resources.Res import coop.composeapp.generated.resources.ic_arrow_back import org.jetbrains.compose.resources.painterResource +import org.publicvalue.multiplatform.qrcode.CameraPosition +import org.publicvalue.multiplatform.qrcode.CodeType +import org.publicvalue.multiplatform.qrcode.ScannerWithPermissions import su.reya.coop.LocalNavController +import su.reya.coop.LocalSnackbarHostState +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") @Composable fun ScanScreen( onBack: () -> Unit ) { val navController = LocalNavController.current - + val snackbarHostState = LocalSnackbarHostState.current + val onResult: (String) -> Unit = { result -> navController.previousBackStackEntry ?.savedStateHandle @@ -28,9 +49,14 @@ fun ScanScreen( } Scaffold( + snackbarHost = { SnackbarHost(snackbarHostState) }, topBar = { TopAppBar( - title = { Text("Scan QR") }, + title = { + Text( + text = "Scan QR", style = MaterialTheme.typography.titleMediumEmphasized + ) + }, navigationIcon = { IconButton(onClick = onBack) { Icon( @@ -39,11 +65,52 @@ fun ScanScreen( ) } }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = Color.Transparent, + titleContentColor = Color.White, + navigationIconContentColor = Color.White, + ) ) - } + }, ) { innerPadding -> - Box(modifier = Modifier.padding(innerPadding)) { - Text("Scan QR") + Box(modifier = Modifier.fillMaxSize()) { + ScannerWithPermissions( + modifier = Modifier.fillMaxSize(), + onScanned = { + println("Scanned: $it"); + onResult(it) + true + }, + types = listOf(CodeType.QR), + cameraPosition = CameraPosition.BACK, + enableTorch = false + ) + Canvas(modifier = Modifier.fillMaxSize()) { + val scannerSize = 250.dp.toPx() + val left = (size.width - scannerSize) / 2 + val top = (size.height - scannerSize) / 2 + drawRect(color = Color.Black.copy(alpha = 0.6f)) + drawRect( + color = Color.Transparent, + topLeft = Offset(left, top), + size = Size(scannerSize, scannerSize), + blendMode = BlendMode.Clear + ) + } + Box( + modifier = Modifier + .size(250.dp) + .align(Alignment.Center) + .border(2.dp, Color.White, RoundedCornerShape(12.dp)) + ) + Text( + text = "Scan a Nostr address", + style = MaterialTheme.typography.titleSmallEmphasized, + color = Color.White, + modifier = Modifier + .align(Alignment.BottomCenter) + .padding(bottom = 64.dp) + ) } } } \ No newline at end of file