mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-10 15:11:58 +01:00
guard artist art resolution and tidy the preload
This commit is contained in:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user