show only an in-flight ring on the library surfaces

A finished download no longer draws anything on album covers, artist rows or
playlist rows: the badge is the progress ring alone, so a fully downloaded tile
looks like any other. The ring takes the theme's primary for the arc over a
theme track, with the one soft shadow, instead of the white glyph and its
outline.
This commit is contained in:
austinried
2026-10-04 00:30:03 +00:00
parent dac56a7fcb
commit b324cbb6b9
2 changed files with 24 additions and 60 deletions
@@ -1,35 +1,27 @@
package com.subtracks.ui.components package com.subtracks.ui.components
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.DownloadDone
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.subtracks.data.model.ListDownloadStatus import com.subtracks.data.model.ListDownloadStatus
const val DOWNLOADED_INDICATOR_TAG = "Downloaded"
const val DOWNLOADING_INDICATOR_TAG = "Downloading" const val DOWNLOADING_INDICATOR_TAG = "Downloading"
enum class DownloadIndicator { Hidden, InProgress, Complete } enum class DownloadIndicator { Hidden, InProgress }
fun ListDownloadStatus.indicator(): DownloadIndicator = fun ListDownloadStatus.indicator(): DownloadIndicator =
when { if (total > 0 && downloading > 0) DownloadIndicator.InProgress else DownloadIndicator.Hidden
total == 0L -> DownloadIndicator.Hidden
complete -> DownloadIndicator.Complete
downloading > 0 -> DownloadIndicator.InProgress
else -> DownloadIndicator.Hidden
}
@Composable @Composable
fun ListDownloadIndicator( fun ListDownloadIndicator(
@@ -37,50 +29,22 @@ fun ListDownloadIndicator(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val current = status ?: return val current = status ?: return
val kind = current.indicator() if (current.indicator() == DownloadIndicator.Hidden) return
if (kind == DownloadIndicator.Hidden) return val progress = { current.downloaded.toFloat() / current.total }
Box(modifier = modifier.size(26.dp), contentAlignment = Alignment.Center) { Box(modifier = modifier.size(20.dp), contentAlignment = Alignment.Center) {
when (kind) {
DownloadIndicator.Complete -> {
Icon(
imageVector = Icons.Rounded.DownloadDone,
contentDescription = null,
tint = Color.Black.copy(alpha = 0.5f),
modifier = Modifier.size(22.dp).blur(4.dp).offset(y = 1.dp),
)
Icon(
imageVector = Icons.Rounded.DownloadDone,
contentDescription = null,
tint = Color.Black.copy(alpha = 0.85f),
modifier =
Modifier
.size(22.dp)
.graphicsLayer {
scaleX = 1.18f
scaleY = 1.18f
}.blur(1.dp),
)
Icon(
imageVector = Icons.Rounded.DownloadDone,
contentDescription = DOWNLOADED_INDICATOR_TAG,
tint = Color.White,
modifier = Modifier.size(22.dp),
)
}
DownloadIndicator.InProgress -> {
CircularProgressIndicator( CircularProgressIndicator(
progress = { current.downloaded.toFloat() / current.total }, progress = progress,
color = Color.White, color = Color.Black.copy(alpha = 0.5f),
trackColor = Color.Black.copy(alpha = 0.45f), trackColor = Color.Transparent,
strokeWidth = 2.5.dp, strokeWidth = 2.5.dp,
modifier = Modifier.size(20.dp).semantics { contentDescription = DOWNLOADING_INDICATOR_TAG }, modifier = Modifier.fillMaxSize().blur(2.dp).offset(y = 1.dp),
)
CircularProgressIndicator(
progress = progress,
color = MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
strokeWidth = 2.5.dp,
modifier = Modifier.fillMaxSize().semantics { contentDescription = DOWNLOADING_INDICATOR_TAG },
) )
}
DownloadIndicator.Hidden -> {
Unit
}
}
} }
} }
@@ -11,7 +11,7 @@ class DownloadIndicatorTest {
} }
@Test @Test
fun aListWithNothingStartedButNoSongsShowsNothing() { fun aPopulatedButUnstartedListShowsNothing() {
assertEquals(DownloadIndicator.Hidden, ListDownloadStatus(total = 4).indicator()) assertEquals(DownloadIndicator.Hidden, ListDownloadStatus(total = 4).indicator())
} }
@@ -31,7 +31,7 @@ class DownloadIndicatorTest {
} }
@Test @Test
fun aFullyDownloadedListShowsDone() { fun aFullyDownloadedListShowsNothing() {
assertEquals(DownloadIndicator.Complete, ListDownloadStatus(total = 4, downloaded = 4).indicator()) assertEquals(DownloadIndicator.Hidden, ListDownloadStatus(total = 4, downloaded = 4).indicator())
} }
} }