From 2ae42b14480f9a5f5a99d57ade4cc900a35ec3ca Mon Sep 17 00:00:00 2001 From: jinukeu Date: Sun, 21 Jan 2024 17:53:35 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=9E=A5=EB=B6=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=84=A4=EA=B3=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../received/ledgeradd/LedgerAddScreen.kt | 156 ++++-------------- .../received/ledgeradd/LedgerAddViewModel.kt | 6 +- .../content/category/CategoryContent.kt | 71 ++++++-- .../content/category/CategoryViewModel.kt | 10 +- .../ledgeradd/content/date/DateContent.kt | 41 ++++- .../ledgeradd/content/date/DateViewModel.kt | 6 +- .../ledgeradd/content/name/NameContent.kt | 27 +++ 7 files changed, 171 insertions(+), 146 deletions(-) diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddScreen.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddScreen.kt index 2910b1e1..61f261ec 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddScreen.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddScreen.kt @@ -9,11 +9,11 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview @@ -30,27 +30,14 @@ import com.susu.core.model.Category import com.susu.core.ui.R import com.susu.core.ui.extension.collectWithLifecycle import com.susu.core.ui.extension.susuDefaultAnimatedContentTransitionSpec -import com.susu.feature.received.Category.category.CategoryViewModel -import com.susu.feature.received.ledgeradd.content.category.CategoryContent -import com.susu.feature.received.ledgeradd.content.category.CategorySideEffect -import com.susu.feature.received.ledgeradd.content.category.CategoryState -import com.susu.feature.received.ledgeradd.content.date.DateContent -import com.susu.feature.received.ledgeradd.content.date.DateSideEffect -import com.susu.feature.received.ledgeradd.content.date.DateState -import com.susu.feature.received.ledgeradd.content.date.DateViewModel -import com.susu.feature.received.ledgeradd.content.name.NameContent -import com.susu.feature.received.ledgeradd.content.name.NameSideEffect -import com.susu.feature.received.ledgeradd.content.name.NameState -import com.susu.feature.received.ledgeradd.content.name.NameViewModel -import kotlinx.coroutines.android.awaitFrame -import kotlinx.coroutines.launch +import com.susu.feature.received.ledgeradd.content.category.CategoryContentRoute +import com.susu.feature.received.ledgeradd.content.date.DateContentRoute +import com.susu.feature.received.ledgeradd.content.name.NameContentRoute +import java.time.LocalDateTime @Composable fun LedgerAddRoute( viewModel: LedgerAddViewModel = hiltViewModel(), - categoryViewModel: CategoryViewModel = hiltViewModel(), - nameViewModel: NameViewModel = hiltViewModel(), - dateViewModel: DateViewModel = hiltViewModel(), popBackStack: () -> Unit, popBackStackWithLedger: (String) -> Unit, handleException: (Throwable, () -> Unit) -> Unit, @@ -64,48 +51,12 @@ fun LedgerAddRoute( } } - val categoryState = categoryViewModel.uiState.collectAsStateWithLifecycle().value - val focusRequester = remember { FocusRequester() } - val scope = rememberCoroutineScope() - categoryViewModel.sideEffect.collectWithLifecycle { sideEffect -> - when (sideEffect) { - is CategorySideEffect.UpdateParentSelectedCategory -> { - viewModel.updateSelectedCategory(sideEffect.category) - dateViewModel.updateNameAndCategory( - name = null, - categoryName = sideEffect.category?.customCategory ?: sideEffect.category?.name, - ) - } - - CategorySideEffect.FocusCustomCategory -> scope.launch { - awaitFrame() - focusRequester.requestFocus() - } - } - } - - LaunchedEffect(key1 = Unit) { - categoryViewModel.getCategoryConfig() + var dateContentCategoryName: String by remember { + mutableStateOf("") } - val nameState = nameViewModel.uiState.collectAsStateWithLifecycle().value - nameViewModel.sideEffect.collectWithLifecycle { sideEffect -> - when (sideEffect) { - is NameSideEffect.UpdateParentName -> { - viewModel.updateName(sideEffect.name) - dateViewModel.updateNameAndCategory( - name = sideEffect.name, - categoryName = null, - ) - } - } - } - - val dateState = dateViewModel.uiState.collectAsStateWithLifecycle().value - dateViewModel.sideEffect.collectWithLifecycle { sideEffect -> - when (sideEffect) { - is DateSideEffect.UpdateParentDate -> viewModel.updateDate(sideEffect.startAt, sideEffect.endAt) - } + var dateContentName: String by remember { + mutableStateOf("") } BackHandler { @@ -116,26 +67,19 @@ fun LedgerAddRoute( uiState = uiState, onClickBack = viewModel::goToPrevStep, onClickNextButton = viewModel::goToNextStep, - categoryState = categoryState, - focusRequester = focusRequester, - onClickCategoryButton = categoryViewModel::selectCategory, - onClickCustomCategoryButton = categoryViewModel::showCustomCategoryTextField, - onClickCustomCategoryTextFieldCloseIcon = categoryViewModel::hideCustomCategoryTextField, - onClickCustomCategoryTextField = categoryViewModel::selectCustomCategory, - onClickCustomCategoryTextFieldClearIcon = { categoryViewModel.updateCustomCategoryText("") }, - onTextChangeCustomCategoryTextField = categoryViewModel::updateCustomCategoryText, - onClickTextFieldInnerButton = categoryViewModel::toggleTextFieldSaved, - updateParentSelectedCategory = categoryViewModel::updateParentSelectedCategory, - nameState = nameState, - onTextChangeName = nameViewModel::updateName, - dateState = dateState, - onStartDateItemSelected = dateViewModel::updateStartDate, - onClickStartDateText = dateViewModel::showStartDateBottomSheet, - onDismissStartDateBottomSheet = dateViewModel::hideStartDateBottomSheet, - onEndDateItemSelected = dateViewModel::updateEndDate, - onClickEndDateText = dateViewModel::showEndDateBottomSheet, - onDismissEndDateBottomSheet = dateViewModel::hideEndDateBottomSheet, - updateParentDate = dateViewModel::updateParentDate, + updateParentSelectedCategory = { category -> + viewModel.updateSelectedCategory(category) + dateContentCategoryName = category?.customCategory ?: category?.name ?: "" + }, + updateParentName = { name -> + viewModel.updateName(name) + dateContentName = name + }, + dateContentName = dateContentName, + dateContentCategoryName = dateContentCategoryName, + updateParentDate = { startAt, endAt -> + viewModel.updateDate(startAt, endAt) + }, ) } @@ -144,26 +88,11 @@ fun LedgerAddScreen( uiState: LedgerAddState = LedgerAddState(), onClickBack: () -> Unit = {}, onClickNextButton: () -> Unit = {}, - categoryState: CategoryState = CategoryState(), - focusRequester: FocusRequester = remember { FocusRequester() }, - onClickCategoryButton: (Category) -> Unit = {}, - onClickCustomCategoryButton: () -> Unit = {}, - onClickCustomCategoryTextFieldCloseIcon: () -> Unit = {}, - onClickCustomCategoryTextField: () -> Unit = {}, - onClickCustomCategoryTextFieldClearIcon: () -> Unit = {}, - onTextChangeCustomCategoryTextField: (String) -> Unit = {}, - onClickTextFieldInnerButton: () -> Unit = {}, - updateParentSelectedCategory: () -> Unit = {}, - nameState: NameState = NameState(), - onTextChangeName: (String) -> Unit = {}, - dateState: DateState = DateState(), - onStartDateItemSelected: (Int, Int, Int) -> Unit = { _, _, _ -> }, - onClickStartDateText: () -> Unit = {}, - onDismissStartDateBottomSheet: () -> Unit = {}, - onEndDateItemSelected: (Int, Int, Int) -> Unit = { _, _, _ -> }, - onClickEndDateText: () -> Unit = {}, - onDismissEndDateBottomSheet: () -> Unit = {}, - updateParentDate: () -> Unit = {}, + updateParentSelectedCategory: (Category?) -> Unit = {}, + updateParentName: (String) -> Unit = {}, + dateContentCategoryName: String = "", + dateContentName: String = "", + updateParentDate: (LocalDateTime?, LocalDateTime?) -> Unit = { _, _ -> }, ) { Box( modifier = Modifier @@ -190,32 +119,17 @@ fun LedgerAddScreen( }, ) { targetState -> when (targetState) { - LedgerAddStep.CATEGORY -> CategoryContent( - uiState = categoryState, - focusRequester = focusRequester, - onClickCategoryButton = onClickCategoryButton, - onClickCustomCategoryButton = onClickCustomCategoryButton, - onClickCustomCategoryTextFieldCloseIcon = onClickCustomCategoryTextFieldCloseIcon, - onClickCustomCategoryTextField = onClickCustomCategoryTextField, - onClickCustomCategoryTextFieldClearIcon = onClickCustomCategoryTextFieldClearIcon, - onTextChangeCustomCategoryTextField = onTextChangeCustomCategoryTextField, - onClickTextFieldInnerButton = onClickTextFieldInnerButton, + LedgerAddStep.CATEGORY -> CategoryContentRoute( updateParentSelectedCategory = updateParentSelectedCategory, ) - LedgerAddStep.NAME -> NameContent( - uiState = nameState, - onTextChangeName = onTextChangeName, + LedgerAddStep.NAME -> NameContentRoute( + updateParentName = updateParentName, ) - LedgerAddStep.DATE -> DateContent( - uiState = dateState, - onStartDateItemSelected = onStartDateItemSelected, - onClickStartDateText = onClickStartDateText, - onDismissStartDateBottomSheet = onDismissStartDateBottomSheet, - onEndDateItemSelected = onEndDateItemSelected, - onClickEndDateText = onClickEndDateText, - onDismissEndDateBottomSheet = onDismissEndDateBottomSheet, + LedgerAddStep.DATE -> DateContentRoute( + name = dateContentName, + categoryName = dateContentCategoryName, updateParentDate = updateParentDate, ) } diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddViewModel.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddViewModel.kt index 3e795b65..200fa96b 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddViewModel.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/LedgerAddViewModel.kt @@ -19,8 +19,10 @@ class LedgerAddViewModel @Inject constructor( ) : BaseViewModel( LedgerAddState(), ) { - private var selectedCategory: Category? = null - private var name: String = "" + var selectedCategory: Category? = null + private set + var name: String = "" + private set private var startAt: LocalDateTime? = null private var endAt: LocalDateTime? = null diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryContent.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryContent.kt index 92af6616..566f29ea 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryContent.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryContent.kt @@ -13,11 +13,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.susu.core.designsystem.component.button.FilledButtonColor import com.susu.core.designsystem.component.button.GhostButtonColor import com.susu.core.designsystem.component.button.MediumButtonStyle @@ -28,8 +31,63 @@ import com.susu.core.designsystem.component.textfieldbutton.TextFieldButtonColor import com.susu.core.designsystem.component.textfieldbutton.style.MediumTextFieldButtonStyle import com.susu.core.designsystem.theme.SusuTheme import com.susu.core.model.Category +import com.susu.core.ui.extension.collectWithLifecycle import com.susu.feature.received.R -import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.android.awaitFrame +import kotlinx.coroutines.launch + +@Composable +fun CategoryContentRoute( + viewModel: CategoryViewModel = hiltViewModel(), + updateParentSelectedCategory: (Category?) -> Unit = {}, +) { + val uiState = viewModel.uiState.collectAsStateWithLifecycle().value + val focusRequester = remember { FocusRequester() } + val scope = rememberCoroutineScope() + viewModel.sideEffect.collectWithLifecycle { sideEffect -> + when (sideEffect) { + is CategorySideEffect.UpdateParentSelectedCategory -> { + updateParentSelectedCategory(sideEffect.category) +// viewModel.updateSelectedCategory(sideEffect.category) +// dateViewModel.updateNameAndCategory( +// name = null, +// categoryName = sideEffect.category?.customCategory ?: sideEffect.category?.name, +// ) + } + + CategorySideEffect.FocusCustomCategory -> scope.launch { + awaitFrame() + focusRequester.requestFocus() + } + } + } + + LaunchedEffect(key1 = Unit) { + viewModel.getCategoryConfig() + } + + LaunchedEffect( + key1 = uiState.selectedCategory, + key2 = uiState.isSavedCustomCategory, + ) { + snapshotFlow { uiState.selectedCategory } + .collect { + viewModel.updateParentSelectedCategory() + } + } + + CategoryContent( + uiState = uiState, + focusRequester = focusRequester, + onClickCategoryButton = viewModel::selectCategory, + onClickCustomCategoryButton = viewModel::showCustomCategoryTextField, + onClickCustomCategoryTextFieldCloseIcon = viewModel::hideCustomCategoryTextField, + onClickCustomCategoryTextField = viewModel::selectCustomCategory, + onClickCustomCategoryTextFieldClearIcon = { viewModel.updateCustomCategoryText("") }, + onTextChangeCustomCategoryTextField = viewModel::updateCustomCategoryText, + onClickTextFieldInnerButton = viewModel::toggleTextFieldSaved, + ) +} @Composable fun CategoryContent( @@ -42,18 +100,7 @@ fun CategoryContent( onClickCustomCategoryTextFieldClearIcon: () -> Unit = {}, onTextChangeCustomCategoryTextField: (String) -> Unit = {}, onClickTextFieldInnerButton: () -> Unit = {}, - updateParentSelectedCategory: () -> Unit = {}, ) { - LaunchedEffect( - key1 = uiState.selectedCategory, - key2 = uiState.isSavedCustomCategory, - ) { - snapshotFlow { uiState.selectedCategory } - .collect { - updateParentSelectedCategory() - } - } - val scrollState = rememberScrollState() Column( diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryViewModel.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryViewModel.kt index fa45f756..c4d8b580 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryViewModel.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/category/CategoryViewModel.kt @@ -1,11 +1,9 @@ -package com.susu.feature.received.Category.category +package com.susu.feature.received.ledgeradd.content.category import androidx.lifecycle.viewModelScope import com.susu.core.model.Category import com.susu.core.ui.base.BaseViewModel import com.susu.domain.usecase.categoryconfig.GetCategoryConfigUseCase -import com.susu.feature.received.ledgeradd.content.category.CategorySideEffect -import com.susu.feature.received.ledgeradd.content.category.CategoryState import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.launch @@ -27,6 +25,8 @@ class CategoryViewModel @Inject constructor( } fun getCategoryConfig() = viewModelScope.launch { + if (currentState.categoryConfig.isNotEmpty()) return@launch + getCategoryConfigUseCase() .onSuccess { intent { @@ -75,5 +75,7 @@ class CategoryViewModel @Inject constructor( ) } - fun updateParentSelectedCategory() = postSideEffect(CategorySideEffect.UpdateParentSelectedCategory(parentSelectedCategory)) + fun updateParentSelectedCategory(category: Category? = parentSelectedCategory) = postSideEffect( + CategorySideEffect.UpdateParentSelectedCategory(category), + ) } diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateContent.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateContent.kt index 1de34115..c992de57 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateContent.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateContent.kt @@ -12,14 +12,51 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.susu.core.designsystem.component.bottomsheet.datepicker.SusuLimitDatePickerBottomSheet import com.susu.core.designsystem.theme.Gray60 import com.susu.core.designsystem.theme.SusuTheme +import com.susu.core.ui.extension.collectWithLifecycle import com.susu.core.ui.util.AnnotatedText import com.susu.core.ui.util.currentDate import com.susu.core.ui.util.minDate import com.susu.feature.received.R import com.susu.feature.received.ledgeradd.content.date.component.SelectDateRow +import java.time.LocalDateTime + +@Composable +fun DateContentRoute( + viewModel: DateViewModel = hiltViewModel(), + name: String, + categoryName: String, + updateParentDate: (LocalDateTime?, LocalDateTime?) -> Unit, +) { + val uiState = viewModel.uiState.collectAsStateWithLifecycle().value + viewModel.sideEffect.collectWithLifecycle { sideEffect -> + when (sideEffect) { + is DateSideEffect.UpdateParentDate -> updateParentDate(sideEffect.startAt, sideEffect.endAt) + } + } + + LaunchedEffect(key1 = Unit) { + updateParentDate(uiState.startAt, uiState.endAt) + } + + LaunchedEffect(key1 = Unit) { + viewModel.updateNameAndCategory(name, categoryName) + } + + DateContent( + uiState = uiState, + onStartDateItemSelected = viewModel::updateStartDate, + onClickStartDateText = viewModel::showStartDateBottomSheet, + onDismissStartDateBottomSheet = viewModel::hideStartDateBottomSheet, + onEndDateItemSelected = viewModel::updateEndDate, + onClickEndDateText = viewModel::showEndDateBottomSheet, + onDismissEndDateBottomSheet = viewModel::hideEndDateBottomSheet, + ) +} @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -31,11 +68,7 @@ fun DateContent( onEndDateItemSelected: (Int, Int, Int) -> Unit = { _, _, _ -> }, onClickEndDateText: () -> Unit = {}, onDismissEndDateBottomSheet: () -> Unit = {}, - updateParentDate: () -> Unit = {}, ) { - LaunchedEffect(key1 = Unit) { - updateParentDate() - } Column( modifier = Modifier .fillMaxSize() diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateViewModel.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateViewModel.kt index 0724095b..c64ac824 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateViewModel.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/date/DateViewModel.kt @@ -10,10 +10,10 @@ import javax.inject.Inject class DateViewModel @Inject constructor() : BaseViewModel( DateState(), ) { - fun updateNameAndCategory(name: String?, categoryName: String?) = intent { + fun updateNameAndCategory(name: String, categoryName: String) = intent { copy( - name = name ?: this.name, - categoryName = categoryName ?: this.categoryName, + name = name, + categoryName = categoryName, ) } diff --git a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/name/NameContent.kt b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/name/NameContent.kt index 01775166..66a09f86 100644 --- a/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/name/NameContent.kt +++ b/feature/received/src/main/java/com/susu/feature/received/ledgeradd/content/name/NameContent.kt @@ -11,10 +11,37 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.susu.core.designsystem.component.textfield.SusuBasicTextField import com.susu.core.designsystem.theme.SusuTheme +import com.susu.core.ui.extension.collectWithLifecycle import com.susu.feature.received.R +@Composable +fun NameContentRoute( + viewModel: NameViewModel = hiltViewModel(), + updateParentName: (String) -> Unit = {}, +) { + val uiState = viewModel.uiState.collectAsStateWithLifecycle().value + viewModel.sideEffect.collectWithLifecycle { sideEffect -> + when (sideEffect) { + is NameSideEffect.UpdateParentName -> { + updateParentName(sideEffect.name) +// dateViewModel.updateNameAndCategory( +// name = sideEffect.name, +// categoryName = null, +// ) + } + } + } + + NameContent( + uiState = uiState, + onTextChangeName = viewModel::updateName, + ) +} + @Composable fun NameContent( uiState: NameState = NameState(),