react-native-gesture-image-viewer 2.4.0 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/lib/module/GestureViewer.js +96 -147
- package/lib/module/GestureViewer.js.map +1 -1
- package/lib/module/GestureViewerManager.js +49 -105
- package/lib/module/GestureViewerManager.js.map +1 -1
- package/lib/module/gestureViewerAnimation.js +18 -0
- package/lib/module/gestureViewerAnimation.js.map +1 -0
- package/lib/module/gestureViewerGestures.js +12 -0
- package/lib/module/gestureViewerGestures.js.map +1 -0
- package/lib/module/gestureViewerPaging.js +66 -0
- package/lib/module/gestureViewerPaging.js.map +1 -0
- package/lib/module/gestureViewerRenderWindow.js +29 -0
- package/lib/module/gestureViewerRenderWindow.js.map +1 -0
- package/lib/module/getWebContentProps.js +6 -0
- package/lib/module/getWebContentProps.js.map +1 -0
- package/lib/module/getWebContentProps.web.js +8 -0
- package/lib/module/getWebContentProps.web.js.map +1 -0
- package/lib/module/platformTapGestures.js +4 -0
- package/lib/module/platformTapGestures.js.map +1 -0
- package/lib/module/platformTapGestures.web.js +4 -0
- package/lib/module/platformTapGestures.web.js.map +1 -0
- package/lib/module/renderWindow.js +160 -0
- package/lib/module/renderWindow.js.map +1 -0
- package/lib/module/useGestureViewer.js +459 -211
- package/lib/module/useGestureViewer.js.map +1 -1
- package/lib/module/useGestureViewerController.js +3 -3
- package/lib/module/useGestureViewerController.js.map +1 -1
- package/lib/module/useGestureViewerManagerBridge.js +85 -0
- package/lib/module/useGestureViewerManagerBridge.js.map +1 -0
- package/lib/module/useGestureViewerPaging.js +168 -79
- package/lib/module/useGestureViewerPaging.js.map +1 -1
- package/lib/module/useWebClickHandler.js +7 -0
- package/lib/module/useWebClickHandler.js.map +1 -0
- package/lib/module/useWebClickHandler.web.js +85 -0
- package/lib/module/useWebClickHandler.web.js.map +1 -0
- package/lib/module/useWebSingleTapTimer.js +12 -0
- package/lib/module/useWebSingleTapTimer.js.map +1 -0
- package/lib/module/useWebSingleTapTimer.web.js +25 -0
- package/lib/module/useWebSingleTapTimer.web.js.map +1 -0
- package/lib/module/utils/index.js +0 -77
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/tapZoom.js +4 -3
- package/lib/module/utils/tapZoom.js.map +1 -1
- package/lib/typescript/src/GestureViewer.d.ts +1 -1
- package/lib/typescript/src/GestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/GestureViewerManager.d.ts +20 -20
- package/lib/typescript/src/GestureViewerManager.d.ts.map +1 -1
- package/lib/typescript/src/gestureViewerAnimation.d.ts +15 -0
- package/lib/typescript/src/gestureViewerAnimation.d.ts.map +1 -0
- package/lib/typescript/src/gestureViewerGestures.d.ts +10 -0
- package/lib/typescript/src/gestureViewerGestures.d.ts.map +1 -0
- package/lib/typescript/src/gestureViewerPaging.d.ts +13 -0
- package/lib/typescript/src/gestureViewerPaging.d.ts.map +1 -0
- package/lib/typescript/src/gestureViewerRenderWindow.d.ts +15 -0
- package/lib/typescript/src/gestureViewerRenderWindow.d.ts.map +1 -0
- package/lib/typescript/src/getWebContentProps.d.ts +3 -0
- package/lib/typescript/src/getWebContentProps.d.ts.map +1 -0
- package/lib/typescript/src/getWebContentProps.web.d.ts +5 -0
- package/lib/typescript/src/getWebContentProps.web.d.ts.map +1 -0
- package/lib/typescript/src/platformTapGestures.d.ts +2 -0
- package/lib/typescript/src/platformTapGestures.d.ts.map +1 -0
- package/lib/typescript/src/platformTapGestures.web.d.ts +2 -0
- package/lib/typescript/src/platformTapGestures.web.d.ts.map +1 -0
- package/lib/typescript/src/renderWindow.d.ts +44 -0
- package/lib/typescript/src/renderWindow.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +36 -53
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewer.d.ts +11 -10
- package/lib/typescript/src/useGestureViewer.d.ts.map +1 -1
- package/lib/typescript/src/useGestureViewerController.d.ts +1 -1
- package/lib/typescript/src/useGestureViewerManagerBridge.d.ts +28 -0
- package/lib/typescript/src/useGestureViewerManagerBridge.d.ts.map +1 -0
- package/lib/typescript/src/useGestureViewerPaging.d.ts +33 -2
- package/lib/typescript/src/useGestureViewerPaging.d.ts.map +1 -1
- package/lib/typescript/src/useWebClickHandler.d.ts +35 -0
- package/lib/typescript/src/useWebClickHandler.d.ts.map +1 -0
- package/lib/typescript/src/useWebClickHandler.web.d.ts +36 -0
- package/lib/typescript/src/useWebClickHandler.web.d.ts.map +1 -0
- package/lib/typescript/src/useWebSingleTapTimer.d.ts +6 -0
- package/lib/typescript/src/useWebSingleTapTimer.d.ts.map +1 -0
- package/lib/typescript/src/useWebSingleTapTimer.web.d.ts +6 -0
- package/lib/typescript/src/useWebSingleTapTimer.web.d.ts.map +1 -0
- package/lib/typescript/src/utils/index.d.ts +0 -20
- package/lib/typescript/src/utils/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/tapZoom.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/GestureViewer.tsx +113 -208
- package/src/GestureViewerManager.ts +77 -122
- package/src/gestureViewerAnimation.ts +18 -0
- package/src/gestureViewerGestures.ts +20 -0
- package/src/gestureViewerPaging.ts +116 -0
- package/src/gestureViewerRenderWindow.ts +56 -0
- package/src/getWebContentProps.ts +5 -0
- package/src/getWebContentProps.web.ts +5 -0
- package/src/platformTapGestures.ts +1 -0
- package/src/platformTapGestures.web.ts +1 -0
- package/src/renderWindow.ts +253 -0
- package/src/types.ts +34 -100
- package/src/useGestureViewer.ts +665 -275
- package/src/useGestureViewerController.ts +3 -3
- package/src/useGestureViewerManagerBridge.ts +118 -0
- package/src/useGestureViewerPaging.ts +306 -112
- package/src/useWebClickHandler.ts +44 -0
- package/src/useWebClickHandler.web.ts +146 -0
- package/src/useWebSingleTapTimer.ts +10 -0
- package/src/useWebSingleTapTimer.web.ts +30 -0
- package/src/utils/index.ts +0 -102
- package/src/utils/tapZoom.ts +4 -3
- package/lib/module/WebPagingFixStyle.js +0 -25
- package/lib/module/WebPagingFixStyle.js.map +0 -1
- package/lib/module/scheduleInitialScroll.js +0 -21
- package/lib/module/scheduleInitialScroll.js.map +0 -1
- package/lib/module/useGestureViewerPaging.types.js +0 -4
- package/lib/module/useGestureViewerPaging.types.js.map +0 -1
- package/lib/module/useGestureViewerPaging.web.js +0 -291
- package/lib/module/useGestureViewerPaging.web.js.map +0 -1
- package/lib/module/utils/FlashList.js +0 -9
- package/lib/module/utils/FlashList.js.map +0 -1
- package/lib/module/utils/webScroll.js +0 -70
- package/lib/module/utils/webScroll.js.map +0 -1
- package/lib/typescript/src/WebPagingFixStyle.d.ts +0 -6
- package/lib/typescript/src/WebPagingFixStyle.d.ts.map +0 -1
- package/lib/typescript/src/scheduleInitialScroll.d.ts +0 -3
- package/lib/typescript/src/scheduleInitialScroll.d.ts.map +0 -1
- package/lib/typescript/src/useGestureViewerPaging.types.d.ts +0 -42
- package/lib/typescript/src/useGestureViewerPaging.types.d.ts.map +0 -1
- package/lib/typescript/src/useGestureViewerPaging.web.d.ts +0 -3
- package/lib/typescript/src/useGestureViewerPaging.web.d.ts.map +0 -1
- package/lib/typescript/src/utils/FlashList.d.ts +0 -2
- package/lib/typescript/src/utils/FlashList.d.ts.map +0 -1
- package/lib/typescript/src/utils/webScroll.d.ts +0 -18
- package/lib/typescript/src/utils/webScroll.d.ts.map +0 -1
- package/src/WebPagingFixStyle.tsx +0 -25
- package/src/scheduleInitialScroll.ts +0 -36
- package/src/useGestureViewerPaging.types.ts +0 -42
- package/src/useGestureViewerPaging.web.ts +0 -453
- package/src/utils/FlashList.ts +0 -7
- package/src/utils/webScroll.ts +0 -96
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
-
import {
|
|
3
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { useWindowDimensions } from 'react-native';
|
|
5
5
|
import { Gesture } from 'react-native-gesture-handler';
|
|
6
|
-
import { Easing, interpolate, useAnimatedReaction, useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
|
|
6
|
+
import { Easing, cancelAnimation, interpolate, useAnimatedReaction, useAnimatedStyle, useSharedValue, withSpring, withTiming } from 'react-native-reanimated';
|
|
7
7
|
import { scheduleOnRN } from 'react-native-worklets';
|
|
8
|
+
import { PAGE_SPRING_CONFIG, SWIPE_THRESHOLD_RATIO, SWIPE_VELOCITY_THRESHOLD } from "./gestureViewerAnimation.js";
|
|
9
|
+
import { normalizeHorizontalSwipeThreshold } from "./gestureViewerPaging.js";
|
|
8
10
|
import { registry } from "./GestureViewerRegistry.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
11
|
+
import { resolveGestureViewerRenderWindow } from "./gestureViewerRenderWindow.js";
|
|
12
|
+
import { enableNativeTapGestures } from './platformTapGestures';
|
|
13
|
+
import { getLogicalIndex, getPageStride, getVirtualIndexForLogicalIndex, normalizePageSpacing, clampIndex, resolveNavigation, shouldRunNavigationDuringTransition } from "./renderWindow.js";
|
|
14
|
+
import { useGestureViewerManagerBridge } from "./useGestureViewerManagerBridge.js";
|
|
15
|
+
import { useGestureViewerPaging } from "./useGestureViewerPaging.js";
|
|
16
|
+
import { useWebClickHandler } from './useWebClickHandler';
|
|
17
|
+
import { useWebSingleTapTimer } from './useWebSingleTapTimer';
|
|
18
|
+
import { createBoundsConstraint } from "./utils/index.js";
|
|
12
19
|
import { getDismissDistance, shouldDismissByDirection } from "./utils/dismiss.js";
|
|
13
20
|
import { applyTapZoomAtPoint } from "./utils/tapZoom.js";
|
|
14
21
|
import { calculateFocalPointTranslation, shouldAcceptFocalPoint } from "./utils/zoom.js";
|
|
22
|
+
const NATIVE_TAP_MAX_DISTANCE = 10;
|
|
23
|
+
const isValidTriggerRect = rect => {
|
|
24
|
+
return !!rect && rect.width > 0 && rect.height > 0;
|
|
25
|
+
};
|
|
15
26
|
export const useGestureViewer = ({
|
|
16
27
|
data,
|
|
17
28
|
initialIndex = 0,
|
|
@@ -21,11 +32,12 @@ export const useGestureViewer = ({
|
|
|
21
32
|
dismiss,
|
|
22
33
|
enableDoubleTapZoom = true,
|
|
23
34
|
enablePinchZoom = true,
|
|
24
|
-
|
|
35
|
+
horizontalSwipe,
|
|
25
36
|
enablePanWhenZoomed = true,
|
|
26
37
|
enableLoop = false,
|
|
27
38
|
maxZoomScale = 2,
|
|
28
|
-
|
|
39
|
+
pageSpacing = 0,
|
|
40
|
+
windowSize = 3,
|
|
29
41
|
height: customHeight,
|
|
30
42
|
id = 'default',
|
|
31
43
|
onDismissStart,
|
|
@@ -39,43 +51,61 @@ export const useGestureViewer = ({
|
|
|
39
51
|
} = useWindowDimensions();
|
|
40
52
|
const width = customWidth || screenWidth;
|
|
41
53
|
const height = customHeight || screenHeight;
|
|
54
|
+
const dataLength = data?.length || 0;
|
|
55
|
+
const normalizedPageSpacing = normalizePageSpacing(pageSpacing);
|
|
56
|
+
const pageStride = getPageStride(width, normalizedPageSpacing);
|
|
57
|
+
const initialCurrentIndex = clampIndex(initialIndex, dataLength);
|
|
58
|
+
const horizontalSwipeEnabled = horizontalSwipe?.enabled ?? true;
|
|
59
|
+
const horizontalSwipeDistanceThresholdRatio = normalizeHorizontalSwipeThreshold(horizontalSwipe?.distanceThresholdRatio, SWIPE_THRESHOLD_RATIO);
|
|
60
|
+
const horizontalSwipeVelocityThreshold = normalizeHorizontalSwipeThreshold(horizontalSwipe?.velocityThreshold, SWIPE_VELOCITY_THRESHOLD);
|
|
42
61
|
const dismissGestureRef = useRef(undefined);
|
|
43
62
|
const [isZoomed, setIsZoomed] = useState(false);
|
|
44
63
|
const [isRotated, setIsRotated] = useState(false);
|
|
45
64
|
const [isPinching, setIsPinching] = useState(false);
|
|
46
65
|
const [shouldStartTriggerAnimation, setShouldStartTriggerAnimation] = useState(false);
|
|
47
|
-
const [
|
|
48
|
-
const [
|
|
49
|
-
const [activeTriggerNode, setActiveTriggerNode] = useState(
|
|
50
|
-
const
|
|
66
|
+
const [currentIndex, setCurrentIndex] = useState(initialCurrentIndex);
|
|
67
|
+
const [centerVirtualIndex, setCenterVirtualIndex] = useState(initialCurrentIndex);
|
|
68
|
+
const [activeTriggerNode, setActiveTriggerNode] = useState(() => registry.getActiveTriggerNode(id));
|
|
69
|
+
const [isTriggerOpening, setIsTriggerOpening] = useState(() => !!registry.getActiveTriggerNode(id));
|
|
51
70
|
const triggerRectRef = useRef(null);
|
|
52
|
-
const pendingIndexRef = useRef(
|
|
71
|
+
const pendingIndexRef = useRef(initialCurrentIndex);
|
|
72
|
+
const currentIndexRef = useRef(initialCurrentIndex);
|
|
73
|
+
const centerVirtualIndexRef = useRef(initialCurrentIndex);
|
|
74
|
+
const previousInitialIndexRef = useRef(initialIndex);
|
|
75
|
+
const hasResolvedInitialIndexRef = useRef(dataLength > 0);
|
|
53
76
|
const onAnimationCompleteRef = useRef(triggerAnimation?.onAnimationComplete);
|
|
54
77
|
const onSingleTapRef = useRef(onSingleTap);
|
|
55
78
|
const dataRef = useRef(data);
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
79
|
+
const dataLengthRef = useRef(dataLength);
|
|
80
|
+
const enableLoopRef = useRef(enableLoop);
|
|
81
|
+
const managerRef = useRef(null);
|
|
82
|
+
const isZoomedRef = useRef(isZoomed);
|
|
83
|
+
const isRotatedRef = useRef(isRotated);
|
|
84
|
+
const isPinchingRef = useRef(isPinching);
|
|
60
85
|
const initialTranslateY = useSharedValue(0);
|
|
61
86
|
const initialTranslateX = useSharedValue(0);
|
|
62
87
|
const startScale = useSharedValue(1);
|
|
63
88
|
const translateY = useSharedValue(0);
|
|
64
89
|
const translateX = useSharedValue(0);
|
|
65
90
|
const scale = useSharedValue(1);
|
|
66
|
-
const backdropOpacity = useSharedValue(1);
|
|
67
91
|
const rotation = useSharedValue(0);
|
|
68
92
|
const triggerScale = useSharedValue(1);
|
|
69
93
|
const triggerTranslateX = useSharedValue(0);
|
|
70
94
|
const triggerTranslateY = useSharedValue(0);
|
|
71
|
-
const triggerOpacity = useSharedValue(1);
|
|
95
|
+
const triggerOpacity = useSharedValue(activeTriggerNode ? 0 : 1);
|
|
96
|
+
const hasZoomChangeListeners = useSharedValue(false);
|
|
97
|
+
const hasRotationChangeListeners = useSharedValue(false);
|
|
72
98
|
const lastFocalX = useSharedValue(0);
|
|
73
99
|
const lastFocalY = useSharedValue(0);
|
|
74
100
|
const startFocalX = useSharedValue(0);
|
|
75
101
|
const startFocalY = useSharedValue(0);
|
|
76
102
|
const hasActiveFocal = useSharedValue(false);
|
|
77
|
-
const
|
|
78
|
-
const
|
|
103
|
+
const nativeInteractionHadMultipleTouches = useSharedValue(false);
|
|
104
|
+
const suppressNativeTap = useSharedValue(false);
|
|
105
|
+
const {
|
|
106
|
+
clearPendingWebSingleTap,
|
|
107
|
+
scheduleWebSingleTap
|
|
108
|
+
} = useWebSingleTapTimer();
|
|
79
109
|
const animationConfig = useMemo(() => ({
|
|
80
110
|
duration: triggerAnimation?.duration ?? 300,
|
|
81
111
|
easing: triggerAnimation?.easing ?? Easing.bezier(0.25, 0.1, 0.25, 1),
|
|
@@ -88,20 +118,22 @@ export const useGestureViewer = ({
|
|
|
88
118
|
resistance: dismiss?.resistance ?? 2,
|
|
89
119
|
threshold: dismiss?.threshold ?? 80
|
|
90
120
|
}), [dismiss?.direction, dismiss?.enabled, dismiss?.threshold, dismiss?.resistance, dismiss?.fadeBackdrop]);
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
121
|
+
const {
|
|
122
|
+
centerVirtualIndex: renderCenterVirtualIndex,
|
|
123
|
+
currentIndex: renderCurrentIndex,
|
|
124
|
+
slots: renderWindowSlots
|
|
125
|
+
} = resolveGestureViewerRenderWindow({
|
|
126
|
+
centerVirtualIndex,
|
|
127
|
+
currentIndex,
|
|
128
|
+
data,
|
|
129
|
+
enableLoop,
|
|
130
|
+
isTriggerOpening,
|
|
131
|
+
windowSize
|
|
132
|
+
});
|
|
97
133
|
const constrainTranslation = useMemo(() => createBoundsConstraint({
|
|
98
134
|
height,
|
|
99
135
|
width
|
|
100
136
|
}), [width, height]);
|
|
101
|
-
const scrollTo = useCallback((index, animated) => {
|
|
102
|
-
const scrollAction = createScrollAction(listRef.current, width + itemSpacing);
|
|
103
|
-
return scrollAction.scrollTo(index, animated);
|
|
104
|
-
}, [width, itemSpacing]);
|
|
105
137
|
const resetTransformState = useCallback(() => {
|
|
106
138
|
translateX.set(withTiming(0));
|
|
107
139
|
translateY.set(withTiming(0));
|
|
@@ -111,114 +143,241 @@ export const useGestureViewer = ({
|
|
|
111
143
|
scale.set(withTiming(1));
|
|
112
144
|
rotation.set(0);
|
|
113
145
|
}, [initialTranslateX, initialTranslateY, rotation, scale, startScale, translateX, translateY]);
|
|
114
|
-
const
|
|
115
|
-
|
|
146
|
+
const resetTransformStateImmediately = useCallback(() => {
|
|
147
|
+
cancelAnimation(translateX);
|
|
148
|
+
cancelAnimation(translateY);
|
|
149
|
+
cancelAnimation(initialTranslateX);
|
|
150
|
+
cancelAnimation(initialTranslateY);
|
|
151
|
+
cancelAnimation(startScale);
|
|
152
|
+
cancelAnimation(scale);
|
|
153
|
+
cancelAnimation(rotation);
|
|
154
|
+
translateX.set(0);
|
|
155
|
+
translateY.set(0);
|
|
156
|
+
initialTranslateX.set(0);
|
|
157
|
+
initialTranslateY.set(0);
|
|
158
|
+
startScale.set(1);
|
|
159
|
+
scale.set(1);
|
|
160
|
+
rotation.set(0);
|
|
161
|
+
}, [initialTranslateX, initialTranslateY, rotation, scale, startScale, translateX, translateY]);
|
|
162
|
+
const commitCurrentIndex = useCallback(nextIndex => {
|
|
163
|
+
pendingIndexRef.current = nextIndex;
|
|
164
|
+
currentIndexRef.current = nextIndex;
|
|
165
|
+
setCurrentIndex(nextIndex);
|
|
166
|
+
managerRef.current?.notifyStateChange();
|
|
167
|
+
}, []);
|
|
168
|
+
const commitVirtualIndexOnly = useCallback(nextVirtualIndex => {
|
|
169
|
+
const nextLogicalIndex = getLogicalIndex(nextVirtualIndex, dataLengthRef.current, enableLoopRef.current);
|
|
170
|
+
if (nextLogicalIndex === null) {
|
|
116
171
|
return;
|
|
117
172
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
173
|
+
centerVirtualIndexRef.current = nextVirtualIndex;
|
|
174
|
+
setCenterVirtualIndex(nextVirtualIndex);
|
|
175
|
+
commitCurrentIndex(nextLogicalIndex);
|
|
176
|
+
}, [commitCurrentIndex]);
|
|
177
|
+
const {
|
|
178
|
+
animateToVirtualPage,
|
|
179
|
+
horizontalPagingGesture,
|
|
180
|
+
isPageTransitioningRef,
|
|
181
|
+
pageTransitionLocked,
|
|
182
|
+
snapToVirtualPage,
|
|
183
|
+
visualPage
|
|
184
|
+
} = useGestureViewerPaging({
|
|
185
|
+
centerVirtualIndex,
|
|
186
|
+
clearPendingWebSingleTap,
|
|
187
|
+
commitVirtualIndexOnly,
|
|
188
|
+
currentIndex,
|
|
189
|
+
dataLength,
|
|
190
|
+
enableLoop,
|
|
191
|
+
horizontalSwipeDistanceThresholdRatio,
|
|
192
|
+
horizontalSwipeEnabled,
|
|
193
|
+
horizontalSwipeVelocityThreshold,
|
|
194
|
+
initialPage: initialCurrentIndex,
|
|
195
|
+
isPinching,
|
|
196
|
+
isRotated,
|
|
197
|
+
isTriggerOpening,
|
|
198
|
+
isZoomed,
|
|
199
|
+
pageStride,
|
|
200
|
+
suppressNativeTap,
|
|
201
|
+
width
|
|
202
|
+
});
|
|
203
|
+
const navigateToIndex = useCallback((targetIndex, options, preferredDirection) => {
|
|
204
|
+
const resolution = resolveNavigation({
|
|
205
|
+
currentIndex: currentIndexRef.current,
|
|
206
|
+
dataLength: dataLengthRef.current,
|
|
207
|
+
enableLoop: enableLoopRef.current,
|
|
208
|
+
preferredDirection,
|
|
209
|
+
targetIndex
|
|
210
|
+
});
|
|
211
|
+
if (resolution.kind === 'noop') {
|
|
122
212
|
return;
|
|
123
213
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
214
|
+
if (isPageTransitioningRef.current && !shouldRunNavigationDuringTransition(resolution, options)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const targetVirtualIndex = resolution.kind === 'step' ? centerVirtualIndexRef.current + resolution.direction : getVirtualIndexForLogicalIndex(resolution.targetIndex, centerVirtualIndexRef.current, dataLengthRef.current, enableLoopRef.current);
|
|
218
|
+
if (targetVirtualIndex === null) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (resolution.kind !== 'step' || options?.animated === false) {
|
|
222
|
+
resetTransformStateImmediately();
|
|
223
|
+
snapToVirtualPage(targetVirtualIndex);
|
|
127
224
|
return;
|
|
128
225
|
}
|
|
129
|
-
manager.setCurrentIndex(nextIndex);
|
|
130
|
-
manager.notifyStateChange();
|
|
131
226
|
resetTransformState();
|
|
132
|
-
|
|
227
|
+
animateToVirtualPage(targetVirtualIndex);
|
|
228
|
+
}, [animateToVirtualPage, isPageTransitioningRef, resetTransformStateImmediately, resetTransformState, snapToVirtualPage]);
|
|
229
|
+
const navigateByDirection = useCallback(direction => {
|
|
230
|
+
const currentDataLength = dataLengthRef.current;
|
|
231
|
+
if (currentDataLength <= 0) {
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const nextIndex = currentIndexRef.current + direction;
|
|
235
|
+
if (nextIndex >= 0 && nextIndex < currentDataLength) {
|
|
236
|
+
navigateToIndex(nextIndex, undefined, direction);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!enableLoopRef.current || currentDataLength <= 1) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
navigateToIndex(direction === 1 ? 0 : currentDataLength - 1, undefined, direction);
|
|
243
|
+
}, [navigateToIndex]);
|
|
244
|
+
const navigateToNext = useCallback(() => {
|
|
245
|
+
navigateByDirection(1);
|
|
246
|
+
}, [navigateByDirection]);
|
|
247
|
+
const navigateToPrevious = useCallback(() => {
|
|
248
|
+
navigateByDirection(-1);
|
|
249
|
+
}, [navigateByDirection]);
|
|
250
|
+
useGestureViewerManagerBridge({
|
|
251
|
+
currentIndexRef,
|
|
252
|
+
dataLengthRef,
|
|
253
|
+
goToIndex: navigateToIndex,
|
|
254
|
+
goToNext: navigateToNext,
|
|
255
|
+
goToPrevious: navigateToPrevious,
|
|
256
|
+
hasRotationChangeListeners,
|
|
257
|
+
hasZoomChangeListeners,
|
|
258
|
+
height,
|
|
259
|
+
id,
|
|
260
|
+
managerRef,
|
|
261
|
+
maxZoomScale,
|
|
262
|
+
rotation,
|
|
263
|
+
scale,
|
|
264
|
+
translateX,
|
|
265
|
+
translateY,
|
|
266
|
+
width
|
|
267
|
+
});
|
|
133
268
|
const emitZoomChange = useCallback((currentScale, prevScale) => {
|
|
134
269
|
managerRef.current?.emitZoomChange(currentScale, prevScale);
|
|
135
270
|
}, []);
|
|
136
271
|
const emitRotationChange = useCallback((currentRotation, prevRotation) => {
|
|
137
272
|
managerRef.current?.emitRotationChange(currentRotation, prevRotation);
|
|
138
273
|
}, []);
|
|
139
|
-
const
|
|
274
|
+
const finishTriggerOpening = useCallback(() => {
|
|
275
|
+
setIsTriggerOpening(false);
|
|
140
276
|
onAnimationCompleteRef.current?.();
|
|
141
277
|
}, []);
|
|
142
278
|
useAnimatedReaction(() => scale.get(), (currentScale, previousScale) => {
|
|
143
|
-
if (currentScale !== previousScale) {
|
|
279
|
+
if (currentScale !== previousScale && hasZoomChangeListeners.get()) {
|
|
144
280
|
scheduleOnRN(emitZoomChange, currentScale, previousScale);
|
|
145
281
|
}
|
|
146
|
-
|
|
282
|
+
const currentIsZoomed = currentScale > 1;
|
|
283
|
+
const previousIsZoomed = (previousScale ?? 1) > 1;
|
|
284
|
+
if (previousScale === null || currentIsZoomed !== previousIsZoomed) {
|
|
285
|
+
scheduleOnRN(setIsZoomed, currentIsZoomed);
|
|
286
|
+
}
|
|
147
287
|
});
|
|
148
288
|
useAnimatedReaction(() => rotation.get(), (currentRotation, previousRotation) => {
|
|
149
|
-
if (currentRotation !== previousRotation) {
|
|
289
|
+
if (currentRotation !== previousRotation && hasRotationChangeListeners.get()) {
|
|
150
290
|
scheduleOnRN(emitRotationChange, currentRotation, previousRotation);
|
|
151
291
|
}
|
|
152
|
-
|
|
292
|
+
const currentIsRotated = currentRotation % 360 !== 0;
|
|
293
|
+
const previousIsRotated = (previousRotation ?? 0) % 360 !== 0;
|
|
294
|
+
if (previousRotation === null || currentIsRotated !== previousIsRotated) {
|
|
295
|
+
scheduleOnRN(setIsRotated, currentIsRotated);
|
|
296
|
+
}
|
|
153
297
|
});
|
|
154
298
|
useEffect(() => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
setCurrentIndex(state.currentIndex);
|
|
161
|
-
});
|
|
299
|
+
return registry.subscribeToActiveTrigger(id, node => {
|
|
300
|
+
setActiveTriggerNode(node);
|
|
301
|
+
if (node) {
|
|
302
|
+
setIsTriggerOpening(true);
|
|
303
|
+
}
|
|
162
304
|
});
|
|
163
|
-
return () => {
|
|
164
|
-
unsubscribeFromRegistry();
|
|
165
|
-
unsubscribe?.();
|
|
166
|
-
};
|
|
167
305
|
}, [id]);
|
|
168
306
|
useEffect(() => {
|
|
169
|
-
|
|
170
|
-
}, [
|
|
307
|
+
dataRef.current = data;
|
|
308
|
+
}, [data]);
|
|
171
309
|
useEffect(() => {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
manager.setDataLength(dataLength);
|
|
177
|
-
manager.setEnableHorizontalSwipe(enableHorizontalSwipe);
|
|
178
|
-
manager.setCurrentIndex(initialIndex);
|
|
179
|
-
manager.setWidth(width + itemSpacing);
|
|
180
|
-
manager.setHeight(height);
|
|
181
|
-
manager.setZoomSharedValues(scale, translateX, translateY, maxZoomScale);
|
|
182
|
-
manager.setResetTransformCallback(resetTransformState);
|
|
183
|
-
manager.setRotation(rotation);
|
|
184
|
-
manager.setEnableLoop(enableLoop);
|
|
185
|
-
manager.notifyStateChange();
|
|
186
|
-
}, [dataLength, enableHorizontalSwipe, initialIndex, manager, width, itemSpacing, maxZoomScale, enableLoop, scale, height, resetTransformState, translateX, translateY, rotation]);
|
|
310
|
+
isZoomedRef.current = isZoomed;
|
|
311
|
+
}, [isZoomed]);
|
|
187
312
|
useEffect(() => {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
manager.setListRef(listRef.current);
|
|
192
|
-
}, [manager]);
|
|
313
|
+
isRotatedRef.current = isRotated;
|
|
314
|
+
}, [isRotated]);
|
|
193
315
|
useEffect(() => {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
scale.set(1);
|
|
200
|
-
backdropOpacity.set(1);
|
|
201
|
-
startScale.set(1);
|
|
202
|
-
rotation.set(0);
|
|
203
|
-
if (!hasValidInitialIndex || !hasDataLengthChanged && adjustedInitialIndex <= 0 || !listRef.current) {
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
return scheduleInitialScroll(() => {
|
|
207
|
-
scrollTo(adjustedInitialIndex, false);
|
|
208
|
-
});
|
|
209
|
-
}, [adjustedInitialIndex, dataLength, initialIndex, translateY, backdropOpacity, translateX, scale, startScale, rotation, scrollTo]);
|
|
316
|
+
isPinchingRef.current = isPinching;
|
|
317
|
+
}, [isPinching]);
|
|
318
|
+
useEffect(() => {
|
|
319
|
+
onSingleTapRef.current = onSingleTap;
|
|
320
|
+
}, [onSingleTap]);
|
|
210
321
|
useEffect(() => {
|
|
211
322
|
onAnimationCompleteRef.current = triggerAnimation?.onAnimationComplete;
|
|
212
323
|
}, [triggerAnimation?.onAnimationComplete]);
|
|
324
|
+
useLayoutEffect(() => {
|
|
325
|
+
const initialIndexChanged = previousInitialIndexRef.current !== initialIndex;
|
|
326
|
+
const shouldResolveInitialIndex = initialIndexChanged || !hasResolvedInitialIndexRef.current && dataLength > 0;
|
|
327
|
+
previousInitialIndexRef.current = initialIndex;
|
|
328
|
+
dataLengthRef.current = dataLength;
|
|
329
|
+
enableLoopRef.current = enableLoop;
|
|
330
|
+
hasResolvedInitialIndexRef.current = dataLength > 0;
|
|
331
|
+
const nextIndex = shouldResolveInitialIndex ? clampIndex(initialIndex, dataLength) : clampIndex(currentIndexRef.current, dataLength);
|
|
332
|
+
const nextVirtualIndex = getVirtualIndexForLogicalIndex(nextIndex, centerVirtualIndexRef.current, dataLength, enableLoop) ?? nextIndex;
|
|
333
|
+
const previousIndex = currentIndexRef.current;
|
|
334
|
+
const previousVirtualIndex = centerVirtualIndexRef.current;
|
|
335
|
+
const shouldSyncVirtualPage = isPageTransitioningRef.current || previousVirtualIndex !== nextVirtualIndex;
|
|
336
|
+
const shouldResetTransform = initialIndexChanged || previousIndex !== nextIndex || shouldSyncVirtualPage;
|
|
337
|
+
if (shouldSyncVirtualPage) {
|
|
338
|
+
snapToVirtualPage(nextVirtualIndex);
|
|
339
|
+
if (dataLength === 0) {
|
|
340
|
+
centerVirtualIndexRef.current = nextVirtualIndex;
|
|
341
|
+
setCenterVirtualIndex(nextVirtualIndex);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
const shouldCommitIndexOutsidePaging = !shouldSyncVirtualPage || dataLength === 0;
|
|
345
|
+
if (shouldCommitIndexOutsidePaging && previousIndex !== nextIndex) {
|
|
346
|
+
commitCurrentIndex(nextIndex);
|
|
347
|
+
}
|
|
348
|
+
if (shouldCommitIndexOutsidePaging && previousIndex === nextIndex) {
|
|
349
|
+
managerRef.current?.notifyStateChange();
|
|
350
|
+
}
|
|
351
|
+
if (shouldResetTransform) {
|
|
352
|
+
resetTransformState();
|
|
353
|
+
}
|
|
354
|
+
}, [commitCurrentIndex, dataLength, enableLoop, initialIndex, isPageTransitioningRef, resetTransformState, snapToVirtualPage]);
|
|
213
355
|
useEffect(() => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}, [
|
|
356
|
+
return () => {
|
|
357
|
+
triggerRectRef.current = null;
|
|
358
|
+
clearPendingWebSingleTap();
|
|
359
|
+
};
|
|
360
|
+
}, [clearPendingWebSingleTap]);
|
|
219
361
|
useEffect(() => {
|
|
220
|
-
|
|
221
|
-
|
|
362
|
+
if (!autoPlay || dataLength <= 1 || isTriggerOpening || isZoomed || isRotated || isPinching || !enableLoop && currentIndex >= dataLength - 1) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
const interval = Math.max(250, Math.floor(autoPlayInterval || 0));
|
|
366
|
+
if (!Number.isFinite(interval)) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const timer = setInterval(() => {
|
|
370
|
+
if (isPageTransitioningRef.current || isZoomedRef.current || isRotatedRef.current || isPinchingRef.current) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const nextIndex = currentIndexRef.current >= dataLengthRef.current - 1 ? enableLoopRef.current ? 0 : null : currentIndexRef.current + 1;
|
|
374
|
+
if (nextIndex === null) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
navigateToIndex(nextIndex);
|
|
378
|
+
}, interval);
|
|
379
|
+
return () => clearInterval(timer);
|
|
380
|
+
}, [autoPlay, autoPlayInterval, currentIndex, dataLength, enableLoop, isPinching, isRotated, isTriggerOpening, isZoomed, isPageTransitioningRef, navigateToIndex]);
|
|
222
381
|
useEffect(() => {
|
|
223
382
|
if (shouldStartTriggerAnimation && triggerRectRef.current) {
|
|
224
383
|
const startX = triggerRectRef.current.x + triggerRectRef.current.width / 2 - width / 2;
|
|
@@ -230,7 +389,7 @@ export const useGestureViewer = ({
|
|
|
230
389
|
triggerOpacity.set(0);
|
|
231
390
|
triggerScale.set(withTiming(1, animationConfig, finished => {
|
|
232
391
|
if (finished) {
|
|
233
|
-
scheduleOnRN(
|
|
392
|
+
scheduleOnRN(finishTriggerOpening);
|
|
234
393
|
}
|
|
235
394
|
}));
|
|
236
395
|
triggerTranslateX.set(withTiming(0, animationConfig));
|
|
@@ -242,9 +401,15 @@ export const useGestureViewer = ({
|
|
|
242
401
|
}));
|
|
243
402
|
setShouldStartTriggerAnimation(false);
|
|
244
403
|
}
|
|
245
|
-
}, [shouldStartTriggerAnimation, animationConfig, width, height, triggerOpacity, triggerScale, triggerTranslateX, triggerTranslateY,
|
|
404
|
+
}, [shouldStartTriggerAnimation, animationConfig, width, height, triggerOpacity, triggerScale, triggerTranslateX, triggerTranslateY, finishTriggerOpening]);
|
|
246
405
|
useEffect(() => {
|
|
247
|
-
if (!activeTriggerNode
|
|
406
|
+
if (!activeTriggerNode) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (typeof activeTriggerNode.measure !== 'function') {
|
|
410
|
+
setIsTriggerOpening(false);
|
|
411
|
+
triggerOpacity.set(1);
|
|
412
|
+
registry.clearActiveTriggerNode(id);
|
|
248
413
|
return;
|
|
249
414
|
}
|
|
250
415
|
activeTriggerNode.measure((_x, _y, measuredWidth, measuredHeight, pageX, pageY) => {
|
|
@@ -255,6 +420,8 @@ export const useGestureViewer = ({
|
|
|
255
420
|
y: pageY
|
|
256
421
|
};
|
|
257
422
|
if (!isValidTriggerRect(nextTriggerRect)) {
|
|
423
|
+
setIsTriggerOpening(false);
|
|
424
|
+
triggerOpacity.set(1);
|
|
258
425
|
registry.clearActiveTriggerNode(id);
|
|
259
426
|
return;
|
|
260
427
|
}
|
|
@@ -263,12 +430,7 @@ export const useGestureViewer = ({
|
|
|
263
430
|
setShouldStartTriggerAnimation(true);
|
|
264
431
|
registry.clearActiveTriggerNode(id);
|
|
265
432
|
});
|
|
266
|
-
}, [activeTriggerNode, id,
|
|
267
|
-
useEffect(() => {
|
|
268
|
-
return () => {
|
|
269
|
-
triggerRectRef.current = null;
|
|
270
|
-
};
|
|
271
|
-
}, []);
|
|
433
|
+
}, [activeTriggerNode, id, triggerOpacity]);
|
|
272
434
|
const animateDismissToRect = useCallback(rect => {
|
|
273
435
|
const endX = rect.x + rect.width / 2 - width / 2;
|
|
274
436
|
const endY = rect.y + rect.height / 2 - height / 2;
|
|
@@ -288,6 +450,9 @@ export const useGestureViewer = ({
|
|
|
288
450
|
}
|
|
289
451
|
}, [onDismiss]);
|
|
290
452
|
const handleDismiss = useCallback(() => {
|
|
453
|
+
if (isPageTransitioningRef.current) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
291
456
|
onDismissStart?.();
|
|
292
457
|
const dismissTargetIndex = pendingIndexRef.current;
|
|
293
458
|
const indexedTriggerNode = registry.getIndexedTriggerNode(id, dismissTargetIndex);
|
|
@@ -316,31 +481,150 @@ export const useGestureViewer = ({
|
|
|
316
481
|
return;
|
|
317
482
|
}
|
|
318
483
|
dismissWithoutTrigger();
|
|
319
|
-
}, [animateDismissToRect, dismissWithoutTrigger, id,
|
|
484
|
+
}, [animateDismissToRect, dismissWithoutTrigger, id, isPageTransitioningRef, onDismissStart]);
|
|
320
485
|
const dismissGesture = useMemo(() => {
|
|
321
|
-
const canDismiss = !isZoomed && dismissOptions.enabled;
|
|
322
|
-
|
|
486
|
+
const canDismiss = !isTriggerOpening && !isPinching && !isZoomed && dismissOptions.enabled;
|
|
487
|
+
const resetDismissTranslation = () => {
|
|
488
|
+
'worklet';
|
|
489
|
+
|
|
490
|
+
cancelAnimation(translateY);
|
|
491
|
+
translateY.set(0);
|
|
492
|
+
};
|
|
493
|
+
return Gesture.Pan().minDistance(10).maxPointers(1).averageTouches(true).activeCursor('grabbing').activeOffsetY([-10, 10]).failOffsetX([-10, 10]).withRef(dismissGestureRef).enabled(canDismiss).onTouchesDown((event, stateManager) => {
|
|
494
|
+
if (event.numberOfTouches === 1) {
|
|
495
|
+
nativeInteractionHadMultipleTouches.set(false);
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
if (event.numberOfTouches > 1) {
|
|
499
|
+
nativeInteractionHadMultipleTouches.set(true);
|
|
500
|
+
suppressNativeTap.set(true);
|
|
501
|
+
resetDismissTranslation();
|
|
502
|
+
stateManager.fail();
|
|
503
|
+
}
|
|
504
|
+
}).onStart(() => {
|
|
505
|
+
suppressNativeTap.set(true);
|
|
506
|
+
}).onUpdate(event => {
|
|
507
|
+
if (nativeInteractionHadMultipleTouches.get() || pageTransitionLocked.get()) {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
323
510
|
translateY.set(event.translationY / dismissOptions.resistance);
|
|
324
511
|
}).onEnd(event => {
|
|
512
|
+
if (nativeInteractionHadMultipleTouches.get()) {
|
|
513
|
+
resetDismissTranslation();
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
if (pageTransitionLocked.get()) {
|
|
517
|
+
resetDismissTranslation();
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
325
520
|
if (canDismiss && shouldDismissByDirection(event.translationY, dismissOptions.threshold, dismissOptions.direction)) {
|
|
326
521
|
scheduleOnRN(handleDismiss);
|
|
327
522
|
return;
|
|
328
523
|
}
|
|
329
|
-
translateY.set(withSpring(0,
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
stiffness: 600
|
|
335
|
-
}));
|
|
524
|
+
translateY.set(withSpring(0, PAGE_SPRING_CONFIG));
|
|
525
|
+
}).onFinalize((_event, success) => {
|
|
526
|
+
if ((!success || nativeInteractionHadMultipleTouches.get()) && scale.get() <= 1) {
|
|
527
|
+
resetDismissTranslation();
|
|
528
|
+
}
|
|
336
529
|
});
|
|
337
|
-
}, [
|
|
530
|
+
}, [dismissOptions, handleDismiss, isPinching, isTriggerOpening, isZoomed, nativeInteractionHadMultipleTouches, pageTransitionLocked, scale, suppressNativeTap, translateY]);
|
|
531
|
+
const getCurrentTapTarget = useCallback(() => {
|
|
532
|
+
const index = pendingIndexRef.current;
|
|
533
|
+
if (index < 0 || index >= dataRef.current.length || !(index in dataRef.current)) {
|
|
534
|
+
return null;
|
|
535
|
+
}
|
|
536
|
+
return {
|
|
537
|
+
index,
|
|
538
|
+
item: dataRef.current[index]
|
|
539
|
+
};
|
|
540
|
+
}, []);
|
|
541
|
+
const isWebInteractionLocked = useCallback(() => isPageTransitioningRef.current || pageTransitionLocked.get(), [isPageTransitioningRef, pageTransitionLocked]);
|
|
542
|
+
const emitSingleTap = useCallback((x, y, tapTarget) => {
|
|
543
|
+
if (isPageTransitioningRef.current) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
const target = tapTarget ?? getCurrentTapTarget();
|
|
547
|
+
if (!target) {
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
const {
|
|
551
|
+
index: targetIndex,
|
|
552
|
+
item: targetItem
|
|
553
|
+
} = target;
|
|
554
|
+
if (targetIndex < 0) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
managerRef.current?.emitTap({
|
|
558
|
+
kind: 'single',
|
|
559
|
+
x,
|
|
560
|
+
y,
|
|
561
|
+
index: targetIndex
|
|
562
|
+
});
|
|
563
|
+
onSingleTapRef.current?.({
|
|
564
|
+
x,
|
|
565
|
+
y,
|
|
566
|
+
index: targetIndex,
|
|
567
|
+
item: targetItem
|
|
568
|
+
});
|
|
569
|
+
}, [getCurrentTapTarget, isPageTransitioningRef]);
|
|
570
|
+
const singleTapGesture = useMemo(() => Gesture.Tap().enabled(enableNativeTapGestures).numberOfTaps(1).maxDistance(NATIVE_TAP_MAX_DISTANCE).onTouchesDown((event, stateManager) => {
|
|
571
|
+
if (event.numberOfTouches === 1) {
|
|
572
|
+
nativeInteractionHadMultipleTouches.set(false);
|
|
573
|
+
suppressNativeTap.set(false);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
nativeInteractionHadMultipleTouches.set(true);
|
|
577
|
+
suppressNativeTap.set(true);
|
|
578
|
+
stateManager.fail();
|
|
579
|
+
}).onEnd((event, success) => {
|
|
580
|
+
if (!success || pageTransitionLocked.get() || suppressNativeTap.get()) {
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
scheduleOnRN(emitSingleTap, event.x, event.y);
|
|
584
|
+
}), [emitSingleTap, nativeInteractionHadMultipleTouches, pageTransitionLocked, suppressNativeTap]);
|
|
585
|
+
const doubleTapGesture = useMemo(() => Gesture.Tap().enabled(enableDoubleTapZoom && enableNativeTapGestures).numberOfTaps(2).maxDistance(NATIVE_TAP_MAX_DISTANCE).onTouchesDown((event, stateManager) => {
|
|
586
|
+
if (event.numberOfTouches === 1) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
nativeInteractionHadMultipleTouches.set(true);
|
|
590
|
+
suppressNativeTap.set(true);
|
|
591
|
+
stateManager.fail();
|
|
592
|
+
}).onEnd(event => {
|
|
593
|
+
if (pageTransitionLocked.get() || suppressNativeTap.get()) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
applyTapZoomAtPoint({
|
|
597
|
+
x: event.x,
|
|
598
|
+
y: event.y,
|
|
599
|
+
width,
|
|
600
|
+
height,
|
|
601
|
+
maxZoomScale,
|
|
602
|
+
scale,
|
|
603
|
+
translateX,
|
|
604
|
+
translateY
|
|
605
|
+
});
|
|
606
|
+
}), [enableDoubleTapZoom, height, maxZoomScale, nativeInteractionHadMultipleTouches, pageTransitionLocked, scale, suppressNativeTap, translateX, translateY, width]);
|
|
607
|
+
const tapGesture = useMemo(() => Gesture.Exclusive(doubleTapGesture, singleTapGesture), [doubleTapGesture, singleTapGesture]);
|
|
338
608
|
const zoomPinchGesture = useMemo(() => Gesture.Pinch().enabled(enablePinchZoom).onTouchesDown(event => {
|
|
339
609
|
if (event.numberOfTouches === 2) {
|
|
610
|
+
nativeInteractionHadMultipleTouches.set(true);
|
|
611
|
+
suppressNativeTap.set(true);
|
|
340
612
|
scheduleOnRN(setIsPinching, true);
|
|
341
613
|
}
|
|
342
614
|
}).onStart(event => {
|
|
343
|
-
|
|
615
|
+
if (pageTransitionLocked.get()) {
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
const currentScale = scale.get();
|
|
619
|
+
nativeInteractionHadMultipleTouches.set(true);
|
|
620
|
+
suppressNativeTap.set(true);
|
|
621
|
+
startScale.set(currentScale);
|
|
622
|
+
if (currentScale <= 1) {
|
|
623
|
+
cancelAnimation(translateX);
|
|
624
|
+
cancelAnimation(translateY);
|
|
625
|
+
translateX.set(0);
|
|
626
|
+
translateY.set(0);
|
|
627
|
+
}
|
|
344
628
|
initialTranslateX.set(translateX.get());
|
|
345
629
|
initialTranslateY.set(translateY.get());
|
|
346
630
|
startFocalX.set(event.focalX);
|
|
@@ -349,6 +633,9 @@ export const useGestureViewer = ({
|
|
|
349
633
|
lastFocalY.set(event.focalY);
|
|
350
634
|
hasActiveFocal.set(false);
|
|
351
635
|
}).onUpdate(event => {
|
|
636
|
+
if (pageTransitionLocked.get()) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
352
639
|
const initialScale = startScale.get();
|
|
353
640
|
const newScale = initialScale * event.scale;
|
|
354
641
|
scale.set(newScale);
|
|
@@ -402,6 +689,9 @@ export const useGestureViewer = ({
|
|
|
402
689
|
translateX.set(constrainedTranslateX);
|
|
403
690
|
translateY.set(constrainedTranslateY);
|
|
404
691
|
}).onEnd(() => {
|
|
692
|
+
if (pageTransitionLocked.get()) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
405
695
|
const currentScale = scale.get();
|
|
406
696
|
if (currentScale > maxZoomScale) {
|
|
407
697
|
scale.set(withTiming(maxZoomScale, {
|
|
@@ -447,11 +737,29 @@ export const useGestureViewer = ({
|
|
|
447
737
|
}).onFinalize(() => {
|
|
448
738
|
hasActiveFocal.set(false);
|
|
449
739
|
scheduleOnRN(setIsPinching, false);
|
|
450
|
-
}), [scale, enablePinchZoom, maxZoomScale, translateX, translateY, startScale, initialTranslateX, initialTranslateY, width, height, constrainTranslation, lastFocalX, lastFocalY, startFocalX, startFocalY, hasActiveFocal]);
|
|
451
|
-
const zoomPanGesture = useMemo(() => Gesture.Pan().enabled(enablePanWhenZoomed && isZoomed).activeCursor('grabbing').averageTouches(true).
|
|
740
|
+
}), [scale, enablePinchZoom, maxZoomScale, translateX, translateY, startScale, initialTranslateX, initialTranslateY, width, height, constrainTranslation, lastFocalX, lastFocalY, startFocalX, startFocalY, hasActiveFocal, nativeInteractionHadMultipleTouches, pageTransitionLocked, suppressNativeTap]);
|
|
741
|
+
const zoomPanGesture = useMemo(() => Gesture.Pan().enabled(enablePanWhenZoomed && !isPinching && isZoomed).maxPointers(1).activeCursor('grabbing').averageTouches(true).onTouchesDown((event, stateManager) => {
|
|
742
|
+
if (event.numberOfTouches === 1) {
|
|
743
|
+
nativeInteractionHadMultipleTouches.set(false);
|
|
744
|
+
return;
|
|
745
|
+
}
|
|
746
|
+
if (event.numberOfTouches > 1) {
|
|
747
|
+
nativeInteractionHadMultipleTouches.set(true);
|
|
748
|
+
suppressNativeTap.set(true);
|
|
749
|
+
stateManager.fail();
|
|
750
|
+
}
|
|
751
|
+
}).onBegin(() => {
|
|
752
|
+
if (nativeInteractionHadMultipleTouches.get() || pageTransitionLocked.get()) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
452
755
|
initialTranslateX.set(translateX.get());
|
|
453
756
|
initialTranslateY.set(translateY.get());
|
|
757
|
+
}).onStart(() => {
|
|
758
|
+
suppressNativeTap.set(true);
|
|
454
759
|
}).onUpdate(event => {
|
|
760
|
+
if (nativeInteractionHadMultipleTouches.get() || pageTransitionLocked.get()) {
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
455
763
|
const currentScale = scale.get();
|
|
456
764
|
if (currentScale > 1) {
|
|
457
765
|
const newTranslateX = initialTranslateX.get() + event.translationX;
|
|
@@ -467,50 +775,22 @@ export const useGestureViewer = ({
|
|
|
467
775
|
translateX.set(constrainedTranslateX);
|
|
468
776
|
translateY.set(constrainedTranslateY);
|
|
469
777
|
}
|
|
470
|
-
}), [translateX, translateY, enablePanWhenZoomed, isZoomed, scale, initialTranslateX, initialTranslateY, constrainTranslation]);
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
onSingleTapRef.current?.({
|
|
488
|
-
x,
|
|
489
|
-
y,
|
|
490
|
-
index,
|
|
491
|
-
item
|
|
492
|
-
});
|
|
493
|
-
}, []);
|
|
494
|
-
const singleTapGesture = useMemo(() => Gesture.Tap().enabled(Platform.OS !== 'web').numberOfTaps(1).onEnd((event, success) => {
|
|
495
|
-
if (!success) {
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
scheduleOnRN(emitSingleTap, event.x, event.y);
|
|
499
|
-
}), [emitSingleTap]);
|
|
500
|
-
const doubleTapGesture = useMemo(() => Gesture.Tap().enabled(enableDoubleTapZoom && Platform.OS !== 'web').numberOfTaps(2).onEnd(event => {
|
|
501
|
-
applyTapZoomAtPoint({
|
|
502
|
-
x: event.x,
|
|
503
|
-
y: event.y,
|
|
504
|
-
width,
|
|
505
|
-
height,
|
|
506
|
-
maxZoomScale,
|
|
507
|
-
scale,
|
|
508
|
-
translateX,
|
|
509
|
-
translateY
|
|
510
|
-
});
|
|
511
|
-
}), [enableDoubleTapZoom, height, maxZoomScale, scale, translateX, translateY, width]);
|
|
512
|
-
const tapGesture = useMemo(() => Gesture.Exclusive(doubleTapGesture, singleTapGesture), [doubleTapGesture, singleTapGesture]);
|
|
513
|
-
const zoomGesture = useMemo(() => Gesture.Race(zoomPinchGesture, Gesture.Exclusive(zoomPanGesture, tapGesture)), [zoomPinchGesture, zoomPanGesture, tapGesture]);
|
|
778
|
+
}), [translateX, translateY, enablePanWhenZoomed, isPinching, isZoomed, scale, initialTranslateX, initialTranslateY, constrainTranslation, nativeInteractionHadMultipleTouches, pageTransitionLocked, suppressNativeTap]);
|
|
779
|
+
const zoomGesture = useMemo(() => Gesture.Exclusive(zoomPanGesture, tapGesture), [zoomPanGesture, tapGesture]);
|
|
780
|
+
const onWebClick = useWebClickHandler({
|
|
781
|
+
clearPendingWebSingleTap,
|
|
782
|
+
emitSingleTap,
|
|
783
|
+
enableDoubleTapZoom,
|
|
784
|
+
getCurrentTapTarget,
|
|
785
|
+
height,
|
|
786
|
+
maxZoomScale,
|
|
787
|
+
scale,
|
|
788
|
+
scheduleWebSingleTap,
|
|
789
|
+
isInteractionLocked: isWebInteractionLocked,
|
|
790
|
+
translateX,
|
|
791
|
+
translateY,
|
|
792
|
+
width
|
|
793
|
+
});
|
|
514
794
|
const animatedStyle = useAnimatedStyle(() => ({
|
|
515
795
|
opacity: triggerOpacity.get(),
|
|
516
796
|
transform: [{
|
|
@@ -542,56 +822,24 @@ export const useGestureViewer = ({
|
|
|
542
822
|
opacity: baseOpacity * dismissOpacity
|
|
543
823
|
};
|
|
544
824
|
}, [dismissOptions.direction, dismissOptions.fadeBackdrop]);
|
|
545
|
-
const nativeScrollGesture = useMemo(() => {
|
|
546
|
-
return Gesture.Native().requireExternalGestureToFail(dismissGestureRef);
|
|
547
|
-
}, []);
|
|
548
|
-
const {
|
|
549
|
-
activeListIndex,
|
|
550
|
-
onMomentumScrollEnd,
|
|
551
|
-
onScroll,
|
|
552
|
-
onScrollBeginDrag,
|
|
553
|
-
onWebClick
|
|
554
|
-
} = useGestureViewerPaging({
|
|
555
|
-
adjustedInitialIndex,
|
|
556
|
-
autoPlay,
|
|
557
|
-
autoPlayInterval,
|
|
558
|
-
currentIndex,
|
|
559
|
-
dataLength,
|
|
560
|
-
enableDoubleTapZoom,
|
|
561
|
-
enableHorizontalSwipe,
|
|
562
|
-
enableLoop,
|
|
563
|
-
height,
|
|
564
|
-
isRotated,
|
|
565
|
-
isZoomed,
|
|
566
|
-
itemSpacing,
|
|
567
|
-
manager,
|
|
568
|
-
maxZoomScale,
|
|
569
|
-
onSingleTap: emitSingleTap,
|
|
570
|
-
scale,
|
|
571
|
-
scrollTo,
|
|
572
|
-
syncCurrentIndex,
|
|
573
|
-
syncPendingIndex,
|
|
574
|
-
translateX,
|
|
575
|
-
translateY,
|
|
576
|
-
width
|
|
577
|
-
});
|
|
578
825
|
return {
|
|
579
|
-
activeListIndex,
|
|
580
826
|
animatedStyle,
|
|
581
827
|
backdropStyle,
|
|
828
|
+
centerVirtualIndex: renderCenterVirtualIndex,
|
|
829
|
+
currentIndex: renderCurrentIndex,
|
|
582
830
|
dataLength,
|
|
583
831
|
dismissGesture,
|
|
584
832
|
handleDismiss,
|
|
833
|
+
horizontalPagingGesture,
|
|
585
834
|
isPinching,
|
|
586
835
|
isRotated,
|
|
587
836
|
isZoomed,
|
|
588
|
-
listRef,
|
|
589
|
-
nativeScrollGesture,
|
|
590
837
|
onWebClick,
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
zoomGesture
|
|
838
|
+
pageStride,
|
|
839
|
+
renderWindowSlots,
|
|
840
|
+
visualPage,
|
|
841
|
+
zoomGesture,
|
|
842
|
+
zoomPinchGesture
|
|
595
843
|
};
|
|
596
844
|
};
|
|
597
845
|
//# sourceMappingURL=useGestureViewer.js.map
|