base functionality implemented for test api
This commit is contained in:
parent
39a60043d2
commit
02385d86d5
@ -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")
|
||||
}
|
@ -3,7 +3,11 @@
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-feature android:name="android.hardware.camera"/>
|
||||
<uses-feature android:name="android.hardware.camera.autofocus"/>
|
||||
<uses-permission android:name="android.permission.CAMERA"/>
|
||||
<application
|
||||
android:hardwareAccelerated="true"
|
||||
android:allowBackup="true"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
@ -15,10 +19,13 @@
|
||||
android:theme="@style/Theme.Nto_minipigs"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:screenOrientation="portrait"
|
||||
tools:replace="screenOrientation"
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.Nto_minipigs">
|
||||
android:theme="@style/Theme.Nto_minipigs"
|
||||
tools:ignore="DiscouragedApi">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
@ -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<Login> { LoginScreen( onNavigateToMain = { navController.popBackStack(); navController.navigate(route = Main) }, viewModel = loginViewModel, dataStore = dataStore ) }
|
||||
composable<Main> { MainScreen( viewModel = mainViewModel, dataStore = dataStore, navController = navController ) }
|
||||
composable<QR> { QRScreen( navController = navController, viewModel = qrViewModel) }
|
||||
composable<QRResult> { QRResultScreen( navController = navController, viewModel = qrViewModel ) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -91,3 +96,9 @@ object Login
|
||||
|
||||
@Serializable
|
||||
object Main
|
||||
|
||||
@Serializable
|
||||
object QR
|
||||
|
||||
@Serializable
|
||||
object QRResult
|
||||
|
@ -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<User>
|
||||
|
||||
@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<DoorResponse>
|
||||
|
||||
@POST("/api/login")
|
||||
suspend fun login(@Body data: Auth): Response<Data>
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.example.nto_minipigs.Retrofit.Models
|
||||
|
||||
data class Door(
|
||||
val id: String
|
||||
)
|
@ -0,0 +1,5 @@
|
||||
package com.example.nto_minipigs.Retrofit.Models
|
||||
|
||||
data class DoorResponse(
|
||||
val name: String
|
||||
)
|
@ -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)
|
||||
|
@ -36,10 +36,6 @@ class MainViewModel: ViewModel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Logout() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sealed class NetworkResponse<out T> {
|
||||
|
@ -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 -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
)
|
||||
}
|
@ -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<NetworkResponse<DoorResponse>>()
|
||||
val data : LiveData<NetworkResponse<DoorResponse>> = _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<out T> {
|
||||
data class Success<out T>(val data: T) : NetworkResponse<T>()
|
||||
data class Error(val message: String) : NetworkResponse<Nothing>()
|
||||
object Loading : NetworkResponse<Nothing>()
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user