GithubHelp home page GithubHelp logo

chrynan / navigation Goto Github PK

View Code? Open in Web Editor NEW
43.0 1.0 3.0 777 KB

Kotlin multi-platform application navigation library.

License: Apache License 2.0

Kotlin 100.00%
kotlin android navigation kotlin-library kotlin-multiplatform kotlin-multiplatform-library kotlin-multiplatform-mobile kotlin-multi-platform navigation-architecture-component navigation-component nav jetpack-compose jetpack-navigation

navigation's Introduction

navigation

navigation

Kotlin multi-platform application navigation library that supports Jetpack Compose.

GitHub tag (latest by date)

val navigator = rememberNavigator(initialDestination = "Greeting")

NavigationContainer(navigator) { (destination, _) ->
    when (destination) {
        "Greeting" -> Column {
            Text("Hello")

            Button(onClick = { navigator.push("Farewell") }) {
                Text("Say Goodbye")
            }
        }
        "Farewell" -> Text("Good-bye")
        else -> Text("Unexpected Destination: $destination")
    }
}

Getting Started ๐Ÿ

The library is provided through Repsy.io. Checkout the releases page to get the latest version.
GitHub tag (latest by date)

Repository

repositories {
    maven {
        url = uri("https://repo.repsy.io/mvn/chrynan/public")
    }
}

Dependencies

core

implementation("com.chrynan.navigation:navigation-core:VERSION")

compose

implementation("com.chrynan.navigation:navigation-compose:VERSION")

Usage ๐Ÿ‘จโ€๐Ÿ’ป

Destinations

NavigationDestinations represent the locations within an application that a Navigator can coordinate. They can be of any type and can contain any data that is useful to render the destination UI. A common approach is to use enums or sealed classes to represent the different NavigationDestinations within an application.

enum class AppDestination {

    HOME,
    SEARCH,
    SETTINGS,
    DETAILS
}

Contexts

A NavigationContext is a way of representing complex or nested navigation destinations. A NavigationContext defines its initialDestination and has its own stack of NavigationDestinations associated with it within the internal implementation of a Navigator. This allows there to be a stack of stacks of NavigationDestinations for an application.

enum class MainContext(
    override val initialDestination: AppDestination,
    val title: String,
    val icon: ImageVector
) : NavigationContext<AppDestination> {

    HOME(title = "Home", icon = Icons.Default.Home, initialDestination = AppDestination.Home),

    SEARCH(title = "Search", icon = Icons.Default.Search, initialDestination = AppDestination.Search),

    SETTINGS(title = "Settings", icon = Icons.Default.Settings, initialDestination = AppDestination.Settings)
}

Navigator

A Navigator is used to navigate between navigation contexts and destinations via the convenient push, popContext, and popDestination functions. A Navigator can be obtained via one of the constructor functions or the remember/rememberSavable functions when using Jetpack Compose/Multiplatform Compose.

val navigator = rememberNavigator(initialDestination = AppDestination.HOME)

BackHandler { navigator.popDestination() }

ListItem(modifier = Modifier.clickable { navigator.push(AppDestination.DETAILS) })

NavigationContainer

The NavigationContainer composable provides a convenient way to listening to destination and context state changes and recomposing its content accordingly. Just provide a Navigator instance and a content composable.

@Composable
fun App() {
    val navigator = rememberNavigator(initialDestination = AppDestination.HOME)

    NavigationContainer(navigator = navigator) { (destination, context) ->
        when (destination) {
            AppDestination.HOME -> HomeScreenComposable()
            AppDestination.SEARCH -> SearchScreenComposable()
            AppDestination.SETTINGS -> SettingsScreenComposable()
            AppDestination.DETAILS -> DetailsScreenComposable()
        }
    }
}

Transitions and animations

You have complete control over the composable functions that render the UI of the application and can use the Jetpack Compose library's transition and animation APIs to change between the navigation context and destination UIs. For more fine-grained control, create a custom composable replacing the NavigationContainer that handles transitions properly for your application. Then just listen and react to the Navigator.state changes.

@Composable
fun <Destination : NavigationDestination, Context : NavigationContext<Destination>> MyNavContainer(
    navigator: Navigator<Destination, Context>,
) {
    val context = navigator.store.context.collectAsState()
    val destination = navigator.store.destination.collectAsState()

    // Render UI from context and destination values and apply any transition or animation desired.
}

