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 src/components/TaxPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export default withOnyx<TaxPickerProps, TaxPickerOnyxProps>({
},
transaction: {
key: ({transactionID, action}) => {
if (action === CONST.IOU.ACTION.CREATE || IOUUtils.isMovingTransactionFromTrackExpense(action)) {
if (IOUUtils.shouldUseTransactionDraft(action)) {
return `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}` as `${typeof ONYXKEYS.COLLECTION.TRANSACTION}${string}`;
}
return `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`;
Expand Down
34 changes: 34 additions & 0 deletions src/hooks/useFetchRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {isEqual} from 'lodash';
import {useEffect} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import * as IOUUtils from '@libs/IOUUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import * as TransactionAction from '@userActions/Transaction';
import type {IOUAction} from '@src/CONST';
import type {Transaction} from '@src/types/onyx';
import type {WaypointCollection} from '@src/types/onyx/Transaction';
import useNetwork from './useNetwork';
import usePrevious from './usePrevious';

export default function useFetchRoute(transaction: OnyxEntry<Transaction>, waypoints: WaypointCollection | undefined, action: IOUAction) {
const {isOffline} = useNetwork();
const hasRouteError = !!transaction?.errorFields?.route;
const hasRoute = TransactionUtils.hasRoute(transaction);
const isRouteAbsentWithoutErrors = !hasRoute && !hasRouteError;
const isLoadingRoute = transaction?.comment?.isLoading ?? false;
const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints);
const previousValidatedWaypoints = usePrevious(validatedWaypoints);
const haveValidatedWaypointsChanged = !isEqual(previousValidatedWaypoints, validatedWaypoints);
const isDistanceRequest = TransactionUtils.isDistanceRequest(transaction);
const shouldFetchRoute = isDistanceRequest && (isRouteAbsentWithoutErrors || haveValidatedWaypointsChanged) && !isLoadingRoute && Object.keys(validatedWaypoints).length > 1;

useEffect(() => {
if (isOffline || !shouldFetchRoute || !transaction?.transactionID) {
return;
}

TransactionAction.getRoute(transaction.transactionID, validatedWaypoints, IOUUtils.shouldUseTransactionDraft(action));
}, [shouldFetchRoute, transaction?.transactionID, validatedWaypoints, isOffline, action]);

return {shouldFetchRoute, validatedWaypoints};
}
5 changes: 5 additions & 0 deletions src/libs/IOUUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,11 +156,16 @@ function isMovingTransactionFromTrackExpense(action?: IOUAction) {
return false;
}

function shouldUseTransactionDraft(action: IOUAction | undefined) {
return action === CONST.IOU.ACTION.CREATE || isMovingTransactionFromTrackExpense(action);
}

export {
calculateAmount,
insertTagIntoTransactionTagsString,
isIOUReportPendingCurrencyConversion,
isMovingTransactionFromTrackExpense,
shouldUseTransactionDraft,
isValidMoneyRequestType,
navigateToStartMoneyRequestStep,
updateIOUOwnerAndTotal,
Expand Down
10 changes: 8 additions & 2 deletions src/libs/actions/TransactionEdit.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Onyx from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import type {Connection, OnyxEntry} from 'react-native-onyx';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Transaction} from '@src/types/onyx';

let connection: Connection;

/**
* Makes a backup copy of a transaction object that can be restored when the user cancels editing a transaction.
*/
Expand All @@ -11,6 +13,10 @@ function createBackupTransaction(transaction: OnyxEntry<Transaction>) {
return;
}

// In Strict Mode, the backup logic useEffect is triggered twice on mount. The restore logic is delayed because we need to connect to the onyx first,
// so it's possible that the restore logic is executed after creating the backup for the 2nd time which will completely clear the backup.
// To avoid that, we need to cancel the pending connection.
Onyx.disconnect(connection);
const newTransaction = {
...transaction,
};
Expand All @@ -27,7 +33,7 @@ function removeBackupTransaction(transactionID: string) {
}

function restoreOriginalTransactionFromBackup(transactionID: string, isDraft: boolean) {
const connection = Onyx.connect({
connection = Onyx.connect({
key: `${ONYXKEYS.COLLECTION.TRANSACTION_BACKUP}${transactionID}`,
callback: (backupTransaction) => {
Onyx.disconnect(connection);
Expand Down
3 changes: 3 additions & 0 deletions src/pages/iou/request/step/IOURequestStepConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import MoneyRequestConfirmationList from '@components/MoneyRequestConfirmationLi
import {usePersonalDetails} from '@components/OnyxProvider';
import ScreenWrapper from '@components/ScreenWrapper';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useFetchRoute from '@hooks/useFetchRoute';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
Expand Down Expand Up @@ -159,6 +160,8 @@ function IOURequestStepConfirmation({
const isPolicyExpenseChat = useMemo(() => participants?.some((participant) => participant.isPolicyExpenseChat), [participants]);
const formHasBeenSubmitted = useRef(false);

useFetchRoute(transaction, transaction?.comment?.waypoints, action);

useEffect(() => {
const policyExpenseChat = participants?.find((participant) => participant.isPolicyExpenseChat);
if (policyExpenseChat?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/iou/request/step/IOURequestStepDate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function IOURequestStepDate({
return;
}

const isTransactionDraft = action === CONST.IOU.ACTION.CREATE || IOUUtils.isMovingTransactionFromTrackExpense(action);
const isTransactionDraft = IOUUtils.shouldUseTransactionDraft(action);

IOU.setMoneyRequestCreated(transaction?.transactionID ?? '-1', newCreated, isTransactionDraft);

Expand Down
2 changes: 1 addition & 1 deletion src/pages/iou/request/step/IOURequestStepDescription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ function IOURequestStepDescription({
navigateBack();
return;
}
const isTransactionDraft = action === CONST.IOU.ACTION.CREATE || IOUUtils.isMovingTransactionFromTrackExpense(action);
const isTransactionDraft = IOUUtils.shouldUseTransactionDraft(action);

IOU.setMoneyRequestDescription(transaction?.transactionID ?? '-1', newComment, isTransactionDraft);

Expand Down
22 changes: 6 additions & 16 deletions src/pages/iou/request/step/IOURequestStepDistance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import DotIndicatorMessage from '@components/DotIndicatorMessage';
import DraggableList from '@components/DraggableList';
import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails';
import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails';
import useFetchRoute from '@hooks/useFetchRoute';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import usePrevious from '@hooks/usePrevious';
import useThemeStyles from '@hooks/useThemeStyles';
import DistanceRequestUtils from '@libs/DistanceRequestUtils';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
Expand Down Expand Up @@ -87,6 +89,7 @@ function IOURequestStepDistance({
},
[optimisticWaypoints, transaction],
);
const {shouldFetchRoute, validatedWaypoints} = useFetchRoute(transaction, waypoints, action);

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.

Strong reason to believe that this change might've let to the surfacing of the following issue:

which in order to fix we had to extend the logic of useFetchRoute and involve BE. More details in the issue and proposed solution.

const waypointsList = Object.keys(waypoints);
const previousWaypoints = usePrevious(waypoints);
const numberOfWaypoints = Object.keys(waypoints).length;
Expand All @@ -95,12 +98,6 @@ function IOURequestStepDistance({
const isLoadingRoute = transaction?.comment?.isLoading ?? false;
const isLoading = transaction?.isLoading ?? false;
const hasRouteError = !!transaction?.errorFields?.route;
const hasRoute = TransactionUtils.hasRoute(transaction);
const validatedWaypoints = TransactionUtils.getValidWaypoints(waypoints);
const previousValidatedWaypoints = usePrevious(validatedWaypoints);
const haveValidatedWaypointsChanged = !isEqual(previousValidatedWaypoints, validatedWaypoints);
const isRouteAbsentWithoutErrors = !hasRoute && !hasRouteError;
const shouldFetchRoute = (isRouteAbsentWithoutErrors || haveValidatedWaypointsChanged) && !isLoadingRoute && Object.keys(validatedWaypoints).length > 1;
const [shouldShowAtLeastTwoDifferentWaypointsError, setShouldShowAtLeastTwoDifferentWaypointsError] = useState(false);
const isWaypointEmpty = (waypoint?: Waypoint) => {
if (!waypoint) {
Expand Down Expand Up @@ -159,13 +156,6 @@ function IOURequestStepDistance({
return MapboxToken.stop;
}, []);

useEffect(() => {
if (isOffline || !shouldFetchRoute) {
return;
}
TransactionAction.getRoute(transactionID, validatedWaypoints, action === CONST.IOU.ACTION.CREATE);
}, [shouldFetchRoute, transactionID, validatedWaypoints, isOffline, action]);

useEffect(() => {
if (numberOfWaypoints <= numberOfPreviousWaypoints) {
return;
Expand Down Expand Up @@ -199,7 +189,7 @@ function IOURequestStepDistance({
TransactionEdit.removeBackupTransaction(transaction?.transactionID ?? '-1');
return;
}
TransactionEdit.restoreOriginalTransactionFromBackup(transaction?.transactionID ?? '-1', action === CONST.IOU.ACTION.CREATE);
TransactionEdit.restoreOriginalTransactionFromBackup(transaction?.transactionID ?? '-1', IOUUtils.shouldUseTransactionDraft(action));
};
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
}, []);
Expand Down Expand Up @@ -394,8 +384,8 @@ function IOURequestStepDistance({

setOptimisticWaypoints(newWaypoints);
Promise.all([
TransactionAction.removeWaypoint(transaction, emptyWaypointIndex.toString(), action === CONST.IOU.ACTION.CREATE),
TransactionAction.updateWaypoints(transactionID, newWaypoints, action === CONST.IOU.ACTION.CREATE),
TransactionAction.removeWaypoint(transaction, emptyWaypointIndex.toString(), IOUUtils.shouldUseTransactionDraft(action)),
TransactionAction.updateWaypoints(transactionID, newWaypoints, IOUUtils.shouldUseTransactionDraft(action)),
]).then(() => {
setOptimisticWaypoints(null);
});
Expand Down
9 changes: 5 additions & 4 deletions src/pages/iou/request/step/IOURequestStepWaypoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import * as ErrorUtils from '@libs/ErrorUtils';
import * as IOUUtils from '@libs/IOUUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as ValidationUtils from '@libs/ValidationUtils';
import * as Modal from '@userActions/Modal';
Expand Down Expand Up @@ -113,13 +114,13 @@ function IOURequestStepWaypoint({
return errors;
};

const saveWaypoint = (waypoint: FormOnyxValues<'waypointForm'>) => Transaction.saveWaypoint(transactionID, pageIndex, waypoint, action === CONST.IOU.ACTION.CREATE);
const saveWaypoint = (waypoint: FormOnyxValues<'waypointForm'>) => Transaction.saveWaypoint(transactionID, pageIndex, waypoint, IOUUtils.shouldUseTransactionDraft(action));

const submit = (values: FormOnyxValues<'waypointForm'>) => {
const waypointValue = values[`waypoint${pageIndex}`] ?? '';
// Allows letting you set a waypoint to an empty value
if (waypointValue === '') {
Transaction.removeWaypoint(transaction, pageIndex, action === CONST.IOU.ACTION.CREATE);
Transaction.removeWaypoint(transaction, pageIndex, IOUUtils.shouldUseTransactionDraft(action));
}

// While the user is offline, the auto-complete address search will not work
Expand All @@ -140,7 +141,7 @@ function IOURequestStepWaypoint({
};

const deleteStopAndHideModal = () => {
Transaction.removeWaypoint(transaction, pageIndex, action === CONST.IOU.ACTION.CREATE);
Transaction.removeWaypoint(transaction, pageIndex, IOUUtils.shouldUseTransactionDraft(action));
setRestoreFocusType(CONST.MODAL.RESTORE_FOCUS_TYPE.DELETE);
setIsDeleteStopModalOpen(false);
goBack();
Expand All @@ -155,7 +156,7 @@ function IOURequestStepWaypoint({
keyForList: `${values.name ?? 'waypoint'}_${Date.now()}`,
};

Transaction.saveWaypoint(transactionID, pageIndex, waypoint, action === CONST.IOU.ACTION.CREATE);
Transaction.saveWaypoint(transactionID, pageIndex, waypoint, IOUUtils.shouldUseTransactionDraft(action));
goBack();
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export default function <TProps extends WithFullTransactionOrNotFoundProps<Money
const transactionID = route.params.transactionID ?? -1;
const userAction = 'action' in route.params && route.params.action ? route.params.action : CONST.IOU.ACTION.CREATE;

if (userAction === CONST.IOU.ACTION.CREATE || IOUUtils.isMovingTransactionFromTrackExpense(userAction)) {
if (IOUUtils.shouldUseTransactionDraft(userAction)) {
return `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}` as `${typeof ONYXKEYS.COLLECTION.TRANSACTION}${string}`;
}
return `${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`;
Expand Down