mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-17 15:32:01 +00:00
feat: adding retry logic to library
This commit is contained in:
parent
5a0b623773
commit
1e75f416e4
2 changed files with 39 additions and 22 deletions
|
|
@ -50,6 +50,12 @@ fun LibraryScreen(
|
||||||
var observedOfflineState by remember { mutableStateOf(false) }
|
var observedOfflineState by remember { mutableStateOf(false) }
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val isTraktSource = uiState.sourceMode == LibrarySourceMode.TRAKT
|
val isTraktSource = uiState.sourceMode == LibrarySourceMode.TRAKT
|
||||||
|
val retryLibraryLoad: () -> Unit = {
|
||||||
|
NetworkStatusRepository.requestRefresh(force = true)
|
||||||
|
coroutineScope.launch {
|
||||||
|
LibraryRepository.pullFromServer(ProfileRepository.activeProfileId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(networkStatusUiState.condition, isTraktSource) {
|
LaunchedEffect(networkStatusUiState.condition, isTraktSource) {
|
||||||
when (networkStatusUiState.condition) {
|
when (networkStatusUiState.condition) {
|
||||||
|
|
@ -110,14 +116,7 @@ fun LibraryScreen(
|
||||||
NuvioNetworkOfflineCard(
|
NuvioNetworkOfflineCard(
|
||||||
condition = networkStatusUiState.condition,
|
condition = networkStatusUiState.condition,
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
onRetry = {
|
onRetry = retryLibraryLoad,
|
||||||
NetworkStatusRepository.requestRefresh(force = true)
|
|
||||||
if (isTraktSource) {
|
|
||||||
coroutineScope.launch {
|
|
||||||
LibraryRepository.pullFromServer(ProfileRepository.activeProfileId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
HomeEmptyStateCard(
|
HomeEmptyStateCard(
|
||||||
|
|
@ -128,6 +127,8 @@ fun LibraryScreen(
|
||||||
stringResource(Res.string.library_load_failed)
|
stringResource(Res.string.library_load_failed)
|
||||||
},
|
},
|
||||||
message = uiState.errorMessage.orEmpty(),
|
message = uiState.errorMessage.orEmpty(),
|
||||||
|
actionLabel = stringResource(Res.string.action_retry),
|
||||||
|
onActionClick = retryLibraryLoad,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,12 +140,7 @@ fun LibraryScreen(
|
||||||
NuvioNetworkOfflineCard(
|
NuvioNetworkOfflineCard(
|
||||||
condition = networkStatusUiState.condition,
|
condition = networkStatusUiState.condition,
|
||||||
modifier = Modifier.padding(horizontal = 16.dp),
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
onRetry = {
|
onRetry = retryLibraryLoad,
|
||||||
NetworkStatusRepository.requestRefresh(force = true)
|
|
||||||
coroutineScope.launch {
|
|
||||||
LibraryRepository.pullFromServer(ProfileRepository.activeProfileId)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
HomeEmptyStateCard(
|
HomeEmptyStateCard(
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ private const val LIST_FETCH_CONCURRENCY = 4
|
||||||
private const val SNAPSHOT_CACHE_TTL_MS = 60_000L
|
private const val SNAPSHOT_CACHE_TTL_MS = 60_000L
|
||||||
private const val LIST_TABS_CACHE_TTL_MS = 60_000L
|
private const val LIST_TABS_CACHE_TTL_MS = 60_000L
|
||||||
private const val FORCE_REFRESH_DEDUP_MS = 10_000L
|
private const val FORCE_REFRESH_DEDUP_MS = 10_000L
|
||||||
|
private const val MAX_VISIBLE_ERROR_MESSAGE_LENGTH = 240
|
||||||
|
|
||||||
data class TraktLibraryUiState(
|
data class TraktLibraryUiState(
|
||||||
val listTabs: List<TraktListTab> = emptyList(),
|
val listTabs: List<TraktListTab> = emptyList(),
|
||||||
|
|
@ -159,21 +160,20 @@ object TraktLibraryRepository {
|
||||||
errorMessage = null,
|
errorMessage = null,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}.onFailure { error ->
|
}
|
||||||
|
result.exceptionOrNull()?.let { error ->
|
||||||
if (error is CancellationException) throw error
|
if (error is CancellationException) throw error
|
||||||
log.w { "Failed to refresh Trakt library: ${error.message}" }
|
log.w(error) { "Failed to refresh Trakt library" }
|
||||||
}.getOrNull()
|
_uiState.value = _uiState.value.copy(
|
||||||
|
|
||||||
if (result == null) {
|
|
||||||
_uiState.value = current.copy(
|
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
hasLoaded = true,
|
hasLoaded = true,
|
||||||
errorMessage = getString(Res.string.trakt_library_load_failed),
|
errorMessage = traktLibraryLoadErrorMessage(error),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_uiState.value = result.copy(
|
val snapshot = result.getOrThrow()
|
||||||
|
_uiState.value = snapshot.copy(
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
hasLoaded = true,
|
hasLoaded = true,
|
||||||
errorMessage = null,
|
errorMessage = null,
|
||||||
|
|
@ -414,6 +414,27 @@ object TraktLibraryRepository {
|
||||||
TraktLibraryStorage.savePayload(json.encodeToString(payload))
|
TraktLibraryStorage.savePayload(json.encodeToString(payload))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun traktLibraryLoadErrorMessage(error: Throwable): String {
|
||||||
|
val fallback = getString(Res.string.trakt_library_load_failed)
|
||||||
|
val detail = error.userVisibleMessage()
|
||||||
|
return when {
|
||||||
|
detail.isBlank() -> fallback
|
||||||
|
detail.equals(fallback, ignoreCase = true) -> fallback
|
||||||
|
else -> detail
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Throwable.userVisibleMessage(): String {
|
||||||
|
val raw = message?.trim()?.takeIf { it.isNotBlank() }
|
||||||
|
?: toString().trim()
|
||||||
|
val firstLine = raw.lines().firstOrNull()?.trim().orEmpty()
|
||||||
|
return if (firstLine.length <= MAX_VISIBLE_ERROR_MESSAGE_LENGTH) {
|
||||||
|
firstLine
|
||||||
|
} else {
|
||||||
|
firstLine.take(MAX_VISIBLE_ERROR_MESSAGE_LENGTH).trimEnd() + "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun fetchListTabs(headers: Map<String, String>): List<TraktListTab> {
|
private suspend fun fetchListTabs(headers: Map<String, String>): List<TraktListTab> {
|
||||||
val watchlistTabs = listOf(
|
val watchlistTabs = listOf(
|
||||||
TraktListTab(
|
TraktListTab(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue