From 2f93879c1df417c594ed730605c8182a699d99da Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Thu, 21 Aug 2025 15:59:31 +0800 Subject: [PATCH] compose: navigation: Migrate from navigation2 to navigation3 Signed-off-by: Aayush Gupta --- app/build.gradle.kts | 4 +- .../java/com/aurora/store/ComposeActivity.kt | 6 +- .../store/compose/navigation/NavDisplay.kt | 72 +++++++++++++++++++ .../store/compose/navigation/NavGraph.kt | 67 ----------------- .../aurora/store/compose/navigation/Screen.kt | 3 +- gradle/libs.versions.toml | 6 +- 6 files changed, 84 insertions(+), 74 deletions(-) create mode 100644 app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt delete mode 100644 app/src/main/java/com/aurora/store/compose/navigation/NavGraph.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 07c8db1e1..98a5c1f71 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -184,6 +184,7 @@ dependencies { implementation(libs.androidx.browser) implementation(libs.androidx.lifecycle.viewmodel.ktx) implementation(libs.androidx.lifecycle.process) + implementation(libs.androidx.lifecycle.navigation3) implementation(libs.androidx.preference.ktx) implementation(libs.androidx.swiperefreshlayout) implementation(libs.androidx.viewpager2) @@ -194,7 +195,8 @@ dependencies { implementation(libs.androidx.adaptive.navigation) implementation(libs.androidx.adaptive.layout) implementation(libs.androidx.paging.compose) - implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.navigation3.runtime) + implementation(libs.androidx.navigation3.ui) implementation(libs.kotlinx.serialization.json) implementation(libs.androidx.navigation.fragment.ktx) implementation(libs.androidx.navigation.ui.ktx) diff --git a/app/src/main/java/com/aurora/store/ComposeActivity.kt b/app/src/main/java/com/aurora/store/ComposeActivity.kt index 9fa92370e..c5db1d773 100644 --- a/app/src/main/java/com/aurora/store/ComposeActivity.kt +++ b/app/src/main/java/com/aurora/store/ComposeActivity.kt @@ -11,10 +11,9 @@ import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.runtime.CompositionLocalProvider import androidx.core.content.IntentCompat -import androidx.navigation.compose.rememberNavController import com.aurora.store.compose.compositions.UI import com.aurora.store.compose.compositions.LocalUI -import com.aurora.store.compose.navigation.NavGraph +import com.aurora.store.compose.navigation.NavDisplay import com.aurora.store.compose.navigation.Screen import com.aurora.store.compose.theme.AuroraTheme import com.aurora.store.util.PackageUtil @@ -42,8 +41,7 @@ class ComposeActivity : ComponentActivity() { setContent { CompositionLocalProvider(LocalUI provides localUI) { AuroraTheme { - val navController = rememberNavController() - NavGraph(navHostController = navController, startDestination = startDestination) + NavDisplay(startDestination = startDestination) } } } diff --git a/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt b/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt new file mode 100644 index 000000000..cbc99a5b4 --- /dev/null +++ b/app/src/main/java/com/aurora/store/compose/navigation/NavDisplay.kt @@ -0,0 +1,72 @@ +/* + * SPDX-FileCopyrightText: 2025 The Calyx Institute + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.aurora.store.compose.navigation + +import androidx.activity.compose.LocalActivity +import androidx.compose.runtime.Composable +import androidx.lifecycle.viewmodel.navigation3.rememberViewModelStoreNavEntryDecorator +import androidx.navigation3.runtime.NavKey +import androidx.navigation3.runtime.entry +import androidx.navigation3.runtime.entryProvider +import androidx.navigation3.runtime.rememberNavBackStack +import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator +import androidx.navigation3.ui.NavDisplay +import com.aurora.store.compose.ui.commons.BlacklistScreen +import com.aurora.store.compose.ui.details.AppDetailsScreen +import com.aurora.store.compose.ui.dev.DevProfileScreen +import com.aurora.store.compose.ui.search.SearchScreen + +/** + * Navigation display for compose screens + * @param startDestination Starting destination for the activity/app + */ +@Composable +fun NavDisplay(startDestination: NavKey) { + val backstack = rememberNavBackStack(startDestination) + + // TODO: Drop this logic once everything is in compose + val activity = LocalActivity.current + fun onNavigateUp() { + if (backstack.size == 1) activity?.finish() else backstack.removeLastOrNull() + } + + NavDisplay( + backStack = backstack, + entryDecorators = listOf( + rememberSavedStateNavEntryDecorator(), + rememberViewModelStoreNavEntryDecorator() + ), + entryProvider = entryProvider { + entry { + BlacklistScreen(onNavigateUp = { onNavigateUp() }) + } + + entry { + SearchScreen(onNavigateUp = { onNavigateUp() }) + } + + entry { screen -> + AppDetailsScreen( + packageName = screen.packageName, + onNavigateUp = { onNavigateUp() }, + onNavigateToAppDetails = { packageName -> + backstack.add(Screen.AppDetails(packageName)) + } + ) + } + + entry { screen -> + DevProfileScreen( + developerId = screen.developerId, + onNavigateUp = { onNavigateUp() }, + onNavigateToAppDetails = { packageName -> + backstack.add(Screen.AppDetails(packageName)) + } + ) + } + } + ) +} diff --git a/app/src/main/java/com/aurora/store/compose/navigation/NavGraph.kt b/app/src/main/java/com/aurora/store/compose/navigation/NavGraph.kt deleted file mode 100644 index e4bd39b27..000000000 --- a/app/src/main/java/com/aurora/store/compose/navigation/NavGraph.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 The Calyx Institute - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -package com.aurora.store.compose.navigation - -import androidx.activity.compose.LocalActivity -import androidx.compose.runtime.Composable -import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.toRoute -import com.aurora.store.compose.ui.commons.BlacklistScreen -import com.aurora.store.compose.ui.details.AppDetailsScreen -import com.aurora.store.compose.ui.dev.DevProfileScreen -import com.aurora.store.compose.ui.search.SearchScreen - -/** - * Navigation graph for compose screens - * @param navHostController [NavHostController] to navigate with compose - * @param startDestination Starting destination for the activity/app - */ -@Composable -fun NavGraph(navHostController: NavHostController, startDestination: Screen) { - // TODO: Drop this logic once everything is in compose - val activity = LocalActivity.current - fun onNavigateUp() { - if (navHostController.previousBackStackEntry != null) { - navHostController.navigateUp() - } else { - activity?.finish() - } - } - - NavHost(navController = navHostController, startDestination = startDestination) { - composable { - BlacklistScreen(onNavigateUp = { onNavigateUp() }) - } - - composable { - SearchScreen(onNavigateUp = { onNavigateUp() }) - } - - composable { backstackEntry -> - val appDetails = backstackEntry.toRoute() - AppDetailsScreen( - packageName = appDetails.packageName, - onNavigateUp = { onNavigateUp() }, - onNavigateToAppDetails = { packageName -> - navHostController.navigate(Screen.AppDetails(packageName)) - } - ) - } - - composable { backstackEntry -> - val devProfile = backstackEntry.toRoute() - DevProfileScreen( - developerId = devProfile.developerId, - onNavigateUp = { onNavigateUp() }, - onNavigateToAppDetails = { packageName -> - navHostController.navigate(Screen.AppDetails(packageName)) - } - ) - } - } -} diff --git a/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt b/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt index a36e6ada4..c0a543efa 100644 --- a/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt +++ b/app/src/main/java/com/aurora/store/compose/navigation/Screen.kt @@ -8,6 +8,7 @@ package com.aurora.store.compose.navigation import android.os.Parcelable import androidx.annotation.DrawableRes import androidx.annotation.StringRes +import androidx.navigation3.runtime.NavKey import com.aurora.store.R import kotlinx.parcelize.Parcelize import kotlinx.serialization.Serializable @@ -22,7 +23,7 @@ import kotlinx.serialization.Serializable sealed class Screen( @StringRes val label: Int? = null, @DrawableRes val icon: Int? = null -) : Parcelable { +) : NavKey, Parcelable { companion object { const val PARCEL_KEY = "SCREEN" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 648e328e9..b3210ce30 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,8 +29,10 @@ ktlint = "12.1.2" leakcanary = "2.14" libsu = "6.0.0" lifecycle = "2.9.2" +lifecycle-navigation3 = "1.0.0-alpha04" material = "1.12.0" navigation = "2.9.3" +navigation3 = "1.0.0-alpha07" okhttp = "5.1.0" paging = "3.3.6" preference = "1.2.1" @@ -63,10 +65,12 @@ androidx-hilt-navigation = { module = "androidx.hilt:hilt-navigation-compose", v androidx-junit = { module = "androidx.test.ext:junit-ktx", version.ref = "androidx-junit" } androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle" } androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } +androidx-lifecycle-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "lifecycle-navigation3" } androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "composeMaterial" } -androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigation" } androidx-navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-ktx", version.ref = "navigation" } androidx-navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "navigation" } +androidx-navigation3-runtime = { module = "androidx.navigation3:navigation3-runtime", version.ref = "navigation3" } +androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", version.ref = "navigation3" } androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging" } androidx-paging-runtime = { module = "androidx.paging:paging-runtime", version.ref = "paging" } androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preference" }