Make CategoryViewModel collect categories only while subscribed (#3720)

Assisted-by: Claude:claude-opus-5
This commit is contained in:
AntsyLich
2026-08-08 11:58:41 +06:00
committed by GitHub
parent bb9767c9df
commit 2aec7d19c0
2 changed files with 24 additions and 29 deletions
@@ -2,10 +2,10 @@ package eu.kanade.tachiyomi.ui.category
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.compose.ui.util.fastMap import androidx.compose.ui.util.fastMap
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
@@ -26,7 +26,7 @@ class CategoryScreen : Screen() {
val navigator = LocalNavigator.currentOrThrow val navigator = LocalNavigator.currentOrThrow
val viewModel = viewModel<CategoryViewModel>() val viewModel = viewModel<CategoryViewModel>()
val state by viewModel.state.collectAsState() val state by viewModel.state.collectAsStateWithLifecycle()
if (state is CategoryScreenState.Loading) { if (state is CategoryScreenState.Loading) {
LoadingScreen() LoadingScreen()
@@ -1,14 +1,19 @@
package eu.kanade.tachiyomi.ui.category package eu.kanade.tachiyomi.ui.category
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.channels.Channel 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.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mihon.core.viewmodel.StateViewModel
import tachiyomi.domain.category.interactor.CreateCategoryWithName import tachiyomi.domain.category.interactor.CreateCategoryWithName
import tachiyomi.domain.category.interactor.DeleteCategory import tachiyomi.domain.category.interactor.DeleteCategory
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
@@ -18,6 +23,7 @@ import tachiyomi.domain.category.model.Category
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
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 CategoryViewModel( class CategoryViewModel(
private val getCategories: GetCategories = Injekt.get(), private val getCategories: GetCategories = Injekt.get(),
@@ -25,24 +31,23 @@ class CategoryViewModel(
private val deleteCategory: DeleteCategory = Injekt.get(), private val deleteCategory: DeleteCategory = Injekt.get(),
private val reorderCategory: ReorderCategory = Injekt.get(), private val reorderCategory: ReorderCategory = Injekt.get(),
private val renameCategory: RenameCategory = Injekt.get(), private val renameCategory: RenameCategory = Injekt.get(),
) : StateViewModel<CategoryScreenState>(CategoryScreenState.Loading) { ) : ViewModel() {
private val _events: Channel<CategoryEvent> = Channel() private val _events: Channel<CategoryEvent> = Channel()
val events = _events.receiveAsFlow() val events = _events.receiveAsFlow()
init { private val dialog = MutableStateFlow<CategoryDialog?>(null)
viewModelScope.launch {
getCategories.subscribe() val state: StateFlow<CategoryScreenState> = combine(
.collectLatest { categories -> getCategories.subscribe(),
mutableState.update { dialog,
CategoryScreenState.Success( ) { categories, dialog ->
categories = categories CategoryScreenState.Success(
.filterNot(Category::isSystemCategory), categories = categories.filterNot(Category::isSystemCategory),
) dialog = dialog,
} )
}
}
} }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5.seconds), CategoryScreenState.Loading)
fun createCategory(name: String) { fun createCategory(name: String) {
viewModelScope.launch { viewModelScope.launch {
@@ -81,21 +86,11 @@ class CategoryViewModel(
} }
fun showDialog(dialog: CategoryDialog) { fun showDialog(dialog: CategoryDialog) {
mutableState.update { this.dialog.update { dialog }
when (it) {
CategoryScreenState.Loading -> it
is CategoryScreenState.Success -> it.copy(dialog = dialog)
}
}
} }
fun dismissDialog() { fun dismissDialog() {
mutableState.update { dialog.update { null }
when (it) {
CategoryScreenState.Loading -> it
is CategoryScreenState.Success -> it.copy(dialog = null)
}
}
} }
} }