compose: navigation: Migrate from navigation2 to navigation3

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2025-08-21 15:59:31 +08:00
parent 7f41ad0923
commit 2f93879c1d
6 changed files with 84 additions and 74 deletions

View File

@@ -184,6 +184,7 @@ dependencies {
implementation(libs.androidx.browser) implementation(libs.androidx.browser)
implementation(libs.androidx.lifecycle.viewmodel.ktx) implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.process) implementation(libs.androidx.lifecycle.process)
implementation(libs.androidx.lifecycle.navigation3)
implementation(libs.androidx.preference.ktx) implementation(libs.androidx.preference.ktx)
implementation(libs.androidx.swiperefreshlayout) implementation(libs.androidx.swiperefreshlayout)
implementation(libs.androidx.viewpager2) implementation(libs.androidx.viewpager2)
@@ -194,7 +195,8 @@ dependencies {
implementation(libs.androidx.adaptive.navigation) implementation(libs.androidx.adaptive.navigation)
implementation(libs.androidx.adaptive.layout) implementation(libs.androidx.adaptive.layout)
implementation(libs.androidx.paging.compose) 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.kotlinx.serialization.json)
implementation(libs.androidx.navigation.fragment.ktx) implementation(libs.androidx.navigation.fragment.ktx)
implementation(libs.androidx.navigation.ui.ktx) implementation(libs.androidx.navigation.ui.ktx)

View File

@@ -11,10 +11,9 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.core.content.IntentCompat import androidx.core.content.IntentCompat
import androidx.navigation.compose.rememberNavController
import com.aurora.store.compose.compositions.UI import com.aurora.store.compose.compositions.UI
import com.aurora.store.compose.compositions.LocalUI 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.navigation.Screen
import com.aurora.store.compose.theme.AuroraTheme import com.aurora.store.compose.theme.AuroraTheme
import com.aurora.store.util.PackageUtil import com.aurora.store.util.PackageUtil
@@ -42,8 +41,7 @@ class ComposeActivity : ComponentActivity() {
setContent { setContent {
CompositionLocalProvider(LocalUI provides localUI) { CompositionLocalProvider(LocalUI provides localUI) {
AuroraTheme { AuroraTheme {
val navController = rememberNavController() NavDisplay(startDestination = startDestination)
NavGraph(navHostController = navController, startDestination = startDestination)
} }
} }
} }

View File

@@ -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<Screen.Blacklist> {
BlacklistScreen(onNavigateUp = { onNavigateUp() })
}
entry<Screen.Search> {
SearchScreen(onNavigateUp = { onNavigateUp() })
}
entry<Screen.AppDetails> { screen ->
AppDetailsScreen(
packageName = screen.packageName,
onNavigateUp = { onNavigateUp() },
onNavigateToAppDetails = { packageName ->
backstack.add(Screen.AppDetails(packageName))
}
)
}
entry<Screen.DevProfile> { screen ->
DevProfileScreen(
developerId = screen.developerId,
onNavigateUp = { onNavigateUp() },
onNavigateToAppDetails = { packageName ->
backstack.add(Screen.AppDetails(packageName))
}
)
}
}
)
}

View File

@@ -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<Screen.Blacklist> {
BlacklistScreen(onNavigateUp = { onNavigateUp() })
}
composable<Screen.Search> {
SearchScreen(onNavigateUp = { onNavigateUp() })
}
composable<Screen.AppDetails> { backstackEntry ->
val appDetails = backstackEntry.toRoute<Screen.AppDetails>()
AppDetailsScreen(
packageName = appDetails.packageName,
onNavigateUp = { onNavigateUp() },
onNavigateToAppDetails = { packageName ->
navHostController.navigate(Screen.AppDetails(packageName))
}
)
}
composable<Screen.DevProfile> { backstackEntry ->
val devProfile = backstackEntry.toRoute<Screen.DevProfile>()
DevProfileScreen(
developerId = devProfile.developerId,
onNavigateUp = { onNavigateUp() },
onNavigateToAppDetails = { packageName ->
navHostController.navigate(Screen.AppDetails(packageName))
}
)
}
}
}

View File

@@ -8,6 +8,7 @@ package com.aurora.store.compose.navigation
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.navigation3.runtime.NavKey
import com.aurora.store.R import com.aurora.store.R
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@@ -22,7 +23,7 @@ import kotlinx.serialization.Serializable
sealed class Screen( sealed class Screen(
@StringRes val label: Int? = null, @StringRes val label: Int? = null,
@DrawableRes val icon: Int? = null @DrawableRes val icon: Int? = null
) : Parcelable { ) : NavKey, Parcelable {
companion object { companion object {
const val PARCEL_KEY = "SCREEN" const val PARCEL_KEY = "SCREEN"

View File

@@ -29,8 +29,10 @@ ktlint = "12.1.2"
leakcanary = "2.14" leakcanary = "2.14"
libsu = "6.0.0" libsu = "6.0.0"
lifecycle = "2.9.2" lifecycle = "2.9.2"
lifecycle-navigation3 = "1.0.0-alpha04"
material = "1.12.0" material = "1.12.0"
navigation = "2.9.3" navigation = "2.9.3"
navigation3 = "1.0.0-alpha07"
okhttp = "5.1.0" okhttp = "5.1.0"
paging = "3.3.6" paging = "3.3.6"
preference = "1.2.1" 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-junit = { module = "androidx.test.ext:junit-ktx", version.ref = "androidx-junit" }
androidx-lifecycle-process = { module = "androidx.lifecycle:lifecycle-process", version.ref = "lifecycle" } 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-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-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-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-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-compose = { module = "androidx.paging:paging-compose", version.ref = "paging" }
androidx-paging-runtime = { module = "androidx.paging:paging-runtime", 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" } androidx-preference-ktx = { module = "androidx.preference:preference-ktx", version.ref = "preference" }