@@ -2,9 +2,11 @@ package com.rumosoft.marvelcompose.presentation
22
33import android.app.Activity
44import android.content.Context
5+ import android.content.Intent
56import android.os.Bundle
67import androidx.activity.ComponentActivity
78import androidx.activity.compose.BackHandler
9+ import androidx.activity.compose.LocalActivity
810import androidx.activity.compose.setContent
911import androidx.activity.enableEdgeToEdge
1012import androidx.compose.foundation.layout.Row
@@ -14,6 +16,7 @@ import androidx.compose.material3.SnackbarHost
1416import androidx.compose.material3.SnackbarHostState
1517import androidx.compose.material3.Surface
1618import androidx.compose.runtime.Composable
19+ import androidx.compose.runtime.LaunchedEffect
1720import androidx.compose.runtime.getValue
1821import androidx.compose.runtime.mutableStateOf
1922import androidx.compose.runtime.remember
@@ -22,21 +25,23 @@ import androidx.compose.runtime.setValue
2225import androidx.compose.ui.Modifier
2326import androidx.compose.ui.platform.LocalContext
2427import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
25- import androidx.navigation.NavHostController
26- import androidx.navigation.compose.currentBackStackEntryAsState
27- import androidx.navigation.compose.rememberNavController
28+ import androidx.navigation3.runtime.NavKey
2829import com.rumosoft.components.presentation.component.isWindowCompact
2930import com.rumosoft.components.presentation.deeplinks.CharactersScreen
3031import com.rumosoft.components.presentation.deeplinks.ComicsScreen
32+ import com.rumosoft.components.presentation.deeplinks.DEEP_LINKS_BASE_PATH
3133import com.rumosoft.components.presentation.deeplinks.Screen
3234import com.rumosoft.components.presentation.theme.MarvelComposeTheme
3335import com.rumosoft.marvelcompose.R
3436import com.rumosoft.marvelcompose.presentation.navigation.BottomNavigationBar
3537import com.rumosoft.marvelcompose.presentation.navigation.NavigationHost
3638import com.rumosoft.marvelcompose.presentation.navigation.NavigationRailBar
39+ import com.rumosoft.marvelcompose.presentation.navigation.NavigationState
40+ import com.rumosoft.marvelcompose.presentation.navigation.Navigator
41+ import com.rumosoft.marvelcompose.presentation.navigation.Tabs
3742import com.rumosoft.marvelcompose.presentation.navigation.Tabs.Characters
3843import com.rumosoft.marvelcompose.presentation.navigation.Tabs.Comics
39- import com.rumosoft.marvelcompose.presentation.navigation.onTabClick
44+ import com.rumosoft.marvelcompose.presentation.navigation.rememberNavigationState
4045import dagger.hilt.android.AndroidEntryPoint
4146import kotlinx.coroutines.CoroutineScope
4247import kotlinx.coroutines.launch
@@ -63,7 +68,20 @@ class MainActivity : ComponentActivity() {
6368
6469@Composable
6570fun MarvelApp () {
66- val navController = rememberNavController()
71+ val navigationState = rememberNavigationState(
72+ startRoute = CharactersScreen ,
73+ topLevelRoutes = setOf<NavKey >(CharactersScreen , ComicsScreen )
74+ )
75+ val navigator = remember { Navigator (navigationState) }
76+
77+ // Handle deep links from intent
78+ val activity = LocalActivity .current
79+ LaunchedEffect (Unit ) {
80+ activity?.intent?.let { intent ->
81+ handleDeepLink(intent, navigator)
82+ }
83+ }
84+
6785 val navigationItems = listOf (
6886 Characters ,
6987 Comics ,
@@ -78,11 +96,11 @@ fun MarvelApp() {
7896 topBar = { topBarContent() },
7997 snackbarHost = { SnackbarHost (hostState = snackBarHostState) },
8098 bottomBar = {
81- if (shouldShowBottomBar(navController )) {
99+ if (shouldShowBottomBar(navigationState )) {
82100 BottomNavigationBar (
83101 navigationItems = navigationItems,
84- currentScreen = getCurrentScreen(navController ),
85- onTabClick = { onTabClick(it, navController ) },
102+ currentScreen = getCurrentScreen(navigationState ),
103+ onTabClick = { onTabClick(it, navigator ) },
86104 )
87105 }
88106 },
@@ -91,18 +109,20 @@ fun MarvelApp() {
91109 Row {
92110 NavigationRailBar (
93111 navigationItems = navigationItems,
94- currentScreen = getCurrentScreen(navController ),
95- onTabClick = { onTabClick(it, navController ) },
112+ currentScreen = getCurrentScreen(navigationState ),
113+ onTabClick = { onTabClick(it, navigator ) },
96114 )
97115 NavigationHost (
98- navController,
116+ navigationState = navigationState,
117+ navigator = navigator,
99118 setTopBarContent = { topBarContent = it },
100119 modifier = Modifier .padding(innerPadding),
101120 )
102121 }
103122 } else {
104123 NavigationHost (
105- navController,
124+ navigationState = navigationState,
125+ navigator = navigator,
106126 setTopBarContent = { topBarContent = it },
107127 modifier = Modifier .padding(innerPadding),
108128 )
@@ -112,32 +132,27 @@ fun MarvelApp() {
112132
113133@Composable
114134private fun shouldShowBottomBar (
115- navController : NavHostController
135+ navigationState : NavigationState
116136): Boolean {
117- println (" isWindowCompact: ${isWindowCompact()} " )
118- println (" currentRoute: ${currentRoute(navController)} " )
119- return isWindowCompact() && (
120- currentRoute(navController)?.contains(" CharactersScreen" ) == true ||
121- currentRoute(navController)?.contains(" ComicsScreen" ) == true )
137+ val isOnTopLevel = navigationState.backStacks[navigationState.topLevelRoute]?.let {
138+ it.size == 1
139+ } ? : true
140+ return isWindowCompact() && isOnTopLevel
122141}
123142
124143@Composable
125- private fun getCurrentScreen (navController : NavHostController ): Screen {
126- val route = navController.currentBackStackEntryAsState().value?.destination?.route
127- return when {
128- route?.contains(" CharactersScreen" ) == true -> CharactersScreen
129- route?.contains(" ComicsScreen" ) == true -> ComicsScreen
144+ private fun getCurrentScreen (navigationState : NavigationState ): Screen {
145+ return when (navigationState.topLevelRoute) {
146+ is ComicsScreen -> ComicsScreen
130147 else -> CharactersScreen
131148 }
132149}
133150
134151@Composable
135152private fun shouldShowNavigationRail () = ! isWindowCompact()
136153
137- @Composable
138- private fun currentRoute (navController : NavHostController ): String? {
139- val navBackStackEntry by navController.currentBackStackEntryAsState()
140- return navBackStackEntry?.destination?.route
154+ private fun onTabClick (tab : Tabs , navigator : Navigator ) {
155+ navigator.navigate(tab.screen as NavKey )
141156}
142157
143158private fun onAppBack (
@@ -154,3 +169,12 @@ private fun onAppBack(
154169 }
155170}
156171
172+ private fun handleDeepLink (intent : Intent , navigator : Navigator ) {
173+ val uri = intent.data ? : return
174+ val path = uri.toString().removePrefix(DEEP_LINKS_BASE_PATH )
175+ when {
176+ path.startsWith(" /comics" ) -> navigator.navigate(ComicsScreen as NavKey )
177+ path.startsWith(" /characters" ) -> navigator.navigate(CharactersScreen as NavKey )
178+ }
179+ }
180+
0 commit comments