MainViewModel.kt
package com.louisfn.somovie.app.ui.main
import androidx.annotation.AnyThread
import androidx.lifecycle.viewModelScope
import com.louisfn.somovie.core.common.annotation.DefaultDispatcher
import com.louisfn.somovie.core.logger.Logger
import com.louisfn.somovie.domain.usecase.global.TmdbConfigurationInteractor
import com.louisfn.somovie.ui.common.LoadingManager
import com.louisfn.somovie.ui.common.base.BaseViewModel
import com.louisfn.somovie.ui.common.base.NoneAction
import com.louisfn.somovie.ui.common.error.ErrorsDispatcher
import com.louisfn.somovie.ui.common.model.ImmutableList
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
internal class MainViewModel @Inject constructor(
@DefaultDispatcher defaultDispatcher: CoroutineDispatcher,
private val errorsDispatcher: ErrorsDispatcher,
private val configurationInteractor: TmdbConfigurationInteractor,
) : BaseViewModel<NoneAction>(defaultDispatcher) {
private val loadingManager = LoadingManager()
val uiState: StateFlow<MainUiState> =
loadingManager
.isLoadingChanges()
.map(::createMainUiState)
.flowOn(defaultDispatcher)
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(),
initialValue = MainUiState.Loading,
)
val errors = errorsDispatcher
.errorChanges()
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
ImmutableList(),
)
init {
viewModelScope.launch {
refreshAppData()
}
}
override fun onCleared() {
errorsDispatcher.cancel()
super.onCleared()
}
@AnyThread
private fun createMainUiState(isRefreshing: Boolean) =
if (isRefreshing) MainUiState.Loading
else MainUiState.Content
@AnyThread
private suspend fun refreshAppData() {
loadingManager.start()
refreshConfiguration()
loadingManager.stop()
}
@AnyThread
private suspend fun refreshConfiguration() {
try {
configurationInteractor.refresh()
} catch (e: Exception) {
Logger.e(e)
}
}
}