diff --git a/core/navigation/build.gradle.kts b/core/navigation/build.gradle.kts index 37b3b81b..8a7c30c1 100644 --- a/core/navigation/build.gradle.kts +++ b/core/navigation/build.gradle.kts @@ -3,8 +3,13 @@ import com.droidknights.app.setNamespace plugins { id("droidknights.android.library") id("droidknights.android.compose") + alias(libs.plugins.kotlin.serialization) } android { setNamespace("core.navigation") } + +dependencies { + implementation(libs.kotlinx.serialization.json) +} diff --git a/core/navigation/src/main/java/com/droidknights/app/core/navigation/.gitkeep b/core/navigation/src/main/java/com/droidknights/app/core/navigation/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/core/navigation/src/main/java/com/droidknights/app/core/navigation/RouteModel.kt b/core/navigation/src/main/java/com/droidknights/app/core/navigation/RouteModel.kt new file mode 100644 index 00000000..73167506 --- /dev/null +++ b/core/navigation/src/main/java/com/droidknights/app/core/navigation/RouteModel.kt @@ -0,0 +1,25 @@ +package com.droidknights.app.core.navigation + +import kotlinx.serialization.Serializable + +sealed interface Route { + @Serializable + data object Contributor : Route + + @Serializable + data object Session : Route + + @Serializable + data class SessionDetail(val sessionId: String) : Route +} + +sealed interface MainTabRoute : Route { + @Serializable + data object Home : MainTabRoute + + @Serializable + data object Setting : MainTabRoute + + @Serializable + data object Bookmark : MainTabRoute +} diff --git a/feature/bookmark/src/main/java/com/droidknights/app/feature/bookmark/navigation/BookmarkNavigation.kt b/feature/bookmark/src/main/java/com/droidknights/app/feature/bookmark/navigation/BookmarkNavigation.kt index b902724b..415c46b4 100644 --- a/feature/bookmark/src/main/java/com/droidknights/app/feature/bookmark/navigation/BookmarkNavigation.kt +++ b/feature/bookmark/src/main/java/com/droidknights/app/feature/bookmark/navigation/BookmarkNavigation.kt @@ -4,21 +4,17 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import com.droidknights.app.core.navigation.MainTabRoute import com.droidknights.app.feature.bookmark.BookmarkRoute fun NavController.navigateBookmark(navOptions: NavOptions) { - navigate(BookmarkRoute.ROUTE, navOptions) + navigate(MainTabRoute.Bookmark, navOptions) } fun NavGraphBuilder.bookmarkNavGraph( onShowErrorSnackBar: (throwable: Throwable?) -> Unit, ) { - composable(route = BookmarkRoute.ROUTE) { + composable { BookmarkRoute(onShowErrorSnackBar) } } - -object BookmarkRoute { - - const val ROUTE = "bookmark" -} diff --git a/feature/contributor/src/main/java/com/droidknights/app/feature/contributor/navigation/ContributorNavigation.kt b/feature/contributor/src/main/java/com/droidknights/app/feature/contributor/navigation/ContributorNavigation.kt index 1aa02b9c..8726e0b0 100644 --- a/feature/contributor/src/main/java/com/droidknights/app/feature/contributor/navigation/ContributorNavigation.kt +++ b/feature/contributor/src/main/java/com/droidknights/app/feature/contributor/navigation/ContributorNavigation.kt @@ -3,25 +3,21 @@ package com.droidknights.app.feature.contributor.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable +import com.droidknights.app.core.navigation.Route import com.droidknights.app.feature.contributor.ContributorRoute fun NavController.navigateContributor() { - this.navigate(ContributorRoute.ROUTE) + this.navigate(Route.Contributor) } fun NavGraphBuilder.contributorNavGraph( onBackClick: () -> Unit, onShowErrorSnackBar: (throwable: Throwable?) -> Unit, ) { - composable(route = ContributorRoute.ROUTE) { + composable { ContributorRoute( onBackClick = onBackClick, onShowErrorSnackBar = onShowErrorSnackBar ) } } - -object ContributorRoute { - - const val ROUTE = "contributor" -} diff --git a/feature/home/src/main/java/com/droidknights/app/feature/home/navigation/HomeNavigation.kt b/feature/home/src/main/java/com/droidknights/app/feature/home/navigation/HomeNavigation.kt index cd166045..9e8b20a2 100644 --- a/feature/home/src/main/java/com/droidknights/app/feature/home/navigation/HomeNavigation.kt +++ b/feature/home/src/main/java/com/droidknights/app/feature/home/navigation/HomeNavigation.kt @@ -5,10 +5,11 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import com.droidknights.app.core.navigation.MainTabRoute import com.droidknights.app.feature.home.HomeRoute fun NavController.navigateHome(navOptions: NavOptions) { - navigate(HomeRoute.ROUTE, navOptions) + navigate(MainTabRoute.Home, navOptions) } fun NavGraphBuilder.homeNavGraph( @@ -17,12 +18,7 @@ fun NavGraphBuilder.homeNavGraph( onContributorClick: () -> Unit, onShowErrorSnackBar: (throwable: Throwable?) -> Unit, ) { - composable(route = HomeRoute.ROUTE) { + composable { HomeRoute(padding, onSessionClick, onContributorClick, onShowErrorSnackBar) } } - -object HomeRoute { - - const val ROUTE = "home" -} diff --git a/feature/main/src/main/java/com/droidknights/app/feature/main/MainNavigator.kt b/feature/main/src/main/java/com/droidknights/app/feature/main/MainNavigator.kt index cac3893f..e2724c8f 100644 --- a/feature/main/src/main/java/com/droidknights/app/feature/main/MainNavigator.kt +++ b/feature/main/src/main/java/com/droidknights/app/feature/main/MainNavigator.kt @@ -3,14 +3,16 @@ package com.droidknights.app.feature.main import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.navigation.NavDestination +import androidx.navigation.NavDestination.Companion.hasRoute import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navOptions +import com.droidknights.app.core.navigation.MainTabRoute +import com.droidknights.app.core.navigation.Route import com.droidknights.app.feature.bookmark.navigation.navigateBookmark import com.droidknights.app.feature.contributor.navigation.navigateContributor -import com.droidknights.app.feature.home.navigation.HomeRoute import com.droidknights.app.feature.home.navigation.navigateHome import com.droidknights.app.feature.session.navigation.navigateSession import com.droidknights.app.feature.session.navigation.navigateSessionDetail @@ -26,9 +28,9 @@ internal class MainNavigator( val startDestination = MainTab.HOME.route val currentTab: MainTab? - @Composable get() = currentDestination - ?.route - ?.let(MainTab::find) + @Composable get() = MainTab.find { tab -> + currentDestination?.hasRoute(tab::class) == true + } fun navigate(tab: MainTab) { val navOptions = navOptions { @@ -63,18 +65,18 @@ internal class MainNavigator( } fun popBackStackIfNotHome() { - if (!isSameCurrentDestination(HomeRoute.ROUTE)) { + if (!isSameCurrentDestination()) { popBackStack() } } - private fun isSameCurrentDestination(route: String) = - navController.currentDestination?.route == route + private inline fun isSameCurrentDestination(): Boolean { + return navController.currentDestination?.hasRoute() == true + } @Composable - fun shouldShowBottomBar(): Boolean { - val currentRoute = currentDestination?.route ?: return false - return currentRoute in MainTab + fun shouldShowBottomBar() = MainTab.contains { + currentDestination?.hasRoute(it::class) == true } } diff --git a/feature/main/src/main/java/com/droidknights/app/feature/main/MainTab.kt b/feature/main/src/main/java/com/droidknights/app/feature/main/MainTab.kt index 1933bded..268da308 100644 --- a/feature/main/src/main/java/com/droidknights/app/feature/main/MainTab.kt +++ b/feature/main/src/main/java/com/droidknights/app/feature/main/MainTab.kt @@ -1,38 +1,39 @@ package com.droidknights.app.feature.main -import com.droidknights.app.feature.bookmark.navigation.BookmarkRoute -import com.droidknights.app.feature.home.navigation.HomeRoute -import com.droidknights.app.feature.setting.navigation.SettingRoute +import androidx.compose.runtime.Composable +import com.droidknights.app.core.navigation.MainTabRoute +import com.droidknights.app.core.navigation.Route internal enum class MainTab( val iconResId: Int, internal val contentDescription: String, - val route: String, + val route: MainTabRoute, ) { SETTING( iconResId = R.drawable.ic_setting, contentDescription = "설정", - SettingRoute.ROUTE_SETTING, + MainTabRoute.Setting, ), HOME( iconResId = R.drawable.ic_home, contentDescription = "홈", - HomeRoute.ROUTE, + MainTabRoute.Home ), BOOKMARK( iconResId = R.drawable.ic_bookmark, contentDescription = "북마크", - BookmarkRoute.ROUTE, + MainTabRoute.Bookmark, ); companion object { - - operator fun contains(route: String): Boolean { - return entries.map { it.route }.contains(route) + @Composable + fun find(predicate: @Composable (MainTabRoute) -> Boolean): MainTab? { + return entries.find { predicate(it.route) } } - fun find(route: String): MainTab? { - return entries.find { it.route == route } + @Composable + fun contains(predicate: @Composable (Route) -> Boolean): Boolean { + return entries.map { it.route }.any { predicate(it) } } } } diff --git a/feature/session/src/main/java/com/droidknights/app/feature/session/navigation/SessionNavigation.kt b/feature/session/src/main/java/com/droidknights/app/feature/session/navigation/SessionNavigation.kt index 2ffcfa57..32089f8c 100644 --- a/feature/session/src/main/java/com/droidknights/app/feature/session/navigation/SessionNavigation.kt +++ b/feature/session/src/main/java/com/droidknights/app/feature/session/navigation/SessionNavigation.kt @@ -2,19 +2,20 @@ package com.droidknights.app.feature.session.navigation import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder -import androidx.navigation.NavType import androidx.navigation.compose.composable -import androidx.navigation.navArgument +import androidx.navigation.toRoute import com.droidknights.app.core.model.Session +import com.droidknights.app.core.navigation.Route import com.droidknights.app.feature.session.SessionDetailScreen import com.droidknights.app.feature.session.SessionScreen +import com.droidknights.app.core.navigation.Route.Session as SessionRoute fun NavController.navigateSession() { - navigate(SessionRoute.ROUTE) + navigate(SessionRoute) } fun NavController.navigateSessionDetail(sessionId: String) { - navigate(SessionRoute.detailRoute(sessionId)) + navigate(Route.SessionDetail(sessionId)) } fun NavGraphBuilder.sessionNavGraph( @@ -22,7 +23,7 @@ fun NavGraphBuilder.sessionNavGraph( onSessionClick: (Session) -> Unit, onShowErrorSnackBar: (throwable: Throwable?) -> Unit, ) { - composable(SessionRoute.ROUTE) { + composable { SessionScreen( onBackClick = onBackClick, onSessionClick = onSessionClick, @@ -30,25 +31,11 @@ fun NavGraphBuilder.sessionNavGraph( ) } - composable( - route = SessionRoute.detailRoute("{id}"), - arguments = listOf( - navArgument("id") { - type = NavType.StringType - } - ) - ) { navBackStackEntry -> - val sessionId = navBackStackEntry.arguments?.getString("id") ?: "" + composable { navBackStackEntry -> + val sessionId = navBackStackEntry.toRoute().sessionId SessionDetailScreen( sessionId = sessionId, onBackClick = onBackClick ) } } - -object SessionRoute { - - const val ROUTE: String = "session" - - fun detailRoute(sessionId: String): String = "$ROUTE/$sessionId" -} diff --git a/feature/setting/src/main/java/com/droidknights/app/feature/setting/navigation/SettingNavigation.kt b/feature/setting/src/main/java/com/droidknights/app/feature/setting/navigation/SettingNavigation.kt index 36d93e40..7ddfe8c3 100644 --- a/feature/setting/src/main/java/com/droidknights/app/feature/setting/navigation/SettingNavigation.kt +++ b/feature/setting/src/main/java/com/droidknights/app/feature/setting/navigation/SettingNavigation.kt @@ -5,22 +5,18 @@ import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable +import com.droidknights.app.core.navigation.MainTabRoute import com.droidknights.app.feature.setting.SettingScreen fun NavController.navigateSetting(navOptions: NavOptions) { - navigate(SettingRoute.ROUTE_SETTING, navOptions) + navigate(MainTabRoute.Setting, navOptions) } fun NavGraphBuilder.settingNavGraph( padding: PaddingValues, onChangeDarkTheme: (Boolean) -> Unit ) { - composable(route = SettingRoute.ROUTE_SETTING) { + composable { SettingScreen(padding, onChangeDarkTheme) } } - -object SettingRoute { - - const val ROUTE_SETTING = "setting" -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a088f248..a616d696 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -26,7 +26,7 @@ androidxComposeBom = "2024.05.00" # https://developer.android.com/jetpack/androidx/releases/compose-kotlin androidxComposeCompiler = "1.5.14" # https://developer.android.com/jetpack/androidx/releases/navigation -androidxComposeNavigation = "2.7.7" +androidxComposeNavigation = "2.8.0-beta02" # https://developer.android.com/jetpack/androidx/releases/compose-material3 androidxComposeMaterial3 = "1.2.1"