Add QR scanning and navigation refactoring

This commit is contained in:
Nikolay Odegov 2025-02-19 12:38:18 +03:00
parent 5c3e7bcdee
commit a667f9984f
12 changed files with 61 additions and 16 deletions

@ -5,4 +5,5 @@ plugins {
alias(libs.plugins.kotlin.compose) apply false alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.android.library) apply false alias(libs.plugins.android.library) apply false
alias(libs.plugins.hilt) apply false alias(libs.plugins.hilt) apply false
id("org.jetbrains.kotlin.plugin.serialization") version "1.7.10" apply false
} }

@ -3,6 +3,7 @@ plugins {
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
id("kotlin-kapt") id("kotlin-kapt")
id("com.google.dagger.hilt.android") id("com.google.dagger.hilt.android")
id("org.jetbrains.kotlin.plugin.serialization")
} }
android { android {
@ -47,4 +48,5 @@ dependencies {
implementation(libs.retrofit) implementation(libs.retrofit)
implementation(libs.converter.gson) implementation(libs.converter.gson)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2")
} }

@ -1,9 +1,20 @@
package com.nto.data.utils package com.nto.data.utils
import kotlinx.serialization.Serializable
sealed class Destinations { sealed class Destinations {
@Serializable
object Login object Login
@Serializable
object Profile object Profile
@Serializable
object Scan object Scan
@Serializable
object Admin object Admin
@Serializable
object Options object Options
} }

@ -4,6 +4,7 @@ plugins {
alias(libs.plugins.kotlin.compose) alias(libs.plugins.kotlin.compose)
id("kotlin-kapt") id("kotlin-kapt")
id("com.google.dagger.hilt.android") id("com.google.dagger.hilt.android")
id("org.jetbrains.kotlin.plugin.serialization")
} }
android { android {
@ -69,8 +70,9 @@ dependencies {
kapt(libs.hilt.compiler) kapt(libs.hilt.compiler)
implementation(libs.hilt) implementation(libs.hilt)
implementation (libs.hilt.navigation) implementation (libs.hilt.navigation)
implementation(libs.navigation) implementation("com.journeyapps:zxing-android-embedded:4.3.0")
implementation("androidx.navigation:navigation-compose:2.8.3")
lintChecks(libs.lint.checks) lintChecks(libs.lint.checks)
lintChecks(libs.lint.checks.compose) lintChecks(libs.lint.checks.compose)
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.2.2")
} }

@ -2,12 +2,12 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application <application
android:name=".di.App"
android:allowBackup="true" android:allowBackup="true"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="true"
android:name=".di.App"
android:theme="@style/Theme.Onomatopoeiafront"> android:theme="@style/Theme.Onomatopoeiafront">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
@ -19,6 +19,11 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity
android:name=".CustomCaptureActivity"
android:stateNotNeeded="true"
android:theme="@style/zxing_CaptureTheme"
android:windowSoftInputMode="stateAlwaysHidden"/>
</application> </application>
</manifest> </manifest>

@ -0,0 +1,5 @@
package com.nto.presentation
import com.journeyapps.barcodescanner.CaptureActivity
class CustomCaptureActivity : CaptureActivity()

@ -0,0 +1 @@
package com.nto.presentation.composable

@ -14,21 +14,21 @@ fun Navigation(navController: NavHostController, modifier: Modifier = Modifier)
NavHost( NavHost(
navController = navController, navController = navController,
modifier = modifier, modifier = modifier,
startDestination = Destinations.Login.toString() startDestination = Destinations.Profile
) { ) {
composable(Destinations.Login.toString()) { composable<Destinations.Login> {
LoginScreen(navController) LoginScreen(navController)
} }
composable(Destinations.Profile.toString()){ composable<Destinations.Profile> {
ProfileScreen(navController) ProfileScreen(navController)
} }
composable(Destinations.Scan.toString()){ composable<Destinations.Scan> {
//TODO //TODO
} }
composable(Destinations.Admin.toString()){ composable<Destinations.Admin> {
//TODO //TODO
} }
composable(Destinations.Options.toString()){ composable<Destinations.Options> {
//TODO //TODO
} }
} }

@ -51,7 +51,7 @@ class LoginViewModel @Inject constructor(private val useCase: LoginUseCase, @App
} }
if (result.successful) { if (result.successful) {
Dispatchers.Main { Dispatchers.Main {
navController.navigate(Destinations.Profile.toString()) navController.navigate(Destinations.Profile)
} }
} }
} }

@ -1,5 +1,8 @@
package com.nto.presentation.screens.profileScreen package com.nto.presentation.screens.profileScreen
import android.content.ContentValues.TAG
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
@ -35,6 +38,9 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanOptions
import com.nto.presentation.CustomCaptureActivity
import com.nto.presentation.R import com.nto.presentation.R
import com.nto.presentation.composable.DecoratedButton import com.nto.presentation.composable.DecoratedButton
import com.nto.presentation.composable.cards.VisitCard import com.nto.presentation.composable.cards.VisitCard
@ -48,7 +54,16 @@ fun ProfileScreen(
viewModel: ProfileViewModel = hiltViewModel<ProfileViewModel>(), viewModel: ProfileViewModel = hiltViewModel<ProfileViewModel>(),
) { ) {
val state = viewModel.state.collectAsState().value val state = viewModel.state.collectAsState().value
val scannerLauncher = rememberLauncherForActivityResult(
contract = ScanContract(),
onResult = { result -> Log.i(TAG, "scanned code: ${result.contents}") }
)
val scanOptions = ScanOptions()
scanOptions.setPrompt("")
scanOptions.setBeepEnabled(false)
scanOptions.setDesiredBarcodeFormats(ScanOptions.QR_CODE)
scanOptions.setOrientationLocked(false)
scanOptions.setCaptureActivity(CustomCaptureActivity::class.java)
Column( Column(
modifier = modifier.background(NTOTheme.colors.primaryBackground) modifier = modifier.background(NTOTheme.colors.primaryBackground)
) { ) {
@ -210,10 +225,11 @@ fun ProfileScreen(
stringResource(R.string.lablel_scan), stringResource(R.string.lablel_scan),
false, false,
modifier = Modifier modifier = Modifier
.padding(10.dp) .padding(bottom = 10.dp)
.fillMaxWidth() .fillMaxWidth()
.height(50.dp) .height(62.dp)
) { ) {
scannerLauncher.launch(scanOptions)
viewModel.scan(navController) viewModel.scan(navController)
} }
} }

@ -35,11 +35,11 @@ class ProfileViewModel @Inject constructor(private val useCase: ProfileUseCase)
} }
fun scan(navController: NavController) { fun scan(navController: NavController) {
navController.navigate(Destinations.Scan.toString()) navController.navigate(Destinations.Scan)
} }
fun option(navController: NavController) { fun option(navController: NavController) {
navController.navigate(Destinations.Options.toString()) navController.navigate(Destinations.Options)
} }
init { init {

@ -0,0 +1,2 @@
package com.nto.presentation.screens.scanResult