-
Can't seem to get the applications navigation flow have tried to check the TreeNav Library but didn't get it right. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
The app manages navigation as state, using a soft fork of Navigation 3 bc Navigation 3 is not KMP compatible yet. This should be resolved with compose 1.9. A high level overview of the navigation semantics are explained in this video. Ultimately, it makes it easy to build out navigation for multiple screen sizes at once. The root navigation type is a To navigate in the app, a navigation action is sent from the a ViewModel, and the ViewModel sends a navigation mutation to the NavMutator. A navigation mutation is a lambda with a For example in the private val SignedInNavigationState = MultiStackNav(
name = "signed-in-app",
stacks = listOf(
AppStack.Home,
AppStack.Search,
AppStack.Messages,
AppStack.Notifications,
).map(AppStack::toStackNav)
)
private val SignedOutNavigationState = MultiStackNav(
name = "signed-out-app",
stacks = listOf(
AppStack.Auth.toStackNav()
)
) Signing in changes the navigation state In the UI layer, navigation happens with the class ActualHomeViewModel(
...
navActions: (NavigationMutation) -> Unit,
...
) A typealias NavigationMutation = NavigationContext.() -> MultiStackNav Its a function that reads the current navigation context, and returns a new interface NavigationContext {
val navState: MultiStackNav
val String.toRoute: Route
fun Route.encodeToQueryParam(): String
} It allows for reading the current navigation state, and for converting a url string to a fully defined The ViewModel takes navigation actions which looks like this: sealed class Navigate : Action(key = "Navigate"), NavigationAction {
data class To(
val delegate: NavigationAction.Destination,
) : Navigate(), NavigationAction by delegate
} All fun profileFollowersDestination(
profileId: ProfileId,
): NavigationAction.Destination = pathDestination(
path = "/profile/${profileId.id}/followers",
referringRouteOption = ReferringRouteOption.Current
)
fun signInDestination(): NavigationAction.Destination = pathDestination(
path = "/auth",
) So on the home screen, if a guest user wants to sign in, routing to the sign in screen looks something like this: PostInteractionsBottomSheet(
...,
onSignInClicked = {
actions(
Action.Navigate.To(signInDestination())
)
},
) All the app does, is either push or pop these destinations unto the internal data class ToRawUrl(
...
) : Destination() {
override val navigationMutation: NavigationMutation = {
routeString(
path = path,
queryParams = miscQueries + mapOf(
"model" to models.map(UrlEncodableModel::toUrlEncodedBase64),
"sharedElementPrefix" to listOfNotNull(sharedElementPrefix),
"avatarSharedElementKey" to listOfNotNull(avatarSharedElementKey),
referringRouteQueryParams(referringRouteOption),
)
).toRoute
.takeIf { it.id != currentRoute.id }
?.let(navState::push) // <--- This is where pushing happens.
?: navState
}
} |
Beta Was this translation helpful? Give feedback.
The app manages navigation as state, using a soft fork of Navigation 3 bc Navigation 3 is not KMP compatible yet. This should be resolved with compose 1.9.
A high level overview of the navigation semantics are explained in this video.
Ultimately, it makes it easy to build out navigation for multiple screen sizes at once.
The root navigation type is a
MultistackNav
, managed by theNavigationStateHolder
typealias. TheNavigationStateHolder
holds an instance of aMultiStackNav
in memory, and every time it changes, it's persisted to disk in theSavedStateDataStore
.To navigate in the app, a navigation action is sent from the a ViewModel, and the ViewModel sends a navigation mutation to the Na…