From bb9767c9df948d94ea0d7dce91f24bfc6a56e9e2 Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Sat, 8 Aug 2026 11:58:30 +0600 Subject: [PATCH] Make SourcesFilterViewModel collect sources only while subscribed (#3719) Assisted-by: Claude:claude-opus-5 --- .../ui/browse/source/SourcesFilterScreen.kt | 4 +- .../browse/source/SourcesFilterViewModel.kt | 48 ++++++++----------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt index 717d0a6b1..f0ff2f703 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterScreen.kt @@ -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() - val state by viewModel.state.collectAsState() + val state by viewModel.state.collectAsStateWithLifecycle() if (state is SourcesFilterViewModel.State.Loading) { LoadingScreen() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterViewModel.kt index 6c1aa6383..46aa7ecb3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesFilterViewModel.kt @@ -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(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 = combine( + getLanguagesWithSources.subscribe(), + preferences.enabledLanguages.changes(), + preferences.disabledSources.changes(), + ) { languagesWithSources, enabledLanguages, disabledSources -> + State.Success( + items = languagesWithSources, + enabledLanguages = enabledLanguages, + disabledSources = disabledSources, + ) } + .catch { throwable -> emit(State.Error(throwable = throwable)) } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), State.Loading) fun toggleSource(source: Source) { toggleSource.await(source)