refactor: eliminate Destination indirection

This commit is contained in:
Harsh Shandilya 2025-05-25 18:31:48 +05:30
parent 9dce06ff80
commit f64d4ab9a1
7 changed files with 34 additions and 40 deletions

View file

@ -17,7 +17,6 @@ plugins {
id("dev.msfjarvis.claw.kotlin-kapt")
id("dev.msfjarvis.claw.sentry")
id("dev.msfjarvis.claw.versioning-plugin")
id("kotlin-parcelize")
alias(libs.plugins.aboutlibraries)
alias(libs.plugins.android.junit5)
alias(libs.plugins.anvil)

View file

@ -24,8 +24,8 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.navigation3.runtime.NavKey
import dev.msfjarvis.claw.android.R
import dev.msfjarvis.claw.android.ui.navigation.Destination
import dev.msfjarvis.claw.android.ui.navigation.Search
import dev.msfjarvis.claw.android.ui.navigation.Settings
@ -34,8 +34,8 @@ import dev.msfjarvis.claw.android.ui.navigation.Settings
fun ClawAppBar(
activity: Activity?,
isTopLevel: Boolean,
navigateTo: (Destination) -> Unit,
popBackStack: () -> Destination?,
navigateTo: (NavKey) -> Unit,
popBackStack: () -> NavKey?,
modifier: Modifier = Modifier,
) {
TopAppBar(

View file

@ -26,12 +26,12 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import androidx.navigation3.runtime.NavKey
import dev.chrisbanes.haze.HazeDefaults
import dev.chrisbanes.haze.HazeState
import dev.chrisbanes.haze.HazeStyle
import dev.chrisbanes.haze.hazeEffect
import dev.msfjarvis.claw.android.ui.navigation.AppDestinations
import dev.msfjarvis.claw.android.ui.navigation.Destination
import dev.msfjarvis.claw.common.ui.FloatingNavigationBar
import kotlinx.collections.immutable.ImmutableList
@ -40,8 +40,8 @@ const val AnimationDuration = 100
@Composable
fun ClawNavigationBar(
items: ImmutableList<NavigationItem>,
currentDestination: Destination?,
navigateTo: (Destination) -> Unit,
currentNavKey: NavKey?,
navigateTo: (NavKey) -> Unit,
isVisible: Boolean,
hazeState: HazeState,
modifier: Modifier = Modifier,
@ -84,7 +84,7 @@ fun ClawNavigationBar(
if (HazeDefaults.blurEnabled()) Color.Transparent else MaterialTheme.colorScheme.surface,
) {
items.forEach { navItem ->
val isSelected = currentDestination == navItem.destination
val isSelected = currentNavKey == navItem.navKey
NavigationBarItem(
icon = {
Crossfade(isSelected, label = "nav-label") {
@ -100,7 +100,7 @@ fun ClawNavigationBar(
if (isSelected) {
navItem.listStateResetCallback()
} else {
navigateTo(navItem.destination)
navigateTo(navItem.navKey)
}
},
modifier = Modifier.testTag(navItem.label.uppercase()),
@ -115,7 +115,7 @@ class NavigationItem
private constructor(
val icon: ImageVector,
val label: String,
val destination: Destination,
val navKey: NavKey,
val selectedIcon: ImageVector,
val listStateResetCallback: () -> Unit,
) {
@ -125,7 +125,7 @@ private constructor(
) : this(
destination.icon,
destination.label,
destination.destination,
destination.navKey,
destination.selectedIcon,
listStateResetCallback,
) {}

View file

@ -21,14 +21,14 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import dev.msfjarvis.claw.android.ui.navigation.Destination
import androidx.navigation3.runtime.NavKey
import kotlinx.collections.immutable.ImmutableList
@Composable
fun ClawNavigationRail(
items: ImmutableList<NavigationItem>,
currentDestination: Destination?,
navigateTo: (Destination) -> Unit,
currentNavKey: NavKey?,
navigateTo: (NavKey) -> Unit,
isVisible: Boolean,
modifier: Modifier = Modifier,
) {
@ -51,7 +51,7 @@ fun ClawNavigationRail(
NavigationRail(modifier = modifier) {
Spacer(Modifier.weight(1f))
items.forEach { navItem ->
val isSelected = currentDestination == navItem.destination
val isSelected = currentNavKey == navItem.navKey
NavigationRailItem(
icon = {
Crossfade(isSelected, label = "nav-label") {
@ -67,7 +67,7 @@ fun ClawNavigationRail(
if (isSelected) {
navItem.listStateResetCallback()
} else {
navigateTo(navItem.destination)
navigateTo(navItem.navKey)
}
},
modifier = Modifier.testTag(navItem.label.uppercase()),

View file

@ -22,7 +22,7 @@ import io.github.aakira.napier.Napier
* to the front while lists add behind. To counter these expectations with the actual backing data
* structure, many APIs in this class inverse of identically named functions on [List].
*/
class ClawBackStack<T : NavKey>(private val initialDestination: T) {
class ClawBackStack(private val initialDestination: NavKey) {
/**
* Marker interface for destinations that occupy the "top" level of the back stack.
*
@ -41,7 +41,7 @@ class ClawBackStack<T : NavKey>(private val initialDestination: T) {
* from getting stuck in a frustratingly long stack of top level destinations that are so easily
* accessible that they have no reason to be on the stack.
*/
fun add(destination: T) {
fun add(destination: NavKey) {
logCurrentState("add")
if (destination is TopLevelDestination) {
backStack.clear()
@ -59,17 +59,17 @@ class ClawBackStack<T : NavKey>(private val initialDestination: T) {
return (top != null && top is TopLevelDestination)
}
fun firstOrNull(): T? {
fun firstOrNull(): NavKey? {
logCurrentState("firstOrNull")
return backStack.lastOrNull()
}
fun lastOrNull(): T? {
fun lastOrNull(): NavKey? {
logCurrentState("lastOrNull")
return backStack.firstOrNull()
}
fun removeLastOrNull(): T? {
fun removeLastOrNull(): NavKey? {
logCurrentState("removeLastOrNull")
return backStack.removeLastOrNull()
}

View file

@ -6,7 +6,6 @@
*/
package dev.msfjarvis.claw.android.ui.navigation
import android.os.Parcelable
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.NewReleases
@ -17,49 +16,46 @@ import androidx.compose.material.icons.outlined.Whatshot
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.navigation3.runtime.NavKey
import dev.msfjarvis.claw.android.ui.navigation.ClawBackStack.TopLevelDestination
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable
sealed interface Destination : Parcelable, NavKey
@Serializable data object Hottest : NavKey, TopLevelDestination
@Parcelize @Serializable data object Hottest : Destination, TopLevelDestination
@Serializable data object Newest : NavKey, TopLevelDestination
@Parcelize @Serializable data object Newest : Destination, TopLevelDestination
@Serializable data object Saved : NavKey, TopLevelDestination
@Parcelize @Serializable data object Saved : Destination, TopLevelDestination
@Serializable data class Comments(val postId: String) : NavKey
@Parcelize @Serializable data class Comments(val postId: String) : Destination
@Serializable data class User(val username: String) : NavKey
@Parcelize @Serializable data class User(val username: String) : Destination
@Serializable data object Search : NavKey
@Parcelize @Serializable data object Search : Destination
@Serializable data object Settings : NavKey
@Parcelize @Serializable data object Settings : Destination
@Parcelize @Serializable data object AboutLibraries : Destination
@Serializable data object AboutLibraries : NavKey
enum class AppDestinations(
val icon: ImageVector,
val label: String,
val destination: Destination,
val navKey: NavKey,
val selectedIcon: ImageVector,
) {
HOTTEST(
icon = Icons.Outlined.Whatshot,
label = "Hottest",
destination = Hottest,
navKey = Hottest,
selectedIcon = Icons.Filled.Whatshot,
),
NEWEST(
icon = Icons.Outlined.NewReleases,
label = "Newest",
destination = Newest,
navKey = Newest,
selectedIcon = Icons.Filled.NewReleases,
),
SAVED(
icon = Icons.Outlined.FavoriteBorder,
label = "Saved",
destination = Saved,
navKey = Saved,
selectedIcon = Icons.Filled.Favorite,
),
}

View file

@ -51,7 +51,6 @@ import dev.msfjarvis.claw.android.ui.navigation.AppDestinations
import dev.msfjarvis.claw.android.ui.navigation.ClawBackStack
import dev.msfjarvis.claw.android.ui.navigation.ClawNavigationType
import dev.msfjarvis.claw.android.ui.navigation.Comments
import dev.msfjarvis.claw.android.ui.navigation.Destination
import dev.msfjarvis.claw.android.ui.navigation.Hottest
import dev.msfjarvis.claw.android.ui.navigation.Newest
import dev.msfjarvis.claw.android.ui.navigation.Saved
@ -75,7 +74,7 @@ fun Nav3Screen(
modifier: Modifier = Modifier,
viewModel: ClawViewModel = injectedViewModel(),
) {
val clawBackStack = ClawBackStack<Destination>(Hottest)
val clawBackStack = ClawBackStack(Hottest)
// region Pain
val context = LocalContext.current
@ -136,7 +135,7 @@ fun Nav3Screen(
AnimatedVisibility(visible = navigationType == ClawNavigationType.BOTTOM_NAVIGATION) {
ClawNavigationBar(
items = navItems,
currentDestination = currentDestination,
currentNavKey = currentDestination,
navigateTo = { clawBackStack.add(it) },
isVisible = clawBackStack.isOnTopLevelDestination(),
hazeState = hazeState,