diff --git a/src/components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext.ts b/src/components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext.ts index 5afee6916524..3d4cb36dc0a9 100644 --- a/src/components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext.ts +++ b/src/components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext.ts @@ -47,6 +47,9 @@ type AttachmentCarouselPagerContextValue = { /** Callback for attachment errors */ onAttachmentError?: (source: AttachmentSource, state?: boolean) => void; + + /** In case we need a gesture that should work simultaneously with panning in MultiGestureCanvas */ + externalGestureHandler?: GestureType; }; const AttachmentCarouselPagerContext = createContext(null); diff --git a/src/components/Attachments/AttachmentCarousel/Pager/index.tsx b/src/components/Attachments/AttachmentCarousel/Pager/index.tsx index 9e98328eb1d1..bf0d37c058a7 100644 --- a/src/components/Attachments/AttachmentCarousel/Pager/index.tsx +++ b/src/components/Attachments/AttachmentCarousel/Pager/index.tsx @@ -2,9 +2,7 @@ import type {ForwardedRef, SetStateAction} from 'react'; import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import type {NativeSyntheticEvent} from 'react-native'; import {View} from 'react-native'; -import type {NativeViewGestureHandlerProps} from 'react-native-gesture-handler'; -import {createNativeWrapper} from 'react-native-gesture-handler'; -import type {PagerViewProps} from 'react-native-pager-view'; +import {Gesture, GestureDetector} from 'react-native-gesture-handler'; import PagerView from 'react-native-pager-view'; import Animated, {useAnimatedProps, useSharedValue} from 'react-native-reanimated'; import CarouselItem from '@components/Attachments/AttachmentCarousel/CarouselItem'; @@ -15,14 +13,7 @@ import shouldUseNewPager from '@libs/shouldUseNewPager'; import AttachmentCarouselPagerContext from './AttachmentCarouselPagerContext'; import usePageScrollHandler from './usePageScrollHandler'; -const WrappedPagerView = createNativeWrapper(PagerView) as React.ForwardRefExoticComponent< - PagerViewProps & - NativeViewGestureHandlerProps & - React.RefAttributes> & { - useNext: boolean; - } ->; -const AnimatedPagerView = Animated.createAnimatedComponent(WrappedPagerView); +const AnimatedPagerView = Animated.createAnimatedComponent(PagerView); type AttachmentCarouselPagerHandle = { setPage: (selectedPage: number) => void; @@ -93,6 +84,8 @@ function AttachmentCarouselPager( const extractItemKey = useCallback((item: Attachment, index: number) => `attachmentID-${item.attachmentID}-${index}`, []); + const nativeGestureHandler = Gesture.Native(); + const contextValue = useMemo( () => ({ pagerItems, @@ -104,8 +97,9 @@ function AttachmentCarouselPager( onSwipeDown: onClose, onScaleChanged: handleScaleChange, onAttachmentError, + externalGestureHandler: nativeGestureHandler, }), - [pagerItems, activePageIndex, isPagerScrolling, isScrollEnabled, handleTap, onClose, handleScaleChange, onAttachmentError], + [pagerItems, activePageIndex, isPagerScrolling, isScrollEnabled, handleTap, onClose, handleScaleChange, nativeGestureHandler, onAttachmentError], ); const animatedProps = useAnimatedProps(() => ({ @@ -141,19 +135,21 @@ function AttachmentCarouselPager( return ( - - {carouselItems} - + + + {carouselItems} + + ); } diff --git a/src/components/Lightbox/index.tsx b/src/components/Lightbox/index.tsx index ec0c6e5efcaa..e9ae48eaacda 100644 --- a/src/components/Lightbox/index.tsx +++ b/src/components/Lightbox/index.tsx @@ -12,7 +12,7 @@ import {getCanvasFitScale} from '@components/MultiGestureCanvas/utils'; import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as FileUtils from '@libs/fileDownload/FileUtils'; +import {isLocalFile} from '@libs/fileDownload/FileUtils'; import NUMBER_OF_CONCURRENT_LIGHTBOXES from './numberOfConcurrentLightboxes'; const cachedImageDimensions = new Map(); @@ -65,6 +65,7 @@ function Lightbox({isAuthTokenRequired = false, uri, onScaleChanged: onScaleChan onSwipeDown, pagerRef, isScrollEnabled, + externalGestureHandler, } = useMemo(() => { if (attachmentCarouselPagerContext === null) { return { @@ -78,6 +79,7 @@ function Lightbox({isAuthTokenRequired = false, uri, onScaleChanged: onScaleChan onScaleChanged: () => {}, onSwipeDown: () => {}, pagerRef: undefined, + externalGestureHandler: undefined, }; } @@ -201,7 +203,7 @@ function Lightbox({isAuthTokenRequired = false, uri, onScaleChanged: onScaleChan [onScaleChangedContext, onScaleChangedProp], ); - const isLocalFile = FileUtils.isLocalFile(uri); + const isALocalFile = isLocalFile(uri); return ( )} - {isLoading && !isLocalFile && } + {isLoading && !isALocalFile && } )} diff --git a/src/components/MultiGestureCanvas/index.tsx b/src/components/MultiGestureCanvas/index.tsx index 22a336c822e8..6638d0eb0555 100644 --- a/src/components/MultiGestureCanvas/index.tsx +++ b/src/components/MultiGestureCanvas/index.tsx @@ -1,8 +1,8 @@ import type {ForwardedRef} from 'react'; import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import {View} from 'react-native'; -import type {GestureType} from 'react-native-gesture-handler'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; +import type {GestureType} from 'react-native-gesture-handler'; import type {GestureRef} from 'react-native-gesture-handler/lib/typescript/handlers/gestures/gesture'; import type PagerView from 'react-native-pager-view'; import type {SharedValue} from 'react-native-reanimated'; @@ -57,6 +57,9 @@ type MultiGestureCanvasProps = ChildrenProps & { /** Handles swipe down event */ onSwipeDown?: OnSwipeDownCallback; + + /** We need to ensure that any native gesture handlers in this component tree is working simultaneously with panning and do not get blocked. */ + externalGestureHandler?: GestureType; }; const defaultContentSize = {width: 1, height: 1}; @@ -74,6 +77,7 @@ function MultiGestureCanvas({ onTap, onScaleChanged, onSwipeDown, + externalGestureHandler, }: MultiGestureCanvasProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); @@ -264,12 +268,14 @@ function MultiGestureCanvas({ const containerStyles = useMemo(() => [styles.flex1, StyleUtils.getMultiGestureCanvasContainerStyle(canvasSize.width)], [StyleUtils, canvasSize.width, styles.flex1]); + const panGestureWrapper = externalGestureHandler ? panGesture.simultaneousWithExternalGesture(externalGestureHandler) : panGesture; + return ( - + e.preventDefault()}