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
2 changes: 1 addition & 1 deletion Mobile-Expensify
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1009015904
versionName "9.1.59-4"
versionCode 1009015906
versionName "9.1.59-6"
// Supported language variants must be declared here to avoid from being removed during the compilation.
// This also helps us to not include unnecessary language variants in the APK.
resConfigs "en", "es"
Expand Down
2 changes: 1 addition & 1 deletion ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>9.1.59.4</string>
<string>9.1.59.6</string>
<key>FullStory</key>
<dict>
<key>OrgId</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.1.59</string>
<key>CFBundleVersion</key>
<string>9.1.59.4</string>
<string>9.1.59.6</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/ShareViewController/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<key>CFBundleShortVersionString</key>
<string>9.1.59</string>
<key>CFBundleVersion</key>
<string>9.1.59.4</string>
<string>9.1.59.6</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "9.1.59-4",
"version": "9.1.59-6",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
1 change: 0 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,6 @@ const CONST = {
EMPTY_ARRAY,
EMPTY_OBJECT,
DEFAULT_NUMBER_ID,
FAKE_REPORT_ID: 'FAKE_REPORT_ID',
USE_EXPENSIFY_URL,
EXPENSIFY_URL,
EXPENSIFY_MOBILE_URL,
Expand Down
34 changes: 5 additions & 29 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,12 @@ const ROUTES = {
backTo,
moneyRequestReportActionID,
transactionID,
iouReportID,
}: {
reportID: string | undefined;
reportActionID?: string;
backTo?: string;
moneyRequestReportActionID?: string;
transactionID?: string;
iouReportID?: string;
}) => {
if (!reportID) {
Log.warn('Invalid reportID is used to build the SEARCH_REPORT route');
Expand All @@ -108,10 +106,6 @@ const ROUTES = {
queryParams.push(`moneyRequestReportActionID=${moneyRequestReportActionID}`);
}

if (iouReportID) {
queryParams.push(`iouReportID=${iouReportID}`);
}

const queryString = queryParams.length > 0 ? (`${baseRoute}?${queryParams.join('&')}` as const) : baseRoute;
return getUrlWithBackToParam(queryString, backTo);
},
Expand Down Expand Up @@ -382,19 +376,10 @@ const ROUTES = {
REPORT: 'r',
REPORT_WITH_ID: {
route: 'r/:reportID?/:reportActionID?',
getRoute: (
reportID: string | undefined,
reportActionID?: string,
referrer?: string,
moneyRequestReportActionID?: string,
transactionID?: string,
backTo?: string,
iouReportID?: string,
) => {
getRoute: (reportID: string | undefined, reportActionID?: string, referrer?: string, moneyRequestReportActionID?: string, transactionID?: string, backTo?: string) => {
if (!reportID) {
Log.warn('Invalid reportID is used to build the REPORT_WITH_ID route');
}

const baseRoute = reportActionID ? (`r/${reportID}/${reportActionID}` as const) : (`r/${reportID}` as const);

const queryParams: string[] = [];
Expand All @@ -408,10 +393,6 @@ const ROUTES = {
queryParams.push(`transactionID=${transactionID}`);
}

if (iouReportID) {
queryParams.push(`iouReportID=${iouReportID}`);
}

const queryString = queryParams.length > 0 ? `?${queryParams.join('&')}` : '';

return getUrlWithBackToParam(`${baseRoute}${queryString}` as const, backTo);
Expand Down Expand Up @@ -611,15 +592,10 @@ const ROUTES = {
},
MONEY_REQUEST_HOLD_REASON: {
route: ':type/edit/reason/:transactionID?/:searchHash?',
getRoute: (type: ValueOf<typeof CONST.POLICY.TYPE>, transactionID: string, reportID: string | undefined, backTo: string, searchHash?: number) => {
let route = searchHash
? (`${type as string}/edit/reason/${transactionID}/${searchHash}/?backTo=${backTo}` as const)
: (`${type as string}/edit/reason/${transactionID}/?backTo=${backTo}` as const);

if (reportID) {
route = `${route}&reportID=${reportID}` as const;
}

getRoute: (type: ValueOf<typeof CONST.POLICY.TYPE>, transactionID: string, reportID: string, backTo: string, searchHash?: number) => {
const route = searchHash
? (`${type as string}/edit/reason/${transactionID}/${searchHash}/?backTo=${backTo}&reportID=${reportID}` as const)
: (`${type as string}/edit/reason/${transactionID}/?backTo=${backTo}&reportID=${reportID}` as const);
return route;
},
},
Expand Down
15 changes: 4 additions & 11 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@ import useSelectedTransactionsActions from '@hooks/useSelectedTransactionsAction
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
import {deleteAppReport, downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported, openReport, openUnreportedExpense} from '@libs/actions/Report';
import {deleteAppReport, downloadReportPDF, exportReportToCSV, exportReportToPDF, exportToIntegration, markAsManuallyExported, openUnreportedExpense} from '@libs/actions/Report';
import {getThreadReportIDsForTransactions, getTotalAmountForIOUReportPreviewButton} from '@libs/MoneyRequestReportUtils';
import Navigation from '@libs/Navigation/Navigation';
import {buildOptimisticNextStepForPreventSelfApprovalsEnabled} from '@libs/NextStepUtils';
import {isSecondaryActionAPaymentOption, selectPaymentType} from '@libs/PaymentUtils';
import type {KYCFlowEvent, TriggerKYCFlow} from '@libs/PaymentUtils';
import {getValidConnectedIntegration} from '@libs/PolicyUtils';
import {getIOUActionForReportID, getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
import {getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
import {getAllExpensesToHoldIfApplicable, getReportPrimaryAction} from '@libs/ReportPrimaryActionUtils';
import {getSecondaryReportActions} from '@libs/ReportSecondaryActionUtils';
import {
buildTransactionThread,
changeMoneyRequestHoldStatus,
generateReportID,
getArchiveReason,
getBankAccountRoute,
getIntegrationIcon,
Expand Down Expand Up @@ -605,14 +603,9 @@ function MoneyReportHeader({
success
text={translate('iou.reviewDuplicates')}
onPress={() => {
let threadID = transactionThreadReportID ?? getFirstDuplicateThreadID(transactions, reportActions);
const threadID = transactionThreadReportID ?? getFirstDuplicateThreadID(transactions, reportActions);
if (!threadID) {
threadID = generateReportID();
const duplicateTransaction = transactions.find((reportTransaction) => isDuplicate(reportTransaction.transactionID));
const transactionID = duplicateTransaction?.transactionID;
const iouAction = getIOUActionForReportID(moneyRequestReport?.reportID, transactionID);
const optimisticTransactionThread = buildTransactionThread(iouAction, moneyRequestReport, undefined, threadID);
openReport(threadID, undefined, session?.email ? [session?.email] : [], optimisticTransactionThread, iouAction?.reportActionID);
return;
}
Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_PAGE.getRoute(threadID));
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,14 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import {getThreadReportIDsForTransactions} from '@libs/MoneyRequestReportUtils';
import {navigationRef} from '@libs/Navigation/Navigation';
import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
import {generateReportID, getMoneyRequestSpendBreakdown, isIOUReport} from '@libs/ReportUtils';
import {getMoneyRequestSpendBreakdown, isIOUReport} from '@libs/ReportUtils';
import {compareValues} from '@libs/SearchUIUtils';
import {getTransactionPendingAction, isTransactionPendingDelete} from '@libs/TransactionUtils';
import shouldShowTransactionYear from '@libs/TransactionUtils/shouldShowTransactionYear';
import Navigation from '@navigation/Navigation';
import type {ReportsSplitNavigatorParamList} from '@navigation/types';
import variables from '@styles/variables';
import CONST from '@src/CONST';
import NAVIGATORS from '@src/NAVIGATORS';
import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
import type * as OnyxTypes from '@src/types/onyx';
Expand Down Expand Up @@ -98,8 +96,6 @@ type SortedTransactions = {
sortOrder: SortOrder;
};

type ReportScreenNavigationProps = ReportsSplitNavigatorParamList[typeof SCREENS.REPORT];

const isSortableColumnName = (key: unknown): key is SortableColumnName => !!sortableColumnNames.find((val) => val === key);

const getTransactionKey = (transaction: OnyxTypes.Transaction, key: SortableColumnName) => {
Expand Down Expand Up @@ -194,27 +190,19 @@ function MoneyRequestReportTransactionList({
const navigateToTransaction = useCallback(
(activeTransaction: OnyxTypes.Transaction) => {
const iouAction = getIOUActionForTransactionID(reportActions, activeTransaction.transactionID);
const reportIDToNavigate = iouAction?.childReportID ?? generateReportID();
const reportIDToNavigate = iouAction?.childReportID;
if (!reportIDToNavigate) {
return;
}

const backTo = Navigation.getActiveRoute() as Route;
const backTo = Navigation.getActiveRoute();

// Single transaction report will open in RHP, and we need to find every other report ID for the rest of transactions
// to display prev/next arrows in RHP for navigating between transactions
const sortedSiblingTransactionReportIDs = getThreadReportIDsForTransactions(reportActions, sortedTransactions);
setActiveTransactionThreadIDs(sortedSiblingTransactionReportIDs);

const routeParams = {
reportID: reportIDToNavigate,
backTo,
} as ReportScreenNavigationProps;

if (!iouAction?.childReportID) {
routeParams.moneyRequestReportActionID = iouAction?.reportActionID;
routeParams.transactionID = activeTransaction.transactionID;
routeParams.iouReportID = activeTransaction.reportID;
}

Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(routeParams));
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID: reportIDToNavigate, backTo}));
},
[reportActions, sortedTransactions],
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/MoneyRequestAction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function MoneyRequestAction({
const transactionID = isMoneyRequestAction(action) ? getOriginalMessage(action)?.IOUTransactionID : CONST.DEFAULT_NUMBER_ID;
if (!action?.childReportID && transactionID && action.reportActionID) {
const optimisticReportID = generateReportID();
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(optimisticReportID, undefined, undefined, action.reportActionID, transactionID, Navigation.getActiveRoute(), requestReportID));
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(optimisticReportID, undefined, undefined, action.reportActionID, transactionID, Navigation.getActiveRoute()));
return;
}

Expand Down
40 changes: 18 additions & 22 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import Log from '@libs/Log';
import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import {getIOUActionForTransactionID, getOriginalMessage, getReportAction, isMoneyRequestAction} from '@libs/ReportActionsUtils';
import {getIOUActionForTransactionID} from '@libs/ReportActionsUtils';
import {canEditFieldOfMoneyRequest, generateReportID} from '@libs/ReportUtils';
import {buildSearchQueryString} from '@libs/SearchQueryUtils';
import {
Expand Down Expand Up @@ -400,28 +400,8 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS

const isFromSelfDM = item.reportID === CONST.REPORT.UNREPORTED_REPORT_ID;
const isTransactionItem = isTransactionListItemType(item);
const backTo = Navigation.getActiveRoute();

// If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user
if (isTransactionItem && item.transactionThreadReportID === CONST.REPORT.UNREPORTED_REPORT_ID) {
const transactionThreadReportID = generateReportID();
const reportAction = getReportAction(item.reportID, item.moneyRequestReportActionID);
const iouReportID = isMoneyRequestAction(reportAction) ? getOriginalMessage(reportAction)?.IOUReportID : undefined;

updateSearchResultsWithTransactionThreadReportID(hash, item.transactionID, transactionThreadReportID);
Navigation.navigate(
ROUTES.SEARCH_REPORT.getRoute({
reportID: transactionThreadReportID,
backTo,
moneyRequestReportActionID: item.moneyRequestReportActionID,
transactionID: item.transactionID,
iouReportID,
}),
);
return;
}

const reportID =
let reportID =
isTransactionItem && (!item.isFromOneTransactionReport || isFromSelfDM) && item.transactionThreadReportID !== CONST.REPORT.UNREPORTED_REPORT_ID
? item.transactionThreadReportID
: item.reportID;
Expand All @@ -430,13 +410,29 @@ function Search({queryJSON, currentSearchResults, lastNonEmptySearchResults, onS
return;
}

const backTo = Navigation.getActiveRoute();
const shouldHandleTransactionAsReport = isReportListItemType(item) || (isTransactionItem && isOpenedAsReport);

if (isBetaEnabled(CONST.BETAS.TABLE_REPORT_VIEW) && shouldHandleTransactionAsReport) {
Navigation.navigate(ROUTES.SEARCH_MONEY_REQUEST_REPORT.getRoute({reportID, backTo}));
return;
}

// If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user
if (isTransactionItem && reportID === CONST.REPORT.UNREPORTED_REPORT_ID) {
reportID = generateReportID();
updateSearchResultsWithTransactionThreadReportID(hash, item.transactionID, reportID);
Navigation.navigate(
ROUTES.SEARCH_REPORT.getRoute({
reportID,
backTo,
moneyRequestReportActionID: item.moneyRequestReportActionID,
transactionID: item.transactionID,
}),
);
return;
}

if (isReportActionListItemType(item)) {
const reportActionID = item.reportActionID;
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, reportActionID, backTo}));
Expand Down
2 changes: 1 addition & 1 deletion src/libs/API/parameters/CreatePerDiemRequestParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type CreatePerDiemRequestParams = {
createdChatReportActionID?: string;
createdIOUReportActionID?: string;
reportPreviewReportActionID: string;
transactionThreadReportID?: string;
transactionThreadReportID: string;
createdReportActionIDForThread: string | undefined;
billable?: boolean;
attendees?: string;
Expand Down
2 changes: 0 additions & 2 deletions src/libs/API/parameters/HoldMoneyRequestParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ type HoldMoneyRequestParams = {
comment: string;
reportActionID: string;
commentReportActionID: string;
transactionThreadReportID?: string;
createdReportActionIDForThread?: string;
};

export default HoldMoneyRequestParams;
2 changes: 0 additions & 2 deletions src/libs/API/parameters/MergeDuplicatesParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ type MergeDuplicatesParams = {
receiptID: number;
reportID: string | undefined;
reportActionID?: string | undefined;
transactionThreadReportID?: string;
createdReportActionIDForThread?: string;
};

export default MergeDuplicatesParams;
4 changes: 2 additions & 2 deletions src/libs/API/parameters/RequestMoneyParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type RequestMoneyParams = {
taxAmount: number;
billable?: boolean;
receiptGpsPoints?: string;
transactionThreadReportID?: string;
createdReportActionIDForThread?: string | undefined;
transactionThreadReportID: string;
createdReportActionIDForThread: string | undefined;
reimbursible?: boolean;
description?: string;
attendees?: string;
Expand Down
1 change: 0 additions & 1 deletion src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1657,7 +1657,6 @@ type ReportsSplitNavigatorParamList = {
backTo?: Routes;
moneyRequestReportActionID?: string;
transactionID?: string;
iouReportID?: string;
};
};

Expand Down
5 changes: 3 additions & 2 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,7 @@ function getOneTransactionThreadReportID(
if (
actionType &&
iouRequestTypesSet.has(actionType) &&
action.childReportID &&
// Include deleted IOU reportActions if:
// - they have an associated IOU transaction ID or
// - they have visible childActions (like comments) that we'd want to display
Expand Down Expand Up @@ -1276,8 +1277,8 @@ function getOneTransactionThreadReportID(
return;
}

// Since we don't always create transaction thread optimistically, we return CONST.FAKE_REPORT_ID
return singleAction?.childReportID ?? CONST.FAKE_REPORT_ID;
// Ensure we have a childReportID associated with the IOU report action
return singleAction?.childReportID;
}

/**
Expand Down
Loading