Feature: add pagging, connect to API
This commit is contained in:
parent
2f99f363c0
commit
6b41efd82e
@ -2,6 +2,7 @@ plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id ("kotlin-kapt")
|
||||
kotlin("plugin.serialization") version "1.4.21"
|
||||
}
|
||||
|
||||
android {
|
||||
|
@ -1,13 +1,20 @@
|
||||
package com.example.android_programming
|
||||
|
||||
import com.example.android_programming.api.repository.RestSneakerRepository
|
||||
import com.example.android_programming.api.repository.RestUserRepository
|
||||
import com.example.android_programming.repository.BasketRepository
|
||||
import com.example.android_programming.repository.OrderRepository
|
||||
import com.example.android_programming.repository.SneakerRepository
|
||||
import com.example.android_programming.repository.UserRepository
|
||||
|
||||
interface AppContainer {
|
||||
val sneakerRepo: SneakerRepository
|
||||
val userRepo: UserRepository
|
||||
val sneakerRepo: RestSneakerRepository
|
||||
val userRepo: RestUserRepository
|
||||
val orderRepo: OrderRepository
|
||||
val basketRepo: BasketRepository
|
||||
|
||||
companion object {
|
||||
const val TIMEOUT = 5000L
|
||||
const val LIMIT = 10
|
||||
}
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
package com.example.android_programming
|
||||
|
||||
import android.content.Context
|
||||
import com.example.android_programming.api.BackendService
|
||||
import com.example.android_programming.api.repository.RestSneakerRepository
|
||||
import com.example.android_programming.api.repository.RestUserRepository
|
||||
import com.example.android_programming.database.AppDatabase
|
||||
import com.example.android_programming.database.remotekeys.repository.RemoteKeysRepositoryImpl
|
||||
import com.example.android_programming.repository.BasketRepoImpl
|
||||
import com.example.android_programming.repository.BasketRepository
|
||||
import com.example.android_programming.repository.OrderRepoImpl
|
||||
@ -12,11 +16,16 @@ import com.example.android_programming.repository.UserRepoImpl
|
||||
import com.example.android_programming.repository.UserRepository
|
||||
|
||||
class AppDataContainer(private val context: Context) : AppContainer {
|
||||
override val sneakerRepo: SneakerRepository by lazy {
|
||||
SneakerRepoImpl(AppDatabase.getInstance(context).sneakerDao())
|
||||
override val sneakerRepo: RestSneakerRepository by lazy {
|
||||
RestSneakerRepository(
|
||||
BackendService.getInstance(),
|
||||
sneakerRepository,
|
||||
AppDatabase.getInstance(context),
|
||||
remoteKeyRepository
|
||||
)
|
||||
}
|
||||
override val userRepo: UserRepository by lazy {
|
||||
UserRepoImpl(AppDatabase.getInstance(context).userDao())
|
||||
override val userRepo: RestUserRepository by lazy {
|
||||
RestUserRepository(BackendService.getInstance())
|
||||
}
|
||||
override val orderRepo: OrderRepository by lazy {
|
||||
OrderRepoImpl(AppDatabase.getInstance(context).orderDao())
|
||||
@ -24,4 +33,10 @@ class AppDataContainer(private val context: Context) : AppContainer {
|
||||
override val basketRepo: BasketRepository by lazy {
|
||||
BasketRepoImpl(AppDatabase.getInstance(context).basketDao())
|
||||
}
|
||||
private val sneakerRepository: SneakerRepoImpl by lazy {
|
||||
SneakerRepoImpl(AppDatabase.getInstance(context).sneakerDao())
|
||||
}
|
||||
private val remoteKeyRepository: RemoteKeysRepositoryImpl by lazy {
|
||||
RemoteKeysRepositoryImpl(AppDatabase.getInstance(context).remoteKeysDao())
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.example.android_programming.api
|
||||
|
||||
import com.example.android_programming.api.model.SneakerRemote
|
||||
import com.example.android_programming.api.model.UserRemote
|
||||
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.http.Path
|
||||
import retrofit2.http.Query
|
||||
|
||||
interface BackendService {
|
||||
|
||||
//SNEAKER
|
||||
@GET("sneaker/get/{id}")
|
||||
suspend fun getSneaker(
|
||||
@Path("id") id: Int,
|
||||
): SneakerRemote
|
||||
|
||||
@GET("sneaker/getAll")
|
||||
suspend fun getSneakers(
|
||||
@Query("page") page: Int,
|
||||
@Query("size") size: Int,
|
||||
): List<SneakerRemote>
|
||||
|
||||
//USER
|
||||
@POST("user/signup")
|
||||
suspend fun SignUp(
|
||||
@Body user: UserRemote,
|
||||
): UserRemote
|
||||
|
||||
companion object {
|
||||
private const val BASE_URL = "https://59k4pfj3-8080.euw.devtunnels.ms/api/"
|
||||
|
||||
@Volatile
|
||||
private var INSTANCE: BackendService? = null
|
||||
|
||||
fun getInstance(): BackendService {
|
||||
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(BackendService::class.java)
|
||||
.also { INSTANCE = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
package com.example.android_programming.api
|
||||
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.LoadType
|
||||
import androidx.paging.PagingState
|
||||
import androidx.paging.RemoteMediator
|
||||
import androidx.room.withTransaction
|
||||
import com.example.android_programming.api.model.toSneaker
|
||||
import com.example.android_programming.api.repository.RestSneakerRepository
|
||||
import com.example.android_programming.database.AppDatabase
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeys
|
||||
import com.example.android_programming.database.remotekeys.repository.RemoteKeyRepository
|
||||
import com.example.android_programming.database.remotekeys.repository.RemoteKeysRepositoryImpl
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import com.example.android_programming.repository.SneakerRepoImpl
|
||||
import com.example.android_programming.repository.SneakerRepository
|
||||
import retrofit2.HttpException
|
||||
import java.io.IOException
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
class SneakerRemoteMediator(
|
||||
private val service: BackendService,
|
||||
private val sneakerRepository: SneakerRepoImpl,
|
||||
private val database: AppDatabase,
|
||||
private val dbRemoteKeyRepository:RemoteKeysRepositoryImpl
|
||||
) : RemoteMediator<Int, Sneaker>() {
|
||||
override suspend fun initialize(): InitializeAction {
|
||||
return InitializeAction.LAUNCH_INITIAL_REFRESH
|
||||
}
|
||||
override suspend fun load(
|
||||
loadType: LoadType,
|
||||
state: PagingState<Int, Sneaker>
|
||||
): 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 sneakers = service.getSneakers(page, state.config.pageSize).map { it.toSneaker() }
|
||||
val endOfPaginationReached = sneakers.isEmpty()
|
||||
database.withTransaction {
|
||||
if (loadType == LoadType.REFRESH) {
|
||||
dbRemoteKeyRepository.deleteRemoteKey(RemoteKeyType.SNEAKER)
|
||||
sneakerRepository.clearSneakers()
|
||||
}
|
||||
val prevKey = if (page == 1) null else page - 1
|
||||
val nextKey = if (endOfPaginationReached) null else page + 1
|
||||
val keys = sneakers.map {
|
||||
RemoteKeys(
|
||||
entityId = it.sneakerId!!,
|
||||
type = RemoteKeyType.SNEAKER,
|
||||
prevKey = prevKey,
|
||||
nextKey = nextKey
|
||||
)
|
||||
}
|
||||
dbRemoteKeyRepository.createRemoteKeys(keys)
|
||||
sneakerRepository.insertSneakers(sneakers)
|
||||
}
|
||||
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, Sneaker>): RemoteKeys? {
|
||||
return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull()
|
||||
?.let { sneaker ->
|
||||
sneaker.sneakerId?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.SNEAKER) }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Sneaker>): RemoteKeys? {
|
||||
return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull()
|
||||
?.let { sneaker ->
|
||||
sneaker.sneakerId?.let { dbRemoteKeyRepository.getAllRemoteKeys(it, RemoteKeyType.SNEAKER) }
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getRemoteKeyClosestToCurrentPosition(
|
||||
state: PagingState<Int, Sneaker>
|
||||
): RemoteKeys? {
|
||||
return state.anchorPosition?.let { position ->
|
||||
state.closestItemToPosition(position)?.sneakerId?.let { sneakerUid ->
|
||||
dbRemoteKeyRepository.getAllRemoteKeys(sneakerUid, RemoteKeyType.SNEAKER)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.example.android_programming.api.model
|
||||
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SneakerRemote (
|
||||
val id: Int? = 0,
|
||||
val brand: String = "",
|
||||
val model: String = "",
|
||||
val description: String = "",
|
||||
val price: Double = 0.0,
|
||||
val photo: Int = 0
|
||||
)
|
||||
|
||||
fun SneakerRemote.toSneaker():Sneaker = Sneaker(
|
||||
id,
|
||||
brand,
|
||||
model,
|
||||
description,
|
||||
price,
|
||||
photo
|
||||
)
|
||||
|
||||
fun Sneaker.toSneakerRemote():SneakerRemote = SneakerRemote(
|
||||
sneakerId,
|
||||
brand,
|
||||
model,
|
||||
description,
|
||||
price,
|
||||
photo
|
||||
)
|
@ -0,0 +1,39 @@
|
||||
package com.example.android_programming.api.model
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.PrimaryKey
|
||||
import com.example.android_programming.model.RoleEnum
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import com.example.android_programming.model.User
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class UserRemote (
|
||||
val id: Int? = 0,
|
||||
val name: String = "",
|
||||
val surname: String = "",
|
||||
val email: String = "",
|
||||
val password: String = "",
|
||||
val role: RoleEnum = RoleEnum.User,
|
||||
val photo: Int? = 0,
|
||||
)
|
||||
|
||||
fun UserRemote.toUser(): User = User(
|
||||
id,
|
||||
name,
|
||||
surname,
|
||||
email,
|
||||
password,
|
||||
role,
|
||||
photo
|
||||
)
|
||||
|
||||
fun User.toUserRemote():UserRemote = UserRemote(
|
||||
userId,
|
||||
name,
|
||||
surname,
|
||||
email,
|
||||
password,
|
||||
role,
|
||||
photo
|
||||
)
|
@ -0,0 +1,59 @@
|
||||
package com.example.android_programming.api.repository
|
||||
|
||||
import android.util.Log
|
||||
import androidx.paging.ExperimentalPagingApi
|
||||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import com.example.android_programming.AppContainer
|
||||
import com.example.android_programming.api.BackendService
|
||||
import com.example.android_programming.api.SneakerRemoteMediator
|
||||
import com.example.android_programming.api.model.toSneaker
|
||||
import com.example.android_programming.database.AppDatabase
|
||||
import com.example.android_programming.database.remotekeys.repository.RemoteKeysRepositoryImpl
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import com.example.android_programming.repository.SneakerRepoImpl
|
||||
import com.example.android_programming.repository.SneakerRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class RestSneakerRepository(
|
||||
private val service: BackendService,
|
||||
private val dbSneakerRepository: SneakerRepoImpl,
|
||||
private val database: AppDatabase,
|
||||
private val dbRemoteKeyRepository: RemoteKeysRepositoryImpl
|
||||
|
||||
) : SneakerRepository {
|
||||
|
||||
override fun getAllSneakers(): Flow<PagingData<Sneaker>> {
|
||||
val pagingSourceFactory = { dbSneakerRepository.getAllSneakersPagingSource() }
|
||||
|
||||
@OptIn(ExperimentalPagingApi::class)
|
||||
return Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
remoteMediator = SneakerRemoteMediator(
|
||||
service,
|
||||
dbSneakerRepository,
|
||||
database,
|
||||
dbRemoteKeyRepository,
|
||||
),
|
||||
pagingSourceFactory = pagingSourceFactory
|
||||
).flow
|
||||
}
|
||||
|
||||
override suspend fun getSneakerById(id: Int): Sneaker = service.getSneaker(id).toSneaker()
|
||||
override suspend fun insertSneaker(sneaker: Sneaker) {
|
||||
print("sdfsd")
|
||||
}
|
||||
|
||||
override suspend fun updateSneaker(sneaker: Sneaker) {
|
||||
print("sdfsd")
|
||||
}
|
||||
|
||||
override suspend fun deleteSneaker(sneaker: Sneaker) {
|
||||
print("sdfsd")
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.example.android_programming.api.repository
|
||||
|
||||
import com.example.android_programming.api.BackendService
|
||||
import com.example.android_programming.api.model.toUserRemote
|
||||
import com.example.android_programming.model.User
|
||||
import com.example.android_programming.repository.UserRepository
|
||||
|
||||
class RestUserRepository(
|
||||
private var service: BackendService
|
||||
): UserRepository {
|
||||
override suspend fun createUser(user: User) {
|
||||
val user1 = user.toUserRemote()
|
||||
service.SignUp(user1)
|
||||
}
|
||||
|
||||
override suspend fun updateUser(user: User) {
|
||||
println()
|
||||
}
|
||||
|
||||
override suspend fun deleteUser(user: User) {
|
||||
println()
|
||||
}
|
||||
|
||||
}
|
@ -36,7 +36,7 @@ import kotlinx.coroutines.delay
|
||||
|
||||
@Composable
|
||||
fun ChangePanel(navHostController: NavHostController, sneakerViewModel: SneakerViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
|
||||
val list = sneakerViewModel.sneakerList.collectAsLazyPagingItems()
|
||||
// val list = sneakerViewModel.sneakerList.collectAsLazyPagingItems()
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
@ -44,18 +44,18 @@ fun ChangePanel(navHostController: NavHostController, sneakerViewModel: SneakerV
|
||||
.background(Color.White)
|
||||
.padding(16.dp, 80.dp)
|
||||
) {
|
||||
Row {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
items(list.itemCount) { index ->
|
||||
list[index]?.let { sneaker ->
|
||||
CardSneakerForChange(item = sneaker, navController = navHostController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Row {
|
||||
// LazyColumn(
|
||||
// modifier = Modifier
|
||||
// .fillMaxSize()
|
||||
// ) {
|
||||
// items(list.itemCount) { index ->
|
||||
// list[index]?.let { sneaker ->
|
||||
// CardSneakerForChange(item = sneaker, navController = navHostController)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,17 +5,28 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.example.android_programming.R
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import com.example.android_programming.vmodel.AppViewModelProvider
|
||||
import com.example.android_programming.vmodel.OrderViewModel
|
||||
import com.example.android_programming.vmodel.SneakerViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
|
||||
@Composable
|
||||
fun RecyclerView(navHostController: NavHostController, sneakerViewModel: SneakerViewModel = viewModel(factory = AppViewModelProvider.Factory)) {
|
||||
|
@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
@Dao
|
||||
interface SneakerDao {
|
||||
@Insert
|
||||
suspend fun insert(sneaker: Sneaker)
|
||||
suspend fun insert(vararg sneaker: Sneaker)
|
||||
|
||||
@Update
|
||||
suspend fun update(sneaker: Sneaker)
|
||||
@ -22,7 +22,10 @@ interface SneakerDao {
|
||||
|
||||
@Query("SELECT*FROM Sneaker")
|
||||
fun getAllSneakersPaged(): PagingSource<Int, Sneaker>
|
||||
|
||||
@Query("select * from Sneaker")
|
||||
fun getAll(): PagingSource<Int, Sneaker>
|
||||
@Query("SELECT * FROM Sneaker WHERE sneakerId = :id")
|
||||
suspend fun getSneakerById(id: Int): Sneaker
|
||||
@Query("DELETE FROM Sneaker")
|
||||
suspend fun deleteAll()
|
||||
}
|
@ -10,6 +10,8 @@ import com.example.android_programming.dao.BasketDao
|
||||
import com.example.android_programming.dao.OrderDao
|
||||
import com.example.android_programming.dao.SneakerDao
|
||||
import com.example.android_programming.dao.UserDao
|
||||
import com.example.android_programming.database.remotekeys.dao.RemoteKeysDao
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeys
|
||||
import com.example.android_programming.model.Basket
|
||||
import com.example.android_programming.model.BasketSneakers
|
||||
import com.example.android_programming.model.Order
|
||||
@ -21,12 +23,13 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Database(entities = [Sneaker::class, User::class, Order::class, OrderSneaker::class, Basket::class, BasketSneakers::class], version = 6)
|
||||
@Database(entities = [Sneaker::class, User::class, Order::class, OrderSneaker::class, Basket::class, BasketSneakers::class, RemoteKeys::class], version = 7)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun sneakerDao(): SneakerDao
|
||||
abstract fun userDao(): UserDao
|
||||
abstract fun orderDao(): OrderDao
|
||||
abstract fun basketDao(): BasketDao
|
||||
abstract fun remoteKeysDao(): RemoteKeysDao
|
||||
|
||||
companion object {
|
||||
private const val DB_NAME: String = "my-db"
|
||||
|
@ -0,0 +1,18 @@
|
||||
package com.example.android_programming.database.remotekeys.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
|
||||
import com.example.android_programming.database.remotekeys.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)
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.example.android_programming.database.remotekeys.model
|
||||
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room.TypeConverter
|
||||
import androidx.room.TypeConverters
|
||||
import com.example.android_programming.model.Sneaker
|
||||
|
||||
enum class RemoteKeyType(private val type: String) {
|
||||
SNEAKER(Sneaker::class.simpleName ?: "Sneaker");
|
||||
@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?
|
||||
)
|
@ -0,0 +1,10 @@
|
||||
package com.example.android_programming.database.remotekeys.repository
|
||||
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeys
|
||||
|
||||
interface RemoteKeyRepository {
|
||||
suspend fun getAllRemoteKeys(id: Int, type: RemoteKeyType): RemoteKeys?
|
||||
suspend fun createRemoteKeys(remoteKeys: List<RemoteKeys>)
|
||||
suspend fun deleteRemoteKey(type: RemoteKeyType)
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.example.android_programming.database.remotekeys.repository
|
||||
|
||||
import com.example.android_programming.database.remotekeys.dao.RemoteKeysDao
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeyType
|
||||
import com.example.android_programming.database.remotekeys.model.RemoteKeys
|
||||
|
||||
class RemoteKeysRepositoryImpl(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)
|
||||
}
|
@ -5,6 +5,7 @@ import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.cachedIn
|
||||
import com.example.android_programming.AppContainer
|
||||
import com.example.android_programming.dao.SneakerDao
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@ -18,12 +19,25 @@ class SneakerRepoImpl(private val sneakerDao: SneakerDao) : SneakerRepository {
|
||||
override suspend fun deleteSneaker(sneaker: Sneaker) = sneakerDao.delete(sneaker)
|
||||
|
||||
override suspend fun getSneakerById(id: Int): Sneaker = sneakerDao.getSneakerById(id)
|
||||
override fun getAllSneakersPaged(): PagingSource<Int, Sneaker> = sneakerDao.getAllSneakersPaged()
|
||||
override fun call(): Flow<PagingData<Sneaker>> {
|
||||
return Pager(
|
||||
PagingConfig(pageSize = 5)
|
||||
) {
|
||||
sneakerDao.getAllSneakersPaged()
|
||||
}.flow
|
||||
}
|
||||
override fun getAllSneakers(): Flow<PagingData<Sneaker>> = Pager(
|
||||
config = PagingConfig(
|
||||
pageSize = AppContainer.LIMIT,
|
||||
enablePlaceholders = false
|
||||
),
|
||||
pagingSourceFactory = sneakerDao::getAll
|
||||
).flow
|
||||
|
||||
suspend fun clearSneakers() = sneakerDao.deleteAll()
|
||||
suspend fun insertSneakers(sneakers: List<Sneaker>) =
|
||||
sneakerDao.insert(*sneakers.toTypedArray())
|
||||
|
||||
fun getAllSneakersPagingSource(): PagingSource<Int, Sneaker> = sneakerDao.getAll()
|
||||
// override fun getAllSneakersPaged(): PagingSource<Int, Sneaker> = sneakerDao.getAllSneakersPaged()
|
||||
// override fun call(): Flow<PagingData<Sneaker>> {
|
||||
// return Pager(
|
||||
// PagingConfig(pageSize = 5)
|
||||
// ) {
|
||||
// sneakerDao.getAllSneakersPaged()
|
||||
// }.flow
|
||||
// }
|
||||
}
|
@ -10,6 +10,5 @@ interface SneakerRepository {
|
||||
suspend fun updateSneaker(sneaker: Sneaker)
|
||||
suspend fun deleteSneaker(sneaker: Sneaker)
|
||||
suspend fun getSneakerById(id: Int): Sneaker
|
||||
fun getAllSneakersPaged(): PagingSource<Int, Sneaker>
|
||||
fun call(): Flow<PagingData<Sneaker>>
|
||||
fun getAllSneakers(): Flow<PagingData<Sneaker>>
|
||||
}
|
@ -13,7 +13,7 @@ class UserRepoImpl(private val userDao: UserDao) : UserRepository {
|
||||
|
||||
override suspend fun deleteUser(user: User) = userDao.deleteUser(user)
|
||||
|
||||
override suspend fun getUserById(id: Int): User = userDao.getUserById(id)
|
||||
|
||||
override suspend fun getUserByEmail(email: String): User = userDao.getUserByEmail(email)
|
||||
// override suspend fun getUserById(id: Int): User = userDao.getUserById(id)
|
||||
//
|
||||
// override suspend fun getUserByEmail(email: String): User = userDao.getUserByEmail(email)
|
||||
}
|
@ -9,6 +9,6 @@ interface UserRepository {
|
||||
suspend fun createUser(user: User)
|
||||
suspend fun updateUser(user: User)
|
||||
suspend fun deleteUser(user: User)
|
||||
suspend fun getUserById(id: Int): User
|
||||
suspend fun getUserByEmail(email: String): User
|
||||
// suspend fun getUserById(id: Int): User
|
||||
// suspend fun getUserByEmail(email: String): User
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.example.android_programming.vmodel
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
@ -14,22 +16,27 @@ import androidx.paging.cachedIn
|
||||
import androidx.paging.map
|
||||
import com.example.android_programming.App
|
||||
import com.example.android_programming.R
|
||||
import com.example.android_programming.api.model.toSneakerRemote
|
||||
import com.example.android_programming.api.repository.RestSneakerRepository
|
||||
import com.example.android_programming.database.AppDatabase
|
||||
import com.example.android_programming.model.Sneaker
|
||||
import com.example.android_programming.repository.SneakerRepository
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SneakerViewModel(private val sneakerRepository: SneakerRepository): ViewModel() {
|
||||
class SneakerViewModel(private val sneakerRepository: RestSneakerRepository): ViewModel() {
|
||||
val sneakerList = sneakerRepository.getAllSneakers()
|
||||
var brand = mutableStateOf("")
|
||||
val model = mutableStateOf("")
|
||||
val description = mutableStateOf("")
|
||||
val price = mutableStateOf("")
|
||||
val photo = mutableIntStateOf(R.drawable.img)
|
||||
val sneakerList = sneakerRepository.call().cachedIn(viewModelScope)
|
||||
var sneaker: Sneaker? = null
|
||||
|
||||
private var _record = MutableStateFlow<Sneaker?>(null)
|
||||
var record: StateFlow<Sneaker?> = _record
|
||||
fun insertSneaker() = viewModelScope.launch {
|
||||
val sneaker = Sneaker(
|
||||
brand = brand.value,
|
||||
@ -45,10 +52,6 @@ class SneakerViewModel(private val sneakerRepository: SneakerRepository): ViewMo
|
||||
sneakerRepository.deleteSneaker(sneaker)
|
||||
}
|
||||
|
||||
fun getSneakerById(id: Int) = viewModelScope.launch {
|
||||
sneakerRepository.getSneakerById(id)
|
||||
}
|
||||
|
||||
fun UpdateSneaker(sneaker: Sneaker) = viewModelScope.launch {
|
||||
sneakerRepository.updateSneaker(sneaker)
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.CreationExtras
|
||||
import com.example.android_programming.App
|
||||
import com.example.android_programming.GlobalUser
|
||||
import com.example.android_programming.R
|
||||
import com.example.android_programming.database.AppDatabase
|
||||
import com.example.android_programming.model.Basket
|
||||
import com.example.android_programming.model.RoleEnum
|
||||
@ -28,16 +29,17 @@ class UserViewModel(private val userRepository: UserRepository): ViewModel() {
|
||||
surname = surname.value,
|
||||
email = email.value,
|
||||
password = password.value,
|
||||
role = RoleEnum.User
|
||||
role = RoleEnum.User,
|
||||
photo = R.drawable.shailushai
|
||||
)
|
||||
userRepository.createUser(user)
|
||||
}
|
||||
fun authUser() = viewModelScope.launch {
|
||||
val user = userRepository.getUserByEmail(email.value)
|
||||
if (password.value != "" && user.password == password.value) {
|
||||
val globalUser = GlobalUser.getInstance()
|
||||
globalUser.setUser(user)
|
||||
}
|
||||
// val user = userRepository.getUserByEmail(email.value)
|
||||
// if (password.value != "" && user.password == password.value) {
|
||||
// val globalUser = GlobalUser.getInstance()
|
||||
// globalUser.setUser(user)
|
||||
// }
|
||||
}
|
||||
|
||||
fun isValidEmail(email: String): Boolean {
|
||||
|
Loading…
x
Reference in New Issue
Block a user