Skip to content

Releases: raamcosta/compose-destinations

1.2.0-beta - Type-safe navigating for result 👀

29 Jan 15:58
Compare
Choose a tag to compare

API CHANGES

  • You can now pass arguments back in a type-safe and simple way!
@Destination(style = DestinationStyle.Dialog::class)
@Composable
fun SomeConfirmationDialog(
    resultBackNavigator: ResultBackNavigator<Boolean>
) {
    // ... after some positive click button:
    resultBackNavigator.navigateBack(result = true)
}

@Destination
@Composable
fun OtherScreen(
    resultRecipient: ResultRecipient<SomeConfirmationDialogDestination, Boolean>
) {
    resultRecipient.onResult { confirmed ->
        // called after SomeConfirmationDialog calls `navigateBack` receiving the result passed in
    }
}

Read more about it here

FIXES

  • Fixed an issue when a specific parameter type of an annotated Composable required opt-in and the @Optin was used. The generated Destination was missing that same OptIn.

1.1.6-beta

22 Jan 15:58
Compare
Choose a tag to compare

API Changes

  • startDestination of both DestinationsNavHost and NavGraph was renamed to startRoute and it's now of type Route (which is an interface only implemented by Destination and NavGraph). This is because NavGraph is also a valid starting point for a NavGraph. So now, Route is used so that you can pass a Destination like before or a NavGraph.
  • RouteIdentified was renamed to Route and is now a sealed interface only implemented by NavGraphSpec and DestinationSpec (as seen above).

1.1.5-beta

18 Jan 19:48
Compare
Choose a tag to compare

1.1.4-beta - Small fix

13 Jan 22:21
Compare
Choose a tag to compare

Changes

1.1.3-beta

08 Jan 18:04
Compare
Choose a tag to compare

Small improvements

  • DestinationsNavigator received small API changes for clear and pop back stacks. You won't be able to pass a Direction to these anymore. A Direction in Compose Destinations is an interface meant only to navigate to a screen since it contains a route with all the arguments. These methods now receive a RouteIdentified instead which are only implemented by the Destination and NavGraph.
    With this change, it is now clear in the type system what kind of "route" you pass to each method (yet another reason to use Compose Destinations 🙌 )

  • Documentation updates

  • Compiler error messages for invalid destinations setup improved

  • Fixed a rare issue that could happen when passing a Parcelable argument with a custom @NavTypeSerializer for it.

1.1.2-beta - Internal improvements

03 Jan 00:58
Compare
Choose a tag to compare

Internal improvements

  • Fixed issues with vanilla navigation compose string arguments:
    • Empty strings
    • Strings already encoded for Uri

1.1.1-beta

29 Dec 23:05
Compare
Choose a tag to compare

