guard artist art resolution and tidy the preload

This commit is contained in:
austinried
2026-10-04 00:29:54 +00:00
parent 745f5f4097
commit d8a0bf709d
4 changed files with 29 additions and 8 deletions
@@ -73,6 +73,13 @@ import com.subtracks.ui.theme.heroDarkenAt
private const val GRADIENT_SCREENS = 2.0f
private const val FADE_DISTANCE_DP = 64
/**
* A themed detail screen: endless artwork gradient, a fading top bar, and a lazy list whose first
* item is [header]. The header and its controls are measured so the bar fades in as they scroll off.
*
* [content] emits the rows after the header and assumes they share a uniform height, which is used
* to estimate the scroll offset for the bar.
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HeroDetailScaffold(
@@ -8,6 +8,7 @@ import com.subtracks.data.model.CoverArtRef
import com.subtracks.data.repo.LibraryRepository
import com.subtracks.data.repo.SourceRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -39,12 +40,24 @@ class ArtistDetailViewModel(
artist
.filterNotNull()
.collectLatest { loaded ->
_art.value = sourceRepository.coverArt(loaded.coverArt)
_artThumbnail.value = sourceRepository.coverArt(loaded.coverArt, thumbnail = true)
val (full, thumbnail) = resolveArt(loaded)
_art.value = full
_artThumbnail.value = thumbnail
}
}
}
private suspend fun resolveArt(artist: Artist): Pair<CoverArtRef?, CoverArtRef?> {
repeat(3) { attempt ->
val full = sourceRepository.coverArt(artist.coverArt)
if (full != null) {
return full to sourceRepository.coverArt(artist.coverArt, thumbnail = true)
}
if (attempt < 2) delay(300)
}
return null to null
}
fun coverArt(
coverArt: String?,
thumbnail: Boolean,
@@ -103,9 +103,13 @@ private fun playlistSummary(playlist: Playlist?): String {
}
private fun formatDuration(seconds: Long): String? {
if (seconds <= 0) return null
if (seconds < 60) return null
val totalMinutes = seconds / 60
val hours = totalMinutes / 60
val minutes = totalMinutes % 60
return if (hours > 0) "$hours hr $minutes min" else "$totalMinutes min"
return when {
hours == 0L -> "$totalMinutes min"
minutes == 0L -> "$hours hr"
else -> "$hours hr $minutes min"
}
}
@@ -75,10 +75,7 @@ fun NowPlayingRoute(
val thumbnail = controller.coverArt(state.item, thumbnail = true)
LaunchedEffect(state.item?.id, state.hasNext) {
if (!state.hasNext) return@LaunchedEffect
controller.upcomingCoverArt(thumbnail = true)?.let {
ArtworkSeedCache.prefetch(context, it)
prefetchImage(context, it)
}
controller.upcomingCoverArt(thumbnail = true)?.let { ArtworkSeedCache.prefetch(context, it) }
controller.upcomingCoverArt()?.let { prefetchImage(context, it) }
}
NowPlayingScreen(