Make CategoryViewModel collect categories only while subscribed (#3720)
Assisted-by: Claude:claude-opus-5
This commit is contained in:
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user