Best Practices

  • Avoid passing a Navigator to @Composable functions and instead hoist the state.
@Composable
fun App() {
  val navigator = rememberNavigator(...)

  ...

  MyScreen(
    onBackPressed = { navigator.popDestination() },
    onGoToDetails = { navigator.push(AppDestination.Details(it)) }
  )
}
  • Use different Navigators for deep nested navigation. This way each component can retain its own navigation hierarchy and delegate to its encapsulating component via state hoisting if it cannot handle the navigation.
@Composable
fun ParentComponent() {
    val parentNavigator = rememberNavigator(...)

    ...

    ChildComponent(onBack = { parentNavigator.popDestination() })
}

@Composable
fun ChildComponent(
    onBack: () -> Unit
) {
    val childNavigator = rememberNavigator(...)

    BackHandler {
        if (!childNavigator.canPopDestination()) {
            onBack.invoke()
        }
    }
}
  • Use the rememberSavableNavigator function along with serializable navigation destinations and contexts to retain the navigation state between configuration changes.
val navigator = rememberSavableNavigator(
    initialContext = MainContext.HOME,
    destinationSerializer = AppDestination.serializer(),
    contextSerializer = MainContext.serializer()
)
  • Create the Navigator instance outside of @Composable functions to handle navigation outside the user interface flow, such as in Activity lifecycle callbacks.
val navigator = Navigator(initialContext = MainContext.HOME)
  • Utilize side-effects in Jetpack Compose for handling navigation to non-composable UI components, such as starting new Activities or changing Fragments.
NavigationContainer(navigator) { (destination, _) ->
    when (destination) {
        is AppDestination.Details -> LaunchedEffect(destination) {
            context.startActivity(DetailsActivity.newIntent(context, destinatin.id))
        }
    }
}
val navigatorSerializer = Navigator.serializer(destinationSerializer, contextSerializer)

parcelable.encodeToParcel(serializer = navigatorSerializer, value = navigator)
json.encodeToString(serializer = navigatorSerializer, value = navigator)

Documentation ๐Ÿ“ƒ

More detailed documentation is available in the docs folder. The entry point to the documentation can be found here.

Security ๐Ÿ›ก๏ธ

For security vulnerabilities, concerns, or issues, please responsibly disclose the information either by opening a public GitHub Issue or reaching out to the project owner.

Contributing โœ๏ธ

Outside contributions are welcome for this project. Please follow the code of conduct and coding conventions when contributing. If contributing code, please add thorough documents. and tests. Thank you!

Sponsorship โค๏ธ

Support this project by becoming a sponsor of my work! And make sure to give the repository a โญ

License โš–๏ธ

Copyright 2023 chRyNaN

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

   http://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.

navigation's People

Contributors

chrynan avatar codlab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

navigation's Issues

crash on rememberSavableNavigator

Describe the bug
the serialization of the navigator is incorrect. On configuration change, the application crash

To Reproduce
defined model :

@Serializable
enum class Route(val value: String) { LIVE("live"), PLAYLIST("playlist"), SEARCH("search"), REPLAY("replay"), PLAYER("player") }

@Serializable
data class RouteData( val id: Route, val arguments: List<String>, )

call to the function
val navigator = rememberSavableNavigator(initialDestination = allRoutes[Route.LIVE]!!, destinationSerializer =RouteData.serializer())

Expected behavior
Configuration change preserve the navigator state

