package dev.privacyllc.period.navigation import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dev.privacyllc.period.core.datastore.UserPreferencesRepository import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject enum class RootState { Loading, Onboarding, Ready } @HiltViewModel class RootViewModel @Inject constructor( preferences: UserPreferencesRepository, private val notificationActions: dev.privacyllc.period.notifications.NotificationActionHandler, ) : ViewModel() { /** * Apply an action tapped on a notification. * * Handled once per intent by the caller. Doing it here rather than in the * activity keeps it off the main thread and, more importantly, routes it * through the same repository call the in-app button uses — two paths into * one piece of state is how a lock-screen "Not yet" and an in-app "Not yet" * come to mean slightly different things. */ fun onNotificationAction(action: String?) { if (action == null) return viewModelScope.launch { notificationActions.handle(action) } } /** * Set when onboarding finishes, so the switch happens immediately rather * than waiting for the preference write to travel back through DataStore — * which is fast, but not instant, and a visible flicker on the last tap of * onboarding is a poor first impression. */ private val finishedThisSession = MutableStateFlow(false) val state: StateFlow = combine( preferences.preferences.map { it.onboardingCompleted }, finishedThisSession, ) { completed, finished -> if (completed || finished) RootState.Ready else RootState.Onboarding }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), RootState.Loading) fun onboardingFinished() { finishedThisSession.value = true } }