@@ -6,24 +6,42 @@ import navigationRef from '@libs/Navigation/navigationRef';
66import { isPendingDeletePolicy , shouldShowPolicy as shouldShowPolicyUtil } from '@libs/PolicyUtils' ;
77import NAVIGATORS from '@src/NAVIGATORS' ;
88import ROUTES from '@src/ROUTES' ;
9+ import type { Route } from '@src/ROUTES' ;
910import SCREENS from '@src/SCREENS' ;
1011import type { Domain , Policy } from '@src/types/onyx' ;
1112import getActiveTabName from './getActiveTabName' ;
13+ import getPathFromState from './getPathFromState' ;
1214
1315type RouteType = NavigationState [ 'routes' ] [ number ] | PartialState < NavigationState > [ 'routes' ] [ number ] ;
1416
17+ /**
18+ * Wraps a leaf navigation state in successive ancestor navigators (outermost first).
19+ * Used to reconstruct the linking-config hierarchy that `getPathFromState` walks when
20+ * resolving a state subtree to a URL.
21+ */
22+ function wrapStateInNavigators ( state : PartialState < NavigationState > , navigators : readonly string [ ] ) : PartialState < NavigationState > {
23+ return navigators . reduceRight < PartialState < NavigationState > > ( ( acc , name ) => ( { routes : [ { name, state : acc } ] , index : 0 } ) , state ) ;
24+ }
25+
1526type Params = {
1627 currentUserLogin ?: string ;
1728 shouldUseNarrowLayout : boolean ;
1829 policy ?: Policy ;
1930 domain ?: Domain ;
2031 lastWorkspacesTabNavigatorRoute ?: RouteType ;
2132 topmostFullScreenRoute ?: RouteType ;
33+ /**
34+ * The full WorkspaceSplitNavigator inner state captured by the hook.
35+ * Wrapped in a synthetic outer node and fed to `getPathFromState` to reconstruct
36+ * the deep URL the user was on (e.g. `/workspaces/POLICY_ID/workflows`). Navigating
37+ * via that URL goes through `getStateFromPath` which produces a fully-formed
38+ * navigation state — bypassing custom router actions that don't seed nested state
39+ * when pushing a fresh TabNavigator on top of an existing fullscreen stack.
40+ */
41+ workspacesTabState ?: NavigationState | PartialState < NavigationState > ;
2242} ;
2343
24- // Navigates to the appropriate workspace tab or workspace list page.
25- // eslint-disable-next-line @typescript-eslint/no-unused-vars -- shouldUseNarrowLayout kept for API compat with callers
26- const navigateToWorkspacesPage = ( { currentUserLogin, shouldUseNarrowLayout, policy, domain, lastWorkspacesTabNavigatorRoute, topmostFullScreenRoute} : Params ) => {
44+ const navigateToWorkspacesPage = ( { currentUserLogin, shouldUseNarrowLayout, policy, domain, lastWorkspacesTabNavigatorRoute, topmostFullScreenRoute, workspacesTabState} : Params ) => {
2745 const rootState = navigationRef . getRootState ( ) ;
2846 const focusedRoute = rootState ? findFocusedRoute ( rootState ) : undefined ;
2947 const isOnWorkspacesList = focusedRoute ?. name === SCREENS . WORKSPACES_LIST ;
@@ -61,9 +79,26 @@ const navigateToWorkspacesPage = ({currentUserLogin, shouldUseNarrowLayout, poli
6179 return ;
6280 }
6381
64- // Restore to last-visited workspace — navigate through standard routing which switches the tab
6582 if ( policy ?. id ) {
66- Navigation . navigate ( ROUTES . WORKSPACE_INITIAL . getRoute ( policy . id ) ) ;
83+ // Synthesize a URL from the captured WorkspaceSplitNavigator inner state and navigate
84+ // to it. URL-based navigation goes through `getStateFromPath`, which produces a fully
85+ // formed nested state and reliably handles pushing a fresh TabNavigator on top of an
86+ // existing fullscreen stack. The state has to be wrapped with its full ancestor chain
87+ // (TAB_NAVIGATOR > WORKSPACE_NAVIGATOR > WORKSPACE_SPLIT_NAVIGATOR) so `getPathFromState`
88+ // can match the linking-config hierarchy and produce a real URL like
89+ // `/workspaces/POLICY_ID/workflows`; otherwise the resolver falls back to navigator
90+ // names as path segments and the result hits 404. Narrow layouts skip the deep-restore
91+ // and go to the workspace's initial page (mirrors mobile behavior).
92+ const wrappedState =
93+ ! shouldUseNarrowLayout && workspacesTabState
94+ ? wrapStateInNavigators ( workspacesTabState as PartialState < NavigationState > , [
95+ NAVIGATORS . TAB_NAVIGATOR ,
96+ NAVIGATORS . WORKSPACE_NAVIGATOR ,
97+ NAVIGATORS . WORKSPACE_SPLIT_NAVIGATOR ,
98+ ] )
99+ : undefined ;
100+ const targetPath = ( wrappedState ? getPathFromState ( wrappedState ) : ROUTES . WORKSPACE_INITIAL . getRoute ( policy . id ) ) as Route ;
101+ Navigation . navigate ( targetPath ) ;
67102 }
68103 return ;
69104 }
0 commit comments