From 2aec7d19c08067814d287df40a0985cca89851a2 Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+AntsyLich@users.noreply.github.com> Date: Sat, 8 Aug 2026 11:58:41 +0600 Subject: [PATCH] Make CategoryViewModel collect categories only while subscribed (#3720) Assisted-by: Claude:claude-opus-5 --- .../tachiyomi/ui/category/CategoryScreen.kt | 4 +- .../ui/category/CategoryViewModel.kt | 49 +++++++++---------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt index 180bdd050..3102e8d8c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryScreen.kt @@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.ui.category 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.compose.ui.util.fastMap +import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -26,7 +26,7 @@ class CategoryScreen : Screen() { val navigator = LocalNavigator.currentOrThrow val viewModel = viewModel() - val state by viewModel.state.collectAsState() + val state by viewModel.state.collectAsStateWithLifecycle() if (state is CategoryScreenState.Loading) { LoadingScreen() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryViewModel.kt index 9dc3bb72d..3d384c826 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryViewModel.kt @@ -1,14 +1,19 @@ package eu.kanade.tachiyomi.ui.category import androidx.compose.runtime.Immutable +import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dev.icerock.moko.resources.StringResource import kotlinx.coroutines.channels.Channel -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.receiveAsFlow +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import mihon.core.viewmodel.StateViewModel import tachiyomi.domain.category.interactor.CreateCategoryWithName import tachiyomi.domain.category.interactor.DeleteCategory import tachiyomi.domain.category.interactor.GetCategories @@ -18,6 +23,7 @@ import tachiyomi.domain.category.model.Category import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import kotlin.time.Duration.Companion.seconds class CategoryViewModel( private val getCategories: GetCategories = Injekt.get(), @@ -25,24 +31,23 @@ class CategoryViewModel( private val deleteCategory: DeleteCategory = Injekt.get(), private val reorderCategory: ReorderCategory = Injekt.get(), private val renameCategory: RenameCategory = Injekt.get(), -) : StateViewModel(CategoryScreenState.Loading) { +) : ViewModel() { private val _events: Channel = Channel() val events = _events.receiveAsFlow() - init { - viewModelScope.launch { - getCategories.subscribe() - .collectLatest { categories -> - mutableState.update { - CategoryScreenState.Success( - categories = categories - .filterNot(Category::isSystemCategory), - ) - } - } - } + private val dialog = MutableStateFlow(null) + + val state: StateFlow = combine( + getCategories.subscribe(), + dialog, + ) { categories, dialog -> + CategoryScreenState.Success( + categories = categories.filterNot(Category::isSystemCategory), + dialog = dialog, + ) } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), CategoryScreenState.Loading) fun createCategory(name: String) { viewModelScope.launch { @@ -81,21 +86,11 @@ class CategoryViewModel( } fun showDialog(dialog: CategoryDialog) { - mutableState.update { - when (it) { - CategoryScreenState.Loading -> it - is CategoryScreenState.Success -> it.copy(dialog = dialog) - } - } + this.dialog.update { dialog } } fun dismissDialog() { - mutableState.update { - when (it) { - CategoryScreenState.Loading -> it - is CategoryScreenState.Success -> it.copy(dialog = null) - } - } + dialog.update { null } } }