Skip to content

Commit f11bc33

Browse files
committed
fix crop image regression
1 parent 1d43910 commit f11bc33

File tree

2 files changed

+44
-26
lines changed

2 files changed

+44
-26
lines changed

src/components/ReceiptCropView/index.tsx

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type {LayoutChangeEvent} from 'react-native';
33
import {View} from 'react-native';
44
import {Gesture, GestureDetector, GestureHandlerRootView} from 'react-native-gesture-handler';
55
import type {GestureUpdateEvent, PanGestureChangeEventPayload, PanGestureHandlerEventPayload} from 'react-native-gesture-handler';
6+
import ImageSize from 'react-native-image-size';
67
import Animated, {useAnimatedStyle, useSharedValue} from 'react-native-reanimated';
78
import Image from '@components/Image';
89
import RESIZE_MODES from '@components/Image/resizeModes';
@@ -71,6 +72,23 @@ function ReceiptCropView({imageUri, onCropChange, initialCrop, isAuthTokenRequir
7172

7273
const isCropInitialized = imageSize.width > 0 && imageSize.height > 0 && containerSize.width > 0 && containerSize.height > 0;
7374

75+
// Use react-native-image-size to get actual original image dimensions (not downsampled display dimensions).
76+
// On Android, expo-image's onLoad reports Glide-downsampled dimensions, which would make crop coordinates
77+
// wrong for expo-image-manipulator (which operates on full-resolution images). See AvatarCropModal for the same pattern.
78+
useEffect(() => {
79+
if (!imageUri) {
80+
return;
81+
}
82+
ImageSize.getSize(imageUri).then(({width, height, rotation: originalRotation}) => {
83+
// On Android, ImageSize returns rotation; when image is rotated 90/270°, swap width/height for layout.
84+
if (originalRotation === 90 || originalRotation === 270) {
85+
setImageSize({width: height, height: width});
86+
} else {
87+
setImageSize({width, height});
88+
}
89+
});
90+
}, [imageUri]);
91+
7492
// Calculate scale factors to convert display coordinates to image coordinates
7593
const {scaleX, scaleY, displayWidth, displayHeight, imageOffsetX, imageOffsetY} = useMemo(() => {
7694
if (!containerSize.width || !containerSize.height || !imageSize.width || !imageSize.height) {
@@ -235,19 +253,12 @@ function ReceiptCropView({imageUri, onCropChange, initialCrop, isAuthTokenRequir
235253
[containerWidthSV, containerHeightSV],
236254
);
237255

238-
const onImageLoad = useCallback(
239-
(event: {nativeEvent: {width: number; height: number}}) => {
240-
const {width, height} = event.nativeEvent;
241-
if (!width || !height || (imageSize.width === width && imageSize.height === height)) {
242-
return;
243-
}
244-
if (!hasImageDimensions) {
245-
setHasImageDimensions(true);
246-
}
247-
setImageSize({width, height});
248-
},
249-
[hasImageDimensions, imageSize.width, imageSize.height],
250-
);
256+
const onImageLoad = useCallback(() => {
257+
if (hasImageDimensions) {
258+
return;
259+
}
260+
setHasImageDimensions(true);
261+
}, [hasImageDimensions]);
251262

252263
/**
253264
* Clamp a value between min and max

src/pages/media/AttachmentModalScreen/routes/TransactionReceiptModalContent.tsx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import useLocalize from '@hooks/useLocalize';
1111
import useNetwork from '@hooks/useNetwork';
1212
import useOnyx from '@hooks/useOnyx';
1313
import usePolicy from '@hooks/usePolicy';
14+
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1415
import useThemeStyles from '@hooks/useThemeStyles';
1516
import {detachReceipt, navigateToStartStepIfScanFileCannotBeRead, removeMoneyRequestOdometerImage, replaceReceipt, setMoneyRequestReceipt} from '@libs/actions/IOU';
1617
import {openReport} from '@libs/actions/Report';
@@ -28,7 +29,7 @@ import AttachmentModalContainer from '@pages/media/AttachmentModalScreen/Attachm
2829
import type {AttachmentModalScreenProps} from '@pages/media/AttachmentModalScreen/types';
2930
import CONST from '@src/CONST';
3031
import ONYXKEYS from '@src/ONYXKEYS';
31-
import ROUTES from '@src/ROUTES';
32+
import ROUTES, {type Route} from '@src/ROUTES';
3233
import type SCREENS from '@src/SCREENS';
3334
import type {ReceiptSource} from '@src/types/onyx/Transaction';
3435
import type {FileObject} from '@src/types/utils/Attachment';
@@ -50,6 +51,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
5051
const [session] = useOnyx(ONYXKEYS.SESSION);
5152
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
5253
const policy = usePolicy(report?.policyID);
54+
const {shouldUseNarrowLayout} = useResponsiveLayout();
5355

5456
// If we have a merge transaction, we need to use the receipt from the merge transaction
5557
const [mergeTransaction] = useOnyx(`${ONYXKEYS.COLLECTION.MERGE_TRANSACTION}${getNonEmptyStringOnyxID(mergeTransactionID)}`);
@@ -503,19 +505,23 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
503505
<Button
504506
icon={expensifyIcons.Camera}
505507
onPress={() => {
508+
const destinationRoute: Route = isOdometerImage
509+
? ROUTES.ODOMETER_IMAGE.getRoute(action ?? CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, imageType)
510+
: ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(
511+
action ?? CONST.IOU.ACTION.EDIT,
512+
iouType,
513+
draftTransactionID ?? transaction?.transactionID,
514+
report?.reportID,
515+
Navigation.getActiveRoute(),
516+
);
517+
518+
if (shouldUseNarrowLayout) {
519+
Navigation.navigate(destinationRoute, {forceReplace: true});
520+
return;
521+
}
522+
506523
Navigation.dismissModal({
507-
callback: () =>
508-
Navigation.navigate(
509-
isOdometerImage
510-
? ROUTES.ODOMETER_IMAGE.getRoute(action ?? CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, imageType)
511-
: ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(
512-
action ?? CONST.IOU.ACTION.EDIT,
513-
iouType,
514-
draftTransactionID ?? transaction?.transactionID,
515-
report?.reportID,
516-
Navigation.getActiveRoute(),
517-
),
518-
),
524+
callback: () => Navigation.navigate(destinationRoute),
519525
});
520526
}}
521527
text={translate('common.replace')}
@@ -556,6 +562,7 @@ function TransactionReceiptModalContent({navigation, route}: AttachmentModalScre
556562
draftTransactionID,
557563
transaction?.transactionID,
558564
report?.reportID,
565+
shouldUseNarrowLayout,
559566
]);
560567

561568
const customAttachmentContent = useMemo(() => {

0 commit comments

Comments
 (0)