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.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
@@ -20,7 +20,7 @@ class SourcesFilterScreen : Screen() {
override fun Content() { override fun Content() {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val viewModel = viewModel<SourcesFilterViewModel>() val viewModel = viewModel<SourcesFilterViewModel>()
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsStateWithLifecycle()
if (state is SourcesFilterViewModel.State.Loading) { if (state is SourcesFilterViewModel.State.Loading) {
LoadingScreen() LoadingScreen()
@@ -1,54 +1,44 @@
package eu.kanade.tachiyomi.ui.browse.source package eu.kanade.tachiyomi.ui.browse.source
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import eu.kanade.domain.source.interactor.GetLanguagesWithSources import eu.kanade.domain.source.interactor.GetLanguagesWithSources
import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleLanguage
import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSource
import eu.kanade.domain.source.service.SourcePreferences 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.catch
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import mihon.core.viewmodel.StateViewModel
import tachiyomi.domain.source.model.Source import tachiyomi.domain.source.model.Source
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.util.SortedMap import java.util.SortedMap
import kotlin.time.Duration.Companion.seconds
class SourcesFilterViewModel( class SourcesFilterViewModel(
private val preferences: SourcePreferences = Injekt.get(), private val preferences: SourcePreferences = Injekt.get(),
private val getLanguagesWithSources: GetLanguagesWithSources = Injekt.get(), private val getLanguagesWithSources: GetLanguagesWithSources = Injekt.get(),
private val toggleSource: ToggleSource = Injekt.get(), private val toggleSource: ToggleSource = Injekt.get(),
private val toggleLanguage: ToggleLanguage = Injekt.get(), private val toggleLanguage: ToggleLanguage = Injekt.get(),
) : StateViewModel<SourcesFilterViewModel.State>(State.Loading) { ) : ViewModel() {
init { val state: StateFlow<State> = combine(
viewModelScope.launch {
combine(
getLanguagesWithSources.subscribe(), getLanguagesWithSources.subscribe(),
preferences.enabledLanguages.changes(), preferences.enabledLanguages.changes(),
preferences.disabledSources.changes(), preferences.disabledSources.changes(),
) { a, b, c -> Triple(a, b, c) } ) { languagesWithSources, enabledLanguages, disabledSources ->
.catch { throwable ->
mutableState.update {
State.Error(
throwable = throwable,
)
}
}
.collectLatest { (languagesWithSources, enabledLanguages, disabledSources) ->
mutableState.update {
State.Success( State.Success(
items = languagesWithSources, items = languagesWithSources,
enabledLanguages = enabledLanguages, enabledLanguages = enabledLanguages,
disabledSources = disabledSources, disabledSources = disabledSources,
) )
} }
} .catch<State> { throwable -> emit(State.Error(throwable = throwable)) }
} .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), State.Loading)
}
fun toggleSource(source: Source) { fun toggleSource(source: Source) {
toggleSource.await(source) toggleSource.await(source)