From 97a5844cd5ad28d592423a9ee8dd346d70a5cb51 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 23 Feb 2026 15:03:23 +0100
Subject: [PATCH 01/27] reusing navigators

---
 .../GetStateForActionHandlers.ts              | 30 ++++++++++++++++---
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index b9a8ad120b0c..a606c394821c 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -120,17 +120,40 @@ function handlePushFullscreenAction(
     configOptions: RouterConfigOptions,
     stackRouter: Router<StackNavigationState<ParamListBase>, CommonActions.Action | StackActionType>,
 ) {
-    const targetScreen = action.payload?.params && 'screen' in action.payload.params ? (action.payload?.params?.screen as string) : undefined;
     const navigatorName = action.payload.name;
+    const params = action.payload.params;
+
+    const targetScreen = params && 'screen' in params ? (params.screen as string) : undefined;
+
+    const existingRoute = state.routes.find((r) => r.name === navigatorName);
+
+    if (existingRoute) {
+        if (existingRoute.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
+            screensWithEnteringAnimation.add(existingRoute.key);
+        }
+
+        const updatedRoute = {
+            ...existingRoute,
+            params: {...existingRoute.params, ...params},
+        };
+
+        const otherRoutes = state.routes.filter((r) => r.key !== existingRoute.key);
+
+        return {
+            ...state,
+            routes: [...otherRoutes, updatedRoute],
+            index: otherRoutes.length,
+        };
+    }
 
-    // If we navigate to the central screen of the split navigator, we need to filter this navigator from preloadedRoutes to remove a sidebar screen from the state
     const shouldFilterPreloadedRoutes =
         getIsNarrowLayout() &&
         isSplitNavigatorName(navigatorName) &&
         targetScreen !== SPLIT_TO_SIDEBAR[navigatorName] &&
         state.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
 
-    const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((preloadedRoute) => preloadedRoute.name !== navigatorName)} : state;
+    const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((r) => r.name !== navigatorName)} : state;
+
     const stateWithNavigator = stackRouter.getStateForAction(adjustedState, action, configOptions);
 
     if (!stateWithNavigator) {
@@ -140,7 +163,6 @@ function handlePushFullscreenAction(
 
     const lastFullScreenRoute = stateWithNavigator.routes.at(-1);
 
-    // Transitioning to all central screens in each split should be animated
     if (lastFullScreenRoute?.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
         screensWithEnteringAnimation.add(lastFullScreenRoute.key);
     }

From 752fba855f9507130ced6dbe59d7a7d992592eab Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 23 Feb 2026 16:20:13 +0100
Subject: [PATCH 02/27] clean code

---
 .../createRootStackNavigator/GetStateForActionHandlers.ts | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index a606c394821c..c82fd26bf41a 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -125,7 +125,7 @@ function handlePushFullscreenAction(
 
     const targetScreen = params && 'screen' in params ? (params.screen as string) : undefined;
 
-    const existingRoute = state.routes.find((r) => r.name === navigatorName);
+    const existingRoute = state.routes.find((route) => route.name === navigatorName);
 
     if (existingRoute) {
         if (existingRoute.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
@@ -137,7 +137,7 @@ function handlePushFullscreenAction(
             params: {...existingRoute.params, ...params},
         };
 
-        const otherRoutes = state.routes.filter((r) => r.key !== existingRoute.key);
+        const otherRoutes = state.routes.filter((route) => route.key !== existingRoute.key);
 
         return {
             ...state,
@@ -146,13 +146,14 @@ function handlePushFullscreenAction(
         };
     }
 
+    // If we navigate to the central screen of the split navigator, we need to filter this navigator from preloadedRoutes to remove a sidebar screen from the state
     const shouldFilterPreloadedRoutes =
         getIsNarrowLayout() &&
         isSplitNavigatorName(navigatorName) &&
         targetScreen !== SPLIT_TO_SIDEBAR[navigatorName] &&
         state.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
 
-    const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((r) => r.name !== navigatorName)} : state;
+    const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((preloadedRoute) => preloadedRoute.name !== navigatorName)} : state;
 
     const stateWithNavigator = stackRouter.getStateForAction(adjustedState, action, configOptions);
 
@@ -163,6 +164,7 @@ function handlePushFullscreenAction(
 
     const lastFullScreenRoute = stateWithNavigator.routes.at(-1);
 
+    // Transitioning to all central screens in each split should be animated
     if (lastFullScreenRoute?.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
         screensWithEnteringAnimation.add(lastFullScreenRoute.key);
     }

From 5df907fa760fcc1ce19c73b7beae96688a1acdbe Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 23 Feb 2026 16:28:25 +0100
Subject: [PATCH 03/27] fix browser history

---
 .../createRootStackNavigator/GetStateForActionHandlers.ts   | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index c82fd26bf41a..e3147ee0b1c1 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -137,12 +137,10 @@ function handlePushFullscreenAction(
             params: {...existingRoute.params, ...params},
         };
 
-        const otherRoutes = state.routes.filter((route) => route.key !== existingRoute.key);
-
         return {
             ...state,
-            routes: [...otherRoutes, updatedRoute],
-            index: otherRoutes.length,
+            routes: [state.routes, updatedRoute],
+            index: state.routes.length,
         };
     }
 

From f8a61f00e101bfd2b6fa23b6d22b338cc109d01d Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Tue, 24 Feb 2026 11:32:57 +0100
Subject: [PATCH 04/27] fix ios undefined state issue

---
 .../createRootStackNavigator/GetStateForActionHandlers.ts       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index e3147ee0b1c1..2e177c187566 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -139,7 +139,7 @@ function handlePushFullscreenAction(
 
         return {
             ...state,
-            routes: [state.routes, updatedRoute],
+            routes: [...state.routes, updatedRoute],
             index: state.routes.length,
         };
     }

From f9f7710798cc732fe7b0aeaec7096e2cbb71d201 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Tue, 24 Feb 2026 12:24:20 +0100
Subject: [PATCH 05/27] fix ios undefined state issue

---
 .../createRootStackNavigator/GetStateForActionHandlers.ts        | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index 2e177c187566..6ab42de5f2ab 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -152,7 +152,6 @@ function handlePushFullscreenAction(
         state.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
 
     const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((preloadedRoute) => preloadedRoute.name !== navigatorName)} : state;
-
     const stateWithNavigator = stackRouter.getStateForAction(adjustedState, action, configOptions);
 
     if (!stateWithNavigator) {

From 593186cf99fbe236cf943d0bb42b060489124b2e Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Fri, 27 Feb 2026 10:41:04 +0100
Subject: [PATCH 06/27] reusage of navigators

---
 .../GetStateForActionHandlers.ts              | 52 ++++++++++---
 .../RootStackRouter.ts                        | 27 ++++++-
 src/libs/Navigation/Navigation.ts             |  4 +
 src/libs/Navigation/NavigationRoot.tsx        | 75 ++++++++++++++-----
 tests/navigation/NavigateTests.tsx            |  1 +
 5 files changed, 129 insertions(+), 30 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index 6ab42de5f2ab..430b9595c3f4 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -122,46 +122,74 @@ function handlePushFullscreenAction(
 ) {
     const navigatorName = action.payload.name;
     const params = action.payload.params;
-
     const targetScreen = params && 'screen' in params ? (params.screen as string) : undefined;
 
-    const existingRoute = state.routes.find((route) => route.name === navigatorName);
+    let currentState = state;
+    const lastRoute = state.routes.at(-1);
+
+
+    if (lastRoute?.params && typeof (lastRoute.params as any).originalIndex === 'number') {
+        const originalIndex = (lastRoute.params as any).originalIndex;
+        const routes = [...state.routes];
+
+        const [movedRoute] = routes.splice(-1, 1);
+
+        const { originalIndex: _, ...cleanParams } = (movedRoute.params as any);
+        const restoredRoute = { ...movedRoute, params: cleanParams };
+
+        routes.splice(originalIndex, 0, restoredRoute);
+
+        currentState = {
+            ...state,
+            routes,
+            index: routes.length - 1,
+        };
+    }
+
+    const existingRoute = currentState.routes.find((route) => route.name === navigatorName);
 
     if (existingRoute) {
         if (existingRoute.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
             screensWithEnteringAnimation.add(existingRoute.key);
         }
 
+        const currentPos = currentState.routes.indexOf(existingRoute);
+
         const updatedRoute = {
             ...existingRoute,
-            params: {...existingRoute.params, ...params},
+            params: {
+                ...existingRoute.params,
+                ...params,
+                originalIndex: currentPos
+            },
         };
 
+        const otherRoutes = currentState.routes.filter((route) => route.key !== existingRoute.key);
+
         return {
-            ...state,
-            routes: [...state.routes, updatedRoute],
-            index: state.routes.length,
+            ...currentState,
+            routes: [...otherRoutes, updatedRoute],
+            index: otherRoutes.length,
         };
     }
 
-    // If we navigate to the central screen of the split navigator, we need to filter this navigator from preloadedRoutes to remove a sidebar screen from the state
     const shouldFilterPreloadedRoutes =
         getIsNarrowLayout() &&
         isSplitNavigatorName(navigatorName) &&
         targetScreen !== SPLIT_TO_SIDEBAR[navigatorName] &&
-        state.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
+        currentState.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
+
+    const adjustedState = shouldFilterPreloadedRoutes
+        ? { ...currentState, preloadedRoutes: currentState.preloadedRoutes.filter((r) => r.name !== navigatorName) }
+        : currentState;
 
-    const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((preloadedRoute) => preloadedRoute.name !== navigatorName)} : state;
     const stateWithNavigator = stackRouter.getStateForAction(adjustedState, action, configOptions);
 
     if (!stateWithNavigator) {
-        Log.hmmm(`[handlePushAction] ${navigatorName} has not been found in the navigation state.`);
         return null;
     }
 
     const lastFullScreenRoute = stateWithNavigator.routes.at(-1);
-
-    // Transitioning to all central screens in each split should be animated
     if (lastFullScreenRoute?.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
         screensWithEnteringAnimation.add(lastFullScreenRoute.key);
     }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
index 8eceff88a361..4e233e6def84 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
@@ -113,10 +113,35 @@ function isNavigatingToModalFromModal(state: StackNavigationState<ParamListBase>
 
 function RootStackRouter(options: RootStackNavigatorRouterOptions) {
     const stackRouter = StackRouter(options);
-
+    debugger;
     return {
         ...stackRouter,
         getStateForAction(state: StackNavigationState<ParamListBase>, action: RootStackNavigatorAction, configOptions: RouterConfigOptions) {
+            debugger;
+            if (action.type === 'POP' || action.type === 'GO_BACK') {
+                const lastRoute = state.routes.at(-1);
+
+                if (lastRoute?.params && typeof (lastRoute.params as any).originalIndex === 'number') {
+                    const originalIndex = (lastRoute.params as any).originalIndex;
+
+                    const newState = stackRouter.getStateForAction(state, action, configOptions);
+                    if (!newState) return null;
+
+                    const routes = [...newState.routes];
+
+                    const { originalIndex: _, ...cleanParams } = (lastRoute.params as any);
+                    const restoredRoute = { ...lastRoute, params: cleanParams };
+
+                    routes.splice(originalIndex, 0, restoredRoute);
+
+                    return {
+                        ...newState,
+                        routes,
+                        index: routes.length - 1,
+                    };
+                }
+            }
+
             // Evaluate navigation guards FIRST
             const guardState = handleNavigationGuards(state, action, configOptions, stackRouter);
             if (guardState) {
diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts
index 6026d5a488bf..a301ea46bb3e 100644
--- a/src/libs/Navigation/Navigation.ts
+++ b/src/libs/Navigation/Navigation.ts
@@ -404,6 +404,7 @@ const defaultGoBackOptions: Required<GoBackOptions> = {
  * @param options - Optional configuration that affects navigation logic, such as parameter comparison.
  */
 function goUp(backToRoute: Route, options?: GoBackOptions) {
+    debugger;
     if (!canNavigate('goUp', {backToRoute}) || !navigationRef.current) {
         Log.hmmm(`[Navigation] Unable to go up. Can't navigate.`);
         return;
@@ -457,6 +458,7 @@ function goUp(backToRoute: Route, options?: GoBackOptions) {
  * @param options - Optional configuration that affects navigation logic
  */
 function goBack(backToRoute?: Route, options?: GoBackOptions) {
+    debugger;
     clearSelectedText();
 
     if (!canNavigate('goBack', {backToRoute})) {
@@ -487,6 +489,8 @@ function goBack(backToRoute?: Route, options?: GoBackOptions) {
  * see the NAVIGATION.md documentation.
  */
 function popToSidebar() {
+
+    debugger;
     setShouldPopToSidebar(false);
 
     const rootState = navigationRef.current?.getRootState();
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 2844878af164..67471b4a1c00 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -1,10 +1,10 @@
-import type {NavigationState} from '@react-navigation/native';
-import {DarkTheme, DefaultTheme, findFocusedRoute, NavigationContainer} from '@react-navigation/native';
-import {hasCompletedGuidedSetupFlowSelector} from '@selectors/Onboarding';
+import type { NavigationState } from '@react-navigation/native';
+import { DarkTheme, DefaultTheme, findFocusedRoute, NavigationContainer } from '@react-navigation/native';
+import { hasCompletedGuidedSetupFlowSelector } from '@selectors/Onboarding';
 import * as Sentry from '@sentry/react-native';
-import React, {useCallback, useContext, useEffect, useMemo, useRef} from 'react';
-import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
-import {useCurrentReportIDActions} from '@hooks/useCurrentReportID';
+import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'react';
+import { ScrollOffsetContext } from '@components/ScrollOffsetContextProvider';
+import { useCurrentReportIDActions } from '@hooks/useCurrentReportID';
 import useOnyx from '@hooks/useOnyx';
 import usePrevious from '@hooks/usePrevious';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -13,24 +13,59 @@ import useThemePreference from '@hooks/useThemePreference';
 import FS from '@libs/Fullstory';
 import Log from '@libs/Log';
 import shouldOpenLastVisitedPath from '@libs/shouldOpenLastVisitedPath';
-import {getPathFromURL} from '@libs/Url';
-import {updateLastVisitedPath} from '@userActions/App';
-import {updateOnboardingLastVisitedPath} from '@userActions/Welcome';
+import { getPathFromURL } from '@libs/Url';
+import { updateLastVisitedPath } from '@userActions/App';
+import { updateOnboardingLastVisitedPath } from '@userActions/Welcome';
 import CONST from '@src/CONST';
-import {endSpan, getSpan, startSpan} from '@src/libs/telemetry/activeSpans';
-import {navigationIntegration} from '@src/libs/telemetry/integrations';
+import { endSpan, getSpan, startSpan } from '@src/libs/telemetry/activeSpans';
+import { navigationIntegration } from '@src/libs/telemetry/integrations';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {Route} from '@src/ROUTES';
+import type { Route } from '@src/ROUTES';
 import ROUTES from '@src/ROUTES';
 import AppNavigator from './AppNavigator';
-import {cleanPreservedNavigatorStates} from './AppNavigator/createSplitNavigator/usePreserveNavigatorState';
+import { cleanPreservedNavigatorStates } from './AppNavigator/createSplitNavigator/usePreserveNavigatorState';
 import getAdaptedStateFromPath from './helpers/getAdaptedStateFromPath';
 import getPathFromState from './helpers/getPathFromState';
-import {isSplitNavigatorName, isWorkspacesTabScreenName} from './helpers/isNavigatorName';
-import {saveSettingsTabPathToSessionStorage, saveWorkspacesTabPathToSessionStorage} from './helpers/lastVisitedTabPathUtils';
-import {linkingConfig} from './linkingConfig';
-import Navigation, {navigationRef} from './Navigation';
+import { isSplitNavigatorName, isWorkspacesTabScreenName } from './helpers/isNavigatorName';
+import { saveSettingsTabPathToSessionStorage, saveWorkspacesTabPathToSessionStorage } from './helpers/lastVisitedTabPathUtils';
+import { linkingConfig } from './linkingConfig';
+import Navigation, { navigationRef } from './Navigation';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 type NavigationRootProps = {
     /** Whether the current user is logged in with an authToken */
@@ -234,9 +269,15 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         const currentRoute = navigationRef.getCurrentRoute();
         Sentry.addBreadcrumb({message: `[NAVIGATION] screen: ${currentRoute?.name}, params: ${JSON.stringify(currentRoute?.params ?? {})}`, category: 'navigation'});
 
+        console.log('__________________');
+        console.log(state);
+        console.log("__________________")
+
+
         updateCurrentReportID(state);
         parseAndLogRoute(state);
 
+
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
diff --git a/tests/navigation/NavigateTests.tsx b/tests/navigation/NavigateTests.tsx
index 636b5995178e..008cec2fd979 100644
--- a/tests/navigation/NavigateTests.tsx
+++ b/tests/navigation/NavigateTests.tsx
@@ -210,6 +210,7 @@ describe('Navigate', () => {
                                 name: NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR,
                                 state: {
                                     index: 0,
+                                    stale: false,
                                     routes: [
                                         {
                                             name: SCREENS.SETTINGS.ROOT,

From bf33da107ac514b14e4feb9af7f49e2d30581446 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Fri, 27 Feb 2026 10:52:29 +0100
Subject: [PATCH 07/27] migrate state editing only to place where it is
 rendering

---
 .../createRootStackNavigator/index.tsx        |  6 ++--
 .../useCustomRootStackNavigatorState/index.ts | 31 ++++++++++++++++---
 2 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx
index b6138ecd540c..af6a121cd86f 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx
@@ -1,10 +1,10 @@
-import type {NavigationProp, NavigatorTypeBagBase, ParamListBase, StaticConfig, TypedNavigator} from '@react-navigation/native';
-import {createNavigatorFactory} from '@react-navigation/native';
+import type { NavigationProp, NavigatorTypeBagBase, ParamListBase, StaticConfig, TypedNavigator } from '@react-navigation/native';
+import { createNavigatorFactory } from '@react-navigation/native';
 import RootNavigatorExtraContent from '@components/Navigation/RootNavigatorExtraContent';
 import useNavigationResetOnLayoutChange from '@libs/Navigation/AppNavigator/useNavigationResetOnLayoutChange';
 import createPlatformStackNavigatorComponent from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent';
 import defaultPlatformStackScreenOptions from '@libs/Navigation/PlatformStackNavigation/defaultPlatformStackScreenOptions';
-import type {PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState} from '@libs/Navigation/PlatformStackNavigation/types';
+import type { PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState } from '@libs/Navigation/PlatformStackNavigation/types';
 import RootStackRouter from './RootStackRouter';
 import useCustomRootStackNavigatorState from './useCustomRootStackNavigatorState';
 
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index 88a7135aa0b3..8941a5a4e832 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,18 +1,39 @@
 import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 
-// This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
     let indexToSlice = Math.max(0, lastSplitIndex);
     const hasPrevRoute = lastSplitIndex > 0;
     const isPrevFullScreen = isFullScreenName(state.routes.at(lastSplitIndex - 1)?.name);
 
-    // If the route before the last full screen is e.g. RHP, we should leave it in the rendered routes,
-    // as there may be display issues (blank screen) when navigating back and recreating that route to render.
     if (hasPrevRoute && !isPrevFullScreen) {
         indexToSlice = lastSplitIndex - 1;
     }
-    const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
-    return {...state, routes: routesToRender, index: routesToRender.length - 1};
+
+
+    const firstKeyMap = new Map<string, string>();
+    state.routes.forEach((route) => {
+        if (!firstKeyMap.has(route.name)) {
+            firstKeyMap.set(route.name, route.key);
+        }
+    });
+
+    const routesToRender = state.routes.slice(indexToSlice).map((route) => {
+        const firstKey = firstKeyMap.get(route.name);
+
+        if (firstKey && route.key !== firstKey) {
+            return {
+                ...route,
+                key: firstKey,
+            };
+        }
+        return route;
+    });
+
+    return {
+        ...state,
+        routes: routesToRender,
+        index: routesToRender.length - 1
+    };
 }

From 9d76506c07d62ab0923208bf939cb412c2e82923 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Fri, 27 Feb 2026 10:56:45 +0100
Subject: [PATCH 08/27] remove unnecessary changes with broke history

---
 .../GetStateForActionHandlers.ts              | 112 ++++++++----------
 .../RootStackRouter.ts                        |  25 ----
 src/libs/Navigation/Navigation.ts             |   3 -
 3 files changed, 51 insertions(+), 89 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index 430b9595c3f4..19cc5e95604b 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -1,15 +1,57 @@
-import type {CommonActions, RouterConfigOptions, StackActionType, StackNavigationState} from '@react-navigation/native';
-import {StackActions} from '@react-navigation/native';
-import type {ParamListBase, Router} from '@react-navigation/routers';
+import type { CommonActions, RouterConfigOptions, StackActionType, StackNavigationState } from '@react-navigation/native';
+import { StackActions } from '@react-navigation/native';
+import type { ParamListBase, Router } from '@react-navigation/routers';
 import SCREENS_WITH_NAVIGATION_TAB_BAR from '@components/Navigation/TopLevelNavigationTabBar/SCREENS_WITH_NAVIGATION_TAB_BAR';
 import getIsNarrowLayout from '@libs/getIsNarrowLayout';
 import Log from '@libs/Log';
-import {isSplitNavigatorName} from '@libs/Navigation/helpers/isNavigatorName';
-import {SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
+import { isSplitNavigatorName } from '@libs/Navigation/helpers/isNavigatorName';
+import { SPLIT_TO_SIDEBAR } from '@libs/Navigation/linkingConfig/RELATIONS';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import SCREENS from '@src/SCREENS';
-import type {OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType} from './types';
+import type { OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType } from './types';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 const MODAL_ROUTES_TO_DISMISS = new Set<string>([
     NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR,
@@ -121,71 +163,19 @@ function handlePushFullscreenAction(
     stackRouter: Router<StackNavigationState<ParamListBase>, CommonActions.Action | StackActionType>,
 ) {
     const navigatorName = action.payload.name;
-    const params = action.payload.params;
-    const targetScreen = params && 'screen' in params ? (params.screen as string) : undefined;
-
-    let currentState = state;
-    const lastRoute = state.routes.at(-1);
-
-
-    if (lastRoute?.params && typeof (lastRoute.params as any).originalIndex === 'number') {
-        const originalIndex = (lastRoute.params as any).originalIndex;
-        const routes = [...state.routes];
-
-        const [movedRoute] = routes.splice(-1, 1);
-
-        const { originalIndex: _, ...cleanParams } = (movedRoute.params as any);
-        const restoredRoute = { ...movedRoute, params: cleanParams };
-
-        routes.splice(originalIndex, 0, restoredRoute);
-
-        currentState = {
-            ...state,
-            routes,
-            index: routes.length - 1,
-        };
-    }
-
-    const existingRoute = currentState.routes.find((route) => route.name === navigatorName);
-
-    if (existingRoute) {
-        if (existingRoute.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
-            screensWithEnteringAnimation.add(existingRoute.key);
-        }
-
-        const currentPos = currentState.routes.indexOf(existingRoute);
-
-        const updatedRoute = {
-            ...existingRoute,
-            params: {
-                ...existingRoute.params,
-                ...params,
-                originalIndex: currentPos
-            },
-        };
-
-        const otherRoutes = currentState.routes.filter((route) => route.key !== existingRoute.key);
-
-        return {
-            ...currentState,
-            routes: [...otherRoutes, updatedRoute],
-            index: otherRoutes.length,
-        };
-    }
 
     const shouldFilterPreloadedRoutes =
         getIsNarrowLayout() &&
         isSplitNavigatorName(navigatorName) &&
         targetScreen !== SPLIT_TO_SIDEBAR[navigatorName] &&
-        currentState.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
+        state.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
 
-    const adjustedState = shouldFilterPreloadedRoutes
-        ? { ...currentState, preloadedRoutes: currentState.preloadedRoutes.filter((r) => r.name !== navigatorName) }
-        : currentState;
+    const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((preloadedRoute) => preloadedRoute.name !== navigatorName)} : state;
 
     const stateWithNavigator = stackRouter.getStateForAction(adjustedState, action, configOptions);
 
     if (!stateWithNavigator) {
+        Log.hmmm(`[handlePushAction] ${navigatorName} has not been found in the navigation state.`);
         return null;
     }
 
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
index 4e233e6def84..c1fe00c1dfa0 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
@@ -113,34 +113,9 @@ function isNavigatingToModalFromModal(state: StackNavigationState<ParamListBase>
 
 function RootStackRouter(options: RootStackNavigatorRouterOptions) {
     const stackRouter = StackRouter(options);
-    debugger;
     return {
         ...stackRouter,
         getStateForAction(state: StackNavigationState<ParamListBase>, action: RootStackNavigatorAction, configOptions: RouterConfigOptions) {
-            debugger;
-            if (action.type === 'POP' || action.type === 'GO_BACK') {
-                const lastRoute = state.routes.at(-1);
-
-                if (lastRoute?.params && typeof (lastRoute.params as any).originalIndex === 'number') {
-                    const originalIndex = (lastRoute.params as any).originalIndex;
-
-                    const newState = stackRouter.getStateForAction(state, action, configOptions);
-                    if (!newState) return null;
-
-                    const routes = [...newState.routes];
-
-                    const { originalIndex: _, ...cleanParams } = (lastRoute.params as any);
-                    const restoredRoute = { ...lastRoute, params: cleanParams };
-
-                    routes.splice(originalIndex, 0, restoredRoute);
-
-                    return {
-                        ...newState,
-                        routes,
-                        index: routes.length - 1,
-                    };
-                }
-            }
 
             // Evaluate navigation guards FIRST
             const guardState = handleNavigationGuards(state, action, configOptions, stackRouter);
diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts
index a301ea46bb3e..8009846422ef 100644
--- a/src/libs/Navigation/Navigation.ts
+++ b/src/libs/Navigation/Navigation.ts
@@ -404,7 +404,6 @@ const defaultGoBackOptions: Required<GoBackOptions> = {
  * @param options - Optional configuration that affects navigation logic, such as parameter comparison.
  */
 function goUp(backToRoute: Route, options?: GoBackOptions) {
-    debugger;
     if (!canNavigate('goUp', {backToRoute}) || !navigationRef.current) {
         Log.hmmm(`[Navigation] Unable to go up. Can't navigate.`);
         return;
@@ -458,7 +457,6 @@ function goUp(backToRoute: Route, options?: GoBackOptions) {
  * @param options - Optional configuration that affects navigation logic
  */
 function goBack(backToRoute?: Route, options?: GoBackOptions) {
-    debugger;
     clearSelectedText();
 
     if (!canNavigate('goBack', {backToRoute})) {
@@ -490,7 +488,6 @@ function goBack(backToRoute?: Route, options?: GoBackOptions) {
  */
 function popToSidebar() {
 
-    debugger;
     setShouldPopToSidebar(false);
 
     const rootState = navigationRef.current?.getRootState();

From 3a4a22ecdb8e1375864bb3cc09c4988ff17d03ec Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Fri, 27 Feb 2026 12:36:34 +0100
Subject: [PATCH 09/27] empty screens after returning to scream

---
 .../GetStateForActionHandlers.ts              | 55 ++------------
 .../useCustomRootStackNavigatorState/index.ts | 45 +++++++----
 src/libs/Navigation/NavigationRoot.tsx        | 75 +++++--------------
 3 files changed, 55 insertions(+), 120 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index 19cc5e95604b..52a53673ec17 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -1,57 +1,15 @@
-import type { CommonActions, RouterConfigOptions, StackActionType, StackNavigationState } from '@react-navigation/native';
-import { StackActions } from '@react-navigation/native';
-import type { ParamListBase, Router } from '@react-navigation/routers';
+import type {CommonActions, RouterConfigOptions, StackActionType, StackNavigationState} from '@react-navigation/native';
+import {StackActions} from '@react-navigation/native';
+import type {ParamListBase, Router} from '@react-navigation/routers';
 import SCREENS_WITH_NAVIGATION_TAB_BAR from '@components/Navigation/TopLevelNavigationTabBar/SCREENS_WITH_NAVIGATION_TAB_BAR';
 import getIsNarrowLayout from '@libs/getIsNarrowLayout';
 import Log from '@libs/Log';
-import { isSplitNavigatorName } from '@libs/Navigation/helpers/isNavigatorName';
-import { SPLIT_TO_SIDEBAR } from '@libs/Navigation/linkingConfig/RELATIONS';
+import {isSplitNavigatorName} from '@libs/Navigation/helpers/isNavigatorName';
+import {SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import SCREENS from '@src/SCREENS';
-import type { OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType } from './types';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+import type {OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType} from './types';
 
 const MODAL_ROUTES_TO_DISMISS = new Set<string>([
     NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR,
@@ -163,6 +121,7 @@ function handlePushFullscreenAction(
     stackRouter: Router<StackNavigationState<ParamListBase>, CommonActions.Action | StackActionType>,
 ) {
     const navigatorName = action.payload.name;
+    const targetScreen = action.payload?.params && 'screen' in action.payload.params ? (action.payload?.params?.screen as string) : undefined;
 
     const shouldFilterPreloadedRoutes =
         getIsNarrowLayout() &&
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index 8941a5a4e832..62bd421bc3b3 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,39 +1,56 @@
+import {screensWithEnteringAnimation, workspaceOrDomainSplitsWithoutEnteringAnimation} from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
 import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 
+// This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
     let indexToSlice = Math.max(0, lastSplitIndex);
     const hasPrevRoute = lastSplitIndex > 0;
     const isPrevFullScreen = isFullScreenName(state.routes.at(lastSplitIndex - 1)?.name);
 
+    // If the route before the last full screen is e.g. RHP, we should leave it in the rendered routes,
+    // as there may be display issues (blank screen) when navigating back and recreating that route to render.
     if (hasPrevRoute && !isPrevFullScreen) {
         indexToSlice = lastSplitIndex - 1;
     }
 
-
+    // Build map: navigator name → key of first occurrence in the full (unsliced) state.
+    // We need the full state so we find the first key even if it was sliced out.
     const firstKeyMap = new Map<string, string>();
-    state.routes.forEach((route) => {
-        if (!firstKeyMap.has(route.name)) {
-            firstKeyMap.set(route.name, route.key);
+    for (const route of state.routes) {
+        if (firstKeyMap.has(route.name)) {
+            continue;
         }
-    });
+        firstKeyMap.set(route.name, route.key);
+    }
 
     const routesToRender = state.routes.slice(indexToSlice).map((route) => {
+        // Only remap keys for fullscreen (split) navigators. Intermediate screens like WorkspacesList
+        // must keep their own keys — remapping them causes the rendered state to look identical to
+        // the previous render, so React Navigation skips the transition and shows a blank screen.
+        if (!isFullScreenName(route.name)) {
+            return route;
+        }
+
         const firstKey = firstKeyMap.get(route.name);
 
         if (firstKey && route.key !== firstKey) {
-            return {
-                ...route,
-                key: firstKey,
-            };
+            // Sync animation sets: the sets track keys added during getStateForAction (router level).
+            // Since rendered key changes from route.key → firstKey, we must remap the set entries
+            // so animation config (getFullscreenNavigatorOptions) picks up the right key.
+            if (screensWithEnteringAnimation.has(route.key)) {
+                screensWithEnteringAnimation.delete(route.key);
+                screensWithEnteringAnimation.add(firstKey);
+            }
+            if (workspaceOrDomainSplitsWithoutEnteringAnimation.has(route.key)) {
+                workspaceOrDomainSplitsWithoutEnteringAnimation.delete(route.key);
+                workspaceOrDomainSplitsWithoutEnteringAnimation.add(firstKey);
+            }
+            return {...route, key: firstKey};
         }
         return route;
     });
 
-    return {
-        ...state,
-        routes: routesToRender,
-        index: routesToRender.length - 1
-    };
+    return {...state, routes: routesToRender, index: routesToRender.length - 1};
 }
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 67471b4a1c00..2844878af164 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -1,10 +1,10 @@
-import type { NavigationState } from '@react-navigation/native';
-import { DarkTheme, DefaultTheme, findFocusedRoute, NavigationContainer } from '@react-navigation/native';
-import { hasCompletedGuidedSetupFlowSelector } from '@selectors/Onboarding';
+import type {NavigationState} from '@react-navigation/native';
+import {DarkTheme, DefaultTheme, findFocusedRoute, NavigationContainer} from '@react-navigation/native';
+import {hasCompletedGuidedSetupFlowSelector} from '@selectors/Onboarding';
 import * as Sentry from '@sentry/react-native';
-import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'react';
-import { ScrollOffsetContext } from '@components/ScrollOffsetContextProvider';
-import { useCurrentReportIDActions } from '@hooks/useCurrentReportID';
+import React, {useCallback, useContext, useEffect, useMemo, useRef} from 'react';
+import {ScrollOffsetContext} from '@components/ScrollOffsetContextProvider';
+import {useCurrentReportIDActions} from '@hooks/useCurrentReportID';
 import useOnyx from '@hooks/useOnyx';
 import usePrevious from '@hooks/usePrevious';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
@@ -13,59 +13,24 @@ import useThemePreference from '@hooks/useThemePreference';
 import FS from '@libs/Fullstory';
 import Log from '@libs/Log';
 import shouldOpenLastVisitedPath from '@libs/shouldOpenLastVisitedPath';
-import { getPathFromURL } from '@libs/Url';
-import { updateLastVisitedPath } from '@userActions/App';
-import { updateOnboardingLastVisitedPath } from '@userActions/Welcome';
+import {getPathFromURL} from '@libs/Url';
+import {updateLastVisitedPath} from '@userActions/App';
+import {updateOnboardingLastVisitedPath} from '@userActions/Welcome';
 import CONST from '@src/CONST';
-import { endSpan, getSpan, startSpan } from '@src/libs/telemetry/activeSpans';
-import { navigationIntegration } from '@src/libs/telemetry/integrations';
+import {endSpan, getSpan, startSpan} from '@src/libs/telemetry/activeSpans';
+import {navigationIntegration} from '@src/libs/telemetry/integrations';
 import NAVIGATORS from '@src/NAVIGATORS';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type { Route } from '@src/ROUTES';
+import type {Route} from '@src/ROUTES';
 import ROUTES from '@src/ROUTES';
 import AppNavigator from './AppNavigator';
-import { cleanPreservedNavigatorStates } from './AppNavigator/createSplitNavigator/usePreserveNavigatorState';
+import {cleanPreservedNavigatorStates} from './AppNavigator/createSplitNavigator/usePreserveNavigatorState';
 import getAdaptedStateFromPath from './helpers/getAdaptedStateFromPath';
 import getPathFromState from './helpers/getPathFromState';
-import { isSplitNavigatorName, isWorkspacesTabScreenName } from './helpers/isNavigatorName';
-import { saveSettingsTabPathToSessionStorage, saveWorkspacesTabPathToSessionStorage } from './helpers/lastVisitedTabPathUtils';
-import { linkingConfig } from './linkingConfig';
-import Navigation, { navigationRef } from './Navigation';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+import {isSplitNavigatorName, isWorkspacesTabScreenName} from './helpers/isNavigatorName';
+import {saveSettingsTabPathToSessionStorage, saveWorkspacesTabPathToSessionStorage} from './helpers/lastVisitedTabPathUtils';
+import {linkingConfig} from './linkingConfig';
+import Navigation, {navigationRef} from './Navigation';
 
 type NavigationRootProps = {
     /** Whether the current user is logged in with an authToken */
@@ -269,15 +234,9 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         const currentRoute = navigationRef.getCurrentRoute();
         Sentry.addBreadcrumb({message: `[NAVIGATION] screen: ${currentRoute?.name}, params: ${JSON.stringify(currentRoute?.params ?? {})}`, category: 'navigation'});
 
-        console.log('__________________');
-        console.log(state);
-        console.log("__________________")
-
-
         updateCurrentReportID(state);
         parseAndLogRoute(state);
 
-
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);

From fdcb6af03bfd7bd680e638d3d8943b4b56a0b953 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Fri, 27 Feb 2026 15:12:21 +0100
Subject: [PATCH 10/27] work in progress

---
 .../reuseNavigatorKey.ts                      | 118 ++++++++++++++++++
 1 file changed, 118 insertions(+)
 create mode 100644 src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
new file mode 100644
index 000000000000..30f87a5d7839
--- /dev/null
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -0,0 +1,118 @@
+import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
+import { screensWithEnteringAnimation } from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
+import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
+
+
+
+
+
+
+type StateRoutes = StackNavigationState<ParamListBase>['routes'];
+
+/**
+ * Remaps the key of a fullscreen navigator route in `routesToRender` to the canonical (first) occurrence key
+ * of that navigator name found in the full navigation state.
+ *
+ * This allows React to reuse the already-mounted navigator component instead of remounting it,
+ * avoiding expensive teardown/setup cycles. The real navigation state is left untouched, so
+ * browser history still works correctly (the state always has unique keys).
+ *
+ * Example: state=[RSN-key1, WSN-key2, RSN-key3], routesToRender=[WSN-key2, RSN-key3]
+ *   → RSN-kopey3 is remapped to RSN-key1 (the first RSN in state, which is already mounted)
+ *   → React sees [WSN-key2, RSN-key1] in both old and new render → reuses RSN-key1 component
+ */
+function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): StateRoutes {
+    debugger;
+    return routesToRender.map((route) => {
+        if (!isFullScreenName(route.name)) {
+            return route;
+        }
+
+        const firstOccurrence = fullState.routes.find((r) => r.name === route.name);
+        if (!firstOccurrence) {
+            return route;
+        }
+
+        const canonicalKey = firstOccurrence.key;
+        const shouldRemap = canonicalKey !== route.key && !routesToRender.some((r) => r.key === canonicalKey);
+
+        if (!shouldRemap) {
+            return route;
+        }
+
+        // Transfer animation marker from new key to canonical key so slide-in animation fires correctly.
+        if (screensWithEnteringAnimation.has(route.key)) {
+            screensWithEnteringAnimation.delete(route.key);
+            screensWithEnteringAnimation.add(canonicalKey);
+        }
+
+        return {...firstOccurrence, params: {...firstOccurrence.params, ...route.params}};
+    });
+}
+
+function cleanNavigationState(state) {
+    function processNavigator(navigatorState) {
+        if (!navigatorState?.routes) {
+            return navigatorState;
+        }
+
+        const seenNames = new Map(); // name -> canonicalKey
+        const keyRemap = new Map(); // oldKey -> canonicalKey
+        const cleanedRoutesReversed = [];
+
+        // 1️⃣ iterujemy OD KOŃCA (nowsze mają priorytet)
+        for (let i = navigatorState.routes.length - 1; i >= 0; i--) {
+            const route = navigatorState.routes[i];
+
+            let nextRoute = route;
+
+            // rekurencja w dół
+            if (route.state) {
+                nextRoute = {
+                    ...route,
+                    state: processNavigator(route.state),
+                };
+            }
+
+            const canonicalKey = seenNames.get(route.name);
+
+            if (canonicalKey) {
+                // duplikat → zachowujemy nowszy route,
+                // ale mapujemy key na wcześniejszy
+                keyRemap.set(route.key, canonicalKey);
+
+                cleanedRoutesReversed.push({
+                    ...nextRoute,
+                    key: canonicalKey,
+                });
+            } else {
+                // pierwsze wystąpienie (od końca)
+                seenNames.set(route.name, route.key);
+                cleanedRoutesReversed.push(nextRoute);
+            }
+        }
+
+        const cleanedRoutes = cleanedRoutesReversed.reverse();
+        const validKeys = new Set(cleanedRoutes.map((r) => r.key));
+
+        // 2️⃣ naprawa history
+        let cleanedHistory = navigatorState.history;
+        if (Array.isArray(navigatorState.history)) {
+            cleanedHistory = navigatorState.history.map((key) => keyRemap.get(key) ?? key).filter((key) => validKeys.has(key));
+        }
+
+        // 3️⃣ naprawa index
+        const cleanedIndex = Math.min(navigatorState.index ?? 0, Math.max(cleanedRoutes.length - 1, 0));
+
+        return {
+            ...navigatorState,
+            routes: cleanedRoutes,
+            history: cleanedHistory,
+            index: cleanedIndex,
+        };
+    }
+
+    return processNavigator(state);
+}
+
+export {reuseNavigatorKey,cleanNavigationState};

From d8ebd3f807d2178c1558eaa3a34b9f47e7c487e8 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 2 Mar 2026 08:18:23 +0100
Subject: [PATCH 11/27] working history but with week performance

---
 .../index.android.ts                          | 14 +++-----
 .../index.ios.ts                              |  4 ++-
 .../useCustomRootStackNavigatorState/index.ts | 35 +++++++++++++++----
 .../reuseNavigatorKey.ts                      |  5 +--
 4 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts
index 88a7135aa0b3..c060873e981f 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts
@@ -1,18 +1,14 @@
 import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import reuseNavigatorKey from './reuseNavigatorKey';
 
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
-    let indexToSlice = Math.max(0, lastSplitIndex);
-    const hasPrevRoute = lastSplitIndex > 0;
-    const isPrevFullScreen = isFullScreenName(state.routes.at(lastSplitIndex - 1)?.name);
 
-    // If the route before the last full screen is e.g. RHP, we should leave it in the rendered routes,
-    // as there may be display issues (blank screen) when navigating back and recreating that route to render.
-    if (hasPrevRoute && !isPrevFullScreen) {
-        indexToSlice = lastSplitIndex - 1;
-    }
+    // Always preserve the previous fullscreen route so React can reuse the mounted navigator component on navigation.
+    const indexToSlice = Math.max(0, lastSplitIndex - 1);
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
-    return {...state, routes: routesToRender, index: routesToRender.length - 1};
+    const remappedRoutes = reuseNavigatorKey(routesToRender, state);
+    return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts
index 0351251d6871..b23fffcb7893 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts
@@ -4,6 +4,7 @@ import {SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {NavigationRoute, SplitNavigatorName} from '@libs/Navigation/types';
 import NAVIGATORS from '@src/NAVIGATORS';
+import reuseNavigatorKey from './reuseNavigatorKey';
 
 // Swiping back on iOS does not work properly when the preloaded route has gestureEnabled set to false.
 // Therefore, on screens where swiping should work, preloadedRoutes will be an empty array during rendering to ensure swiping works properly.
@@ -36,7 +37,8 @@ function getShouldHidePreloadedRoutes(route?: NavigationRoute) {
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
     const routesToRender = state.routes.slice(Math.max(0, lastSplitIndex - 1), state.routes.length);
-    const stateToRender = {...state, routes: routesToRender, index: routesToRender.length - 1};
+    const remappedRoutes = reuseNavigatorKey(routesToRender, state);
+    const stateToRender = {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
     if (getShouldHidePreloadedRoutes(stateToRender.routes.at(-1))) {
         return {...stateToRender, preloadedRoutes: []};
     }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index 88a7135aa0b3..0aa4d900220e 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,18 +1,41 @@
-import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
-import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
+import type { CustomStateHookProps } from '@libs/Navigation/PlatformStackNavigation/types';
+import reuseNavigatorKey, { cleanNavigationState } from './reuseNavigatorKey';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
-    const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
+
+    const cleanState = cleanNavigationState(state)
+    const lastSplitIndex = cleanState.routes.findLastIndex((route) => isFullScreenName(route.name));
     let indexToSlice = Math.max(0, lastSplitIndex);
     const hasPrevRoute = lastSplitIndex > 0;
-    const isPrevFullScreen = isFullScreenName(state.routes.at(lastSplitIndex - 1)?.name);
+    const isPrevFullScreen = isFullScreenName(cleanState.routes.at(lastSplitIndex - 1)?.name);
 
     // If the route before the last full screen is e.g. RHP, we should leave it in the rendered routes,
     // as there may be display issues (blank screen) when navigating back and recreating that route to render.
     if (hasPrevRoute && !isPrevFullScreen) {
         indexToSlice = lastSplitIndex - 1;
     }
-    const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
-    return {...state, routes: routesToRender, index: routesToRender.length - 1};
+    const routesToRender = cleanState.routes.slice(indexToSlice, cleanState.routes.length);
+    return {...cleanState, routes: routesToRender, index: routesToRender.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index 30f87a5d7839..b50ff11d42de 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -111,8 +111,9 @@ function cleanNavigationState(state) {
             index: cleanedIndex,
         };
     }
-
-    return processNavigator(state);
+    const result = processNavigator(state);
+    debugger;
+    return result
 }
 
 export {reuseNavigatorKey,cleanNavigationState};

From 70e834a0d597c2c0fddb2fcbe7f1a6eb91e50793 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 2 Mar 2026 11:30:58 +0100
Subject: [PATCH 12/27] performance is great again, last bug when returning to
 split navigators switching tabs does not work

---
 .../FreezeWrapper/getIsScreenBlurred/index.ts |  21 ++-
 .../useCustomRootStackNavigatorState/index.ts |  41 ++----
 .../reuseNavigatorKey.ts                      | 120 ++++--------------
 .../createSplitNavigator/index.tsx            |   2 +
 4 files changed, 61 insertions(+), 123 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred/index.ts b/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred/index.ts
index 0b51e817a0ba..12e12543c4cc 100644
--- a/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred/index.ts
+++ b/src/libs/Navigation/AppNavigator/FreezeWrapper/getIsScreenBlurred/index.ts
@@ -3,7 +3,26 @@ import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 
 function getIsScreenBlurred(state: NavigationState, currentRouteKey: string) {
     const lastFullScreenRoute = state.routes.findLast((route) => isFullScreenName(route.name));
-    return lastFullScreenRoute?.key !== currentRouteKey;
+
+    if (!lastFullScreenRoute) {
+        return false;
+    }
+
+    // Direct key match — screen is focused.
+    if (lastFullScreenRoute.key === currentRouteKey) {
+        return false;
+    }
+
+    // Key mismatch fallback: check if the current route and the focused route are the same navigator type.
+    // This handles the key-reuse optimization in useCustomRootStackNavigatorState where the rendered
+    // route keeps an old canonical key while the real navigation state has a newer key for the same
+    // navigator type. Without this check, FreezeWrapper would incorrectly freeze the active screen.
+    const currentRouteInState = state.routes.find((r) => r.key === currentRouteKey);
+    if (currentRouteInState?.name === lastFullScreenRoute.name) {
+        return false;
+    }
+
+    return true;
 }
 
 export default getIsScreenBlurred;
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index 0aa4d900220e..320de6c9a9f9 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,41 +1,24 @@
-import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
-import type { CustomStateHookProps } from '@libs/Navigation/PlatformStackNavigation/types';
-import reuseNavigatorKey, { cleanNavigationState } from './reuseNavigatorKey';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
+import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import reuseNavigatorKey from './reuseNavigatorKey';
 
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
-
-    const cleanState = cleanNavigationState(state)
-    const lastSplitIndex = cleanState.routes.findLastIndex((route) => isFullScreenName(route.name));
+    const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
     let indexToSlice = Math.max(0, lastSplitIndex);
     const hasPrevRoute = lastSplitIndex > 0;
-    const isPrevFullScreen = isFullScreenName(cleanState.routes.at(lastSplitIndex - 1)?.name);
+    const isPrevFullScreen = isFullScreenName(state.routes.at(lastSplitIndex - 1)?.name);
 
     // If the route before the last full screen is e.g. RHP, we should leave it in the rendered routes,
     // as there may be display issues (blank screen) when navigating back and recreating that route to render.
     if (hasPrevRoute && !isPrevFullScreen) {
         indexToSlice = lastSplitIndex - 1;
     }
-    const routesToRender = cleanState.routes.slice(indexToSlice, cleanState.routes.length);
-    return {...cleanState, routes: routesToRender, index: routesToRender.length - 1};
+
+    const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
+    const remappedRoutes = reuseNavigatorKey(routesToRender, state);
+
+    debugger;
+
+    return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index b50ff11d42de..d23c4d62e7c3 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -1,119 +1,53 @@
-import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
-import { screensWithEnteringAnimation } from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
-import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
-
-
-
-
-
+import type {ParamListBase, StackNavigationState} from '@react-navigation/native';
+import {screensWithEnteringAnimation} from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
+import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 
 /**
- * Remaps the key of a fullscreen navigator route in `routesToRender` to the canonical (first) occurrence key
- * of that navigator name found in the full navigation state.
- *
- * This allows React to reuse the already-mounted navigator component instead of remounting it,
- * avoiding expensive teardown/setup cycles. The real navigation state is left untouched, so
- * browser history still works correctly (the state always has unique keys).
+ * For each fullscreen navigator in routesToRender, checks if a route with the same name
+ * already exists in the full state (with a different key). If so, replaces the new route
+ * with the existing one updated with the new params — exactly mirroring what
+ * handlePushFullscreenAction did at the router level.
  *
- * Example: state=[RSN-key1, WSN-key2, RSN-key3], routesToRender=[WSN-key2, RSN-key3]
- *   → RSN-kopey3 is remapped to RSN-key1 (the first RSN in state, which is already mounted)
- *   → React sees [WSN-key2, RSN-key1] in both old and new render → reuses RSN-key1 component
+ * This causes React to reuse the already-mounted navigator component (same key),
+ * while the new params tell the navigator which screen to show.
+ * The real navigation state is untouched.
  */
 function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): StateRoutes {
-    debugger;
     return routesToRender.map((route) => {
         if (!isFullScreenName(route.name)) {
             return route;
         }
 
-        const firstOccurrence = fullState.routes.find((r) => r.name === route.name);
-        if (!firstOccurrence) {
+        // Find a route already in the stack with the same navigator name.
+        // A different key means it was pushed in a previous navigation action.
+        const existingRoute = fullState.routes.find((r) => r.name === route.name && r.key !== route.key);
+
+        if (!existingRoute) {
             return route;
         }
 
-        const canonicalKey = firstOccurrence.key;
-        const shouldRemap = canonicalKey !== route.key && !routesToRender.some((r) => r.key === canonicalKey);
-
-        if (!shouldRemap) {
+        // Avoid duplicate keys in the rendered list.
+        if (routesToRender.some((r) => r.key === existingRoute.key)) {
             return route;
         }
 
-        // Transfer animation marker from new key to canonical key so slide-in animation fires correctly.
+        // Transfer animation marker so the entering animation fires on the reused component.
         if (screensWithEnteringAnimation.has(route.key)) {
             screensWithEnteringAnimation.delete(route.key);
-            screensWithEnteringAnimation.add(canonicalKey);
-        }
-
-        return {...firstOccurrence, params: {...firstOccurrence.params, ...route.params}};
-    });
-}
-
-function cleanNavigationState(state) {
-    function processNavigator(navigatorState) {
-        if (!navigatorState?.routes) {
-            return navigatorState;
+            screensWithEnteringAnimation.add(existingRoute.key);
         }
 
-        const seenNames = new Map(); // name -> canonicalKey
-        const keyRemap = new Map(); // oldKey -> canonicalKey
-        const cleanedRoutesReversed = [];
-
-        // 1️⃣ iterujemy OD KOŃCA (nowsze mają priorytet)
-        for (let i = navigatorState.routes.length - 1; i >= 0; i--) {
-            const route = navigatorState.routes[i];
-
-            let nextRoute = route;
-
-            // rekurencja w dół
-            if (route.state) {
-                nextRoute = {
-                    ...route,
-                    state: processNavigator(route.state),
-                };
-            }
-
-            const canonicalKey = seenNames.get(route.name);
-
-            if (canonicalKey) {
-                // duplikat → zachowujemy nowszy route,
-                // ale mapujemy key na wcześniejszy
-                keyRemap.set(route.key, canonicalKey);
-
-                cleanedRoutesReversed.push({
-                    ...nextRoute,
-                    key: canonicalKey,
-                });
-            } else {
-                // pierwsze wystąpienie (od końca)
-                seenNames.set(route.name, route.key);
-                cleanedRoutesReversed.push(nextRoute);
-            }
-        }
-
-        const cleanedRoutes = cleanedRoutesReversed.reverse();
-        const validKeys = new Set(cleanedRoutes.map((r) => r.key));
-
-        // 2️⃣ naprawa history
-        let cleanedHistory = navigatorState.history;
-        if (Array.isArray(navigatorState.history)) {
-            cleanedHistory = navigatorState.history.map((key) => keyRemap.get(key) ?? key).filter((key) => validKeys.has(key));
-        }
-
-        // 3️⃣ naprawa index
-        const cleanedIndex = Math.min(navigatorState.index ?? 0, Math.max(cleanedRoutes.length - 1, 0));
-
+        // Mirror handlePushFullscreenAction:
+        // spread the existing route (preserves key and navigator state) and merge new params on top.
+        // The existing key causes React to reuse the mounted component.
+        // The merged params carry the new navigation target (screen/params) into the reused component.
         return {
-            ...navigatorState,
-            routes: cleanedRoutes,
-            history: cleanedHistory,
-            index: cleanedIndex,
+            ...existingRoute,
+            params: {...existingRoute.params, ...route.params},
         };
-    }
-    const result = processNavigator(state);
-    debugger;
-    return result
+    });
 }
 
-export {reuseNavigatorKey,cleanNavigationState};
+export default reuseNavigatorKey;
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx
index 4483297f6a1b..03b6d0f4a6bd 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx
@@ -13,11 +13,13 @@ import type {
 } from '@libs/Navigation/PlatformStackNavigation/types';
 import SidebarSpacerWrapper from './SidebarSpacerWrapper';
 import SplitRouter from './SplitRouter';
+import useNavigateOnParamsChange from './useNavigateOnParamsChange';
 import usePreserveNavigatorState from './usePreserveNavigatorState';
 
 function useCustomEffects(props: CustomEffectsHookProps) {
     useNavigationResetOnLayoutChange(props);
     usePreserveNavigatorState(props.state, props.parentRoute);
+    useNavigateOnParamsChange(props);
 }
 
 function useCustomSplitNavigatorState({state}: CustomStateHookProps) {

From 09ee767a3f2bacce9a89ded9f3884ba98a342761 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 2 Mar 2026 12:40:59 +0100
Subject: [PATCH 13/27] performance is great again, fix bug when navigating on
 the same split navigator

---
 .../reuseNavigatorKey.ts                      | 25 +++++++++----------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index d23c4d62e7c3..6633e2478401 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -1,6 +1,6 @@
-import type {ParamListBase, StackNavigationState} from '@react-navigation/native';
-import {screensWithEnteringAnimation} from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
-import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
+import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
+import { screensWithEnteringAnimation } from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
+import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
 
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 
@@ -9,19 +9,20 @@ type StateRoutes = StackNavigationState<ParamListBase>['routes'];
  * already exists in the full state (with a different key). If so, replaces the new route
  * with the existing one updated with the new params — exactly mirroring what
  * handlePushFullscreenAction did at the router level.
- *
  * This causes React to reuse the already-mounted navigator component (same key),
  * while the new params tell the navigator which screen to show.
  * The real navigation state is untouched.
  */
+
+
+
 function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): StateRoutes {
     return routesToRender.map((route) => {
-        if (!isFullScreenName(route.name)) {
+        if (!isFullScreenName(route.name) || fullState.routes.at(fullState.routes.length - 1)?.name === route.name) {
             return route;
         }
 
-        // Find a route already in the stack with the same navigator name.
-        // A different key means it was pushed in a previous navigation action.
+        // Find an already mounted route with the same navigator name
         const existingRoute = fullState.routes.find((r) => r.name === route.name && r.key !== route.key);
 
         if (!existingRoute) {
@@ -39,13 +40,11 @@ function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigati
             screensWithEnteringAnimation.add(existingRoute.key);
         }
 
-        // Mirror handlePushFullscreenAction:
-        // spread the existing route (preserves key and navigator state) and merge new params on top.
-        // The existing key causes React to reuse the mounted component.
-        // The merged params carry the new navigation target (screen/params) into the reused component.
         return {
-            ...existingRoute,
-            params: {...existingRoute.params, ...route.params},
+            ...existingRoute, // Preserve key and internal navigator state
+            params: {
+                ...route.params, // Apply params from the new navigation action
+            },
         };
     });
 }

From a7b74237ae40c4afa85b47c0107a53b7f8842e37 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 2 Mar 2026 13:08:56 +0100
Subject: [PATCH 14/27] refactor reuseNavigatorKey function

---
 .../reuseNavigatorKey.ts                      | 36 ++++++++++---------
 1 file changed, 20 insertions(+), 16 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index 6633e2478401..dac2390e5b9a 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -5,45 +5,49 @@ import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 
 /**
- * For each fullscreen navigator in routesToRender, checks if a route with the same name
- * already exists in the full state (with a different key). If so, replaces the new route
- * with the existing one updated with the new params — exactly mirroring what
- * handlePushFullscreenAction did at the router level.
- * This causes React to reuse the already-mounted navigator component (same key),
- * while the new params tell the navigator which screen to show.
- * The real navigation state is untouched.
+ * For each fullscreen navigator in routesToRender, checks whether a navigator
+ * with the same name is already mounted in the current navigation state.
+ *
+ * If such a route exists (with a different key), the new route is replaced
+ * with the existing one while applying the new params.
+ *
+ * This preserves the original route key so React can reuse the already-mounted
+ * navigator instance, while the updated params instruct it which screen to display.
+ *
+ * The actual navigation state is not mutated — this only affects what gets rendered.
  */
-
-
-
 function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): StateRoutes {
     return routesToRender.map((route) => {
-        if (!isFullScreenName(route.name) || fullState.routes.at(fullState.routes.length - 1)?.name === route.name) {
+        const previousRoute = fullState.routes.at(-2);
+
+        // Skip if this is not a fullscreen navigator or if we're already inside the same navigator
+        if (!isFullScreenName(route.name) || previousRoute?.name === route.name) {
             return route;
         }
 
-        // Find an already mounted route with the same navigator name
+        // Look for an already mounted navigator with the same name but a different key
         const existingRoute = fullState.routes.find((r) => r.name === route.name && r.key !== route.key);
 
         if (!existingRoute) {
             return route;
         }
 
-        // Avoid duplicate keys in the rendered list.
+        // Prevent rendering two routes with the same key
         if (routesToRender.some((r) => r.key === existingRoute.key)) {
             return route;
         }
 
-        // Transfer animation marker so the entering animation fires on the reused component.
+        // Move the entering-animation marker to the reused route key
+        // so the animation runs on the existing navigator instance
         if (screensWithEnteringAnimation.has(route.key)) {
             screensWithEnteringAnimation.delete(route.key);
             screensWithEnteringAnimation.add(existingRoute.key);
         }
 
         return {
-            ...existingRoute, // Preserve key and internal navigator state
+            ...existingRoute, // Reuse the mounted navigator (preserve key and internal state)
             params: {
-                ...route.params, // Apply params from the new navigation action
+                ...route.params, // Apply params from the incoming navigation action
             },
         };
     });

From c79f24e9d2dde31929def887d4cec1d54b3bbb54 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 2 Mar 2026 13:18:51 +0100
Subject: [PATCH 15/27] fix prettier and eslint, remove unnecessary hook from
 split navigator

---
 .../RootStackRouter.ts                        |  1 -
 .../createRootStackNavigator/index.tsx        |  6 +--
 .../useCustomRootStackNavigatorState/index.ts |  2 -
 .../reuseNavigatorKey.ts                      |  6 +--
 .../createSplitNavigator/index.tsx            |  2 -
 .../useNavigateOnParamsChange.ts              | 46 +++++++++++++++++++
 src/libs/Navigation/Navigation.ts             |  1 -
 7 files changed, 52 insertions(+), 12 deletions(-)
 create mode 100644 src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
index c1fe00c1dfa0..4f57fa322570 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
@@ -116,7 +116,6 @@ function RootStackRouter(options: RootStackNavigatorRouterOptions) {
     return {
         ...stackRouter,
         getStateForAction(state: StackNavigationState<ParamListBase>, action: RootStackNavigatorAction, configOptions: RouterConfigOptions) {
-
             // Evaluate navigation guards FIRST
             const guardState = handleNavigationGuards(state, action, configOptions, stackRouter);
             if (guardState) {
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx
index af6a121cd86f..b6138ecd540c 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/index.tsx
@@ -1,10 +1,10 @@
-import type { NavigationProp, NavigatorTypeBagBase, ParamListBase, StaticConfig, TypedNavigator } from '@react-navigation/native';
-import { createNavigatorFactory } from '@react-navigation/native';
+import type {NavigationProp, NavigatorTypeBagBase, ParamListBase, StaticConfig, TypedNavigator} from '@react-navigation/native';
+import {createNavigatorFactory} from '@react-navigation/native';
 import RootNavigatorExtraContent from '@components/Navigation/RootNavigatorExtraContent';
 import useNavigationResetOnLayoutChange from '@libs/Navigation/AppNavigator/useNavigationResetOnLayoutChange';
 import createPlatformStackNavigatorComponent from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent';
 import defaultPlatformStackScreenOptions from '@libs/Navigation/PlatformStackNavigation/defaultPlatformStackScreenOptions';
-import type { PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState } from '@libs/Navigation/PlatformStackNavigation/types';
+import type {PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState} from '@libs/Navigation/PlatformStackNavigation/types';
 import RootStackRouter from './RootStackRouter';
 import useCustomRootStackNavigatorState from './useCustomRootStackNavigatorState';
 
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index 320de6c9a9f9..2ae33c9b8f18 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -18,7 +18,5 @@ export default function useCustomRootStackNavigatorState({state}: CustomStateHoo
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
     const remappedRoutes = reuseNavigatorKey(routesToRender, state);
 
-    debugger;
-
     return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index dac2390e5b9a..d79fc67c93b2 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -1,6 +1,6 @@
-import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
-import { screensWithEnteringAnimation } from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
-import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
+import type {ParamListBase, StackNavigationState} from '@react-navigation/native';
+import {screensWithEnteringAnimation} from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
+import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx b/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx
index 03b6d0f4a6bd..4483297f6a1b 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/index.tsx
@@ -13,13 +13,11 @@ import type {
 } from '@libs/Navigation/PlatformStackNavigation/types';
 import SidebarSpacerWrapper from './SidebarSpacerWrapper';
 import SplitRouter from './SplitRouter';
-import useNavigateOnParamsChange from './useNavigateOnParamsChange';
 import usePreserveNavigatorState from './usePreserveNavigatorState';
 
 function useCustomEffects(props: CustomEffectsHookProps) {
     useNavigationResetOnLayoutChange(props);
     usePreserveNavigatorState(props.state, props.parentRoute);
-    useNavigateOnParamsChange(props);
 }
 
 function useCustomSplitNavigatorState({state}: CustomStateHookProps) {
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
new file mode 100644
index 000000000000..1e7eb1b5bd4d
--- /dev/null
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
@@ -0,0 +1,46 @@
+import {useEffect, useRef} from 'react';
+import type {CustomEffectsHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
+
+/**
+ * When reuseNavigatorKey remaps a new route to reuse an existing navigator component,
+ * the component keeps its old internal navigation state but receives new parentRoute.params
+ * pointing to a different screen. This hook detects that change and dispatches a navigate
+ * action within the split navigator so the correct screen is shown.
+ *
+ * Without this, clicking a sub-tab (e.g. wallet) while already inside a split navigator
+ * would change the URL but leave the displayed screen unchanged.
+ */
+function useNavigateOnParamsChange({navigation, parentRoute, state}: CustomEffectsHookProps) {
+    // Initialize with current params so we don't navigate on the first mount.
+    const lastHandledParamsRef = useRef(parentRoute?.params);
+
+    // No dependency array — runs after every render.
+    // The ref guard ensures we only act when params actually change.
+    useEffect(() => {
+        const currentParams = parentRoute?.params;
+
+        if (lastHandledParamsRef.current === currentParams) {
+            return;
+        }
+
+        lastHandledParamsRef.current = currentParams;
+
+        const screenToNavigate = currentParams && 'screen' in currentParams ? (currentParams.screen as string) : undefined;
+
+        if (!screenToNavigate) {
+            return;
+        }
+
+        // Already showing the correct screen — nothing to do.
+        const lastRoute = state.routes.at(-1);
+        if (lastRoute?.name === screenToNavigate) {
+            return;
+        }
+
+        const screenParams = currentParams && 'params' in currentParams ? (currentParams.params as Record<string, unknown>) : undefined;
+
+        navigation.navigate(screenToNavigate, screenParams);
+    });
+}
+
+export default useNavigateOnParamsChange;
diff --git a/src/libs/Navigation/Navigation.ts b/src/libs/Navigation/Navigation.ts
index 8009846422ef..6026d5a488bf 100644
--- a/src/libs/Navigation/Navigation.ts
+++ b/src/libs/Navigation/Navigation.ts
@@ -487,7 +487,6 @@ function goBack(backToRoute?: Route, options?: GoBackOptions) {
  * see the NAVIGATION.md documentation.
  */
 function popToSidebar() {
-
     setShouldPopToSidebar(false);
 
     const rootState = navigationRef.current?.getRootState();

From 1a9196856959ddf806f33aafdbcc70db0718a57b Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 2 Mar 2026 13:23:07 +0100
Subject: [PATCH 16/27] remove changes from jest test

---
 tests/navigation/NavigateTests.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tests/navigation/NavigateTests.tsx b/tests/navigation/NavigateTests.tsx
index 008cec2fd979..636b5995178e 100644
--- a/tests/navigation/NavigateTests.tsx
+++ b/tests/navigation/NavigateTests.tsx
@@ -210,7 +210,6 @@ describe('Navigate', () => {
                                 name: NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR,
                                 state: {
                                     index: 0,
-                                    stale: false,
                                     routes: [
                                         {
                                             name: SCREENS.SETTINGS.ROOT,

From 3863f2ae1f0048998442c6f79e1bfad4722fa33f Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Fri, 6 Mar 2026 16:57:47 +0100
Subject: [PATCH 17/27] block pushing duplicate of split navigator

---
 .../reuseNavigatorKey.ts                      | 32 +++++++++++++++++--
 .../createSplitNavigator/SplitRouter.ts       |  7 ++--
 src/libs/Navigation/NavigationRoot.tsx        |  3 ++
 .../helpers/linkTo/getMinimalAction.ts        | 13 ++++++--
 src/libs/Navigation/helpers/linkTo/index.ts   | 11 ++++++-
 5 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index d79fc67c93b2..63a4da9aa47f 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -4,6 +4,21 @@ import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 
+type RemappedStateRoute = StateRoutes[number] & {originalKey?: string};
+
+/**
+ * Tracks the mapping from a new route's key (originalKey) to the mounted navigator's key.
+ * This allows getMinimalAction to drill into the mounted navigator's preserved state
+ * even though the new route has no embedded state in the root navigation state.
+ *
+ * Example: when T3unFG is remapped to MBc.key, remappedKeyMap[T3unFGKey] = MBcKey.
+ */
+const remappedKeyMap: Record<string, string> = {};
+
+function getRemappedNavigatorKey(originalKey: string): string | undefined {
+    return remappedKeyMap[originalKey];
+}
+
 /**
  * For each fullscreen navigator in routesToRender, checks whether a navigator
  * with the same name is already mounted in the current navigation state.
@@ -16,7 +31,12 @@ type StateRoutes = StackNavigationState<ParamListBase>['routes'];
  *
  * The actual navigation state is not mutated — this only affects what gets rendered.
  */
-function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): StateRoutes {
+function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): RemappedStateRoute[] {
+    // Rebuild the mapping from scratch on every call so it always reflects the current render state.
+    for (const key of Object.keys(remappedKeyMap)) {
+        delete remappedKeyMap[key];
+    }
+
     return routesToRender.map((route) => {
         const previousRoute = fullState.routes.at(-2);
 
@@ -44,13 +64,21 @@ function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigati
             screensWithEnteringAnimation.add(existingRoute.key);
         }
 
+        // Track that route.key is rendered via existingRoute.key so that getMinimalAction
+        // can look up the mounted navigator's preserved state when route has no embedded state.
+        remappedKeyMap[route.key] = existingRoute.key;
+
         return {
-            ...existingRoute, // Reuse the mounted navigator (preserve key and internal state)
+            ...existingRoute, // Reuse the mounted navigator (preserve key so React doesn't unmount it)
+            state: undefined, // Clear old embedded state so getInitialState is called with the new params
             params: {
                 ...route.params, // Apply params from the incoming navigation action
             },
+            originalKey: route.key,
         };
     });
 }
 
+export type {RemappedStateRoute};
+export {getRemappedNavigatorKey};
 export default reuseNavigatorKey;
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts b/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts
index 397388f73693..2754a5f6dd8c 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts
@@ -75,7 +75,8 @@ function adaptStateIfNecessary({state, options: {sidebarScreen, defaultCentralSc
             const previousSameNavigator = rootState?.routes.filter((route) => route.name === parentRoute.name).at(-2);
 
             // If we have optimization for not rendering all split navigators, then last selected option may not be in the state. In this case state has to be read from the preserved state.
-            const previousSameNavigatorState = previousSameNavigator?.state ?? (previousSameNavigator?.key ? getPreservedNavigatorState(previousSameNavigator.key) : undefined);
+            const previousSameNavigatorKey = (previousSameNavigator as {originalKey?: string} | undefined)?.originalKey ?? previousSameNavigator?.key;
+            const previousSameNavigatorState = previousSameNavigator?.state ?? (previousSameNavigatorKey ? getPreservedNavigatorState(previousSameNavigatorKey) : undefined);
             const previousSelectedCentralScreen =
                 previousSameNavigatorState?.routes && previousSameNavigatorState.routes.length > 1 ? previousSameNavigatorState.routes.at(-1)?.name : undefined;
 
@@ -136,7 +137,9 @@ function SplitRouter(options: SplitNavigatorRouterOptions) {
         },
 
         getInitialState({routeNames, routeParamList, routeGetIdList}: RouterConfigOptions) {
-            const initialState = getPreservedNavigatorState(options.parentRoute.key) ?? stackRouter.getInitialState({routeNames, routeParamList, routeGetIdList});
+            const parentRouteKey: string = (options.parentRoute as {originalKey?: string}).originalKey ?? options.parentRoute.key;
+            debugger;
+            const initialState = getPreservedNavigatorState(parentRouteKey) ?? stackRouter.getInitialState({routeNames, routeParamList, routeGetIdList});
             const maybeAdaptedState = adaptStateIfNecessary({state: initialState, options});
 
             // If we needed to modify the state we need to rehydrate it to get keys for new routes.
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 2844878af164..788e4a567b1f 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -240,6 +240,9 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
+
+        console.log("dupa")
+        console.log(state)
     };
 
     const onReadyWithSentry = useCallback(() => {
diff --git a/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts b/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts
index 9eab2f6f8717..f7d56d884256 100644
--- a/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts
+++ b/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts
@@ -13,19 +13,26 @@ type MinimalAction = {
  *
  * @param action action generated by getActionFromState
  * @param state The root state
+ * @param getStateForRouteKey optional fallback to look up a navigator's state by route key
+ *        when the route has no embedded state in the root state (e.g. because it is rendered
+ *        via a remapped key from reuseNavigatorKey and never mounted under its own key).
  * @returns minimalAction minimal action is the action that we should dispatch
  */
-function getMinimalAction(action: NavigationAction, state: NavigationState): MinimalAction {
+function getMinimalAction(action: NavigationAction, state: NavigationState, getStateForRouteKey?: (key: string) => State | undefined): MinimalAction {
     let currentAction: NavigationAction = action;
     let currentState: State | undefined = state;
     let currentTargetKey: string | undefined;
 
     while (currentAction.payload && 'name' in currentAction.payload && currentState?.routes[currentState.index ?? -1].name === currentAction.payload.name) {
-        if (!currentState?.routes[currentState.index ?? -1].state) {
+        // Cast to a known shape so TypeScript can type .key and .state without falling back to any.
+        const currentRoute = currentState?.routes[currentState.index ?? -1] as {key: string; state?: State} | undefined;
+        const routeState = currentRoute?.state ?? getStateForRouteKey?.(currentRoute?.key ?? '');
+
+        if (!routeState) {
             break;
         }
 
-        currentState = currentState?.routes[currentState.index ?? -1].state;
+        currentState = routeState;
         currentTargetKey = currentState?.key;
 
         const payload = currentAction.payload as ActionPayload;
diff --git a/src/libs/Navigation/helpers/linkTo/index.ts b/src/libs/Navigation/helpers/linkTo/index.ts
index 63126c40e1c7..47077f0b6533 100644
--- a/src/libs/Navigation/helpers/linkTo/index.ts
+++ b/src/libs/Navigation/helpers/linkTo/index.ts
@@ -1,6 +1,8 @@
 import {getActionFromState} from '@react-navigation/core';
 import type {NavigationContainerRef, NavigationState, PartialState} from '@react-navigation/native';
 import {findFocusedRoute, StackActions} from '@react-navigation/native';
+import {getRemappedNavigatorKey} from '@libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey';
+import {getPreservedNavigatorState} from '@libs/Navigation/AppNavigator/createSplitNavigator/usePreserveNavigatorState';
 import {getMatchingFullScreenRoute, isFullScreenName} from '@libs/Navigation/helpers/getAdaptedStateFromPath';
 import getStateFromPath from '@libs/Navigation/helpers/getStateFromPath';
 import normalizePath from '@libs/Navigation/helpers/normalizePath';
@@ -182,6 +184,13 @@ export default function linkTo(navigation: NavigationContainerRef<RootNavigatorP
         }
     }
 
-    const {action: minimalAction} = getMinimalAction(action, navigation.getRootState());
+    // When a route has no embedded state (e.g. because reuseNavigatorKey is rendering it
+    // via a different key), look up the preserved state of the actually mounted navigator.
+    const getStateForRouteKey = (key: string) => {
+        const mountedKey = getRemappedNavigatorKey(key) ?? key;
+        return getPreservedNavigatorState(mountedKey);
+    };
+
+    const {action: minimalAction} = getMinimalAction(action, navigation.getRootState(), getStateForRouteKey);
     navigation.dispatch(minimalAction);
 }

From a61eadf8b013d5441170e2847580299649cf5f04 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 9 Mar 2026 10:01:32 +0100
Subject: [PATCH 18/27] refactor code

---
 .../GetStateForActionHandlers.ts              | 59 ++++++++++++++++---
 .../RootStackRouter.ts                        |  1 +
 .../index.android.ts                          |  4 +-
 .../index.ios.ts                              |  4 +-
 .../useCustomRootStackNavigatorState/index.ts |  4 +-
 .../reuseNavigatorKey.ts                      | 31 +++++++---
 .../createSplitNavigator/SplitRouter.ts       |  1 -
 .../useNavigateOnParamsChange.ts              |  2 +-
 src/libs/Navigation/NavigationRoot.tsx        |  3 -
 .../helpers/linkTo/getMinimalAction.ts        |  2 +-
 src/libs/Navigation/helpers/linkTo/index.ts   |  2 +-
 11 files changed, 84 insertions(+), 29 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index 52a53673ec17..fba96f0202c4 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -1,15 +1,57 @@
-import type {CommonActions, RouterConfigOptions, StackActionType, StackNavigationState} from '@react-navigation/native';
-import {StackActions} from '@react-navigation/native';
-import type {ParamListBase, Router} from '@react-navigation/routers';
+import type { CommonActions, RouterConfigOptions, StackActionType, StackNavigationState } from '@react-navigation/native';
+import { StackActions } from '@react-navigation/native';
+import type { ParamListBase, Router } from '@react-navigation/routers';
 import SCREENS_WITH_NAVIGATION_TAB_BAR from '@components/Navigation/TopLevelNavigationTabBar/SCREENS_WITH_NAVIGATION_TAB_BAR';
 import getIsNarrowLayout from '@libs/getIsNarrowLayout';
 import Log from '@libs/Log';
-import {isSplitNavigatorName} from '@libs/Navigation/helpers/isNavigatorName';
-import {SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
+import { isSplitNavigatorName } from '@libs/Navigation/helpers/isNavigatorName';
+import { SPLIT_TO_SIDEBAR } from '@libs/Navigation/linkingConfig/RELATIONS';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import SCREENS from '@src/SCREENS';
-import type {OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType} from './types';
+import type { OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType } from './types';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 const MODAL_ROUTES_TO_DISMISS = new Set<string>([
     NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR,
@@ -120,9 +162,10 @@ function handlePushFullscreenAction(
     configOptions: RouterConfigOptions,
     stackRouter: Router<StackNavigationState<ParamListBase>, CommonActions.Action | StackActionType>,
 ) {
-    const navigatorName = action.payload.name;
     const targetScreen = action.payload?.params && 'screen' in action.payload.params ? (action.payload?.params?.screen as string) : undefined;
+    const navigatorName = action.payload.name;
 
+    // If we navigate to the central screen of the split navigator, we need to filter this navigator from preloadedRoutes to remove a sidebar screen from the state
     const shouldFilterPreloadedRoutes =
         getIsNarrowLayout() &&
         isSplitNavigatorName(navigatorName) &&
@@ -130,7 +173,6 @@ function handlePushFullscreenAction(
         state.preloadedRoutes?.some((preloadedRoute) => preloadedRoute.name === navigatorName);
 
     const adjustedState = shouldFilterPreloadedRoutes ? {...state, preloadedRoutes: state.preloadedRoutes.filter((preloadedRoute) => preloadedRoute.name !== navigatorName)} : state;
-
     const stateWithNavigator = stackRouter.getStateForAction(adjustedState, action, configOptions);
 
     if (!stateWithNavigator) {
@@ -138,6 +180,7 @@ function handlePushFullscreenAction(
         return null;
     }
 
+    // Transitioning to all central screens in each split should be animated
     const lastFullScreenRoute = stateWithNavigator.routes.at(-1);
     if (lastFullScreenRoute?.key && targetScreen && !SCREENS_WITH_NAVIGATION_TAB_BAR.includes(targetScreen)) {
         screensWithEnteringAnimation.add(lastFullScreenRoute.key);
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
index 4f57fa322570..8eceff88a361 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/RootStackRouter.ts
@@ -113,6 +113,7 @@ function isNavigatingToModalFromModal(state: StackNavigationState<ParamListBase>
 
 function RootStackRouter(options: RootStackNavigatorRouterOptions) {
     const stackRouter = StackRouter(options);
+
     return {
         ...stackRouter,
         getStateForAction(state: StackNavigationState<ParamListBase>, action: RootStackNavigatorAction, configOptions: RouterConfigOptions) {
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts
index c060873e981f..789a412b9bb3 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.android.ts
@@ -1,6 +1,6 @@
 import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import reuseNavigatorKey from './reuseNavigatorKey';
+import buildOptimizedRoutes from './reuseNavigatorKey';
 
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
@@ -9,6 +9,6 @@ export default function useCustomRootStackNavigatorState({state}: CustomStateHoo
     // Always preserve the previous fullscreen route so React can reuse the mounted navigator component on navigation.
     const indexToSlice = Math.max(0, lastSplitIndex - 1);
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
-    const remappedRoutes = reuseNavigatorKey(routesToRender, state);
+    const remappedRoutes = buildOptimizedRoutes(routesToRender, state);
     return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts
index b23fffcb7893..ae5a7f2a85e5 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ios.ts
@@ -4,7 +4,7 @@ import {SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import type {NavigationRoute, SplitNavigatorName} from '@libs/Navigation/types';
 import NAVIGATORS from '@src/NAVIGATORS';
-import reuseNavigatorKey from './reuseNavigatorKey';
+import buildOptimizedRoutes from './reuseNavigatorKey';
 
 // Swiping back on iOS does not work properly when the preloaded route has gestureEnabled set to false.
 // Therefore, on screens where swiping should work, preloadedRoutes will be an empty array during rendering to ensure swiping works properly.
@@ -37,7 +37,7 @@ function getShouldHidePreloadedRoutes(route?: NavigationRoute) {
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
     const routesToRender = state.routes.slice(Math.max(0, lastSplitIndex - 1), state.routes.length);
-    const remappedRoutes = reuseNavigatorKey(routesToRender, state);
+    const remappedRoutes = buildOptimizedRoutes(routesToRender, state);
     const stateToRender = {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
     if (getShouldHidePreloadedRoutes(stateToRender.routes.at(-1))) {
         return {...stateToRender, preloadedRoutes: []};
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index 2ae33c9b8f18..ec5fec7ed29b 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,6 +1,6 @@
 import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
-import reuseNavigatorKey from './reuseNavigatorKey';
+import buildOptimizedRoutes from './reuseNavigatorKey';
 
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
@@ -16,7 +16,7 @@ export default function useCustomRootStackNavigatorState({state}: CustomStateHoo
     }
 
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
-    const remappedRoutes = reuseNavigatorKey(routesToRender, state);
+    const remappedRoutes = buildOptimizedRoutes(routesToRender, state);
 
     return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index 63a4da9aa47f..dc04d8c68552 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -1,6 +1,21 @@
-import type {ParamListBase, StackNavigationState} from '@react-navigation/native';
-import {screensWithEnteringAnimation} from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
-import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
+import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
+import { screensWithEnteringAnimation } from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
+import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 
@@ -11,7 +26,7 @@ type RemappedStateRoute = StateRoutes[number] & {originalKey?: string};
  * This allows getMinimalAction to drill into the mounted navigator's preserved state
  * even though the new route has no embedded state in the root navigation state.
  *
- * Example: when T3unFG is remapped to MBc.key, remappedKeyMap[T3unFGKey] = MBcKey.
+ * Example: when Inbox.key = key1 is remapped to Inbox.key = key2, remappedKeyMap[key2] = key1.
  */
 const remappedKeyMap: Record<string, string> = {};
 
@@ -31,14 +46,14 @@ function getRemappedNavigatorKey(originalKey: string): string | undefined {
  *
  * The actual navigation state is not mutated — this only affects what gets rendered.
  */
-function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigationState<ParamListBase>): RemappedStateRoute[] {
+function buildOptimizedRoutes(routesToRender: StateRoutes, state: StackNavigationState<ParamListBase>): RemappedStateRoute[] {
     // Rebuild the mapping from scratch on every call so it always reflects the current render state.
     for (const key of Object.keys(remappedKeyMap)) {
         delete remappedKeyMap[key];
     }
 
     return routesToRender.map((route) => {
-        const previousRoute = fullState.routes.at(-2);
+        const previousRoute = state.routes.at(-2);
 
         // Skip if this is not a fullscreen navigator or if we're already inside the same navigator
         if (!isFullScreenName(route.name) || previousRoute?.name === route.name) {
@@ -46,7 +61,7 @@ function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigati
         }
 
         // Look for an already mounted navigator with the same name but a different key
-        const existingRoute = fullState.routes.find((r) => r.name === route.name && r.key !== route.key);
+        const existingRoute = state.routes.find((r) => r.name === route.name && r.key !== route.key);
 
         if (!existingRoute) {
             return route;
@@ -81,4 +96,4 @@ function reuseNavigatorKey(routesToRender: StateRoutes, fullState: StackNavigati
 
 export type {RemappedStateRoute};
 export {getRemappedNavigatorKey};
-export default reuseNavigatorKey;
+export default buildOptimizedRoutes;
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts b/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts
index 2754a5f6dd8c..7cc4b0dd4a1a 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/SplitRouter.ts
@@ -138,7 +138,6 @@ function SplitRouter(options: SplitNavigatorRouterOptions) {
 
         getInitialState({routeNames, routeParamList, routeGetIdList}: RouterConfigOptions) {
             const parentRouteKey: string = (options.parentRoute as {originalKey?: string}).originalKey ?? options.parentRoute.key;
-            debugger;
             const initialState = getPreservedNavigatorState(parentRouteKey) ?? stackRouter.getInitialState({routeNames, routeParamList, routeGetIdList});
             const maybeAdaptedState = adaptStateIfNecessary({state: initialState, options});
 
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
index 1e7eb1b5bd4d..66631f627200 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
@@ -2,7 +2,7 @@ import {useEffect, useRef} from 'react';
 import type {CustomEffectsHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 
 /**
- * When reuseNavigatorKey remaps a new route to reuse an existing navigator component,
+ * When buildOptimizedRoutes remaps a new route to reuse an existing navigator component,
  * the component keeps its old internal navigation state but receives new parentRoute.params
  * pointing to a different screen. This hook detects that change and dispatches a navigate
  * action within the split navigator so the correct screen is shown.
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 788e4a567b1f..2844878af164 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -240,9 +240,6 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
-
-        console.log("dupa")
-        console.log(state)
     };
 
     const onReadyWithSentry = useCallback(() => {
diff --git a/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts b/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts
index f7d56d884256..28f1fde85fdb 100644
--- a/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts
+++ b/src/libs/Navigation/helpers/linkTo/getMinimalAction.ts
@@ -15,7 +15,7 @@ type MinimalAction = {
  * @param state The root state
  * @param getStateForRouteKey optional fallback to look up a navigator's state by route key
  *        when the route has no embedded state in the root state (e.g. because it is rendered
- *        via a remapped key from reuseNavigatorKey and never mounted under its own key).
+ *        via a remapped key from buildOptimizedRoutes and never mounted under its own key).
  * @returns minimalAction minimal action is the action that we should dispatch
  */
 function getMinimalAction(action: NavigationAction, state: NavigationState, getStateForRouteKey?: (key: string) => State | undefined): MinimalAction {
diff --git a/src/libs/Navigation/helpers/linkTo/index.ts b/src/libs/Navigation/helpers/linkTo/index.ts
index 47077f0b6533..c84e27a0a4a2 100644
--- a/src/libs/Navigation/helpers/linkTo/index.ts
+++ b/src/libs/Navigation/helpers/linkTo/index.ts
@@ -184,7 +184,7 @@ export default function linkTo(navigation: NavigationContainerRef<RootNavigatorP
         }
     }
 
-    // When a route has no embedded state (e.g. because reuseNavigatorKey is rendering it
+    // When a route has no embedded state (e.g. because buildOptimizedRoutes is rendering it
     // via a different key), look up the preserved state of the actually mounted navigator.
     const getStateForRouteKey = (key: string) => {
         const mountedKey = getRemappedNavigatorKey(key) ?? key;

From 6d617247e66497aed273b14f147ef2ed79b74155 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 9 Mar 2026 10:13:11 +0100
Subject: [PATCH 19/27] npm run prettier

---
 .../GetStateForActionHandlers.ts              | 54 +++----------------
 .../reuseNavigatorKey.ts                      | 21 ++------
 2 files changed, 9 insertions(+), 66 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
index fba96f0202c4..f4833a3281c6 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts
@@ -1,57 +1,15 @@
-import type { CommonActions, RouterConfigOptions, StackActionType, StackNavigationState } from '@react-navigation/native';
-import { StackActions } from '@react-navigation/native';
-import type { ParamListBase, Router } from '@react-navigation/routers';
+import type {CommonActions, RouterConfigOptions, StackActionType, StackNavigationState} from '@react-navigation/native';
+import {StackActions} from '@react-navigation/native';
+import type {ParamListBase, Router} from '@react-navigation/routers';
 import SCREENS_WITH_NAVIGATION_TAB_BAR from '@components/Navigation/TopLevelNavigationTabBar/SCREENS_WITH_NAVIGATION_TAB_BAR';
 import getIsNarrowLayout from '@libs/getIsNarrowLayout';
 import Log from '@libs/Log';
-import { isSplitNavigatorName } from '@libs/Navigation/helpers/isNavigatorName';
-import { SPLIT_TO_SIDEBAR } from '@libs/Navigation/linkingConfig/RELATIONS';
+import {isSplitNavigatorName} from '@libs/Navigation/helpers/isNavigatorName';
+import {SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS';
 import CONST from '@src/CONST';
 import NAVIGATORS from '@src/NAVIGATORS';
 import SCREENS from '@src/SCREENS';
-import type { OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType } from './types';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+import type {OpenDomainSplitActionType, OpenWorkspaceSplitActionType, PushActionType, ReplaceActionType, ToggleSidePanelWithHistoryActionType} from './types';
 
 const MODAL_ROUTES_TO_DISMISS = new Set<string>([
     NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR,
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index dc04d8c68552..181ec46f6f6e 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -1,21 +1,6 @@
-import type { ParamListBase, StackNavigationState } from '@react-navigation/native';
-import { screensWithEnteringAnimation } from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
-import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+import type {ParamListBase, StackNavigationState} from '@react-navigation/native';
+import {screensWithEnteringAnimation} from '@libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers';
+import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
 
 type StateRoutes = StackNavigationState<ParamListBase>['routes'];
 

From 165359e32bdec134672e054e6afdd0764c8833a0 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 9 Mar 2026 13:19:15 +0100
Subject: [PATCH 20/27] fix empty tab on mobile ios

---
 .../useCustomRootStackNavigatorState/index.ts       | 13 +++++++++++--
 .../reuseNavigatorKey.ts                            | 13 +++++++++++++
 src/libs/Navigation/NavigationRoot.tsx              |  3 +++
 src/libs/Navigation/navigationRef.ts                |  2 ++
 4 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index ec5fec7ed29b..d9e0af277088 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,7 +1,12 @@
-import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
-import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
+import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
+import type { CustomStateHookProps } from '@libs/Navigation/PlatformStackNavigation/types';
 import buildOptimizedRoutes from './reuseNavigatorKey';
 
+
+
+
+
+
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
@@ -18,5 +23,9 @@ export default function useCustomRootStackNavigatorState({state}: CustomStateHoo
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
     const remappedRoutes = buildOptimizedRoutes(routesToRender, state);
 
+
+    console.log("to render")
+    console.log({...state, routes: remappedRoutes, index: remappedRoutes.length - 1});
+
     return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index 181ec46f6f6e..b527c4aafa68 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -57,6 +57,19 @@ function buildOptimizedRoutes(routesToRender: StateRoutes, state: StackNavigatio
             return route;
         }
 
+        // Prevent reordering of native views: skip remap if there are routes between existingRoute
+        // and the current route in the full state that are also being rendered. Remapping in this
+        // case would swap their positions in the array and cause a blank screen in the native stack.
+        const existingRouteIndexInFull = state.routes.findIndex((r) => r.key === existingRoute.key);
+        const currentRouteIndexInFull = state.routes.findIndex((r) => r.key === route.key);
+        const hasIntermediateRenderedRoutes = state.routes
+            .slice(existingRouteIndexInFull + 1, currentRouteIndexInFull)
+            .some((routeBetween) => routesToRender.some((r) => r.key === routeBetween.key));
+
+        if (hasIntermediateRenderedRoutes) {
+            return route;
+        }
+
         // Move the entering-animation marker to the reused route key
         // so the animation runs on the existing navigator instance
         if (screensWithEnteringAnimation.has(route.key)) {
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 2844878af164..519a492aa6d0 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -240,6 +240,9 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
+
+        console.log("dupa dupa")
+        console.log(state)
     };
 
     const onReadyWithSentry = useCallback(() => {
diff --git a/src/libs/Navigation/navigationRef.ts b/src/libs/Navigation/navigationRef.ts
index 17742e5d0937..87adf1c246ee 100644
--- a/src/libs/Navigation/navigationRef.ts
+++ b/src/libs/Navigation/navigationRef.ts
@@ -3,4 +3,6 @@ import type {NavigationRef} from './types';
 
 const navigationRef: NavigationRef = createNavigationContainerRef();
 
+// document.navigationRef = navigationRef;
+
 export default navigationRef;

From 8419336a110b62af72adcf26501c15471fcc2583 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Mon, 9 Mar 2026 13:24:21 +0100
Subject: [PATCH 21/27] fix prettier

---
 .../useCustomRootStackNavigatorState/index.ts        | 12 +++---------
 src/libs/Navigation/NavigationRoot.tsx               |  3 ---
 2 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index d9e0af277088..e536b0ea817c 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -1,12 +1,7 @@
-import { isFullScreenName } from '@libs/Navigation/helpers/isNavigatorName';
-import type { CustomStateHookProps } from '@libs/Navigation/PlatformStackNavigation/types';
+import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
+import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 import buildOptimizedRoutes from './reuseNavigatorKey';
 
-
-
-
-
-
 // This is an optimization to keep mounted only last few screens in the stack.
 export default function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
     const lastSplitIndex = state.routes.findLastIndex((route) => isFullScreenName(route.name));
@@ -23,8 +18,7 @@ export default function useCustomRootStackNavigatorState({state}: CustomStateHoo
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
     const remappedRoutes = buildOptimizedRoutes(routesToRender, state);
 
-
-    console.log("to render")
+    console.log('to render');
     console.log({...state, routes: remappedRoutes, index: remappedRoutes.length - 1});
 
     return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 519a492aa6d0..2844878af164 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -240,9 +240,6 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
-
-        console.log("dupa dupa")
-        console.log(state)
     };
 
     const onReadyWithSentry = useCallback(() => {

From d9d0fc69c7b448abe2f13cb5a9ad57e693bf9a6c Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Tue, 10 Mar 2026 11:33:22 +0100
Subject: [PATCH 22/27] wip

---
 src/libs/Navigation/NavigationRoot.tsx | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 2844878af164..862dd9fdf792 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -240,6 +240,8 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
+
+        console.log('Navigation state changed', state);
     };
 
     const onReadyWithSentry = useCallback(() => {

From 3049e5901509931eed034c8cce4748936b659446 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Tue, 10 Mar 2026 11:33:27 +0100
Subject: [PATCH 23/27] wip

---
 .../reuseNavigatorKey.ts                             | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index b527c4aafa68..907d800ddf6f 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -9,7 +9,7 @@ type RemappedStateRoute = StateRoutes[number] & {originalKey?: string};
 /**
  * Tracks the mapping from a new route's key (originalKey) to the mounted navigator's key.
  * This allows getMinimalAction to drill into the mounted navigator's preserved state
- * even though the new route has no embedded state in the root navigation state.
+ * when looking up the nested state for a route that is rendered via a remapped key.
  *
  * Example: when Inbox.key = key1 is remapped to Inbox.key = key2, remappedKeyMap[key2] = key1.
  */
@@ -27,7 +27,9 @@ function getRemappedNavigatorKey(originalKey: string): string | undefined {
  * with the existing one while applying the new params.
  *
  * This preserves the original route key so React can reuse the already-mounted
- * navigator instance, while the updated params instruct it which screen to display.
+ * navigator instance. The existing navigator's internal state is kept intact so its
+ * navigation history is not lost. useNavigateOnParamsChange will forward-navigate
+ * to the correct screen based on the updated params.
  *
  * The actual navigation state is not mutated — this only affects what gets rendered.
  */
@@ -78,12 +80,14 @@ function buildOptimizedRoutes(routesToRender: StateRoutes, state: StackNavigatio
         }
 
         // Track that route.key is rendered via existingRoute.key so that getMinimalAction
-        // can look up the mounted navigator's preserved state when route has no embedded state.
+        // can look up the mounted navigator's preserved state.
         remappedKeyMap[route.key] = existingRoute.key;
 
         return {
             ...existingRoute, // Reuse the mounted navigator (preserve key so React doesn't unmount it)
-            state: undefined, // Clear old embedded state so getInitialState is called with the new params
+            // Do not clear state — keeping the existing navigator's internal state preserves its
+            // navigation history. useNavigateOnParamsChange will forward-navigate to the correct
+            // screen based on the updated params, so history is extended rather than reset.
             params: {
                 ...route.params, // Apply params from the incoming navigation action
             },

From 9dfa35653c6147e8aae44c27c7acad1a017eb001 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Wed, 11 Mar 2026 12:36:02 +0100
Subject: [PATCH 24/27] resolve state problem

---
 .../reuseNavigatorKey.ts                      | 19 +++++++++++++------
 .../useNavigateOnParamsChange.ts              | 15 +++++++++------
 2 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index 907d800ddf6f..0e12b31b96c9 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -59,16 +59,23 @@ function buildOptimizedRoutes(routesToRender: StateRoutes, state: StackNavigatio
             return route;
         }
 
+        const existingRouteIndexInFull = state.routes.findIndex((r) => r.key === existingRoute.key);
+        const currentRouteIndexInFull = state.routes.findIndex((r) => r.key === route.key);
+        const routesBetween = state.routes.slice(existingRouteIndexInFull + 1, currentRouteIndexInFull);
+
         // Prevent reordering of native views: skip remap if there are routes between existingRoute
         // and the current route in the full state that are also being rendered. Remapping in this
         // case would swap their positions in the array and cause a blank screen in the native stack.
-        const existingRouteIndexInFull = state.routes.findIndex((r) => r.key === existingRoute.key);
-        const currentRouteIndexInFull = state.routes.findIndex((r) => r.key === route.key);
-        const hasIntermediateRenderedRoutes = state.routes
-            .slice(existingRouteIndexInFull + 1, currentRouteIndexInFull)
-            .some((routeBetween) => routesToRender.some((r) => r.key === routeBetween.key));
+        const hasIntermediateRenderedRoutes = routesBetween.some((routeBetween) => routesToRender.some((r) => r.key === routeBetween.key));
+
+        // Skip remap if there are routes of a different navigator type between existingRoute and
+        // currentRoute in the full navigation state. Without this guard, on platforms that only
+        // render one route at a time (web), the current route would be rendered under existingRoute's
+        // key and never mounted under its own key — so it would never receive embedded state,
+        // which breaks the URL and back navigation.
+        const hasIntermediateRoutesOfDifferentType = routesBetween.some((routeBetween) => routeBetween.name !== route.name);
 
-        if (hasIntermediateRenderedRoutes) {
+        if (hasIntermediateRenderedRoutes || hasIntermediateRoutesOfDifferentType) {
             return route;
         }
 
diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
index 66631f627200..a301cf4826b4 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
@@ -1,3 +1,4 @@
+import isEqual from 'lodash/isEqual';
 import {useEffect, useRef} from 'react';
 import type {CustomEffectsHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 
@@ -11,8 +12,10 @@ import type {CustomEffectsHookProps} from '@libs/Navigation/PlatformStackNavigat
  * would change the URL but leave the displayed screen unchanged.
  */
 function useNavigateOnParamsChange({navigation, parentRoute, state}: CustomEffectsHookProps) {
-    // Initialize with current params so we don't navigate on the first mount.
-    const lastHandledParamsRef = useRef(parentRoute?.params);
+    // Initialized to undefined (not the current params) so that the first render also checks
+    // whether the navigator's initial state matches the target screen. This is required for
+    // freshly-mounted navigators whose getInitialState may not navigate to the correct screen.
+    const lastHandledParamsRef = useRef<Record<string, unknown> | undefined>(undefined);
 
     // No dependency array — runs after every render.
     // The ref guard ensures we only act when params actually change.
@@ -31,14 +34,14 @@ function useNavigateOnParamsChange({navigation, parentRoute, state}: CustomEffec
             return;
         }
 
-        // Already showing the correct screen — nothing to do.
+        const screenParams = currentParams && 'params' in currentParams ? (currentParams.params as Record<string, unknown>) : undefined;
+
+        // Already showing the correct screen with the same params — nothing to do.
         const lastRoute = state.routes.at(-1);
-        if (lastRoute?.name === screenToNavigate) {
+        if (lastRoute?.name === screenToNavigate && isEqual(lastRoute?.params, screenParams)) {
             return;
         }
 
-        const screenParams = currentParams && 'params' in currentParams ? (currentParams.params as Record<string, unknown>) : undefined;
-
         navigation.navigate(screenToNavigate, screenParams);
     });
 }

From f8d17422e83cda06e04e0f6c8c8c97ac8a197f47 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Wed, 11 Mar 2026 13:10:29 +0100
Subject: [PATCH 25/27] working on performance

---
 .../useCustomRootStackNavigatorState/index.ts |  3 --
 .../Navigation/helpers/getPathFromState.ts    | 53 +++++++++++++++++--
 src/libs/Navigation/linkingConfig/index.ts    |  2 +
 3 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
index e536b0ea817c..ec5fec7ed29b 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/index.ts
@@ -18,8 +18,5 @@ export default function useCustomRootStackNavigatorState({state}: CustomStateHoo
     const routesToRender = state.routes.slice(indexToSlice, state.routes.length);
     const remappedRoutes = buildOptimizedRoutes(routesToRender, state);
 
-    console.log('to render');
-    console.log({...state, routes: remappedRoutes, index: remappedRoutes.length - 1});
-
     return {...state, routes: remappedRoutes, index: remappedRoutes.length - 1};
 }
diff --git a/src/libs/Navigation/helpers/getPathFromState.ts b/src/libs/Navigation/helpers/getPathFromState.ts
index fa48471b6f8d..09a6de0e096e 100644
--- a/src/libs/Navigation/helpers/getPathFromState.ts
+++ b/src/libs/Navigation/helpers/getPathFromState.ts
@@ -1,7 +1,7 @@
 import {findFocusedRoute, getPathFromState as RNGetPathFromState} from '@react-navigation/native';
 import type {NavigationState, PartialState} from '@react-navigation/routers';
-import {linkingConfig} from '@libs/Navigation/linkingConfig';
-import {normalizedConfigs} from '@libs/Navigation/linkingConfig/config';
+import {getRemappedNavigatorKey} from '@libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey';
+import {config, normalizedConfigs} from '@libs/Navigation/linkingConfig/config';
 import type {DynamicRouteSuffix} from '@src/ROUTES';
 import type {Screen} from '@src/SCREENS';
 import {dynamicRoutePaths} from './isDynamicRouteSuffix';
@@ -21,8 +21,53 @@ function isDynamicRouteScreen(screenName: Screen): boolean {
     return dynamicRoutePaths.has(screenPath as DynamicRouteSuffix);
 }
 
+/**
+ * When buildOptimizedRoutes remaps a new route (e.g. RSN-key3) to reuse an existing
+ * mounted navigator (RSN-key1), the new route is never mounted under its own key and
+ * its embedded state in the root navigation state remains undefined. This causes
+ * getPathFromState to serialize route.params directly, producing a broken URL.
+ *
+ * This function patches the state by copying the mounted navigator's current state to
+ * the logical (unmounted) route so URL generation can drill into the correct nested state.
+ */
+function patchStateWithRemappedStates(state: State): State {
+    if (!('routes' in state) || !state.routes) {
+        return state;
+    }
+
+    let changed = false;
+    const routes = (state as NavigationState).routes;
+
+    const patchedRoutes = routes.map((route) => {
+        if (route.state) {
+            return route;
+        }
+
+        const remappedKey = getRemappedNavigatorKey(route.key);
+        if (!remappedKey) {
+            return route;
+        }
+
+        const remappedRoute = routes.find((r) => r.key === remappedKey);
+        if (!remappedRoute?.state) {
+            return route;
+        }
+
+        changed = true;
+        return {...route, state: remappedRoute.state};
+    });
+
+    if (!changed) {
+        return state;
+    }
+
+    return {...(state as NavigationState), routes: patchedRoutes};
+}
+
 const getPathFromState = (state: State): string => {
-    const focusedRoute = findFocusedRoute(state);
+    const patchedState = patchStateWithRemappedStates(state);
+
+    const focusedRoute = findFocusedRoute(patchedState);
     const screenName = focusedRoute?.name ?? '';
 
     // Handle dynamic route screens that require special path that is placed in state
@@ -31,7 +76,7 @@ const getPathFromState = (state: State): string => {
     }
 
     // For regular routes, use React Navigation's default path generation
-    const path = RNGetPathFromState(state, linkingConfig.config);
+    const path = RNGetPathFromState(patchedState, config);
 
     return path;
 };
diff --git a/src/libs/Navigation/linkingConfig/index.ts b/src/libs/Navigation/linkingConfig/index.ts
index 4eec394d5bcb..65f20eb3870e 100644
--- a/src/libs/Navigation/linkingConfig/index.ts
+++ b/src/libs/Navigation/linkingConfig/index.ts
@@ -1,12 +1,14 @@
 /* eslint-disable @typescript-eslint/naming-convention */
 import type {LinkingOptions} from '@react-navigation/native';
 import getAdaptedStateFromPath from '@libs/Navigation/helpers/getAdaptedStateFromPath';
+import getPathFromState from '@libs/Navigation/helpers/getPathFromState';
 import type {RootNavigatorParamList} from '@libs/Navigation/types';
 import {config} from './config';
 import prefixes from './prefixes';
 
 const linkingConfig: LinkingOptions<RootNavigatorParamList> = {
     getStateFromPath: getAdaptedStateFromPath,
+    getPathFromState,
     prefixes,
     config,
 };

From 31dba0b6d5375ccd1253e5ec9cf7e27a5ab156f0 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Wed, 11 Mar 2026 13:21:43 +0100
Subject: [PATCH 26/27] working solution, but not full performance gain

---
 .../reuseNavigatorKey.ts                                 | 9 +--------
 src/libs/Navigation/NavigationRoot.tsx                   | 2 --
 2 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
index 0e12b31b96c9..b886d865327d 100644
--- a/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
+++ b/src/libs/Navigation/AppNavigator/createRootStackNavigator/useCustomRootStackNavigatorState/reuseNavigatorKey.ts
@@ -68,14 +68,7 @@ function buildOptimizedRoutes(routesToRender: StateRoutes, state: StackNavigatio
         // case would swap their positions in the array and cause a blank screen in the native stack.
         const hasIntermediateRenderedRoutes = routesBetween.some((routeBetween) => routesToRender.some((r) => r.key === routeBetween.key));
 
-        // Skip remap if there are routes of a different navigator type between existingRoute and
-        // currentRoute in the full navigation state. Without this guard, on platforms that only
-        // render one route at a time (web), the current route would be rendered under existingRoute's
-        // key and never mounted under its own key — so it would never receive embedded state,
-        // which breaks the URL and back navigation.
-        const hasIntermediateRoutesOfDifferentType = routesBetween.some((routeBetween) => routeBetween.name !== route.name);
-
-        if (hasIntermediateRenderedRoutes || hasIntermediateRoutesOfDifferentType) {
+        if (hasIntermediateRenderedRoutes) {
             return route;
         }
 
diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx
index 862dd9fdf792..2844878af164 100644
--- a/src/libs/Navigation/NavigationRoot.tsx
+++ b/src/libs/Navigation/NavigationRoot.tsx
@@ -240,8 +240,6 @@ function NavigationRoot({authenticated, lastVisitedPath, initialUrl, onReady}: N
         // We want to clean saved scroll offsets for screens that aren't anymore in the state.
         cleanStaleScrollOffsets(state);
         cleanPreservedNavigatorStates(state);
-
-        console.log('Navigation state changed', state);
     };
 
     const onReadyWithSentry = useCallback(() => {

From fa56030f802051dc2ce33658505a2956cb0d60a4 Mon Sep 17 00:00:00 2001
From: sumo_slonik <jakub.nowakowski@swmansion.com>
Date: Wed, 11 Mar 2026 14:52:11 +0100
Subject: [PATCH 27/27] working on performance gain

---
 .../createSplitNavigator/useNavigateOnParamsChange.ts         | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
index a301cf4826b4..276b5bf146aa 100644
--- a/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
+++ b/src/libs/Navigation/AppNavigator/createSplitNavigator/useNavigateOnParamsChange.ts
@@ -1,4 +1,4 @@
-import isEqual from 'lodash/isEqual';
+import {deepEqual} from 'fast-equals';
 import {useEffect, useRef} from 'react';
 import type {CustomEffectsHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
 
@@ -38,7 +38,7 @@ function useNavigateOnParamsChange({navigation, parentRoute, state}: CustomEffec
 
         // Already showing the correct screen with the same params — nothing to do.
         const lastRoute = state.routes.at(-1);
-        if (lastRoute?.name === screenToNavigate && isEqual(lastRoute?.params, screenParams)) {
+        if (lastRoute?.name === screenToNavigate && deepEqual(lastRoute?.params, screenParams)) {
             return;
         }
 
