Better error handling for errors on home page rows (#1128)

## Description
Adds better error handling when loading home page rows. For example,
this fixes loading errors if a playlist row is configured, but the
playlist is deleted.

Also fixes an issue from #1116 where changing users doesn't go the home
page.

### Related issues
Related to #1124

### Testing
Emulator

## Screenshots
N/A

## AI or LLM usage
None
This commit is contained in:
Ray 2026-03-21 19:17:43 -04:00 committed by GitHub
parent dac0b7208c
commit 920733075b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 43 additions and 33 deletions

View file

@ -438,10 +438,7 @@ class HomeSettingsService
): HomeRowConfigDisplay = ): HomeRowConfigDisplay =
when (config) { when (config) {
is HomeRowConfig.ByParent -> { is HomeRowConfig.ByParent -> {
val name = val name = getItemName(config.parentId) ?: ""
api.userLibraryApi
.getItem(itemId = config.parentId)
.content.name ?: ""
HomeRowConfigDisplay( HomeRowConfigDisplay(
id, id,
name, name,
@ -466,10 +463,7 @@ class HomeSettingsService
} }
is HomeRowConfig.Genres -> { is HomeRowConfig.Genres -> {
val name = val name = getItemName(config.parentId) ?: ""
api.userLibraryApi
.getItem(itemId = config.parentId)
.content.name ?: ""
HomeRowConfigDisplay( HomeRowConfigDisplay(
id, id,
context.getString(R.string.genres_in, name), context.getString(R.string.genres_in, name),
@ -490,10 +484,7 @@ class HomeSettingsService
} }
is HomeRowConfig.RecentlyAdded -> { is HomeRowConfig.RecentlyAdded -> {
val name = val name = getItemName(config.parentId) ?: ""
api.userLibraryApi
.getItem(itemId = config.parentId)
.content.name ?: ""
HomeRowConfigDisplay( HomeRowConfigDisplay(
id, id,
context.getString(R.string.recently_added_in, name), context.getString(R.string.recently_added_in, name),
@ -502,10 +493,7 @@ class HomeSettingsService
} }
is HomeRowConfig.RecentlyReleased -> { is HomeRowConfig.RecentlyReleased -> {
val name = val name = getItemName(config.parentId) ?: ""
api.userLibraryApi
.getItem(itemId = config.parentId)
.content.name ?: ""
HomeRowConfigDisplay( HomeRowConfigDisplay(
id, id,
context.getString(R.string.recently_released_in, name), context.getString(R.string.recently_released_in, name),
@ -547,10 +535,7 @@ class HomeSettingsService
} }
is HomeRowConfig.Suggestions -> { is HomeRowConfig.Suggestions -> {
val name = val name = getItemName(config.parentId) ?: ""
api.userLibraryApi
.getItem(itemId = config.parentId)
.content.name ?: ""
HomeRowConfigDisplay( HomeRowConfigDisplay(
id = id, id = id,
title = context.getString(R.string.suggestions_for, name), title = context.getString(R.string.suggestions_for, name),
@ -559,6 +544,16 @@ class HomeSettingsService
} }
} }
private suspend fun getItemName(itemId: UUID): String? =
try {
api.userLibraryApi
.getItem(itemId = itemId)
.content.name
} catch (ex: Exception) {
Timber.e(ex, "Could not get name for %s", itemId)
context.getString(R.string.unknown)
}
/** /**
* Fetch the data from the server for a given [HomeRowConfig] * Fetch the data from the server for a given [HomeRowConfig]
*/ */

View file

@ -1,5 +1,6 @@
package com.github.damontecres.wholphin.services package com.github.damontecres.wholphin.services
import androidx.navigation3.runtime.NavBackStack
import com.github.damontecres.wholphin.ui.nav.Destination import com.github.damontecres.wholphin.ui.nav.Destination
import org.acra.ACRA import org.acra.ACRA
import timber.log.Timber import timber.log.Timber
@ -13,7 +14,7 @@ import javax.inject.Singleton
class NavigationManager class NavigationManager
@Inject @Inject
constructor() { constructor() {
var backStack: MutableList<Destination> = mutableListOf() var backStack: MutableList<Destination> = NavBackStack(Destination.Home())
/** /**
* Go to the specified [com.github.damontecres.wholphin.ui.nav.Destination] * Go to the specified [com.github.damontecres.wholphin.ui.nav.Destination]

View file

@ -16,7 +16,9 @@ import javax.inject.Singleton
@Singleton @Singleton
class SetupNavigationManager class SetupNavigationManager
@Inject @Inject
constructor() { constructor(
private val navigationManager: NavigationManager,
) {
var backStack: MutableList<SetupDestination> = mutableStateListOf(SetupDestination.Loading) var backStack: MutableList<SetupDestination> = mutableStateListOf(SetupDestination.Loading)
/** /**
@ -25,6 +27,9 @@ class SetupNavigationManager
fun navigateTo(destination: SetupDestination) { fun navigateTo(destination: SetupDestination) {
backStack[0] = destination backStack[0] = destination
log() log()
if (destination !is SetupDestination.AppContent) {
navigationManager.reloadHome()
}
} }
private fun log() { private fun log() {

View file

@ -122,19 +122,23 @@ class HomeSettingsViewModel
state.value state.value
.let { state -> .let { state ->
state.rows state.rows
.map { it.config }
.map { row -> .map { row ->
viewModelScope.async(Dispatchers.IO) { viewModelScope.async(Dispatchers.IO) {
semaphore.withPermit { semaphore.withPermit {
homeSettingsService.fetchDataForRow( try {
row = row, homeSettingsService.fetchDataForRow(
scope = viewModelScope, row = row.config,
prefs = prefs, scope = viewModelScope,
userDto = userDto, prefs = prefs,
libraries = state.libraries, userDto = userDto,
limit = limit, libraries = state.libraries,
isRefresh = false, limit = limit,
) isRefresh = false,
)
} catch (ex: Exception) {
Timber.e(ex, "Error on row %s", row)
HomeRowLoadingState.Error(row.title, exception = ex)
}
} }
} }
} }
@ -195,7 +199,12 @@ class HomeSettingsViewModel
viewModelScope.launchIO { viewModelScope.launchIO {
updateState { updateState {
val rows = it.rows.toMutableList().apply { removeAt(index) } val rows = it.rows.toMutableList().apply { removeAt(index) }
val rowData = it.rowData.toMutableList().apply { removeAt(index) } val rowData =
if (index in it.rowData.indices) {
it.rowData.toMutableList().apply { removeAt(index) }
} else {
it.rowData
}
it.copy( it.copy(
rows = rows, rows = rows,
rowData = rowData, rowData = rowData,