diff --git a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt index 740194ee..778ad9c5 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt @@ -12,6 +12,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -65,6 +66,15 @@ fun AlbumDetailRoute( val discs by viewModel.discs.collectAsStateWithLifecycle(initialValue = emptyList()) val downloads by viewModel.downloads.collectAsStateWithLifecycle() val downloadStatus by viewModel.downloadStatus.collectAsStateWithLifecycle() + val offline by viewModel.offline.collectAsStateWithLifecycle() + var hadDownloads by remember { mutableStateOf(false) } + LaunchedEffect(downloadStatus.downloaded, offline) { + if (downloadStatus.downloaded > 0) { + hadDownloads = true + } else if (hadDownloads && offline) { + onBack() + } + } val scope = rememberCoroutineScope() var pendingDelete by remember { mutableStateOf(null) } val playback by playbackController.state.collectAsStateWithLifecycle() diff --git a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailViewModel.kt b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailViewModel.kt index 41445527..db1151bd 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailViewModel.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailViewModel.kt @@ -45,6 +45,8 @@ class AlbumDetailViewModel( val downloads: StateFlow> = downloadRepository.states() + val offline: StateFlow = sourceRepository.offline + val downloadStatus: StateFlow = sourceId .flatMapLatest { downloadRepository.status(it, DownloadList.Album, albumId) } diff --git a/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt index 15679d9a..49190085 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailScreen.kt @@ -47,6 +47,7 @@ import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf @@ -148,6 +149,15 @@ fun ArtistDetailRoute( val art by viewModel.art.collectAsStateWithLifecycle() val artThumbnail by viewModel.artThumbnail.collectAsStateWithLifecycle() val downloadStatus by viewModel.downloadStatus.collectAsStateWithLifecycle() + val offline by viewModel.offline.collectAsStateWithLifecycle() + var hadDownloads by remember { mutableStateOf(false) } + LaunchedEffect(downloadStatus.downloaded, offline) { + if (downloadStatus.downloaded > 0) { + hadDownloads = true + } else if (hadDownloads && offline) { + onBack() + } + } val albumDownloads by viewModel.albumDownloads.collectAsStateWithLifecycle() val scope = rememberCoroutineScope() var pendingDelete by remember { mutableStateOf(null) } @@ -185,6 +195,7 @@ fun ArtistDetailRoute( onMore = { artist?.let { contextMenuHost?.show(MenuTarget.Artist(it, artThumbnail ?: art, downloadStatus), actions) } }, starred = artist?.starred != null, onToggleStar = artist?.let { a -> { setStar(StarType.Artist, a.id, a.starred == null) } }, + offline = offline, ) pendingDelete?.let { pending -> @@ -214,6 +225,7 @@ fun ArtistDetailScreen( starred: Boolean = false, onToggleStar: (() -> Unit)? = null, onShuffle: () -> Unit = {}, + offline: Boolean = false, modifier: Modifier = Modifier, ) { val listState = rememberLazyGridState() @@ -227,6 +239,7 @@ fun ArtistDetailScreen( val statusBarTop = with(density) { WindowInsets.statusBars.getTop(this).toDp() } val navBarBottom = with(density) { WindowInsets.navigationBars.getBottom(this).toDp() } val barHeight = statusBarTop + TopAppBarDefaults.TopAppBarExpandedHeight + val albumCount = if (offline) albums.size.toLong() else artist?.albumCount ?: 0L val imageTitleTop = ART_HEIGHT - TITLE_INSET - lineHeight val fadeStartPx = with(density) { (imageTitleTop - barHeight - FADE_LEAD).toPx() } val fadeEndPx = with(density) { (imageTitleTop + lineHeight / 2 - barHeight).toPx() } @@ -348,7 +361,7 @@ fun ArtistDetailScreen( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = "${artist?.albumCount ?: 0} ${if (artist?.albumCount == 1L) "album" else "albums"}", + text = "$albumCount ${if (albumCount == 1L) "album" else "albums"}", style = MaterialTheme.typography.bodyLarge, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.weight(1f), diff --git a/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailViewModel.kt b/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailViewModel.kt index cd998d06..84a32806 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailViewModel.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/ArtistDetailViewModel.kt @@ -38,6 +38,8 @@ class ArtistDetailViewModel( val artist: Flow = sourceId.flatMapLatest { libraryRepository.artist(it, artistId) } + val offline: StateFlow = sourceRepository.offline + val albums: Flow> = combine(sourceId, sourceRepository.offline) { id, offline -> id to offline } .flatMapLatest { (id, offline) -> libraryRepository.artistAlbums(id, artistId, offline) } diff --git a/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt index 0db81f89..b58550b2 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/LibraryScreen.kt @@ -860,7 +860,7 @@ internal fun LibraryTabs( Icon( imageVector = Icons.Rounded.CloudOff, contentDescription = "Offline mode; tap to go online", - tint = MaterialTheme.colorScheme.error, + tint = MaterialTheme.colorScheme.onBackground, ) } } diff --git a/app/src/main/kotlin/com/subtracks/ui/library/PlaylistDetailScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/PlaylistDetailScreen.kt index b8ae3392..7b0eaa65 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/PlaylistDetailScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/PlaylistDetailScreen.kt @@ -2,6 +2,7 @@ package com.subtracks.ui.library import androidx.compose.foundation.combinedClickable import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -52,6 +53,14 @@ fun PlaylistDetailRoute( val downloads by viewModel.downloads.collectAsStateWithLifecycle() val downloadStatus by viewModel.downloadStatus.collectAsStateWithLifecycle() val offline by viewModel.offline.collectAsStateWithLifecycle() + var hadDownloads by remember { mutableStateOf(false) } + LaunchedEffect(downloadStatus.downloaded, offline) { + if (downloadStatus.downloaded > 0) { + hadDownloads = true + } else if (hadDownloads && offline) { + onBack() + } + } val scope = rememberCoroutineScope() var pendingDelete by remember { mutableStateOf(null) } val playback by playbackController.state.collectAsStateWithLifecycle()