Stacktrace error
Process: fr.fgognet.antv.debug, PID: 5263 kotlinx.serialization.SerializationException: Class 'RouteData' is not registered for polymorphic serialization in the scope of 'Any'. To be registered automatically, class 'RouteData' has to be '@Serializable', and the base class 'Any' has to be sealed and '@Serializable'. Alternatively, register the serializer for 'RouteData' explicitly in a corresponding SerializersModule. at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:102) at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:114) at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:109) at kotlinx.serialization.internal.AbstractPolymorphicSerializer.serialize(AbstractPolymorphicSerializer.kt:32) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80) at com.chrynan.navigation.NavigationEvent$Forward$Destination.write$Self(NavigationEvent.kt:102) at com.chrynan.navigation.NavigationEvent$Forward$Destination$$serializer.serialize(NavigationEvent.kt:102) at com.chrynan.navigation.NavigationEvent$Forward$Destination$$serializer.serialize(NavigationEvent.kt:102) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80) at kotlinx.serialization.internal.AbstractPolymorphicSerializer.serialize(AbstractPolymorphicSerializer.kt:35) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at kotlinx.serialization.internal.NullableSerializer.serialize(NullableSerializer.kt:23) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at com.chrynan.navigation.NavigationStateSerializer.serialize(NavigationState.kt:142) at com.chrynan.navigation.NavigationStateSerializer.serialize(NavigationState.kt:131) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at com.chrynan.navigation.NavigationStateStoreSerializer.serialize(NavigationStateStore.kt:184) at com.chrynan.navigation.NavigationStateStoreSerializer.serialize(NavigationStateStore.kt:164) at kotlinx.serialization.encoding.Encoder$DefaultImpls.encodeSerializableValue(Encoding.kt:279) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableValue(AbstractEncoder.kt:18) at kotlinx.serialization.encoding.AbstractEncoder.encodeSerializableElement(AbstractEncoder.kt:80) at com.chrynan.navigation.NavigatorSnapshot.write$Self(Navigator.kt:190) at com.chrynan.navigation.NavigatorSnapshot$$serializer.serialize(Navigator.kt:190) at com.chrynan.navigation.NavigatorSnapshot$$serializer.serialize(Navigator.kt:190)

MinSdk to 21

Jetpack Compose min sdk version is 21 and this library should also support min sdk version 21

The library is also missing functions like push and pop , I created my own push by using duplicate Strategy of Add to Stack

Could you please fix this fast , My app is currntnly increasing its min SDK version to be able to use this library

[QUESTION] how to clear stack navigating to specific destination

@chRyNaN

I want to navigate to a destination but have nothing in the back stack, so user can't go back !

I don't know how to do it at version 0.10.0, Maybe it can be done using context (i don't know how) but it would be hard compared to this

basically I would like to do resetTo(destination)

Use case

Account Screen -> User signs out (set initial destination to Sign in Screen)
Sign In Screen -> User signs in (set initial destination to Account Screen)
Sign Up Screen -> User signs up (set initial destination to Account Screen or Sign in Screen if he's not signed in)

Tries

router.push(SingleNavigationContext<AccountNavigation>(AccountNavigation.Account))

SingleNavigationContext's constructor is internal

CRITICAL BUG using java.time.Instant which is not available in API below 26

Here are two exceptions , I updated the app with the library to min Sdk 21 and my users are getting this exception , I found this using Firebase Crashlytics

Since
https://stackoverflow.com/questions/52510370/java-lang-noclassdeffounderror-failed-resolution-of-ljava-time-localdate-erro

Please instead of using Kotlinx date time library to get the current time Millis , Use the expect actual functions , Please update the library as soon as possible , We have a lot of users who have this bug

Caused by java.lang.ClassNotFoundException: Didn't find class "java.time.Instant" on path: DexPathList[[zip file "/data/app/com.wakaztahir.mindnode-1/base.apk", zip file "/data/app/com.wakaztahir.mindnode-1/split_config.es.apk", zip file "/data/app/com.wakaztahir.mindnode-1/split_config.xhdpi.apk"],nativeLibraryDirectories=[/data/app/com.wakaztahir.mindnode-1/lib/arm, /system/lib, /vendor/lib]]
       at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:380)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
       at kotlinx.datetime.Instant.<clinit>(Instant.kt:96)
       at kotlinx.datetime.Clock$System.now(Clock.kt:25)
       at com.chrynan.navigation.NavigationEvent$Forward$Destination.<init>(NavigationEvent.kt:105)
       at com.chrynan.navigation.NavigatorKt.goTo(Navigator.kt:107)
       at com.wakaztahir.mindnode.ui.components.main.MainScreenKt$MainScreen$1$1$1$2.invoke(MainScreen.kt:116)
       at com.wakaztahir.mindnode.ui.components.main.MainScreenKt$MainScreen$1$1$1$2.invoke(MainScreen.kt:102)
       at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$1$2.invoke-k-4lQ0M(Clickable.kt:167)
       at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$1$2.invoke(Clickable.kt:156)
       at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1.invokeSuspend(TapGestureDetector.kt:255)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:177)
       at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
       at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:566)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.dispatchPointerEvent(SuspendingPointerInputFilter.kt:456)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:469)
       at androidx.compose.ui.node.BackwardsCompatNode.onPointerEvent-H0pRuoY(BackwardsCompatNode.kt:374)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:314)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:183)
       at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:102)
       at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:98)
       at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1361)
       at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1307)
       at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:1246)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:609)
       at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1895)
       at android.app.Activity.dispatchTouchEvent(Activity.java:3241)
       at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:571)
       at android.view.View.dispatchPointerEvent(View.java:11009)
       at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5155)
       at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5007)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4532)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4585)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4551)
       at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4684)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4559)
       at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4741)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4532)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4585)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4551)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4559)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4532)
       at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7092)
       at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7024)
       at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6985)
       at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7202)
       at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:323)
       at android.os.Looper.loop(Looper.java:136)
       at android.app.ActivityThread.main(ActivityThread.java:6776)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)
