From 93ee958434a33e42fabe9fbeb6e8d1a7a6fef0b5 Mon Sep 17 00:00:00 2001 From: Honey Date: Wed, 2 Sep 2026 07:42:24 +0200 Subject: [PATCH] feat: artist-page scroll/search memory (android) + move APK button to bottom (web) - Android: the artist page's main list and the "Alle anzeigen" album overlay (grid scroll + search query) are hoisted into the Artist/Explore ViewModels, so drilling into an album/artist and back keeps position + query. Covers the library artist and Deezer (Explore) artist screens. - Web: the "Android App" download section now sits at the very bottom of Settings, below the Navidrome-Server (account) section. Co-Authored-By: Claude Opus 4.8 --- .../app/ui/screen/ArtistDetailScreen.kt | 14 +++++++---- .../novasonic/app/ui/screen/ExploreScreen.kt | 3 +++ .../app/ui/screen/ItunesArtistScreen.kt | 6 +++++ .../app/viewmodel/ArtistViewModel.kt | 6 +++++ .../app/viewmodel/ExploreViewModel.kt | 4 ++++ index.html | 24 +++++++++---------- 6 files changed, 41 insertions(+), 16 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 b6f3c09..02ad0b4 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 @@ -215,11 +215,14 @@ fun ArtistDetailScreen( title = openAllAlbums ?: "", entries = allAlbumEntries, onBack = { openAllAlbums = null }, + gridState = vm.allAlbumsGrid, + query = vm.allAlbumsQuery.value, + onQueryChange = { vm.allAlbumsQuery.value = it }, ) return } - LazyColumn(Modifier.fillMaxSize()) { + LazyColumn(state = vm.pageListState, modifier = Modifier.fillMaxSize()) { // Back link item { Row( @@ -624,8 +627,10 @@ internal fun AllAlbumsOverlay( title: String, entries: List, onBack: () -> Unit, + gridState: androidx.compose.foundation.lazy.grid.LazyGridState = androidx.compose.foundation.lazy.grid.rememberLazyGridState(), + query: String = "", + onQueryChange: (String) -> Unit = {}, ) { - var query by remember { mutableStateOf("") } val filtered = remember(query, entries) { if (query.isBlank()) entries else entries.filter { it.name.contains(query, ignoreCase = true) } @@ -660,11 +665,11 @@ internal fun AllAlbumsOverlay( // Search bar OutlinedTextField( value = query, - onValueChange = { query = it }, + onValueChange = onQueryChange, placeholder = { Text("Suchen…", color = NsOnSurface2) }, leadingIcon = { Icon(Icons.Default.Search, null, tint = NsOnSurface2) }, trailingIcon = if (query.isNotEmpty()) { { - IconButton(onClick = { query = "" }) { + IconButton(onClick = { onQueryChange("") }) { Icon(Icons.Default.Clear, null, tint = NsOnSurface2) } } } else null, @@ -684,6 +689,7 @@ internal fun AllAlbumsOverlay( ) LazyVerticalGrid( + state = gridState, columns = GridCells.Fixed(2), contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp), horizontalArrangement = Arrangement.spacedBy(12.dp), diff --git a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt index fd22249..6df54be 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ExploreScreen.kt @@ -145,6 +145,9 @@ fun ExploreScreen( allAlbumsOpen = state.artistAllAlbums, onOpenAllAlbums = vm::openArtistAllAlbums, onCloseAllAlbums = vm::closeArtistAllAlbums, + allAlbumsGrid = vm.allAlbumsGrid, + allAlbumsQuery = vm.allAlbumsQuery.value, + onAllAlbumsQueryChange = { vm.allAlbumsQuery.value = it }, ) } } diff --git a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ItunesArtistScreen.kt b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ItunesArtistScreen.kt index c95dbff..ecf1fc4 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ItunesArtistScreen.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/ui/screen/ItunesArtistScreen.kt @@ -109,6 +109,9 @@ fun ItunesArtistScreen( allAlbumsOpen: String?, onOpenAllAlbums: (String) -> Unit, onCloseAllAlbums: () -> Unit, + allAlbumsGrid: androidx.compose.foundation.lazy.grid.LazyGridState = androidx.compose.foundation.lazy.grid.rememberLazyGridState(), + allAlbumsQuery: String = "", + onAllAlbumsQueryChange: (String) -> Unit = {}, ) { val artist = artistState.artist val cats = if (!artistState.isLoading) @@ -144,6 +147,9 @@ fun ItunesArtistScreen( title = allAlbumsOpen, entries = allAlbumEntries, onBack = onCloseAllAlbums, + gridState = allAlbumsGrid, + query = allAlbumsQuery, + onQueryChange = onAllAlbumsQueryChange, ) return } diff --git a/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ArtistViewModel.kt b/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ArtistViewModel.kt index 5cbcbe7..e4151c1 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ArtistViewModel.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ArtistViewModel.kt @@ -70,6 +70,12 @@ class ArtistViewModel(app: Application, savedState: SavedStateHandle) : AndroidV private val _state = MutableStateFlow(ArtistUiState()) val state: StateFlow = _state + // Scroll of the artist page + the "alle anzeigen" overlay, hoisted so tapping an album/artist and + // coming back returns you to the same spot (the artist route entry, hence this VM, is retained). + val pageListState = androidx.compose.foundation.lazy.LazyListState() + val allAlbumsGrid = androidx.compose.foundation.lazy.grid.LazyGridState() + val allAlbumsQuery = androidx.compose.runtime.mutableStateOf("") + init { if (artistId.isNullOrBlank()) { _state.value = ArtistUiState(isLoading = false, error = "Keine Künstler-ID übergeben") diff --git a/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ExploreViewModel.kt b/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ExploreViewModel.kt index 0a2eeb0..9a46627 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ExploreViewModel.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/viewmodel/ExploreViewModel.kt @@ -79,6 +79,10 @@ class ExploreViewModel(app: Application) : AndroidViewModel(app) { // Global-search results scroll — hoisted so it survives an album/artist drill-in and back. val searchListState = LazyListState() + // "Alle anzeigen" overlay (Deezer artist albums): scroll + search query, hoisted so an album + // drill-in and back keeps both (the overlay itself leaves composition on drill-in). + val allAlbumsGrid = androidx.compose.foundation.lazy.grid.LazyGridState() + val allAlbumsQuery = androidx.compose.runtime.mutableStateOf("") private var searchJob: Job? = null diff --git a/index.html b/index.html index f0686c7..f422a1c 100644 --- a/index.html +++ b/index.html @@ -605,18 +605,6 @@
-

📊 @@ -709,6 +697,18 @@

+