some beginning
This commit is contained in:
parent
638b9d6aaf
commit
7c3af23e3b
@ -76,7 +76,7 @@ dependencies {
|
||||
implementation("androidx.compose.ui:ui-tooling-preview:1.6.0-beta02")
|
||||
implementation("androidx.compose.material3:material3:1.1.2")
|
||||
implementation("androidx.paging:paging-compose:3.2.1")
|
||||
implementation("eu.bambooapps:compose-material3-pullrefresh:1.0.0")
|
||||
implementation("eu.bambooapps:compose-material3-pullrefresh:1.0.1")
|
||||
|
||||
// Room
|
||||
val roomVersion = "2.6.1"
|
||||
|
@ -0,0 +1,66 @@
|
||||
package com.zyzf.coffeepreorder.api
|
||||
|
||||
import com.zyzf.coffeepreorder.api.model.CoffeeRemote
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.PUT
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface MyServerService {
|
||||
@GET("groups")
|
||||
suspend fun getGroups(): List<GroupRemote>
|
||||
|
||||
@GET("coffee")
|
||||
suspend fun getCoffees(
|
||||
@Query("_page") page: Int,
|
||||
@Query("_limit") limit: Int,
|
||||
): List<CoffeeRemote>
|
||||
|
||||
@GET("coffee/{id}")
|
||||
suspend fun getCoffee(
|
||||
@Path("id") id: Int,
|
||||
): CoffeeRemote
|
||||
|
||||
@POST("coffee")
|
||||
suspend fun createCoffee(
|
||||
@Body student: CoffeeRemote,
|
||||
): CoffeeRemote
|
||||
|
||||
@PUT("coffee/{id}")
|
||||
suspend fun updateCoffee(
|
||||
@Path("id") id: Int,
|
||||
@Body student: CoffeeRemote,
|
||||
): CoffeeRemote
|
||||
|
||||
@DELETE("coffee/{id}")
|
||||
suspend fun deleteCoffee(
|
||||
@Path("id") id: Int,
|
||||
): CoffeeRemote
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = "http://10.120.175.105:8079/"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: MyServerService? = null
|
||||
|
||||
fun getInstance(): MyServerService {
|
||||
return INSTANCE ?: synchronized(this) {
|
||||
val logger = HttpLoggingInterceptor()
|
||||
logger.level = HttpLoggingInterceptor.Level.BASIC
|
||||
val client = OkHttpClient.Builder()
|
||||
.addInterceptor(logger)
|
||||
.build()
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(client)
|
||||
.addConverterFactory(Json.asConverterFactory("application/json".toMediaType()))
|
||||
.build()
|
||||
.create(MyServerService::class.java)
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
package com.zyzf.coffeepreorder.api.coffee
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffee
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeyType
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineCoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineRemoteKeyRepository
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class CoffeeRemoteMediator(
|
||||
private val service: MyServerService,
|
||||
private val dbCoffeeRepository: OfflineCoffeeRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : RemoteMediator<Int, Coffee>() {
|
||||
|
||||
override suspend fun initialize(): InitializeAction {
|
||||
return InitializeAction.LAUNCH_INITIAL_REFRESH
|
||||
}
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Coffee>
|
||||
): MediatorResult {
|
||||
val page = when (loadType) {
|
||||
LoadType.REFRESH -> {
|
||||
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
|
||||
remoteKeys?.nextKey?.minus(1) ?: 1
|
||||
}
|
||||
|
||||
LoadType.PREPEND -> {
|
||||
val remoteKeys = getRemoteKeyForFirstItem(state)
|
||||
remoteKeys?.prevKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
|
||||
LoadType.APPEND -> {
|
||||
val remoteKeys = getRemoteKeyForLastItem(state)
|
||||
remoteKeys?.nextKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val coffees = service.getCoffees(page, state.config.pageSize).map { it.toCoffee() }
|
||||
val endOfPaginationReached = coffees.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.Coffee)
|
||||
dbCoffeeRepository.clearCoffees()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
val keys = coffees.map {
|
||||
RemoteKeys(
|
||||
entityId = it.uid,
|
||||
type = RemoteKeyType.Coffee,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
for (coffee in coffees) {
|
||||
dbCoffeeRepository.insert(coffee.name, coffee.cost, coffee.ingredients)
|
||||
}
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
} catch (exception: IOException) {
|
||||
return MediatorResult.Error(exception)
|
||||
} catch (exception: HttpException) {
|
||||
return MediatorResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyClosestToCurrentPosition(
|
||||
state: PagingState<Int, Coffee>
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.uid?.let { coffeeUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(coffeeUid, RemoteKeyType.Coffee)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.zyzf.coffeepreorder.api.coffee
|
||||
|
||||
import android.util.Log
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffee
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffeeRemote
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineCoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineRemoteKeyRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class RestCoffeeRepository(
|
||||
private val service: MyServerService,
|
||||
private val dbCoffeeRepository: OfflineCoffeeRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : CoffeeRepository {
|
||||
override fun getAll(): Flow<PagingData<Coffee>> {
|
||||
Log.d(RestCoffeeRepository::class.simpleName, "Get coffees")
|
||||
|
||||
val pagingSourceFactory = { dbCoffeeRepository.getAllCoffeesPagingSource() }
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = CoffeeRemoteMediator(
|
||||
service,
|
||||
dbCoffeeRepository,
|
||||
dbRemoteKeyRepository,
|
||||
database,
|
||||
),
|
||||
pagingSourceFactory = pagingSourceFactory
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun getByUid(uid: Int): Coffee? =
|
||||
service.getCoffee(uid).toCoffee()
|
||||
|
||||
override suspend fun insert(name: String, cost: Double, ingredients: String): Int {
|
||||
return service.createCoffee(Coffee(name, cost, ingredients, null, 0).toCoffeeRemote()).toCoffee().uid
|
||||
}
|
||||
|
||||
override suspend fun update(uid: Int, name: String, cost: Double, ingredients: String, cartId: Int?, count: Int): Int? {
|
||||
return service.updateCoffee(uid, Coffee(uid, name, cost, ingredients, cartId, count).toCoffeeRemote()).toCoffee().uid
|
||||
}
|
||||
|
||||
override suspend fun delete(coffee: Coffee) {
|
||||
service.deleteCoffee(coffee.uid).toCoffee()
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.zyzf.coffeepreorder.api.model
|
||||
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CoffeeRemote(
|
||||
val id: Int = 0,
|
||||
val name: String = "",
|
||||
val cost: Double = 0.0,
|
||||
val ingredients: String = "",
|
||||
val cartId: Int? = 0,
|
||||
val count: Int = 0
|
||||
)
|
||||
|
||||
fun CoffeeRemote.toCoffee(): Coffee = Coffee(
|
||||
id,
|
||||
name,
|
||||
cost,
|
||||
ingredients,
|
||||
cartId,
|
||||
count
|
||||
)
|
||||
|
||||
fun Coffee.toCoffeeRemote(): CoffeeRemote = CoffeeRemote(
|
||||
uid,
|
||||
name,
|
||||
cost,
|
||||
ingredients,
|
||||
cartId,
|
||||
count
|
||||
)
|
@ -0,0 +1,32 @@
|
||||
package com.zyzf.coffeepreorder.api.model
|
||||
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserRemote(
|
||||
val id: Int = 0,
|
||||
val login: String = "",
|
||||
val fio: String = "",
|
||||
val phone: String = "",
|
||||
val password: String = "",
|
||||
val role: String = "user"
|
||||
)
|
||||
|
||||
fun UserRemote.toUser(): User = User(
|
||||
id,
|
||||
login,
|
||||
fio,
|
||||
phone,
|
||||
password,
|
||||
role
|
||||
)
|
||||
|
||||
fun User.toUserRemote(): UserRemote = UserRemote(
|
||||
uid,
|
||||
login,
|
||||
fio,
|
||||
phone,
|
||||
password,
|
||||
role
|
||||
)
|
@ -0,0 +1,64 @@
|
||||
package com.zyzf.coffeepreorder.api.user
|
||||
|
||||
import android.util.Log
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.coffee.CoffeeRemoteMediator
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffee
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffeeRemote
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
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
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class RestUserRepository(
|
||||
private val service: MyServerService,
|
||||
private val dbUserRepository: OfflineUserRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : UserRepository {
|
||||
override fun getAll(): Flow<PagingData<User>> {
|
||||
Log.d(RestUserRepository::class.simpleName, "Get users")
|
||||
|
||||
val pagingSourceFactory = { dbUserRepository.getAllUserPagingSource() }
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = UserRemoteMediator(
|
||||
service,
|
||||
dbUserRepository,
|
||||
dbRemoteKeyRepository,
|
||||
database,
|
||||
),
|
||||
pagingSourceFactory = pagingSourceFactory
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun getByUid(uid: Int): User? =
|
||||
service.getUser(uid).toUser()
|
||||
|
||||
override suspend fun insert(name: String, cost: Double, ingredients: String): Int {
|
||||
return service.createCoffee(Coffee(name, cost, ingredients, null, 0).toCoffeeRemote()).toCoffee().uid
|
||||
}
|
||||
|
||||
override suspend fun update(uid: Int, name: String, cost: Double, ingredients: String, cartId: Int?, count: Int): Int? {
|
||||
return service.updateCoffee(uid, Coffee(uid, name, cost, ingredients, cartId, count).toCoffeeRemote()).toCoffee().uid
|
||||
}
|
||||
|
||||
override suspend fun delete(coffee: Coffee) {
|
||||
service.deleteCoffee(coffee.uid).toCoffee()
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package com.zyzf.coffeepreorder.api.user
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.zyzf.coffeepreorder.api.MyServerService
|
||||
import com.zyzf.coffeepreorder.api.model.toCoffee
|
||||
import com.zyzf.coffeepreorder.database.AppDatabase
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeyType
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineCoffeeRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineRemoteKeyRepository
|
||||
import com.zyzf.coffeepreorder.database.repository.OfflineUserRepository
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class UserRemoteMediator(
|
||||
private val service: MyServerService,
|
||||
private val dbUserRepository: OfflineUserRepository,
|
||||
private val dbRemoteKeyRepository: OfflineRemoteKeyRepository,
|
||||
private val database: AppDatabase
|
||||
) : RemoteMediator<Int, User>() {
|
||||
|
||||
override suspend fun initialize(): InitializeAction {
|
||||
return InitializeAction.LAUNCH_INITIAL_REFRESH
|
||||
}
|
||||
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, User>
|
||||
): MediatorResult {
|
||||
val page = when (loadType) {
|
||||
LoadType.REFRESH -> {
|
||||
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
|
||||
remoteKeys?.nextKey?.minus(1) ?: 1
|
||||
}
|
||||
|
||||
LoadType.PREPEND -> {
|
||||
val remoteKeys = getRemoteKeyForFirstItem(state)
|
||||
remoteKeys?.prevKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
|
||||
LoadType.APPEND -> {
|
||||
val remoteKeys = getRemoteKeyForLastItem(state)
|
||||
remoteKeys?.nextKey
|
||||
?: return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
val coffees = service.getUsers(page, state.config.pageSize).map { it.toCoffee() }
|
||||
val endOfPaginationReached = coffees.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.User)
|
||||
dbUserRepository.clearCoffees()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
val keys = coffees.map {
|
||||
RemoteKeys(
|
||||
entityId = it.uid,
|
||||
type = RemoteKeyType.User,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
for (user in coffees) {
|
||||
dbUserRepository.insert()
|
||||
}
|
||||
}
|
||||
return MediatorResult.Success(endOfPaginationReached = endOfPaginationReached)
|
||||
} catch (exception: IOException) {
|
||||
return MediatorResult.Error(exception)
|
||||
} catch (exception: HttpException) {
|
||||
return MediatorResult.Error(exception)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyClosestToCurrentPosition(
|
||||
state: PagingState<Int, User>
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.uid?.let { userUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(userUid, RemoteKeyType.User)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -12,6 +12,11 @@ interface AppContainer {
|
||||
val coffeeRepository: CoffeeRepository
|
||||
val userRepository: UserRepository
|
||||
val cartRepository: CartRepository
|
||||
|
||||
companion object {
|
||||
const val TIMEOUT = 5000L
|
||||
const val LIMIT = 10
|
||||
}
|
||||
}
|
||||
|
||||
class AppDataContainer(private val context: Context) : AppContainer {
|
||||
@ -24,9 +29,4 @@ class AppDataContainer(private val context: Context) : AppContainer {
|
||||
override val cartRepository: CartRepository by lazy {
|
||||
OfflineCartRepository(AppDatabase.getInstance(context).cartDao())
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TIMEOUT = 5000L
|
||||
const val LIMIT = 10
|
||||
}
|
||||
}
|
@ -1,16 +1,24 @@
|
||||
package com.zyzf.coffeepreorder.database.dao
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import androidx.room.Update
|
||||
import com.zyzf.coffeepreorder.database.model.Cart
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
|
||||
@Dao
|
||||
interface CartDao {
|
||||
@Query("select * from cart limit 1")
|
||||
suspend fun get(): Cart
|
||||
|
||||
@Query("select * from coffee where cart_id is not null and count > 0 order by name collate nocase asc")
|
||||
fun getAllInCart(): PagingSource<Int, Coffee>
|
||||
|
||||
@Query("select sum(cost) from coffee where cart_id is not null and count > 0")
|
||||
fun getSumInCart(): Double
|
||||
|
||||
@Insert
|
||||
suspend fun insert(cart: Cart)
|
||||
|
||||
|
@ -5,28 +5,24 @@ import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Query
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.CoffeeWithCart
|
||||
|
||||
@Dao
|
||||
interface CoffeeDao {
|
||||
@Query("select * from coffee order by name collate nocase asc")
|
||||
fun getAll(): PagingSource<Int, Coffee>
|
||||
|
||||
@Query("select * from coffee where cart_id is not null and count > 0 order by name collate nocase asc")
|
||||
fun getAllInCart(): PagingSource<Int, Coffee>
|
||||
|
||||
@Query("select sum(cost) from coffee where cart_id is not null and count > 0")
|
||||
fun getSumInCart(): Double
|
||||
|
||||
@Query("select coffee.uid, name, cost, ingredients, cart_id, count, cart.uid as cart_uid from coffee left join cart on coffee.cart_id = cart.uid where coffee.uid = :uid")
|
||||
suspend fun getByUid(uid: Int): CoffeeWithCart?
|
||||
@Query("select coffee.uid, name, cost, ingredients, cart_id, count from coffee where coffee.uid = :uid")
|
||||
suspend fun getByUid(uid: Int): Coffee?
|
||||
|
||||
@Query("insert into coffee (name, cost, ingredients, count) values (:name, :cost, :ingredients, 0)")
|
||||
suspend fun insert(name: String, cost: Double, ingredients: String): Long
|
||||
suspend fun insert(name: String, cost: Double, ingredients: String): Int
|
||||
|
||||
@Query("update coffee set name = :name, cost = :cost, ingredients = :ingredients, cart_id = :cartId, count = :count where uid = :uid")
|
||||
suspend fun update(uid: Int, name: String, cost: Double, ingredients: String, cartId: Int?, count: Int): Int?
|
||||
|
||||
@Delete
|
||||
suspend fun delete(coffee: Coffee)
|
||||
|
||||
@Query("delete from coffee")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.zyzf.coffeepreorder.database.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeyType
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
|
||||
@Dao
|
||||
interface RemoteKeysDao {
|
||||
@Query("SELECT * FROM remote_keys WHERE entityId = :entityId AND type = :type")
|
||||
suspend fun getRemoteKeys(entityId: Int, type: RemoteKeyType): RemoteKeys?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insertAll(remoteKey: List<RemoteKeys>)
|
||||
|
||||
@Query("DELETE FROM remote_keys WHERE type = :type")
|
||||
suspend fun clearRemoteKeys(type: RemoteKeyType)
|
||||
}
|
@ -1,15 +1,17 @@
|
||||
package com.zyzf.coffeepreorder.database.dao
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.Query
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface UserDao {
|
||||
@Query("select * from user")
|
||||
fun getAll(): Flow<List<User>>
|
||||
fun getAll(): PagingSource<Int, User>
|
||||
|
||||
@Query("select * from user where login = :login and password = :password")
|
||||
suspend fun tryLogin(login: String, password: String): User?
|
||||
|
@ -1,11 +0,0 @@
|
||||
package com.zyzf.coffeepreorder.database.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Embedded
|
||||
|
||||
data class CoffeeWithCart(
|
||||
@Embedded
|
||||
val coffee: Coffee,
|
||||
@ColumnInfo(name = "cart_uid")
|
||||
val cartUid: Int
|
||||
)
|
@ -0,0 +1,26 @@
|
||||
package com.zyzf.coffeepreorder.database.model
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
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");
|
||||
|
||||
@TypeConverter
|
||||
fun toRemoteKeyType(value: String) = RemoteKeyType.values().first { it.type == value }
|
||||
|
||||
@TypeConverter
|
||||
fun fromRemoteKeyType(value: RemoteKeyType) = value.type
|
||||
}
|
||||
|
||||
@Entity(tableName = "remote_keys")
|
||||
data class RemoteKeys(
|
||||
@PrimaryKey val entityId: Int,
|
||||
@TypeConverters(RemoteKeyType::class)
|
||||
val type: RemoteKeyType,
|
||||
val prevKey: Int?,
|
||||
val nextKey: Int?
|
||||
)
|
@ -8,7 +8,7 @@ import androidx.room.PrimaryKey
|
||||
@Entity(tableName = "user")
|
||||
data class User(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
val uid: Int?,
|
||||
val uid: Int = 0,
|
||||
@ColumnInfo(name = "login")
|
||||
var login: String,
|
||||
@ColumnInfo(name = "fio")
|
||||
@ -27,7 +27,20 @@ data class User(
|
||||
phone: String,
|
||||
password: String,
|
||||
role: String
|
||||
) : this(null, login, fio, phone, password, role)
|
||||
) : this(0, login, fio, phone, password, role)
|
||||
|
||||
companion object {
|
||||
fun getUser(index: Int = 0): User {
|
||||
return User(
|
||||
index,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"user"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
@ -1,10 +1,15 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.model.Cart
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CartRepository {
|
||||
suspend fun get(): Cart
|
||||
suspend fun insert(cart: Cart)
|
||||
fun getAllInCart(): Flow<PagingData<Coffee>>
|
||||
fun getSumInCart(): Double
|
||||
suspend fun insertCoffee(cartId: Int, coffeeId: Int, count: Int)
|
||||
suspend fun deleteCoffee(coffeeId: Int, count: Int)
|
||||
suspend fun update(cart: Cart)
|
||||
|
@ -2,15 +2,12 @@ package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.CoffeeWithCart
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface CoffeeRepository {
|
||||
fun getAll(): Flow<PagingData<Coffee>>
|
||||
fun getAllInCart(): Flow<PagingData<Coffee>>
|
||||
fun getSumInCart(): Double
|
||||
suspend fun getByUid(uid: Int): CoffeeWithCart?
|
||||
suspend fun insert(name: String, cost: Double, ingredients: String): Long
|
||||
suspend fun getByUid(uid: Int): Coffee?
|
||||
suspend fun insert(name: String, cost: Double, ingredients: String): Int
|
||||
suspend fun update(uid: Int, name: String, cost: Double, ingredients: String, cartId: Int?, count: Int): Int?
|
||||
suspend fun delete(coffee: Coffee)
|
||||
}
|
@ -1,9 +1,23 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.dao.CartDao
|
||||
import com.zyzf.coffeepreorder.database.model.Cart
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineCartRepository(private val cartDao: CartDao) : CartRepository {
|
||||
override fun getAllInCart(): Flow<PagingData<Coffee>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = cartDao::getAllInCart
|
||||
).flow
|
||||
override fun getSumInCart(): Double = cartDao.getSumInCart()
|
||||
override suspend fun get(): Cart = cartDao.get()
|
||||
override suspend fun insert(cart: Cart) = cartDao.insert(cart)
|
||||
override suspend fun insertCoffee(cartId: Int, coffeeId: Int, count: Int) = cartDao.insertCoffee(cartId, coffeeId, count)
|
||||
|
@ -3,30 +3,25 @@ package com.zyzf.coffeepreorder.database.repository
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.AppDataContainer
|
||||
import androidx.paging.PagingSource
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.dao.CoffeeDao
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.CoffeeWithCart
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineCoffeeRepository(private val coffeeDao: CoffeeDao) : CoffeeRepository {
|
||||
override fun getAll(): Flow<PagingData<Coffee>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppDataContainer.LIMIT,
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = coffeeDao::getAll
|
||||
).flow
|
||||
override fun getAllInCart(): Flow<PagingData<Coffee>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppDataContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = coffeeDao::getAllInCart
|
||||
).flow
|
||||
override fun getSumInCart(): Double = coffeeDao.getSumInCart()
|
||||
override suspend fun getByUid(uid: Int): CoffeeWithCart? = coffeeDao.getByUid(uid)
|
||||
override suspend fun insert(name: String, cost: Double, ingredients: String): Long = coffeeDao.insert(name, cost, ingredients)
|
||||
|
||||
fun getAllCoffeesPagingSource(): PagingSource<Int, Coffee> = coffeeDao.getAll()
|
||||
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): Int = coffeeDao.insert(name, cost, ingredients)
|
||||
override suspend fun update(uid: Int, name: String, cost: Double, ingredients: String, cartId: Int?, count: Int): Int? = coffeeDao.update(uid, name, cost, ingredients, cartId, count)
|
||||
override suspend fun delete(coffee: Coffee) = coffeeDao.delete(coffee)
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import com.zyzf.coffeepreorder.database.dao.RemoteKeysDao
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeyType
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
|
||||
class OfflineRemoteKeyRepository(private val remoteKeysDao: RemoteKeysDao) : RemoteKeyRepository {
|
||||
override suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType) =
|
||||
remoteKeysDao.getRemoteKeys(id, type)
|
||||
|
||||
override suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>) =
|
||||
remoteKeysDao.insertAll(remoteKeys)
|
||||
|
||||
override suspend fun deleteRemoteKey(type: RemoteKeyType) =
|
||||
remoteKeysDao.clearRemoteKeys(type)
|
||||
}
|
@ -1,11 +1,24 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import com.zyzf.coffeepreorder.database.AppContainer
|
||||
import com.zyzf.coffeepreorder.database.dao.UserDao
|
||||
import com.zyzf.coffeepreorder.database.model.Coffee
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class OfflineUserRepository(private val userDao: UserDao) : UserRepository {
|
||||
override fun getAll(): Flow<List<User>> = userDao.getAll()
|
||||
override fun getAll(): Flow<PagingData<User>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = userDao::getAll
|
||||
).flow
|
||||
fun getAllUserPagingSource(): PagingSource<Int, User> = userDao.getAll()
|
||||
override suspend fun tryLogin(login: String, password: String): User? = userDao.tryLogin(login, password)
|
||||
override suspend fun getByUid(uid: Int): User? = userDao.getByUid(uid)
|
||||
override suspend fun getLogined(): User? = userDao.getLogined()
|
||||
|
@ -0,0 +1,10 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeyType
|
||||
import com.zyzf.coffeepreorder.database.model.RemoteKeys
|
||||
|
||||
interface RemoteKeyRepository {
|
||||
suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys?
|
||||
suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>)
|
||||
suspend fun deleteRemoteKey(type: RemoteKeyType)
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package com.zyzf.coffeepreorder.database.repository
|
||||
|
||||
import androidx.paging.PagingData
|
||||
import com.zyzf.coffeepreorder.database.model.User
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface UserRepository {
|
||||
fun getAll(): Flow<List<User>>
|
||||
fun getAll(): Flow<PagingData<User>>
|
||||
suspend fun tryLogin(login: String, password: String): User?
|
||||
suspend fun getByUid(uid: Int): User?
|
||||
suspend fun getLogined(): User?
|
||||
|
@ -8,10 +8,9 @@ import com.zyzf.coffeepreorder.database.repository.CoffeeRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class CartViewModel(
|
||||
private val coffeeRepository: CoffeeRepository,
|
||||
private val cartRepository: CartRepository
|
||||
) : ViewModel() {
|
||||
val coffeeListUiState: Flow<PagingData<Coffee>> = coffeeRepository.getAllInCart()
|
||||
val coffeeListUiState: Flow<PagingData<Coffee>> = cartRepository.getAllInCart()
|
||||
|
||||
suspend fun deleteCoffeeFromCart(coffee: Coffee) {
|
||||
cartRepository.deleteCoffee(coffee.uid, 1)
|
||||
|
@ -36,7 +36,7 @@ class CoffeeListViewModel(
|
||||
cart.uid?.let { cartRepository.insertCoffee(it, coffeeUid, 1) }
|
||||
}
|
||||
suspend fun createCoffee(coffee: Coffee, imageUri: Uri, context: Context) {
|
||||
val newCoffee: Long = coffeeRepository.insert(coffee.name, coffee.cost, coffee.ingredients)
|
||||
val newCoffee: Int = coffeeRepository.insert(coffee.name, coffee.cost, coffee.ingredients)
|
||||
val inputStream = context.contentResolver.openInputStream(imageUri)
|
||||
val bitmap = BitmapFactory.decodeStream(inputStream)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user