library: drop the download progress indicator

This commit is contained in:
austinried
2026-10-21 06:04:23 +00:00
parent 6f1e1612e1
commit e487d2e0b1
7 changed files with 1 additions and 141 deletions
@@ -78,13 +78,6 @@ data class ListDownloadStatus(
val complete: Boolean get() = total > 0 && downloaded == total
}
data class DownloadProgress(
val bytes: Long,
val total: Long,
) {
val fraction: Float? get() = fractionOf(bytes, total)
}
data class EntityDownloadStatus(
val id: String,
val total: Long = 0,
@@ -396,7 +396,6 @@ private fun MainNavigation() {
navigateDetail(Routes.PLAYLIST_DETAIL, "playlistId", playlist.id, Routes.playlist(playlist.id))
},
onOpenSettings = { navController.navigate(Routes.SETTINGS) },
onOpenDownloads = { navController.navigate(Routes.DOWNLOADS) },
onOpenSearch = { navController.navigate(Routes.SEARCH) },
onViewAlbum = { albumId -> navigateDetail(Routes.ALBUM_DETAIL, "albumId", albumId, Routes.album(albumId)) },
onViewArtist = { artistId ->
@@ -34,7 +34,6 @@ import androidx.compose.material.icons.rounded.Album
import androidx.compose.material.icons.rounded.ArrowDownward
import androidx.compose.material.icons.rounded.ArrowUpward
import androidx.compose.material.icons.rounded.CloudOff
import androidx.compose.material.icons.rounded.Download
import androidx.compose.material.icons.rounded.DownloadDone
import androidx.compose.material.icons.rounded.FilterAltOff
import androidx.compose.material.icons.rounded.Home
@@ -111,7 +110,6 @@ import com.subtracks.data.model.Artist
import com.subtracks.data.model.BulkDownloadAction
import com.subtracks.data.model.CoverArtRef
import com.subtracks.data.model.DownloadList
import com.subtracks.data.model.DownloadProgress
import com.subtracks.data.model.ListDownloadStatus
import com.subtracks.data.model.Playlist
import com.subtracks.data.prefs.AlbumSort
@@ -230,7 +228,6 @@ fun LibraryRoute(
onArtistClick: (Artist) -> Unit,
onPlaylistClick: (Playlist) -> Unit,
onOpenSettings: () -> Unit,
onOpenDownloads: () -> Unit = {},
onOpenSearch: () -> Unit = {},
onViewAlbum: (String) -> Unit,
onViewArtist: (String) -> Unit,
@@ -261,7 +258,6 @@ fun LibraryRoute(
val listQueryState = listTab?.let { viewModel.listQuery(it).collectAsStateWithLifecycle() }
val listQuery = listQueryState?.value ?: ListQuery("")
val offline by viewModel.offline.collectAsStateWithLifecycle()
val downloadProgress by viewModel.downloadProgress.collectAsStateWithLifecycle()
val playSort by viewModel.playSortAvailability.collectAsStateWithLifecycle()
val displayQuery = if (offline) listQuery.copy(downloaded = true) else listQuery
val searchState = listTab?.let { viewModel.search(it).collectAsStateWithLifecycle() }
@@ -319,7 +315,6 @@ fun LibraryRoute(
onPlaylistClick = onPlaylistClick,
onSync = viewModel::sync,
onOpenSettings = onOpenSettings,
onOpenDownloads = onOpenDownloads,
onOpenSearch = onOpenSearch,
onItemLongClick = {
focusManager.clearFocus()
@@ -329,7 +324,6 @@ fun LibraryRoute(
resetKeys = resetKeys,
offline = offline,
onExitOffline = { viewModel.setOffline(false) },
downloadProgress = downloadProgress,
sortOptions = sortOptionsFor(selectedTab, playSort),
starredSupported = listTab?.supportsStarred == true,
onSortChange = { sort -> listTab?.let { viewModel.setListQuery(it, listQuery.copy(sort = sort)) } },
@@ -404,12 +398,10 @@ fun LibraryScreen(
onSync: () -> Unit,
onOpenSettings: () -> Unit,
modifier: Modifier = Modifier,
onOpenDownloads: () -> Unit = {},
artistArt: (Artist) -> ArtistArt = { ArtistArt() },
onOpenSearch: () -> Unit = {},
offline: Boolean = false,
onExitOffline: () -> Unit = {},
downloadProgress: DownloadProgress? = null,
onItemLongClick: (MenuTarget) -> Unit = {},
syncing: Boolean = false,
refreshing: Boolean = false,
@@ -602,8 +594,6 @@ fun LibraryScreen(
onOpenSettings = onOpenSettings,
offline = offline,
onExitOffline = onExitOffline,
downloadProgress = downloadProgress,
onOpenDownloads = onOpenDownloads,
artwork = artwork,
syncing = syncing,
)
@@ -868,8 +858,6 @@ internal fun LibraryTabs(
onOpenSettings: () -> Unit,
offline: Boolean = false,
onExitOffline: () -> Unit = {},
downloadProgress: DownloadProgress? = null,
onOpenDownloads: () -> Unit = {},
artwork: ArtworkColors?,
syncing: Boolean = false,
) {
@@ -953,14 +941,7 @@ internal fun LibraryTabs(
)
}
Spacer(Modifier.weight(1f))
if (downloadProgress != null) {
IconButton(onClick = onOpenDownloads) {
DownloadProgressIcon(
progress = downloadProgress,
color = MaterialTheme.colorScheme.primary,
)
}
} else if (offline) {
if (offline) {
IconButton(onClick = onExitOffline) {
Icon(
imageVector = Icons.Rounded.CloudOff,
@@ -991,41 +972,6 @@ internal fun LibraryTabs(
}
}
@Composable
private fun DownloadProgressIcon(
progress: DownloadProgress,
color: Color,
) {
val description = stringResource(R.string.downloads_in_progress)
Box(
modifier = Modifier.size(32.dp).semantics { contentDescription = description },
contentAlignment = Alignment.Center,
) {
val fraction = progress.fraction
if (fraction != null) {
CircularProgressIndicator(
progress = { fraction },
color = color,
trackColor = MaterialTheme.colorScheme.surfaceContainerHighest,
strokeWidth = 2.dp,
modifier = Modifier.fillMaxSize(),
)
} else {
CircularProgressIndicator(
color = color,
strokeWidth = 2.dp,
modifier = Modifier.fillMaxSize(),
)
}
Icon(
imageVector = Icons.Rounded.Download,
contentDescription = null,
tint = color,
modifier = Modifier.size(16.dp),
)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun TabButton(
@@ -9,11 +9,8 @@ import com.subtracks.data.model.Artist
import com.subtracks.data.model.BulkDownloadAction
import com.subtracks.data.model.CoverArtRef
import com.subtracks.data.model.DownloadList
import com.subtracks.data.model.DownloadProgress
import com.subtracks.data.model.DownloadStatus
import com.subtracks.data.model.ListDownloadStatus
import com.subtracks.data.model.Playlist
import com.subtracks.data.model.SongDownload
import com.subtracks.data.prefs.AlbumSort
import com.subtracks.data.prefs.ArtistSort
import com.subtracks.data.prefs.LibraryListTab
@@ -118,13 +115,6 @@ class LibraryViewModel(
val offline: StateFlow<Boolean> = sourceRepository.offline
val downloadProgress: StateFlow<DownloadProgress?> =
combine(
downloadRepository.activeDownloads(),
sourceRepository.activeSourceId(),
) { rows, sourceId -> downloadProgress(rows, sourceId) }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), null)
fun setOffline(enabled: Boolean) = sourceRepository.setOfflineMode(enabled)
val syncing: StateFlow<Boolean> =
@@ -233,21 +223,6 @@ class LibraryViewModel(
}
}
internal fun downloadProgress(
rows: List<SongDownload>,
sourceId: Long?,
): DownloadProgress? {
if (sourceId == null) return null
val active = rows.filter { it.sourceId == sourceId }
if (active.isEmpty()) return null
val running = active.filter { it.status == DownloadStatus.Running }
if (running.isEmpty() || running.any { it.total <= 0 }) return DownloadProgress(bytes = 0, total = 0)
return DownloadProgress(
bytes = running.sumOf { it.bytes },
total = running.sumOf { it.total },
)
}
internal fun ListQuery.albumSort(): AlbumSort = AlbumSort.entries.firstOrNull { it.name == sort } ?: AlbumSort.Name
internal fun ListQuery.artistSort(): ArtistSort = ArtistSort.entries.firstOrNull { it.name == sort } ?: ArtistSort.Name
-1
View File
@@ -176,7 +176,6 @@
<string name="filter_downloaded">Downloaded</string>
<string name="close_search">Close search</string>
<string name="offline_mode_status">Offline mode; tap to go online</string>
<string name="downloads_in_progress">Downloads in progress; tap to open the download manager</string>
<string name="shuffle_artist">Shuffle artist</string>
<string name="status_playing">Playing</string>
@@ -1,10 +1,7 @@
package com.subtracks.ui.components
import com.subtracks.data.model.DownloadProgress
import com.subtracks.data.model.ListDownloadStatus
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
@@ -38,14 +35,4 @@ class DownloadIndicatorTest {
fun aFullyDownloadedListIsNotDownloading() {
assertFalse(ListDownloadStatus(total = 4, downloaded = 4).isDownloading())
}
@Test
fun totalDownloadProgressCombinesEveryInFlightTransfer() {
assertEquals(0.4f, DownloadProgress(bytes = 40, total = 100).fraction)
}
@Test
fun queuedDownloadsWithoutASizeShowAnIndeterminateRing() {
assertNull(DownloadProgress(bytes = 0, total = 0).fraction)
}
}
@@ -1,15 +1,11 @@
package com.subtracks.ui.library
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.subtracks.data.model.DownloadProgress
import com.subtracks.data.model.DownloadStatus
import com.subtracks.data.model.SongDownload
import com.subtracks.data.prefs.AlbumSort
import com.subtracks.data.prefs.ArtistSort
import com.subtracks.data.prefs.ListQuery
import com.subtracks.data.prefs.PlaylistSort
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import org.junit.runner.RunWith
@@ -28,39 +24,4 @@ class LibraryViewModelTest {
assertEquals(ArtistSort.Name, ListQuery("LegacyArtistOrder").artistSort())
assertEquals(PlaylistSort.Name, ListQuery("LegacyPlaylistOrder").playlistSort())
}
@Test
fun downloadProgressOnlyCountsTheActiveSource() {
val rows = listOf(download(1, bytes = 40, total = 100), download(2, bytes = 10, total = 20))
assertEquals(DownloadProgress(bytes = 40, total = 100), downloadProgress(rows, sourceId = 1))
}
@Test
fun anotherSourcesDownloadsDoNotShowAProgressRing() {
assertNull(downloadProgress(listOf(download(2, bytes = 10, total = 20)), sourceId = 1))
}
@Test
fun aTransferWithoutAKnownSizeIsIndeterminate() {
val rows =
listOf(
download(1, bytes = 100, total = 100),
download(1, bytes = 20, total = 0).copy(songId = "s2"),
)
assertEquals(DownloadProgress(bytes = 0, total = 0), downloadProgress(rows, sourceId = 1))
}
private fun download(
sourceId: Long,
bytes: Long,
total: Long,
) = SongDownload(
sourceId = sourceId,
songId = "s1",
status = DownloadStatus.Running,
bytes = bytes,
total = total,
)
}