Make SourcesFilterViewModel collect sources only while subscribed (#3719)

Assisted-by: Claude:claude-opus-5
This commit is contained in:
AntsyLich
2026-08-08 11:58:30 +06:00
committed by GitHub
parent 864281af7d
commit bb9767c9df
2 changed files with 21 additions and 31 deletions
@@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.ui.browse.source
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
@@ -20,7 +20,7 @@ class SourcesFilterScreen : Screen() {
override fun Content() {
val navigator = LocalNavigator.currentOrThrow
val viewModel = viewModel<SourcesFilterViewModel>()
val state by viewModel.state.collectAsState()
val state by viewModel.state.collectAsStateWithLifecycle()
if (state is SourcesFilterViewModel.State.Loading) {
LoadingScreen()
@@ -1,54 +1,44 @@
package eu.kanade.tachiyomi.ui.browse.source
import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import eu.kanade.domain.source.interactor.GetLanguagesWithSources
import eu.kanade.domain.source.interactor.ToggleLanguage
import eu.kanade.domain.source.interactor.ToggleSource
import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.WhileSubscribed
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import mihon.core.viewmodel.StateViewModel
import kotlinx.coroutines.flow.stateIn
import tachiyomi.domain.source.model.Source
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.SortedMap
import kotlin.time.Duration.Companion.seconds
class SourcesFilterViewModel(
private val preferences: SourcePreferences = Injekt.get(),
private val getLanguagesWithSources: GetLanguagesWithSources = Injekt.get(),
private val toggleSource: ToggleSource = Injekt.get(),
private val toggleLanguage: ToggleLanguage = Injekt.get(),
) : StateViewModel<SourcesFilterViewModel.State>(State.Loading) {
) : ViewModel() {
init {
viewModelScope.launch {
combine(
getLanguagesWithSources.subscribe(),
preferences.enabledLanguages.changes(),
preferences.disabledSources.changes(),
) { a, b, c -> Triple(a, b, c) }
.catch { throwable ->
mutableState.update {
State.Error(
throwable = throwable,
)
}
}
.collectLatest { (languagesWithSources, enabledLanguages, disabledSources) ->
mutableState.update {
State.Success(
items = languagesWithSources,
enabledLanguages = enabledLanguages,
disabledSources = disabledSources,
)
}
}
}
val state: StateFlow<State> = combine(
getLanguagesWithSources.subscribe(),
preferences.enabledLanguages.changes(),
preferences.disabledSources.changes(),
) { languagesWithSources, enabledLanguages, disabledSources ->
State.Success(
items = languagesWithSources,
enabledLanguages = enabledLanguages,
disabledSources = disabledSources,
)
}
.catch<State> { throwable -> emit(State.Error(throwable = throwable)) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), State.Loading)
fun toggleSource(source: Source) {
toggleSource.await(source)