Fatal Exception: java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Instant;
       at kotlinx.datetime.Instant.<clinit>(Instant.kt:96)
       at kotlinx.datetime.Clock$System.now(Clock.kt:25)
       at com.chrynan.navigation.NavigationEvent$Forward$Destination.<init>(NavigationEvent.kt:105)
       at com.chrynan.navigation.NavigatorKt.goTo(Navigator.kt:107)
       at com.wakaztahir.mindnode.ui.components.main.MainScreenKt$MainScreen$1$1$1$2.invoke(MainScreen.kt:116)
       at com.wakaztahir.mindnode.ui.components.main.MainScreenKt$MainScreen$1$1$1$2.invoke(MainScreen.kt:102)
       at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$1$2.invoke-k-4lQ0M(Clickable.kt:167)
       at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$1$2.invoke(Clickable.kt:156)
       at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1.invokeSuspend(TapGestureDetector.kt:255)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
       at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:177)
       at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
       at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
       at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:566)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.dispatchPointerEvent(SuspendingPointerInputFilter.kt:456)
       at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:469)
       at androidx.compose.ui.node.BackwardsCompatNode.onPointerEvent-H0pRuoY(BackwardsCompatNode.kt:374)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:314)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:301)
       at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:183)
       at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:102)
       at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:98)
       at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1361)
       at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1307)
       at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:1246)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2864)
       at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2549)
       at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:609)
       at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1895)
       at android.app.Activity.dispatchTouchEvent(Activity.java:3241)
       at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:571)
       at android.view.View.dispatchPointerEvent(View.java:11009)
       at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:5155)
       at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5007)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4532)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4585)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4551)
       at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4684)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4559)
       at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4741)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4532)
       at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4585)
       at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4551)
       at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4559)
       at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4532)
       at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:7092)
       at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:7024)
       at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6985)
       at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:7202)
       at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
       at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
       at android.os.MessageQueue.next(MessageQueue.java:323)
       at android.os.Looper.loop(Looper.java:136)
       at android.app.ActivityThread.main(ActivityThread.java:6776)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1496)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1386)

Document Nested Navigation

I love the library for its simplicity , I hope it keeps that with its updates but there's very little documentation of nested navigation

New API in latest version

I have upgraded this library to the 0.8.0 version. Now the API StackDuplicateContentStrategy is gone. I don't know how to clear my stack before navigate to a specific destination. Please help!!

Proposing a minimum version of Android set to 23

Is your feature request related to a problem? Please describe.
Using this library currently in an app with minimal support of 23

Describe the solution you'd like
Bumping the lib to 0.7.0 while supporting more versions

Describe alternatives you've considered
N/A

Additional context
N/A

Overload resolution ambiguity for goTo function

Overload resolution ambiguity. All these functions match. in IDE:

public fun <Destination : NavigationDestination /* = Any */, Context : NavigationContext<TypeVariable(Destination)>> Navigator<TypeVariable(Destination), TypeVariable(Context)>.goTo(destination: TypeVariable(Destination)): Boolean defined in com.chrynan.navigation
public fun <Destination : Any, Context : NavigationContext<TypeVariable(Destination)>> Navigator<TypeVariable(Destination), TypeVariable(Context)>.goTo(destination: TypeVariable(Destination)): Unit defined in com.chrynan.navigation

also to use dispatch , the constructors for Forward Event or Backward Event Destination are internal or private , so dispatch can't be used

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.