diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
index 5552f15320f3..abe371768879 100644
--- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js
+++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js
@@ -37,15 +37,6 @@ const propTypes = {
transactionID: PropTypes.string,
}).isRequired,
- /** Whether there is only one element in the attachment carousel */
- isSingleItem: PropTypes.bool.isRequired,
-
- /** The index of the carousel item */
- index: PropTypes.number.isRequired,
-
- /** The index of the currently active carousel item */
- activeIndex: PropTypes.number.isRequired,
-
/** onPress callback */
onPress: PropTypes.func,
};
@@ -54,7 +45,7 @@ const defaultProps = {
onPress: undefined,
};
-function CarouselItem({item, index, activeIndex, isSingleItem, onPress}) {
+function CarouselItem({item, onPress}) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isAttachmentHidden} = useContext(ReportAttachmentsContext);
@@ -103,12 +94,8 @@ function CarouselItem({item, index, activeIndex, isSingleItem, onPress}) {
diff --git a/src/components/Attachments/AttachmentCarousel/Pager/index.js b/src/components/Attachments/AttachmentCarousel/Pager/index.js
index e0f652e47e4c..84f77dae4953 100644
--- a/src/components/Attachments/AttachmentCarousel/Pager/index.js
+++ b/src/components/Attachments/AttachmentCarousel/Pager/index.js
@@ -3,8 +3,9 @@ import React, {useEffect, useImperativeHandle, useMemo, useRef, useState} from '
import {View} from 'react-native';
import {createNativeWrapper} from 'react-native-gesture-handler';
import PagerView from 'react-native-pager-view';
-import Animated, {runOnJS, useAnimatedProps, useAnimatedReaction, useEvent, useHandler, useSharedValue} from 'react-native-reanimated';
+import Animated, {runOnJS, useAnimatedReaction, useEvent, useHandler, useSharedValue} from 'react-native-reanimated';
import _ from 'underscore';
+import CarouselItem from '@components/Attachments/AttachmentCarousel/CarouselItem';
import refPropTypes from '@components/refPropTypes';
import useThemeStyles from '@hooks/useThemeStyles';
import AttachmentCarouselPagerContext from './AttachmentCarouselPagerContext';
@@ -36,8 +37,9 @@ const pagerPropTypes = {
url: PropTypes.string,
}),
).isRequired,
- renderItem: PropTypes.func.isRequired,
- initialIndex: PropTypes.number,
+ activeSource: PropTypes.string.isRequired,
+ initialPage: PropTypes.number,
+ scrollEnabled: PropTypes.bool,
onPageSelected: PropTypes.func,
onTap: PropTypes.func,
onScaleChanged: PropTypes.func,
@@ -45,53 +47,61 @@ const pagerPropTypes = {
};
const pagerDefaultProps = {
- initialIndex: 0,
+ initialPage: 0,
+ scrollEnabled: true,
onPageSelected: () => {},
onTap: () => {},
onScaleChanged: () => {},
forwardedRef: null,
};
-function AttachmentCarouselPager({items, renderItem, initialIndex, onPageSelected, onTap, onScaleChanged, forwardedRef}) {
+function AttachmentCarouselPager({items, activeSource, initialPage, scrollEnabled, onPageSelected, onTap, onScaleChanged, forwardedRef}) {
const styles = useThemeStyles();
- const shouldPagerScroll = useSharedValue(true);
const pagerRef = useRef(null);
- const isSwipingInPager = useSharedValue(false);
- const activeIndex = useSharedValue(initialIndex);
+ const activePage = useSharedValue(initialPage);
+ const [activePageState, setActivePageState] = useState(initialPage);
+ // Set active page initially and when initial page changes
+ useEffect(() => {
+ setActivePageState(initialPage);
+ activePage.value = initialPage;
+ }, [activePage, initialPage]);
+
+ const itemsMeta = useMemo(() => _.map(items, (item, index) => ({source: item.source, index, isActive: index === activePageState})), [activePageState, items]);
+
+ const isPagerSwiping = useSharedValue(false);
const pageScrollHandler = usePageScrollHandler(
{
onPageScroll: (e) => {
'worklet';
- activeIndex.value = e.position;
- isSwipingInPager.value = e.offset !== 0;
+ activePage.value = e.position;
+ isPagerSwiping.value = e.offset !== 0;
},
},
[],
);
- const [activePage, setActivePage] = useState(initialIndex);
-
- useEffect(() => {
- setActivePage(initialIndex);
- activeIndex.value = initialIndex;
- }, [activeIndex, initialIndex]);
-
- // we use reanimated for this since onPageSelected is called
- // in the middle of the pager animation
+ const [isPagerSwipingState, setPagerSwipingState] = useState(false);
useAnimatedReaction(
- () => isSwipingInPager.value,
- (stillScrolling) => {
- if (stillScrolling) {
- return;
- }
-
- runOnJS(setActivePage)(activeIndex.value);
+ () => [isPagerSwiping.value],
+ (isSwiping) => {
+ runOnJS(setPagerSwipingState)(isSwiping);
},
);
+ const contextValue = useMemo(
+ () => ({
+ itemsMeta,
+ activePage: activePageState,
+ isPagerSwiping: isPagerSwipingState,
+ onTap,
+ onScaleChanged,
+ }),
+ [activePageState, isPagerSwipingState, itemsMeta, onScaleChanged, onTap],
+ );
+
useImperativeHandle(
forwardedRef,
() => ({
@@ -100,19 +110,22 @@ function AttachmentCarouselPager({items, renderItem, initialIndex, onPageSelecte
[],
);
- const animatedProps = useAnimatedProps(() => ({
- scrollEnabled: shouldPagerScroll.value,
- }));
-
- const contextValue = useMemo(
- () => ({
- onTap,
- onScaleChanged,
- pagerRef,
- shouldPagerScroll,
- isSwipingInPager,
- }),
- [isSwipingInPager, shouldPagerScroll, onScaleChanged, onTap],
+ const Content = useMemo(
+ () =>
+ _.map(items, (item, index) => (
+
+
+
+ )),
+ [activePageState, activeSource, items, styles.flex1],
);
return (
@@ -120,21 +133,14 @@ function AttachmentCarouselPager({items, renderItem, initialIndex, onPageSelecte
- {_.map(items, (item, index) => (
-
- {renderItem({item, index, isActive: index === activePage})}
-
- ))}
+ {Content}
);
diff --git a/src/components/Attachments/AttachmentCarousel/index.native.js b/src/components/Attachments/AttachmentCarousel/index.native.js
index 8f168093c217..64262b38b0d1 100644
--- a/src/components/Attachments/AttachmentCarousel/index.native.js
+++ b/src/components/Attachments/AttachmentCarousel/index.native.js
@@ -13,7 +13,6 @@ import variables from '@styles/variables';
import ONYXKEYS from '@src/ONYXKEYS';
import {defaultProps, propTypes} from './attachmentCarouselPropTypes';
import CarouselButtons from './CarouselButtons';
-import CarouselItem from './CarouselItem';
import extractAttachmentsFromReport from './extractAttachmentsFromReport';
import AttachmentCarouselPager from './Pager';
import useCarouselArrows from './useCarouselArrows';
@@ -88,25 +87,6 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source,
[autoHideArrows, page, updatePage],
);
- /**
- * Defines how a single attachment should be rendered
- * @param {{ reportActionID: String, isAuthTokenRequired: Boolean, source: String, file: { name: String }, hasBeenFlagged: Boolean }} item
- * @returns {JSX.Element}
- */
- const renderItem = useCallback(
- ({item, index, isActive}) => (
- setShouldShowArrows(!shouldShowArrows)}
- />
- ),
- [activeSource, attachments.length, page, setShouldShowArrows, shouldShowArrows],
- );
-
const handleScaleChange = useCallback(
(newScale) => {
const newIsZoomedOut = newScale === 1;
@@ -122,11 +102,7 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source,
);
return (
- setShouldShowArrows(true)}
- onMouseLeave={() => setShouldShowArrows(false)}
- >
+
{page == null ? (
) : (
@@ -152,8 +128,10 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source,
setShouldShowArrows(!shouldShowArrows)}
onPageSelected={({nativeEvent: {position: newPage}}) => updatePage(newPage)}
onScaleChanged={handleScaleChange}
ref={pagerRef}
diff --git a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
index f53b993f6053..05c27213557f 100755
--- a/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
+++ b/src/components/Attachments/AttachmentView/AttachmentViewImage/index.js
@@ -12,22 +12,7 @@ const propTypes = {
...withLocalizePropTypes,
};
-function AttachmentViewImage({
- source,
- file,
- isAuthTokenRequired,
- isUsedInCarousel,
- isSingleCarouselItem,
- carouselItemIndex,
- carouselActiveItemIndex,
- isFocused,
- loadComplete,
- onPress,
- onError,
- isImage,
- onScaleChanged,
- translate,
-}) {
+function AttachmentViewImage({source, file, isAuthTokenRequired, isFocused, loadComplete, onPress, onError, isImage, onScaleChanged, translate}) {
const styles = useThemeStyles();
const children = (
);
diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js
index b0060afdb813..179d627a23fa 100755
--- a/src/components/Attachments/AttachmentView/index.js
+++ b/src/components/Attachments/AttachmentView/index.js
@@ -72,9 +72,6 @@ function AttachmentView({
translate,
isFocused,
isUsedInCarousel,
- isSingleCarouselItem,
- carouselItemIndex,
- carouselActiveItemIndex,
isUsedInAttachmentModal,
isWorkspaceAvatar,
fallbackSource,
@@ -138,8 +135,6 @@ function AttachmentView({
isFocused={isFocused}
isAuthTokenRequired={isAuthTokenRequired}
encryptedSourceUrl={encryptedSourceUrl}
- carouselItemIndex={carouselItemIndex}
- carouselActiveItemIndex={carouselActiveItemIndex}
onPress={onPress}
onScaleChanged={onScaleChanged}
onToggleKeyboard={onToggleKeyboard}
@@ -169,9 +164,6 @@ function AttachmentView({
loadComplete={loadComplete}
isFocused={isFocused}
isUsedInCarousel={isUsedInCarousel}
- isSingleCarouselItem={isSingleCarouselItem}
- carouselItemIndex={carouselItemIndex}
- carouselActiveItemIndex={carouselActiveItemIndex}
isImage={isImage}
onPress={onPress}
onScaleChanged={onScaleChanged}
diff --git a/src/components/Attachments/AttachmentView/propTypes.js b/src/components/Attachments/AttachmentView/propTypes.js
index 286c903ccf5b..31750da53e77 100644
--- a/src/components/Attachments/AttachmentView/propTypes.js
+++ b/src/components/Attachments/AttachmentView/propTypes.js
@@ -17,18 +17,6 @@ const attachmentViewPropTypes = {
/** Whether this AttachmentView is shown as part of a AttachmentCarousel */
isUsedInCarousel: PropTypes.bool,
- /** When "isUsedInCarousel" is set to true, determines whether there is only one item in the carousel */
- isSingleCarouselItem: PropTypes.bool,
-
- /** Whether this AttachmentView is shown as part of an AttachmentModal */
- isUsedInAttachmentModal: PropTypes.bool,
-
- /** The index of the carousel item */
- carouselItemIndex: PropTypes.number,
-
- /** The index of the currently active carousel item */
- carouselActiveItemIndex: PropTypes.number,
-
/** Function for handle on press */
onPress: PropTypes.func,
@@ -42,11 +30,8 @@ const attachmentViewDefaultProps = {
name: '',
},
isFocused: false,
- isUsedInCarousel: false,
- isSingleCarouselItem: false,
- carouselItemIndex: 0,
- carouselActiveItemIndex: 0,
isSingleElement: false,
+ isUsedInCarousel: false,
isUsedInAttachmentModal: false,
onPress: undefined,
onScaleChanged: () => {},
diff --git a/src/components/ImageView/index.native.js b/src/components/ImageView/index.native.js
index 98349b213aa5..007bc753ec0d 100644
--- a/src/components/ImageView/index.native.js
+++ b/src/components/ImageView/index.native.js
@@ -11,9 +11,6 @@ const propTypes = {
...imageViewPropTypes,
...zoomRangePropTypes,
- /** Function for handle on press */
- onPress: PropTypes.func,
-
/** Additional styles to add to the component */
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
};
@@ -26,20 +23,14 @@ const defaultProps = {
style: {},
};
-function ImageView({isAuthTokenRequired, url, onScaleChanged, onPress, style, zoomRange, onError, isUsedInCarousel, isSingleCarouselItem, carouselItemIndex, carouselActiveItemIndex}) {
- const hasSiblingCarouselItems = isUsedInCarousel && !isSingleCarouselItem;
-
+function ImageView({isAuthTokenRequired, url, onScaleChanged, style, zoomRange, onError}) {
return (
);
diff --git a/src/components/ImageView/propTypes.js b/src/components/ImageView/propTypes.js
index 3809d9aed043..359626e4bd69 100644
--- a/src/components/ImageView/propTypes.js
+++ b/src/components/ImageView/propTypes.js
@@ -19,28 +19,12 @@ const imageViewPropTypes = {
/** Whether this view is the active screen */
isFocused: PropTypes.bool,
-
- /** Whether this AttachmentView is shown as part of a AttachmentCarousel */
- isUsedInCarousel: PropTypes.bool,
-
- /** When "isUsedInCarousel" is set to true, determines whether there is only one item in the carousel */
- isSingleCarouselItem: PropTypes.bool,
-
- /** The index of the carousel item */
- carouselItemIndex: PropTypes.number,
-
- /** The index of the currently active carousel item */
- carouselActiveItemIndex: PropTypes.number,
};
const imageViewDefaultProps = {
isAuthTokenRequired: false,
onError: () => {},
isFocused: true,
- isUsedInCarousel: false,
- isSingleCarouselItem: false,
- carouselItemIndex: 0,
- carouselActiveItemIndex: 0,
};
export {imageViewPropTypes, imageViewDefaultProps};
diff --git a/src/components/Lightbox.js b/src/components/Lightbox.js
index 366759cc6cd7..6f1f7a0c6437 100644
--- a/src/components/Lightbox.js
+++ b/src/components/Lightbox.js
@@ -1,8 +1,10 @@
/* eslint-disable es/no-optional-chaining */
+import _ from 'lodash';
import PropTypes from 'prop-types';
-import React, {useCallback, useEffect, useMemo, useState} from 'react';
+import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react';
import {ActivityIndicator, PixelRatio, StyleSheet, View} from 'react-native';
import useStyleUtils from '@hooks/useStyleUtils';
+import AttachmentCarouselPagerContext from './Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext';
import * as AttachmentsPropTypes from './Attachments/propTypes';
import Image from './Image';
import MultiGestureCanvas from './MultiGestureCanvas';
@@ -25,9 +27,6 @@ const propTypes = {
/** Triggers whenever the zoom scale changes */
onScaleChanged: PropTypes.func,
- /** Function for handle on press */
- onPress: PropTypes.func,
-
/** Handles errors while displaying the image */
onError: PropTypes.func,
@@ -37,15 +36,6 @@ const propTypes = {
/** Whether source url requires authentication */
isAuthTokenRequired: PropTypes.bool,
- /** Whether the Lightbox is used within a carousel component and there are other sibling elements */
- hasSiblingCarouselItems: PropTypes.bool,
-
- /** The index of the carousel item */
- index: PropTypes.number,
-
- /** The index of the currently active carousel item */
- activeIndex: PropTypes.number,
-
/** Additional styles to add to the component */
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),
};
@@ -54,20 +44,39 @@ const defaultProps = {
...zoomRangeDefaultProps,
isAuthTokenRequired: false,
- index: 0,
- activeIndex: 0,
- hasSiblingCarouselItems: false,
onScaleChanged: () => {},
- onPress: () => {},
onError: () => {},
style: {},
};
const DEFAULT_IMAGE_SIZE = 200;
-function Lightbox({isAuthTokenRequired, source, onScaleChanged, onPress, onError, style, index, activeIndex, hasSiblingCarouselItems, zoomRange}) {
+function Lightbox({isAuthTokenRequired, source, onScaleChanged, onError, style, zoomRange}) {
const StyleUtils = useStyleUtils();
+ const attachmentCarouselPagerContext = useContext(AttachmentCarouselPagerContext);
+ const {isUsedInCarousel, isSingleCarouselItem, page, activePage, onTap, isPagerSwiping} = useMemo(() => {
+ if (attachmentCarouselPagerContext == null) {
+ return {
+ isUsedInCarousel: false,
+ isSingleCarouselItem: true,
+ page: 0,
+ activePage: 0,
+ onTap: () => {},
+ isPagerSwiping: false,
+ };
+ }
+
+ const foundPageIndex = _.findIndex(attachmentCarouselPagerContext.itemsMeta, (item) => item.source === source);
+ return {
+ ...attachmentCarouselPagerContext,
+ isUsedInCarousel: true,
+ isSingleCarouselItem: attachmentCarouselPagerContext.itemsMeta.length === 1,
+ page: foundPageIndex,
+ };
+ }, [attachmentCarouselPagerContext, source]);
+ const hasSiblingCarouselItems = isUsedInCarousel && !isSingleCarouselItem;
+
const [containerSize, setContainerSize] = useState({width: 0, height: 0});
const isContainerLoaded = containerSize.width !== 0 && containerSize.height !== 0;
@@ -77,8 +86,8 @@ function Lightbox({isAuthTokenRequired, source, onScaleChanged, onPress, onError
cachedDimensions.set(source, newDimensions);
};
- const isItemActive = index === activeIndex;
- const [isActive, setActive] = useState(isItemActive);
+ const isActivePage = page === activePage;
+ const [isActive, setActive] = useState(isActivePage);
const [isImageLoaded, setImageLoaded] = useState(false);
const isInactiveCarouselItem = hasSiblingCarouselItems && !isActive;
@@ -92,9 +101,9 @@ function Lightbox({isAuthTokenRequired, source, onScaleChanged, onPress, onError
}
const indexCanvasOffset = Math.floor((NUMBER_OF_CONCURRENT_LIGHTBOXES - 1) / 2) || 0;
- const indexOutOfRange = index > activeIndex + indexCanvasOffset || index < activeIndex - indexCanvasOffset;
+ const indexOutOfRange = page > activePage + indexCanvasOffset || page < activePage - indexCanvasOffset;
return !indexOutOfRange;
- }, [activeIndex, index]);
+ }, [activePage, page]);
const isLightboxVisible = isLightboxInRange && (isActive || isLightboxLoaded || isFallbackLoaded);
// If the fallback image is currently visible, we want to hide the Lightbox until the fallback gets hidden,
@@ -114,12 +123,12 @@ function Lightbox({isAuthTokenRequired, source, onScaleChanged, onPress, onError
// to prevent the image transformer from flashing while still rendering
// Instead, we show the fallback image while the image transformer is loading the image
useEffect(() => {
- if (isItemActive) {
+ if (isActivePage) {
setTimeout(() => setActive(true), 1);
} else {
setActive(false);
}
- }, [isItemActive]);
+ }, [isActivePage]);
useEffect(() => {
if (isLightboxVisible) {
@@ -171,7 +180,6 @@ function Lightbox({isAuthTokenRequired, source, onScaleChanged, onPress, onError
return (
@@ -181,6 +189,8 @@ function Lightbox({isAuthTokenRequired, source, onScaleChanged, onPress, onError
- attachmentCarouselPagerContext || {
- onTap: () => {},
- onScaleChanged: () => {},
- pagerRef: pagerRefFallback,
- shouldPagerScroll: false,
- isSwipingInPager: false,
- },
- [attachmentCarouselPagerContext],
- );
-
- const onScaleChanged = useCallback(
- (newScale) => {
- onScaleChangedProp(newScale);
- onScaleChangedContext(newScale);
- },
- [onScaleChangedContext, onScaleChangedProp],
- );
-
// Based on the (original) content size and the canvas size, we calculate the horizontal and vertical scale factors
// to fit the content inside the canvas
// We later use the lower of the two scale factors to fit the content inside the canvas
@@ -123,7 +92,8 @@ function MultiGestureCanvas({canvasSize, isActive = true, onScaleChanged: onScal
zoomScale.value = 1;
});
- const {singleTapGesture: basicSingleTapGesture, doubleTapGesture} = useTapGestures({
+ const {singleTapGesture: baseSingleTapGesture, doubleTapGesture} = useTapGestures({
+ areTransformationsEnabled,
canvasSize,
contentSize,
minContentScale,
@@ -138,9 +108,10 @@ function MultiGestureCanvas({canvasSize, isActive = true, onScaleChanged: onScal
onScaleChanged,
onTap,
});
- const singleTapGesture = basicSingleTapGesture.requireExternalGestureToFail(doubleTapGesture, panGestureRef);
+ const singleTapGesture = baseSingleTapGesture.requireExternalGestureToFail(doubleTapGesture, panGestureRef);
const panGesture = usePanGesture({
+ areTransformationsEnabled,
canvasSize,
contentSize,
zoomScale,
@@ -149,13 +120,13 @@ function MultiGestureCanvas({canvasSize, isActive = true, onScaleChanged: onScal
offsetY,
panTranslateX,
panTranslateY,
- isSwipingInPager,
stopAnimation,
})
- .simultaneousWithExternalGesture(pagerRef, singleTapGesture, doubleTapGesture)
+ .simultaneousWithExternalGesture(singleTapGesture, doubleTapGesture)
.withRef(panGestureRef);
const pinchGesture = usePinchGesture({
+ areTransformationsEnabled,
canvasSize,
zoomScale,
zoomRange,
@@ -164,20 +135,10 @@ function MultiGestureCanvas({canvasSize, isActive = true, onScaleChanged: onScal
pinchTranslateX,
pinchTranslateY,
pinchScale,
- isSwipingInPager,
stopAnimation,
onScaleChanged,
}).simultaneousWithExternalGesture(panGesture, singleTapGesture, doubleTapGesture);
- // Enables/disables the pager scroll based on the zoom scale
- // When the content is zoomed in/out, the pager should be disabled
- useAnimatedReaction(
- () => zoomScale.value,
- () => {
- shouldPagerScroll.value = zoomScale.value === 1;
- },
- );
-
// Trigger a reset when the canvas gets inactive, but only if it was already mounted before
const mounted = useRef(false);
useEffect(() => {
diff --git a/src/components/MultiGestureCanvas/propTypes.js b/src/components/MultiGestureCanvas/propTypes.js
index f1961ec0e156..744dd07db0c8 100644
--- a/src/components/MultiGestureCanvas/propTypes.js
+++ b/src/components/MultiGestureCanvas/propTypes.js
@@ -29,6 +29,9 @@ const multiGestureCanvasPropTypes = {
*/
isActive: PropTypes.bool,
+ /** Whether pan, pinch and double tap transformations are enabled */
+ areTransformationsEnabled: PropTypes.bool,
+
/** Handles scale changed event */
onScaleChanged: PropTypes.func,
@@ -64,6 +67,7 @@ const multiGestureCanvasPropTypes = {
const multiGestureCanvasDefaultProps = {
isActive: true,
+ areTransformationsEnabled: true,
onScaleChanged: () => undefined,
contentSize: undefined,
contentScaling: undefined,
diff --git a/src/components/MultiGestureCanvas/usePanGesture.js b/src/components/MultiGestureCanvas/usePanGesture.js
index aec24cb2e99e..27067511a135 100644
--- a/src/components/MultiGestureCanvas/usePanGesture.js
+++ b/src/components/MultiGestureCanvas/usePanGesture.js
@@ -8,7 +8,7 @@ import * as MultiGestureCanvasUtils from './utils';
// https://docs.swmansion.com/react-native-reanimated/docs/animations/withDecay/
const PAN_DECAY_DECELARATION = 0.9915;
-const usePanGesture = ({canvasSize, contentSize, zoomScale, totalScale, offsetX, offsetY, panTranslateX, panTranslateY, isSwipingInPager, stopAnimation}) => {
+const usePanGesture = ({areTransformationsEnabled, canvasSize, contentSize, zoomScale, totalScale, offsetX, offsetY, panTranslateX, panTranslateY, stopAnimation}) => {
// The content size after fitting it to the canvas and zooming
const zoomedContentWidth = useDerivedValue(() => contentSize.width * totalScale.value, [contentSize.width]);
const zoomedContentHeight = useDerivedValue(() => contentSize.height * totalScale.value, [contentSize.height]);
@@ -107,8 +107,8 @@ const usePanGesture = ({canvasSize, contentSize, zoomScale, totalScale, offsetX,
.manualActivation(true)
.averageTouches(true)
.onTouchesMove((_evt, state) => {
- // We only allow panning when the content is zoomed in
- if (zoomScale.value <= 1 || isSwipingInPager.value) {
+ // We only allow panning when the content is zoomed in and the tranformations are enabled
+ if (zoomScale.value <= 1 || !areTransformationsEnabled) {
return;
}
@@ -137,8 +137,8 @@ const usePanGesture = ({canvasSize, contentSize, zoomScale, totalScale, offsetX,
panTranslateX.value = 0;
panTranslateY.value = 0;
- // If we are swiping (in the pager), we don't want to return to boundaries
- if (isSwipingInPager.value) {
+ // If we the MultiGestureCanvas is disabled, we don't want to return to boundaries
+ if (!areTransformationsEnabled) {
return;
}
diff --git a/src/components/MultiGestureCanvas/usePinchGesture.js b/src/components/MultiGestureCanvas/usePinchGesture.js
index 21c5e55e0117..63f023251aa4 100644
--- a/src/components/MultiGestureCanvas/usePinchGesture.js
+++ b/src/components/MultiGestureCanvas/usePinchGesture.js
@@ -5,6 +5,7 @@ import {runOnJS, useAnimatedReaction, useSharedValue, withSpring} from 'react-na
import * as MultiGestureCanvasUtils from './utils';
const usePinchGesture = ({
+ areTransformationsEnabled,
canvasSize,
zoomScale,
zoomRange,
@@ -13,7 +14,6 @@ const usePinchGesture = ({
pinchTranslateX: totalPinchTranslateX,
pinchTranslateY: totalPinchTranslateY,
pinchScale,
- isSwipingInPager,
stopAnimation,
onScaleChanged,
}) => {
@@ -71,8 +71,8 @@ const usePinchGesture = ({
const pinchGesture = Gesture.Pinch()
.enabled(pinchEnabled)
.onTouchesDown((_evt, state) => {
- // We don't want to activate pinch gesture when we are swiping in the pager
- if (!isSwipingInPager.value) {
+ // We don't want to activate pinch gesture when transformations are disabled
+ if (!areTransformationsEnabled) {
return;
}
diff --git a/src/components/MultiGestureCanvas/useTapGestures.js b/src/components/MultiGestureCanvas/useTapGestures.js
index eefe8c506b33..467b005fb1a2 100644
--- a/src/components/MultiGestureCanvas/useTapGestures.js
+++ b/src/components/MultiGestureCanvas/useTapGestures.js
@@ -6,7 +6,21 @@ import * as MultiGestureCanvasUtils from './utils';
const DOUBLE_TAP_SCALE = 3;
-const useTapGestures = ({canvasSize, contentSize, minContentScale, maxContentScale, offsetX, offsetY, pinchScale, zoomScale, reset, stopAnimation, onScaleChanged, onTap}) => {
+const useTapGestures = ({
+ areTransformationsEnabled,
+ canvasSize,
+ contentSize,
+ minContentScale,
+ maxContentScale,
+ offsetX,
+ offsetY,
+ pinchScale,
+ zoomScale,
+ reset,
+ stopAnimation,
+ onScaleChanged,
+ onTap,
+}) => {
// The content size after scaling it with minimum scale to fit the content into the canvas
const scaledContentWidth = useMemo(() => contentSize.width * minContentScale, [contentSize.width, minContentScale]);
const scaledContentHeight = useMemo(() => contentSize.height * minContentScale, [contentSize.height, minContentScale]);
@@ -88,6 +102,13 @@ const useTapGestures = ({canvasSize, contentSize, minContentScale, maxContentSca
);
const doubleTapGesture = Gesture.Tap()
+ .onTouchesDown((_evt, state) => {
+ if (areTransformationsEnabled) {
+ return;
+ }
+
+ state.fail();
+ })
.numberOfTaps(2)
.maxDelay(150)
.maxDistance(20)