Add NiaBackStack and BackStack providers

Bump agp versions and add navigation 3 dependency
pull/1902/head
Clara Fok 2 months ago
parent 7cc2b1ae42
commit a163dd7929

@ -79,6 +79,7 @@ dependencies {
implementation(projects.core.designsystem) implementation(projects.core.designsystem)
implementation(projects.core.data) implementation(projects.core.data)
implementation(projects.core.model) implementation(projects.core.model)
implementation(projects.core.navigation)
implementation(projects.core.analytics) implementation(projects.core.analytics)
implementation(projects.sync.work) implementation(projects.sync.work)

@ -0,0 +1,34 @@
/*
* Copyright 2025 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.google.samples.apps.nowinandroid.di
import com.google.samples.apps.nowinandroid.core.navigation.NiaBackStack
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import javax.inject.Singleton
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object NiaAppNavigation {
@Provides
@Singleton
fun provideNiaBackStack(): NiaBackStack =
NiaBackStack(startKey = TopLevelDestination.FOR_YOU)
}

@ -37,7 +37,7 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
extensions.configure<ApplicationExtension> { extensions.configure<ApplicationExtension> {
configureKotlinAndroid(this) configureKotlinAndroid(this)
defaultConfig.targetSdk = 35 defaultConfig.targetSdk = 36
@Suppress("UnstableApiUsage") @Suppress("UnstableApiUsage")
testOptions.animationsDisabled = true testOptions.animationsDisabled = true
configureGradleManagedDevices(this) configureGradleManagedDevices(this)

@ -37,7 +37,7 @@ class AndroidLibraryConventionPlugin : Plugin<Project> {
extensions.configure<LibraryExtension> { extensions.configure<LibraryExtension> {
configureKotlinAndroid(this) configureKotlinAndroid(this)
defaultConfig.targetSdk = 35 defaultConfig.targetSdk = 36
defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" defaultConfig.testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testOptions.animationsDisabled = true testOptions.animationsDisabled = true
configureFlavors(this) configureFlavors(this)

@ -30,7 +30,7 @@ class AndroidTestConventionPlugin : Plugin<Project> {
extensions.configure<TestExtension> { extensions.configure<TestExtension> {
configureKotlinAndroid(this) configureKotlinAndroid(this)
defaultConfig.targetSdk = 35 defaultConfig.targetSdk = 36
configureGradleManagedDevices(this) configureGradleManagedDevices(this)
} }
} }

@ -35,7 +35,7 @@ internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *, *, *>, commonExtension: CommonExtension<*, *, *, *, *, *>,
) { ) {
commonExtension.apply { commonExtension.apply {
compileSdk = 35 compileSdk = 36
defaultConfig { defaultConfig {
minSdk = 21 minSdk = 21

@ -0,0 +1 @@
/build

@ -0,0 +1,8 @@
plugins {
alias(libs.plugins.nowinandroid.jvm.library)
alias(libs.plugins.nowinandroid.hilt)
}
dependencies {
implementation(libs.androidx.navigation3.runtime)
}

@ -0,0 +1,77 @@
/*
* Copyright 2025 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.google.samples.apps.nowinandroid.core.navigation
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList
import javax.inject.Inject
import kotlin.collections.remove
class NiaBackStack @Inject constructor(
startKey: Any,
) {
val backStack = mutableStateListOf(startKey)
// Maintain a stack for each top level route
private var topLevelStacks : LinkedHashMap<Any, SnapshotStateList<Any>> = linkedMapOf(
startKey to mutableStateListOf(startKey)
)
// Expose the current top level route for consumers
var topLevelKey by mutableStateOf(startKey)
private set
private fun updateBackStack() =
backStack.apply {
clear()
addAll(topLevelStacks.flatMap { it.value })
}
fun navigateToTopLevelDestination(key: Any){
// If the top level doesn't exist, add it
if (topLevelStacks[key] == null){
topLevelStacks.put(key, mutableStateListOf(key))
} else {
// Otherwise just move it to the end of the stacks
topLevelStacks.apply {
remove(key)?.let {
put(key, it)
}
}
}
topLevelKey = key
updateBackStack()
}
fun navigate(key: Any){
println("cfok navigate $key")
topLevelStacks[topLevelKey]?.add(key)
updateBackStack()
}
fun removeLast(){
val removedKey = topLevelStacks[topLevelKey]?.removeLastOrNull()
// If the removed key was a top level key, remove the associated top level stack
topLevelStacks.remove(removedKey)
topLevelKey = topLevelStacks.keys.last()
updateBackStack()
}
}

@ -2,8 +2,8 @@
accompanist = "0.37.0" accompanist = "0.37.0"
androidDesugarJdkLibs = "2.1.4" androidDesugarJdkLibs = "2.1.4"
# AGP and tools should be updated together # AGP and tools should be updated together
androidGradlePlugin = "8.9.0" androidGradlePlugin = "8.9.3"
androidTools = "31.9.0" androidTools = "31.9.3"
androidxActivity = "1.9.3" androidxActivity = "1.9.3"
androidxAppCompat = "1.7.0" androidxAppCompat = "1.7.0"
androidxBrowser = "1.8.0" androidxBrowser = "1.8.0"
@ -21,6 +21,7 @@ androidxLintGradle = "1.0.0-alpha03"
androidxMacroBenchmark = "1.3.4" androidxMacroBenchmark = "1.3.4"
androidxMetrics = "1.0.0-beta01" androidxMetrics = "1.0.0-beta01"
androidxNavigation = "2.8.5" androidxNavigation = "2.8.5"
androidxNavigation3 = "1.0.0-alpha03"
androidxProfileinstaller = "1.4.1" androidxProfileinstaller = "1.4.1"
androidxTestCore = "1.7.0-rc01" androidxTestCore = "1.7.0-rc01"
androidxTestExt = "1.3.0-rc01" androidxTestExt = "1.3.0-rc01"
@ -99,6 +100,8 @@ androidx-lint-gradle = { group = "androidx.lint", name = "lint-gradle", version.
androidx-metrics = { group = "androidx.metrics", name = "metrics-performance", version.ref = "androidxMetrics" } androidx-metrics = { group = "androidx.metrics", name = "metrics-performance", version.ref = "androidxMetrics" }
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigation" } androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigation" }
androidx-navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "androidxNavigation" } androidx-navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "androidxNavigation" }
androidx-navigation3-runtime = { group = "androidx.navigation3", name = "navigation3-runtime", version.ref = "androidxNavigation3" }
androidx-navigation3-ui = { group = "androidx.navigation3", name = "navigation3-ui", version.ref = "androidxNavigation3" }
androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "androidxProfileinstaller" } androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "androidxProfileinstaller" }
androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTestCore" } androidx-test-core = { group = "androidx.test", name = "core", version.ref = "androidxTestCore" }
androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxEspresso" } androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxEspresso" }

@ -59,6 +59,7 @@ include(":core:datastore-test")
include(":core:designsystem") include(":core:designsystem")
include(":core:domain") include(":core:domain")
include(":core:model") include(":core:model")
include(":core:navigation")
include(":core:network") include(":core:network")
include(":core:notifications") include(":core:notifications")
include(":core:screenshot-testing") include(":core:screenshot-testing")

Loading…
Cancel
Save