mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
address the review: source title after a queue reorder, scrim timing, thumbnail painter
- derive the now playing fallback title from the current item for every kind except the songs list, so a track reordered into the album queue (now a Song entry) still shows its album - reset the resolved title to the fallback when the queue context changes, so crossing albums does not briefly show the previous name - start the now playing scrim fade later (0.85) so it darkens the sheet, not the library, while the sheet is still sliding up - reuse the thumbnail's onSuccess painter ratio instead of loading a second thumbnail painter for the aspect ratio - drop the now-unneeded ExperimentalLayoutApi opt-in on AddSourceScreen (imePadding is stable)
This commit is contained in:
@@ -94,7 +94,7 @@ private const val OVERLAY_DURATION_MS = 200
|
|||||||
private const val EXPAND_FADE = 0.1f
|
private const val EXPAND_FADE = 0.1f
|
||||||
private const val FLING_VELOCITY = 1000f
|
private const val FLING_VELOCITY = 1000f
|
||||||
private const val MINI_PLAYER_ANIM_MS = 200
|
private const val MINI_PLAYER_ANIM_MS = 200
|
||||||
private const val SCRIM_FADE_START = 0.6f
|
private const val SCRIM_FADE_START = 0.85f
|
||||||
|
|
||||||
private object Routes {
|
private object Routes {
|
||||||
const val LIBRARY = "library"
|
const val LIBRARY = "library"
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ fun CoverArt(
|
|||||||
val context = LocalPlatformContext.current
|
val context = LocalPlatformContext.current
|
||||||
var failed by remember(ref, thumbnailRef) { mutableStateOf(false) }
|
var failed by remember(ref, thumbnailRef) { mutableStateOf(false) }
|
||||||
var thumbnailLoaded by remember(ref, thumbnailRef) { mutableStateOf(false) }
|
var thumbnailLoaded by remember(ref, thumbnailRef) { mutableStateOf(false) }
|
||||||
|
var thumbnailRatio by remember(ref, thumbnailRef) { mutableStateOf<Float?>(null) }
|
||||||
val model = remember(ref, thumbnailRef) { ref?.let { imageRequest(context, it, crossfade = thumbnailRef != null) } }
|
val model = remember(ref, thumbnailRef) { ref?.let { imageRequest(context, it, crossfade = thumbnailRef != null) } }
|
||||||
val frameModifier =
|
val frameModifier =
|
||||||
Modifier
|
Modifier
|
||||||
@@ -65,6 +66,7 @@ fun CoverArt(
|
|||||||
failed = failed,
|
failed = failed,
|
||||||
thumbnailLoaded = thumbnailLoaded,
|
thumbnailLoaded = thumbnailLoaded,
|
||||||
onThumbnailLoaded = { thumbnailLoaded = true },
|
onThumbnailLoaded = { thumbnailLoaded = true },
|
||||||
|
onThumbnailRatio = { thumbnailRatio = it },
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
) {
|
) {
|
||||||
if (ref != null) {
|
if (ref != null) {
|
||||||
@@ -85,15 +87,10 @@ fun CoverArt(
|
|||||||
onError = { failed = true },
|
onError = { failed = true },
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
)
|
)
|
||||||
val thumbnailPainter =
|
|
||||||
rememberAsyncImagePainter(
|
|
||||||
model = remember(thumbnailRef) { thumbnailRef?.let { imageRequest(context, it, crossfade = false) } },
|
|
||||||
contentScale = ContentScale.Fit,
|
|
||||||
)
|
|
||||||
BoxWithConstraints(modifier, contentAlignment = Alignment.Center) {
|
BoxWithConstraints(modifier, contentAlignment = Alignment.Center) {
|
||||||
val ratio =
|
val ratio =
|
||||||
painter.intrinsicSize.ratioOrNull()
|
painter.intrinsicSize.ratioOrNull()
|
||||||
?: thumbnailPainter.intrinsicSize.ratioOrNull()
|
?: thumbnailRatio
|
||||||
?: 1f
|
?: 1f
|
||||||
val width = if (ratio > maxWidth.value / maxHeight.value) maxWidth else maxHeight * ratio
|
val width = if (ratio > maxWidth.value / maxHeight.value) maxWidth else maxHeight * ratio
|
||||||
Box(Modifier.size(width, width / ratio).then(frameModifier)) {
|
Box(Modifier.size(width, width / ratio).then(frameModifier)) {
|
||||||
@@ -105,6 +102,7 @@ fun CoverArt(
|
|||||||
failed = failed,
|
failed = failed,
|
||||||
thumbnailLoaded = thumbnailLoaded,
|
thumbnailLoaded = thumbnailLoaded,
|
||||||
onThumbnailLoaded = { thumbnailLoaded = true },
|
onThumbnailLoaded = { thumbnailLoaded = true },
|
||||||
|
onThumbnailRatio = { thumbnailRatio = it },
|
||||||
contentScale = ContentScale.Fit,
|
contentScale = ContentScale.Fit,
|
||||||
) {
|
) {
|
||||||
if (ref != null) {
|
if (ref != null) {
|
||||||
@@ -130,6 +128,7 @@ private fun BoxScope.CoverArtContent(
|
|||||||
failed: Boolean,
|
failed: Boolean,
|
||||||
thumbnailLoaded: Boolean,
|
thumbnailLoaded: Boolean,
|
||||||
onThumbnailLoaded: () -> Unit,
|
onThumbnailLoaded: () -> Unit,
|
||||||
|
onThumbnailRatio: (Float) -> Unit,
|
||||||
contentScale: ContentScale,
|
contentScale: ContentScale,
|
||||||
main: @Composable () -> Unit,
|
main: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
@@ -147,7 +146,12 @@ private fun BoxScope.CoverArtContent(
|
|||||||
model = remember(thumbnailRef) { imageRequest(context, thumbnailRef, crossfade = false) },
|
model = remember(thumbnailRef) { imageRequest(context, thumbnailRef, crossfade = false) },
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
contentScale = contentScale,
|
contentScale = contentScale,
|
||||||
onSuccess = { onThumbnailLoaded() },
|
onSuccess = { success ->
|
||||||
|
onThumbnailLoaded()
|
||||||
|
success.painter.intrinsicSize
|
||||||
|
.ratioOrNull()
|
||||||
|
?.let(onThumbnailRatio)
|
||||||
|
},
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,8 +83,14 @@ fun NowPlayingRoute(
|
|||||||
val art = controller.coverArt(state.item)
|
val art = controller.coverArt(state.item)
|
||||||
val thumbnail = controller.coverArt(state.item, thumbnail = true)
|
val thumbnail = controller.coverArt(state.item, thumbnail = true)
|
||||||
val queueContext = state.context
|
val queueContext = state.context
|
||||||
val fallbackTitle = if (queueContext?.kind == QueueKind.Album) state.item?.album.orEmpty() else "Library"
|
val fallbackTitle =
|
||||||
|
if (queueContext?.kind == QueueKind.Songs) {
|
||||||
|
"Library"
|
||||||
|
} else {
|
||||||
|
state.item?.album?.takeIf { it.isNotBlank() } ?: "Library"
|
||||||
|
}
|
||||||
val sourceTitle by produceState<String>(initialValue = fallbackTitle, queueContext) {
|
val sourceTitle by produceState<String>(initialValue = fallbackTitle, queueContext) {
|
||||||
|
value = fallbackTitle
|
||||||
value = controller.sourceTitle(queueContext) ?: fallbackTitle
|
value = controller.sourceTitle(queueContext) ?: fallbackTitle
|
||||||
}
|
}
|
||||||
LaunchedEffect(state.item?.id, state.hasNext) {
|
LaunchedEffect(state.item?.id, state.hasNext) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.subtracks.ui.settings
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -58,7 +57,7 @@ fun AddSourceRoute(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun AddSourceScreen(
|
fun AddSourceScreen(
|
||||||
state: AddSourceState,
|
state: AddSourceState,
|
||||||
|
|||||||
Reference in New Issue
Block a user