diff --git a/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavGraphBuilder.kt b/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavGraphBuilder.kt index 3148c011..5c733119 100644 --- a/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavGraphBuilder.kt +++ b/turbo/src/main/kotlin/dev/hotwire/turbo/nav/TurboNavGraphBuilder.kt @@ -1,7 +1,6 @@ package dev.hotwire.turbo.nav import android.net.Uri -import androidx.annotation.IdRes import androidx.appcompat.app.AppCompatActivity import androidx.core.net.toUri import androidx.fragment.app.DialogFragment @@ -13,6 +12,7 @@ import androidx.navigation.fragment.FragmentNavigator import androidx.navigation.fragment.FragmentNavigatorDestinationBuilder import dev.hotwire.turbo.config.TurboPathConfiguration import dev.hotwire.turbo.config.uri +import java.util.* import kotlin.reflect.KClass import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.isSubclassOf @@ -23,13 +23,13 @@ internal class TurboNavGraphBuilder( private val pathConfiguration: TurboPathConfiguration ) { private data class ActivityDestination( - val id: Int, + val route: String, val uri: Uri, val kClass: KClass ) private data class FragmentDestination( - val id: Int, + val route: String, val uri: Uri, val kClass: KClass ) @@ -38,11 +38,11 @@ internal class TurboNavGraphBuilder( registeredActivities: List>, registeredFragments: List> ): NavGraph { - var currentId = 1 + var currentRoute = 1 val activityDestinations = registeredActivities.map { ActivityDestination( - id = currentId.also { currentId++ }, + route = currentRoute.also { currentRoute++ }.toString(), uri = it.turboAnnotation().uri.toUri(), kClass = it ) @@ -50,7 +50,7 @@ internal class TurboNavGraphBuilder( val fragmentDestinations = registeredFragments.map { FragmentDestination( - id = currentId.also { currentId++ }, + route = currentRoute.also { currentRoute++ }.toString(), uri = it.turboAnnotation().uri.toUri(), kClass = it ) @@ -59,7 +59,7 @@ internal class TurboNavGraphBuilder( return createGraph( activityDestinations, fragmentDestinations, - fragmentDestinations.startDestination().id + fragmentDestinations.startDestination().route ) } @@ -67,24 +67,24 @@ internal class TurboNavGraphBuilder( private fun createGraph( activityDestinations: List, fragmentDestinations: List, - startDestinationId: Int + startDestinationRoute: String ): NavGraph { - return navController.createGraph(startDestination = startDestinationId) { + return navController.createGraph(startDestination = startDestinationRoute) { activityDestinations.forEach { - activity(it.id) { + activity(it.route) { activityClass = it.kClass deepLink(it.uri.toString()) } } fragmentDestinations.withoutDialogs().forEach { - fragment(it.id, it.kClass) { + fragment(it.route, it.kClass) { deepLink(it.uri.toString()) } } fragmentDestinations.dialogs().forEach { - dialog(it.id, it.kClass as KClass) { + dialog(it.route, it.kClass as KClass) { deepLink(it.uri.toString()) } } @@ -92,6 +92,15 @@ internal class TurboNavGraphBuilder( argument("location") { defaultValue = startLocation } + + // Use a random value to represent a unique instance of the graph, so the + // graph is unique every time. This lets it be reset/recreated on-demand from + // `TurboSessionNavHostFragment.reset()`. Replacing an existing nav graph with + // an identical one would bypass recreating the nav stack from scratch in + // `NavController.setGraph()`. + argument("unique_instance") { + defaultValue = UUID.randomUUID().toString() + } } } @@ -100,7 +109,7 @@ internal class TurboNavGraphBuilder( } private fun List.withoutDialogs(): List { - return minus(dialogs()) + return minus(dialogs().toSet()) } private fun List.startDestination(): FragmentDestination { @@ -118,26 +127,26 @@ internal class TurboNavGraphBuilder( // Modified from AndroidX FragmentNavigatorDestinationBuilder extensions private inline fun NavGraphBuilder.fragment( - @IdRes id: Int, + route: String, fragmentClass: KClass, builder: FragmentNavigatorDestinationBuilder.() -> Unit ) = destination( FragmentNavigatorDestinationBuilder( provider[FragmentNavigator::class], - id, + route, fragmentClass ).apply(builder) ) // Modified from AndroidX DialogFragmentNavigatorDestinationBuilder extensions private inline fun NavGraphBuilder.dialog( - @IdRes id: Int, + route: String, fragmentClass: KClass, builder: DialogFragmentNavigatorDestinationBuilder.() -> Unit ) = destination( DialogFragmentNavigatorDestinationBuilder( provider[DialogFragmentNavigator::class], - id, + route, fragmentClass ).apply(builder) )