refactor: simplify Profile feature state management and update ViewModel

This commit is contained in:
2026-05-30 11:46:14 +03:00
parent 63bae014c5
commit d428af4ac4
5 changed files with 17 additions and 47 deletions
@@ -210,7 +210,6 @@ fun MainScreen(
)
profileScreen(
activity = activity,
onError = onError,
onSettingsButtonClicked = onSettingsButtonClicked,
onPhotoClicked = onPhotoClicked
)
@@ -5,49 +5,33 @@ import androidx.lifecycle.viewModelScope
import dev.meloda.fast.common.VkConstants
import dev.meloda.fast.common.extensions.listenValue
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.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
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
interface ProfileViewModel {
val screenState: StateFlow<ProfileScreenState>
val baseError: StateFlow<BaseError?>
}
class ProfileViewModelImpl(
class ProfileViewModel(
private val getLocalUserByIdUseCase: GetLocalUserByIdUseCase,
private val loadUserByIdUseCase: LoadUserByIdUseCase
) : ViewModel(), ProfileViewModel {
) : ViewModel() {
override val screenState = MutableStateFlow(ProfileScreenState.EMPTY)
override val baseError = MutableStateFlow<BaseError?>(null)
private val screenState = MutableStateFlow(ProfileScreenState.EMPTY)
init {
getLocalAccountInfo()
}
fun screenStateFlow(): StateFlow<ProfileScreenState> = screenState.asStateFlow()
private fun getLocalAccountInfo() {
getLocalUserByIdUseCase(UserConfig.userId)
.listenValue(viewModelScope) { state ->
state.processState(
error = { error ->
if (error is State.Error.ApiError) {
when (error.errorCode) {
VkErrorCode.USER_AUTHORIZATION_FAILED -> {
baseError.setValue { BaseError.SessionExpired }
}
else -> Unit
}
}
error = {
screenState.setValue { old ->
old.copy(
avatarUrl = null,
@@ -1,9 +1,9 @@
package dev.meloda.fast.profile.di
import dev.meloda.fast.profile.ProfileViewModelImpl
import dev.meloda.fast.profile.ProfileViewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module
val profileModule = module {
viewModelOf(::ProfileViewModelImpl)
viewModelOf(::ProfileViewModel)
}
@@ -1,11 +1,11 @@
package dev.meloda.fast.profile.navigation
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.getValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable
import dev.meloda.fast.model.BaseError
import dev.meloda.fast.profile.ProfileViewModel
import dev.meloda.fast.profile.ProfileViewModelImpl
import dev.meloda.fast.profile.presentation.ProfileRoute
import kotlinx.serialization.Serializable
import org.koin.androidx.viewmodel.ext.android.getViewModel
@@ -15,19 +15,18 @@ object Profile
fun NavGraphBuilder.profileScreen(
activity: AppCompatActivity,
onError: (BaseError) -> Unit,
onSettingsButtonClicked: () -> Unit,
onPhotoClicked: (url: String) -> Unit
) {
val viewModel: ProfileViewModel = with(activity) {
getViewModel<ProfileViewModelImpl>()
}
val viewModel: ProfileViewModel = with(activity) { getViewModel() }
composable<Profile> {
val screenState by viewModel.screenStateFlow().collectAsStateWithLifecycle()
ProfileRoute(
onError = onError,
screenState = screenState,
onSettingsButtonClicked = onSettingsButtonClicked,
onPhotoClicked = onPhotoClicked,
viewModel = viewModel
)
}
}
@@ -20,7 +20,6 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
@@ -29,31 +28,21 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.AsyncImage
import dev.meloda.fast.model.BaseError
import dev.meloda.fast.profile.ProfileViewModel
import dev.meloda.fast.profile.ProfileViewModelImpl
import dev.meloda.fast.profile.model.ProfileScreenState
import dev.meloda.fast.ui.R
import dev.meloda.fast.ui.components.SegmentedButtonItem
import dev.meloda.fast.ui.components.SegmentedButtonsRow
import dev.meloda.fast.ui.util.buildImmutableList
import org.koin.androidx.compose.koinViewModel
@Composable
fun ProfileRoute(
onError: (BaseError) -> Unit,
screenState: ProfileScreenState,
onSettingsButtonClicked: () -> Unit,
onPhotoClicked: (url: String) -> Unit,
viewModel: ProfileViewModel = koinViewModel<ProfileViewModelImpl>()
) {
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
ProfileScreen(
screenState = screenState,
baseError = baseError,
onSettingsButtonClicked = onSettingsButtonClicked,
onPhotoClicked = onPhotoClicked
)
@@ -64,7 +53,6 @@ fun ProfileRoute(
@Composable
fun ProfileScreen(
screenState: ProfileScreenState = ProfileScreenState.EMPTY,
baseError: BaseError? = null,
onSettingsButtonClicked: () -> Unit = {},
onPhotoClicked: (url: String) -> Unit = {}
) {