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
22 changes: 15 additions & 7 deletions src/libs/actions/IOU/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@
};

let allPersonalDetails: OnyxTypes.PersonalDetailsList = {};
Onyx.connect({

Check warning on line 795 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
allPersonalDetails = value ?? {};
Expand Down Expand Up @@ -925,7 +925,7 @@
};

let allTransactions: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 928 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -939,7 +939,7 @@
});

let allTransactionDrafts: NonNullable<OnyxCollection<OnyxTypes.Transaction>> = {};
Onyx.connect({

Check warning on line 942 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_DRAFT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -948,7 +948,7 @@
});

let allTransactionViolations: NonNullable<OnyxCollection<OnyxTypes.TransactionViolations>> = {};
Onyx.connect({

Check warning on line 951 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -962,7 +962,7 @@
});

let allPolicyTags: OnyxCollection<OnyxTypes.PolicyTagLists> = {};
Onyx.connect({

Check warning on line 965 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY_TAGS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -975,7 +975,7 @@
});

let allReports: OnyxCollection<OnyxTypes.Report>;
Onyx.connect({

Check warning on line 978 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -984,7 +984,7 @@
});

let allReportNameValuePairs: OnyxCollection<OnyxTypes.ReportNameValuePairs>;
Onyx.connect({

Check warning on line 987 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -994,7 +994,7 @@

let deprecatedUserAccountID = -1;
let deprecatedCurrentUserEmail = '';
Onyx.connect({

Check warning on line 997 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
deprecatedCurrentUserEmail = value?.email ?? '';
Expand All @@ -1003,7 +1003,7 @@
});

let deprecatedCurrentUserPersonalDetails: OnyxEntry<OnyxTypes.PersonalDetails>;
Onyx.connect({

Check warning on line 1006 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.PERSONAL_DETAILS_LIST,
callback: (value) => {
deprecatedCurrentUserPersonalDetails = value?.[deprecatedUserAccountID] ?? undefined;
Expand All @@ -1011,7 +1011,7 @@
});

let allReportActions: OnyxCollection<OnyxTypes.ReportActions>;
Onyx.connect({

Check warning on line 1014 in src/libs/actions/IOU/index.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {
Expand Down Expand Up @@ -1698,13 +1698,19 @@

/**
* Set odometer image for a transaction
* @param transactionID - The transaction ID
* @param transaction - The transaction or transaction draft
* @param imageType - 'start' or 'end'
* @param file - The image file (File object on web, URI string on native)
* @param isDraft - Whether this is a draft transaction
* @param shouldRevokeOldImage - Whether to revoke the previous blob URL immediately (always false on native where blob URLs don't exist; false on web when a backup transaction exists making the caller responsible for revoking)
*/
function setMoneyRequestOdometerImage(transactionID: string, imageType: OdometerImageType, file: FileObject | string, isDraft: boolean, shouldRevokeOldImage: boolean) {
function setMoneyRequestOdometerImage(
transaction: OnyxEntry<OnyxTypes.Transaction>,
imageType: OdometerImageType,
file: FileObject | string,
isDraft: boolean,
shouldRevokeOldImage: boolean,
) {
const imageKey = imageType === CONST.IOU.ODOMETER_IMAGE_TYPE.START ? 'odometerStartImage' : 'odometerEndImage';
const normalizedFile: FileObject | string =
typeof file === 'string'
Expand All @@ -1715,7 +1721,7 @@
type: file.type,
size: file.size,
};
const transaction = isDraft ? allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`] : allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
const transactionID = transaction?.transactionID;
const existingImage = transaction?.comment?.[imageKey];
if (shouldRevokeOldImage) {
revokeOdometerImageUri(existingImage, normalizedFile);
Expand All @@ -1729,19 +1735,21 @@

/**
* Remove odometer image from a transaction
* @param transactionID - The transaction ID
* @param transaction - The transaction or transaction draft
* @param imageType - 'start' or 'end'
* @param isDraft - Whether this is a draft transaction
* @param shouldRevokeOldImage - Whether to revoke the previous blob URL immediately (always false on native where blob URLs don't exist; false on web when a backup transaction exists making the caller responsible for revoking)
*/
function removeMoneyRequestOdometerImage(transactionID: string, imageType: OdometerImageType, isDraft: boolean, shouldRevokeOldImage: boolean) {
function removeMoneyRequestOdometerImage(transaction: OnyxEntry<OnyxTypes.Transaction>, imageType: OdometerImageType, isDraft: boolean, shouldRevokeOldImage: boolean) {
if (!transaction?.transactionID) {
return;
Comment thread
parasharrajat marked this conversation as resolved.
}
const imageKey = imageType === CONST.IOU.ODOMETER_IMAGE_TYPE.START ? 'odometerStartImage' : 'odometerEndImage';
const transaction = isDraft ? allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`] : allTransactions[`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`];
const existingImage = transaction?.comment?.[imageKey];
if (shouldRevokeOldImage) {
revokeOdometerImageUri(existingImage);
}
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {
Onyx.merge(`${isDraft ? ONYXKEYS.COLLECTION.TRANSACTION_DRAFT : ONYXKEYS.COLLECTION.TRANSACTION}${transaction?.transactionID}`, {
Comment thread
parasharrajat marked this conversation as resolved.
comment: {
[imageKey]: null,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function IOURequestStepOdometerImage({
route: {
params: {action, iouType, transactionID, reportID, backToReport, imageType, isEditingConfirmation},
},
transaction,
}: IOURequestStepOdometerImageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
Expand Down Expand Up @@ -187,7 +188,7 @@ function IOURequestStepOdometerImage({
if (!file) {
return;
}
setMoneyRequestOdometerImage(transactionID, imageType, getOdometerImageUri(file), isTransactionDraft, false);
setMoneyRequestOdometerImage(transaction, imageType, getOdometerImageUri(file), isTransactionDraft, false);
navigateBack();
};

Expand Down Expand Up @@ -242,7 +243,7 @@ function IOURequestStepOdometerImage({
cropImageToAspectRatio(imageObject, viewfinderLayout.current?.width, viewfinderLayout.current?.height, undefined, photo.orientation)
.then(({file, filename, source}) => {
setMoneyRequestOdometerImage(
transactionID,
transaction,
imageType,
{
uri: source,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function IOURequestStepOdometerImage({
route: {
params: {action, iouType, transactionID, reportID, backToReport, imageType, isEditingConfirmation},
},
transaction,
}: IOURequestStepOdometerImageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
Expand Down Expand Up @@ -88,7 +89,7 @@ function IOURequestStepOdometerImage({
};

const handleImageSelected = (file: FileObject) => {
setMoneyRequestOdometerImage(transactionID, imageType, file as File, isTransactionDraft, isEditingConfirmation !== 'true');
setMoneyRequestOdometerImage(transaction, imageType, file as File, isTransactionDraft, isEditingConfirmation !== 'true');
shouldRevokeOnUnmountRef.current = false;
navigateBack();
};
Expand Down Expand Up @@ -230,7 +231,7 @@ function IOURequestStepOdometerImage({
if (source !== imageObject.source) {
URL.revokeObjectURL(imageObject.source);
}
setMoneyRequestOdometerImage(transactionID, imageType, file ?? source, isTransactionDraft, isEditingConfirmation !== 'true');
setMoneyRequestOdometerImage(transaction, imageType, file ?? source, isTransactionDraft, isEditingConfirmation !== 'true');
navigateBack();
})
.catch((error: unknown) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,14 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
if (!transaction?.transactionID || !imageType) {
return;
}
removeMoneyRequestOdometerImage(transaction.transactionID, imageType, isDraftTransaction, !isEditingConfirmation);
removeMoneyRequestOdometerImage(transaction, imageType, isDraftTransaction, !isEditingConfirmation);
const odometerGoBackRoute =
isOdometerImage &&
(isEditingConfirmation === true
? ROUTES.MONEY_REQUEST_STEP_DISTANCE_ODOMETER.getRoute(action ?? CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)
: ROUTES.DISTANCE_REQUEST_CREATE_TAB_ODOMETER.getRoute(action ?? CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToReport));
Navigation.goBack(odometerGoBackRoute || undefined);
}, [transaction?.transactionID, imageType, isOdometerImage, isDraftTransaction, isEditingConfirmation, action, iouType, transactionID, reportID, backToReport]);
}, [transaction, imageType, isDraftTransaction, isOdometerImage, isEditingConfirmation, action, iouType, transactionID, reportID, backToReport]);

const onDownloadAttachment = useDownloadAttachment({
isAuthTokenRequired,
Expand Down Expand Up @@ -309,7 +309,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
const rotatedFilename = file.name ?? receiptFilename;

if (isOdometerImage) {
setMoneyRequestOdometerImage(transaction.transactionID, imageType, file, isDraftTransaction, !isEditingConfirmation);
setMoneyRequestOdometerImage(transaction, imageType, file, isDraftTransaction, !isEditingConfirmation);
} else if (isDraftTransaction) {
setMoneyRequestReceipt(transaction.transactionID, imageUriResult, rotatedFilename, isDraftTransaction, fileType);
} else {
Expand All @@ -328,21 +328,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
.catch(() => {
setIsRotating(false);
});
}, [
transaction?.transactionID,
isDraftTransaction,
isOdometerImage,
imageType,
sourceUri,
isImage,
receiptFilename,
fileName,
fileType,
policyCategories,
transaction?.receipt,
policy,
isEditingConfirmation,
]);
}, [transaction, sourceUri, isImage, fileName, fileType, receiptFilename, isOdometerImage, isDraftTransaction, imageType, isEditingConfirmation, policyCategories, policy]);

const shouldShowRotateAndCropReceiptButton = useMemo(
() =>
Expand Down Expand Up @@ -410,7 +396,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
const croppedFilename = file.name ?? receiptFilename;

if (isOdometerImage) {
setMoneyRequestOdometerImage(transaction.transactionID, imageType, file, isDraftTransaction, !isEditingConfirmation);
setMoneyRequestOdometerImage(transaction, imageType, file, isDraftTransaction, !isEditingConfirmation);
} else if (isDraftTransaction) {
setMoneyRequestReceipt(transaction.transactionID, imageUriResult, croppedFilename, isDraftTransaction, fileType);
} else {
Expand All @@ -429,20 +415,20 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
setIsCropSaving(false);
});
}, [
transaction?.transactionID,
isDraftTransaction,
isOdometerImage,
imageType,
transaction,
sourceUri,
isImage,
cropRect,
receiptFilename,
fileName,
fileType,
policyCategories,
policy,
exitCropMode,
receiptFilename,
isOdometerImage,
isDraftTransaction,
imageType,
isEditingConfirmation,
policyCategories,
policy,
]);

const threeDotsMenuItems: ThreeDotsMenuItemFactory = useCallback(
Expand Down
83 changes: 83 additions & 0 deletions tests/actions/IOUTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ import {
payMoneyRequest,
rejectExpenseReport,
rejectMoneyRequest,
removeMoneyRequestOdometerImage,
replaceReceipt,
requestMoney,
resetDraftTransactionsCustomUnit,
retractReport,
setMoneyRequestCategory,
setMoneyRequestDistanceRate,
setMoneyRequestOdometerImage,
shouldOptimisticallyUpdateSearch,
submitReport,
trackExpense,
Expand Down Expand Up @@ -17516,4 +17518,85 @@ describe('actions/IOU', () => {
expect(updatedTransaction?.comment?.customUnit?.quantity).toBe(100);
});
});

describe('setMoneyRequestOdometerImage and removeMoneyRequestOdometerImage', () => {
beforeEach(() => {
jest.mock('@libs/OdometerImageUtils', () => ({
// eslint-disable-next-line @typescript-eslint/naming-convention
__esModule: true,
default: jest.fn(),
}));
});

afterEach(() => {
jest.unmock('@libs/OdometerImageUtils');
});
it('should set odometer start image on a draft transaction', async () => {
const transaction = createRandomTransaction(1);
const transactionID = transaction.transactionID;
const file = {uri: 'image.uri', name: 'image.jpg', type: 'image/jpeg', size: 1234};
const imageType = CONST.IOU.ODOMETER_IMAGE_TYPE.START;

await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, transaction);

setMoneyRequestOdometerImage(transaction, imageType, file, true, false);
await waitForBatchedUpdates();

const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`);
expect(draftTransaction?.comment?.odometerStartImage).toEqual(file);
});

it('should set odometer end image on a non-draft transaction', async () => {
const transaction = createRandomTransaction(1);
const transactionID = transaction.transactionID;
const file = {uri: 'image.uri', name: 'image.jpg', type: 'image/jpeg', size: 1234};
const imageType = CONST.IOU.ODOMETER_IMAGE_TYPE.END;

await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, transaction);

setMoneyRequestOdometerImage(transaction, imageType, file, false, false);
await waitForBatchedUpdates();

const updatedTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`);
expect(updatedTransaction?.comment?.odometerEndImage).toEqual(file);
});

it('should remove odometer start image from a draft transaction', async () => {
const transaction = {
...createRandomTransaction(1),
comment: {
odometerStartImage: {uri: 'image.uri'},
},
} as Transaction;
const transactionID = transaction.transactionID;
const imageType = CONST.IOU.ODOMETER_IMAGE_TYPE.START;

await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, transaction);

removeMoneyRequestOdometerImage(transaction, imageType, true, false);
await waitForBatchedUpdates();

const draftTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`);
expect(draftTransaction?.comment?.odometerStartImage).toBeUndefined();
});

it('should remove odometer end image from a non-draft transaction', async () => {
const transaction = {
...createRandomTransaction(1),
comment: {
odometerEndImage: {uri: 'image.uri'},
},
} as Transaction;
const transactionID = transaction.transactionID;
const imageType = CONST.IOU.ODOMETER_IMAGE_TYPE.END;

await Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, transaction);

removeMoneyRequestOdometerImage(transaction, imageType, false, false);
await waitForBatchedUpdates();

const updatedTransaction = await getOnyxValue(`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`);
expect(updatedTransaction?.comment?.odometerEndImage).toBeUndefined();
});
});
});
Loading