From 8999d02a4a8ff33dd8ebf39cd6f7a52677a59dff Mon Sep 17 00:00:00 2001 From: Jay Ohms Date: Mon, 2 Dec 2024 09:49:49 -0500 Subject: [PATCH] Fix dialog fragment navigation issues. This fixes regressions when refactoring the Navigator to use a single instance across a navigation host. The topmost DialogFragment is not available from the NavigatorHost.childFragmentManager, since it is added directly to the Activity's window instead. --- .../fragments/HotwireBottomSheetFragment.kt | 6 +++++ .../hotwire/navigation/navigator/Navigator.kt | 23 +++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireBottomSheetFragment.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireBottomSheetFragment.kt index 5b0aa36..82a565a 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireBottomSheetFragment.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/fragments/HotwireBottomSheetFragment.kt @@ -33,6 +33,7 @@ abstract class HotwireBottomSheetFragment : BottomSheetDialogFragment(), override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + navigator.currentDialogDestination = this delegate.onViewCreated() if (shouldObserveTitleChanges()) { @@ -43,6 +44,11 @@ abstract class HotwireBottomSheetFragment : BottomSheetDialogFragment(), } } + override fun onDestroyView() { + navigator.currentDialogDestination = null + super.onDestroyView() + } + /** * This is marked `final` to prevent further use, as it's now deprecated in * AndroidX's Fragment implementation. diff --git a/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt b/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt index 0f65180..323f429 100644 --- a/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt +++ b/navigation-fragments/src/main/java/dev/hotwire/navigation/navigator/Navigator.kt @@ -28,7 +28,14 @@ class Navigator( private val navController = host.navController /** - * Retrieves the currently active [HotwireDestination] on the backstack. + * The currently active dialog destination on the backstack if present, otherwise null. + * Dialog fragments are added to the Activity window and are not added directly to the + * [NavigatorHost] childFragmentManager. + */ + internal var currentDialogDestination: HotwireDialogDestination? = null + + /** + * Retrieves the currently active (fullscreen) [HotwireDestination] on the backstack. */ val currentDestination: HotwireDestination get() = host.childFragmentManager.primaryNavigationFragment as HotwireDestination? @@ -85,9 +92,9 @@ class Navigator( */ fun pop() { navigateWhenReady { - val currentFragment = currentDestination.fragment - if (currentFragment is HotwireDialogDestination) { - currentFragment.closeDialog() + val currentDialogDestination = currentDialogDestination + if (currentDialogDestination != null) { + currentDialogDestination.closeDialog() } else { navController.popBackStack() } @@ -162,10 +169,8 @@ class Navigator( } navigateWhenReady { - val currentFragment = currentDestination.fragment - if (currentFragment is HotwireDialogDestination) { - currentFragment.closeDialog() - } + // If a dialog is on top of the backstack, close it first + currentDialogDestination?.closeDialog() navController.popBackStack(navController.graph.startDestinationId, false) onCleared() @@ -264,7 +269,7 @@ class Navigator( ) navigateWhenReady { - val isDialog = currentDestination.fragment is HotwireDialogDestination + val isDialog = currentDialogDestination != null if (isDialog) { // Pop the backstack before sending the modal result, since the // underlying fragment is still active and will receive the