Skip to content

Commit

Permalink
fix: pager swiping
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Pader committed Jan 7, 2024
1 parent 934bfd3 commit 6be9adb
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 31 deletions.
30 changes: 11 additions & 19 deletions src/components/Attachments/AttachmentCarousel/Pager/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ 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, useAnimatedReaction, useEvent, useHandler, useSharedValue} from 'react-native-reanimated';
import Animated, {useEvent, useHandler, useSharedValue} from 'react-native-reanimated';
import _ from 'underscore';
import CarouselItem from '@components/Attachments/AttachmentCarousel/CarouselItem';
import refPropTypes from '@components/refPropTypes';
Expand Down Expand Up @@ -59,18 +59,10 @@ function AttachmentCarouselPager({items, activeSource, initialPage, scrollEnable
const styles = useThemeStyles();
const pagerRef = useRef(null);

const isPagerSwiping = useSharedValue(false);
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) => {
Expand All @@ -83,24 +75,24 @@ function AttachmentCarouselPager({items, activeSource, initialPage, scrollEnable
[],
);

const [isPagerSwipingState, setPagerSwipingState] = useState(false);
useAnimatedReaction(
() => [isPagerSwiping.value],
(isSwiping) => {
runOnJS(setPagerSwipingState)(isSwiping);
},
);
// 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 contextValue = useMemo(
() => ({
itemsMeta,
activePage: activePageState,
isPagerSwiping: isPagerSwipingState,
isPagerSwiping,
onTap,
onScaleChanged,
pagerRef,
}),
[activePageState, isPagerSwipingState, itemsMeta, onScaleChanged, onTap],
[activePageState, isPagerSwiping, itemsMeta, onScaleChanged, onTap],
);

useImperativeHandle(
Expand Down
2 changes: 1 addition & 1 deletion src/components/Lightbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,13 @@ function Lightbox({isAuthTokenRequired, source, onError, style, zoomRange}) {
<View style={[...StyleUtils.getFullscreenCenteredContentStyles(), StyleUtils.getLightboxVisibilityStyle(shouldHideLightbox)]}>
<MultiGestureCanvas
isActive={isActive}
areTransformationsEnabled={!isPagerSwiping}
onTap={onTap}
onScaleChanged={onScaleChanged}
canvasSize={containerSize}
contentSize={imageDimensions?.lightboxSize}
zoomRange={zoomRange}
pagerRef={pagerRef}
isPagerSwiping={isPagerSwiping}
>
<Image
source={{uri: source}}
Expand Down
8 changes: 4 additions & 4 deletions src/components/MultiGestureCanvas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function getDeepDefaultProps({contentSize: contentSizeProp = {}, zoomRange: zoom
return {contentSize, zoomRange};
}

function MultiGestureCanvas({canvasSize, isActive, areTransformationsEnabled, onScaleChanged, onTap, children, pagerRef, ...props}) {
function MultiGestureCanvas({canvasSize, isActive, onScaleChanged, onTap, children, isPagerSwiping, pagerRef, ...props}) {
const styles = useThemeStyles();
const StyleUtils = useStyleUtils();
const {contentSize, zoomRange} = getDeepDefaultProps(props);
Expand Down Expand Up @@ -94,7 +94,6 @@ function MultiGestureCanvas({canvasSize, isActive, areTransformationsEnabled, on
});

const {singleTapGesture: baseSingleTapGesture, doubleTapGesture} = useTapGestures({
areTransformationsEnabled,
canvasSize,
contentSize,
minContentScale,
Expand All @@ -108,11 +107,11 @@ function MultiGestureCanvas({canvasSize, isActive, areTransformationsEnabled, on
stopAnimation,
onScaleChanged,
onTap,
isPagerSwiping,
});
const singleTapGesture = baseSingleTapGesture.requireExternalGestureToFail(doubleTapGesture, panGestureRef);

const panGesture = usePanGesture({
areTransformationsEnabled,
canvasSize,
contentSize,
zoomScale,
Expand All @@ -122,12 +121,12 @@ function MultiGestureCanvas({canvasSize, isActive, areTransformationsEnabled, on
panTranslateX,
panTranslateY,
stopAnimation,
isPagerSwiping,
})
.simultaneousWithExternalGesture(pagerRef, singleTapGesture, doubleTapGesture)
.withRef(panGestureRef);

const pinchGesture = usePinchGesture({
areTransformationsEnabled,
canvasSize,
zoomScale,
zoomRange,
Expand All @@ -138,6 +137,7 @@ function MultiGestureCanvas({canvasSize, isActive, areTransformationsEnabled, on
pinchScale,
stopAnimation,
onScaleChanged,
isPagerSwiping,
}).simultaneousWithExternalGesture(panGesture, singleTapGesture, doubleTapGesture);

// Trigger a reset when the canvas gets inactive, but only if it was already mounted before
Expand Down
6 changes: 3 additions & 3 deletions src/components/MultiGestureCanvas/usePanGesture.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ({areTransformationsEnabled, canvasSize, contentSize, zoomScale, totalScale, offsetX, offsetY, panTranslateX, panTranslateY, stopAnimation}) => {
const usePanGesture = ({canvasSize, contentSize, zoomScale, totalScale, offsetX, offsetY, panTranslateX, panTranslateY, stopAnimation, isPagerSwiping}) => {
// 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]);
Expand Down Expand Up @@ -108,7 +108,7 @@ const usePanGesture = ({areTransformationsEnabled, canvasSize, contentSize, zoom
.averageTouches(true)
.onTouchesMove((_evt, state) => {
// We only allow panning when the content is zoomed in and the tranformations are enabled
if (zoomScale.value <= 1 || !areTransformationsEnabled) {
if (zoomScale.value <= 1 || isPagerSwiping.value) {
return;
}

Expand Down Expand Up @@ -138,7 +138,7 @@ const usePanGesture = ({areTransformationsEnabled, canvasSize, contentSize, zoom
panTranslateY.value = 0;

// If we the MultiGestureCanvas is disabled, we don't want to return to boundaries
if (!areTransformationsEnabled) {
if (isPagerSwiping.value) {
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/MultiGestureCanvas/usePinchGesture.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {runOnJS, useAnimatedReaction, useSharedValue, withSpring} from 'react-na
import * as MultiGestureCanvasUtils from './utils';

const usePinchGesture = ({
areTransformationsEnabled,
canvasSize,
zoomScale,
zoomRange,
Expand All @@ -16,6 +15,7 @@ const usePinchGesture = ({
pinchScale,
stopAnimation,
onScaleChanged,
isPagerSwiping,
}) => {
// The current pinch gesture event scale
const currentPinchScale = useSharedValue(1);
Expand Down Expand Up @@ -72,7 +72,7 @@ const usePinchGesture = ({
.enabled(pinchEnabled)
.onTouchesDown((_evt, state) => {
// We don't want to activate pinch gesture when transformations are disabled
if (!areTransformationsEnabled) {
if (!isPagerSwiping.value) {
return;
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/MultiGestureCanvas/useTapGestures.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import * as MultiGestureCanvasUtils from './utils';
const DOUBLE_TAP_SCALE = 3;

const useTapGestures = ({
areTransformationsEnabled,
canvasSize,
contentSize,
minContentScale,
Expand All @@ -20,6 +19,7 @@ const useTapGestures = ({
stopAnimation,
onScaleChanged,
onTap,
isPagerSwiping,
}) => {
// 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]);
Expand Down Expand Up @@ -105,7 +105,7 @@ const useTapGestures = ({

const doubleTapGesture = Gesture.Tap()
.onTouchesDown((_evt, state) => {
if (areTransformationsEnabled) {
if (!isPagerSwiping.value) {
return;
}

Expand Down

0 comments on commit 6be9adb

Please sign in to comment.