From 8741c2fb88834915f957022e71ed0a5b54323d00 Mon Sep 17 00:00:00 2001 From: Honey Date: Wed, 1 Jul 2026 21:35:01 +0200 Subject: [PATCH] fix(android): back from album returns to the "all albums" view, not the artist page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The artist screen's "show all albums" overlay state was plain remember(), so navigating into an album and pressing back reset it — dumping you on the collapsed artist page instead of the list you came from. Persist which section is open via rememberSaveable (a String? title) so it survives the round-trip, and re-derive the overlay entries from the (surviving) categorized albums. Co-Authored-By: Claude Opus 4.8 --- .../app/ui/screen/ArtistDetailScreen.kt | 76 +++++++++---------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ArtistDetailScreen.kt b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ArtistDetailScreen.kt index 50540af..46901a7 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ArtistDetailScreen.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ArtistDetailScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.material.icons.filled.Shuffle import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -68,11 +69,12 @@ fun ArtistDetailScreen( BackHandler(enabled = state.partialAlbum != null) { vm.dismissPartialAlbum() } BackHandler(enabled = state.subAlbumItem != null && state.partialAlbum == null) { vm.dismissSubAlbum() } - var showAllAlbums by remember { mutableStateOf(false) } - var allAlbumsTitle by remember { mutableStateOf("") } - var allAlbumEntries by remember { mutableStateOf>(emptyList()) } + // Which "all albums" section is expanded (by title), or null. rememberSaveable so it survives + // navigating into an album and back — otherwise back would land on the collapsed artist page. + var openAllAlbums by rememberSaveable { mutableStateOf(null) } + val showAllAlbums = openAllAlbums != null BackHandler(enabled = showAllAlbums && state.partialAlbum == null && state.subAlbumItem == null) { - showAllAlbums = false + openAllAlbums = null } LaunchedEffect(state.pendingShufflePlay) { @@ -163,11 +165,35 @@ fun ArtistDetailScreen( // Album categories (computed once iTunes data arrives) val cats = if (state.iAlbums.isNotEmpty()) categorizeAlbums(artist.album, state.iAlbums) else null + // Rebuild the overlay entries from the (surviving) categorized albums for whichever section is + // open. Derived — not stored — so it's correct after returning from an album. + val allAlbumEntries: List = when (openAllAlbums) { + "In Library" -> cats?.downloaded?.map { (nd, _) -> + AllAlbumEntry(name = nd.name, year = nd.year?.toString(), artUrl = coverUrl(nd.coverArt), onClick = { onAlbumClick(nd) }) + }.orEmpty() + "Unvollständig" -> cats?.partial?.map { (nd, ia, counts) -> + AllAlbumEntry( + name = nd.name, year = nd.year?.toString(), + artUrl = ia.artworkUrl100?.replace("100x100bb", "300x300bb") ?: coverUrl(nd.coverArt), + badge = "${counts.first}/${counts.second}", + onClick = { vm.loadPartialAlbum(nd, ia) }, onDownload = { vm.showDownloadSheet(ia) }, + ) + }.orEmpty() + "Nicht heruntergeladen" -> cats?.notDownloaded?.map { ia -> + AllAlbumEntry( + name = ia.collectionName ?: "—", year = ia.releaseDate?.take(4), + artUrl = ia.artworkUrl100?.replace("100x100bb", "300x300bb"), dimmed = true, + onClick = { vm.loadSubAlbum(ia) }, onDownload = { vm.showDownloadSheet(ia) }, + ) + }.orEmpty() + else -> emptyList() + } + if (showAllAlbums) { AllAlbumsOverlay( - title = allAlbumsTitle, + title = openAllAlbums ?: "", entries = allAlbumEntries, - onBack = { showAllAlbums = false }, + onBack = { openAllAlbums = null }, ) return } @@ -349,13 +375,7 @@ fun ArtistDetailScreen( if (cats.downloaded.isNotEmpty()) { item { ArtistSectionHeader("In Library", cats.downloaded.size, - onShowAll = if (cats.downloaded.size > 4) ({ - allAlbumsTitle = "In Library" - allAlbumEntries = cats.downloaded.map { (nd, _) -> - AllAlbumEntry(name = nd.name, year = nd.year?.toString(), artUrl = coverUrl(nd.coverArt), onClick = { onAlbumClick(nd) }) - } - showAllAlbums = true - }) else null + onShowAll = if (cats.downloaded.size > 4) ({ openAllAlbums = "In Library" }) else null ) } item { @@ -379,20 +399,7 @@ fun ArtistDetailScreen( if (cats.partial.isNotEmpty()) { item { ArtistSectionHeader("Unvollständig", cats.partial.size, - onShowAll = if (cats.partial.size > 4) ({ - allAlbumsTitle = "Unvollständig" - allAlbumEntries = cats.partial.map { (nd, ia, counts) -> - AllAlbumEntry( - name = nd.name, - year = nd.year?.toString(), - artUrl = ia.artworkUrl100?.replace("100x100bb", "300x300bb") ?: coverUrl(nd.coverArt), - badge = "${counts.first}/${counts.second}", - onClick = { vm.loadPartialAlbum(nd, ia) }, - onDownload = { vm.showDownloadSheet(ia) }, - ) - } - showAllAlbums = true - }) else null + onShowAll = if (cats.partial.size > 4) ({ openAllAlbums = "Unvollständig" }) else null ) } item { @@ -419,20 +426,7 @@ fun ArtistDetailScreen( if (cats.notDownloaded.isNotEmpty()) { item { ArtistSectionHeader("Nicht heruntergeladen", cats.notDownloaded.size, - onShowAll = if (cats.notDownloaded.size > 4) ({ - allAlbumsTitle = "Nicht heruntergeladen" - allAlbumEntries = cats.notDownloaded.map { ia -> - AllAlbumEntry( - name = ia.collectionName ?: "—", - year = ia.releaseDate?.take(4), - artUrl = ia.artworkUrl100?.replace("100x100bb", "300x300bb"), - dimmed = true, - onClick = { vm.loadSubAlbum(ia) }, - onDownload = { vm.showDownloadSheet(ia) }, - ) - } - showAllAlbums = true - }) else null + onShowAll = if (cats.notDownloaded.size > 4) ({ openAllAlbums = "Nicht heruntergeladen" }) else null ) } item {