Make ExtensionFilterViewModel collect languages only while subscribed (#3718)

Assisted-by: Claude:claude-opus-5
This commit is contained in:
AntsyLich
2026-08-08 11:58:18 +06:00
committed by GitHub
parent f6aad7497e
commit 864281af7d
2 changed files with 22 additions and 26 deletions
@@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.ui.browse.extension
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
@@ -22,7 +22,7 @@ class ExtensionFilterScreen : Screen() {
val context = LocalContext.current val context = LocalContext.current
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val viewModel = viewModel<ExtensionFilterViewModel>() val viewModel = viewModel<ExtensionFilterViewModel>()
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsStateWithLifecycle()
if (state is ExtensionFilterState.Loading) { if (state is ExtensionFilterState.Loading) {
LoadingScreen() LoadingScreen()
@@ -1,53 +1,49 @@
package eu.kanade.tachiyomi.ui.browse.extension package eu.kanade.tachiyomi.ui.browse.extension
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.extension.interactor.GetExtensionLanguages import eu.kanade.domain.extension.interactor.GetExtensionLanguages
import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleLanguage
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
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.receiveAsFlow import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import logcat.LogPriority import logcat.LogPriority
import mihon.core.viewmodel.StateViewModel
import tachiyomi.core.common.util.system.logcat import tachiyomi.core.common.util.system.logcat
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.time.Duration.Companion.seconds
class ExtensionFilterViewModel( class ExtensionFilterViewModel(
private val preferences: SourcePreferences = Injekt.get(), private val preferences: SourcePreferences = Injekt.get(),
private val getExtensionLanguages: GetExtensionLanguages = Injekt.get(), private val getExtensionLanguages: GetExtensionLanguages = Injekt.get(),
private val toggleLanguage: ToggleLanguage = Injekt.get(), private val toggleLanguage: ToggleLanguage = Injekt.get(),
) : StateViewModel<ExtensionFilterState>(ExtensionFilterState.Loading) { ) : ViewModel() {
private val _events: Channel<ExtensionFilterEvent> = Channel() private val _events: Channel<ExtensionFilterEvent> = Channel()
val events: Flow<ExtensionFilterEvent> = _events.receiveAsFlow() val events: Flow<ExtensionFilterEvent> = _events.receiveAsFlow()
init { val state: StateFlow<ExtensionFilterState> = combine(
viewModelScope.launch {
combine(
getExtensionLanguages.subscribe(), getExtensionLanguages.subscribe(),
preferences.enabledLanguages.changes(), preferences.enabledLanguages.changes(),
) { a, b -> a to b } ) { extensionLanguages, enabledLanguages ->
.catch { throwable ->
logcat(LogPriority.ERROR, throwable)
_events.send(ExtensionFilterEvent.FailedFetchingLanguages)
}
.collectLatest { (extensionLanguages, enabledLanguages) ->
mutableState.update {
ExtensionFilterState.Success( ExtensionFilterState.Success(
languages = extensionLanguages, languages = extensionLanguages,
enabledLanguages = enabledLanguages, enabledLanguages = enabledLanguages,
) )
} }
.catch { throwable ->
logcat(LogPriority.ERROR, throwable)
_events.send(ExtensionFilterEvent.FailedFetchingLanguages)
} }
} .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), ExtensionFilterState.Loading)
}
fun toggle(language: String) { fun toggle(language: String) {
toggleLanguage.await(language) toggleLanguage.await(language)