diff --git a/src/CONST.ts b/src/CONST.ts index 07a65a6b5bd9..467911c7242e 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -6408,7 +6408,10 @@ const CONST = { ACTIVE_WORKSPACE_ID: 'ACTIVE_WORKSPACE_ID', RETRY_LAZY_REFRESHED: 'RETRY_LAZY_REFRESHED', LAST_REFRESH_TIMESTAMP: 'LAST_REFRESH_TIMESTAMP', - LAST_VISITED_WORKSPACES_TAB_PATH: 'LAST_VISITED_WORKSPACES_TAB_PATH', + LAST_VISITED_TAB_PATH: { + WORKSPACES: 'LAST_VISITED_WORKSPACES_TAB_PATH', + SETTINGS: 'LAST_VISITED_SETTINGS_TAB_PATH', + }, }, RESERVATION_TYPE: { diff --git a/src/components/Navigation/NavigationTabBar/index.tsx b/src/components/Navigation/NavigationTabBar/index.tsx index 1b7bd2a66f15..7098b75ad11e 100644 --- a/src/components/Navigation/NavigationTabBar/index.tsx +++ b/src/components/Navigation/NavigationTabBar/index.tsx @@ -23,7 +23,12 @@ import clearSelectedText from '@libs/clearSelectedText/clearSelectedText'; import getPlatform from '@libs/getPlatform'; import interceptAnonymousUser from '@libs/interceptAnonymousUser'; import {getPreservedNavigatorState} from '@libs/Navigation/AppNavigator/createSplitNavigator/usePreserveNavigatorState'; -import {getLastVisitedWorkspacesTabPath, getLastVisitedWorkspaceTabScreen, getWorkspacesTabStateFromSessionStorage} from '@libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen'; +import { + getLastVisitedTabPath, + getLastVisitedWorkspaceTabScreen, + getSettingsTabStateFromSessionStorage, + getWorkspacesTabStateFromSessionStorage, +} from '@libs/Navigation/helpers/lastVisitedTabPathUtils'; import {buildCannedSearchQuery, buildSearchQueryJSON, buildSearchQueryString} from '@libs/SearchQueryUtils'; import type {BrickRoad} from '@libs/WorkspacesSettingsUtils'; import {getChatTabBrickRoad} from '@libs/WorkspacesSettingsUtils'; @@ -121,9 +126,17 @@ function NavigationTabBar({selectedTab, isTooltipAllowed = false, isTopLevelBar return; } interceptAnonymousUser(() => { + const settingsTabState = getSettingsTabStateFromSessionStorage(); + if (settingsTabState && !shouldUseNarrowLayout) { + const lastVisitedSettingsRoute = getLastVisitedTabPath(settingsTabState); + if (lastVisitedSettingsRoute) { + Navigation.navigate(lastVisitedSettingsRoute); + return; + } + } Navigation.navigate(ROUTES.SETTINGS); }); - }, [selectedTab]); + }, [selectedTab, shouldUseNarrowLayout]); /** * The settings tab is related to SettingsSplitNavigator and WorkspaceSplitNavigator. @@ -185,7 +198,7 @@ function NavigationTabBar({selectedTab, isTooltipAllowed = false, isTopLevelBar // If the path stored in the session storage leads to a settings screen, we just navigate to it on a wide layout. // On a small screen, we want to go to the page containing the bottom tab bar (ROUTES.SETTINGS or ROUTES.SETTINGS_WORKSPACES) when changing tabs if (workspacesTabState && !shouldUseNarrowLayout) { - const lastVisitedSettingsRoute = getLastVisitedWorkspacesTabPath(workspacesTabState); + const lastVisitedSettingsRoute = getLastVisitedTabPath(workspacesTabState); if (lastVisitedSettingsRoute) { Navigation.navigate(lastVisitedSettingsRoute); return; diff --git a/src/libs/Navigation/NavigationRoot.tsx b/src/libs/Navigation/NavigationRoot.tsx index 477283ed4219..1af0ac2adfcf 100644 --- a/src/libs/Navigation/NavigationRoot.tsx +++ b/src/libs/Navigation/NavigationRoot.tsx @@ -27,8 +27,8 @@ import AppNavigator from './AppNavigator'; import {cleanPreservedNavigatorStates} from './AppNavigator/createSplitNavigator/usePreserveNavigatorState'; import customGetPathFromState from './helpers/customGetPathFromState'; import getAdaptedStateFromPath from './helpers/getAdaptedStateFromPath'; -import {saveWorkspacesTabPathToSessionStorage} from './helpers/getLastVisitedWorkspaceTabScreen'; import {isWorkspacesTabScreenName} from './helpers/isNavigatorName'; +import {saveSettingsTabPathToSessionStorage, saveWorkspacesTabPathToSessionStorage} from './helpers/lastVisitedTabPathUtils'; import {linkingConfig} from './linkingConfig'; import Navigation, {navigationRef} from './Navigation'; @@ -75,6 +75,8 @@ function parseAndLogRoute(state: NavigationState) { Navigation.setIsNavigationReady(); if (isWorkspacesTabScreenName(state.routes.at(-1)?.name)) { saveWorkspacesTabPathToSessionStorage(currentPath); + } else if (state.routes.at(-1)?.name === NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR) { + saveSettingsTabPathToSessionStorage(currentPath); } // Fullstory Page navigation tracking diff --git a/src/libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen/index.native.ts b/src/libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen/index.native.ts deleted file mode 100644 index b9ed7bd1785d..000000000000 --- a/src/libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen/index.native.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type {NavigationState, PartialState} from '@react-navigation/native'; -import type {Route} from '@src/ROUTES'; - -function clearSessionStorage() {} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function saveWorkspacesTabPathToSessionStorage(url: string) {} - -function getWorkspacesTabStateFromSessionStorage(): PartialState | undefined { - return undefined; -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function getLastVisitedWorkspacesTabPath(state: NavigationState | PartialState): Route | undefined { - return undefined; -} - -function getLastVisitedWorkspaceTabScreen() { - return undefined; -} - -export {clearSessionStorage, getLastVisitedWorkspaceTabScreen, getLastVisitedWorkspacesTabPath, saveWorkspacesTabPathToSessionStorage, getWorkspacesTabStateFromSessionStorage}; diff --git a/src/libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen/index.ts b/src/libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen/index.ts deleted file mode 100644 index fed6de39ff11..000000000000 --- a/src/libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type {NavigationState, PartialState} from '@react-navigation/native'; -import {findFocusedRoute} from '@react-navigation/native'; -import getStateFromPath from '@libs/Navigation/helpers/getStateFromPath'; -import CONST from '@src/CONST'; -import type {Route} from '@src/ROUTES'; - -function clearSessionStorage() { - sessionStorage.clear(); -} - -function saveWorkspacesTabPathToSessionStorage(url: string) { - sessionStorage.setItem(CONST.SESSION_STORAGE_KEYS.LAST_VISITED_WORKSPACES_TAB_PATH, url); -} - -function getWorkspacesTabStateFromSessionStorage(): PartialState | undefined { - const lastVisitedWorkspacesTabPath = sessionStorage.getItem(CONST.SESSION_STORAGE_KEYS.LAST_VISITED_WORKSPACES_TAB_PATH); - if (!lastVisitedWorkspacesTabPath) { - return undefined; - } - return getStateFromPath(lastVisitedWorkspacesTabPath as Route); -} - -function getWorkspacesTabScreenNameFromState(state?: PartialState) { - return state?.routes.at(-1)?.state?.routes.at(-1)?.name; -} - -function getLastVisitedWorkspacesTabPath(state: NavigationState | PartialState): Route | undefined { - const lastVisitedWorkspacesTabPath = findFocusedRoute(state)?.path; - if (!lastVisitedWorkspacesTabPath) { - return undefined; - } - return lastVisitedWorkspacesTabPath as Route; -} - -function getLastVisitedWorkspaceTabScreen() { - const workspacesTabState = getWorkspacesTabStateFromSessionStorage(); - const workspacesTabScreenName = getWorkspacesTabScreenNameFromState(workspacesTabState); - return workspacesTabScreenName; -} - -export {clearSessionStorage, getLastVisitedWorkspaceTabScreen, getLastVisitedWorkspacesTabPath, saveWorkspacesTabPathToSessionStorage, getWorkspacesTabStateFromSessionStorage}; diff --git a/src/libs/Navigation/helpers/isNavigatorName.ts b/src/libs/Navigation/helpers/isNavigatorName.ts index f9a713a7caa2..1f2e01358720 100644 --- a/src/libs/Navigation/helpers/isNavigatorName.ts +++ b/src/libs/Navigation/helpers/isNavigatorName.ts @@ -1,5 +1,5 @@ import {SIDEBAR_TO_SPLIT, SPLIT_TO_SIDEBAR} from '@libs/Navigation/linkingConfig/RELATIONS'; -import type {FullScreenName, OnboardingFlowName, SplitNavigatorName, SplitNavigatorSidebarScreen, WorkspacesTabScreenName} from '@libs/Navigation/types'; +import type {FullScreenName, OnboardingFlowName, SplitNavigatorName, SplitNavigatorSidebarScreen, WorkspacesTabNavigatorName} from '@libs/Navigation/types'; import NAVIGATORS from '@src/NAVIGATORS'; import SCREENS from '@src/SCREENS'; @@ -50,7 +50,7 @@ function isSidebarScreenName(screen: string | undefined) { } function isWorkspacesTabScreenName(screen: string | undefined) { - return checkIfScreenHasMatchingNameToSetValues(screen, WORKSPACES_TAB_SET); + return checkIfScreenHasMatchingNameToSetValues(screen, WORKSPACES_TAB_SET); } export {isFullScreenName, isOnboardingFlowName, isSidebarScreenName, isSplitNavigatorName, isWorkspacesTabScreenName}; diff --git a/src/libs/Navigation/helpers/lastVisitedTabPathUtils/index.native.ts b/src/libs/Navigation/helpers/lastVisitedTabPathUtils/index.native.ts new file mode 100644 index 000000000000..9b4bcb0c62b8 --- /dev/null +++ b/src/libs/Navigation/helpers/lastVisitedTabPathUtils/index.native.ts @@ -0,0 +1,36 @@ +import type {NavigationState, PartialState} from '@react-navigation/native'; +import type {Route} from '@src/ROUTES'; + +function clearSessionStorage() {} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function saveWorkspacesTabPathToSessionStorage(url: string) {} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function saveSettingsTabPathToSessionStorage(url: string) {} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +function getLastVisitedTabPath(state: NavigationState | PartialState): Route | undefined { + return undefined; +} + +function getWorkspacesTabStateFromSessionStorage() { + return undefined; +} +function getSettingsTabStateFromSessionStorage() { + return undefined; +} + +function getLastVisitedWorkspaceTabScreen() { + return undefined; +} + +export { + clearSessionStorage, + getLastVisitedWorkspaceTabScreen, + getLastVisitedTabPath, + saveSettingsTabPathToSessionStorage, + getSettingsTabStateFromSessionStorage, + saveWorkspacesTabPathToSessionStorage, + getWorkspacesTabStateFromSessionStorage, +}; diff --git a/src/libs/Navigation/helpers/lastVisitedTabPathUtils/index.ts b/src/libs/Navigation/helpers/lastVisitedTabPathUtils/index.ts new file mode 100644 index 000000000000..b422ea0e4d5a --- /dev/null +++ b/src/libs/Navigation/helpers/lastVisitedTabPathUtils/index.ts @@ -0,0 +1,75 @@ +import type {NavigationState, PartialState} from '@react-navigation/native'; +import {findFocusedRoute} from '@react-navigation/native'; +import type {ValueOf} from 'type-fest'; +import getStateFromPath from '@libs/Navigation/helpers/getStateFromPath'; +import CONST from '@src/CONST'; +import type {Route} from '@src/ROUTES'; + +type LastVisitedTabPathKey = ValueOf; + +/** + * Clears all session storage data. + */ +function clearSessionStorage() { + sessionStorage.clear(); +} + +/** + * Generic function to save a path to session storage by key + */ +function saveTabPathToSessionStorage(key: LastVisitedTabPathKey, url: string) { + sessionStorage.setItem(key, url); +} + +/** + * Converts stored path to navigation state + */ +function getTabStateFromSessionStorage(key: LastVisitedTabPathKey) { + const path = sessionStorage.getItem(key) as Route | undefined; + if (!path) { + return undefined; + } + return getStateFromPath(path); +} + +/** + * Generic function to extract the path from currently focused route + */ +function getLastVisitedTabPath(state: NavigationState | PartialState) { + const focusedRoute = findFocusedRoute(state); + if (!focusedRoute) { + return undefined; + } + return focusedRoute.path as Route; +} + +function saveWorkspacesTabPathToSessionStorage(url: string) { + saveTabPathToSessionStorage(CONST.SESSION_STORAGE_KEYS.LAST_VISITED_TAB_PATH.WORKSPACES, url); +} + +function getWorkspacesTabStateFromSessionStorage() { + return getTabStateFromSessionStorage(CONST.SESSION_STORAGE_KEYS.LAST_VISITED_TAB_PATH.WORKSPACES); +} + +function saveSettingsTabPathToSessionStorage(url: string) { + saveTabPathToSessionStorage(CONST.SESSION_STORAGE_KEYS.LAST_VISITED_TAB_PATH.SETTINGS, url); +} + +function getSettingsTabStateFromSessionStorage() { + return getTabStateFromSessionStorage(CONST.SESSION_STORAGE_KEYS.LAST_VISITED_TAB_PATH.SETTINGS); +} + +function getLastVisitedWorkspaceTabScreen() { + const workspacesTabState = getWorkspacesTabStateFromSessionStorage(); + return workspacesTabState?.routes?.at(-1)?.state?.routes?.at(-1)?.name; +} + +export { + clearSessionStorage, + getLastVisitedWorkspaceTabScreen, + getLastVisitedTabPath, + saveSettingsTabPathToSessionStorage, + getSettingsTabStateFromSessionStorage, + saveWorkspacesTabPathToSessionStorage, + getWorkspacesTabStateFromSessionStorage, +}; diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 84dfd67f1239..87423aa671ba 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -2051,7 +2051,8 @@ type SearchFullscreenNavigatorName = typeof NAVIGATORS.SEARCH_FULLSCREEN_NAVIGAT type FullScreenName = SplitNavigatorName | SearchFullscreenNavigatorName; -type WorkspacesTabScreenName = typeof NAVIGATORS.WORKSPACE_HUB_SPLIT_NAVIGATOR | typeof NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR; +// There are two split navigators which can be displayed when the Workspaces tab is selected +type WorkspacesTabNavigatorName = typeof NAVIGATORS.WORKSPACE_HUB_SPLIT_NAVIGATOR | typeof NAVIGATORS.WORKSPACE_SPLIT_NAVIGATOR; type WorkspaceScreenName = keyof WorkspaceSplitNavigatorParamList; @@ -2136,5 +2137,5 @@ export type { TestDriveModalNavigatorParamList, WorkspaceScreenName, TestDriveDemoNavigatorParamList, - WorkspacesTabScreenName, + WorkspacesTabNavigatorName, }; diff --git a/src/libs/actions/SignInRedirect.ts b/src/libs/actions/SignInRedirect.ts index a02bbbea7546..d0cfc5352156 100644 --- a/src/libs/actions/SignInRedirect.ts +++ b/src/libs/actions/SignInRedirect.ts @@ -1,6 +1,6 @@ import Onyx from 'react-native-onyx'; import {getMicroSecondOnyxErrorWithMessage} from '@libs/ErrorUtils'; -import {clearSessionStorage} from '@libs/Navigation/helpers/getLastVisitedWorkspaceTabScreen'; +import {clearSessionStorage} from '@libs/Navigation/helpers/lastVisitedTabPathUtils'; import type {OnyxKey} from '@src/ONYXKEYS'; import ONYXKEYS from '@src/ONYXKEYS'; import {clearAllPolicies} from './Policy/Policy';