Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Search v1] Add ReportScreen to RHP #40570

Merged
merged 21 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const ROUTES = {
getRoute: (query: string) => `search/${query}` as const,
},

SEARCH_REPORT: {
route: '/search/:query/view/:reportID',
getRoute: (query: string, reportID: string) => `search/${query}/view/${reportID}` as const,
},

// This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated
CONCIERGE: 'concierge',
FLAG_COMMENT: {
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const SCREENS = {
WORKSPACES_CENTRAL_PANE: 'WorkspacesCentralPane',
SEARCH: {
CENTRAL_PANE: 'Search_Central_Pane',
REPORT_RHP: 'Search_Report_RHP',
BOTTOM_TAB: 'Search_Bottom_Tab',
},
SETTINGS: {
Expand Down Expand Up @@ -131,6 +132,7 @@ const SCREENS = {
ROOM_INVITE: 'RoomInvite',
REFERRAL: 'Referral',
PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold',
SEARCH_REPORT: 'SearchReport',
},
ONBOARDING_MODAL: {
ONBOARDING: 'Onboarding',
Expand Down
32 changes: 22 additions & 10 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,25 @@ type MoneyReportHeaderProps = MoneyReportHeaderOnyxProps & {
/** The reportID of the transaction thread report associated with this current report, if any */
// eslint-disable-next-line react/no-unused-prop-types
transactionThreadReportID?: string | null;

/** Whether we should display the header as in narrow layout */
shouldUseNarrowLayout?: boolean;
};

function MoneyReportHeader({session, policy, chatReport, nextStep, report: moneyRequestReport, transactionThreadReport, reportActions}: MoneyReportHeaderProps) {
function MoneyReportHeader({
session,
policy,
chatReport,
nextStep,
report: moneyRequestReport,
transactionThreadReport,
reportActions,
shouldUseNarrowLayout = false,
}: MoneyReportHeaderProps) {
const styles = useThemeStyles();
const [isDeleteRequestModalVisible, setIsDeleteRequestModalVisible] = useState(false);
const {translate} = useLocalize();
const {windowWidth, isSmallScreenWidth} = useWindowDimensions();
const {windowWidth} = useWindowDimensions();
const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(moneyRequestReport);
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const requestParentReportAction = useMemo(() => {
Expand Down Expand Up @@ -108,7 +120,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
const formattedAmount = CurrencyUtils.convertToDisplayString(reimbursableSpend, moneyRequestReport.currency);
const [nonHeldAmount, fullAmount] = ReportUtils.getNonHeldAndFullAmount(moneyRequestReport, policy);
const displayedAmount = ReportUtils.hasHeldExpenses(moneyRequestReport.reportID) && canAllowSettlement ? nonHeldAmount : formattedAmount;
const isMoreContentShown = shouldShowNextStep || (shouldShowAnyButton && isSmallScreenWidth);
const isMoreContentShown = shouldShowNextStep || (shouldShowAnyButton && shouldUseNarrowLayout);

const confirmPayment = (type?: PaymentMethodType | undefined) => {
if (!type) {
Expand Down Expand Up @@ -185,15 +197,15 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
shouldShowPinButton={false}
report={moneyRequestReport}
policy={policy}
shouldShowBackButton={isSmallScreenWidth}
shouldShowBackButton={shouldUseNarrowLayout}
onBackButtonPress={() => Navigation.goBack(undefined, false, true)}
// Shows border if no buttons or next steps are showing below the header
shouldShowBorderBottom={!(shouldShowAnyButton && isSmallScreenWidth) && !(shouldShowNextStep && !isSmallScreenWidth)}
shouldShowBorderBottom={!(shouldShowAnyButton && shouldUseNarrowLayout) && !(shouldShowNextStep && !shouldUseNarrowLayout)}
shouldShowThreeDotsButton
threeDotsMenuItems={threeDotsMenuItems}
threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)}
>
{shouldShowSettlementButton && !isSmallScreenWidth && (
{shouldShowSettlementButton && !shouldUseNarrowLayout && (
<View style={styles.pv2}>
<SettlementButton
currency={moneyRequestReport.currency}
Expand All @@ -213,7 +225,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
/>
</View>
)}
{shouldShowSubmitButton && !isSmallScreenWidth && (
{shouldShowSubmitButton && !shouldUseNarrowLayout && (
<View style={styles.pv2}>
<Button
medium
Expand All @@ -227,7 +239,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
)}
</HeaderWithBackButton>
<View style={isMoreContentShown ? [styles.dFlex, styles.flexColumn, styles.borderBottom] : []}>
{shouldShowSettlementButton && isSmallScreenWidth && (
{shouldShowSettlementButton && shouldUseNarrowLayout && (
<View style={[styles.ph5, styles.pb2]}>
<SettlementButton
currency={moneyRequestReport.currency}
Expand All @@ -246,7 +258,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
/>
</View>
)}
{shouldShowSubmitButton && isSmallScreenWidth && (
{shouldShowSubmitButton && shouldUseNarrowLayout && (
<View style={[styles.ph5, styles.pb2]}>
<Button
medium
Expand All @@ -269,7 +281,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
nonHeldAmount={!ReportUtils.hasOnlyHeldExpenses(moneyRequestReport.reportID) ? nonHeldAmount : undefined}
requestType={requestType}
fullAmount={fullAmount}
isSmallScreenWidth={isSmallScreenWidth}
isSmallScreenWidth={shouldUseNarrowLayout}
Copy link
Contributor

Choose a reason for hiding this comment

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

Passing the shouldUseNarrowLayout value as isSmallScreenWidth will stretch the confirmation modal in the web. We should not have changed the isSmallScreenWidth value, as this change caused the issue #45002

onClose={() => setIsHoldMenuVisible(false)}
isVisible={isHoldMenuVisible}
paymentType={paymentType}
Expand Down
24 changes: 18 additions & 6 deletions src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,21 @@ type MoneyRequestHeaderProps = MoneyRequestHeaderOnyxProps & {

/** The report action the transaction is tied to from the parent report */
parentReportAction: OnyxEntry<ReportAction>;

/** Whether we should display the header as in narrow layout */
shouldUseNarrowLayout?: boolean;
};

function MoneyRequestHeader({session, parentReport, report, parentReportAction, transaction, shownHoldUseExplanation = false, policy}: MoneyRequestHeaderProps) {
function MoneyRequestHeader({
session,
parentReport,
report,
parentReportAction,
transaction,
shownHoldUseExplanation = false,
policy,
shouldUseNarrowLayout = false,
}: MoneyRequestHeaderProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
Expand All @@ -61,7 +73,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
const isSettled = ReportUtils.isSettled(moneyRequestReport?.reportID);
const isApproved = ReportUtils.isReportApproved(moneyRequestReport);
const isOnHold = TransactionUtils.isOnHold(transaction);
const {isSmallScreenWidth, windowWidth} = useWindowDimensions();
const {windowWidth} = useWindowDimensions();

// Only the requestor can take delete the expense, admins can only edit it.
const isActionOwner = typeof parentReportAction?.actorAccountID === 'number' && typeof session?.accountID === 'number' && parentReportAction.actorAccountID === session?.accountID;
Expand Down Expand Up @@ -144,14 +156,14 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
return;
}

if (isSmallScreenWidth) {
if (shouldUseNarrowLayout) {
if (Navigation.getActiveRoute().slice(1) === ROUTES.PROCESS_MONEY_REQUEST_HOLD) {
Navigation.goBack();
}
} else {
Navigation.navigate(ROUTES.PROCESS_MONEY_REQUEST_HOLD);
}
}, [isSmallScreenWidth, shouldShowHoldMenu]);
}, [shouldUseNarrowLayout, shouldShowHoldMenu]);

const handleHoldRequestClose = () => {
IOU.setShownHoldUseExplanation();
Expand Down Expand Up @@ -180,7 +192,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
ownerAccountID: parentReport?.ownerAccountID,
}}
policy={policy}
shouldShowBackButton={isSmallScreenWidth}
shouldShowBackButton={shouldUseNarrowLayout}
onBackButtonPress={() => Navigation.goBack(undefined, false, true)}
/>
{isPending && (
Expand Down Expand Up @@ -209,7 +221,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
cancelText={translate('common.cancel')}
danger
/>
{isSmallScreenWidth && shouldShowHoldMenu && (
{shouldUseNarrowLayout && shouldShowHoldMenu && (
Copy link
Contributor

Choose a reason for hiding this comment

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

The ProcessMoneyRequestHoldMenu is to be shown for small screen devices. However, since shouldUseNarrowLayout is used here, this will also get shown when the held report is opened in RHP thereby resulting in issue #42007

<ProcessMoneyRequestHoldMenu
onClose={handleHoldRequestClose}
onConfirm={handleHoldRequestClose}
Expand Down
9 changes: 9 additions & 0 deletions src/hooks/useIsReportOpenInRHP.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {useNavigationState} from '@react-navigation/native';
import getTopmostRouteName from '@libs/Navigation/getTopmostRouteName';
import SCREENS from '@src/SCREENS';

// This hook checks if the currently open route is ReportScreen in RHP.
export default function useIsReportOpenInRHP() {
const activeRoute = useNavigationState(getTopmostRouteName);
return activeRoute === SCREENS.SEARCH.REPORT_RHP;
}
5 changes: 4 additions & 1 deletion src/hooks/useThumbnailDimensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {useMemo} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import type {DimensionValue} from 'react-native/Libraries/StyleSheet/StyleSheetTypes';
import CONST from '@src/CONST';
import useIsReportOpenInRHP from './useIsReportOpenInRHP';
import useWindowDimensions from './useWindowDimensions';

type ThumbnailDimensions = {
Expand All @@ -13,8 +14,10 @@ type ThumbnailDimensions = {
};

export default function useThumbnailDimensions(width: number, height: number): ThumbnailDimensions {
const isReportOpenInRHP = useIsReportOpenInRHP();
const {isSmallScreenWidth} = useWindowDimensions();
const fixedDimension = isSmallScreenWidth ? CONST.THUMBNAIL_IMAGE.SMALL_SCREEN.SIZE : CONST.THUMBNAIL_IMAGE.WIDE_SCREEN.SIZE;
const shouldUseNarrowLayout = isSmallScreenWidth || isReportOpenInRHP;
const fixedDimension = shouldUseNarrowLayout ? CONST.THUMBNAIL_IMAGE.SMALL_SCREEN.SIZE : CONST.THUMBNAIL_IMAGE.WIDE_SCREEN.SIZE;
const thumbnailDimensionsStyles = useMemo(() => {
if (!width || !height) {
return {width: fixedDimension, aspectRatio: CONST.THUMBNAIL_IMAGE.NAN_ASPECT_RATIO};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import type {
ReportSettingsNavigatorParamList,
RoomInviteNavigatorParamList,
RoomMembersNavigatorParamList,
SearchReportParamList,
SettingsNavigatorParamList,
SignInNavigatorParamList,
SplitDetailsNavigatorParamList,
Expand Down Expand Up @@ -333,7 +334,6 @@ const PrivateNotesModalStackNavigator = createModalStackNavigator<PrivateNotesNa
const SignInModalStackNavigator = createModalStackNavigator<SignInNavigatorParamList>({
[SCREENS.SIGN_IN_ROOT]: () => require('../../../../pages/signin/SignInModal').default as React.ComponentType,
});

const ReferralModalStackNavigator = createModalStackNavigator<ReferralDetailsNavigatorParamList>({
[SCREENS.REFERRAL_DETAILS]: () => require('../../../../pages/ReferralDetailsPage').default as React.ComponentType,
});
Expand All @@ -342,6 +342,10 @@ const ProcessMoneyRequestHoldStackNavigator = createModalStackNavigator({
[SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: () => require('../../../../pages/ProcessMoneyRequestHoldPage').default as React.ComponentType,
});

const SearchReportModalStackNavigator = createModalStackNavigator<SearchReportParamList>({
[SCREENS.SEARCH.REPORT_RHP]: () => require('../../../../pages/home/ReportScreen').default as React.ComponentType,
});

export {
AddPersonalBankAccountModalStackNavigator,
DetailsModalStackNavigator,
Expand Down Expand Up @@ -372,4 +376,5 @@ export {
WalletStatementStackNavigator,
ProcessMoneyRequestHoldStackNavigator,
WorkspaceSettingsModalStackNavigator,
SearchReportModalStackNavigator,
};
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) {
name="ProcessMoneyRequestHold"
component={ModalStackNavigators.ProcessMoneyRequestHoldStackNavigator}
/>
<Stack.Screen
name={SCREENS.RIGHT_MODAL.SEARCH_REPORT}
component={ModalStackNavigators.SearchReportModalStackNavigator}
/>
</Stack.Navigator>
</View>
</NoDropZone>
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/Navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ROUTES, {HYBRID_APP_ROUTES} from '@src/ROUTES';
import {PROTECTED_SCREENS} from '@src/SCREENS';
import type {Report} from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import originalCloseRHPFlow from './closeRHPFlow';
import originalDismissModal from './dismissModal';
import originalDismissModalWithReport from './dismissModalWithReport';
import originalGetTopmostReportActionId from './getTopmostReportActionID';
Expand Down Expand Up @@ -60,6 +61,8 @@ const dismissModal = (reportID?: string, ref = navigationRef) => {
const report = getReport(reportID);
originalDismissModalWithReport({reportID, ...report}, ref);
};
// Re-exporting the closeRHPFlow here to fill in default value for navigationRef. The closeRHPFlow isn't defined in this file to avoid cyclic dependencies.
const closeRHPFlow = (ref = navigationRef) => originalCloseRHPFlow(ref);

// Re-exporting the dismissModalWithReport here to fill in default value for navigationRef. The dismissModalWithReport isn't defined in this file to avoid cyclic dependencies.
// This method is needed because it allows to dismiss the modal and then open the report. Within this method is checked whether the report belongs to a specific workspace. Sometimes the report we want to check, hasn't been added to the Onyx yet.
Expand Down Expand Up @@ -380,6 +383,7 @@ export default {
navigateWithSwitchPolicyID,
resetToHome,
isDisplayedInModal,
closeRHPFlow,
};

export {navigationRef};
30 changes: 30 additions & 0 deletions src/libs/Navigation/closeRHPFlow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type {NavigationContainerRef} from '@react-navigation/native';
import {StackActions} from '@react-navigation/native';
import Log from '@libs/Log';
import NAVIGATORS from '@src/NAVIGATORS';
import type {RootStackParamList} from './types';

/**
* Closes the last RHP flow, if there is only one, closes the entire RHP.
*/
export default function closeRHPFlow(navigationRef: NavigationContainerRef<RootStackParamList>) {
if (!navigationRef.isReady()) {
return;
}
const state = navigationRef.getState();
const lastRoute = state.routes.at(-1);
const isLastRouteRHP = lastRoute?.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR;

if (!isLastRouteRHP) {
Log.warn('RHP Navigator has not been found when calling closeRHPFlow function');
return;
}

let target = state.key;

const hasMoreThanOneRoute = lastRoute?.state?.routes?.length && lastRoute.state.routes.length > 1;
if (lastRoute?.state?.key && hasMoreThanOneRoute) {
target = lastRoute.state.key;
}
navigationRef.dispatch({...StackActions.pop(), target});
}
12 changes: 12 additions & 0 deletions src/libs/Navigation/getTopmostRouteName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type {NavigationState, PartialState} from '@react-navigation/native';

// Get the name of topmost route in the navigation stack.
function getTopmostRouteName(state: NavigationState | PartialState<NavigationState>): string | undefined {
if (!state) {
return;
}

return state.routes.at(-1)?.name;
}

export default getTopmostRouteName;
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<CentralPaneName, string[]>> =
[SCREENS.SETTINGS.ABOUT]: [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS],
[SCREENS.SETTINGS.SAVE_THE_WORLD]: [SCREENS.I_KNOW_A_TEACHER, SCREENS.INTRO_SCHOOL_PRINCIPAL, SCREENS.I_AM_A_TEACHER],
[SCREENS.SETTINGS.TROUBLESHOOT]: [SCREENS.SETTINGS.CONSOLE],
[SCREENS.SEARCH.CENTRAL_PANE]: [SCREENS.SEARCH.REPORT_RHP],
};

export default CENTRAL_PANE_TO_RHP_MAPPING;
5 changes: 5 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,11 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: ROUTES.PROCESS_MONEY_REQUEST_HOLD,
},
},
[SCREENS.RIGHT_MODAL.SEARCH_REPORT]: {
screens: {
[SCREENS.SEARCH.REPORT_RHP]: ROUTES.SEARCH_REPORT.route,
},
},
},
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ function getMatchingRootRouteForRHPRoute(
// Check for CentralPaneNavigator
for (const [centralPaneName, RHPNames] of Object.entries(CENTRAL_PANE_TO_RHP_MAPPING)) {
if (RHPNames.includes(route.name)) {
return createCentralPaneNavigator({name: centralPaneName as CentralPaneName, params: route.params});
const params = {...route.params};
if (centralPaneName === SCREENS.SEARCH.CENTRAL_PANE) {
delete (params as Record<string, string | undefined>)?.reportID;
}
return createCentralPaneNavigator({name: centralPaneName as CentralPaneName, params});
}
}

Expand Down Expand Up @@ -195,6 +199,7 @@ function getAdaptedState(state: PartialState<NavigationState<RootStackParamList>
if (matchingRootRoute?.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) {
routes.push(createCentralPaneNavigator({name: SCREENS.SETTINGS.WORKSPACES}));
}

if (matchingRootRoute && (!isNarrowLayout || !isRHPScreenOpenedFromLHN)) {
routes.push(matchingRootRoute);
}
Expand Down
9 changes: 9 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ type RightModalNavigatorParamList = {
[SCREENS.RIGHT_MODAL.PROCESS_MONEY_REQUEST_HOLD]: NavigatorScreenParams<ProcessMoneyRequestHoldNavigatorParamList>;
[SCREENS.RIGHT_MODAL.REFERRAL]: NavigatorScreenParams<ReferralDetailsNavigatorParamList>;
[SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams<PrivateNotesNavigatorParamList>;
[SCREENS.RIGHT_MODAL.SEARCH_REPORT]: NavigatorScreenParams<SearchReportParamList>;
};

type WorkspacesCentralPaneNavigatorParamList = {
Expand Down Expand Up @@ -826,6 +827,13 @@ type AuthScreensParamList = SharedScreensParamList & {
};
};

type SearchReportParamList = {
[SCREENS.SEARCH.REPORT_RHP]: {
query: string;
reportID: string;
};
};

type RootStackParamList = PublicScreensParamList & AuthScreensParamList & ChatFinderNavigatorParamList;

type BottomTabName = keyof BottomTabNavigatorParamList;
Expand Down Expand Up @@ -891,4 +899,5 @@ export type {
WelcomeVideoModalNavigatorParamList,
WorkspaceSwitcherNavigatorParamList,
WorkspacesCentralPaneNavigatorParamList,
SearchReportParamList,
};
Loading
Loading