forked from melod1n/fast-messenger
separation of users use cases
This commit is contained in:
@@ -12,8 +12,8 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "dev.meloda.fast"
|
applicationId = "dev.meloda.fast"
|
||||||
|
|
||||||
versionCode = 4
|
versionCode = libs.versions.versionCode.get().toInt()
|
||||||
versionName = "0.1.1"
|
versionName = libs.versions.versionName.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package dev.meloda.fast.data
|
package dev.meloda.fast.data
|
||||||
|
|
||||||
|
import com.slack.eithernet.ApiResult
|
||||||
import dev.meloda.fast.network.OAuthErrorDomain
|
import dev.meloda.fast.network.OAuthErrorDomain
|
||||||
import dev.meloda.fast.network.RestApiErrorDomain
|
import dev.meloda.fast.network.RestApiErrorDomain
|
||||||
import dev.meloda.fast.network.VkErrorCode
|
import dev.meloda.fast.network.VkErrorCode
|
||||||
import com.slack.eithernet.ApiResult
|
|
||||||
|
|
||||||
sealed class State<out T> {
|
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.HttpFailure -> this.error.toStateApiError()
|
||||||
is ApiResult.Failure.ApiFailure -> 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.AccountUseCase
|
||||||
import dev.meloda.fast.domain.AccountUseCaseImpl
|
import dev.meloda.fast.domain.AccountUseCaseImpl
|
||||||
import dev.meloda.fast.domain.GetCurrentAccountUseCase
|
import dev.meloda.fast.domain.GetCurrentAccountUseCase
|
||||||
import dev.meloda.fast.domain.UsersUseCase
|
import dev.meloda.fast.domain.GetLocalUserByIdUseCase
|
||||||
import dev.meloda.fast.domain.UsersUseCaseImpl
|
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.core.module.dsl.singleOf
|
||||||
import org.koin.dsl.bind
|
import org.koin.dsl.bind
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
@@ -13,7 +16,12 @@ import org.koin.dsl.module
|
|||||||
val domainModule = module {
|
val domainModule = module {
|
||||||
includes(dataModule)
|
includes(dataModule)
|
||||||
|
|
||||||
singleOf(::UsersUseCaseImpl) bind UsersUseCase::class
|
singleOf(::GetLocalUserByIdUseCase)
|
||||||
|
singleOf(::GetLocalUsersByIdsUseCase)
|
||||||
|
singleOf(::LoadUserByIdUseCase)
|
||||||
|
singleOf(::LoadUsersByIdsUseCase)
|
||||||
|
singleOf(::StoreUsersUseCase)
|
||||||
|
|
||||||
singleOf(::AccountUseCaseImpl) bind AccountUseCase::class
|
singleOf(::AccountUseCaseImpl) bind AccountUseCase::class
|
||||||
singleOf(::GetCurrentAccountUseCase)
|
singleOf(::GetCurrentAccountUseCase)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import dev.meloda.fast.data.UserConfig
|
|||||||
import dev.meloda.fast.data.db.AccountsRepository
|
import dev.meloda.fast.data.db.AccountsRepository
|
||||||
import dev.meloda.fast.data.processState
|
import dev.meloda.fast.data.processState
|
||||||
import dev.meloda.fast.datastore.AppSettings
|
import dev.meloda.fast.datastore.AppSettings
|
||||||
|
import dev.meloda.fast.domain.LoadUserByIdUseCase
|
||||||
import dev.meloda.fast.domain.OAuthUseCase
|
import dev.meloda.fast.domain.OAuthUseCase
|
||||||
import dev.meloda.fast.domain.UsersUseCase
|
|
||||||
import dev.meloda.fast.model.database.AccountEntity
|
import dev.meloda.fast.model.database.AccountEntity
|
||||||
import dev.meloda.fast.network.OAuthErrorDomain
|
import dev.meloda.fast.network.OAuthErrorDomain
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -71,7 +71,7 @@ interface LoginViewModel {
|
|||||||
|
|
||||||
class LoginViewModelImpl(
|
class LoginViewModelImpl(
|
||||||
private val oAuthUseCase: OAuthUseCase,
|
private val oAuthUseCase: OAuthUseCase,
|
||||||
private val usersUseCase: UsersUseCase,
|
private val loadUserByIdUseCase: LoadUserByIdUseCase,
|
||||||
private val accountsRepository: AccountsRepository,
|
private val accountsRepository: AccountsRepository,
|
||||||
private val loginValidator: LoginValidator,
|
private val loginValidator: LoginValidator,
|
||||||
private val longPollController: LongPollController
|
private val longPollController: LongPollController
|
||||||
@@ -171,8 +171,8 @@ class LoginViewModelImpl(
|
|||||||
UserConfig.trustedHash = account.trustedHash
|
UserConfig.trustedHash = account.trustedHash
|
||||||
}
|
}
|
||||||
|
|
||||||
usersUseCase.get(
|
loadUserByIdUseCase(
|
||||||
userIds = null,
|
userId = null,
|
||||||
fields = VkConstants.USER_FIELDS,
|
fields = VkConstants.USER_FIELDS,
|
||||||
nomCase = null
|
nomCase = null
|
||||||
).listenValue(viewModelScope) { state ->
|
).listenValue(viewModelScope) { state ->
|
||||||
@@ -185,7 +185,7 @@ class LoginViewModelImpl(
|
|||||||
// TODO: 19/07/2024, Danil Nikolaev: show error?
|
// TODO: 19/07/2024, Danil Nikolaev: show error?
|
||||||
},
|
},
|
||||||
success = { response ->
|
success = { response ->
|
||||||
val actualUserId = response.first().id
|
val actualUserId = requireNotNull(response).id
|
||||||
|
|
||||||
currentAccount = currentAccount.copy(userId = actualUserId)
|
currentAccount = currentAccount.copy(userId = actualUserId)
|
||||||
|
|
||||||
@@ -245,8 +245,8 @@ class LoginViewModelImpl(
|
|||||||
return@processState
|
return@processState
|
||||||
}
|
}
|
||||||
|
|
||||||
usersUseCase.get(
|
loadUserByIdUseCase(
|
||||||
userIds = listOf(userId),
|
userId = userId,
|
||||||
fields = VkConstants.USER_FIELDS,
|
fields = VkConstants.USER_FIELDS,
|
||||||
nomCase = null
|
nomCase = null
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import dev.meloda.fast.common.extensions.setValue
|
|||||||
import dev.meloda.fast.data.State
|
import dev.meloda.fast.data.State
|
||||||
import dev.meloda.fast.data.UserConfig
|
import dev.meloda.fast.data.UserConfig
|
||||||
import dev.meloda.fast.data.processState
|
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.model.BaseError
|
||||||
import dev.meloda.fast.network.VkErrorCode
|
import dev.meloda.fast.network.VkErrorCode
|
||||||
import dev.meloda.fast.profile.model.ProfileScreenState
|
import dev.meloda.fast.profile.model.ProfileScreenState
|
||||||
@@ -21,7 +22,8 @@ interface ProfileViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ProfileViewModelImpl(
|
class ProfileViewModelImpl(
|
||||||
private val usersUseCase: UsersUseCase
|
private val getLocalUserByIdUseCase: GetLocalUserByIdUseCase,
|
||||||
|
private val loadUserByIdUseCase: LoadUserByIdUseCase
|
||||||
) : ViewModel(), ProfileViewModel {
|
) : ViewModel(), ProfileViewModel {
|
||||||
|
|
||||||
override val screenState = MutableStateFlow(ProfileScreenState.EMPTY)
|
override val screenState = MutableStateFlow(ProfileScreenState.EMPTY)
|
||||||
@@ -32,7 +34,7 @@ class ProfileViewModelImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getLocalAccountInfo() {
|
private fun getLocalAccountInfo() {
|
||||||
usersUseCase.getLocalUser(UserConfig.userId)
|
getLocalUserByIdUseCase(UserConfig.userId)
|
||||||
.listenValue(viewModelScope) { state ->
|
.listenValue(viewModelScope) { state ->
|
||||||
state.processState(
|
state.processState(
|
||||||
error = { error ->
|
error = { error ->
|
||||||
@@ -67,8 +69,8 @@ class ProfileViewModelImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadAccountInfo() {
|
private fun loadAccountInfo() {
|
||||||
usersUseCase.get(
|
loadUserByIdUseCase(
|
||||||
userIds = null,
|
userId = null,
|
||||||
fields = VkConstants.USER_FIELDS,
|
fields = VkConstants.USER_FIELDS,
|
||||||
nomCase = null
|
nomCase = null
|
||||||
).listenValue(viewModelScope) { state ->
|
).listenValue(viewModelScope) { state ->
|
||||||
@@ -77,7 +79,7 @@ class ProfileViewModelImpl(
|
|||||||
// TODO: 12/07/2024, Danil Nikolaev: if local info is null then show error view
|
// TODO: 12/07/2024, Danil Nikolaev: if local info is null then show error view
|
||||||
},
|
},
|
||||||
success = { response ->
|
success = { response ->
|
||||||
val user = response.single()
|
val user = requireNotNull(response)
|
||||||
|
|
||||||
screenState.setValue { old ->
|
screenState.setValue { old ->
|
||||||
old.copy(
|
old.copy(
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
minSdk = "24"
|
minSdk = "24"
|
||||||
targetSdk = "35"
|
targetSdk = "35"
|
||||||
compileSdk = "35"
|
compileSdk = "35"
|
||||||
versionCode = "4"
|
versionCode = "5"
|
||||||
versionName = "0.1.1"
|
versionName = "0.1.2"
|
||||||
|
|
||||||
agp = "8.5.2"
|
agp = "8.5.2"
|
||||||
converterMoshi = "2.11.0"
|
converterMoshi = "2.11.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user