separation of users use cases

This commit is contained in:
2024-08-14 21:03:35 +03:00
parent bafebfa4ae
commit 58e2906c0f
13 changed files with 170 additions and 80 deletions
+2 -2
View File
@@ -12,8 +12,8 @@ android {
defaultConfig {
applicationId = "dev.meloda.fast"
versionCode = 4
versionName = "0.1.1"
versionCode = libs.versions.versionCode.get().toInt()
versionName = libs.versions.versionName.get()
}
signingConfigs {
@@ -1,9 +1,9 @@
package dev.meloda.fast.data
import com.slack.eithernet.ApiResult
import dev.meloda.fast.network.OAuthErrorDomain
import dev.meloda.fast.network.RestApiErrorDomain
import dev.meloda.fast.network.VkErrorCode
import com.slack.eithernet.ApiResult
sealed class State<out T> {
@@ -72,3 +72,12 @@ fun <T : Any> ApiResult<T, RestApiErrorDomain>.mapToState() = when (this) {
is ApiResult.Failure.HttpFailure -> this.error.toStateApiError()
is ApiResult.Failure.ApiFailure -> this.error.toStateApiError()
}
fun <T : Any, N> ApiResult<T, RestApiErrorDomain>.mapToState(successMapper: (T) -> N) = when (this) {
is ApiResult.Success -> State.Success(successMapper(this.value))
is ApiResult.Failure.NetworkFailure -> State.Error.ConnectionError
is ApiResult.Failure.UnknownFailure -> State.UNKNOWN_ERROR
is ApiResult.Failure.HttpFailure -> this.error.toStateApiError()
is ApiResult.Failure.ApiFailure -> this.error.toStateApiError()
}
@@ -0,0 +1,23 @@
package dev.meloda.fast.domain
import dev.meloda.fast.data.State
import dev.meloda.fast.data.api.users.UsersRepository
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class GetLocalUserByIdUseCase(private val repository: UsersRepository) {
operator fun invoke(userId: Int): Flow<State<VkUser?>> = flow {
emit(State.Loading)
val newState = kotlin.runCatching {
repository.getLocalUsers(userIds = listOf(userId)).singleOrNull()
}.fold(
onSuccess = { user -> State.Success(user) },
onFailure = { State.Error.InternalError }
)
emit(newState)
}
}
@@ -0,0 +1,23 @@
package dev.meloda.fast.domain
import dev.meloda.fast.data.State
import dev.meloda.fast.data.api.users.UsersRepository
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class GetLocalUsersByIdsUseCase(private val repository: UsersRepository) {
operator fun invoke(userIds: List<Int>): Flow<State<List<VkUser>>> = flow {
emit(State.Loading)
val newState = kotlin.runCatching {
repository.getLocalUsers(userIds = userIds)
}.fold(
onSuccess = { user -> State.Success(user) },
onFailure = { State.Error.InternalError }
)
emit(newState)
}
}
@@ -0,0 +1,28 @@
package dev.meloda.fast.domain
import dev.meloda.fast.common.VkConstants
import dev.meloda.fast.data.State
import dev.meloda.fast.data.api.users.UsersRepository
import dev.meloda.fast.data.mapToState
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class LoadUserByIdUseCase(private val repository: UsersRepository) {
operator fun invoke(
userId: Int?,
fields: String = VkConstants.USER_FIELDS,
nomCase: String? = null
): Flow<State<VkUser?>> = flow {
emit(State.Loading)
val newState = repository.get(
userIds = userId?.let(::listOf),
fields = fields,
nomCase = nomCase
).mapToState(List<VkUser>::singleOrNull)
emit(newState)
}
}
@@ -0,0 +1,28 @@
package dev.meloda.fast.domain
import dev.meloda.fast.common.VkConstants
import dev.meloda.fast.data.State
import dev.meloda.fast.data.api.users.UsersRepository
import dev.meloda.fast.data.mapToState
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class LoadUsersByIdsUseCase(private val repository: UsersRepository) {
operator fun invoke(
userIds: List<Int>?,
fields: String = VkConstants.USER_FIELDS,
nomCase: String? = null
): Flow<State<List<VkUser>>> = flow {
emit(State.Loading)
val newState = repository.get(
userIds = userIds,
fields = fields,
nomCase = nomCase
).mapToState()
emit(newState)
}
}
@@ -0,0 +1,28 @@
package dev.meloda.fast.domain
import dev.meloda.fast.data.State
import dev.meloda.fast.data.api.users.UsersRepository
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class StoreUsersUseCase(private val repository: UsersRepository) {
operator fun invoke(users: List<VkUser>): Flow<State<Unit>> = flow {
emit(State.Loading)
val newState = kotlin.runCatching {
repository.storeUsers(users)
}.fold(
onSuccess = {
State.Success(Unit)
},
onFailure = { error ->
error.printStackTrace()
State.Error.InternalError
}
)
emit(newState)
}
}
@@ -1,19 +0,0 @@
package dev.meloda.fast.domain
import dev.meloda.fast.data.State
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
interface UsersUseCase {
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,40 +0,0 @@
package dev.meloda.fast.domain
import dev.meloda.fast.data.State
import dev.meloda.fast.data.api.users.UsersRepository
import dev.meloda.fast.data.mapToState
import dev.meloda.fast.model.api.domain.VkUser
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class UsersUseCaseImpl(
private val repository: UsersRepository,
) : UsersUseCase {
override fun get(
userIds: List<Int>?,
fields: String?,
nomCase: String?
): Flow<State<List<VkUser>>> = flow {
emit(State.Loading)
val newState = repository.get(userIds, fields, nomCase).mapToState()
emit(newState)
}
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 storeUser(user: VkUser) = repository.storeUsers(listOf(user))
override suspend fun storeUsers(users: List<VkUser>) = repository.storeUsers(users)
}
@@ -4,8 +4,11 @@ import dev.meloda.fast.data.di.dataModule
import dev.meloda.fast.domain.AccountUseCase
import dev.meloda.fast.domain.AccountUseCaseImpl
import dev.meloda.fast.domain.GetCurrentAccountUseCase
import dev.meloda.fast.domain.UsersUseCase
import dev.meloda.fast.domain.UsersUseCaseImpl
import dev.meloda.fast.domain.GetLocalUserByIdUseCase
import dev.meloda.fast.domain.GetLocalUsersByIdsUseCase
import dev.meloda.fast.domain.LoadUserByIdUseCase
import dev.meloda.fast.domain.LoadUsersByIdsUseCase
import dev.meloda.fast.domain.StoreUsersUseCase
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.bind
import org.koin.dsl.module
@@ -13,7 +16,12 @@ import org.koin.dsl.module
val domainModule = module {
includes(dataModule)
singleOf(::UsersUseCaseImpl) bind UsersUseCase::class
singleOf(::GetLocalUserByIdUseCase)
singleOf(::GetLocalUsersByIdsUseCase)
singleOf(::LoadUserByIdUseCase)
singleOf(::LoadUsersByIdsUseCase)
singleOf(::StoreUsersUseCase)
singleOf(::AccountUseCaseImpl) bind AccountUseCase::class
singleOf(::GetCurrentAccountUseCase)
}
@@ -20,8 +20,8 @@ import dev.meloda.fast.data.UserConfig
import dev.meloda.fast.data.db.AccountsRepository
import dev.meloda.fast.data.processState
import dev.meloda.fast.datastore.AppSettings
import dev.meloda.fast.domain.LoadUserByIdUseCase
import dev.meloda.fast.domain.OAuthUseCase
import dev.meloda.fast.domain.UsersUseCase
import dev.meloda.fast.model.database.AccountEntity
import dev.meloda.fast.network.OAuthErrorDomain
import kotlinx.coroutines.Dispatchers
@@ -71,7 +71,7 @@ interface LoginViewModel {
class LoginViewModelImpl(
private val oAuthUseCase: OAuthUseCase,
private val usersUseCase: UsersUseCase,
private val loadUserByIdUseCase: LoadUserByIdUseCase,
private val accountsRepository: AccountsRepository,
private val loginValidator: LoginValidator,
private val longPollController: LongPollController
@@ -171,8 +171,8 @@ class LoginViewModelImpl(
UserConfig.trustedHash = account.trustedHash
}
usersUseCase.get(
userIds = null,
loadUserByIdUseCase(
userId = null,
fields = VkConstants.USER_FIELDS,
nomCase = null
).listenValue(viewModelScope) { state ->
@@ -185,7 +185,7 @@ class LoginViewModelImpl(
// TODO: 19/07/2024, Danil Nikolaev: show error?
},
success = { response ->
val actualUserId = response.first().id
val actualUserId = requireNotNull(response).id
currentAccount = currentAccount.copy(userId = actualUserId)
@@ -245,8 +245,8 @@ class LoginViewModelImpl(
return@processState
}
usersUseCase.get(
userIds = listOf(userId),
loadUserByIdUseCase(
userId = userId,
fields = VkConstants.USER_FIELDS,
nomCase = null
)
@@ -8,7 +8,8 @@ import dev.meloda.fast.common.extensions.setValue
import dev.meloda.fast.data.State
import dev.meloda.fast.data.UserConfig
import dev.meloda.fast.data.processState
import dev.meloda.fast.domain.UsersUseCase
import dev.meloda.fast.domain.GetLocalUserByIdUseCase
import dev.meloda.fast.domain.LoadUserByIdUseCase
import dev.meloda.fast.model.BaseError
import dev.meloda.fast.network.VkErrorCode
import dev.meloda.fast.profile.model.ProfileScreenState
@@ -21,7 +22,8 @@ interface ProfileViewModel {
}
class ProfileViewModelImpl(
private val usersUseCase: UsersUseCase
private val getLocalUserByIdUseCase: GetLocalUserByIdUseCase,
private val loadUserByIdUseCase: LoadUserByIdUseCase
) : ViewModel(), ProfileViewModel {
override val screenState = MutableStateFlow(ProfileScreenState.EMPTY)
@@ -32,7 +34,7 @@ class ProfileViewModelImpl(
}
private fun getLocalAccountInfo() {
usersUseCase.getLocalUser(UserConfig.userId)
getLocalUserByIdUseCase(UserConfig.userId)
.listenValue(viewModelScope) { state ->
state.processState(
error = { error ->
@@ -67,8 +69,8 @@ class ProfileViewModelImpl(
}
private fun loadAccountInfo() {
usersUseCase.get(
userIds = null,
loadUserByIdUseCase(
userId = null,
fields = VkConstants.USER_FIELDS,
nomCase = null
).listenValue(viewModelScope) { state ->
@@ -77,7 +79,7 @@ class ProfileViewModelImpl(
// TODO: 12/07/2024, Danil Nikolaev: if local info is null then show error view
},
success = { response ->
val user = response.single()
val user = requireNotNull(response)
screenState.setValue { old ->
old.copy(
+2 -2
View File
@@ -2,8 +2,8 @@
minSdk = "24"
targetSdk = "35"
compileSdk = "35"
versionCode = "4"
versionName = "0.1.1"
versionCode = "5"
versionName = "0.1.2"
agp = "8.5.2"
converterMoshi = "2.11.0"