diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt index 4d3b60c97..79fd0ce92 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/App.kt @@ -394,6 +394,8 @@ fun App( initialTab: AppScreenTab = AppScreenTab.Home, initialRoute: AppRoute = TabsRoute, useNativeNavigation: Boolean = false, + useNativeTabBar: Boolean = false, + useTabletFloatingTabBar: Boolean = false, ownsAppRuntime: Boolean = true, bypassAppGate: Boolean = false, onNavigate: ((AppRoute, launchSingleTop: Boolean) -> Unit)? = null, @@ -425,6 +427,8 @@ fun App( initialTab = initialTab, initialRoute = initialRoute, useNativeNavigation = useNativeNavigation, + useNativeTabBar = useNativeTabBar, + useTabletFloatingTabBar = useTabletFloatingTabBar, ownsAppRuntime = false, onNavigate = onNavigate, onGoBack = onGoBack, @@ -688,6 +692,8 @@ fun App( initialTab = initialTab, initialRoute = initialRoute, useNativeNavigation = useNativeNavigation, + useNativeTabBar = useNativeTabBar, + useTabletFloatingTabBar = useTabletFloatingTabBar, ownsAppRuntime = ownsAppRuntime, onNavigate = onNavigate, onGoBack = onGoBack, @@ -716,6 +722,8 @@ private fun MainAppContent( initialTab: AppScreenTab = AppScreenTab.Home, initialRoute: AppRoute = TabsRoute, useNativeNavigation: Boolean = false, + useNativeTabBar: Boolean = false, + useTabletFloatingTabBar: Boolean = false, ownsAppRuntime: Boolean = true, onNavigate: ((AppRoute, launchSingleTop: Boolean) -> Unit)? = null, onGoBack: (() -> Unit)? = null, @@ -1762,9 +1770,12 @@ private fun MainAppContent( ) BoxWithConstraints(modifier = Modifier.fillMaxSize()) { - val isTabletLayout = maxWidth >= 768.dp - val useNativeBottomTabs = useNativeNavigation || - (liquidGlassNativeTabBarSupported && liquidGlassNativeTabBarEnabled && initialHomeReady) + val isTabletLayout = useTabletFloatingTabBar || maxWidth >= 768.dp + val useNativeBottomTabs = if (useNativeNavigation) { + useNativeTabBar + } else { + liquidGlassNativeTabBarSupported && liquidGlassNativeTabBarEnabled && initialHomeReady + } val nativeTabSafeBottomPadding = nuvioBottomNavigationBarInsets() .asPaddingValues() .calculateBottomPadding() @@ -1877,7 +1888,7 @@ private fun MainAppContent( } }, onConnectCloudClick = { - if (useNativeNavigation) { + if (useNativeNavigation && !isTabletLayout) { activateTab(AppScreenTab.Settings) navController.navigate( SettingsPageRoute( @@ -1893,7 +1904,7 @@ private fun MainAppContent( onContinueWatchingClick = onContinueWatchingClick, onContinueWatchingLongPress = onContinueWatchingLongPress, onSwitchProfile = onSwitchProfile, - onSettingsPageClick = if (useNativeNavigation) { + onSettingsPageClick = if (useNativeNavigation && !isTabletLayout) { { pageName, title -> navController.navigate(SettingsPageRoute(pageName, title)) } diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/MainViewController.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/MainViewController.kt index 03d3371bf..9ca9b557c 100644 --- a/composeApp/src/iosMain/kotlin/com/nuvio/app/MainViewController.kt +++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/MainViewController.kt @@ -16,6 +16,8 @@ fun MainViewController(): UIViewController = nuvioComposeViewController { @Suppress("unused") fun MainViewController( initialTabName: String, + useNativeTabBar: Boolean, + useTabletFloatingTabBar: Boolean, onNavigate: (AppRoute, Boolean) -> Unit, onGoBack: () -> Unit, onReplace: (AppRoute) -> Unit, @@ -28,6 +30,8 @@ fun MainViewController( App( initialTab = initialTab, useNativeNavigation = true, + useNativeTabBar = useNativeTabBar, + useTabletFloatingTabBar = useTabletFloatingTabBar, ownsAppRuntime = initialTab == AppScreenTab.Home, bypassAppGate = initialTab != AppScreenTab.Home, onNavigate = onNavigate, diff --git a/iosApp/iosApp/ContentView.swift b/iosApp/iosApp/ContentView.swift index bdde594a0..f49ce6de3 100644 --- a/iosApp/iosApp/ContentView.swift +++ b/iosApp/iosApp/ContentView.swift @@ -529,12 +529,16 @@ final class AppNavigationCoordinator: ObservableObject { @available(iOS 16.0, *) struct NativeNavComposeView: UIViewControllerRepresentable { let tab: NuvioAppTab + let usesNativeTabBar: Bool + let usesTabletFloatingTabBar: Bool let coordinator: TabNavigationCoordinator let appCoordinator: AppNavigationCoordinator func makeUIViewController(context: Context) -> UIViewController { let controller = MainViewControllerKt.MainViewController( initialTabName: tab.rawValue, + useNativeTabBar: usesNativeTabBar, + useTabletFloatingTabBar: usesTabletFloatingTabBar, onNavigate: { route, launchSingleTop in appCoordinator.push( route, @@ -607,6 +611,8 @@ struct DetailComposeView: UIViewControllerRepresentable { @available(iOS 16.0, *) struct TabContentView: View { let tab: NuvioAppTab + let usesNativeTabBar: Bool + let usesTabletFloatingTabBar: Bool @ObservedObject var coordinator: TabNavigationCoordinator @ObservedObject var appCoordinator: AppNavigationCoordinator @@ -619,6 +625,8 @@ struct TabContentView: View { ) { NativeNavComposeView( tab: tab, + usesNativeTabBar: usesNativeTabBar, + usesTabletFloatingTabBar: usesTabletFloatingTabBar, coordinator: coordinator, appCoordinator: appCoordinator ) @@ -646,7 +654,7 @@ struct TabContentView: View { // stack. Applying it here keeps the authentication/profile gate truly // full-screen on iOS 26, where a modifier on TabView itself is ignored. .toolbar( - appCoordinator.isAppReady && coordinator.path.isEmpty + usesNativeTabBar && appCoordinator.isAppReady && coordinator.path.isEmpty ? Visibility.visible : Visibility.hidden, for: .tabBar @@ -728,6 +736,20 @@ struct NativeNavContentView: View { @StateObject private var appCoordinator = AppNavigationCoordinator() @StateObject private var iconStore = NativeTabIconStore() + private var usesNativeTabBar: Bool { + guard UIDevice.current.userInterfaceIdiom == .phone else { + return false + } + if #available(iOS 26.0, *) { + return true + } + return false + } + + private var usesTabletFloatingTabBar: Bool { + UIDevice.current.userInterfaceIdiom == .pad + } + private var tabs: some View { TabView( selection: Binding( @@ -746,6 +768,8 @@ struct NativeNavContentView: View { ForEach(NuvioAppTab.allCases, id: \.self) { tab in TabContentView( tab: tab, + usesNativeTabBar: usesNativeTabBar, + usesTabletFloatingTabBar: usesTabletFloatingTabBar, coordinator: appCoordinator.coordinator(for: tab), appCoordinator: appCoordinator ) @@ -773,7 +797,7 @@ struct NativeNavContentView: View { @ViewBuilder var body: some View { - if #available(iOS 26.0, *) { + if #available(iOS 26.0, *), usesNativeTabBar { tabs.tabBarMinimizeBehavior(.automatic) } else { tabs