diff --git a/apps/mobile/src/features/workspace/AndroidWorkspaceNavigation.android.tsx b/apps/mobile/src/features/workspace/AndroidWorkspaceNavigation.android.tsx index addf9718b09dd..734319b000b55 100644 --- a/apps/mobile/src/features/workspace/AndroidWorkspaceNavigation.android.tsx +++ b/apps/mobile/src/features/workspace/AndroidWorkspaceNavigation.android.tsx @@ -1,5 +1,5 @@ import { requireNativeView } from "expo"; -import { CommonActions, useNavigation } from "@react-navigation/native"; +import { useNavigation } from "@react-navigation/native"; import { androidWorkspaceNavigationState } from "../../lib/android-workspace-navigation"; import { Keyboard, @@ -16,6 +16,7 @@ import { androidWorkspaceNavigationColors } from "./android-workspace-navigation import { useAppearancePreferences } from "../settings/appearance/AppearancePreferencesProvider"; import { useWorkspaceTabs } from "./WorkspaceTabsContext"; import type { WorkspaceTab } from "./workspace-tabs-state"; +import { resetAndroidWorkspace } from "./useAndroidWorkspaceSelection"; export const ANDROID_WORKSPACE_RAIL_WIDTH = 80; @@ -81,9 +82,7 @@ export function AndroidWorkspaceNavigation(props: { const tab = event.nativeEvent.tab; if (tab !== workspace.state.selectedTab) { workspace.dispatch({ type: "select", tab }); - navigation.dispatch((state) => - CommonActions.reset(androidWorkspaceNavigationState(state)), - ); + resetAndroidWorkspace(navigation, (state) => androidWorkspaceNavigationState(state)); } props.onSelect?.(); }} diff --git a/apps/mobile/src/features/workspace/useAndroidWorkspaceSelection.ts b/apps/mobile/src/features/workspace/useAndroidWorkspaceSelection.ts index 46f49e9c071e5..76e5c81e5e034 100644 --- a/apps/mobile/src/features/workspace/useAndroidWorkspaceSelection.ts +++ b/apps/mobile/src/features/workspace/useAndroidWorkspaceSelection.ts @@ -1,4 +1,9 @@ -import { CommonActions, useNavigation } from "@react-navigation/native"; +import { + CommonActions, + useNavigation, + type NavigationAction, + type NavigationState, +} from "@react-navigation/native"; import { useCallback } from "react"; import { Keyboard } from "react-native"; import { @@ -7,6 +12,27 @@ import { } from "../../lib/android-workspace-navigation"; import { useWorkspaceTabs } from "./WorkspaceTabsContext"; +/** + * The sidebar and navigation rail sit in the root layout, where a state-callback dispatch goes + * to the focused navigator. While a nested flow such as New thread has focus, that navigator has + * no Home or Thread route and drops the reset, so address the root stack by its key. + */ +interface WorkspaceNavigation { + getParent(): WorkspaceNavigation | undefined; + getState(): NavigationState | undefined; + dispatch(action: NavigationAction): void; +} + +export function resetAndroidWorkspace( + navigation: WorkspaceNavigation, + next: (state: NavigationState) => Parameters[0], +) { + let root = navigation; + for (let parent = root.getParent(); parent; parent = parent.getParent()) root = parent; + const state = root.getState(); + if (state) root.dispatch({ ...CommonActions.reset(next(state)), target: state.key }); +} + export function useAndroidWorkspaceSelection() { const navigation = useNavigation(); const dispatch = useWorkspaceTabs()?.dispatch; @@ -20,8 +46,8 @@ export function useAndroidWorkspaceSelection() { type: "select", tab: destination.name === "Thread" ? "threads" : "pullRequests", }); - navigation.dispatch((state) => - CommonActions.reset(androidWorkspaceNavigationState(state, destination, reviewers)), + resetAndroidWorkspace(navigation, (state) => + androidWorkspaceNavigationState(state, destination, reviewers), ); }, [navigation, dispatch],