some beginning

This commit is contained in:
zyzf 2023-12-11 20:49:31 +04:00
parent 638b9d6aaf
commit 7c3af23e3b
26 changed files with 629 additions and 53 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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