address the bulk download review

- Cancelling a list while its download loop was still enqueueing missed every
  song queued after the cancel looked. The loop now holds the lock for the whole
  queue, so a cancel waits for it to finish and then removes all of it. That
  needed the enqueue helper split into a locked entry point and a body the loop
  can call while already holding the lock — calling the locked one from inside
  the lock deadlocked, which is what hung the tests.
- An empty resolved list now says so instead of doing nothing.
- One song failing to enqueue no longer aborts the rest of the batch.
- The artist actions resolve through the albums the artist page lists, matching
  what is on screen, rather than through songs.artistId, which for a guest on a
  compilation enqueued nothing.
- Bulk actions are one `applyAction` on the repository, so the three view models
  and both screens stop repeating the same dispatch.
- Tests: the playlist and artist resolve paths, a Running row counted as
  downloading, the action dispatch, and the action rule moved to a plain unit
  test.
This commit is contained in:
austinried
2026-10-04 00:30:02 +00:00
parent b2b92a388e
commit bf561075a2
15 changed files with 178 additions and 99 deletions
@@ -74,6 +74,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.subtracks.data.model.Album
import com.subtracks.data.model.Artist
import com.subtracks.data.model.BulkDownloadAction
import com.subtracks.data.model.CoverArtRef
import com.subtracks.data.source.StarType
import com.subtracks.playback.PlaybackController
@@ -146,9 +147,9 @@ fun ArtistDetailRoute(
shuffleAlbum = { viewModel.shuffleAlbum(it.id) },
playNext = { playbackController.playNext(it.sourceId, it.kind, it.refId) },
addToQueue = { playbackController.addToQueue(it.sourceId, it.kind, it.refId) },
downloadArtist = { viewModel.downloadAll() },
cancelArtistDownload = { viewModel.cancelDownloads() },
deleteArtistDownload = { viewModel.deleteDownloads() },
downloadArtist = { viewModel.onDownloadAction(BulkDownloadAction.Download) },
cancelArtistDownload = { viewModel.onDownloadAction(BulkDownloadAction.Cancel) },
deleteArtistDownload = { viewModel.onDownloadAction(BulkDownloadAction.Delete) },
setStar = setStar,
viewAlbum = onViewAlbum,
)