account's info on profile screen; storing users into cache

This commit is contained in:
2024-07-12 23:20:24 +03:00
parent eef90a06ea
commit 25acc6505b
14 changed files with 374 additions and 120 deletions
@@ -42,12 +42,22 @@ inline fun <T> State<T>.processState(
success: (data: T) -> (Unit),
idle: (() -> (Unit)) = {},
loading: (() -> (Unit)) = {},
any: () -> Unit = {}
) {
when (this) {
is State.Error -> error(this)
is State.Error -> {
error(this)
any()
}
State.Idle -> idle()
State.Loading -> loading()
is State.Success -> success(data)
is State.Success -> {
success(data)
any()
}
}
}
@@ -1,8 +1,18 @@
package com.meloda.app.fast.data.api.users
import com.meloda.app.fast.model.api.data.VkUserData
import com.meloda.app.fast.model.api.requests.UsersGetRequest
import com.meloda.app.fast.model.api.domain.VkUser
import com.meloda.app.fast.network.RestApiErrorDomain
import com.slack.eithernet.ApiResult
interface UsersRepository {
suspend fun getById(params: UsersGetRequest): List<VkUserData>
suspend fun get(
userIds: List<Int>?,
fields: String?,
nomCase: String?
): ApiResult<List<VkUser>, RestApiErrorDomain>
suspend fun getLocalUsers(userIds: List<Int>): List<VkUser>
suspend fun storeUsers(users: List<VkUser>)
}
@@ -1,16 +1,62 @@
package com.meloda.app.fast.data.api.users
import com.meloda.app.fast.data.VkMemoryCache
import com.meloda.app.fast.database.dao.UsersDao
import com.meloda.app.fast.model.api.data.VkUserData
import com.meloda.app.fast.model.api.domain.VkUser
import com.meloda.app.fast.model.api.domain.asEntity
import com.meloda.app.fast.model.api.requests.UsersGetRequest
import com.meloda.app.fast.model.database.VkUserEntity
import com.meloda.app.fast.model.database.asExternalModel
import com.meloda.app.fast.network.RestApiErrorDomain
import com.meloda.app.fast.network.mapApiResult
import com.meloda.app.fast.network.service.users.UsersService
import com.slack.eithernet.ApiResult
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class UsersRepositoryImpl(
private val usersService: UsersService
private val service: UsersService,
private val dao: UsersDao
) : UsersRepository {
override suspend fun getById(params: UsersGetRequest): List<VkUserData> {
// TODO: 05/05/2024, Danil Nikolaev: implement
override suspend fun get(
userIds: List<Int>?,
fields: String?,
nomCase: String?
): ApiResult<List<VkUser>, RestApiErrorDomain> = withContext(Dispatchers.IO) {
val requestModel = UsersGetRequest(
userIds = userIds,
fields = fields,
nomCase = nomCase
)
return emptyList()
service.get(requestModel.map).mapApiResult(
successMapper = { apiResponse ->
val response = apiResponse.requireResponse()
val users = response.map(VkUserData::mapToDomain)
launch { storeUsers(users) }
VkMemoryCache.appendUsers(users)
users
},
errorMapper = { error ->
error?.toDomain()
}
)
}
override suspend fun getLocalUsers(
userIds: List<Int>
): List<VkUser> = withContext(Dispatchers.IO) {
dao.getAllByIds(userIds).map(VkUserEntity::asExternalModel)
}
override suspend fun storeUsers(users: List<VkUser>) {
dao.insertAll(users.map(VkUser::asEntity))
}
}
@@ -6,18 +6,14 @@ import kotlinx.coroutines.flow.Flow
interface UsersUseCase {
fun getUserById(
userId: Int,
fields: String?,
nomCase: String?
): Flow<State<VkUser?>>
fun getUsersByIds(
userIds: List<Int>,
fun get(
userIds: List<Int>?,
fields: String?,
nomCase: String?
): Flow<State<List<VkUser>>>
fun getLocalUser(userId: Int): Flow<State<VkUser?>>
suspend fun storeUser(user: VkUser)
suspend fun storeUsers(users: List<VkUser>)
}
@@ -1,67 +1,39 @@
package com.meloda.app.fast.data.api.users
import com.meloda.app.fast.data.State
import com.meloda.app.fast.data.mapToState
import com.meloda.app.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
// TODO: 05/05/2024, Danil Nikolaev: implement
class UsersUseCaseImpl(
private val usersRepository: UsersRepository,
private val repository: UsersRepository,
) : UsersUseCase {
override fun getUserById(
userId: Int,
fields: String?,
nomCase: String?
): Flow<State<VkUser?>> = flow {
// emit(State.Loading)
//
// val newState = usersRepository.getById(
// UsersGetRequest(
// userIds = listOf(userId),
// fields = fields,
// nomCase = nomCase
// )
// ).fold(
// onSuccess = { response -> State.Success(response.singleOrNull()?.mapToDomain()) },
// onNetworkFailure = { State.Error.ConnectionError },
// onUnknownFailure = { State.UNKNOWN_ERROR },
// onHttpFailure = { result -> result.error.toStateApiError() },
// onApiFailure = { result -> result.error.toStateApiError() }
// )
// emit(newState)
}
override fun getUsersByIds(
userIds: List<Int>,
override fun get(
userIds: List<Int>?,
fields: String?,
nomCase: String?
): Flow<State<List<VkUser>>> = flow {
// emit(State.Loading)
//
// val newState = usersRepository.getById(
// UsersGetRequest(
// userIds = userIds,
// fields = fields,
// nomCase = nomCase
// )
// ).fold(
// onSuccess = { response -> State.Success(response.map(VkUserData::mapToDomain)) },
// onNetworkFailure = { State.Error.ConnectionError },
// onUnknownFailure = { State.UNKNOWN_ERROR },
// onHttpFailure = { result -> result.error.toStateApiError() },
// onApiFailure = { result -> result.error.toStateApiError() }
// )
// emit(newState)
emit(State.Loading)
val newState = repository.get(userIds, fields, nomCase).mapToState()
emit(newState)
}
override suspend fun storeUser(user: VkUser) {
override fun getLocalUser(userId: Int): Flow<State<VkUser?>> = flow {
emit(State.Loading)
val newState = kotlin.runCatching {
repository.getLocalUsers(listOf(userId)).singleOrNull()
}.fold(
onSuccess = { user -> State.Success(user) },
onFailure = { State.Error.InternalError }
)
emit(newState)
}
override suspend fun storeUsers(users: List<VkUser>) {
}
override suspend fun storeUser(user: VkUser) = repository.storeUsers(listOf(user))
override suspend fun storeUsers(users: List<VkUser>) = repository.storeUsers(users)
}
@@ -9,7 +9,7 @@ data class UsersGetRequest(
val map
get() = mutableMapOf<String, String>()
.apply {
userIds?.let { this["user_ids"] = it.joinToString() }
userIds?.let { this["user_ids"] = it.joinToString(",") }
fields?.let { this["fields"] = it }
nomCase?.let { this["nom_case"] = it }
}
@@ -2,6 +2,8 @@ package com.meloda.app.fast.model.database
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.meloda.app.fast.model.api.domain.OnlineStatus
import com.meloda.app.fast.model.api.domain.VkUser
@Entity(tableName = "users")
data class VkUserEntity(
@@ -18,3 +20,20 @@ data class VkUserEntity(
val photo100: String?,
val photo200: String?
)
fun VkUserEntity.asExternalModel(): VkUser = VkUser(
id = id,
firstName = firstName,
lastName = lastName,
onlineStatus = when {
!isOnline -> OnlineStatus.Offline
!isOnlineMobile -> OnlineStatus.Online(onlineAppId)
else -> OnlineStatus.OnlineMobile(onlineAppId)
},
photo50 = photo50,
photo100 = photo100,
photo200 = photo200,
lastSeen = lastSeen,
lastSeenStatus = lastSeenStatus,
birthday = birthday
)
@@ -12,7 +12,7 @@ interface UsersService {
@FormUrlEncoded
@POST(UsersUrls.GET_BY_ID)
suspend fun getById(
suspend fun get(
@FieldMap params: Map<String, String>?
): ApiResult<ApiResponse<List<VkUserData>>, RestApiError>
}