Fix infinite loading in library

This commit is contained in:
Syer10
2023-07-03 21:20:45 -04:00
parent fdccb50850
commit ae10f1476f
3 changed files with 113 additions and 100 deletions

View File

@@ -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() },

View File

@@ -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) {

View File

@@ -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,
)
}
}
}
}