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

View File

@ -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
} }

View File

@ -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")
} }

View File

@ -1,9 +1,20 @@
package com.nto.data.utils package com.nto.data.utils
sealed class Destinations{ import kotlinx.serialization.Serializable
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
} }

View File

@ -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")
} }

View File

@ -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>

View File

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

View File

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

View File

@ -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
} }
} }

View File

@ -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)
} }
} }
} }

View File

@ -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)
} }
} }

View File

@ -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 {

View File

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