From 0d4b57c1e99d2cf1a62341d86a1ce5556118d202 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 10:04:32 -0700 Subject: [PATCH 1/8] Deduplicate lifecycle runtime compose --- app/build.gradle.kts | 1 - gradle/libs.versions.toml | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f28f4a98..058342b8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -106,7 +106,6 @@ dependencies { implementation(libs.graphics.shapes) implementation(libs.lifecycle.ktx) - implementation(libs.lifecycle.compose) implementation(libs.lifecycle.runtime.compose) ksp(libs.room.compiler) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7c5d887e..c65cec48 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -84,9 +84,8 @@ hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } junit = { group = "junit", name = "junit", version.ref = "junit" } -lifecycle-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } lifecycle-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } -lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycle" } +lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } media3-common = { group = "androidx.media3", name = "media3-common", version.ref = "media3" } media3-effect = { group = "androidx.media3", name = "media3-effect", version.ref = "media3" } media3-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" } From 583a2b5ba21e910d814fac4db8f8f5c15e3a6f08 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 10:35:40 -0700 Subject: [PATCH 2/8] kotlin 2.0 and compose gradle plugin --- .gitignore | 1 + app/build.gradle.kts | 16 ++++------------ build.gradle.kts | 1 + gradle/libs.versions.toml | 5 +++-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c8d29..5928b36e 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ .externalNativeBuild .cxx local.properties +.kotlin diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 058342b8..c5a66f25 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,10 +14,10 @@ * limitations under the License. */ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.baselineprofile) + alias(libs.plugins.compose) alias(libs.plugins.hilt) alias(libs.plugins.kotlinAndroid) alias(libs.plugins.ksp) @@ -25,6 +25,9 @@ plugins { kotlin { jvmToolchain(17) + compilerOptions { + freeCompilerArgs = listOf("-Xcontext-receivers") + } } android { @@ -47,20 +50,9 @@ android { proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - kotlinOptions { - jvmTarget = "17" - freeCompilerArgs = listOf("-Xcontext-receivers") - } buildFeatures { compose = true } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() - } packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" diff --git a/build.gradle.kts b/build.gradle.kts index f20db0e1..4eba6969 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ plugins { alias(libs.plugins.androidApplication) apply false alias(libs.plugins.androidTest) apply false alias(libs.plugins.baselineprofile) apply false + alias(libs.plugins.compose) apply false alias(libs.plugins.kotlinAndroid) apply false alias(libs.plugins.spotless) apply false alias(libs.plugins.hilt) apply false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c65cec48..b5314b24 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,8 +31,8 @@ graphics = "1.0.0-beta01" hilt = "2.48.1" hiltNavigationCompose = "1.1.0" junit = "4.13.2" -kotlin = "1.9.20" -ksp = "1.9.20-1.0.14" +kotlin = "2.0.0" +ksp = "2.0.0-1.0.21" lifecycle = "2.7.0" material3 = "1.2.1" media3 = "1.3.1" @@ -107,6 +107,7 @@ ktlint = "com.pinterest.ktlint:ktlint-cli:1.1.1" # Used in build.gradle.kts androidApplication = { id = "com.android.application", version.ref = "agp" } androidTest = { id = "com.android.test", version.ref = "agp" } baselineprofile = { id = "androidx.baselineprofile", version.ref = "baselineprofile" } +compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } From 8d19114011c88f7178aef82f7688bf7e21659a61 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 10:43:01 -0700 Subject: [PATCH 3/8] update compose bom and navigation suite --- app/build.gradle.kts | 1 - gradle/libs.versions.toml | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c5a66f25..ce43fa1b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -77,7 +77,6 @@ dependencies { val composeBom = platform(libs.compose.bom) implementation(composeBom) androidTestImplementation(composeBom) - implementation(libs.compose.foundation) implementation(libs.compose.ui) implementation(libs.compose.ui.graphics) implementation(libs.compose.ui.text.google.fonts) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b5314b24..11fe4f69 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,9 +20,7 @@ benchmarkMacroJunit4 = "1.2.4" baselineprofile = "1.2.4" camera = "1.3.3" coil = "2.4.0" -compose_bom = "2024.05.00" -composeCompiler = "1.5.4" # Used in app/build.gradle.kts -compose-foundation = "1.6.0-beta03" +compose_bom = "2024.08.00" concurrent = "1.1.0" core = "1.13.1" core-splashscreen = "1.2.0-alpha01" @@ -45,7 +43,7 @@ truth = "1.1.3" turbine = "1.0.0" uiautomator = "2.3.0" window = "1.2.0" -material3-adaptive-navigation-suite = "1.0.0-alpha05" +material3-adaptive-navigation-suite = "1.3.0-rc01" glance = "1.1.0-beta02" [libraries] @@ -65,7 +63,6 @@ compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = compose-material-icons = { group = "androidx.compose.material", name = "material-icons-extended" } compose-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" } compose-material3-adaptive = { group = "androidx.compose.material3", name = "material3-adaptive-navigation-suite", version.ref = "material3-adaptive-navigation-suite"} -compose-foundation = { group = "androidx.compose.foundation", name = "foundation" } compose-ui = { group = "androidx.compose.ui", name = "ui" } compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } compose-ui-test = { group = "androidx.compose.ui", name = "ui-test-junit4" } From e485506352f922bf70b4e735ef3f20408529a6d7 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 11:01:47 -0700 Subject: [PATCH 4/8] Update various UI libs --- gradle/libs.versions.toml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 11fe4f69..bb4aae49 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,27 +13,27 @@ # limitations under the License. [versions] -accompanist = "0.32.0" -activity = "1.9.0" +accompanist = "0.34.0" +activity = "1.9.1" agp = "8.2.2" benchmarkMacroJunit4 = "1.2.4" baselineprofile = "1.2.4" -camera = "1.3.3" -coil = "2.4.0" +camera = "1.3.4" +coil = "2.6.0" compose_bom = "2024.08.00" concurrent = "1.1.0" core = "1.13.1" core-splashscreen = "1.2.0-alpha01" espresso = "3.5.1" -graphics = "1.0.0-beta01" -hilt = "2.48.1" -hiltNavigationCompose = "1.1.0" +graphics = "1.0.0" +hilt = "2.51.1" +hiltNavigationCompose = "1.2.0" junit = "4.13.2" kotlin = "2.0.0" ksp = "2.0.0-1.0.21" -lifecycle = "2.7.0" +lifecycle = "2.8.4" material3 = "1.2.1" -media3 = "1.3.1" +media3 = "1.4.1" navigation = "2.7.7" profileinstaller = "1.3.1" room = "2.6.1" @@ -42,9 +42,9 @@ test = "1.1.5" truth = "1.1.3" turbine = "1.0.0" uiautomator = "2.3.0" -window = "1.2.0" +window = "1.3.0" material3-adaptive-navigation-suite = "1.3.0-rc01" -glance = "1.1.0-beta02" +glance = "1.1.0" [libraries] accompanist-painter = { group = "com.google.accompanist", name = "accompanist-drawablepainter", version.ref = "accompanist" } From 139d0ba1bdf31bd188d8073b86daaaa3dd343a3f Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 11:09:57 -0700 Subject: [PATCH 5/8] update test & other versions --- gradle/libs.versions.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bb4aae49..db552487 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,15 +16,15 @@ accompanist = "0.34.0" activity = "1.9.1" agp = "8.2.2" -benchmarkMacroJunit4 = "1.2.4" -baselineprofile = "1.2.4" +benchmarkMacroJunit4 = "1.3.0" +baselineprofile = "1.3.0" camera = "1.3.4" coil = "2.6.0" compose_bom = "2024.08.00" -concurrent = "1.1.0" +concurrent = "1.2.0" core = "1.13.1" core-splashscreen = "1.2.0-alpha01" -espresso = "3.5.1" +espresso = "3.6.1" graphics = "1.0.0" hilt = "2.51.1" hiltNavigationCompose = "1.2.0" @@ -38,8 +38,8 @@ navigation = "2.7.7" profileinstaller = "1.3.1" room = "2.6.1" spotless = "6.24.0" -test = "1.1.5" -truth = "1.1.3" +test = "1.2.1" +truth = "1.4.4" turbine = "1.0.0" uiautomator = "2.3.0" window = "1.3.0" From d8f53e985c6f9bf165e5fccde1861ea9a9505afe Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 13:37:21 -0700 Subject: [PATCH 6/8] run spotlessApply --- .../com/google/android/samples/socialite/MainActivity.kt | 9 ++++----- .../java/com/google/android/samples/socialite/ui/Main.kt | 3 --- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/google/android/samples/socialite/MainActivity.kt b/app/src/main/java/com/google/android/samples/socialite/MainActivity.kt index b1c22230..8dca7ce2 100644 --- a/app/src/main/java/com/google/android/samples/socialite/MainActivity.kt +++ b/app/src/main/java/com/google/android/samples/socialite/MainActivity.kt @@ -22,7 +22,6 @@ import android.os.Bundle import android.view.WindowInsetsController import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.isSystemInDarkTheme import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen @@ -36,7 +35,6 @@ class MainActivity : ComponentActivity() { installSplashScreen() super.onCreate(savedInstanceState) setContent { - // setSystemBarAppearance can be removed after calling enableEdgeToEdge() setSystemBarAppearance(isSystemInDarkTheme()) @@ -55,16 +53,17 @@ class MainActivity : ComponentActivity() { return ShortcutParams(shortcutId, text) } - private fun setSystemBarAppearance(isSystemInDarkTheme : Boolean) { + private fun setSystemBarAppearance(isSystemInDarkTheme: Boolean) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (isSystemInDarkTheme) { window?.insetsController?.setSystemBarsAppearance( - 0, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS + 0, + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, ) } else { window?.insetsController?.setSystemBarsAppearance( WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, - WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS, ) } } diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt b/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt index 8f9a886e..7cd7e274 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/Main.kt @@ -20,14 +20,11 @@ import android.app.Activity import android.content.Intent import android.content.pm.ActivityInfo import android.os.Bundle -import androidx.compose.animation.core.CubicBezierEasing import androidx.compose.animation.core.FastOutLinearInEasing import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.animation.scaleIn -import androidx.compose.animation.scaleOut import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier From 5f353566ff6dc8619aa43ae539b18b76c518d513 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 14:25:48 -0700 Subject: [PATCH 7/8] Call navigate instead of recomposing HavHost Previously, the app had a NavHost but didn't actually call navigate. NavHost's startDestination was read from external state (the currently selected nav item), which led to some undesirable behaviors. - NavHost itself was recomposed when selecting a nav item. - Pressing back always exited the app because you were always at the start destination. Now the NavHost has a stable startDestination, and nav item state is driven by the NavHostController's current destination. Selecting a nav item calls navigate, and the user always goes back through the startDestination before exiting the app. --- .../android/samples/socialite/ui/home/Home.kt | 56 +++++++++++++------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt index f82dde11..0fb4ea7b 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt @@ -28,71 +28,85 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.material3.adaptive.navigationsuite.ExperimentalMaterial3AdaptiveNavigationSuiteApi import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.google.android.samples.socialite.R import com.google.android.samples.socialite.ui.AnimationConstants import com.google.android.samples.socialite.ui.home.timeline.Timeline -@OptIn(ExperimentalMaterial3AdaptiveNavigationSuiteApi::class) @Composable fun Home( onChatClicked: (chatId: Long) -> Unit, modifier: Modifier = Modifier, ) { - var currentDestination by rememberSaveable { mutableStateOf(Destination.Chats) } + val navController = rememberNavController() + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentDestination = Destination.fromRoute( + navBackStackEntry?.destination?.route + ) ?: Destination.START_DESTINATION + NavigationSuiteScaffold( navigationSuiteItems = { - for (destination in Destination.entries) { - val selected = currentDestination.route == destination.route + Destination.entries.forEach { + val isSelected = it == currentDestination item( - selected = selected, - onClick = { currentDestination = destination }, + selected = isSelected, + onClick = { + if (!isSelected) { + navController.navigate(it.route) { + popUpTo(navController.graph.findStartDestination().id) + launchSingleTop = true + } + } + }, icon = { Icon( - imageVector = destination.imageVector, - contentDescription = stringResource(destination.label), + imageVector = it.imageVector, + contentDescription = stringResource(it.label), ) }, label = { - Text(text = stringResource(destination.label)) + Text(text = stringResource(it.label)) }, alwaysShowLabel = false, ) } }, - ) { HomeContent(currentDestination, modifier, onChatClicked) } + ) { + HomeContent(navController, currentDestination, modifier, onChatClicked) + } } @Composable private fun HomeContent( + navController: NavHostController, currentDestination: Destination, modifier: Modifier, onChatClicked: (chatId: Long) -> Unit, ) { Scaffold( modifier = modifier, - topBar = { HomeAppBar(title = stringResource(currentDestination.label)) }, + topBar = { + HomeAppBar(title = stringResource(currentDestination.label)) + }, ) { innerPadding -> - val navController = rememberNavController() HomeBackground(modifier = Modifier.fillMaxSize()) NavHost( navController = navController, - startDestination = currentDestination.route, + startDestination = Destination.START_DESTINATION.route, modifier = modifier, ) { composable( @@ -167,5 +181,11 @@ private enum class Destination( route = "settings", label = R.string.settings, imageVector = Icons.Outlined.Settings, - ), + ); + + companion object { + val START_DESTINATION = Chats + + fun fromRoute(route: String?): Destination? = entries.find { it.route == route } + } } From a177ea7b2ce4239d50c42f8bb180fd6598a40634 Mon Sep 17 00:00:00 2001 From: Jonathan Koren Date: Thu, 29 Aug 2024 15:43:59 -0700 Subject: [PATCH 8/8] Use type-safe navigation --- app/build.gradle.kts | 2 + .../android/samples/socialite/ui/home/Home.kt | 47 +++++++++++++------ build.gradle.kts | 5 +- gradle/libs.versions.toml | 5 +- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ce43fa1b..6bd7dda9 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -20,6 +20,7 @@ plugins { alias(libs.plugins.compose) alias(libs.plugins.hilt) alias(libs.plugins.kotlinAndroid) + alias(libs.plugins.kotlinSerialization) alias(libs.plugins.ksp) } @@ -90,6 +91,7 @@ dependencies { implementation(libs.activity.compose) implementation(libs.navigation.compose) + implementation(libs.kotlinx.serialization.json) implementation(libs.accompanist.painter) implementation(libs.accompanist.permissions) diff --git a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt index 0fb4ea7b..4062a482 100644 --- a/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt +++ b/app/src/main/java/com/google/android/samples/socialite/ui/home/Home.kt @@ -37,6 +37,9 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavBackStackEntry +import androidx.navigation.NavDestination.Companion.hasRoute +import androidx.navigation.NavDestination.Companion.hierarchy import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost @@ -46,6 +49,7 @@ import androidx.navigation.compose.rememberNavController import com.google.android.samples.socialite.R import com.google.android.samples.socialite.ui.AnimationConstants import com.google.android.samples.socialite.ui.home.timeline.Timeline +import kotlinx.serialization.Serializable @Composable fun Home( @@ -54,9 +58,7 @@ fun Home( ) { val navController = rememberNavController() val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentDestination = Destination.fromRoute( - navBackStackEntry?.destination?.route - ) ?: Destination.START_DESTINATION + val currentDestination = Destination.fromNavBackStackEntry(navBackStackEntry) NavigationSuiteScaffold( navigationSuiteItems = { @@ -109,8 +111,7 @@ private fun HomeContent( startDestination = Destination.START_DESTINATION.route, modifier = modifier, ) { - composable( - route = Destination.Timeline.route, + composable( enterTransition = { AnimationConstants.enterTransition }, exitTransition = { AnimationConstants.exitTransition }, ) { @@ -119,8 +120,7 @@ private fun HomeContent( modifier = modifier, ) } - composable( - route = Destination.Chats.route, + composable( enterTransition = { AnimationConstants.enterTransition }, exitTransition = { AnimationConstants.exitTransition }, ) { @@ -133,8 +133,7 @@ private fun HomeContent( modifier = modifier, ) } - composable( - route = Destination.Settings.route, + composable( enterTransition = { AnimationConstants.enterTransition }, exitTransition = { AnimationConstants.exitTransition }, ) { @@ -162,30 +161,48 @@ fun HomeAppBar( ) } +sealed interface Route { + @Serializable + data object TimelineRoute : Route + + @Serializable + data object ChatsRoute : Route + + @Serializable + data object SettingsRoute : Route +} + private enum class Destination( - val route: String, + val route: Route, @StringRes val label: Int, val imageVector: ImageVector, ) { Timeline( - route = "timeline", + route = Route.TimelineRoute, label = R.string.timeline, imageVector = Icons.Outlined.VideoLibrary, ), Chats( - route = "chats", + route = Route.ChatsRoute, label = R.string.chats, imageVector = Icons.Outlined.ChatBubbleOutline, ), Settings( - route = "settings", + route = Route.SettingsRoute, label = R.string.settings, imageVector = Icons.Outlined.Settings, - ); + ), + ; companion object { val START_DESTINATION = Chats - fun fromRoute(route: String?): Destination? = entries.find { it.route == route } + fun fromNavBackStackEntry(nbse: NavBackStackEntry?): Destination { + return entries.find { dest -> + nbse?.destination?.hierarchy?.any { + it.hasRoute(dest.route::class) + } == true + } ?: START_DESTINATION + } } } diff --git a/build.gradle.kts b/build.gradle.kts index 4eba6969..e47034ba 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,10 +22,11 @@ plugins { alias(libs.plugins.androidTest) apply false alias(libs.plugins.baselineprofile) apply false alias(libs.plugins.compose) apply false - alias(libs.plugins.kotlinAndroid) apply false - alias(libs.plugins.spotless) apply false alias(libs.plugins.hilt) apply false + alias(libs.plugins.kotlinAndroid) apply false + alias(libs.plugins.kotlinSerialization) apply false alias(libs.plugins.ksp) apply false + alias(libs.plugins.spotless) apply false } subprojects { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index db552487..ff7f87eb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,11 +30,12 @@ hilt = "2.51.1" hiltNavigationCompose = "1.2.0" junit = "4.13.2" kotlin = "2.0.0" +kotlinxSerializationJson = "1.6.3" ksp = "2.0.0-1.0.21" lifecycle = "2.8.4" material3 = "1.2.1" media3 = "1.4.1" -navigation = "2.7.7" +navigation = "2.8.0-rc01" profileinstaller = "1.3.1" room = "2.6.1" spotless = "6.24.0" @@ -81,6 +82,7 @@ hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref hilt-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" } junit = { group = "junit", name = "junit", version.ref = "junit" } +kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } lifecycle-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle" } media3-common = { group = "androidx.media3", name = "media3-common", version.ref = "media3" } @@ -107,5 +109,6 @@ baselineprofile = { id = "androidx.baselineprofile", version.ref = "baselineprof compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" }