Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/components/AvatarWithDisplayName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ type AvatarWithDisplayNameProps = {

/** Transactions inside report */
transactions?: TransactionListItemType[];

/** Whether to open the parent report link in the current tab if possible */
openParentReportInCurrentTab?: boolean;
};

const fallbackIcon: Icon = {
Expand Down Expand Up @@ -156,6 +159,7 @@ function AvatarWithDisplayName({
shouldEnableDetailPageNavigation = false,
shouldUseCustomSearchTitleName = false,
transactions = [],
openParentReportInCurrentTab = false,
}: AvatarWithDisplayNameProps) {
const [parentReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`, {canEvict: false, canBeMissing: false});
const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}) ?? CONST.EMPTY_OBJECT;
Expand Down Expand Up @@ -267,6 +271,7 @@ function AvatarWithDisplayName({
parentReportID={report?.parentReportID}
parentReportActionID={report?.parentReportActionID}
pressableStyles={[styles.alignSelfStart, styles.mw100]}
openParentReportInCurrentTab={openParentReportInCurrentTab}
/>
)}
{!!subtitle && (
Expand Down
3 changes: 3 additions & 0 deletions src/components/HeaderWithBackButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ function HeaderWithBackButton({
progressBarPercentage,
style,
subTitleLink = '',
openParentReportInCurrentTab = false,
}: HeaderWithBackButtonProps) {
const theme = useTheme();
const styles = useThemeStyles();
Expand Down Expand Up @@ -101,6 +102,7 @@ function HeaderWithBackButton({
report={report}
policy={policy}
shouldEnableDetailPageNavigation={shouldEnableDetailPageNavigation}
openParentReportInCurrentTab={openParentReportInCurrentTab}
/>
);
}
Expand Down Expand Up @@ -133,6 +135,7 @@ function HeaderWithBackButton({
title,
titleColor,
translate,
openParentReportInCurrentTab,
]);

return (
Expand Down
3 changes: 3 additions & 0 deletions src/components/HeaderWithBackButton/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ type HeaderWithBackButtonProps = Partial<ChildrenProps> & {

/** The URL link associated with the attachment's subtitle, if available */
subTitleLink?: string;

/** Whether to open the parent report link in the current tab if possible */
openParentReportInCurrentTab?: boolean;
};

export type {ThreeDotsMenuItem};
Expand Down
1 change: 1 addition & 0 deletions src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ function MoneyRequestHeader({report, parentReportAction, policy, onBackButtonPre
shouldDisplayHelpButton={!isReportInRHP}
onBackButtonPress={onBackButtonPress}
shouldEnableDetailPageNavigation
openParentReportInCurrentTab
>
{!shouldUseNarrowLayout && (
<View style={[styles.flexRow, styles.gap2]}>
Expand Down
47 changes: 45 additions & 2 deletions src/components/ParentNavigationSubtitle.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import {useRoute} from '@react-navigation/native';
import React from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
import useRootNavigationState from '@hooks/useRootNavigationState';
import useThemeStyles from '@hooks/useThemeStyles';
import {isFullScreenName} from '@libs/Navigation/helpers/isNavigatorName';
import Navigation from '@libs/Navigation/Navigation';
import type {SearchFullscreenNavigatorParamList} from '@libs/Navigation/types';
import {getReportAction, shouldReportActionBeVisible} from '@libs/ReportActionsUtils';
import {canUserPerformWriteAction as canUserPerformWriteActionReportUtils} from '@libs/ReportUtils';
import CONST from '@src/CONST';
import type {ParentNavigationSummaryParams} from '@src/languages/params';
import NAVIGATORS from '@src/NAVIGATORS';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback';
import Text from './Text';

Expand All @@ -24,14 +30,26 @@ type ParentNavigationSubtitleProps = {

/** PressableWithoutFeedback additional styles */
pressableStyles?: StyleProp<ViewStyle>;

/** Whether to open the parent report link in the current tab if possible */
openParentReportInCurrentTab?: boolean;
};

function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportActionID, parentReportID = '', pressableStyles}: ParentNavigationSubtitleProps) {
function ParentNavigationSubtitle({
parentNavigationSubtitleData,
parentReportActionID,
parentReportID = '',
pressableStyles,
openParentReportInCurrentTab = false,
}: ParentNavigationSubtitleProps) {
const currentRoute = useRoute();
const styles = useThemeStyles();
const {workspaceName, reportName} = parentNavigationSubtitleData;
const {translate} = useLocalize();
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`);
const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`, {canBeMissing: false});
const canUserPerformWriteAction = canUserPerformWriteActionReportUtils(report);
const isReportInRHP = currentRoute.name === SCREENS.SEARCH.REPORT_RHP;
const currentFullScreenRoute = useRootNavigationState((state) => state?.routes?.findLast((route) => isFullScreenName(route.name)));

// We should not display the parent navigation subtitle if the user does not have access to the parent chat (the reportName is empty in this case)
if (!reportName) {
Expand All @@ -43,6 +61,31 @@ function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportAct
onPress={() => {
const parentAction = getReportAction(parentReportID, parentReportActionID);
const isVisibleAction = shouldReportActionBeVisible(parentAction, parentAction?.reportActionID ?? CONST.DEFAULT_NUMBER_ID, canUserPerformWriteAction);

if (openParentReportInCurrentTab && isReportInRHP) {
// If the report is displayed in RHP in Reports tab, we want to stay in the current tab after opening the parent report

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for adding these comments, always better to add more with this logic

if (currentFullScreenRoute?.name === NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR) {
const lastRoute = currentFullScreenRoute?.state?.routes.at(-1);
if (lastRoute?.name === SCREENS.SEARCH.MONEY_REQUEST_REPORT) {
const moneyRequestReportID = (lastRoute?.params as SearchFullscreenNavigatorParamList[typeof SCREENS.SEARCH.MONEY_REQUEST_REPORT])?.reportID;
// If the parent report is already displayed underneath RHP, simply dismiss the modal
if (moneyRequestReportID === parentReportID) {
Navigation.dismissModal();
return;
}
}

Navigation.navigate(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID: parentReportID}));
return;
}

// If the parent report is already displayed underneath RHP, simply dismiss the modal
if (Navigation.getTopmostReportId() === parentReportID) {
Navigation.dismissModal();
return;
}
}

if (isVisibleAction) {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parentReportID, parentReportActionID));
} else {
Expand Down
25 changes: 17 additions & 8 deletions src/libs/Navigation/AppNavigator/AuthScreens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import getCurrentUrl from '@libs/Navigation/currentUrl';
import Navigation from '@libs/Navigation/Navigation';
import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
import Presentation from '@libs/Navigation/PlatformStackNavigation/navigationOptions/presentation';
import type {PlatformStackNavigationOptions} from '@libs/Navigation/PlatformStackNavigation/types';
import type {AuthScreensParamList} from '@libs/Navigation/types';
import NetworkConnection from '@libs/NetworkConnection';
import onyxSubscribe from '@libs/onyxSubscribe';
Expand Down Expand Up @@ -59,7 +60,12 @@ import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
import createRootStackNavigator from './createRootStackNavigator';
import {reportsSplitsWithEnteringAnimation, settingsSplitWithEnteringAnimation, workspaceSplitsWithoutEnteringAnimation} from './createRootStackNavigator/GetStateForActionHandlers';
import {
reportsSplitsWithEnteringAnimation,
searchFullscreenWithEnteringAnimation,
settingsSplitWithEnteringAnimation,
workspaceSplitsWithoutEnteringAnimation,
} from './createRootStackNavigator/GetStateForActionHandlers';
import defaultScreenOptions from './defaultScreenOptions';
import {ShareModalStackNavigator} from './ModalStackNavigators';
import ExplanationModalNavigator from './Navigators/ExplanationModalNavigator';
Expand Down Expand Up @@ -445,27 +451,30 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
};
};

const getSplitNavigatorOptions =
(routesWithEnteringAnimation: Set<string>) =>
const getFullScreenNavigatorOptions =
(routesWithEnteringAnimation: Set<string>, defaultOptions: PlatformStackNavigationOptions) =>
({route}: {route: RouteProp<AuthScreensParamList>}) => {
// We don't need to do anything special for the wide screen.
if (!shouldUseNarrowLayout) {
return rootNavigatorScreenOptions.splitNavigator;
return defaultOptions;
}
// On the narrow screen, we want to animate this navigator if pushed SplitNavigator includes desired screen
const animationEnabled = routesWithEnteringAnimation.has(route.key);

return {
...rootNavigatorScreenOptions.splitNavigator,
...defaultOptions,
animation: animationEnabled ? Animations.SLIDE_FROM_RIGHT : Animations.NONE,
};
};

// Animation is enabled when navigating to the report screen
const getReportsSplitNavigatorOptions = getSplitNavigatorOptions(reportsSplitsWithEnteringAnimation);
const getReportsSplitNavigatorOptions = getFullScreenNavigatorOptions(reportsSplitsWithEnteringAnimation, rootNavigatorScreenOptions.splitNavigator);

// Animation is enabled when navigating to any screen different than SCREENS.SETTINGS.ROOT
const getSettingsSplitNavigatorOptions = getSplitNavigatorOptions(settingsSplitWithEnteringAnimation);
const getSettingsSplitNavigatorOptions = getFullScreenNavigatorOptions(settingsSplitWithEnteringAnimation, rootNavigatorScreenOptions.splitNavigator);

// Animation is enabled when navigating to SCREENS.SEARCH.MONEY_REQUEST_REPORT
const getSearchFullscreenNavigatorOptions = getFullScreenNavigatorOptions(searchFullscreenWithEnteringAnimation, rootNavigatorScreenOptions.fullScreen);

const clearStatus = () => {
User.clearCustomStatus();
Expand Down Expand Up @@ -516,7 +525,7 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
/>
<RootStack.Screen
name={NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR}
options={rootNavigatorScreenOptions.fullScreen}
options={getSearchFullscreenNavigatorOptions}
getComponent={loadSearchNavigator}
/>
<RootStack.Screen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import type {CommonActions, RouterConfigOptions, StackActionType, StackNavigatio
import {StackActions} from '@react-navigation/native';
import type {ParamListBase, Router} from '@react-navigation/routers';
import Log from '@libs/Log';
import getPolicyIDFromState from '@libs/Navigation/helpers/getPolicyIDFromState';
import type {RootNavigatorParamList, State} from '@libs/Navigation/types';
import type {RootNavigatorParamList} from '@libs/Navigation/types';
import * as SearchQueryUtils from '@libs/SearchQueryUtils';
import NAVIGATORS from '@src/NAVIGATORS';
import SCREENS from '@src/SCREENS';
Expand All @@ -29,7 +28,7 @@ const MODAL_ROUTES_TO_DISMISS: string[] = [
const workspaceSplitsWithoutEnteringAnimation = new Set<string>();
const reportsSplitsWithEnteringAnimation = new Set<string>();
const settingsSplitWithEnteringAnimation = new Set<string>();

const searchFullscreenWithEnteringAnimation = new Set<string>();
/**
* Handles the OPEN_WORKSPACE_SPLIT action.
* If the user is on other tab than settings and the workspace split is "remembered", this action will be called after pressing the settings tab.
Expand Down Expand Up @@ -202,44 +201,23 @@ function handlePushSearchPageAction(
action: PushActionType,
configOptions: RouterConfigOptions,
stackRouter: Router<StackNavigationState<ParamListBase>, CommonActions.Action | StackActionType>,
setActiveWorkspaceID: (workspaceID: string | undefined) => void,
) {
let updatedAction = action;
const currentParams = action.payload.params as RootNavigatorParamList[typeof NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR];
if (currentParams?.screen === SCREENS.SEARCH.ROOT) {
const searchParams = currentParams?.params;
const queryJSON = SearchQueryUtils.buildSearchQueryJSON(searchParams.q);
if (!queryJSON) {
return null;
}
const stateWithSearchFullscreenNavigator = stackRouter.getStateForAction(state, action, configOptions);

if (!queryJSON.policyID) {
const policyID = getPolicyIDFromState(state as State<RootNavigatorParamList>);
if (!stateWithSearchFullscreenNavigator) {
Log.hmmm('[handlePushSettingsAction] SearchFullscreenNavigator has not been found in the navigation state.');
return null;
}

if (policyID) {
queryJSON.policyID = policyID;
} else {
delete queryJSON.policyID;
}
} else {
setActiveWorkspaceID(queryJSON.policyID);
}
const lastFullScreenRoute = stateWithSearchFullscreenNavigator.routes.at(-1);
const actionPayloadScreen = action.payload?.params && 'screen' in action.payload.params ? action.payload?.params?.screen : undefined;

updatedAction = {
...action,
payload: {
...action.payload,
params: {
...action.payload.params,
params: {
q: SearchQueryUtils.buildSearchQueryString(queryJSON),
},
},
},
};
// Transitioning to SCREENS.SEARCH.MONEY_REQUEST_REPORT should be animated
if (actionPayloadScreen === SCREENS.SEARCH.MONEY_REQUEST_REPORT && lastFullScreenRoute?.key) {
searchFullscreenWithEnteringAnimation.add(lastFullScreenRoute.key);
}

return stackRouter.getStateForAction(state, updatedAction, configOptions);
return stateWithSearchFullscreenNavigator;
}

function handleReplaceReportsSplitNavigatorAction(
Expand Down Expand Up @@ -309,6 +287,7 @@ export {
handleSwitchPolicyIDAction,
handleSwitchPolicyIDFromSearchAction,
reportsSplitsWithEnteringAnimation,
searchFullscreenWithEnteringAnimation,
settingsSplitWithEnteringAnimation,
workspaceSplitsWithoutEnteringAnimation,
};
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ function RootStackRouter(options: RootStackNavigatorRouterOptions) {
}

if (action.payload.name === NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR) {
return handlePushSearchPageAction(state, action, configOptions, stackRouter, setActiveWorkspaceID);
return handlePushSearchPageAction(state, action, configOptions, stackRouter);
}

if (action.payload.name === NAVIGATORS.SETTINGS_SPLIT_NAVIGATOR) {
Expand Down