Parcelable / Serializable navigation arguments improvements

  • Parcelable/Serializable navigation arguments are now queriable from SavedStateHandle/NavBackStackEntry by get<Parcelable> / getParcelable respectively (before you could only get them via the generated Destination - this will still be the preferred way since you don't need to use the string keys, but you now have the option).

  • You can now optionally define how you want your Parcelable/Serializable navigation arguments to be represented in the navigation route. This enables deep linking into a screen containing a mandatory navigation argument of this type.

Example:
data class Things(
    val thingOne: String,
    val thingTwo: String
)

@NavTypeSerializer
class ThingsNavTypeSerializer : ParcelableNavTypeSerializer<Things> {

    override fun toRouteString(value: Things): String {
        return "${value.thingOne};${value.thingTwo}"
    }

    override fun fromRouteString(routeStr: String, jClass: Class<out Things>): Things {
        return routeStr.split(";").run {
            Things(get(0), get(1))
        }
    }
}

Notes:

  • After this, you can now use a deep link passing "thingOne;thingTwo" in the URL and the instance of Things is created from the fromRouteString method.
  • Notice the @NavTypeSerializer and the superclass you need to implement ParcelableNavTypeSerializer<YOUR_NAV_ARG_TYPE> .
    If your navigation argument is Serializable, then your class should implement SerializableNavTypeSerializer<YOUR_NAV_ARG_TYPE> instead.
  • Main reason to do this is if you want to have a deep link to this destination sending this parameter. Otherwise, you don't need to do this: Compose Destinations has a default ParcelableNavTypeSerializer it will use behind the scenes.

GENERATED CODE PACKAGE

  • By default all generated code will be inside a package composed of the common part of all the @Destination annotated functions.
    For example:

Destination Screen A:
com.yourapp.ui.screens.featureA.ScreenA

Destination Screen B:
com.yourapp.ui.screens.featureB.ScreenB

In this case, the common part would be com.yourapp.ui.screens, so this would be the base package for the generated code.

  • Ability to override the above default with a fixed package name in build.gradle of your module:
ksp {
    arg("compose-destinations.codeGenPackageName", "your.preferred.packagename")
}

Note: Regardless of if you go with the default behavior or define your package name, destinations will be in PACKAGE_NAME.destinations.

API CHANGES

  • Routed interface was renamed to Direction. This is the instance that gets returned to you when you invoke a Destination. You can then pass it to the DestinationsNavigator or call .route to navigate to this Direction.

1.0.2-beta

20 Dec 23:36
Compare
Choose a tag to compare

API CHANGES

Parameters accessible when manually calling specific screen Composables

With this version, the way to access parameters inside the trailing lambda has changed.
Now, they are accessible through the receiver of the lambda. This allows lazy evaluation of parameters
and allows us to expose more of them (ex: DestinationsNavigator) without polluting your code or hurting performance if you don't use them.
It also allowed us to remove APIs like composableWithNoArgs since now nav args are lazily prepared, and so, there is no reason for these APIs anymore.

Before
composable(SomeScreenDestination) { navArgs, navBackStackEntry ->
    SomeScreen(
        arg1 = navArgs.arg1,
        navigator = DestinationsNavController(navController, navBackStackEntry),
        backStackEntry = navBackStackEntry
    )
}
After
composable(SomeScreenDestination) { //this: DestinationScope<SomeScreenDestination.NavArgs>
    SomeScreen(
        arg1 = navArgs.arg1,
        navigator = destinationsNavigator,
        backStackEntry = navBackStackEntry
    )
}

Animations Core

The call to rememberAnimatedNavHostEngine changed slightly. Mostly related to overriding defaults in nested nav graphs.

Before
val navHostEngine = rememberAnimatedNavHostEngine(
    defaultAnimationParams = DefaultAnimationParams(
        contentAlignment = Alignment.TopCenter,
    ), //others are default values which means no animations by default
) { navGraph ->
    when(navGraph) {
        NavGraphs.settings -> NavGraphDefaultAnimationParams(
            enterTransition = { fadeIn(animationSpec = tween(2000)) },
            exitTransition = { fadeOut(animationSpec = tween(2000)) }
        )
        
        NavGraphs.someOtherGraph -> NavGraphDefaultAnimationParams(
                enterTransition = { fadeIn(animationSpec = tween(700)) },
                exitTransition = { fadeOut(animationSpec = tween(700)) }
        )
        
        else -> NavGraphDefaultAnimationParams()
    }
}
After
val navHostEngine = rememberAnimatedNavHostEngine(
    navHostContentAlignment = Alignment.TopCenter,
    rootDefaultAnimations = RootNavGraphDefaultAnimations(), //default values means no animations by default
    defaultAnimationsForNestedNavGraph = mapOf(
        NavGraphs.settings to NestedNavGraphDefaultAnimations(
            enterTransition = { fadeIn(animationSpec = tween(2000)) },
            exitTransition = { fadeOut(animationSpec = tween(2000)) }
        ),
        NavGraphs.otherNestedGraph to NestedNavGraphDefaultAnimations.ACCOMPANIST_FADING
    ) // all other nav graphs not specified in this map, will get their animations from the `rootDefaultAnimations` above.
)

1.0.0-beta - Usability and internals improved 🙌

12 Dec 16:01
Compare
Choose a tag to compare

NEW FEATURES:

  • Support Parcelable, Serializable and Enums navigation arguments 🎉
  • Support to disable NavGraphs generation and create your own to have more control on some less common scenarios. This enables multiple DestinationsNavHost since you can now declare multiple top-level NavGraphs.
  • Support to manually call specific Destination Composables enabling passing NavHost level components to those specific screens.
  • Added extension functions of NavGraphBuilder to make it possible to use original NavHost Composables instead of DestinationsNavHost.

SETUP CHANGES:

  • Jetpack Compose Navigation is now a transitive dependency of this library. This means you don't need to add that dependency in your gradle build if you include this library.
  • Accompanist Navigation-Animation and Accompanist Navigation-Material are now also transitive dependencies of the "animations-core".
    So if you plan to have animated transitions between screens or Bottom Sheet screens, you don't need to include those dependencies.
    Simply replace the "normal core" with "animations-core". Check the README setup section.

API CHANGES:

  • DestinationsNavHost now has a mandatory parameter: NavGraph. This is partly due to the feature of disabling NavGraphs generation (which means we can't always know there is a NavGraph with the name "root") but also because this is more explicit what navigation graph is being used to populate that DestinationsNavHost.
  • Animations-core contains a AnimatedNavHostEngine which you'll need to get calling rememberAnimatedNavHostEngine and pass to DestinationsNavHost. The rememberAnimatedNavHostEngine call accepts a DefaultAnimationParams for animations that will be applied to all screen transitions (that don't override it) and accepts a lambda that allows you to override the default for specific nested navigation graphs (also overridable by screen via style parameter of Destination annotation).

0.9.4-beta

07 Nov 18:20
Compare
Choose a tag to compare

Done

  • Changes to accommodate accompanist 0.21.2-beta

API changes

  • Due to changes in accompanist navigation animation dependency, we have to define animations in a slightly different way:

BEFORE

object SomeScreenDestinationAnimations : AnimatedDestinationStyle {

    override fun AnimatedContentScope<String>.enterTransition(
        initial: Destination?,
        target: Destination?
    ): EnterTransition? {

        return when (initial) {
            SomeOtherScreenDestination ->
                slideInHorizontally(
                    initialOffsetX = { 1000 },
                    animationSpec = tween(700)
                )
            else -> null
        }
    }

//...

AFTER

object SomeScreenDestinationAnimations : DestinationStyle.Animated {

    override fun AnimatedContentScope<NavBackStackEntry>.enterTransition(): EnterTransition? {

        return when (initialState.navDestination) {
            SomeOtherScreenDestination ->
                slideInHorizontally(
                    initialOffsetX = { 1000 },
                    animationSpec = tween(700)
                )
            else -> null
        }
    }

//...

Notes:

  • Changed supertype interface from AnimatedDestinationStyle to DestinationStyle.Animated
  • Methods signature reciver changed to AnimatedContentScope<NavBackStackEntry>
  • Methods signature don't have parameters; you can get the initial and target destinations by initialState.navDestination and targetState.navDestination
  • You can check a commit to a file on the sample app where made these changes here

Known compatibility with

  • androidx.navigation:navigation-compose:2.4.0-beta02
  • androidx.compose.ui:ui:1.1.0-beta02
  • com.google.accompanist:accompanist-navigation-material:0.21.2-beta
  • com.google.accompanist:accompanist-navigation-animation:0.21.2-beta