many done
This commit is contained in:
parent
d2db976f34
commit
8c7ed46049
3
.idea/.gitignore
vendored
3
.idea/.gitignore
vendored
@ -1,3 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
@ -1 +0,0 @@
|
||||
Coffee Preorder
|
@ -5,7 +5,7 @@
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="jbr-17" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.20" />
|
||||
<option name="version" value="1.9.10" />
|
||||
</component>
|
||||
</project>
|
@ -1,3 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -2,6 +2,7 @@ plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("com.google.devtools.ksp")
|
||||
id("org.jetbrains.kotlin.plugin.serialization")
|
||||
}
|
||||
|
||||
android {
|
||||
@ -41,7 +42,7 @@ android {
|
||||
compose = true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = "1.5.5"
|
||||
kotlinCompilerExtensionVersion = "1.5.3"
|
||||
}
|
||||
packaging {
|
||||
resources {
|
||||
@ -56,12 +57,9 @@ kotlin {
|
||||
|
||||
dependencies {
|
||||
// Retrofit
|
||||
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
|
||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||
implementation("io.coil-kt:coil-compose:2.5.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
|
||||
implementation("androidx.paging:paging-compose:3.2.1")
|
||||
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2")
|
||||
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")
|
||||
|
||||
@ -72,30 +70,30 @@ dependencies {
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
|
||||
|
||||
// UI
|
||||
implementation("androidx.activity:activity-compose:1.8.1")
|
||||
implementation("androidx.activity:activity-compose:1.8.2")
|
||||
implementation(platform("androidx.compose:compose-bom:2023.10.01"))
|
||||
implementation("androidx.navigation:navigation-compose:2.7.5")
|
||||
implementation("androidx.compose.ui:ui:1.6.0-beta02")
|
||||
implementation("androidx.compose.ui:ui-graphics:1.6.0-beta02")
|
||||
implementation("androidx.compose.ui:ui-tooling-preview:1.6.0-beta02")
|
||||
implementation("androidx.navigation:navigation-compose:2.7.6")
|
||||
implementation("androidx.compose.ui:ui:1.6.0-beta03")
|
||||
implementation("androidx.compose.ui:ui-graphics:1.6.0-beta03")
|
||||
implementation("androidx.compose.ui:ui-tooling-preview:1.6.0-beta03")
|
||||
implementation("androidx.compose.material3:material3:1.1.2")
|
||||
implementation("androidx.compose.material:material:1.5.4")
|
||||
implementation("androidx.paging:paging-compose:3.2.1")
|
||||
implementation("eu.bambooapps:compose-material3-pullrefresh:1.0.1")
|
||||
|
||||
// Room
|
||||
val roomVersion = "2.6.1"
|
||||
implementation("androidx.room:room-runtime:$roomVersion")
|
||||
annotationProcessor("androidx.room:room-compiler:$roomVersion")
|
||||
ksp("androidx.room:room-compiler:$roomVersion")
|
||||
implementation("androidx.room:room-ktx:$roomVersion")
|
||||
implementation("androidx.room:room-paging:$roomVersion")
|
||||
implementation("androidx.room:room-runtime:2.6.1")
|
||||
annotationProcessor("androidx.room:room-compiler:2.6.1")
|
||||
ksp("androidx.room:room-compiler:2.6.1")
|
||||
implementation("androidx.room:room-ktx:2.6.1")
|
||||
implementation("androidx.room:room-paging:2.6.1")
|
||||
|
||||
// Tests
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.5")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
|
||||
androidTestImplementation(platform("androidx.compose:compose-bom:2023.10.01"))
|
||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.6.0-beta02")
|
||||
debugImplementation("androidx.compose.ui:ui-tooling:1.6.0-beta02")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.0-beta02")
|
||||
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.6.0-beta03")
|
||||
debugImplementation("androidx.compose.ui:ui-tooling:1.6.0-beta03")
|
||||
debugImplementation("androidx.compose.ui:ui-test-manifest:1.6.0-beta03")
|
||||
}
|
63
app/proguard-rules.pro
vendored
63
app/proguard-rules.pro
vendored
@ -1,21 +1,48 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
|
||||
# EnclosingMethod is required to use InnerClasses.
|
||||
-keepattributes Signature, InnerClasses, EnclosingMethod
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
# Retrofit does reflection on method and parameter annotations.
|
||||
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
# Keep annotation default values (e.g., retrofit2.http.Field.encoded).
|
||||
-keepattributes AnnotationDefault
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
# Retain service method parameters when optimizing.
|
||||
-keepclassmembers,allowshrinking,allowobfuscation interface * {
|
||||
@retrofit2.http.* <methods>;
|
||||
}
|
||||
|
||||
# Ignore annotation used for build tooling.
|
||||
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
|
||||
|
||||
# Ignore JSR 305 annotations for embedding nullability information.
|
||||
-dontwarn javax.annotation.**
|
||||
|
||||
# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
|
||||
-dontwarn kotlin.Unit
|
||||
|
||||
# Top-level functions that can only be used by Kotlin.
|
||||
-dontwarn retrofit2.KotlinExtensions
|
||||
-dontwarn retrofit2.KotlinExtensions$*
|
||||
|
||||
# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
|
||||
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
|
||||
-if interface * { @retrofit2.http.* <methods>; }
|
||||
-keep,allowobfuscation interface <1>
|
||||
|
||||
# Keep inherited services.
|
||||
-if interface * { @retrofit2.http.* <methods>; }
|
||||
-keep,allowobfuscation interface * extends <1>
|
||||
|
||||
# With R8 full mode generic signatures are stripped for classes that are not
|
||||
# kept. Suspend functions are wrapped in continuations where the type argument
|
||||
# is used.
|
||||
-keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation
|
||||
|
||||
# R8 full mode strips generic signatures from return types if not kept.
|
||||
-if interface * { @retrofit2.http.* public *** *(...); }
|
||||
-keep,allowoptimization,allowshrinking,allowobfuscation class <3>
|
||||
|
||||
# With R8 full mode generic signatures are stripped for classes that are not kept.
|
||||
-keep,allowobfuscation,allowshrinking class retrofit2.Response
|
@ -8,7 +8,7 @@
|
||||
<uses-permission android:name="com.google.android.gms.persmission.AD_ID" />
|
||||
<application
|
||||
android:name=".CoffeeApplication"
|
||||
android:allowBackup="false"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
@ -16,7 +16,8 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.CoffeePreorder"
|
||||
tools:targetApi="31">
|
||||
tools:targetApi="31"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
<activity
|
||||
android:name=".MainComposeActivity"
|
||||
android:exported="true"
|
||||
|
@ -3,6 +3,7 @@ package com.zyzf.coffeepreorder
|
||||
import android.app.Application
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.AppDataContainer
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
|
||||
class CoffeeApplication : Application() {
|
||||
|
@ -17,68 +17,68 @@ import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface MyServerService {
|
||||
@GET("user")
|
||||
@GET("user/")
|
||||
suspend fun getUsers(
|
||||
@Query("pageNo") page: Int,
|
||||
@Query("pageSize") limit: Int,
|
||||
): List<UserRemote>
|
||||
|
||||
@GET("user/{id}")
|
||||
@GET("user/{id}/")
|
||||
suspend fun getUser(
|
||||
@Path("id") id: Int,
|
||||
): UserRemote
|
||||
|
||||
@GET("user")
|
||||
suspend fun tryLogin(
|
||||
@Body login: String,
|
||||
@Body password: String,
|
||||
): UserRemote
|
||||
@GET("user/tryLogin")
|
||||
fun tryLogin(
|
||||
@Query("login") login: String,
|
||||
@Query("password") password: String,
|
||||
): UserRemote?
|
||||
|
||||
@POST("user")
|
||||
suspend fun createUser(
|
||||
@POST("user/")
|
||||
fun createUser(
|
||||
@Body user: UserRemote,
|
||||
): UserRemote
|
||||
|
||||
@PUT("user/{id}")
|
||||
suspend fun updateUser(
|
||||
@PUT("user/{id}/")
|
||||
fun updateUser(
|
||||
@Path("id") id: Int,
|
||||
@Body user: UserRemote,
|
||||
): UserRemote
|
||||
|
||||
@DELETE("user/{id}")
|
||||
@DELETE("user/{id}/")
|
||||
suspend fun deleteUser(
|
||||
@Path("id") id: Int,
|
||||
): UserRemote
|
||||
|
||||
@GET("coffee")
|
||||
@GET("coffee/")
|
||||
suspend fun getCoffees(
|
||||
@Query("pageNo") page: Int,
|
||||
@Query("pageSize") limit: Int,
|
||||
): List<CoffeeRemote>
|
||||
|
||||
@GET("coffee/{id}")
|
||||
@GET("coffee/{id}/")
|
||||
suspend fun getCoffee(
|
||||
@Path("id") id: Int,
|
||||
): CoffeeRemote
|
||||
|
||||
@POST("coffee")
|
||||
suspend fun createCoffee(
|
||||
@POST("coffee/")
|
||||
fun createCoffee(
|
||||
@Body coffee: CoffeeRemote,
|
||||
): CoffeeRemote
|
||||
|
||||
@PUT("coffee/{id}")
|
||||
suspend fun updateCoffee(
|
||||
@PUT("coffee/{id}/")
|
||||
fun updateCoffee(
|
||||
@Path("id") id: Int,
|
||||
@Body coffee: CoffeeRemote,
|
||||
): CoffeeRemote
|
||||
|
||||
@DELETE("coffee/{id}")
|
||||
@DELETE("coffee/{id}/")
|
||||
suspend fun deleteCoffee(
|
||||
@Path("id") id: Int,
|
||||
): CoffeeRemote
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = "http://192.168.42.94:8080/api/"
|
||||
private const val BASE_URL = "http://192.168.0.100:8080/api/"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: MyServerService? = null
|
||||
|
@ -56,7 +56,7 @@ class CoffeeRemoteMediator(
|
||||
val endOfPaginationReached = coffees.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.Coffee)
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.COFFEE)
|
||||
dbCoffeeRepository.clearCoffees()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
@ -64,15 +64,13 @@ class CoffeeRemoteMediator(
|
||||
val keys = coffees.map {
|
||||
RemoteKeys(
|
||||
entityId = it.uid,
|
||||
type = RemoteKeyType.Coffee,
|
||||
type = RemoteKeyType.COFFEE,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
for (coffee in coffees) {
|
||||
dbCoffeeRepository.insert(coffee.name, coffee.cost, coffee.ingredients)
|
||||
}
|
||||
dbCoffeeRepository.insertCoffees(coffees)
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
} catch (exception: IOException) {
|
||||
@ -85,14 +83,14 @@ class CoffeeRemoteMediator(
|
||||
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Coffee>): RemoteKeys? {
|
||||
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
|
||||
?.let { coffee ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffee.uid, RemoteKeyType.Coffee)
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffee.uid, RemoteKeyType.COFFEE)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Coffee>): RemoteKeys? {
|
||||
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
|
||||
?.let { coffee ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffee.uid, RemoteKeyType.Coffee)
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffee.uid, RemoteKeyType.COFFEE)
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +99,7 @@ class CoffeeRemoteMediator(
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.uid?.let { coffeeUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffeeUid, RemoteKeyType.Coffee)
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffeeUid, RemoteKeyType.COFFEE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class RestCoffeeRepository(
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : CoffeeRepository {
|
||||
override fun getAll(): Flow<PagingData<Coffee>> {
|
||||
override fun getAllCoffees(): Flow<PagingData<Coffee>> {
|
||||
Log.d(RestCoffeeRepository::class.simpleName, "Get coffees")
|
||||
|
||||
val pagingSourceFactory = { dbCoffeeRepository.getAllCoffeesPagingSource() }
|
||||
@ -43,15 +43,15 @@ class RestCoffeeRepository(
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun getByUid(uid: Int): Coffee? =
|
||||
override suspend fun getByUid(uid: Int): Coffee =
|
||||
service.getCoffee(uid).toCoffee()
|
||||
|
||||
override suspend fun insert(name: String, cost: Double, ingredients: String): Long {
|
||||
return service.createCoffee(Coffee(name, cost, ingredients).toCoffeeRemote()).toCoffee().uid.toLong()
|
||||
override fun insert(coffee: Coffee): Long {
|
||||
return service.createCoffee(coffee.toCoffeeRemote()).toCoffee().uid.toLong()
|
||||
}
|
||||
|
||||
override suspend fun update(uid: Int, name: String, cost: Double, ingredients: String): Int? {
|
||||
return service.updateCoffee(uid, Coffee(uid, name, cost, ingredients).toCoffeeRemote()).toCoffee().uid
|
||||
override fun update(coffee: Coffee): Int {
|
||||
return service.updateCoffee(coffee.uid, coffee.toCoffeeRemote()).toCoffee().uid
|
||||
}
|
||||
|
||||
override suspend fun delete(coffee: Coffee) {
|
||||
|
@ -52,19 +52,19 @@ class RestUserRepository(
|
||||
override suspend fun getByUid(uid: Int): User? =
|
||||
service.getUser(uid).toUser()
|
||||
|
||||
override suspend fun tryLogin(login: String, password: String): User? =
|
||||
service.tryLogin(login, password).toUser()
|
||||
override fun tryLogin(login: String, password: String): User? =
|
||||
service.tryLogin(login, password)?.toUser()
|
||||
|
||||
|
||||
override suspend fun insert(login: String, fio: String, phone: String, password: String, role: String): Long {
|
||||
return service.createUser(User(login, fio, phone, password, role).toUserRemote()).toUser().uid.toLong()
|
||||
override fun insert(user: User): Long {
|
||||
return service.createUser(user.toUserRemote()).toUser().uid.toLong()
|
||||
}
|
||||
|
||||
override suspend fun update(uid: Int, login: String, fio: String, phone: String, password: String, role: String): Int? {
|
||||
return service.updateUser(uid, User(uid, login, fio, phone, password, role).toUserRemote()).toUser().uid
|
||||
override fun update(user: User): Int? {
|
||||
return service.updateUser(user.uid, user.toUserRemote()).toUser().uid
|
||||
}
|
||||
|
||||
override suspend fun delete(userId: Int) {
|
||||
service.deleteUser(userId).toUser()
|
||||
override suspend fun delete(user: User) {
|
||||
service.deleteUser(user.uid).toUser()
|
||||
}
|
||||
}
|
@ -59,22 +59,21 @@ class UserRemoteMediator(
|
||||
val endOfPaginationReached = users.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.User)
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.USER)
|
||||
dbUserRepository.clearUsers()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
val keys = users.map {
|
||||
RemoteKeys(
|
||||
entityId = it.uid,
|
||||
type = RemoteKeyType.User,
|
||||
type = RemoteKeyType.USER,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
for (user in users) {
|
||||
dbUserRepository.insert(user.login, user.fio, user.phone, user.password, user.role)
|
||||
}
|
||||
dbUserRepository.insertUsers(users)
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
} catch (exception: IOException) {
|
||||
@ -87,14 +86,14 @@ class UserRemoteMediator(
|
||||
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, User>): RemoteKeys? {
|
||||
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
|
||||
?.let { user ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(user.uid, RemoteKeyType.User)
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(user.uid, RemoteKeyType.USER)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, User>): RemoteKeys? {
|
||||
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
|
||||
?.let { user ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(user.uid, RemoteKeyType.User)
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(user.uid, RemoteKeyType.USER)
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +102,7 @@ class UserRemoteMediator(
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.uid?.let { userUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(userUid, RemoteKeyType.User)
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(userUid, RemoteKeyType.USER)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
package com.zyzf.coffeepreorder.database
|
||||
|
||||
import android.content.Context
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.coffee.RestCoffeeRepository
|
||||
import com.zyzf.coffeepreorder.api.user.RestUserRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.CartRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineCartRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineCoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineRemoteKeyRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineUserRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.UserRepository
|
||||
|
||||
interface AppContainer {
|
||||
val coffeeRepository: CoffeeRepository
|
||||
val userRepository: UserRepository
|
||||
val cartRepository: CartRepository
|
||||
val coffeeRestRepository: RestCoffeeRepository
|
||||
val userRestRepository: RestUserRepository
|
||||
|
||||
companion object {
|
||||
const val TIMEOUT = 5000L
|
||||
@ -20,13 +22,32 @@ interface AppContainer {
|
||||
}
|
||||
|
||||
class AppDataContainer(private val context: Context) : AppContainer {
|
||||
override val coffeeRepository: CoffeeRepository by lazy {
|
||||
private val coffeeRepository: OfflineCoffeeRepository by lazy {
|
||||
OfflineCoffeeRepository(AppDatabase.getInstance(context).coffeeDao())
|
||||
}
|
||||
override val userRepository: UserRepository by lazy {
|
||||
private val userRepository: OfflineUserRepository by lazy {
|
||||
OfflineUserRepository(AppDatabase.getInstance(context).userDao())
|
||||
}
|
||||
override val cartRepository: CartRepository by lazy {
|
||||
OfflineCartRepository(AppDatabase.getInstance(context).cartDao())
|
||||
}
|
||||
private val remoteKeyRepository: OfflineRemoteKeyRepository by lazy {
|
||||
OfflineRemoteKeyRepository(AppDatabase.getInstance(context).remoteKeysDao())
|
||||
}
|
||||
override val coffeeRestRepository: RestCoffeeRepository by lazy {
|
||||
RestCoffeeRepository(
|
||||
MyServerService.getInstance(),
|
||||
coffeeRepository,
|
||||
remoteKeyRepository,
|
||||
AppDatabase.getInstance(context)
|
||||
)
|
||||
}
|
||||
override val userRestRepository: RestUserRepository by lazy {
|
||||
RestUserRepository(
|
||||
MyServerService.getInstance(),
|
||||
userRepository,
|
||||
remoteKeyRepository,
|
||||
AppDatabase.getInstance(context)
|
||||
)
|
||||
}
|
||||
}
|
@ -4,22 +4,21 @@ import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import com.zyzf.coffeepreorder.database.dao.CartDao
|
||||
import com.zyzf.coffeepreorder.database.dao.CoffeeDao
|
||||
import com.zyzf.coffeepreorder.database.dao.RemoteKeysDao
|
||||
import com.zyzf.coffeepreorder.database.dao.UserDao
|
||||
import com.zyzf.coffeepreorder.database.model.Cart
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Database(entities = [User::class, Coffee::class, Cart::class], version = 1, exportSchema = false)
|
||||
@Database(entities = [User::class, Coffee::class, Cart::class, RemoteKeys::class], version = 1, exportSchema = false)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun userDao(): UserDao
|
||||
abstract fun coffeeDao(): CoffeeDao
|
||||
abstract fun cartDao(): CartDao
|
||||
abstract fun remoteKeysDao(): RemoteKeysDao
|
||||
|
||||
companion object {
|
||||
private const val DB_NAME: String = "coffee-preorder"
|
||||
@ -32,7 +31,7 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
// Users
|
||||
val userDao = database.userDao()
|
||||
val user1 = User("zyzf", "Ян К.", "+79911152503", "250303zyzf", "admin")
|
||||
userDao.insert(user1.login, user1.fio, user1.phone, user1.password, user1.role)
|
||||
userDao.insert(user1)
|
||||
// Coffees
|
||||
val coffeeDao = database.coffeeDao()
|
||||
val coffee1 = Coffee("Coffee1", 200.0, "Ing1")
|
||||
@ -46,17 +45,17 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
val coffee9 = Coffee("Coffee9", 200.0, "Ing1")
|
||||
val coffee10 = Coffee("Coffee10", 900.0, "Ing1")
|
||||
val coffee11 = Coffee("Coffee11", 200.0, "Ing1")
|
||||
coffeeDao.insert(coffee1.name, coffee1.cost, coffee1.ingredients)
|
||||
coffeeDao.insert(coffee2.name, coffee2.cost, coffee2.ingredients)
|
||||
coffeeDao.insert(coffee3.name, coffee3.cost, coffee3.ingredients)
|
||||
coffeeDao.insert(coffee4.name, coffee4.cost, coffee4.ingredients)
|
||||
coffeeDao.insert(coffee5.name, coffee5.cost, coffee5.ingredients)
|
||||
coffeeDao.insert(coffee6.name, coffee6.cost, coffee6.ingredients)
|
||||
coffeeDao.insert(coffee7.name, coffee7.cost, coffee7.ingredients)
|
||||
coffeeDao.insert(coffee8.name, coffee8.cost, coffee8.ingredients)
|
||||
coffeeDao.insert(coffee9.name, coffee9.cost, coffee9.ingredients)
|
||||
coffeeDao.insert(coffee10.name, coffee10.cost, coffee10.ingredients)
|
||||
coffeeDao.insert(coffee11.name, coffee11.cost, coffee11.ingredients)
|
||||
coffeeDao.insert(coffee1)
|
||||
coffeeDao.insert(coffee2)
|
||||
coffeeDao.insert(coffee3)
|
||||
coffeeDao.insert(coffee4)
|
||||
coffeeDao.insert(coffee5)
|
||||
coffeeDao.insert(coffee6)
|
||||
coffeeDao.insert(coffee7)
|
||||
coffeeDao.insert(coffee8)
|
||||
coffeeDao.insert(coffee9)
|
||||
coffeeDao.insert(coffee10)
|
||||
coffeeDao.insert(coffee11)
|
||||
// Cart
|
||||
val cartDao = database.cartDao()
|
||||
val cart = Cart(2, 1)
|
||||
@ -71,14 +70,15 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
AppDatabase::class.java,
|
||||
DB_NAME
|
||||
)
|
||||
.addCallback(object : Callback() {
|
||||
override fun onCreate(db: SupportSQLiteDatabase) {
|
||||
super.onCreate(db)
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
populateDatabase()
|
||||
}
|
||||
}
|
||||
})
|
||||
// .addCallback(object : Callback() {
|
||||
// override fun onCreate(db: SupportSQLiteDatabase) {
|
||||
// super.onCreate(db)
|
||||
// CoroutineScope(Dispatchers.IO).launch {
|
||||
// populateDatabase()
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
.allowMainThreadQueries()
|
||||
.build()
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
|
@ -3,22 +3,27 @@ package com.zyzf.coffeepreorder.database.dao
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
|
||||
@Dao
|
||||
interface CoffeeDao {
|
||||
@Query("select * from coffee order by name collate nocase asc")
|
||||
fun getAll(): PagingSource<Int, Coffee>
|
||||
fun getAllCoffees(): PagingSource<Int, Coffee>
|
||||
|
||||
@Query("select coffee.uid, name, cost, ingredients from coffee where coffee.uid = :uid")
|
||||
suspend fun getByUid(uid: Int): Coffee?
|
||||
|
||||
@Query("insert into coffee (name, cost, ingredients) values (:name, :cost, :ingredients)")
|
||||
suspend fun insert(name: String, cost: Double, ingredients: String): Long
|
||||
@Insert
|
||||
fun insert(coffee: Coffee): Long
|
||||
|
||||
@Query("update coffee set name = :name, cost = :cost, ingredients = :ingredients where uid = :uid")
|
||||
suspend fun update(uid: Int, name: String, cost: Double, ingredients: String): Int?
|
||||
@Insert
|
||||
suspend fun insert(vararg coffee: Coffee)
|
||||
|
||||
@Update
|
||||
fun update(coffee: Coffee): Int
|
||||
|
||||
@Delete
|
||||
suspend fun delete(coffee: Coffee)
|
||||
|
@ -2,8 +2,11 @@ package com.zyzf.coffeepreorder.database.dao
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.zyzf.coffeepreorder.api.user.RestUserRepository
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@ -14,17 +17,23 @@ interface UserDao {
|
||||
fun getAll(): PagingSource<Int, User>
|
||||
|
||||
@Query("select * from user where login = :login and password = :password")
|
||||
suspend fun tryLogin(login: String, password: String): User?
|
||||
fun tryLogin(login: String, password: String): User?
|
||||
|
||||
@Query("select * from user where uid = :uid")
|
||||
suspend fun getByUid(uid: Int): User?
|
||||
|
||||
@Query("insert into user (login, fio, phone, password, role) values (:login, :fio, :phone, :password, :role)")
|
||||
suspend fun insert(login: String, fio: String, phone: String, password: String, role: String): Long
|
||||
@Insert
|
||||
fun insert(user: User): Long
|
||||
|
||||
@Query("update user set login = :login, fio = :fio, phone = :phone, password = :password, role = :role where uid = :uid")
|
||||
suspend fun update(uid: Int, login: String, fio: String, phone: String, password: String, role: String): Int?
|
||||
@Insert
|
||||
fun insert(vararg user: User)
|
||||
|
||||
@Query("delete from user where uid = :uid")
|
||||
suspend fun delete(uid: Int)
|
||||
@Update
|
||||
fun update(user: User): Int?
|
||||
|
||||
@Delete
|
||||
suspend fun delete(user: User)
|
||||
|
||||
@Query("delete from user")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -17,7 +17,7 @@ import androidx.room.PrimaryKey
|
||||
])
|
||||
data class Cart(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val uid: Int?,
|
||||
val uid: Int = 0,
|
||||
@ColumnInfo(name = "coffee_id", index = true)
|
||||
val coffeeId: Int,
|
||||
@ColumnInfo(name = "count", index = true)
|
||||
@ -27,16 +27,22 @@ data class Cart(
|
||||
constructor(
|
||||
coffeeId: Int,
|
||||
count: Int
|
||||
) : this(null, coffeeId, 0)
|
||||
) : this(0, coffeeId, count)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as Cart
|
||||
return uid == other.uid
|
||||
if (uid != other.uid) return false
|
||||
if (coffeeId != other.coffeeId) return false
|
||||
if (count != other.count) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return uid ?: -1
|
||||
var result = uid
|
||||
result = 31 * result + coffeeId.hashCode()
|
||||
result = 31 * result + count.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package com.zyzf.coffeepreorder.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.ForeignKey
|
||||
import androidx.room.Ignore
|
||||
import androidx.room.PrimaryKey
|
||||
|
||||
@ -39,10 +38,18 @@ data class Coffee(
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as Coffee
|
||||
return uid == other.uid
|
||||
if (uid != other.uid) return false
|
||||
if (name != other.name) return false
|
||||
if (cost != other.cost) return false
|
||||
if (ingredients != other.ingredients) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return uid
|
||||
var result = uid
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + cost.hashCode()
|
||||
result = 31 * result + ingredients.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@ import androidx.room.TypeConverter
|
||||
import androidx.room.TypeConverters
|
||||
|
||||
enum class RemoteKeyType(private val type: String) {
|
||||
Coffee(Coffee::class.simpleName ?: "Coffee"),
|
||||
User(User::class.simpleName ?: "User");
|
||||
COFFEE(Coffee::class.simpleName ?: "Coffee"),
|
||||
USER(User::class.simpleName ?: "User");
|
||||
|
||||
@TypeConverter
|
||||
fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value }
|
||||
@ -24,3 +24,4 @@ data class RemoteKeys(
|
||||
val prevKey: Int?,
|
||||
val nextKey: Int?
|
||||
)
|
||||
|
||||
|
@ -46,10 +46,22 @@ data class User(
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
other as User
|
||||
return uid == other.uid
|
||||
if (uid != other.uid) return false
|
||||
if (login != other.login) return false
|
||||
if (fio != other.fio) return false
|
||||
if (phone != other.phone) return false
|
||||
if (password != other.password) return false
|
||||
if (role != other.role) return false
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return uid ?: -1
|
||||
var result = uid
|
||||
result = 31 * result + login.hashCode()
|
||||
result = 31 * result + fio.hashCode()
|
||||
result = 31 * result + phone.hashCode()
|
||||
result = 31 * result + password.hashCode()
|
||||
result = 31 * result + role.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,4 +15,4 @@ interface CartRepository {
|
||||
fun getCountForCoffee(coffeeId: Int): Double
|
||||
suspend fun update(cart: Cart)
|
||||
suspend fun deleteAll()
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CoffeeRepository {
|
||||
fun getAll(): Flow<PagingData<Coffee>>
|
||||
fun getAllCoffees(): Flow<PagingData<Coffee>>
|
||||
suspend fun getByUid(uid: Int): Coffee?
|
||||
suspend fun insert(name: String, cost: Double, ingredients: String): Long
|
||||
suspend fun update(uid: Int, name: String, cost: Double, ingredients: String): Int?
|
||||
fun insert(coffee: Coffee): Long
|
||||
fun update(coffee: Coffee): Int
|
||||
suspend fun delete(coffee: Coffee)
|
||||
}
|
@ -25,4 +25,4 @@ class OfflineCartRepository(private val cartDao: CartDao) : CartRepository {
|
||||
override fun getCountForCoffee(coffeeId: Int): Double = cartDao.getCountForCoffee(coffeeId)
|
||||
override suspend fun update(cart: Cart) = cartDao.update(cart)
|
||||
override suspend fun deleteAll() = cartDao.deleteAll()
|
||||
}
|
||||
}
|
||||
|
@ -10,18 +10,20 @@ import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineCoffeeRepository(private val coffeeDao: CoffeeDao) : CoffeeRepository {
|
||||
override fun getAll(): Flow<PagingData<Coffee>> = Pager(
|
||||
override fun getAllCoffees(): Flow<PagingData<Coffee>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = coffeeDao::getAll
|
||||
pagingSourceFactory = coffeeDao::getAllCoffees
|
||||
).flow
|
||||
|
||||
fun getAllCoffeesPagingSource(): PagingSource<Int, Coffee> = coffeeDao.getAll()
|
||||
fun getAllCoffeesPagingSource(): PagingSource<Int, Coffee> = coffeeDao.getAllCoffees()
|
||||
suspend fun clearCoffees() = coffeeDao.deleteAll()
|
||||
override suspend fun getByUid(uid: Int): Coffee? = coffeeDao.getByUid(uid)
|
||||
override suspend fun insert(name: String, cost: Double, ingredients: String): Long = coffeeDao.insert(name, cost, ingredients)
|
||||
override suspend fun update(uid: Int, name: String, cost: Double, ingredients: String): Int? = coffeeDao.update(uid, name, cost, ingredients)
|
||||
override fun insert(coffee: Coffee): Long = coffeeDao.insert(coffee)
|
||||
suspend fun insertCoffees(coffees: List<Coffee>) =
|
||||
coffeeDao.insert(*coffees.toTypedArray())
|
||||
override fun update(coffee: Coffee): Int = coffeeDao.update(coffee)
|
||||
override suspend fun delete(coffee: Coffee) = coffeeDao.delete(coffee)
|
||||
}
|
@ -20,8 +20,11 @@ class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
|
||||
).flow
|
||||
fun getAllUserPagingSource(): PagingSource<Int, User> = userDao.getAll()
|
||||
override suspend fun getByUid(uid: Int): User? = userDao.getByUid(uid)
|
||||
override suspend fun tryLogin(login: String, password: String): User? = userDao.tryLogin(login, password)
|
||||
override suspend fun insert(login: String, fio: String, phone: String, password: String, role: String): Long = userDao.insert(login, fio, phone, password, role)
|
||||
override suspend fun update(uid: Int, login: String, fio: String, phone: String, password: String, role: String): Int? = userDao.update(uid, login, fio, phone, password, role)
|
||||
override suspend fun delete(uid: Int) = userDao.delete(uid)
|
||||
override fun tryLogin(login: String, password: String): User? = userDao.tryLogin(login, password)
|
||||
override fun insert(user: User): Long = userDao.insert(user)
|
||||
fun insertUsers(users: List<User>) =
|
||||
userDao.insert(*users.toTypedArray())
|
||||
override fun update(user: User): Int? = userDao.update(user)
|
||||
override suspend fun delete(user: User) = userDao.delete(user)
|
||||
suspend fun clearUsers() = userDao.deleteAll()
|
||||
}
|
@ -7,8 +7,8 @@ import kotlinx.coroutines.flow.Flow
|
||||
interface UserRepository {
|
||||
fun getAll(): Flow<PagingData<User>>
|
||||
suspend fun getByUid(uid: Int): User?
|
||||
suspend fun tryLogin(login: String, password: String): User?
|
||||
suspend fun insert(login: String, fio: String, phone: String, password: String, role: String): Long
|
||||
suspend fun update(uid: Int, login: String, fio: String, phone: String, password: String, role: String) : Int?
|
||||
suspend fun delete(uid: Int)
|
||||
fun tryLogin(login: String, password: String): User?
|
||||
fun insert(user: User): Long
|
||||
fun update(user: User) : Int?
|
||||
suspend fun delete(user: User)
|
||||
}
|
@ -7,15 +7,23 @@ import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.zyzf.coffeepreorder.CoffeeApplication
|
||||
import com.zyzf.coffeepreorder.ui.cart.CartViewModel
|
||||
import com.zyzf.coffeepreorder.ui.coffee.CoffeeListViewModel
|
||||
import com.zyzf.coffeepreorder.ui.login.LoginViewModel
|
||||
import com.zyzf.coffeepreorder.ui.register.RegisterViewModel
|
||||
|
||||
object AppViewModelProvider {
|
||||
val Factory = viewModelFactory {
|
||||
initializer {
|
||||
CoffeeListViewModel(coffeeApplication().container.coffeeRepository, coffeeApplication().container.cartRepository)
|
||||
CoffeeListViewModel(coffeeApplication().container.coffeeRestRepository, coffeeApplication().container.cartRepository)
|
||||
}
|
||||
initializer {
|
||||
CartViewModel(coffeeApplication().container.cartRepository)
|
||||
}
|
||||
initializer {
|
||||
LoginViewModel(coffeeApplication().container.userRestRepository)
|
||||
}
|
||||
initializer {
|
||||
RegisterViewModel(coffeeApplication().container.userRestRepository)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.repository.CartRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class CartViewModel(
|
||||
|
@ -13,7 +13,6 @@ import com.jcraft.jsch.JSch
|
||||
import com.jcraft.jsch.JSchException
|
||||
import com.jcraft.jsch.Session
|
||||
import com.jcraft.jsch.SftpException
|
||||
import com.zyzf.coffeepreorder.database.model.Cart
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.repository.CartRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
@ -29,13 +28,13 @@ class CoffeeListViewModel(
|
||||
private val coffeeRepository: CoffeeRepository,
|
||||
private val cartRepository: CartRepository
|
||||
) : ViewModel() {
|
||||
val coffeeListUiState: Flow<PagingData<Coffee>> = coffeeRepository.getAll()
|
||||
val coffeeListUiState: Flow<PagingData<Coffee>> = coffeeRepository.getAllCoffees()
|
||||
|
||||
suspend fun addCoffeeToCart(coffeeUid: Int) {
|
||||
cartRepository.insertCoffee(coffeeUid, 1)
|
||||
}
|
||||
suspend fun createCoffee(coffee: Coffee, imageUri: Uri, context: Context) {
|
||||
val newCoffee: Long = coffeeRepository.insert(coffee.name, coffee.cost, coffee.ingredients)
|
||||
val newCoffee: Long = coffeeRepository.insert(coffee)
|
||||
val inputStream = context.contentResolver.openInputStream(imageUri)
|
||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
|
||||
@ -54,7 +53,7 @@ class CoffeeListViewModel(
|
||||
copyFileToSftp(f, "/mnt/nextcloud/data/Zyzf/files/Images")
|
||||
}
|
||||
suspend fun editCoffee(coffee: Coffee, imageUri: Uri, context: Context) {
|
||||
val editedCoffee: Int = coffeeRepository.update(coffee.uid, coffee.name, coffee.cost, coffee.ingredients)!!
|
||||
val editedCoffee: Int = coffeeRepository.update(coffee)
|
||||
val inputStream = context.contentResolver.openInputStream(imageUri)
|
||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
|
||||
|
@ -23,6 +23,7 @@ import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@ -34,6 +35,7 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
@ -41,18 +43,25 @@ import com.zyzf.coffeepreorder.CoffeeApplication
|
||||
import com.zyzf.coffeepreorder.R
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import com.zyzf.coffeepreorder.ui.AppViewModelProvider
|
||||
import com.zyzf.coffeepreorder.ui.coffee.CoffeeListViewModel
|
||||
import com.zyzf.coffeepreorder.ui.navigation.Screen
|
||||
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@Composable
|
||||
fun Login(navController: NavController?) {
|
||||
fun Login(
|
||||
navController: NavController?,
|
||||
viewModel: LoginViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var login by remember { mutableStateOf("") }
|
||||
var password by remember { mutableStateOf("") }
|
||||
LaunchedEffect(Unit) {
|
||||
@ -91,8 +100,8 @@ fun Login(navController: NavController?) {
|
||||
Button(
|
||||
onClick = {
|
||||
var user: User?
|
||||
GlobalScope.launch (Dispatchers.Main) {
|
||||
user = AppDatabase.getInstance(context).userDao().tryLogin(login, password)
|
||||
coroutineScope.launch {
|
||||
user = viewModel.tryLogin(login, password)
|
||||
if (user != null) {
|
||||
CoffeeApplication.currentUser = null
|
||||
CoffeeApplication.currentUser = user
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.zyzf.coffeepreorder.ui.login
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.zyzf.coffeepreorder.api.user.RestUserRepository
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import com.zyzf.coffeepreorder.database.repository.UserRepository
|
||||
|
||||
class LoginViewModel(
|
||||
private val userRepository: UserRepository
|
||||
) : ViewModel() {
|
||||
fun tryLogin(login: String, password: String): User? {
|
||||
return userRepository.tryLogin(login, password)
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ enum class Screen(
|
||||
|
||||
fun getItem(route: String): Screen? {
|
||||
val findRoute = route.split("/").first()
|
||||
return entries.find { value -> value.route.startsWith(findRoute) }
|
||||
return values().find { value -> value.route.startsWith(findRoute) }
|
||||
}
|
||||
}
|
||||
}
|
@ -195,7 +195,7 @@ fun Profile(navController: NavController?) {
|
||||
onClick = {
|
||||
GlobalScope.launch (Dispatchers.Main) {
|
||||
if (userOldPsswd.value == user.password && userNewPsswd.value == userNewPsswdConf.value) {
|
||||
val userUid: Int? = AppDatabase.getInstance(context).userDao().update(user.uid!!, userLogin, userFIO, userPhone, userNewPsswd.value, user.role)
|
||||
val userUid: Int? = AppDatabase.getInstance(context).userDao().update(User(user.uid!!, userLogin, userFIO, userPhone, userNewPsswd.value, user.role))
|
||||
user = AppDatabase.getInstance(context).userDao().getByUid(userUid!!)!!
|
||||
CoffeeApplication.currentUser = user
|
||||
}
|
||||
@ -274,7 +274,7 @@ fun Profile(navController: NavController?) {
|
||||
onClick = {
|
||||
GlobalScope.launch (Dispatchers.Main) {
|
||||
CoffeeApplication.currentUser = null
|
||||
AppDatabase.getInstance(context).userDao().delete(user.uid!!)
|
||||
AppDatabase.getInstance(context).userDao().delete(user)
|
||||
}
|
||||
openDialogDelete.value = false
|
||||
navController?.navigate(Screen.Login.route)
|
||||
|
@ -22,6 +22,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@ -33,6 +34,7 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavController
|
||||
import coil.compose.AsyncImage
|
||||
import coil.request.ImageRequest
|
||||
@ -40,17 +42,24 @@ import com.zyzf.coffeepreorder.CoffeeApplication
|
||||
import com.zyzf.coffeepreorder.R
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import com.zyzf.coffeepreorder.ui.AppViewModelProvider
|
||||
import com.zyzf.coffeepreorder.ui.login.LoginViewModel
|
||||
import com.zyzf.coffeepreorder.ui.navigation.Screen
|
||||
import com.zyzf.coffeepreorder.ui.theme.CoffeePreorderTheme
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(DelicateCoroutinesApi::class)
|
||||
@Composable
|
||||
fun Register(navController: NavController?) {
|
||||
fun Register(
|
||||
navController: NavController?,
|
||||
viewModel: RegisterViewModel = viewModel(factory = AppViewModelProvider.Factory)
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var login: String by remember { mutableStateOf("") }
|
||||
var fio: String by remember { mutableStateOf("") }
|
||||
var phone: String by remember { mutableStateOf("") }
|
||||
@ -105,10 +114,9 @@ fun Register(navController: NavController?) {
|
||||
Button(
|
||||
onClick = {
|
||||
var user: User?
|
||||
GlobalScope.launch (Dispatchers.Main) {
|
||||
coroutineScope.launch (Dispatchers.Main) {
|
||||
if (password == confPassword) {
|
||||
AppDatabase.getInstance(context).userDao().insert(login, fio, phone, password, "user")
|
||||
user = AppDatabase.getInstance(context).userDao().tryLogin(login, password)
|
||||
user = viewModel.register(User(login, fio, phone, password, "user"))
|
||||
if (user != null) {
|
||||
CoffeeApplication.currentUser = null
|
||||
CoffeeApplication.currentUser = user!!
|
||||
|
@ -0,0 +1,15 @@
|
||||
package com.zyzf.coffeepreorder.ui.register
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import com.zyzf.coffeepreorder.database.repository.UserRepository
|
||||
|
||||
class RegisterViewModel(
|
||||
private val userRepository: UserRepository
|
||||
) : ViewModel() {
|
||||
fun register(user: User): User? {
|
||||
userRepository.insert(user)
|
||||
return userRepository.tryLogin(user.login, user.password)
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">192.168.42.94</domain>
|
||||
<domain includeSubdomains="true">192.168.0.100</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
@ -2,9 +2,12 @@ package com.kalyshev.yan.coffee.controller;
|
||||
|
||||
import com.kalyshev.yan.WebConfiguration;
|
||||
import com.kalyshev.yan.coffee.service.CoffeeService;
|
||||
import com.kalyshev.yan.user.model.User;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(WebConfiguration.REST_API + "/coffee")
|
||||
public class CoffeeController {
|
||||
@ -17,13 +20,13 @@ public class CoffeeController {
|
||||
return new CoffeeDto(coffeeService.findCoffee(id));
|
||||
}
|
||||
@GetMapping("/")
|
||||
public CoffeeResponse getAllCoffees(
|
||||
@RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo,
|
||||
public List<CoffeeDto> getAllCoffees(
|
||||
@RequestParam(value = "pageNo", defaultValue = "1", required = false) int pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10", required = false) int pageSize,
|
||||
@RequestParam(value = "sortBy", defaultValue = "id", required = false) String sortBy,
|
||||
@RequestParam(value = "sortDir", defaultValue = "asc", required = false) String sortDir
|
||||
){
|
||||
return coffeeService.findAllCoffees(pageNo, pageSize, sortBy, sortDir);
|
||||
return coffeeService.findAllCoffees(pageNo-1, pageSize, sortBy, sortDir);
|
||||
}
|
||||
@PostMapping("/")
|
||||
public CoffeeDto createCoffee(@RequestBody @Valid CoffeeDto coffeeDto) {
|
||||
|
@ -1,32 +0,0 @@
|
||||
package com.kalyshev.yan.coffee.controller;
|
||||
|
||||
import com.kalyshev.yan.user.controller.UserDto;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class CoffeeResponse {
|
||||
private List<CoffeeDto> content;
|
||||
private int pageNo;
|
||||
private int pageSize;
|
||||
private long totalElements;
|
||||
private int totalPages;
|
||||
private boolean last;
|
||||
public List<CoffeeDto> getContent() {return content;}
|
||||
public int getPageNo() {return pageNo;}
|
||||
public int getPageSize() {return pageSize;}
|
||||
public long getTotalElements() {return totalElements;}
|
||||
public int getTotalPages() {return totalPages;}
|
||||
public boolean getLast() {return last;}
|
||||
public void setContent (List<CoffeeDto> content) { this.content = content; }
|
||||
public void setPageNo (int pageNo) { this.pageNo = pageNo; }
|
||||
public void setPageSize (int pageSize) { this.pageSize = pageSize; }
|
||||
public void setTotalElements (long totalElements) { this.totalElements = totalElements; }
|
||||
public void setTotalPages (int totalPages) { this.totalPages = totalPages; }
|
||||
public void setLast (boolean last) { this.last = last; }
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package com.kalyshev.yan.coffee.service;
|
||||
|
||||
import com.kalyshev.yan.coffee.controller.CoffeeDto;
|
||||
import com.kalyshev.yan.coffee.controller.CoffeeResponse;
|
||||
import com.kalyshev.yan.coffee.model.Coffee;
|
||||
import com.kalyshev.yan.coffee.repository.CoffeeRepository;
|
||||
import com.kalyshev.yan.user.model.User;
|
||||
import com.kalyshev.yan.user.repository.UserNotFoundException;
|
||||
import com.kalyshev.yan.util.validation.ValidatorUtil;
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -44,7 +44,7 @@ public class CoffeeService {
|
||||
return coffee.orElseThrow(() -> new UserNotFoundException(id));
|
||||
}
|
||||
@Transactional(readOnly = true)
|
||||
public CoffeeResponse findAllCoffees(int pageNo, int pageSize, String sortBy, String sortDir) {
|
||||
public List<CoffeeDto> findAllCoffees(int pageNo, int pageSize, String sortBy, String sortDir) {
|
||||
Sort sort = sortDir.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortBy).ascending()
|
||||
: Sort.by(sortBy).descending();
|
||||
|
||||
@ -60,15 +60,7 @@ public class CoffeeService {
|
||||
.map(CoffeeDto::new)
|
||||
.toList();
|
||||
|
||||
CoffeeResponse coffeeResponse = new CoffeeResponse();
|
||||
coffeeResponse.setContent(content);
|
||||
coffeeResponse.setPageNo(coffees.getNumber());
|
||||
coffeeResponse.setPageSize(coffees.getSize());
|
||||
coffeeResponse.setTotalElements(coffees.getTotalElements());
|
||||
coffeeResponse.setTotalPages(coffees.getTotalPages());
|
||||
coffeeResponse.setLast(coffees.isLast());
|
||||
|
||||
return coffeeResponse;
|
||||
return content;
|
||||
}
|
||||
@Transactional
|
||||
public Coffee updateCoffee(Long id, String name, Double cost, String ingredients) {
|
||||
|
@ -6,6 +6,8 @@ import com.kalyshev.yan.user.service.UserService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(WebConfiguration.REST_API + "/user")
|
||||
public class UserController {
|
||||
@ -18,7 +20,7 @@ public class UserController {
|
||||
return new UserDto(userService.findUser(id));
|
||||
}
|
||||
@GetMapping("/")
|
||||
public UserResponse getAllUsers(
|
||||
public List<UserDto> getAllUsers(
|
||||
@RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10", required = false) int pageSize,
|
||||
@RequestParam(value = "sortBy", defaultValue = "id", required = false) String sortBy,
|
||||
|
@ -1,31 +0,0 @@
|
||||
package com.kalyshev.yan.user.controller;
|
||||
|
||||
import com.kalyshev.yan.coffee.controller.CoffeeDto;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UserResponse {
|
||||
private List<UserDto> content;
|
||||
private int pageNo;
|
||||
private int pageSize;
|
||||
private long totalElements;
|
||||
private int totalPages;
|
||||
private boolean last;
|
||||
public List<UserDto> getContent() {return content;}
|
||||
public int getPageNo() {return pageNo;}
|
||||
public int getPageSize() {return pageSize;}
|
||||
public long getTotalElements() {return totalElements;}
|
||||
public int getTotalPages() {return totalPages;}
|
||||
public void setContent (List<UserDto> content) { this.content = content; }
|
||||
public void setPageNo (int pageNo) { this.pageNo = pageNo; }
|
||||
public void setPageSize (int pageSize) { this.pageSize = pageSize; }
|
||||
public void setTotalElements (long totalElements) { this.totalElements = totalElements; }
|
||||
public void setTotalPages (int totalPages) { this.totalPages = totalPages; }
|
||||
public void setLast (boolean last) { this.last = last; }
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package com.kalyshev.yan.user.service;
|
||||
|
||||
import com.kalyshev.yan.user.controller.UserDto;
|
||||
import com.kalyshev.yan.user.controller.UserResponse;
|
||||
import com.kalyshev.yan.user.model.User;
|
||||
import com.kalyshev.yan.user.repository.UserNotFoundException;
|
||||
import com.kalyshev.yan.user.repository.UserRepository;
|
||||
@ -58,7 +57,7 @@ public class UserService {
|
||||
return user.orElseThrow(() -> new UserNotFoundException((long)0));
|
||||
}
|
||||
@Transactional(readOnly = true)
|
||||
public UserResponse findAllUsers(int pageNo, int pageSize, String sortBy, String sortDir) {
|
||||
public List<UserDto> findAllUsers(int pageNo, int pageSize, String sortBy, String sortDir) {
|
||||
Sort sort = sortDir.equalsIgnoreCase(Sort.Direction.ASC.name()) ? Sort.by(sortBy).ascending()
|
||||
: Sort.by(sortBy).descending();
|
||||
|
||||
@ -74,15 +73,7 @@ public class UserService {
|
||||
.map(UserDto::new)
|
||||
.toList();
|
||||
|
||||
UserResponse userResponse = new UserResponse();
|
||||
userResponse.setContent(content);
|
||||
userResponse.setPageNo(users.getNumber());
|
||||
userResponse.setPageSize(users.getSize());
|
||||
userResponse.setTotalElements(users.getTotalElements());
|
||||
userResponse.setTotalPages(users.getTotalPages());
|
||||
userResponse.setLast(users.isLast());
|
||||
|
||||
return userResponse;
|
||||
return content;
|
||||
}
|
||||
@Transactional
|
||||
public User updateUser(Long id, String login, String fio, String phone, String password, String role) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
plugins {
|
||||
id("com.android.application") version "8.2.0" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.9.20" apply false
|
||||
id("com.google.devtools.ksp") version "1.9.20-1.0.14" apply false
|
||||
id("org.jetbrains.kotlin.android") version "1.9.10" apply false
|
||||
id("com.google.devtools.ksp") version "1.9.10-1.0.13" apply false
|
||||
id("org.jetbrains.kotlin.plugin.serialization") version "1.9.10" apply false
|
||||
}
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Sun Oct 15 15:51:04 GMT+04:00 2023
|
||||
#Thu Dec 14 21:41:14 GMT+04:00 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
Loading…
Reference in New Issue
Block a user