mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 07:29:14 +01:00
confirm the artist delete too
Only a single song deletes without asking; the artist's delete now opens the same dialog as the album and playlist, naming the artist and the space it frees. The artist's download action stays in its more-menu rather than getting a visible control, deliberately, so bulk downloading a whole artist is a considered action.
This commit is contained in:
@@ -50,7 +50,9 @@ import androidx.compose.runtime.CompositionLocalProvider
|
|||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableFloatStateOf
|
import androidx.compose.runtime.mutableFloatStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -80,6 +82,7 @@ import com.subtracks.data.source.StarType
|
|||||||
import com.subtracks.playback.PlaybackController
|
import com.subtracks.playback.PlaybackController
|
||||||
import com.subtracks.ui.components.ContextMenuHost
|
import com.subtracks.ui.components.ContextMenuHost
|
||||||
import com.subtracks.ui.components.CoverArt
|
import com.subtracks.ui.components.CoverArt
|
||||||
|
import com.subtracks.ui.components.DeleteDownloadsDialog
|
||||||
import com.subtracks.ui.components.ItemActions
|
import com.subtracks.ui.components.ItemActions
|
||||||
import com.subtracks.ui.components.MenuTarget
|
import com.subtracks.ui.components.MenuTarget
|
||||||
import com.subtracks.ui.components.rememberViewportFill
|
import com.subtracks.ui.components.rememberViewportFill
|
||||||
@@ -91,6 +94,7 @@ import com.subtracks.ui.theme.baseArtworkColors
|
|||||||
import com.subtracks.ui.theme.heroBarColor
|
import com.subtracks.ui.theme.heroBarColor
|
||||||
import com.subtracks.ui.theme.rememberArtworkColors
|
import com.subtracks.ui.theme.rememberArtworkColors
|
||||||
import com.subtracks.ui.theme.rememberOverlaidNameBusy
|
import com.subtracks.ui.theme.rememberOverlaidNameBusy
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
@@ -140,6 +144,8 @@ fun ArtistDetailRoute(
|
|||||||
val art by viewModel.art.collectAsStateWithLifecycle()
|
val art by viewModel.art.collectAsStateWithLifecycle()
|
||||||
val artThumbnail by viewModel.artThumbnail.collectAsStateWithLifecycle()
|
val artThumbnail by viewModel.artThumbnail.collectAsStateWithLifecycle()
|
||||||
val downloadStatus by viewModel.downloadStatus.collectAsStateWithLifecycle()
|
val downloadStatus by viewModel.downloadStatus.collectAsStateWithLifecycle()
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
var pendingDelete by remember { mutableStateOf<Long?>(null) }
|
||||||
val shortcutArt = remember(coverArtId) { coverArtId?.let { viewModel.coverArt(it, true) } }
|
val shortcutArt = remember(coverArtId) { coverArtId?.let { viewModel.coverArt(it, true) } }
|
||||||
val actions =
|
val actions =
|
||||||
ItemActions(
|
ItemActions(
|
||||||
@@ -149,7 +155,7 @@ fun ArtistDetailRoute(
|
|||||||
addToQueue = { playbackController.addToQueue(it.sourceId, it.kind, it.refId) },
|
addToQueue = { playbackController.addToQueue(it.sourceId, it.kind, it.refId) },
|
||||||
downloadArtist = { viewModel.onDownloadAction(BulkDownloadAction.Download) },
|
downloadArtist = { viewModel.onDownloadAction(BulkDownloadAction.Download) },
|
||||||
cancelArtistDownload = { viewModel.onDownloadAction(BulkDownloadAction.Cancel) },
|
cancelArtistDownload = { viewModel.onDownloadAction(BulkDownloadAction.Cancel) },
|
||||||
deleteArtistDownload = { viewModel.onDownloadAction(BulkDownloadAction.Delete) },
|
deleteArtistDownload = { scope.launch { pendingDelete = viewModel.downloadedBytes() } },
|
||||||
setStar = setStar,
|
setStar = setStar,
|
||||||
viewAlbum = onViewAlbum,
|
viewAlbum = onViewAlbum,
|
||||||
)
|
)
|
||||||
@@ -167,6 +173,15 @@ fun ArtistDetailRoute(
|
|||||||
starred = artist?.starred != null,
|
starred = artist?.starred != null,
|
||||||
onToggleStar = artist?.let { a -> { setStar(StarType.Artist, a.id, a.starred == null) } },
|
onToggleStar = artist?.let { a -> { setStar(StarType.Artist, a.id, a.starred == null) } },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
pendingDelete?.let { bytes ->
|
||||||
|
DeleteDownloadsDialog(
|
||||||
|
name = artist?.name.orEmpty(),
|
||||||
|
bytes = bytes,
|
||||||
|
onConfirm = { viewModel.onDownloadAction(BulkDownloadAction.Delete) },
|
||||||
|
onDismiss = { pendingDelete = null },
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ class ArtistDetailViewModel(
|
|||||||
.flatMapLatest { downloadRepository.status(it, DownloadList.Artist, artistId) }
|
.flatMapLatest { downloadRepository.status(it, DownloadList.Artist, artistId) }
|
||||||
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), ListDownloadStatus())
|
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), ListDownloadStatus())
|
||||||
|
|
||||||
|
suspend fun downloadedBytes(): Long = downloadRepository.downloadedBytes(sourceId.first(), DownloadList.Artist, artistId)
|
||||||
|
|
||||||
fun onDownloadAction(action: BulkDownloadAction) {
|
fun onDownloadAction(action: BulkDownloadAction) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
downloadRepository.applyAction(sourceId.first(), DownloadList.Artist, artistId, action)
|
downloadRepository.applyAction(sourceId.first(), DownloadList.Artist, artistId, action)
|
||||||
|
|||||||
@@ -667,6 +667,7 @@ class DownloadRepositoryTest {
|
|||||||
writeFile(1, "s3", "123")
|
writeFile(1, "s3", "123")
|
||||||
|
|
||||||
assertEquals(5L, repository.downloadedBytes(1, DownloadList.Album, "al1"))
|
assertEquals(5L, repository.downloadedBytes(1, DownloadList.Album, "al1"))
|
||||||
|
assertEquals(5L, repository.downloadedBytes(1, DownloadList.Artist, "ar1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requestedSongIds(): List<String> = engine.requests.map { it.second.path.substringAfterLast('/') }
|
private fun requestedSongIds(): List<String> = engine.requests.map { it.second.path.substringAfterLast('/') }
|
||||||
|
|||||||
Reference in New Issue
Block a user