stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
352 lines (349 loc) • 19.4 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useImageGalleryGestures = exports.clamp = exports.IsSwiping = exports.HasPinched = void 0;
var _react = require("react");
var _reactNative = require("react-native");
var _reactNativeGestureHandler = require("react-native-gesture-handler");
var _reactNativeReanimated = require("react-native-reanimated");
var _ImageGalleryContext = require("../../../contexts/imageGalleryContext/ImageGalleryContext");
var _OverlayContext = require("../../../contexts/overlayContext/OverlayContext");
var _native = require("../../../native");
var HasPinched = exports.HasPinched = function (HasPinched) {
HasPinched[HasPinched["FALSE"] = 0] = "FALSE";
HasPinched[HasPinched["TRUE"] = 1] = "TRUE";
return HasPinched;
}({});
var IsSwiping = exports.IsSwiping = function (IsSwiping) {
IsSwiping[IsSwiping["UNDETERMINED"] = 0] = "UNDETERMINED";
IsSwiping[IsSwiping["TRUE"] = 1] = "TRUE";
IsSwiping[IsSwiping["FALSE"] = 2] = "FALSE";
return IsSwiping;
}({});
var MARGIN = 32;
var useImageGalleryGestures = ({
currentImageHeight,
halfScreenHeight,
halfScreenWidth,
headerFooterVisible,
offsetScale,
overlayOpacity,
scale,
screenHeight,
screenWidth,
translateX,
translateY,
translationX
}) => {
var _useImageGalleryConte = (0, _ImageGalleryContext.useImageGalleryContext)(),
imageGalleryStateStore = _useImageGalleryConte.imageGalleryStateStore;
var currentIndexShared = imageGalleryStateStore.currentIndexShared;
var doubleTapRef = (0, _react.useRef)(undefined);
var panRef = (0, _react.useRef)(undefined);
var pinchRef = (0, _react.useRef)(undefined);
var singleTapRef = (0, _react.useRef)(undefined);
var _useOverlayContext = (0, _OverlayContext.useOverlayContext)(),
overlay = _useOverlayContext.overlay,
setOverlay = _useOverlayContext.setOverlay;
var isAndroid = _reactNative.Platform.OS === 'android';
var hasHitBottomScale = (0, _reactNativeReanimated.useSharedValue)(1);
var hasHitTopScale = (0, _reactNativeReanimated.useSharedValue)(0);
var originX = (0, _reactNativeReanimated.useSharedValue)(0);
var originY = (0, _reactNativeReanimated.useSharedValue)(0);
var oldFocalX = (0, _reactNativeReanimated.useSharedValue)(0);
var oldFocalY = (0, _reactNativeReanimated.useSharedValue)(0);
var focalX = (0, _reactNativeReanimated.useSharedValue)(0);
var focalY = (0, _reactNativeReanimated.useSharedValue)(0);
var offsetX = (0, _reactNativeReanimated.useSharedValue)(0);
var offsetY = (0, _reactNativeReanimated.useSharedValue)(0);
var focalOffsetX = (0, _reactNativeReanimated.useSharedValue)(0);
var focalOffsetY = (0, _reactNativeReanimated.useSharedValue)(0);
var adjustedFocalX = (0, _reactNativeReanimated.useSharedValue)(0);
var adjustedFocalY = (0, _reactNativeReanimated.useSharedValue)(0);
var tapX = (0, _reactNativeReanimated.useSharedValue)(0);
var tapY = (0, _reactNativeReanimated.useSharedValue)(0);
var numberOfPinchFingers = (0, _reactNativeReanimated.useSharedValue)(0);
var isSwiping = (0, _reactNativeReanimated.useSharedValue)(0);
var isPinch = (0, _reactNativeReanimated.useSharedValue)(false);
var hasPinched = (0, _reactNativeReanimated.useSharedValue)(0);
var resetTouchValues = () => {
'worklet';
focalX.value = 0;
focalY.value = 0;
oldFocalX.value = 0;
oldFocalY.value = 0;
originX.value = 0;
originY.value = 0;
focalOffsetX.value = 0;
focalOffsetY.value = 0;
numberOfPinchFingers.value = 0;
isPinch.value = false;
isSwiping.value = IsSwiping.UNDETERMINED;
};
var resetMovementValues = () => {
'worklet';
translateX.value = 0;
translateY.value = 0;
scale.value = 1;
offsetScale.value = 1;
};
var assetsLength = imageGalleryStateStore.assets.length;
var clearImageGallery = () => {
(0, _reactNativeReanimated.runOnJS)(setOverlay)('none');
};
var moveToNextImage = () => {
var currentIndex = imageGalleryStateStore.state.getLatestValue().currentIndex;
imageGalleryStateStore.currentIndex = currentIndex + 1;
};
var moveToPreviousImage = () => {
var currentIndex = imageGalleryStateStore.state.getLatestValue().currentIndex;
imageGalleryStateStore.currentIndex = currentIndex - 1;
};
var pan = _reactNativeGestureHandler.Gesture.Pan().enabled(overlay === 'gallery').maxPointers(isAndroid ? 0 : 1).minDistance(10).onStart(() => {
if (!isPinch.value) {
(0, _reactNativeReanimated.cancelAnimation)(translateX);
(0, _reactNativeReanimated.cancelAnimation)(translateY);
(0, _reactNativeReanimated.cancelAnimation)(scale);
offsetX.value = translateX.value;
offsetY.value = translateY.value;
}
hasPinched.value = HasPinched.FALSE;
}).onChange(event => {
if (event.numberOfPointers === 1 && !isPinch.value) {
if (isAndroid && hasPinched.value === HasPinched.TRUE) {
hasPinched.value = HasPinched.FALSE;
isSwiping.value = IsSwiping.FALSE;
offsetX.value = translateX.value + event.translationX;
offsetY.value = translateY.value - event.translationY;
}
if (isSwiping.value === IsSwiping.UNDETERMINED) {
var maxXYRatio = 0.25;
if (Math.abs(event.translationX / event.translationY) > maxXYRatio && (Math.abs(-halfScreenWidth * (scale.value - 1) - offsetX.value) < 3 || Math.abs(halfScreenWidth * (scale.value - 1) - offsetX.value) < 3)) {
isSwiping.value = IsSwiping.TRUE;
}
if (Math.abs(event.translationY) > 25) {
isSwiping.value = IsSwiping.FALSE;
}
}
var localEvtScale = scale.value / offsetScale.value;
translateX.value = scale.value !== offsetScale.value ? offsetX.value * localEvtScale + event.translationX : offsetX.value + event.translationX;
translateY.value = isSwiping.value !== IsSwiping.TRUE ? scale.value !== offsetScale.value ? offsetY.value * localEvtScale + event.translationY : offsetY.value + event.translationY : translateY.value;
var imageHeight = currentImageHeight.value;
scale.value = imageHeight * offsetScale.value < screenHeight && translateY.value > 0 ? offsetScale.value * (1 - 1 / 3 * (translateY.value / screenHeight)) : imageHeight * offsetScale.value > screenHeight && translateY.value > imageHeight / 2 * offsetScale.value - halfScreenHeight ? offsetScale.value * (1 - 1 / 3 * ((translateY.value - (imageHeight / 2 * offsetScale.value - halfScreenHeight)) / screenHeight)) : scale.value;
overlayOpacity.value = localEvtScale;
}
}).onEnd(event => {
if (!isPinch.value && event.numberOfPointers < 2) {
var finalXPosition = event.translationX - event.velocityX * 0.3;
var finalYPosition = event.translationY + event.velocityY * 0.1;
var currentIndex = currentIndexShared.value;
if (currentIndex < assetsLength - 1 && Math.abs(halfScreenWidth * (scale.value - 1) + offsetX.value) < 3 && translateX.value < 0 && finalXPosition > halfScreenWidth && isSwiping.value === IsSwiping.TRUE) {
(0, _reactNativeReanimated.cancelAnimation)(translationX);
translationX.value = (0, _reactNativeReanimated.withTiming)(-(screenWidth + MARGIN) * (currentIndex + 1), {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
}, () => {
resetMovementValues();
(0, _reactNativeReanimated.runOnJS)(moveToNextImage)();
});
} else if (currentIndex > 0 && Math.abs(-halfScreenWidth * (scale.value - 1) + offsetX.value) < 3 && translateX.value > 0 && finalXPosition < -halfScreenWidth && isSwiping.value === IsSwiping.TRUE) {
(0, _reactNativeReanimated.cancelAnimation)(translationX);
translationX.value = (0, _reactNativeReanimated.withTiming)(-(screenWidth + MARGIN) * (currentIndex - 1), {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
}, () => {
resetMovementValues();
(0, _reactNativeReanimated.runOnJS)(moveToPreviousImage)();
});
}
translateX.value = scale.value < 1 ? (0, _reactNativeReanimated.withTiming)(0) : translateX.value > halfScreenWidth * (scale.value - 1) ? (0, _reactNativeReanimated.withTiming)(halfScreenWidth * (scale.value - 1), {
duration: 200
}) : translateX.value < -halfScreenWidth * (scale.value - 1) ? (0, _reactNativeReanimated.withTiming)(-halfScreenWidth * (scale.value - 1), {
duration: 200
}) : (0, _reactNativeReanimated.withDecay)({
clamp: [-halfScreenWidth * (scale.value - 1), halfScreenWidth * (scale.value - 1)],
deceleration: 0.99,
velocity: -event.velocityX
});
var imageHeight = currentImageHeight.value;
translateY.value = imageHeight * scale.value < screenHeight ? (0, _reactNativeReanimated.withTiming)(0, {
reduceMotion: _reactNativeReanimated.ReduceMotion.Never
}) : translateY.value > imageHeight / 2 * scale.value - halfScreenHeight ? (0, _reactNativeReanimated.withTiming)(imageHeight / 2 * scale.value - halfScreenHeight, {
reduceMotion: _reactNativeReanimated.ReduceMotion.Never
}) : translateY.value < -imageHeight / 2 * scale.value + halfScreenHeight ? (0, _reactNativeReanimated.withTiming)(-imageHeight / 2 * scale.value + halfScreenHeight) : (0, _reactNativeReanimated.withDecay)({
clamp: [-imageHeight / 2 * scale.value + halfScreenHeight, imageHeight / 2 * scale.value - halfScreenHeight],
deceleration: 0.99,
velocity: event.velocityY
});
resetTouchValues();
scale.value = scale.value !== offsetScale.value ? (0, _reactNativeReanimated.withTiming)(offsetScale.value) : offsetScale.value;
if (finalYPosition > halfScreenHeight && offsetY.value + 8 >= imageHeight / 2 * scale.value - halfScreenHeight && isSwiping.value !== IsSwiping.TRUE && translateY.value !== 0 && !(Math.abs(halfScreenWidth * (scale.value - 1) + offsetX.value) < 3 && translateX.value < 0 && finalXPosition < -halfScreenWidth) && !(Math.abs(-halfScreenWidth * (scale.value - 1) + offsetX.value) < 3 && translateX.value > 0 && finalXPosition > halfScreenWidth)) {
(0, _reactNativeReanimated.cancelAnimation)(translateX);
(0, _reactNativeReanimated.cancelAnimation)(translateY);
(0, _reactNativeReanimated.cancelAnimation)(scale);
overlayOpacity.value = (0, _reactNativeReanimated.withTiming)(0, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
}, () => {
(0, _reactNativeReanimated.runOnJS)(clearImageGallery)();
});
scale.value = (0, _reactNativeReanimated.withTiming)(0.6, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
translateY.value = event.velocityY > 1000 ? (0, _reactNativeReanimated.withDecay)({
velocity: event.velocityY
}) : (0, _reactNativeReanimated.withTiming)(halfScreenHeight + imageHeight / 2 * scale.value, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
translateX.value = (0, _reactNativeReanimated.withDecay)({
velocity: -event.velocityX
});
}
}
}).simultaneousWithExternalGesture(pinchRef).withRef(panRef);
var triggerHaptic = _native.NativeHandlers.triggerHaptic;
var pinch = _reactNativeGestureHandler.Gesture.Pinch().onStart(event => {
if (!isAndroid) {
(0, _reactNativeReanimated.cancelAnimation)(translateX);
(0, _reactNativeReanimated.cancelAnimation)(translateY);
(0, _reactNativeReanimated.cancelAnimation)(scale);
isPinch.value = true;
isSwiping.value = IsSwiping.UNDETERMINED;
numberOfPinchFingers.value = event.numberOfPointers;
offsetX.value = translateX.value;
offsetY.value = translateY.value;
adjustedFocalX.value = event.focalX - (halfScreenWidth - offsetX.value);
adjustedFocalY.value = event.focalY - (halfScreenHeight + offsetY.value);
originX.value = adjustedFocalX.value;
originY.value = adjustedFocalY.value;
offsetScale.value = scale.value;
}
hasPinched.value = HasPinched.FALSE;
}).onChange(event => {
if (!isPinch.value && isAndroid) {
hasPinched.value = HasPinched.TRUE;
(0, _reactNativeReanimated.cancelAnimation)(translateX);
(0, _reactNativeReanimated.cancelAnimation)(translateY);
(0, _reactNativeReanimated.cancelAnimation)(scale);
isSwiping.value = IsSwiping.UNDETERMINED;
numberOfPinchFingers.value = event.numberOfPointers;
offsetX.value = translateX.value;
offsetY.value = translateY.value;
adjustedFocalX.value = event.focalX - (halfScreenWidth - offsetX.value);
adjustedFocalY.value = event.focalY - (halfScreenHeight + offsetY.value);
originX.value = adjustedFocalX.value;
originY.value = adjustedFocalY.value;
offsetScale.value = scale.value;
}
isPinch.value = true;
scale.value = clamp(offsetScale.value * event.scale, 1, 8);
var localEvtScale = scale.value / offsetScale.value;
if (scale.value !== 8 && scale.value !== 1) {
hasHitTopScale.value = 0;
hasHitBottomScale.value = 0;
} else if (scale.value === 8 && hasHitTopScale.value === 0) {
hasHitTopScale.value = 1;
(0, _reactNativeReanimated.runOnJS)(triggerHaptic)('impactLight');
} else if (scale.value === 1 && hasHitBottomScale.value === 0) {
hasHitBottomScale.value = 1;
(0, _reactNativeReanimated.runOnJS)(triggerHaptic)('impactLight');
}
adjustedFocalX.value = event.focalX - (halfScreenWidth - offsetX.value);
adjustedFocalY.value = event.focalY - (halfScreenHeight + offsetY.value);
if (numberOfPinchFingers.value !== event.numberOfPointers) {
numberOfPinchFingers.value = event.numberOfPointers;
if (event.numberOfPointers === 1) {
focalOffsetX.value = oldFocalX.value - adjustedFocalX.value;
focalOffsetY.value = oldFocalY.value - adjustedFocalY.value;
} else if (numberOfPinchFingers.value > 1) {
originX.value = originX.value - (oldFocalX.value / localEvtScale - adjustedFocalX.value / localEvtScale);
originY.value = originY.value - (oldFocalY.value / localEvtScale - adjustedFocalY.value / localEvtScale);
}
}
if (numberOfPinchFingers.value === 1) {
oldFocalX.value = adjustedFocalX.value + focalOffsetX.value;
oldFocalY.value = adjustedFocalY.value + focalOffsetY.value;
translateX.value = offsetX.value - oldFocalX.value + localEvtScale * originX.value;
translateY.value = offsetY.value + oldFocalY.value - localEvtScale * originY.value;
} else if (numberOfPinchFingers.value > 1) {
oldFocalX.value = adjustedFocalX.value;
oldFocalY.value = adjustedFocalY.value;
translateX.value = offsetX.value - adjustedFocalX.value + localEvtScale * originX.value;
translateY.value = offsetY.value + adjustedFocalY.value - localEvtScale * originY.value;
}
}).onEnd(() => {
if (isPinch.value) {
translateX.value = scale.value < 1 ? (0, _reactNativeReanimated.withTiming)(0) : translateX.value > halfScreenWidth * (scale.value - 1) ? (0, _reactNativeReanimated.withTiming)(halfScreenWidth * (scale.value - 1)) : translateX.value < -halfScreenWidth * (scale.value - 1) ? (0, _reactNativeReanimated.withTiming)(-halfScreenWidth * (scale.value - 1)) : translateX.value;
var imageHeight = currentImageHeight.value;
translateY.value = imageHeight * scale.value < screenHeight ? (0, _reactNativeReanimated.withTiming)(0) : translateY.value > imageHeight / 2 * scale.value - screenHeight / 2 ? (0, _reactNativeReanimated.withTiming)(imageHeight / 2 * scale.value - screenHeight / 2) : translateY.value < -imageHeight / 2 * scale.value + screenHeight / 2 ? (0, _reactNativeReanimated.withTiming)(-imageHeight / 2 * scale.value + screenHeight / 2) : translateY.value;
offsetScale.value = scale.value < 1 ? 1 : scale.value;
scale.value = scale.value < 1 ? (0, _reactNativeReanimated.withTiming)(1) : scale.value;
resetTouchValues();
}
}).withRef(pinchRef).simultaneousWithExternalGesture(panRef);
var singleTap = _reactNativeGestureHandler.Gesture.Tap().minPointers(1).numberOfTaps(1).onEnd(() => {
(0, _reactNativeReanimated.cancelAnimation)(headerFooterVisible);
headerFooterVisible.value = headerFooterVisible.value > 0 ? (0, _reactNativeReanimated.withTiming)(0) : (0, _reactNativeReanimated.withTiming)(1);
}).requireExternalGestureToFail(panRef, pinchRef, doubleTapRef).withRef(singleTapRef);
var doubleTap = _reactNativeGestureHandler.Gesture.Tap().maxDeltaX(8).maxDeltaY(8).maxDistance(8).minPointers(1).numberOfTaps(2).onStart(event => {
tapX.value = event.absoluteX;
tapY.value = event.absoluteY;
}).onEnd(event => {
if (Math.abs(tapX.value - event.absoluteX) < 64 && Math.abs(tapY.value - event.absoluteY) < 64) {
if (offsetScale.value === 1 && offsetX.value === 0 && offsetY.value === 0) {
offsetScale.value = 2;
scale.value = (0, _reactNativeReanimated.withTiming)(2, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
translateX.value = (0, _reactNativeReanimated.withTiming)(event.absoluteX - halfScreenWidth, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
var imageHeight = currentImageHeight.value;
if (imageHeight * 2 > screenHeight) {
var translateYTopBottom = event.absoluteY > halfScreenHeight ? -(imageHeight * 2 - screenHeight) / 2 : (imageHeight * 2 - screenHeight) / 2;
translateY.value = (0, _reactNativeReanimated.withTiming)(translateYTopBottom, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
}
} else {
offsetScale.value = 1;
scale.value = (0, _reactNativeReanimated.withTiming)(1, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
offsetX.value = 0;
offsetY.value = 0;
translateX.value = (0, _reactNativeReanimated.withTiming)(0, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
translateY.value = (0, _reactNativeReanimated.withTiming)(0, {
duration: 200,
easing: _reactNativeReanimated.Easing.out(_reactNativeReanimated.Easing.ease)
});
if (headerFooterVisible.value !== 0) {
(0, _reactNativeReanimated.cancelAnimation)(headerFooterVisible);
headerFooterVisible.value = (0, _reactNativeReanimated.withTiming)(0);
}
}
}
}).withRef(doubleTapRef);
return {
doubleTap,
pan,
pinch,
singleTap
};
};
exports.useImageGalleryGestures = useImageGalleryGestures;
var clamp = (value, lowerBound, upperBound) => {
'worklet';
return Math.min(Math.max(lowerBound, value), upperBound);
};
exports.clamp = clamp;
//# sourceMappingURL=useImageGalleryGestures.js.map