From d428af4ac4bf3c905ca5da16c41b015207c1d63e Mon Sep 17 00:00:00 2001 From: Danil Nikolaev Date: Sat, 30 May 2026 11:46:14 +0300 Subject: [PATCH] refactor: simplify Profile feature state management and update ViewModel --- .../meloda/fast/presentation/MainScreen.kt | 1 - .../meloda/fast/profile/ProfileViewModel.kt | 30 +++++-------------- .../meloda/fast/profile/di/ProfileModule.kt | 4 +-- .../fast/profile/navigation/ProfileRoute.kt | 15 +++++----- .../profile/presentation/ProfileScreen.kt | 14 +-------- 5 files changed, 17 insertions(+), 47 deletions(-) diff --git a/app/src/main/kotlin/dev/meloda/fast/presentation/MainScreen.kt b/app/src/main/kotlin/dev/meloda/fast/presentation/MainScreen.kt index 678e0d24..208308cc 100644 --- a/app/src/main/kotlin/dev/meloda/fast/presentation/MainScreen.kt +++ b/app/src/main/kotlin/dev/meloda/fast/presentation/MainScreen.kt @@ -210,7 +210,6 @@ fun MainScreen( ) profileScreen( activity = activity, - onError = onError, onSettingsButtonClicked = onSettingsButtonClicked, onPhotoClicked = onPhotoClicked ) diff --git a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt index 24cccd5a..e3de652f 100644 --- a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt +++ b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/ProfileViewModel.kt @@ -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 - val baseError: StateFlow -} - -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(null) + private val screenState = MutableStateFlow(ProfileScreenState.EMPTY) init { getLocalAccountInfo() } + fun screenStateFlow(): StateFlow = 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, diff --git a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/di/ProfileModule.kt b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/di/ProfileModule.kt index f4903930..251c6f93 100644 --- a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/di/ProfileModule.kt +++ b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/di/ProfileModule.kt @@ -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) } diff --git a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/navigation/ProfileRoute.kt b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/navigation/ProfileRoute.kt index 06a481b2..ff0f3ff2 100644 --- a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/navigation/ProfileRoute.kt +++ b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/navigation/ProfileRoute.kt @@ -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() - } + val viewModel: ProfileViewModel = with(activity) { getViewModel() } + composable { + val screenState by viewModel.screenStateFlow().collectAsStateWithLifecycle() + ProfileRoute( - onError = onError, + screenState = screenState, onSettingsButtonClicked = onSettingsButtonClicked, onPhotoClicked = onPhotoClicked, - viewModel = viewModel ) } } diff --git a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/presentation/ProfileScreen.kt b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/presentation/ProfileScreen.kt index edebaf51..cff3a1b6 100644 --- a/feature/profile/src/main/kotlin/dev/meloda/fast/profile/presentation/ProfileScreen.kt +++ b/feature/profile/src/main/kotlin/dev/meloda/fast/profile/presentation/ProfileScreen.kt @@ -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() ) { - 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 = {} ) {