mirror of
https://github.com/Suwayomi/TachideskJUI.git
synced 2026-01-06 03:42:33 +01:00
Fix infinite loading in library
This commit is contained in:
@@ -33,8 +33,6 @@ class LibraryScreen : BaseScreen() {
|
||||
displayMode = vm.displayMode.collectAsState().value,
|
||||
gridColumns = vm.gridColumns.collectAsState().value,
|
||||
gridSize = vm.gridSize.collectAsState().value,
|
||||
isLoading = vm.isLoading.collectAsState().value,
|
||||
error = vm.error.collectAsState().value,
|
||||
query = vm.query.collectAsState().value,
|
||||
updateQuery = vm::updateQuery,
|
||||
getLibraryForPage = { vm.getLibraryForCategoryId(it).collectAsState() },
|
||||
|
||||
@@ -52,6 +52,20 @@ import me.tatarka.inject.annotations.Assisted
|
||||
import me.tatarka.inject.annotations.Inject
|
||||
import org.lighthousegames.logging.logging
|
||||
|
||||
@Stable
|
||||
sealed class LibraryState {
|
||||
@Stable
|
||||
object Loading : LibraryState()
|
||||
|
||||
@Stable
|
||||
data class Failed(val e: Throwable) : LibraryState()
|
||||
|
||||
@Stable
|
||||
data class Loaded(
|
||||
val categories: ImmutableList<Category>
|
||||
) : LibraryState()
|
||||
}
|
||||
|
||||
@Stable
|
||||
sealed class CategoryState {
|
||||
@Stable
|
||||
@@ -68,7 +82,7 @@ sealed class CategoryState {
|
||||
}
|
||||
|
||||
private typealias LibraryMap = MutableMap<Long, MutableStateFlow<CategoryState>>
|
||||
private data class Library(val categories: MutableStateFlow<ImmutableList<Category>>, val mangaMap: LibraryMap)
|
||||
private data class Library(val categories: MutableStateFlow<LibraryState>, val mangaMap: LibraryMap)
|
||||
|
||||
private fun LibraryMap.getManga(id: Long) =
|
||||
getOrPut(id) {
|
||||
@@ -98,7 +112,7 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
contextWrapper: ContextWrapper,
|
||||
@Assisted private val savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel(contextWrapper) {
|
||||
private val library = Library(MutableStateFlow(persistentListOf()), mutableMapOf())
|
||||
private val library = Library(MutableStateFlow(LibraryState.Loading), mutableMapOf())
|
||||
val categories = library.categories.asStateFlow()
|
||||
|
||||
private val _selectedCategoryIndex by savedStateHandle.getStateFlow { 0 }
|
||||
@@ -140,12 +154,6 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val _isLoading = MutableStateFlow(true)
|
||||
val isLoading = _isLoading.asStateFlow()
|
||||
|
||||
private val _error = MutableStateFlow<String?>(null)
|
||||
val error = _error.asStateFlow()
|
||||
|
||||
private val _query by savedStateHandle.getStateFlow { "" }
|
||||
val query = _query.asStateFlow()
|
||||
|
||||
@@ -158,14 +166,16 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
private fun getLibrary() {
|
||||
_isLoading.value = true
|
||||
library.categories.value = LibraryState.Loading
|
||||
getCategories.asFlow()
|
||||
.onEach { categories ->
|
||||
if (categories.isEmpty()) {
|
||||
throw Exception(MR.strings.library_empty.toPlatformString())
|
||||
}
|
||||
library.categories.value = categories.sortedBy { it.order }
|
||||
.toImmutableList()
|
||||
library.categories.value = LibraryState.Loaded(
|
||||
categories.sortedBy { it.order }
|
||||
.toImmutableList()
|
||||
)
|
||||
categories.forEach { category ->
|
||||
getMangaListFromCategory.asFlow(category)
|
||||
.onEach {
|
||||
@@ -181,12 +191,10 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
}
|
||||
.launchIn(coroutineScope)
|
||||
}
|
||||
_isLoading.value = false
|
||||
}
|
||||
.catch {
|
||||
_error.value = it.message
|
||||
library.categories.value = LibraryState.Failed(it)
|
||||
log.warn(it) { "Failed to get categories" }
|
||||
_isLoading.value = false
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
@@ -273,7 +281,7 @@ class LibraryScreenViewModel @Inject constructor(
|
||||
.filter { mangaMapEntry ->
|
||||
(mangaMapEntry.value.value as? CategoryState.Loaded)?.items?.value?.firstOrNull { it.id == mangaId } != null
|
||||
}
|
||||
.map { (id) -> library.categories.value.first { it.id == id } }
|
||||
.mapNotNull { (id) -> (library.categories.value as? LibraryState.Loaded)?.categories?.first { it.id == id } }
|
||||
}
|
||||
|
||||
fun removeManga(mangaId: Long) {
|
||||
|
||||
@@ -41,7 +41,6 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.unit.dp
|
||||
import ca.gosyer.jui.domain.base.WebsocketService
|
||||
import ca.gosyer.jui.domain.category.model.Category
|
||||
import ca.gosyer.jui.domain.library.model.DisplayMode
|
||||
import ca.gosyer.jui.i18n.MR
|
||||
import ca.gosyer.jui.ui.base.navigation.ActionItem
|
||||
@@ -49,8 +48,10 @@ import ca.gosyer.jui.ui.base.navigation.BackHandler
|
||||
import ca.gosyer.jui.ui.base.navigation.OverflowMode
|
||||
import ca.gosyer.jui.ui.base.navigation.Toolbar
|
||||
import ca.gosyer.jui.ui.library.CategoryState
|
||||
import ca.gosyer.jui.ui.library.LibraryState
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySheet
|
||||
import ca.gosyer.jui.ui.library.settings.LibrarySideMenu
|
||||
import ca.gosyer.jui.uicore.components.ErrorScreen
|
||||
import ca.gosyer.jui.uicore.components.LoadingScreen
|
||||
import ca.gosyer.jui.uicore.insets.navigationBars
|
||||
import ca.gosyer.jui.uicore.insets.statusBars
|
||||
@@ -60,13 +61,11 @@ import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@Composable
|
||||
fun LibraryScreenContent(
|
||||
categories: ImmutableList<Category>,
|
||||
categories: LibraryState,
|
||||
selectedCategoryIndex: Int,
|
||||
displayMode: DisplayMode,
|
||||
gridColumns: Int,
|
||||
gridSize: Int,
|
||||
isLoading: Boolean,
|
||||
error: String?,
|
||||
query: String,
|
||||
updateQuery: (String) -> Unit,
|
||||
getLibraryForPage: @Composable (Long) -> State<CategoryState>,
|
||||
@@ -110,8 +109,6 @@ fun LibraryScreenContent(
|
||||
displayMode = displayMode,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
isLoading = isLoading,
|
||||
error = error,
|
||||
query = query,
|
||||
updateQuery = updateQuery,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
@@ -137,8 +134,6 @@ fun LibraryScreenContent(
|
||||
displayMode = displayMode,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
isLoading = isLoading,
|
||||
error = error,
|
||||
query = query,
|
||||
updateQuery = updateQuery,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
@@ -165,13 +160,11 @@ fun LibraryScreenContent(
|
||||
@Composable
|
||||
fun WideLibraryScreenContent(
|
||||
pagerState: PagerState,
|
||||
categories: ImmutableList<Category>,
|
||||
categories: LibraryState,
|
||||
selectedCategoryIndex: Int,
|
||||
displayMode: DisplayMode,
|
||||
gridColumns: Int,
|
||||
gridSize: Int,
|
||||
isLoading: Boolean,
|
||||
error: String?,
|
||||
query: String,
|
||||
updateQuery: (String) -> Unit,
|
||||
getLibraryForPage: @Composable (Long) -> State<CategoryState>,
|
||||
@@ -208,57 +201,65 @@ fun WideLibraryScreenContent(
|
||||
)
|
||||
},
|
||||
)
|
||||
LibraryTabs(
|
||||
visible = true, // vm.showCategoryTabs,
|
||||
pagerState = pagerState,
|
||||
categories = categories,
|
||||
selectedPage = selectedCategoryIndex,
|
||||
onPageChanged = onPageChanged,
|
||||
)
|
||||
if (categories is LibraryState.Loaded) {
|
||||
LibraryTabs(
|
||||
visible = true, // vm.showCategoryTabs,
|
||||
pagerState = pagerState,
|
||||
categories = categories.categories,
|
||||
selectedPage = selectedCategoryIndex,
|
||||
onPageChanged = onPageChanged,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
) { padding ->
|
||||
Box(Modifier.padding(padding)) {
|
||||
if (categories.isEmpty()) {
|
||||
LoadingScreen(isLoading, errorMessage = error)
|
||||
} else {
|
||||
LibraryPager(
|
||||
pagerState = pagerState,
|
||||
categories = categories,
|
||||
displayMode = displayMode,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
|
||||
if (showingMenu) {
|
||||
Box(
|
||||
Modifier.fillMaxSize().pointerInput(isLoading) {
|
||||
forEachGesture {
|
||||
detectTapGestures {
|
||||
setShowingMenu(false)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
when (categories) {
|
||||
is LibraryState.Failed -> {
|
||||
ErrorScreen(categories.e.message)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
showingMenu,
|
||||
enter = fadeIn() + slideInHorizontally(initialOffsetX = { it * 2 }),
|
||||
exit = fadeOut() + slideOutHorizontally(targetOffsetX = { it * 2 }),
|
||||
modifier = Modifier.align(Alignment.TopEnd),
|
||||
) {
|
||||
LibrarySideMenu(
|
||||
libraryFilters = libraryFilters,
|
||||
librarySort = librarySort,
|
||||
libraryDisplay = libraryDisplay,
|
||||
LibraryState.Loading -> {
|
||||
LoadingScreen(true)
|
||||
}
|
||||
is LibraryState.Loaded -> {
|
||||
LibraryPager(
|
||||
pagerState = pagerState,
|
||||
categories = categories.categories,
|
||||
displayMode = displayMode,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
|
||||
if (showingMenu) {
|
||||
Box(
|
||||
Modifier.fillMaxSize().pointerInput(Unit) {
|
||||
forEachGesture {
|
||||
detectTapGestures {
|
||||
setShowingMenu(false)
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
AnimatedVisibility(
|
||||
showingMenu,
|
||||
enter = fadeIn() + slideInHorizontally(initialOffsetX = { it * 2 }),
|
||||
exit = fadeOut() + slideOutHorizontally(targetOffsetX = { it * 2 }),
|
||||
modifier = Modifier.align(Alignment.TopEnd),
|
||||
) {
|
||||
LibrarySideMenu(
|
||||
libraryFilters = libraryFilters,
|
||||
librarySort = librarySort,
|
||||
libraryDisplay = libraryDisplay,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,13 +269,11 @@ fun WideLibraryScreenContent(
|
||||
@Composable
|
||||
fun ThinLibraryScreenContent(
|
||||
pagerState: PagerState,
|
||||
categories: ImmutableList<Category>,
|
||||
categories: LibraryState,
|
||||
selectedCategoryIndex: Int,
|
||||
displayMode: DisplayMode,
|
||||
gridColumns: Int,
|
||||
gridSize: Int,
|
||||
isLoading: Boolean,
|
||||
error: String?,
|
||||
query: String,
|
||||
updateQuery: (String) -> Unit,
|
||||
getLibraryForPage: @Composable (Long) -> State<CategoryState>,
|
||||
@@ -334,13 +333,15 @@ fun ThinLibraryScreenContent(
|
||||
)
|
||||
},
|
||||
)
|
||||
LibraryTabs(
|
||||
visible = true, // vm.showCategoryTabs,
|
||||
pagerState = pagerState,
|
||||
categories = categories,
|
||||
selectedPage = selectedCategoryIndex,
|
||||
onPageChanged = onPageChanged,
|
||||
)
|
||||
if (categories is LibraryState.Loaded) {
|
||||
LibraryTabs(
|
||||
visible = true, // vm.showCategoryTabs,
|
||||
pagerState = pagerState,
|
||||
categories = categories.categories,
|
||||
selectedPage = selectedCategoryIndex,
|
||||
onPageChanged = onPageChanged,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
) { padding ->
|
||||
@@ -355,23 +356,29 @@ fun ThinLibraryScreenContent(
|
||||
)
|
||||
},
|
||||
) {
|
||||
if (categories.isEmpty()) {
|
||||
LoadingScreen(isLoading, errorMessage = error)
|
||||
} else {
|
||||
LibraryPager(
|
||||
pagerState = pagerState,
|
||||
categories = categories,
|
||||
displayMode = displayMode,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
when (categories) {
|
||||
LibraryState.Loading -> {
|
||||
LoadingScreen(true)
|
||||
}
|
||||
is LibraryState.Failed -> {
|
||||
ErrorScreen(categories.e.message)
|
||||
}
|
||||
is LibraryState.Loaded -> {
|
||||
LibraryPager(
|
||||
pagerState = pagerState,
|
||||
categories = categories.categories,
|
||||
displayMode = displayMode,
|
||||
gridColumns = gridColumns,
|
||||
gridSize = gridSize,
|
||||
getLibraryForPage = getLibraryForPage,
|
||||
onClickManga = onClickManga,
|
||||
onRemoveMangaClicked = onRemoveMangaClicked,
|
||||
showUnread = showUnread,
|
||||
showDownloaded = showDownloaded,
|
||||
showLanguage = showLanguage,
|
||||
showLocal = showLocal,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user