diff --git a/app/src/main/java/com/yapp/chaeum/navigation/AppNavHost.kt b/app/src/main/java/com/yapp/chaeum/navigation/AppNavHost.kt index 08e922a5..6269374b 100644 --- a/app/src/main/java/com/yapp/chaeum/navigation/AppNavHost.kt +++ b/app/src/main/java/com/yapp/chaeum/navigation/AppNavHost.kt @@ -3,12 +3,12 @@ package com.yapp.chaeum.navigation import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.compose.NavHost -import com.example.auth.navigation.AuthRoute -import com.example.auth.navigation.authScreen -import com.example.etc.navigation.etcScreen -import com.example.matching.navigation.matchingScreen -import com.example.mypage.navigation.myPageScreen +import androidx.navigation.compose.composable +import com.example.auth.navigation.AuthGraph +import com.example.auth.navigation.authNavGraph import com.yapp.chaeum.ui.AppState +import com.yapp.chaeum.ui.HomeGraph +import com.yapp.chaeum.ui.HomeRoute @Composable fun AppNavHost( @@ -18,14 +18,14 @@ fun AppNavHost( val navController = appState.navController NavHost( navController = navController, - startDestination = AuthRoute, + startDestination = AuthGraph, modifier = modifier, ) { - authScreen( + authNavGraph( onLoginSuccess = { appState.loginSuccess() }, ) - matchingScreen() - myPageScreen() - etcScreen() + composable { + HomeRoute() + } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/yapp/chaeum/navigation/HomeNavHost.kt b/app/src/main/java/com/yapp/chaeum/navigation/HomeNavHost.kt new file mode 100644 index 00000000..97729fa0 --- /dev/null +++ b/app/src/main/java/com/yapp/chaeum/navigation/HomeNavHost.kt @@ -0,0 +1,26 @@ +package com.yapp.chaeum.navigation + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import com.example.etc.navigation.etcScreen +import com.example.matching.navigation.MatchingGraph +import com.example.matching.navigation.matchingNavGraph +import com.example.mypage.navigation.myPageScreen + +@Composable +fun HomeNavHost( + navController: NavHostController, + modifier: Modifier = Modifier, +) { + NavHost( + navController = navController, + startDestination = MatchingGraph, + modifier = modifier, + ) { + matchingNavGraph() + myPageScreen() + etcScreen() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yapp/chaeum/navigation/TopLevelDestinvation.kt b/app/src/main/java/com/yapp/chaeum/navigation/TopLevelDestinvation.kt index 9291b1eb..18d5fa81 100644 --- a/app/src/main/java/com/yapp/chaeum/navigation/TopLevelDestinvation.kt +++ b/app/src/main/java/com/yapp/chaeum/navigation/TopLevelDestinvation.kt @@ -5,7 +5,7 @@ import androidx.compose.material.icons.filled.Call import androidx.compose.material.icons.outlined.Call import androidx.compose.ui.graphics.vector.ImageVector import com.example.etc.navigation.EtcRoute -import com.example.matching.navigation.MatchingRoute +import com.example.matching.navigation.MatchingGraphDest import com.example.mypage.navigation.MyPageRoute import kotlin.reflect.KClass @@ -21,7 +21,7 @@ enum class TopLevelDestination( unselectedIcon = Icons.Outlined.Call, iconText = "매칭", titleText = "매칭", - route = MatchingRoute::class, + route = MatchingGraphDest.MatchingRoute::class, ), MYPAGE( selectedIcon = Icons.Filled.Call, diff --git a/app/src/main/java/com/yapp/chaeum/ui/App.kt b/app/src/main/java/com/yapp/chaeum/ui/App.kt index 468825d6..13bc2ee6 100644 --- a/app/src/main/java/com/yapp/chaeum/ui/App.kt +++ b/app/src/main/java/com/yapp/chaeum/ui/App.kt @@ -1,66 +1,11 @@ package com.yapp.chaeum.ui -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding -import androidx.compose.material.BottomNavigation -import androidx.compose.material.BottomNavigationItem -import androidx.compose.material.Icon -import androidx.compose.material.Text -import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.navigation.NavDestination -import androidx.navigation.NavDestination.Companion.hierarchy -import androidx.navigation.compose.currentBackStackEntryAsState import com.yapp.chaeum.navigation.AppNavHost -import com.yapp.chaeum.navigation.TopLevelDestination -import kotlin.reflect.KClass @Composable fun App(appState: AppState = rememberAppState()) { - val navBackStackEntry by appState.navController.currentBackStackEntryAsState() - val currentDestination = navBackStackEntry?.destination - - // 현재 화면이 TopLevelDestination 중 하나인지 확인 - val isTopLevel = TopLevelDestination.entries.any { - currentDestination?.route == it.route.qualifiedName - } - - Scaffold( - bottomBar = { - if (isTopLevel) { - BottomNavigation( - modifier = Modifier.navigationBarsPadding() - ) { - TopLevelDestination.entries.forEach { topLevelRoute -> - BottomNavigationItem( - icon = { - Icon( - topLevelRoute.selectedIcon, - contentDescription = topLevelRoute.name - ) - }, - label = { Text(topLevelRoute.name) }, - selected = currentDestination?.hierarchy?.any { destination -> - destination.route == topLevelRoute.route.qualifiedName - } == true, - onClick = { - appState.navigateToTopLevelDestination(topLevelRoute) - } - ) - } - } - } - } - ) { innerPadding -> - AppNavHost( - appState = appState, - modifier = Modifier.padding(innerPadding) - ) - } + AppNavHost( + appState = appState, + ) } - -private fun NavDestination.hasRoute(routeClass: KClass<*>): Boolean { - return this.route == routeClass.qualifiedName -} \ No newline at end of file diff --git a/app/src/main/java/com/yapp/chaeum/ui/AppState.kt b/app/src/main/java/com/yapp/chaeum/ui/AppState.kt index 72833005..3e78c151 100644 --- a/app/src/main/java/com/yapp/chaeum/ui/AppState.kt +++ b/app/src/main/java/com/yapp/chaeum/ui/AppState.kt @@ -5,66 +5,25 @@ import androidx.compose.runtime.remember import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController -import androidx.navigation.navOptions -import com.example.auth.navigation.AuthRoute -import com.example.auth.navigation.navigateToAuth -import com.example.etc.navigation.navigateToEtc -import com.example.matching.navigation.MatchingRoute -import com.example.matching.navigation.navigateToMatching -import com.example.mypage.navigation.navigateToMyPage -import com.yapp.chaeum.navigation.TopLevelDestination @Composable fun rememberAppState( navController: NavHostController = rememberNavController(), ): AppState { - return remember( - navController, - ) { - AppState( - navController = navController, - ) + return remember(navController) { + AppState(navController = navController) } } class AppState( val navController: NavHostController, ) { - fun navigateToTopLevelDestination(topLevelDestination: TopLevelDestination) { - val topLevelNavOptions = navOptions { + fun loginSuccess() { + navController.navigate(HomeGraph) { popUpTo(navController.graph.findStartDestination().id) { - saveState = true + inclusive = true } launchSingleTop = true - restoreState = true - } - - when (topLevelDestination) { - TopLevelDestination.MATCHING -> navController.navigateToMatching(topLevelNavOptions) - TopLevelDestination.MYPAGE -> navController.navigateToMyPage(topLevelNavOptions) - TopLevelDestination.ETC -> navController.navigateToEtc(topLevelNavOptions) - } - } - - fun navigateBack() { - navController.popBackStack() - } - - fun logout() { - navController.navigateToAuth( - navOptions { - popUpTo(navController.graph.findStartDestination().id) { - inclusive = true - } - launchSingleTop = true - } - ) - } - - fun loginSuccess() { - navController.navigate(MatchingRoute) { - popUpTo(AuthRoute) { inclusive = true } - launchSingleTop = true } } } \ No newline at end of file diff --git a/app/src/main/java/com/yapp/chaeum/ui/HomeRoute.kt b/app/src/main/java/com/yapp/chaeum/ui/HomeRoute.kt new file mode 100644 index 00000000..21023d3a --- /dev/null +++ b/app/src/main/java/com/yapp/chaeum/ui/HomeRoute.kt @@ -0,0 +1,65 @@ +package com.yapp.chaeum.ui + +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material.BottomNavigation +import androidx.compose.material.BottomNavigationItem +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.navigation.NavDestination.Companion.hierarchy +import androidx.navigation.compose.currentBackStackEntryAsState +import com.yapp.chaeum.navigation.HomeNavHost +import com.yapp.chaeum.navigation.TopLevelDestination +import kotlinx.serialization.Serializable + +@Serializable +data object HomeGraph + +@Composable +fun HomeRoute( + homeState: HomeState = rememberHomeState() +) { + Scaffold( + bottomBar = { + HomeBottomBar(homeState) + } + ) { innerPadding -> + HomeNavHost( + navController = homeState.navController, + modifier = Modifier.padding(innerPadding) + ) + } +} + +@Composable +private fun HomeBottomBar( + homeState: HomeState, +) { + val navBackStackEntry by homeState.navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + BottomNavigation( + modifier = Modifier.navigationBarsPadding() + ) { + TopLevelDestination.entries.forEach { topLevelRoute -> + BottomNavigationItem( + icon = { + Icon( + imageVector = topLevelRoute.selectedIcon, + contentDescription = topLevelRoute.name + ) + }, + label = { Text(topLevelRoute.name) }, + selected = currentDestination?.hierarchy?.any { destination -> + destination.route == topLevelRoute.route.qualifiedName + } == true, + onClick = { + homeState.navigateToTopLevelDestination(topLevelRoute) + } + ) + } + } +} diff --git a/app/src/main/java/com/yapp/chaeum/ui/HomeState.kt b/app/src/main/java/com/yapp/chaeum/ui/HomeState.kt new file mode 100644 index 00000000..62c41fca --- /dev/null +++ b/app/src/main/java/com/yapp/chaeum/ui/HomeState.kt @@ -0,0 +1,41 @@ +package com.yapp.chaeum.ui + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController +import androidx.navigation.compose.rememberNavController +import androidx.navigation.navOptions +import com.example.etc.navigation.navigateToEtc +import com.example.matching.navigation.navigateToMatching +import com.example.mypage.navigation.navigateToMyPage +import com.yapp.chaeum.navigation.TopLevelDestination + +@Composable +fun rememberHomeState( + navController: NavHostController = rememberNavController(), +): HomeState { + return remember(navController) { + HomeState(navController = navController) + } +} + +class HomeState( + val navController: NavHostController, +) { + fun navigateToTopLevelDestination(topLevelDestination: TopLevelDestination) { + val topLevelNavOptions = navOptions { + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + launchSingleTop = true + restoreState = true + } + + when (topLevelDestination) { + TopLevelDestination.MATCHING -> navController.navigateToMatching(topLevelNavOptions) + TopLevelDestination.MYPAGE -> navController.navigateToMyPage(topLevelNavOptions) + TopLevelDestination.ETC -> navController.navigateToEtc(topLevelNavOptions) + } + } +} \ No newline at end of file diff --git a/feature/auth/src/main/java/com/example/auth/navigation/AuthNavigation.kt b/feature/auth/src/main/java/com/example/auth/navigation/AuthNavigation.kt index 60d47f20..7d54471b 100644 --- a/feature/auth/src/main/java/com/example/auth/navigation/AuthNavigation.kt +++ b/feature/auth/src/main/java/com/example/auth/navigation/AuthNavigation.kt @@ -4,21 +4,29 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import androidx.navigation.navigation import com.example.auth.AuthRoute import kotlinx.serialization.Serializable @Serializable -object AuthRoute +data object AuthGraph + +sealed class AuthGraphDest { + @Serializable + data object AuthRoute : AuthGraphDest() +} fun NavController.navigateToAuth(navOptions: NavOptions) = - navigate(route = AuthRoute, navOptions) + navigate(route = AuthGraphDest.AuthRoute, navOptions) -fun NavGraphBuilder.authScreen( - onLoginSuccess: () -> Unit +fun NavGraphBuilder.authNavGraph( + onLoginSuccess: () -> Unit, ) { - composable { - AuthRoute( - onLoginSuccess = onLoginSuccess - ) + navigation(startDestination = AuthGraphDest.AuthRoute) { + composable { + AuthRoute( + onLoginSuccess = onLoginSuccess + ) + } } -} +} \ No newline at end of file diff --git a/feature/matching/src/main/java/com/example/matching/navigation/MatchingNavigation.kt b/feature/matching/src/main/java/com/example/matching/navigation/MatchingNavigation.kt index c9fe35b6..0c3f111c 100644 --- a/feature/matching/src/main/java/com/example/matching/navigation/MatchingNavigation.kt +++ b/feature/matching/src/main/java/com/example/matching/navigation/MatchingNavigation.kt @@ -4,17 +4,26 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import androidx.navigation.navigation import com.example.matching.MatchingRoute import kotlinx.serialization.Serializable + @Serializable -object MatchingRoute +data object MatchingGraph + +sealed class MatchingGraphDest { + @Serializable + data object MatchingRoute : MatchingGraphDest() +} fun NavController.navigateToMatching(navOptions: NavOptions) = - navigate(route = MatchingRoute, navOptions) + navigate(route = MatchingGraphDest.MatchingRoute, navOptions) -fun NavGraphBuilder.matchingScreen() { - composable { - MatchingRoute() +fun NavGraphBuilder.matchingNavGraph() { + navigation(startDestination = MatchingGraphDest.MatchingRoute) { + composable { + MatchingRoute() + } } -} +} \ No newline at end of file