diff --git a/src/libs/TransactionUtils/index.ts b/src/libs/TransactionUtils/index.ts index f5712fd337553..3bd854c5d4683 100644 --- a/src/libs/TransactionUtils/index.ts +++ b/src/libs/TransactionUtils/index.ts @@ -580,6 +580,21 @@ function hasReceiptSource(transaction: OnyxInputOrEntry): boolean { return !!transaction?.receipt?.source; } +/** Check if odometer image has the source file */ +function hasOdometerImageSource(transaction: OnyxInputOrEntry, imageType: string): boolean { + const odometerImage = imageType === CONST.IOU.ODOMETER_IMAGE_TYPE.START ? transaction?.comment?.odometerStartImage : transaction?.comment?.odometerEndImage; + if (!odometerImage) { + return false; + } + if (typeof odometerImage === 'string') { + return odometerImage.length > 0; + } + if ('uri' in odometerImage) { + return typeof odometerImage.uri === 'string' && odometerImage.uri.length > 0; + } + return true; +} + function isDemoTransaction(transaction: OnyxInputOrEntry): boolean { return transaction?.comment?.isDemoTransaction ?? false; } @@ -2939,6 +2954,7 @@ export { removeTransactionFromDuplicateTransactionViolation, getCardName, hasReceiptSource, + hasOdometerImageSource, shouldShowAttendees, getAllSortedTransactions, getFormattedPostedDate, diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 19b2c38cf087f..7c652819afa3f 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1537,7 +1537,7 @@ function IOURequestStepConfirmation({ shouldEnableMaxHeight={canUseTouchScreen()} testID="IOURequestStepConfirmation" > - + )?.type ?? (odometerUriExtension ? `image/${odometerUriExtension}` : CONST.IMAGE_FILE_FORMAT.JPEG); const [odometerImageSource, setOdometerImageSource] = useState(undefined); useEffect(() => { @@ -131,13 +150,15 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre const canDeleteReceipt = canEditFieldOfMoneyRequest(parentReportAction, CONST.EDIT_REQUEST_FIELD.RECEIPT, true); const receiptFilename = transaction?.receipt?.filename; - const isImage = !!receiptFilename && Str.isImage(receiptFilename); const isStitchedOdometerReceipt = isOdometerDistanceRequest(transaction) && !imageType; const shouldShowReplaceReceiptButton = ((canEditReceipt && !readonly) || isDraftTransaction) && !transaction?.receipt?.isTestDriveReceipt && !isStitchedOdometerReceipt; const shouldShowDeleteReceiptButton = canDeleteReceipt && !readonly && !isDraftTransaction && !transaction?.receipt?.isTestDriveReceipt; const isEReceipt = transaction && !hasReceiptSource(transaction) && hasEReceipt(transaction); + const fileName = (isOdometerImage ? odometerFilename : receiptFilename) ?? ''; + const isImage = !!fileName && Str.isImage(fileName); + const fileType = isOdometerImage ? odometerFileType : (transaction?.receipt?.type ?? CONST.IMAGE_FILE_FORMAT.JPEG); const isTrackExpenseActionValue = isTrackExpenseAction(parentReportAction); const iouType = useMemo(() => iouTypeParam ?? (isTrackExpenseActionValue ? CONST.IOU.TYPE.TRACK : CONST.IOU.TYPE.SUBMIT), [isTrackExpenseActionValue, iouTypeParam]); @@ -261,13 +282,11 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre return; } - const receiptType = transaction?.receipt?.type ?? CONST.IMAGE_FILE_FORMAT.JPEG; - setIsRotating(true); cropOrRotateImage(sourceUri as string, [{rotate: -90}], { compress: 1, - name: receiptFilename, - type: receiptType, + name: fileName, + type: fileType, }) .then((rotatedImage) => { if (!rotatedImage) { @@ -284,8 +303,10 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre const file = rotatedImage as File; const rotatedFilename = file.name ?? receiptFilename; - if (isDraftTransaction) { - setMoneyRequestReceipt(transaction.transactionID, imageUriResult, rotatedFilename, isDraftTransaction, receiptType); + if (isOdometerImage) { + setMoneyRequestOdometerImage(transaction.transactionID, imageType, file, isDraftTransaction); + } else if (isDraftTransaction) { + setMoneyRequestReceipt(transaction.transactionID, imageUriResult, rotatedFilename, isDraftTransaction, fileType); } else { replaceReceipt({ transactionID: transaction.transactionID, @@ -302,17 +323,17 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre .catch(() => { setIsRotating(false); }); - }, [transaction?.transactionID, isDraftTransaction, sourceUri, isImage, receiptFilename, policyCategories, transaction?.receipt, policy]); + }, [transaction?.transactionID, isDraftTransaction, isOdometerImage, imageType, sourceUri, isImage, receiptFilename, fileName, fileType, policyCategories, transaction?.receipt, policy]); const shouldShowRotateAndCropReceiptButton = useMemo( () => shouldShowReplaceReceiptButton && transaction && - hasReceiptSource(transaction) && + (hasReceiptSource(transaction) || (isOdometerImage && hasOdometerImageSource(transaction, imageType))) && !isEReceipt && !transaction?.receipt?.isTestDriveReceipt && - (receiptFilename ? Str.isImage(receiptFilename) : false), - [shouldShowReplaceReceiptButton, transaction, isEReceipt, receiptFilename], + isImage, + [shouldShowReplaceReceiptButton, transaction, isEReceipt, isOdometerImage, imageType, isImage], ); const enterCropMode = useCallback(() => { @@ -335,8 +356,6 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre return; } - const receiptType = transaction?.receipt?.type ?? CONST.IMAGE_FILE_FORMAT.JPEG; - setIsCropSaving(true); cropOrRotateImage( sourceUri as string, @@ -352,8 +371,8 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre ], { compress: 1, - name: receiptFilename, - type: receiptType, + name: fileName, + type: fileType, }, ) .then((croppedImage) => { @@ -371,8 +390,10 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre const file = croppedImage as File; const croppedFilename = file.name ?? receiptFilename; - if (isDraftTransaction) { - setMoneyRequestReceipt(transaction.transactionID, imageUriResult, croppedFilename, isDraftTransaction, receiptType); + if (isOdometerImage) { + setMoneyRequestOdometerImage(transaction.transactionID, imageType, file, isDraftTransaction); + } else if (isDraftTransaction) { + setMoneyRequestReceipt(transaction.transactionID, imageUriResult, croppedFilename, isDraftTransaction, fileType); } else { replaceReceipt({ transactionID: transaction.transactionID, @@ -388,7 +409,21 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre .catch(() => { setIsCropSaving(false); }); - }, [transaction?.transactionID, isDraftTransaction, sourceUri, isImage, cropRect, receiptFilename, policyCategories, transaction?.receipt?.type, policy, exitCropMode]); + }, [ + transaction?.transactionID, + isDraftTransaction, + isOdometerImage, + imageType, + sourceUri, + isImage, + cropRect, + receiptFilename, + fileName, + fileType, + policyCategories, + policy, + exitCropMode, + ]); const threeDotsMenuItems: ThreeDotsMenuItemFactory = useCallback( ({file, source: innerSource, isLocalSource}) => {