diff --git a/android/app/src/main/kotlin/com/novasonic/app/ui/AppNavigation.kt b/android/app/src/main/kotlin/com/novasonic/app/ui/AppNavigation.kt index d6ffb2d..13a768a 100644 --- a/android/app/src/main/kotlin/com/novasonic/app/ui/AppNavigation.kt +++ b/android/app/src/main/kotlin/com/novasonic/app/ui/AppNavigation.kt @@ -96,6 +96,10 @@ fun AppNavigation() { var showNotifications by remember { mutableStateOf(false) } var selectedAbsItem by remember { mutableStateOf(null) } var showAbsPlayer by remember { mutableStateOf(false) } + // Close action for the Erkunden (Apple) in-screen overlay (iTunes artist / album). Handled at the + // app root because a BackHandler inside the NavHost "erkunden" destination loses back priority to + // the NavHost, which pops Erkunden → Home instead of dismissing the overlay. + var exploreOverlayBack by remember { mutableStateOf<(() -> Unit)?>(null) } val backDispatcher = LocalOnBackPressedDispatcherOwner.current?.onBackPressedDispatcher DisposableEffect(showNowPlaying, backDispatcher) { @@ -122,6 +126,15 @@ fun AppNavigation() { backDispatcher.addCallback(cb) onDispose { cb.remove() } } + DisposableEffect(exploreOverlayBack, backDispatcher) { + val action = exploreOverlayBack + if (action == null || backDispatcher == null) return@DisposableEffect onDispose {} + val cb = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { action() } + } + backDispatcher.addCallback(cb) + onDispose { cb.remove() } + } fun coverUrl(coverId: String?) = repo.coverArtUrl(coverId, 600) fun heroCoverUrl(coverId: String?) = repo.coverArtUrl(coverId, 1000) @@ -275,6 +288,7 @@ fun AppNavigation() { onAlbumClick = { album -> navController.navigate("album/${album.id}") }, onArtistClick = { artist -> navController.navigate("artist/${artist.id}") }, onShowContextMenu = ::showContextMenu, + onOverlayBackChange = { exploreOverlayBack = it }, onOpenImporter = { navController.navigate("importer") }, ) } @@ -395,21 +409,6 @@ fun AppNavigation() { } } - // ── TEMP NAV DEBUG — zeigt den Back-Stack; wird nach der Diagnose entfernt ── - val dbgBackStack by navController.currentBackStack.collectAsStateWithLifecycle() - Box(Modifier.fillMaxWidth().statusBarsPadding(), contentAlignment = androidx.compose.ui.Alignment.TopCenter) { - Text( - "🧭 " + dbgBackStack.mapNotNull { it.destination.route?.substringBefore("/") } - .filter { it != "null" }.joinToString(" › "), - color = Color(0xFFFFEB3B), - fontSize = 9.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier - .background(Color(0xCC000000)) - .padding(horizontal = 6.dp, vertical = 2.dp), - ) - } - // NowPlaying overlay AnimatedVisibility( visible = showNowPlaying, 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 313b238..66019dc 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 @@ -1,6 +1,5 @@ package com.novasonic.app.ui.screen -import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -50,6 +49,7 @@ fun ExploreScreen( onAlbumClick: (com.novasonic.app.api.model.Album) -> Unit, onArtistClick: (com.novasonic.app.api.model.Artist) -> Unit, onShowContextMenu: ((com.novasonic.app.api.model.Song) -> Unit)? = null, + onOverlayBackChange: ((() -> Unit)?) -> Unit = {}, onOpenImporter: () -> Unit = {}, ) { val vm: ExploreViewModel = viewModel() @@ -57,10 +57,29 @@ fun ExploreScreen( val focusManager = LocalFocusManager.current val context = LocalContext.current - // BackHandlers for state-based navigation (must be unconditional) - BackHandler(enabled = state.artistDetail != null && state.partialAlbum != null) { vm.dismissPartialAlbum() } - BackHandler(enabled = state.artistDetail != null && state.albumTracks != null && state.partialAlbum == null) { vm.dismissAlbum() } - BackHandler(enabled = state.artistDetail != null && state.albumTracks == null && state.partialAlbum == null) { vm.closeArtistDetail() } + // Overlay back is handled at the app root (see AppNavigation.exploreOverlayBack): a BackHandler + // inside this NavHost destination loses back priority to the NavHost, which pops Erkunden → Home. + // Report the current overlay's close action up; clear it when this screen leaves composition + // (e.g. drilling into a real album route) so that screen's own back works normally. + val overlayKind = when { + state.artistDetail != null && state.partialAlbum != null -> 4 // artist → partial album + state.artistDetail != null && state.albumTracks != null -> 3 // artist → iTunes album + state.artistDetail != null -> 2 // iTunes artist + state.albumTracks != null -> 1 // album straight from search + else -> 0 + } + DisposableEffect(overlayKind) { + onOverlayBackChange( + when (overlayKind) { + 4 -> vm::dismissPartialAlbum + 3 -> vm::dismissAlbum + 2 -> vm::closeArtistDetail + 1 -> vm::dismissAlbum + else -> null + } + ) + onDispose { onOverlayBackChange(null) } + } // Download sheet state.downloadSheetItem?.let { item ->