diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintFragment.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintFragment.kt index cdf313a6..83bd9cd9 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintFragment.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintFragment.kt @@ -5,6 +5,7 @@ import android.view.View import androidx.core.os.bundleOf import androidx.core.view.isVisible import androidx.fragment.app.viewModels +import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.navigation.fragment.findNavController import androidx.viewpager2.widget.ViewPager2 import com.google.firebase.analytics.FirebaseAnalytics @@ -29,6 +30,9 @@ import timber.log.Timber class HintFragment : BaseFragment(FragmentHintBinding::inflate) { private val viewModel: HintViewModel by viewModels() + private val gameSharedViewModel: com.nextroom.nextroom.presentation.ui.main.GameSharedViewModel by hiltNavGraphViewModels( + R.id.game_navigation + ) private val state: HintState get() = viewModel.container.stateFlow.value @@ -43,6 +47,21 @@ class HintFragment : BaseFragment(FragmentHintBinding::infl override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) FirebaseAnalytics.getInstance(requireContext()).logEvent("screen_view", bundleOf("screen_name" to "hint")) + + // Shared ViewModel에서 hint 수집 + viewLifecycleOwner.repeatOnStarted { + gameSharedViewModel.currentHint.collect { hint -> + hint?.let { viewModel.setHint(it) } + } + } + + // Shared ViewModel에서 subscribeStatus 수집 + viewLifecycleOwner.repeatOnStarted { + gameSharedViewModel.subscribeStatus.collect { subscribeStatus -> + viewModel.setSubscribeStatus(subscribeStatus) + } + } + initViews() viewModel.observe(viewLifecycleOwner, state = ::render, sideEffect = ::handleEvent) } diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintViewModel.kt index 8912962c..890dbe41 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintViewModel.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/hint/HintViewModel.kt @@ -1,6 +1,5 @@ package com.nextroom.nextroom.presentation.ui.hint -import androidx.lifecycle.SavedStateHandle import com.mangbaam.commonutil.DateTimeUtil import com.nextroom.nextroom.domain.repository.AdminRepository import com.nextroom.nextroom.domain.repository.DataStoreRepository @@ -18,7 +17,6 @@ import javax.inject.Inject @HiltViewModel class HintViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, private val timerRepository: TimerRepository, private val statsRepository: StatisticsRepository, private val adminRepository: AdminRepository, @@ -26,12 +24,7 @@ class HintViewModel @Inject constructor( ) : BaseViewModel() { override val container: Container = - container( - HintState( - hint = savedStateHandle.get("hint") ?: Hint(), - userSubscribeStatus = HintFragmentArgs.fromSavedStateHandle(savedStateHandle).subscribeStatus, - ) - ) + container(HintState()) private val state: HintState get() = container.stateFlow.value @@ -60,6 +53,20 @@ class HintViewModel @Inject constructor( reduce { state.copy(networkDisconnectedCount = count) } } + /** + * Called by HintFragment when hint is received from GameSharedViewModel + */ + fun setHint(hint: Hint) = intent { + reduce { state.copy(hint = hint) } + } + + /** + * Called by HintFragment when subscribeStatus is received from GameSharedViewModel + */ + fun setSubscribeStatus(subscribeStatus: com.nextroom.nextroom.domain.model.SubscribeStatus) = intent { + reduce { state.copy(userSubscribeStatus = subscribeStatus) } + } + fun openAnswer() = intent { reduce { state.copy(hint = state.hint.copy(answerOpened = true)) } // 정답 오픈 시간 통계 집계 diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/GameViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/GameViewModel.kt new file mode 100644 index 00000000..d5c28604 --- /dev/null +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/GameViewModel.kt @@ -0,0 +1,48 @@ +package com.nextroom.nextroom.presentation.ui.main + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import com.nextroom.nextroom.domain.model.SubscribeStatus +import com.nextroom.nextroom.presentation.model.Hint +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import javax.inject.Inject + +@HiltViewModel +class GameSharedViewModel @Inject constructor( + savedStateHandle: SavedStateHandle +) : ViewModel() { + + // subscribeStatus는 상위 navigation에서 전달받음 + private val _subscribeStatus = MutableStateFlow( + TimerFragmentArgs.fromSavedStateHandle(savedStateHandle).subscribeStatus + ) + val subscribeStatus: StateFlow = _subscribeStatus.asStateFlow() + + // hint는 TimerFragment에서 설정 + private val _currentHint = MutableStateFlow(null) + val currentHint: StateFlow = _currentHint.asStateFlow() + + /** + * Called by TimerFragment when user opens a hint + */ + fun setCurrentHint(hint: Hint) { + _currentHint.value = hint + } + + /** + * Called when HintFragment updates hint state (e.g., answer opened) + */ + fun updateCurrentHint(hint: Hint) { + _currentHint.value = hint + } + + /** + * Clear hint when returning to timer screen + */ + fun clearCurrentHint() { + _currentHint.value = null + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerEvent.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerEvent.kt index 9a6d776f..47d8e382 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerEvent.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerEvent.kt @@ -1,12 +1,10 @@ package com.nextroom.nextroom.presentation.ui.main -import com.nextroom.nextroom.domain.model.SubscribeStatus import com.nextroom.nextroom.presentation.model.Hint sealed interface TimerEvent { data class OnOpenHint( - val hint: Hint, - val subscribeStatus: SubscribeStatus + val hint: Hint ) : TimerEvent data object TimerFinish : TimerEvent diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerFragment.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerFragment.kt index 4be8a308..1f047e2c 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerFragment.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerFragment.kt @@ -12,6 +12,7 @@ import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.viewModels +import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.navigation.fragment.findNavController import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource @@ -50,6 +51,7 @@ class TimerFragment : BaseFragment(FragmentTimerBinding::i private val viewModel: TimerViewModel by viewModels() private val painterViewModel: PainterViewModel by activityViewModels() + private val gameSharedViewModel: GameSharedViewModel by hiltNavGraphViewModels(R.id.game_navigation) private var gameStartConfirmDialog: NRDialog? = null @@ -266,7 +268,8 @@ class TimerFragment : BaseFragment(FragmentTimerBinding::i when (event) { is TimerEvent.ClearHintCode -> binding.customCodeInput.setCode("") is TimerEvent.OnOpenHint -> { - val action = TimerFragmentDirections.moveToHintFragment(event.hint, event.subscribeStatus) + gameSharedViewModel.setCurrentHint(event.hint) + val action = TimerFragmentDirections.moveToHintFragment() findNavController().safeNavigate(action) viewModel.clearHintCode() } diff --git a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerViewModel.kt b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerViewModel.kt index 21dc38c0..de3e5907 100644 --- a/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerViewModel.kt +++ b/presentation/src/main/java/com/nextroom/nextroom/presentation/ui/main/TimerViewModel.kt @@ -208,8 +208,7 @@ class TimerViewModel @Inject constructor( answerOpened = state.answerOpenedHints.contains(hint.id), hintImageUrlList = hint.hintImageUrlList.toList(), answerImageUrlList = hint.answerImageUrlList.toList() - ), - TimerFragmentArgs.fromSavedStateHandle(savedStateHandle).subscribeStatus + ) ), ) setGameState() diff --git a/presentation/src/main/res/navigation/game_navigation.xml b/presentation/src/main/res/navigation/game_navigation.xml index 995be402..46fcd5c3 100644 --- a/presentation/src/main/res/navigation/game_navigation.xml +++ b/presentation/src/main/res/navigation/game_navigation.xml @@ -12,14 +12,7 @@ - - - + app:destination="@id/hint_fragment" /> @@ -43,12 +36,6 @@ - -