From bb3d8f57ca467724abc312d898e7739d66a00cb8 Mon Sep 17 00:00:00 2001 From: Luqman Fadlli Date: Fri, 17 Jul 2026 00:04:10 +0700 Subject: [PATCH 1/2] fix(ios): hide NavBar overlay obstructing collection folder header --- iosApp/iosApp/ContentView.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/iosApp/iosApp/ContentView.swift b/iosApp/iosApp/ContentView.swift index 07d45432a..e67901f6f 100644 --- a/iosApp/iosApp/ContentView.swift +++ b/iosApp/iosApp/ContentView.swift @@ -790,11 +790,17 @@ private struct DetailDestinationView: View { @ObservedObject var appCoordinator: AppNavigationCoordinator private var usesComposeNavigationHeader: Bool { - wrapper.route is DetailRoute || wrapper.route is StreamRoute + wrapper.route is DetailRoute || + wrapper.route is StreamRoute || + wrapper.route is FolderDetailRoute + } + + private var hidesNativeNavigationBar: Bool { + wrapper.route.hidesNavigationBar || usesComposeNavigationHeader } private var showsReadabilityFade: Bool { - !wrapper.route.hidesNavigationBar && !usesComposeNavigationHeader + !hidesNativeNavigationBar } private var content: some View { @@ -822,7 +828,7 @@ private struct DetailDestinationView: View { } .toolbar(.hidden, for: .tabBar) .toolbar( - wrapper.route.hidesNavigationBar ? Visibility.hidden : Visibility.visible, + hidesNativeNavigationBar ? Visibility.hidden : Visibility.visible, for: .navigationBar ) } From 6de66cfa76be913d348bed25921beacda3754c60 Mon Sep 17 00:00:00 2001 From: Luqman Fadlli Date: Fri, 17 Jul 2026 00:11:44 +0700 Subject: [PATCH 2/2] fix(ios): restore back gesture and navigation --- .../features/collection/FolderDetailScreen.kt | 18 ++++--- iosApp/iosApp/ContentView.swift | 48 ++++++++++++------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/FolderDetailScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/FolderDetailScreen.kt index 11ba0a6c9..e6b16a9ca 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/FolderDetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/collection/FolderDetailScreen.kt @@ -63,6 +63,7 @@ import com.nuvio.app.features.home.stableKey import com.nuvio.app.features.home.components.HomeCatalogRowSection import com.nuvio.app.features.watched.WatchedRepository import com.nuvio.app.features.watching.application.WatchingState +import com.nuvio.app.navigation.LocalUseNativeNavigation import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map @@ -86,6 +87,7 @@ fun FolderDetailScreen( WatchedRepository.uiState }.collectAsState() val folder = uiState.folder + val useNativeNavigation = LocalUseNativeNavigation.current val coverImageUrl = folder?.coverImageUrl?.takeIf { it.isNotBlank() } val density = LocalDensity.current val statusBarTop = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() @@ -141,13 +143,15 @@ fun FolderDetailScreen( ) } - NuvioScreenHeader( - title = folder?.title ?: uiState.collectionTitle, - modifier = Modifier.padding(horizontal = 16.dp), - includeStatusBarPadding = coverImageUrl == null, - topPadding = if (coverImageUrl != null) statusBarTop * heroCollapseFraction else null, - onBack = onBack, - ) + if (!useNativeNavigation) { + NuvioScreenHeader( + title = folder?.title ?: uiState.collectionTitle, + modifier = Modifier.padding(horizontal = 16.dp), + includeStatusBarPadding = coverImageUrl == null, + topPadding = if (coverImageUrl != null) statusBarTop * heroCollapseFraction else null, + onBack = onBack, + ) + } if (folder == null && !uiState.isLoading) { Box( diff --git a/iosApp/iosApp/ContentView.swift b/iosApp/iosApp/ContentView.swift index e67901f6f..feac50ee9 100644 --- a/iosApp/iosApp/ContentView.swift +++ b/iosApp/iosApp/ContentView.swift @@ -102,19 +102,19 @@ final class RootComposeViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - setInteractiveContentPopGestureEnabled(false) + configureBackGestures(isVisible: true) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - setInteractiveContentPopGestureEnabled(false) + configureBackGestures(isVisible: true) if let tabBar = tabBarController?.tabBar { onTabBarAvailable?(tabBar) } } override func viewWillDisappear(_ animated: Bool) { - setInteractiveContentPopGestureEnabled(true) + configureBackGestures(isVisible: false) super.viewWillDisappear(animated) } @@ -124,11 +124,12 @@ final class RootComposeViewController: UIViewController { setNeedsStatusBarAppearanceUpdate() } - private func setInteractiveContentPopGestureEnabled(_ enabled: Bool) { - guard disablesInteractiveContentPopGesture else { return } + private func configureBackGestures(isVisible: Bool) { if #available(iOS 26.0, *) { - navigationController?.interactiveContentPopGestureRecognizer?.isEnabled = enabled + navigationController?.interactiveContentPopGestureRecognizer?.isEnabled = false } + navigationController?.interactivePopGestureRecognizer?.isEnabled = + isVisible ? !disablesInteractiveContentPopGesture : true } private func immersiveController(in controller: UIViewController?) -> UIViewController? { @@ -700,7 +701,7 @@ struct DetailComposeView: UIViewControllerRepresentable { ) return NuvioComposeHost.wrap( controller, - disablesInteractiveContentPopGesture: true + disablesInteractiveContentPopGesture: route is PlayerRoute ) } @@ -790,27 +791,38 @@ private struct DetailDestinationView: View { @ObservedObject var appCoordinator: AppNavigationCoordinator private var usesComposeNavigationHeader: Bool { - wrapper.route is DetailRoute || - wrapper.route is StreamRoute || - wrapper.route is FolderDetailRoute + wrapper.route is DetailRoute || wrapper.route is StreamRoute + } + + private var respectsNativeNavigationSafeArea: Bool { + wrapper.route is FolderDetailRoute } private var hidesNativeNavigationBar: Bool { - wrapper.route.hidesNavigationBar || usesComposeNavigationHeader + wrapper.route.hidesNavigationBar } private var showsReadabilityFade: Bool { - !hidesNativeNavigationBar + !hidesNativeNavigationBar && !usesComposeNavigationHeader } private var content: some View { ZStack(alignment: .top) { - DetailComposeView( - route: wrapper.route, - coordinator: coordinator, - appCoordinator: appCoordinator - ) - .ignoresSafeArea(.all) + if respectsNativeNavigationSafeArea { + DetailComposeView( + route: wrapper.route, + coordinator: coordinator, + appCoordinator: appCoordinator + ) + .ignoresSafeArea(.all, edges: [.horizontal, .bottom]) + } else { + DetailComposeView( + route: wrapper.route, + coordinator: coordinator, + appCoordinator: appCoordinator + ) + .ignoresSafeArea(.all) + } if showsReadabilityFade { NativeToolbarReadabilityFade()