11package dev.hotwire.turbo.nav
22
33import android.net.Uri
4- import androidx.annotation.IdRes
54import androidx.appcompat.app.AppCompatActivity
65import androidx.core.net.toUri
76import androidx.fragment.app.DialogFragment
@@ -13,6 +12,7 @@ import androidx.navigation.fragment.FragmentNavigator
1312import androidx.navigation.fragment.FragmentNavigatorDestinationBuilder
1413import dev.hotwire.turbo.config.TurboPathConfiguration
1514import dev.hotwire.turbo.config.uri
15+ import java.util.*
1616import kotlin.reflect.KClass
1717import kotlin.reflect.full.findAnnotation
1818import kotlin.reflect.full.isSubclassOf
@@ -23,13 +23,13 @@ internal class TurboNavGraphBuilder(
2323 private val pathConfiguration : TurboPathConfiguration
2424) {
2525 private data class ActivityDestination (
26- val id : Int ,
26+ val route : String ,
2727 val uri : Uri ,
2828 val kClass : KClass <out AppCompatActivity >
2929 )
3030
3131 private data class FragmentDestination (
32- val id : Int ,
32+ val route : String ,
3333 val uri : Uri ,
3434 val kClass : KClass <out Fragment >
3535 )
@@ -38,19 +38,19 @@ internal class TurboNavGraphBuilder(
3838 registeredActivities : List <KClass <out AppCompatActivity >>,
3939 registeredFragments : List <KClass <out Fragment >>
4040 ): NavGraph {
41- var currentId = 1
41+ var currentRoute = 1
4242
4343 val activityDestinations = registeredActivities.map {
4444 ActivityDestination (
45- id = currentId .also { currentId ++ },
45+ route = currentRoute .also { currentRoute ++ }.toString() ,
4646 uri = it.turboAnnotation().uri.toUri(),
4747 kClass = it
4848 )
4949 }
5050
5151 val fragmentDestinations = registeredFragments.map {
5252 FragmentDestination (
53- id = currentId .also { currentId ++ },
53+ route = currentRoute .also { currentRoute ++ }.toString() ,
5454 uri = it.turboAnnotation().uri.toUri(),
5555 kClass = it
5656 )
@@ -59,39 +59,48 @@ internal class TurboNavGraphBuilder(
5959 return createGraph(
6060 activityDestinations,
6161 fragmentDestinations,
62- fragmentDestinations.startDestination().id
62+ fragmentDestinations.startDestination().route
6363 )
6464 }
6565
6666 @Suppress(" UNCHECKED_CAST" )
6767 private fun createGraph (
6868 activityDestinations : List <ActivityDestination >,
6969 fragmentDestinations : List <FragmentDestination >,
70- startDestinationId : Int
70+ startDestinationRoute : String
7171 ): NavGraph {
72- return navController.createGraph(startDestination = startDestinationId ) {
72+ return navController.createGraph(startDestination = startDestinationRoute ) {
7373 activityDestinations.forEach {
74- activity(it.id ) {
74+ activity(it.route ) {
7575 activityClass = it.kClass
7676 deepLink(it.uri.toString())
7777 }
7878 }
7979
8080 fragmentDestinations.withoutDialogs().forEach {
81- fragment(it.id , it.kClass) {
81+ fragment(it.route , it.kClass) {
8282 deepLink(it.uri.toString())
8383 }
8484 }
8585
8686 fragmentDestinations.dialogs().forEach {
87- dialog(it.id , it.kClass as KClass <out DialogFragment >) {
87+ dialog(it.route , it.kClass as KClass <out DialogFragment >) {
8888 deepLink(it.uri.toString())
8989 }
9090 }
9191
9292 argument(" location" ) {
9393 defaultValue = startLocation
9494 }
95+
96+ // Use a random value to represent a unique instance of the graph, so the
97+ // graph is unique every time. This lets it be reset/recreated on-demand from
98+ // `TurboSessionNavHostFragment.reset()`. Replacing an existing nav graph with
99+ // an identical one would bypass recreating the nav stack from scratch in
100+ // `NavController.setGraph()`.
101+ argument(" unique_instance" ) {
102+ defaultValue = UUID .randomUUID().toString()
103+ }
95104 }
96105 }
97106
@@ -100,7 +109,7 @@ internal class TurboNavGraphBuilder(
100109 }
101110
102111 private fun List<FragmentDestination>.withoutDialogs (): List <FragmentDestination > {
103- return minus(dialogs())
112+ return minus(dialogs().toSet() )
104113 }
105114
106115 private fun List<FragmentDestination>.startDestination (): FragmentDestination {
@@ -118,26 +127,26 @@ internal class TurboNavGraphBuilder(
118127
119128 // Modified from AndroidX FragmentNavigatorDestinationBuilder extensions
120129 private inline fun NavGraphBuilder.fragment (
121- @IdRes id : Int ,
130+ route : String ,
122131 fragmentClass : KClass <out Fragment >,
123132 builder : FragmentNavigatorDestinationBuilder .() -> Unit
124133 ) = destination(
125134 FragmentNavigatorDestinationBuilder (
126135 provider[FragmentNavigator ::class ],
127- id ,
136+ route ,
128137 fragmentClass
129138 ).apply (builder)
130139 )
131140
132141 // Modified from AndroidX DialogFragmentNavigatorDestinationBuilder extensions
133142 private inline fun NavGraphBuilder.dialog (
134- @IdRes id : Int ,
143+ route : String ,
135144 fragmentClass : KClass <out DialogFragment >,
136145 builder : DialogFragmentNavigatorDestinationBuilder .() -> Unit
137146 ) = destination(
138147 DialogFragmentNavigatorDestinationBuilder (
139148 provider[DialogFragmentNavigator ::class ],
140- id ,
149+ route ,
141150 fragmentClass
142151 ).apply (builder)
143152 )
0 commit comments