Make UpcomingViewModel collect manga only while subscribed (#3725)
Assisted-by: Claude:claude-opus-5
This commit is contained in:
@@ -3,23 +3,29 @@ package mihon.feature.upcoming
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.util.fastMap
|
||||
import androidx.compose.ui.util.fastMapIndexedNotNull
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import eu.kanade.core.util.insertSeparatorsReversed
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.YearMonth
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
import kotlinx.datetime.yearMonth
|
||||
import mihon.core.viewmodel.StateViewModel
|
||||
import mihon.domain.upcoming.interactor.GetUpcomingManga
|
||||
import tachiyomi.core.common.preference.getAndSet
|
||||
import tachiyomi.core.common.util.lang.launchIO
|
||||
import tachiyomi.domain.category.interactor.GetCategories
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
@@ -27,39 +33,57 @@ import tachiyomi.domain.upcoming.service.UpcomingPreferences
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class UpcomingViewModel(
|
||||
private val getUpcomingManga: GetUpcomingManga = Injekt.get(),
|
||||
val getCategories: GetCategories = Injekt.get(),
|
||||
val upcomingPreferences: UpcomingPreferences = Injekt.get(),
|
||||
) : StateViewModel<UpcomingViewModel.State>(State()) {
|
||||
) : ViewModel() {
|
||||
|
||||
val excludedCategories = upcomingPreferences.filterExcludedCategories
|
||||
val includedCategories = upcomingPreferences.filterIncludedCategories
|
||||
|
||||
init {
|
||||
viewModelScope.launchIO {
|
||||
getUpcomingItemPreferenceFlow()
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest {
|
||||
getUpcomingManga.subscribe(
|
||||
excludedCategories = it.filterExcludedCategories,
|
||||
includedCategories = it.filterIncludedCategories,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
}
|
||||
.collectLatest {
|
||||
mutableState.update { state ->
|
||||
val upcomingItems = it.toUpcomingUIModels()
|
||||
state.copy(
|
||||
items = upcomingItems,
|
||||
events = upcomingItems.toEvents(),
|
||||
headerIndexes = upcomingItems.getHeaderIndexes(),
|
||||
)
|
||||
}
|
||||
}
|
||||
private val selectedYearMonth = MutableStateFlow(
|
||||
value = Clock.System.now()
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
.yearMonth,
|
||||
)
|
||||
|
||||
private val dialog = MutableStateFlow<Dialog?>(null)
|
||||
|
||||
private val upcoming = getUpcomingItemPreferenceFlow()
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest {
|
||||
getUpcomingManga.subscribe(
|
||||
excludedCategories = it.filterExcludedCategories,
|
||||
includedCategories = it.filterIncludedCategories,
|
||||
)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.map { it.toUpcomingUIModels() }
|
||||
.flowOn(Dispatchers.IO)
|
||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), emptyList())
|
||||
|
||||
val state: StateFlow<State> = combine(
|
||||
upcoming,
|
||||
selectedYearMonth,
|
||||
dialog,
|
||||
) { upcoming, selectedYearMonth, dialog ->
|
||||
State(
|
||||
selectedYearMonth = selectedYearMonth,
|
||||
items = upcoming,
|
||||
events = upcoming.toEvents(),
|
||||
headerIndexes = upcoming.getHeaderIndexes(),
|
||||
dialog = dialog,
|
||||
)
|
||||
}
|
||||
.stateIn(
|
||||
viewModelScope,
|
||||
SharingStarted.WhileSubscribed(5.seconds),
|
||||
State(selectedYearMonth = selectedYearMonth.value),
|
||||
)
|
||||
|
||||
private fun List<Manga>.toUpcomingUIModels(): List<UpcomingUIModel> {
|
||||
var mangaCount = 0
|
||||
@@ -101,7 +125,7 @@ class UpcomingViewModel(
|
||||
}
|
||||
|
||||
fun setSelectedYearMonth(yearMonth: YearMonth) {
|
||||
mutableState.update { it.copy(selectedYearMonth = yearMonth) }
|
||||
selectedYearMonth.update { yearMonth }
|
||||
}
|
||||
|
||||
private fun getUpcomingItemPreferenceFlow(): Flow<ItemPreferences> {
|
||||
@@ -117,11 +141,11 @@ class UpcomingViewModel(
|
||||
}
|
||||
|
||||
fun resetDialog() {
|
||||
mutableState.update { it.copy(dialog = null) }
|
||||
dialog.update { null }
|
||||
}
|
||||
|
||||
fun showFilterDialog() {
|
||||
mutableState.update { it.copy(dialog = Dialog.FilterSheet) }
|
||||
dialog.update { Dialog.FilterSheet }
|
||||
}
|
||||
|
||||
fun cycleCategory(category: Category) {
|
||||
@@ -143,10 +167,7 @@ class UpcomingViewModel(
|
||||
)
|
||||
|
||||
data class State(
|
||||
val selectedYearMonth: YearMonth = Clock.System.now()
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.date
|
||||
.yearMonth,
|
||||
val selectedYearMonth: YearMonth,
|
||||
val items: List<UpcomingUIModel> = listOf(),
|
||||
val events: Map<LocalDate, Int> = mapOf(),
|
||||
val headerIndexes: Map<LocalDate, Int> = mapOf(),
|
||||
|
||||
Reference in New Issue
Block a user