diff --git a/JetNews/app/build.gradle.kts b/JetNews/app/build.gradle.kts
index 6fee8c50b0..335ae5dfb6 100644
--- a/JetNews/app/build.gradle.kts
+++ b/JetNews/app/build.gradle.kts
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.compose)
+ alias(libs.plugins.kotlin.serialization)
}
android {
@@ -92,6 +93,7 @@ dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.kotlinx.coroutines.android)
+ implementation(libs.kotlinx.serialization.core)
implementation(libs.androidx.compose.animation)
implementation(libs.androidx.compose.foundation.layout)
@@ -116,7 +118,9 @@ dependencies {
implementation(libs.androidx.lifecycle.livedata.ktx)
implementation(libs.androidx.lifecycle.viewModelCompose)
implementation(libs.androidx.lifecycle.runtime.compose)
+ implementation(libs.androidx.lifecycle.viewmodel.navigation3)
implementation(libs.androidx.navigation.compose)
+ implementation(libs.androidx.navigation3.ui)
implementation(libs.androidx.window)
androidTestImplementation(libs.junit)
diff --git a/JetNews/app/src/main/AndroidManifest.xml b/JetNews/app/src/main/AndroidManifest.xml
index 134af83d20..ddbddb1676 100644
--- a/JetNews/app/src/main/AndroidManifest.xml
+++ b/JetNews/app/src/main/AndroidManifest.xml
@@ -40,6 +40,14 @@
android:pathPrefix="/jetnews"
android:scheme="https" />
+
+
+
+
+
+
Unit,
navigateToInterests: () -> Unit,
closeDrawer: () -> Unit,
@@ -58,7 +61,7 @@ fun AppDrawer(
NavigationDrawerItem(
label = { Text(stringResource(id = R.string.home_title)) },
icon = { Icon(painterResource(R.drawable.ic_home), null) },
- selected = currentRoute == JetnewsDestinations.HOME_ROUTE,
+ selected = currentKey is HomeKey,
onClick = {
navigateToHome()
closeDrawer()
@@ -68,7 +71,7 @@ fun AppDrawer(
NavigationDrawerItem(
label = { Text(stringResource(id = R.string.interests_title)) },
icon = { Icon(painterResource(R.drawable.ic_list_alt), null) },
- selected = currentRoute == JetnewsDestinations.INTERESTS_ROUTE,
+ selected = currentKey == InterestsKey,
onClick = {
navigateToInterests()
closeDrawer()
@@ -102,7 +105,7 @@ fun PreviewAppDrawer() {
JetnewsTheme {
AppDrawer(
drawerState = rememberDrawerState(initialValue = DrawerValue.Open),
- currentRoute = JetnewsDestinations.HOME_ROUTE,
+ currentKey = HomeKey(),
navigateToHome = {},
navigateToInterests = {},
closeDrawer = { },
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt
index e0acc812e1..59d57e52e1 100644
--- a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt
+++ b/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsApp.kt
@@ -23,40 +23,37 @@ import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.rememberDrawerState
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
-import androidx.navigation.compose.currentBackStackEntryAsState
-import androidx.navigation.compose.rememberNavController
+import androidx.navigation3.runtime.NavKey
import com.example.jetnews.data.AppContainer
import com.example.jetnews.ui.components.AppNavRail
+import com.example.jetnews.ui.navigation.HomeKey
+import com.example.jetnews.ui.navigation.JetnewsNavDisplay
+import com.example.jetnews.ui.navigation.NavigationState
+import com.example.jetnews.ui.navigation.Navigator
+import com.example.jetnews.ui.navigation.rememberNavigationState
import com.example.jetnews.ui.theme.JetnewsTheme
import kotlinx.coroutines.launch
@Composable
-fun JetnewsApp(appContainer: AppContainer, widthSizeClass: WindowWidthSizeClass) {
+fun JetnewsApp(appContainer: AppContainer, widthSizeClass: WindowWidthSizeClass, deeplinkKey: HomeKey?) {
JetnewsTheme {
- val navController = rememberNavController()
- val navigationActions = remember(navController) {
- JetnewsNavigationActions(navController)
- }
-
val coroutineScope = rememberCoroutineScope()
- val navBackStackEntry by navController.currentBackStackEntryAsState()
- val currentRoute =
- navBackStackEntry?.destination?.route ?: JetnewsDestinations.HOME_ROUTE
-
val isExpandedScreen = widthSizeClass == WindowWidthSizeClass.Expanded
val sizeAwareDrawerState = rememberSizeAwareDrawerState(isExpandedScreen)
+ val navigationState = rememberNavigationState(deeplinkKey ?: HomeKey())
+ val navigator = Navigator(navigationState)
+
ModalNavigationDrawer(
drawerContent = {
AppDrawer(
drawerState = sizeAwareDrawerState,
- currentRoute = currentRoute,
- navigateToHome = navigationActions.navigateToHome,
- navigateToInterests = navigationActions.navigateToInterests,
+ currentKey = navigationState.currentKey,
+ navigateToHome = navigator::toHome,
+ navigateToInterests = navigator::toInterests,
closeDrawer = { coroutineScope.launch { sizeAwareDrawerState.close() } },
)
},
@@ -67,15 +64,16 @@ fun JetnewsApp(appContainer: AppContainer, widthSizeClass: WindowWidthSizeClass)
Row {
if (isExpandedScreen) {
AppNavRail(
- currentRoute = currentRoute,
- navigateToHome = navigationActions.navigateToHome,
- navigateToInterests = navigationActions.navigateToInterests,
+ currentKey = navigationState.currentKey,
+ navigateToHome = navigator::toHome,
+ navigateToInterests = navigator::toInterests,
)
}
- JetnewsNavGraph(
+ JetnewsNavDisplay(
+ navigationState = navigationState,
appContainer = appContainer,
+ onBack = navigator::pop,
isExpandedScreen = isExpandedScreen,
- navController = navController,
openDrawer = { coroutineScope.launch { sizeAwareDrawerState.open() } },
)
}
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsNavGraph.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsNavGraph.kt
deleted file mode 100644
index 8e8202e592..0000000000
--- a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsNavGraph.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.jetnews.ui
-
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.lifecycle.viewmodel.compose.viewModel
-import androidx.navigation.NavHostController
-import androidx.navigation.compose.NavHost
-import androidx.navigation.compose.composable
-import androidx.navigation.compose.rememberNavController
-import androidx.navigation.navDeepLink
-import com.example.jetnews.JetnewsApplication.Companion.JETNEWS_APP_URI
-import com.example.jetnews.data.AppContainer
-import com.example.jetnews.ui.home.HomeRoute
-import com.example.jetnews.ui.home.HomeViewModel
-import com.example.jetnews.ui.interests.InterestsRoute
-import com.example.jetnews.ui.interests.InterestsViewModel
-
-const val POST_ID = "postId"
-
-@Composable
-fun JetnewsNavGraph(
- appContainer: AppContainer,
- isExpandedScreen: Boolean,
- modifier: Modifier = Modifier,
- navController: NavHostController = rememberNavController(),
- openDrawer: () -> Unit = {},
- startDestination: String = JetnewsDestinations.HOME_ROUTE,
-) {
- NavHost(
- navController = navController,
- startDestination = startDestination,
- modifier = modifier,
- ) {
- composable(
- route = JetnewsDestinations.HOME_ROUTE,
- deepLinks = listOf(
- navDeepLink {
- uriPattern =
- "$JETNEWS_APP_URI/${JetnewsDestinations.HOME_ROUTE}?$POST_ID={$POST_ID}"
- },
- ),
- ) { navBackStackEntry ->
- val homeViewModel: HomeViewModel = viewModel(
- factory = HomeViewModel.provideFactory(
- postsRepository = appContainer.postsRepository,
- preSelectedPostId = navBackStackEntry.arguments?.getString(POST_ID),
- ),
- )
- HomeRoute(
- homeViewModel = homeViewModel,
- isExpandedScreen = isExpandedScreen,
- openDrawer = openDrawer,
- )
- }
- composable(JetnewsDestinations.INTERESTS_ROUTE) {
- val interestsViewModel: InterestsViewModel = viewModel(
- factory = InterestsViewModel.provideFactory(appContainer.interestsRepository),
- )
- InterestsRoute(
- interestsViewModel = interestsViewModel,
- isExpandedScreen = isExpandedScreen,
- openDrawer = openDrawer,
- )
- }
- }
-}
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsNavigation.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsNavigation.kt
deleted file mode 100644
index 8dd1ee01d6..0000000000
--- a/JetNews/app/src/main/java/com/example/jetnews/ui/JetnewsNavigation.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.jetnews.ui
-
-import androidx.navigation.NavGraph.Companion.findStartDestination
-import androidx.navigation.NavHostController
-
-/**
- * Destinations used in the [JetnewsApp].
- */
-object JetnewsDestinations {
- const val HOME_ROUTE = "home"
- const val INTERESTS_ROUTE = "interests"
-}
-
-/**
- * Models the navigation actions in the app.
- */
-class JetnewsNavigationActions(navController: NavHostController) {
- val navigateToHome: () -> Unit = {
- navController.navigate(JetnewsDestinations.HOME_ROUTE) {
- // Pop up to the start destination of the graph to
- // avoid building up a large stack of destinations
- // on the back stack as users select items
- popUpTo(navController.graph.findStartDestination().id) {
- saveState = true
- }
- // Avoid multiple copies of the same destination when
- // reselecting the same item
- launchSingleTop = true
- // Restore state when reselecting a previously selected item
- restoreState = true
- }
- }
- val navigateToInterests: () -> Unit = {
- navController.navigate(JetnewsDestinations.INTERESTS_ROUTE) {
- popUpTo(navController.graph.findStartDestination().id) {
- saveState = true
- }
- launchSingleTop = true
- restoreState = true
- }
- }
-}
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt
index bd6d2ac0bd..635364cd66 100644
--- a/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt
+++ b/JetNews/app/src/main/java/com/example/jetnews/ui/MainActivity.kt
@@ -16,13 +16,18 @@
package com.example.jetnews.ui
+import android.content.Intent
+import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
+import androidx.navigation3.runtime.NavKey
import com.example.jetnews.JetnewsApplication
+import com.example.jetnews.ui.navigation.HomeKey
+import com.example.jetnews.ui.navigation.POST_ID
class MainActivity : ComponentActivity() {
@@ -34,7 +39,18 @@ class MainActivity : ComponentActivity() {
val appContainer = (application as JetnewsApplication).container
setContent {
val widthSizeClass = calculateWindowSizeClass(this).widthSizeClass
- JetnewsApp(appContainer, widthSizeClass)
+ JetnewsApp(appContainer, widthSizeClass, getDeepLinkKey(intent))
}
}
}
+
+private fun getDeepLinkKey(intent: Intent): HomeKey? {
+ val uri: Uri = intent.data ?: return null
+ val pathParams = uri.pathSegments
+ if (pathParams.lastOrNull() != "home") return null
+
+ val queryParams = uri.getQueryParameters(POST_ID)
+ if (queryParams.isEmpty() || queryParams.size > 1) return null
+ // "https://developer.android.com/jetnews/home?postId={$POST_ID}"
+ return HomeKey(postId = Uri.decode(queryParams.firstOrNull()))
+}
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/components/AppNavRail.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/components/AppNavRail.kt
index b6d48e74f2..e400039d69 100644
--- a/JetNews/app/src/main/java/com/example/jetnews/ui/components/AppNavRail.kt
+++ b/JetNews/app/src/main/java/com/example/jetnews/ui/components/AppNavRail.kt
@@ -30,12 +30,14 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.navigation3.runtime.NavKey
import com.example.jetnews.R
-import com.example.jetnews.ui.JetnewsDestinations
+import com.example.jetnews.ui.navigation.HomeKey
+import com.example.jetnews.ui.navigation.InterestsKey
import com.example.jetnews.ui.theme.JetnewsTheme
@Composable
-fun AppNavRail(currentRoute: String, navigateToHome: () -> Unit, navigateToInterests: () -> Unit, modifier: Modifier = Modifier) {
+fun AppNavRail(currentKey: NavKey, navigateToHome: () -> Unit, navigateToInterests: () -> Unit, modifier: Modifier = Modifier) {
NavigationRail(
header = {
Icon(
@@ -49,14 +51,14 @@ fun AppNavRail(currentRoute: String, navigateToHome: () -> Unit, navigateToInter
) {
Spacer(Modifier.weight(1f))
NavigationRailItem(
- selected = currentRoute == JetnewsDestinations.HOME_ROUTE,
+ selected = currentKey is HomeKey,
onClick = navigateToHome,
icon = { Icon(painterResource(id = R.drawable.ic_home), stringResource(R.string.home_title)) },
label = { Text(stringResource(R.string.home_title)) },
alwaysShowLabel = false,
)
NavigationRailItem(
- selected = currentRoute == JetnewsDestinations.INTERESTS_ROUTE,
+ selected = currentKey == InterestsKey,
onClick = navigateToInterests,
icon = { Icon(painterResource(id = R.drawable.ic_list_alt), stringResource(R.string.interests_title)) },
label = { Text(stringResource(R.string.interests_title)) },
@@ -72,7 +74,7 @@ fun AppNavRail(currentRoute: String, navigateToHome: () -> Unit, navigateToInter
fun PreviewAppNavRail() {
JetnewsTheme {
AppNavRail(
- currentRoute = JetnewsDestinations.HOME_ROUTE,
+ currentKey = HomeKey(),
navigateToHome = {},
navigateToInterests = {},
)
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/navigation/JetnewsNavDisplay.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/navigation/JetnewsNavDisplay.kt
new file mode 100644
index 0000000000..61b1cf1d05
--- /dev/null
+++ b/JetNews/app/src/main/java/com/example/jetnews/ui/navigation/JetnewsNavDisplay.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.jetnews.ui.navigation
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.lifecycle.viewmodel.compose.viewModel
+import androidx.navigation3.runtime.EntryProviderScope
+import androidx.navigation3.runtime.NavKey
+import androidx.navigation3.runtime.entryProvider
+import androidx.navigation3.ui.NavDisplay
+import com.example.jetnews.data.AppContainer
+import com.example.jetnews.data.interests.InterestsRepository
+import com.example.jetnews.data.posts.PostsRepository
+import com.example.jetnews.ui.home.HomeRoute
+import com.example.jetnews.ui.home.HomeViewModel
+import com.example.jetnews.ui.interests.InterestsRoute
+import com.example.jetnews.ui.interests.InterestsViewModel
+
+const val POST_ID = "postId"
+
+@Composable
+fun JetnewsNavDisplay(
+ navigationState: NavigationState,
+ appContainer: AppContainer,
+ onBack: () -> Unit,
+ isExpandedScreen: Boolean,
+ modifier: Modifier = Modifier,
+ openDrawer: () -> Unit = {},
+) {
+
+ val decoratedEntries = navigationState.getEntries(
+ entryProvider = entryProvider {
+ homeEntry(
+ appContainer.postsRepository,
+ isExpandedScreen,
+ openDrawer,
+ )
+ interestsEntry(
+ appContainer.interestsRepository,
+ isExpandedScreen,
+ openDrawer,
+ )
+ },
+ )
+
+ NavDisplay(
+ entries = decoratedEntries,
+ modifier = modifier,
+ onBack = onBack,
+ )
+}
+
+private fun EntryProviderScope.homeEntry(postsRepository: PostsRepository, isExpandedScreen: Boolean, openDrawer: () -> Unit) {
+ entry {
+ val homeViewModel: HomeViewModel = viewModel(
+ factory = HomeViewModel.provideFactory(
+ postsRepository = postsRepository,
+ preSelectedPostId = it.postId,
+ ),
+ )
+ HomeRoute(
+ homeViewModel = homeViewModel,
+ isExpandedScreen = isExpandedScreen,
+ openDrawer = openDrawer,
+ )
+ }
+}
+
+private fun EntryProviderScope.interestsEntry(
+ interestsRepository: InterestsRepository,
+ isExpandedScreen: Boolean,
+ openDrawer: () -> Unit,
+) {
+ entry {
+ val interestsViewModel: InterestsViewModel = viewModel(
+ factory = InterestsViewModel.provideFactory(interestsRepository),
+ )
+ InterestsRoute(
+ interestsViewModel = interestsViewModel,
+ isExpandedScreen = isExpandedScreen,
+ openDrawer = openDrawer,
+ )
+ }
+}
diff --git a/JetNews/app/src/main/java/com/example/jetnews/ui/navigation/JetnewsNavigation.kt b/JetNews/app/src/main/java/com/example/jetnews/ui/navigation/JetnewsNavigation.kt
new file mode 100644
index 0000000000..8d3f8f1f22
--- /dev/null
+++ b/JetNews/app/src/main/java/com/example/jetnews/ui/navigation/JetnewsNavigation.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.example.jetnews.ui.navigation
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.snapshots.SnapshotStateList
+import androidx.compose.runtime.toMutableStateList
+import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator
+import androidx.navigation3.runtime.NavBackStack
+import androidx.navigation3.runtime.NavEntry
+import androidx.navigation3.runtime.NavKey
+import androidx.navigation3.runtime.rememberDecoratedNavEntries
+import androidx.navigation3.runtime.rememberNavBackStack
+import androidx.navigation3.runtime.rememberSaveableStateHolderNavEntryDecorator
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class HomeKey(val postId: String? = null) : NavKey
+
+@Serializable
+object InterestsKey : NavKey
+
+fun getNavigationKeys(startKey: HomeKey) = listOf(startKey, InterestsKey)
+
+@Composable
+fun rememberNavigationState(startKey: HomeKey): NavigationState {
+ val currentKeys = rememberNavBackStack(startKey)
+ val backStacks = buildMap {
+ getNavigationKeys(startKey)
+ .forEach {
+ put(it::class.toString(), rememberNavBackStack(it))
+ }
+ }.toMutableMap()
+ return remember(startKey) { NavigationState(currentKeys, backStacks) }
+}
+
+/**
+ * Contains the navigation state
+ */
+class NavigationState(val currentKeys: NavBackStack, val backStacks: MutableMap>) {
+
+ val currentKey
+ get() = currentKeys.last()
+ val currentBackStack
+ get() = backStacks[currentKey::class.toString()]
+
+ @Composable
+ fun getEntries(entryProvider: (NavKey) -> NavEntry): SnapshotStateList> {
+ val decoratedEntries = backStacks.mapValues { (_, stack) ->
+ val decorators = listOf(
+ rememberSaveableStateHolderNavEntryDecorator(),
+ rememberViewModelStoreNavEntryDecorator(),
+ )
+ rememberDecoratedNavEntries(
+ backStack = stack,
+ entryDecorators = decorators,
+ entryProvider = entryProvider,
+ )
+ }
+
+ return currentKeys
+ .flatMap { decoratedEntries[it::class.toString()]!! }
+ .toMutableStateList()
+ }
+}
+
+/**
+ * Models the navigation actions in the app.
+ */
+class Navigator(val state: NavigationState) {
+ fun toHome(postId: String? = null) {
+ val newKey = HomeKey(postId)
+ if (state.currentKey == newKey) return
+
+ state.currentKeys.clear()
+ state.currentKeys.add(newKey)
+ state.backStacks[newKey::class.toString()]?.apply {
+ clear()
+ add(newKey)
+ }
+ }
+
+ fun toInterests() {
+ if (state.currentKey == InterestsKey) return
+ state.currentKeys.add(InterestsKey)
+ }
+
+ fun pop() {
+ state.currentKeys.removeLastOrNull()
+ }
+}
diff --git a/JetNews/gradle/libs.versions.toml b/JetNews/gradle/libs.versions.toml
index b9be095d92..c1b8ca2a6e 100644
--- a/JetNews/gradle/libs.versions.toml
+++ b/JetNews/gradle/libs.versions.toml
@@ -17,6 +17,7 @@ androidx-lifecycle = "2.8.2"
androidx-lifecycle-compose = "2.10.0"
androidx-lifecycle-runtime-compose = "2.10.0"
androidx-navigation = "2.9.7"
+androidx-navigation3 = "1.1.0-alpha03"
androidx-palette = "1.0.0"
androidx-test = "1.7.0"
androidx-test-espresso = "3.7.0"
@@ -40,7 +41,7 @@ horologist = "0.7.15"
jdkDesugar = "2.1.5"
junit = "4.13.2"
kotlin = "2.3.0"
-kotlinx-serialization-json = "1.10.0"
+kotlinx-serialization = "1.10.0"
kotlinx_immutable = "0.4.0"
ksp = "2.3.5"
maps-compose = "8.0.0"
@@ -102,10 +103,12 @@ androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-ru
androidx-lifecycle-viewModelCompose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle-compose" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle-compose" }
androidx-lifecycle-viewmodel-savedstate = { module = "androidx.lifecycle:lifecycle-viewmodel-savedstate", version.ref = "androidx-lifecycle-compose" }
+androidx-lifecycle-viewmodel-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "androidx-lifecycle-compose" }
androidx-material-icons-core = { module = "androidx.compose.material:material-icons-core" }
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "androidx-navigation" }
androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "androidx-navigation" }
+androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "androidx-navigation3" }
androidx-palette = { module = "androidx.palette:palette", version.ref = "androidx-palette" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
androidx-room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
@@ -148,7 +151,8 @@ kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.re
kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version.ref = "kotlinx_immutable" }
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" }
-kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }
+kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
okhttp-logging = { module = "com.squareup.okhttp3:logging-interceptor", version.ref = "okhttp" }
okhttp3 = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" }
play-services-wearable = { module = "com.google.android.gms:play-services-wearable", version.ref = "play-services-wearable" }