diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index ed52de8..10ef019 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -70,4 +70,10 @@ dependencies {
implementation("androidx.datastore:datastore:1.1.2")
implementation("androidx.compose.runtime:runtime-livedata:1.7.8")
implementation("io.coil-kt:coil-compose:2.0.0-rc01")
+ implementation("com.google.accompanist:accompanist-permissions:0.34.0")
+ implementation("androidx.camera:camera-camera2:1.4.1")
+ implementation("androidx.camera:camera-lifecycle:1.4.1")
+ implementation("androidx.camera:camera-view:1.4.1")
+ implementation("com.journeyapps:zxing-android-embedded:4.3.0")
+ implementation("com.google.zxing:core:3.4.0")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4bffea7..26607c7 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,7 +3,11 @@
xmlns:tools="http://schemas.android.com/tools">
+
+
+
+ android:theme="@style/Theme.Nto_minipigs"
+ tools:ignore="DiscouragedApi">
diff --git a/app/src/main/java/com/example/nto_minipigs/MainActivity.kt b/app/src/main/java/com/example/nto_minipigs/MainActivity.kt
index c6f7e79..96021b1 100644
--- a/app/src/main/java/com/example/nto_minipigs/MainActivity.kt
+++ b/app/src/main/java/com/example/nto_minipigs/MainActivity.kt
@@ -3,6 +3,7 @@ package com.example.nto_minipigs
import android.content.Context
import android.os.Bundle
import android.util.Log
+import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@@ -11,7 +12,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
@@ -33,6 +33,9 @@ import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Serializable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
+import com.example.nto_minipigs.ui.screens.QR.QRResultScreen
+import com.example.nto_minipigs.ui.screens.QR.QRScreen
+import com.example.nto_minipigs.ui.screens.QR.QRViewModel
class MainActivity : ComponentActivity() {
@@ -49,6 +52,7 @@ class MainActivity : ComponentActivity() {
val navController = rememberNavController()
val loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java]
val mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
+ val qrViewModel = ViewModelProvider(this)[QRViewModel::class.java]
val token = dataStore.getToken()
@@ -57,10 +61,11 @@ class MainActivity : ComponentActivity() {
NavHost(
navController = navController,
startDestination = if(token == "") Login else Main
-// startDestination = Login
) {
composable { LoginScreen( onNavigateToMain = { navController.popBackStack(); navController.navigate(route = Main) }, viewModel = loginViewModel, dataStore = dataStore ) }
composable { MainScreen( viewModel = mainViewModel, dataStore = dataStore, navController = navController ) }
+ composable { QRScreen( navController = navController, viewModel = qrViewModel) }
+ composable { QRResultScreen( navController = navController, viewModel = qrViewModel ) }
}
}
}
@@ -91,3 +96,9 @@ object Login
@Serializable
object Main
+
+@Serializable
+object QR
+
+@Serializable
+object QRResult
diff --git a/app/src/main/java/com/example/nto_minipigs/Retrofit/ApiService.kt b/app/src/main/java/com/example/nto_minipigs/Retrofit/ApiService.kt
index 43a3601..4d61d77 100644
--- a/app/src/main/java/com/example/nto_minipigs/Retrofit/ApiService.kt
+++ b/app/src/main/java/com/example/nto_minipigs/Retrofit/ApiService.kt
@@ -2,6 +2,8 @@ package com.example.nto_minipigs.Retrofit
import com.example.nto_minipigs.Retrofit.Models.Auth
import com.example.nto_minipigs.Retrofit.Models.Data
+import com.example.nto_minipigs.Retrofit.Models.Door
+import com.example.nto_minipigs.Retrofit.Models.DoorResponse
import com.example.nto_minipigs.Retrofit.Models.User
import okhttp3.ResponseBody
import retrofit2.Response
@@ -19,8 +21,8 @@ public interface ApiService {
@GET("/api/info")
suspend fun info(@Header("Authorization") token: String): Response
- @PATCH("/api/{LOGIN}/open")
- suspend fun open(@Body data: Data, @Path("LOGIN") login: String): ResponseBody
+ @PATCH("/api/open")
+ suspend fun open(@Body data: Door): Response
@POST("/api/login")
suspend fun login(@Body data: Auth): Response
diff --git a/app/src/main/java/com/example/nto_minipigs/Retrofit/Models/Door.kt b/app/src/main/java/com/example/nto_minipigs/Retrofit/Models/Door.kt
new file mode 100644
index 0000000..cd8f1d4
--- /dev/null
+++ b/app/src/main/java/com/example/nto_minipigs/Retrofit/Models/Door.kt
@@ -0,0 +1,5 @@
+package com.example.nto_minipigs.Retrofit.Models
+
+data class Door(
+ val id: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nto_minipigs/Retrofit/Models/DoorResponse.kt b/app/src/main/java/com/example/nto_minipigs/Retrofit/Models/DoorResponse.kt
new file mode 100644
index 0000000..dee6213
--- /dev/null
+++ b/app/src/main/java/com/example/nto_minipigs/Retrofit/Models/DoorResponse.kt
@@ -0,0 +1,5 @@
+package com.example.nto_minipigs.Retrofit.Models
+
+data class DoorResponse(
+ val name: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainScreen.kt b/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainScreen.kt
index 1c7f7f4..a904c76 100644
--- a/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainScreen.kt
+++ b/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainScreen.kt
@@ -58,6 +58,7 @@ import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import coil.compose.rememberAsyncImagePainter
import com.example.nto_minipigs.Login
+import com.example.nto_minipigs.QR
import com.example.nto_minipigs.UserData
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
@@ -193,7 +194,7 @@ fun MainScreen( viewModel: MainViewModel, dataStore: UserData, navController: Na
}
}
Button(
- onClick = { },
+ onClick = {navController.navigate(QR) },
shape = CircleShape,
modifier = Modifier
.align(Alignment.BottomEnd)
diff --git a/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainViewModel.kt b/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainViewModel.kt
index 43ef478..7a4b7ac 100644
--- a/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainViewModel.kt
+++ b/app/src/main/java/com/example/nto_minipigs/ui/screens/Main/MainViewModel.kt
@@ -36,10 +36,6 @@ class MainViewModel: ViewModel() {
}
}
}
-
- fun Logout() {
-
- }
}
sealed class NetworkResponse {
diff --git a/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRResultScreen.kt b/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRResultScreen.kt
new file mode 100644
index 0000000..1d6b305
--- /dev/null
+++ b/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRResultScreen.kt
@@ -0,0 +1,70 @@
+package com.example.nto_minipigs.ui.screens.QR
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.Cancel
+import androidx.compose.material.icons.outlined.Check
+import androidx.compose.material.icons.outlined.CheckCircle
+import androidx.compose.material.icons.outlined.Close
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
+import androidx.navigation.NavController
+import com.example.nto_minipigs.QRResult
+import com.example.nto_minipigs.ui.screens.Main.NetworkResponse
+import com.example.nto_minipigs.ui.screens.QR.QRViewModel
+
+@Composable
+fun QRResultScreen(navController: NavController, viewModel: QRViewModel) {
+ val data = viewModel.data.observeAsState()
+ Surface {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ when(val result = data.value){
+ is com.example.nto_minipigs.ui.screens.QR.NetworkResponse.Error -> {
+ Icon(
+ Icons.Outlined.Cancel,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.error,
+ modifier = Modifier
+ .size(100.dp)
+ )
+ }
+ com.example.nto_minipigs.ui.screens.QR.NetworkResponse.Loading -> {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.Center,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ CircularProgressIndicator()
+ }
+ }
+ is com.example.nto_minipigs.ui.screens.QR.NetworkResponse.Success -> {
+ Icon(
+ Icons.Outlined.CheckCircle,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.primary,
+ modifier = Modifier
+ .size(100.dp)
+ )
+ }
+
+ null -> {}
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRScreen.kt b/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRScreen.kt
new file mode 100644
index 0000000..5119bbb
--- /dev/null
+++ b/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRScreen.kt
@@ -0,0 +1,54 @@
+package com.example.nto_minipigs.ui.screens.QR
+
+import android.app.Activity
+import android.util.Log
+import androidx.activity.result.ActivityResultLauncher
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import com.journeyapps.barcodescanner.CaptureManager
+import com.journeyapps.barcodescanner.CompoundBarcodeView
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.navigation.NavController
+import com.example.nto_minipigs.QRResult
+
+@Composable
+fun QRScreen(navController: NavController, viewModel: QRViewModel) {
+ var scanFlag by remember {
+ mutableStateOf(false)
+ }
+
+ AndroidView(
+ factory = { context ->
+ CompoundBarcodeView(context).apply {
+ val capture = CaptureManager(context as Activity, this)
+ capture.initializeFromIntent(context.intent, null)
+ this.setStatusText("")
+ capture.decode()
+ this.decodeContinuous { result ->
+ if (scanFlag) {
+ return@decodeContinuous
+ }
+ println("scanFlag true")
+ scanFlag = true
+ result.text?.let { barCodeOrQr ->
+ Log.d("penis", barCodeOrQr)
+ scanFlag = true
+ this.pause()
+ viewModel.Fetch(barCodeOrQr)
+ navController.navigate(QRResult)
+ }
+ //If you don't put this scanFlag = false, it will never work again.
+ //you can put a delay over 2 seconds and then scanFlag = false to prevent multiple scanning
+ }
+ this.resume()
+ }
+ },
+ modifier = Modifier
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRViewModel.kt b/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRViewModel.kt
new file mode 100644
index 0000000..7078df3
--- /dev/null
+++ b/app/src/main/java/com/example/nto_minipigs/ui/screens/QR/QRViewModel.kt
@@ -0,0 +1,46 @@
+package com.example.nto_minipigs.ui.screens.QR
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.nto_minipigs.Retrofit.Models.Data
+import com.example.nto_minipigs.Retrofit.Models.Door
+import com.example.nto_minipigs.Retrofit.Models.DoorResponse
+import com.example.nto_minipigs.Retrofit.Models.User
+import kotlinx.coroutines.launch
+
+class QRViewModel: ViewModel() {
+ private val serviceApi = RetrofitClient.apiService
+
+ private val _data = MutableLiveData>()
+ val data : LiveData> = _data
+
+ fun Fetch(id: String) {
+ _data.value = NetworkResponse.Loading
+
+ viewModelScope.launch {
+ if(id != null) {
+ try {
+ val request = Door(id)
+ val response = serviceApi.open(request)
+ if(response.isSuccessful) {
+ response.body()?.let {
+ _data.value = NetworkResponse.Success(it)
+ }
+ } else {
+ _data.value = NetworkResponse.Error(response.message())
+ }
+ } catch(e: Exception) {
+ _data.value = NetworkResponse.Error(e.toString())
+ }
+ }
+ }
+ }
+}
+
+sealed class NetworkResponse {
+ data class Success(val data: T) : NetworkResponse()
+ data class Error(val message: String) : NetworkResponse()
+ object Loading : NetworkResponse()
+}
\ No newline at end of file