@@ -2,6 +2,7 @@ package com.threegap.bitnagil.presentation.home
22
33import android.util.Log
44import androidx.lifecycle.SavedStateHandle
5+ import androidx.lifecycle.ViewModel
56import androidx.lifecycle.viewModelScope
67import com.threegap.bitnagil.domain.emotion.usecase.FetchTodayEmotionUseCase
78import com.threegap.bitnagil.domain.emotion.usecase.GetEmotionChangeEventFlowUseCase
@@ -13,7 +14,6 @@ import com.threegap.bitnagil.domain.routine.usecase.RoutineCompletionUseCase
1314import com.threegap.bitnagil.domain.user.usecase.FetchUserProfileUseCase
1415import com.threegap.bitnagil.domain.writeroutine.usecase.GetWriteRoutineEventFlowUseCase
1516import com.threegap.bitnagil.presentation.common.mviviewmodel.MviViewModel
16- import com.threegap.bitnagil.presentation.home.model.HomeIntent
1717import com.threegap.bitnagil.presentation.home.model.HomeSideEffect
1818import com.threegap.bitnagil.presentation.home.model.HomeState
1919import com.threegap.bitnagil.presentation.home.model.RoutineScheduleUiModel
@@ -28,24 +28,27 @@ import kotlinx.coroutines.flow.distinctUntilChanged
2828import kotlinx.coroutines.flow.drop
2929import kotlinx.coroutines.flow.map
3030import kotlinx.coroutines.launch
31+ import org.orbitmvi.orbit.Container
32+ import org.orbitmvi.orbit.ContainerHost
3133import org.orbitmvi.orbit.syntax.Syntax
34+ import org.orbitmvi.orbit.viewmodel.container
3235import java.time.LocalDate
3336import javax.inject.Inject
3437
3538@HiltViewModel
3639class HomeViewModel @Inject constructor(
37- savedStateHandle : SavedStateHandle ,
3840 private val fetchWeeklyRoutinesUseCase : FetchWeeklyRoutinesUseCase ,
3941 private val fetchUserProfileUseCase : FetchUserProfileUseCase ,
4042 private val fetchTodayEmotionUseCase : FetchTodayEmotionUseCase ,
4143 private val routineCompletionUseCase : RoutineCompletionUseCase ,
4244 private val getWriteRoutineEventFlowUseCase : GetWriteRoutineEventFlowUseCase ,
4345 private val getEmotionChangeEventFlowUseCase : GetEmotionChangeEventFlowUseCase ,
4446 private val getOnBoardingRecommendRoutineEventFlowUseCase : GetOnBoardingRecommendRoutineEventFlowUseCase ,
45- ) : MviViewModel<HomeState, HomeSideEffect, HomeIntent>(
46- initState = HomeState (),
47- savedStateHandle = savedStateHandle,
48- ) {
47+ private val toggleRoutineUseCase : ToggleRoutineUseCase ,
48+ ) : ContainerHost<HomeState, HomeSideEffect>, ViewModel() {
49+
50+ override val container: Container <HomeState , HomeSideEffect > = container(initialState = HomeState .INIT )
51+
4952 private val pendingChangesByDate = mutableMapOf<String , MutableList <RoutineCompletionInfo >>()
5053 private val backupStatesByDate = mutableMapOf<String , RoutineScheduleUiModel >()
5154 private val routineSyncTrigger = MutableSharedFlow <LocalDate >()
@@ -56,92 +59,54 @@ class HomeViewModel @Inject constructor(
5659 observeRecommendRoutineEvent()
5760 observeWeekChanges()
5861 observeRoutineUpdates()
59- fetchWeeklyRoutines(stateFlow.value.currentWeeks)
62+ fetchWeeklyRoutines(container. stateFlow.value.currentWeeks)
6063 fetchUserProfile()
6164 fetchTodayEmotion(LocalDate .now())
6265 }
6366
64- override suspend fun Syntax <HomeState , HomeSideEffect >.reduceState (
65- intent : HomeIntent ,
66- state : HomeState ,
67- ): HomeState ? {
68- val newState = when (intent) {
69- is HomeIntent .UpdateLoading -> {
70- state.copy(isLoading = intent.isLoading)
71- }
67+ fun selectDate (data : LocalDate ) {
68+ intent {
69+ reduce { state.copy(selectedDate = data) }
70+ }
71+ }
7272
73- is HomeIntent .LoadUserProfile -> {
74- state.copy(userNickname = intent.nickname)
75- }
73+ fun getNextWeek () {
74+ intent {
75+ val newWeek = state.selectedDate.plusWeeks(1 ).getCurrentWeekDays()
76+ reduce { state.copy(currentWeeks = newWeek, selectedDate = newWeek.first()) }
77+ }
78+ }
7679
77- is HomeIntent .LoadWeeklyRoutines -> {
78- state.copy(routines = intent.routines)
79- }
80+ fun getPreviousWeek () {
81+ intent {
82+ val newWeek = state.selectedDate.minusWeeks(1 ).getCurrentWeekDays()
83+ reduce { state.copy(currentWeeks = newWeek, selectedDate = newWeek.first()) }
84+ }
85+ }
8086
81- is HomeIntent .OnDateSelect -> {
82- state.copy(selectedDate = intent.date)
83- }
8487
85- is HomeIntent .OnNextWeekClick -> {
86- val newWeek = state.selectedDate.plusWeeks(1 ).getCurrentWeekDays()
87- state.copy(
88- currentWeeks = newWeek,
89- selectedDate = newWeek.first(),
90- )
91- }
9288
93- is HomeIntent .OnPreviousWeekClick -> {
94- val newWeek = state.selectedDate.minusWeeks(1 ).getCurrentWeekDays()
95- state.copy(
96- currentWeeks = newWeek,
97- selectedDate = newWeek.first(),
98- )
99- }
10089
101- is HomeIntent .OnRoutineCompletionToggle -> {
102- updateMainRoutine(state, intent.routineId)
103- }
10490
105- is HomeIntent .OnSubRoutineCompletionToggle -> {
106- updateSubRoutine(state, intent.routineId, intent.subRoutineIndex)
10791 }
10892
109- is HomeIntent .LoadTodayEmotion -> {
110- state.copy(todayEmotion = intent.emotion)
111- }
11293
113- is HomeIntent .OnHelpClick -> {
114- sendSideEffect(HomeSideEffect .NavigateToGuide )
115- null
11694 }
11795
118- is HomeIntent .OnRegisterEmotionClick -> {
119- sendSideEffect(HomeSideEffect .NavigateToEmotion )
120- null
12196 }
12297
123- is HomeIntent .OnRegisterRoutineClick -> {
124- sendSideEffect(HomeSideEffect .NavigateToRegisterRoutine )
125- null
12698 }
12799
128- is HomeIntent .OnShowMoreRoutinesClick -> {
129- val selectedDate = stateFlow.value.selectedDate.toString()
130- sendSideEffect(HomeSideEffect .NavigateToRoutineList (selectedDate))
131- null
132100 }
133101
134- is HomeIntent .RoutineToggleCompletionFailure -> {
135- null
136102 }
137103 }
138- return newState
139104 }
140105
141106 private fun observeWriteRoutineEvent () {
142107 viewModelScope.launch {
143108 getWriteRoutineEventFlowUseCase().collect {
144- fetchWeeklyRoutines(stateFlow.value.currentWeeks)
109+ fetchWeeklyRoutines(container. stateFlow.value.currentWeeks)
145110 }
146111 }
147112 }
@@ -158,7 +123,7 @@ class HomeViewModel @Inject constructor(
158123 private fun observeRecommendRoutineEvent () {
159124 viewModelScope.launch {
160125 getOnBoardingRecommendRoutineEventFlowUseCase().collect {
161- fetchWeeklyRoutines(stateFlow.value.currentWeeks)
126+ fetchWeeklyRoutines(container. stateFlow.value.currentWeeks)
162127 }
163128 }
164129 }
@@ -189,50 +154,45 @@ class HomeViewModel @Inject constructor(
189154 }
190155
191156 private fun fetchUserProfile () {
192- sendIntent( HomeIntent . UpdateLoading ( true ))
193- viewModelScope.launch {
157+ intent {
158+ reduce { state.copy(isLoading = true ) }
194159 fetchUserProfileUseCase().fold(
195160 onSuccess = {
196- sendIntent(HomeIntent .LoadUserProfile (it.nickname))
197- sendIntent(HomeIntent .UpdateLoading (false ))
161+ reduce { state.copy(userNickname = it.nickname, isLoading = false ) }
198162 },
199- onFailure = { error ->
200- Log .e(" HomeViewModel" , " 유저 정보 가져오기 실패: ${error .message} " )
201- sendIntent( HomeIntent . UpdateLoading ( false ))
163+ onFailure = {
164+ Log .e(" HomeViewModel" , " 유저 정보 가져오기 실패: ${it .message} " )
165+ reduce { state.copy(isLoading = false ) }
202166 },
203167 )
204168 }
205169 }
206170
207171 private fun fetchWeeklyRoutines (currentWeeks : List <LocalDate >) {
208- sendIntent(HomeIntent .UpdateLoading (true ))
209- val startDate = currentWeeks.first().toString()
210- val endDate = currentWeeks.last().toString()
211- viewModelScope.launch {
212- fetchWeeklyRoutinesUseCase(startDate, endDate).fold(
213- onSuccess = { routines ->
214- sendIntent(HomeIntent .LoadWeeklyRoutines (routines.toUiModel()))
215- sendIntent(HomeIntent .UpdateLoading (false ))
172+ intent {
173+ reduce { state.copy(isLoading = true ) }
174+ fetchWeeklyRoutinesUseCase(currentWeeks).fold(
175+ onSuccess = {
176+ reduce { state.copy(isLoading = false , routineSchedule = it.toUiModel()) }
216177 },
217- onFailure = { error ->
218- Log .e(" HomeViewModel" , " 루틴 가져오기 실패: ${error .message} " )
219- sendIntent( HomeIntent . UpdateLoading ( false ))
178+ onFailure = {
179+ Log .e(" HomeViewModel" , " 루틴 가져오기 실패: ${it .message} " )
180+ reduce { state.copy(isLoading = false ) }
220181 },
221182 )
222183 }
223184 }
224185
225186 private fun fetchTodayEmotion (currentDate : LocalDate ) {
226- sendIntent( HomeIntent . UpdateLoading ( true ))
227- viewModelScope.launch {
187+ intent {
188+ reduce { state.copy(isLoading = true ) }
228189 fetchTodayEmotionUseCase(currentDate.toString()).fold(
229- onSuccess = { todayEmotion ->
230- sendIntent(HomeIntent .LoadTodayEmotion (todayEmotion?.toUiModel()))
231- sendIntent(HomeIntent .UpdateLoading (false ))
190+ onSuccess = {
191+ reduce { state.copy(isLoading = false , todayEmotion = it?.toUiModel()) }
232192 },
233- onFailure = { error ->
234- Log .e(" HomeViewModel" , " 나의 감정 실패: ${error .message} " )
235- sendIntent( HomeIntent . UpdateLoading ( false ))
193+ onFailure = {
194+ Log .e(" HomeViewModel" , " 나의 감정 실패: ${it .message} " )
195+ reduce { state.copy(isLoading = false ) }
236196 },
237197 )
238198 }
0 commit comments