@planningcenter/chat-react-native 3.12.2-rc.2 → 3.12.2
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useMemo, useState, useCallback, useRef } from 'react';
|
|
2
2
|
import { StatusBar, StyleSheet, Modal, View, Linking, Dimensions, } from 'react-native';
|
|
3
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
3
|
+
import { useSafeAreaInsets, SafeAreaProvider } from 'react-native-safe-area-context';
|
|
4
4
|
import { FlatList, Gesture, GestureDetector, GestureHandlerRootView, } from 'react-native-gesture-handler';
|
|
5
5
|
import Animated, { runOnJS, useAnimatedStyle, useAnimatedReaction, useSharedValue, withSpring, withDecay, } from 'react-native-reanimated';
|
|
6
6
|
import { tokens } from '../../../vendor/tapestry/tokens';
|
|
@@ -47,6 +47,16 @@ export function ImageAttachment({ attachment, imageAttachments, currentImageInde
|
|
|
47
47
|
</>);
|
|
48
48
|
}
|
|
49
49
|
const LightboxModal = ({ visible, setModalVisible, imageAttachments, initialImageIndex, metaProps, }) => {
|
|
50
|
+
const onRequestClose = useCallback(() => {
|
|
51
|
+
setModalVisible(false);
|
|
52
|
+
}, [setModalVisible]);
|
|
53
|
+
return (<Modal visible={visible} transparent animationType="fade" onRequestClose={onRequestClose}>
|
|
54
|
+
<SafeAreaProvider>
|
|
55
|
+
<LightboxGallery imageAttachments={imageAttachments} initialImageIndex={initialImageIndex} metaProps={metaProps} onRequestClose={onRequestClose}/>
|
|
56
|
+
</SafeAreaProvider>
|
|
57
|
+
</Modal>);
|
|
58
|
+
};
|
|
59
|
+
const LightboxGallery = ({ imageAttachments, initialImageIndex, metaProps, onRequestClose, }) => {
|
|
50
60
|
const styles = useStyles();
|
|
51
61
|
const insets = useSafeAreaInsets();
|
|
52
62
|
const [currentImageIndex, setCurrentImageIndex] = useState(initialImageIndex);
|
|
@@ -116,9 +126,9 @@ const LightboxModal = ({ visible, setModalVisible, imageAttachments, initialImag
|
|
|
116
126
|
enableFlatListScroll,
|
|
117
127
|
]);
|
|
118
128
|
const handleCloseModal = useCallback(() => {
|
|
119
|
-
|
|
129
|
+
onRequestClose();
|
|
120
130
|
resetAllGestures();
|
|
121
|
-
}, [
|
|
131
|
+
}, [onRequestClose, resetAllGestures]);
|
|
122
132
|
/* ============================
|
|
123
133
|
UTILITY WORKLET FUNCTIONS
|
|
124
134
|
'worklet' runs functions on the UI thread, instead of the JS thread for better performance.
|
|
@@ -449,7 +459,7 @@ const LightboxModal = ({ visible, setModalVisible, imageAttachments, initialImag
|
|
|
449
459
|
const transformImageGestures = Gesture.Race(tapGestures, pinchOrPanGestures);
|
|
450
460
|
// Dismiss can work simultaneously with all gestures
|
|
451
461
|
const composedGesture = Gesture.Simultaneous(transformImageGestures, panToDismissModalGesture);
|
|
452
|
-
return (
|
|
462
|
+
return (<>
|
|
453
463
|
<StatusBar barStyle="light-content" hidden={isStatusBarHidden} animated showHideTransition="slide"/>
|
|
454
464
|
<GestureHandlerRootView>
|
|
455
465
|
<GestureDetector gesture={composedGesture}>
|
|
@@ -460,7 +470,7 @@ const LightboxModal = ({ visible, setModalVisible, imageAttachments, initialImag
|
|
|
460
470
|
</GestureHandlerRootView>
|
|
461
471
|
<LightboxToolbarHeader metaProps={metaProps} lightboxToolbarVisible={lightboxToolbarVisible} isStatusBarHidden={isStatusBarHidden} handleOpenInBrowser={handleOpenInBrowser} handleCloseModal={handleCloseModal}/>
|
|
462
472
|
{imageAttachments.length > 1 && (<LightboxToolbarFooter lightboxToolbarVisible={lightboxToolbarVisible} totalImages={imageAttachments.length} currentImageIndex={currentImageIndex}/>)}
|
|
463
|
-
|
|
473
|
+
</>);
|
|
464
474
|
};
|
|
465
475
|
const GestureImage = ({ item, gesturesEnabled, scale, translateX, translateY, dismissY, opacity, }) => {
|
|
466
476
|
const styles = useStyles();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/image_attachment.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useMemo, useState, Dispatch, SetStateAction, useCallback, useRef } from 'react'\nimport {\n StatusBar,\n StyleSheet,\n Modal,\n View,\n Linking,\n Dimensions,\n NativeSyntheticEvent,\n NativeScrollEvent,\n ViewToken,\n} from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport {\n FlatList,\n Gesture,\n GestureDetector,\n GestureHandlerRootView,\n} from 'react-native-gesture-handler'\nimport Animated, {\n runOnJS,\n useAnimatedStyle,\n useAnimatedReaction,\n useSharedValue,\n withSpring,\n withDecay,\n SharedValue,\n} from 'react-native-reanimated'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { IconButton, Image, Heading, Text } from '../../display'\nimport colorFunction from 'color'\nimport { formatDatePreview } from '../../../utils/date'\nimport { DenormalizedMessageAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'\nimport { PlatformPressable } from '@react-navigation/elements'\nimport { useTheme } from '../../../hooks'\nimport { platformFontWeightMedium } from '../../../utils'\n\nconst { width: WINDOW_WIDTH, height: WINDOW_HEIGHT } = Dimensions.get('window')\nconst DISMISS_PAN_THRESHOLD = 250\nconst MIN_DISTANCE_FOR_PAN = 10 // Higher threshold gives pinching priority\nconst SINGLE_FINGER_POINTER = 1 // Single-finger panning / tapping helps to avoid conflicts with pinching\nconst DEFAULT_OPACITY = 1\nconst DEFAULT_TRANSLATE_X = 0\nconst DEFAULT_TRANSLATE_Y = 0\nconst DEFAULT_SCALE = 1\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 5\nconst MAX_SCALE_OVERSHOOT = 5\nconst DOUBLE_TAP_ZOOM_SCALE = 2\nconst DECAY_VELOCITY_FACTOR = 0.4\nconst RESET_SPRING_CONFIG = {\n damping: 20,\n stiffness: 150,\n}\n\nexport type MetaProps = {\n authorName: string\n createdAt: string\n}\n\nexport function ImageAttachment({\n attachment,\n imageAttachments,\n currentImageIndex,\n metaProps,\n onMessageAttachmentLongPress,\n}: {\n attachment: DenormalizedMessageAttachmentResource\n imageAttachments: DenormalizedMessageAttachmentResource[]\n currentImageIndex: number\n metaProps: MetaProps\n onMessageAttachmentLongPress: (attachment: DenormalizedMessageAttachmentResource) => void\n}) {\n const { attributes } = attachment\n const { url, urlMedium, filename, metadata = {} } = attributes\n const { colors } = useTheme()\n\n const styles = useStyles({ imageWidth: metadata.width, imageHeight: metadata.height })\n const [visible, setVisible] = useState(false)\n\n // Force modal to remount with fresh state\n // Fixes a bug where dismissing the modal too quickly causes the Reanimated shared values (like toolbarVisible) to not reset.\n const [modalKey, setModalKey] = useState(0)\n\n return (\n <>\n <PlatformPressable\n style={styles.container}\n onPress={() => {\n setModalKey(prev => prev + 1)\n setVisible(true)\n }}\n onLongPress={() => onMessageAttachmentLongPress(attachment)}\n android_ripple={{ color: colors.androidRippleNeutral, foreground: true }}\n accessibilityHint=\"Long press for more options\"\n >\n <Image\n source={{ uri: urlMedium || url }}\n style={styles.image}\n wrapperStyle={styles.attachmentImageWrapper}\n alt={filename}\n />\n </PlatformPressable>\n <LightboxModal\n key={modalKey}\n visible={visible}\n setModalVisible={setVisible}\n imageAttachments={imageAttachments}\n initialImageIndex={currentImageIndex}\n metaProps={metaProps}\n />\n </>\n )\n}\n\ninterface LightboxModalProps {\n visible: boolean\n setModalVisible: Dispatch<SetStateAction<boolean>>\n imageAttachments: DenormalizedMessageAttachmentResource[]\n initialImageIndex: number\n metaProps: MetaProps\n}\n\nconst LightboxModal = ({\n visible,\n setModalVisible,\n imageAttachments,\n initialImageIndex,\n metaProps,\n}: LightboxModalProps) => {\n const styles = useStyles()\n const insets = useSafeAreaInsets()\n const [currentImageIndex, setCurrentImageIndex] = useState(initialImageIndex)\n\n // Get current image data\n const currentImage = imageAttachments[currentImageIndex]\n const { url, urlMedium, metadata = {} } = currentImage.attributes\n const imageWidth = metadata.width\n const imageHeight = metadata.height\n\n // Calculate available space for image display\n const availableWindowWidth = WINDOW_WIDTH\n const availableWindowHeight = WINDOW_HEIGHT - insets.top - insets.bottom\n\n /* ============================\n ANIMATION VALUES\n ============================ */\n // Native State:\n const dismissY = useSharedValue(0) // vertical distance to dismiss modal\n const opacity = useSharedValue(DEFAULT_OPACITY) // opacity of modal\n const scale = useSharedValue(DEFAULT_SCALE) // zoom level of image\n const focalX = useSharedValue(0) // focal point of image between fingers\n const focalY = useSharedValue(0) // focal point of image between fingers\n const translateX = useSharedValue(DEFAULT_TRANSLATE_X) // horizontal distance to pan image\n const translateY = useSharedValue(DEFAULT_TRANSLATE_Y) // vertical distance to pan image\n const savedScale = useSharedValue(DEFAULT_SCALE) // previous zoom level\n const savedTranslateX = useSharedValue(DEFAULT_TRANSLATE_X) // previous horizontal position\n const savedTranslateY = useSharedValue(DEFAULT_TRANSLATE_Y) // previous vertical position\n const lightboxToolbarVisible = useSharedValue(1) // toolbar visibility state\n\n // React (JS) State:\n const [isStatusBarHidden, setIsStatusBarHidden] = useState(false)\n const [flatListScrollEnabled, setFlatListScrollEnabled] = useState(true)\n\n // Syncs toolbar useSharedValue state with React's state so that the status bar can be hidden/shown based on the toolbar's animation\n useAnimatedReaction(\n () => lightboxToolbarVisible.value,\n value => {\n runOnJS(setIsStatusBarHidden)(value === 0)\n }\n )\n\n /* ============================\n HANDLERS\n ============================ */\n const handleOpenInBrowser = useCallback(() => {\n Linking.openURL(urlMedium || url)\n }, [urlMedium, url])\n\n // Helper to enable or disable FlatList scroll state after gestures have ended\n const enableFlatListScroll = useCallback((enableScroll: boolean) => {\n setFlatListScrollEnabled(enableScroll)\n }, [])\n\n const resetDismissGestures = useCallback(() => {\n dismissY.value = withSpring(0, RESET_SPRING_CONFIG)\n opacity.value = withSpring(DEFAULT_OPACITY, RESET_SPRING_CONFIG)\n }, [dismissY, opacity])\n\n const resetAllGestures = useCallback(() => {\n resetDismissGestures()\n scale.value = withSpring(DEFAULT_SCALE, RESET_SPRING_CONFIG)\n translateX.value = withSpring(DEFAULT_TRANSLATE_X, RESET_SPRING_CONFIG)\n translateY.value = withSpring(DEFAULT_TRANSLATE_Y, RESET_SPRING_CONFIG)\n savedScale.value = DEFAULT_SCALE\n savedTranslateX.value = DEFAULT_TRANSLATE_X\n savedTranslateY.value = DEFAULT_TRANSLATE_Y\n lightboxToolbarVisible.value = withSpring(1, RESET_SPRING_CONFIG)\n enableFlatListScroll(true)\n }, [\n resetDismissGestures,\n scale,\n translateX,\n translateY,\n savedScale,\n savedTranslateX,\n savedTranslateY,\n lightboxToolbarVisible,\n enableFlatListScroll,\n ])\n\n const handleCloseModal = useCallback(() => {\n setModalVisible(false)\n resetAllGestures()\n }, [setModalVisible, resetAllGestures])\n\n /* ============================\n UTILITY WORKLET FUNCTIONS\n 'worklet' runs functions on the UI thread, instead of the JS thread for better performance.\n ============================ */\n const getImageContainedToWindowDimensions = () => {\n 'worklet'\n\n if (!imageWidth || !imageHeight) {\n return { width: availableWindowWidth, height: availableWindowHeight }\n }\n\n const imageAspectRatio = imageWidth / imageHeight\n const windowAspectRatio = availableWindowWidth / availableWindowHeight\n\n // Constrain image width if its wider than window\n if (imageAspectRatio > windowAspectRatio) {\n return {\n width: availableWindowWidth,\n height: availableWindowWidth / imageAspectRatio,\n }\n }\n\n // Constrain image height if its taller than window\n return {\n width: availableWindowHeight * imageAspectRatio,\n height: availableWindowHeight,\n }\n }\n\n const zoomToFocalPoint = ({\n focalPointX,\n focalPointY,\n targetScale,\n currentSavedScale,\n currentSavedTranslateX,\n currentSavedTranslateY,\n }: {\n focalPointX: number\n focalPointY: number\n targetScale: number\n currentSavedScale: number\n currentSavedTranslateX: number\n currentSavedTranslateY: number\n }) => {\n 'worklet'\n\n // How far the focal point is from the center of the window\n const windowCenterX = WINDOW_WIDTH / 2\n const windowCenterY = WINDOW_HEIGHT / 2\n\n // Position of focal point relative to current image position\n const focalRelativeX = focalPointX - windowCenterX - currentSavedTranslateX\n const focalRelativeY = focalPointY - windowCenterY - currentSavedTranslateY\n\n // Calculate new translation to keep focal point under fingers\n const scaleRatio = targetScale / currentSavedScale\n const newTranslateX = currentSavedTranslateX + focalRelativeX * (1 - scaleRatio)\n const newTranslateY = currentSavedTranslateY + focalRelativeY * (1 - scaleRatio)\n\n return {\n translateX: newTranslateX,\n translateY: newTranslateY,\n }\n }\n\n const getMaxTranslationLimits = (currentScale: number) => {\n 'worklet'\n\n const { width: containedImageWidth, height: containedImageHeight } =\n getImageContainedToWindowDimensions()\n\n // Image dimensions after scaling/zooming\n const scaledWidth = containedImageWidth * currentScale\n const scaledHeight = containedImageHeight * currentScale\n\n // How much the scaled image exceeds the window container\n const excessWidth = scaledWidth - availableWindowWidth\n const excessHeight = scaledHeight - availableWindowHeight\n\n // How far the image can move in each direction before hitting window edges\n const maxTranslateX = Math.max(DEFAULT_TRANSLATE_X, excessWidth / 2)\n const maxTranslateY = Math.max(DEFAULT_TRANSLATE_Y, excessHeight / 2)\n\n return { maxTranslateX, maxTranslateY }\n }\n\n const clampDecay = (currentScale: number): { x: [number, number]; y: [number, number] } => {\n 'worklet'\n\n const { maxTranslateX, maxTranslateY } = getMaxTranslationLimits(currentScale)\n\n return {\n x: [-maxTranslateX, maxTranslateX],\n y: [-maxTranslateY, maxTranslateY],\n }\n }\n\n const clampTranslation = ({\n x,\n y,\n currentScale,\n }: {\n x: number\n y: number\n currentScale: number\n }) => {\n 'worklet'\n\n const { maxTranslateX, maxTranslateY } = getMaxTranslationLimits(currentScale)\n\n return {\n x: Math.min(maxTranslateX, Math.max(-maxTranslateX, x)),\n y: Math.min(maxTranslateY, Math.max(-maxTranslateY, y)),\n }\n }\n\n const isImageAtVerticalBoundry = (currentScale: number) => {\n 'worklet'\n\n const { height: containedImageHeight } = getImageContainedToWindowDimensions()\n\n // Calculate how much the image can exceed the window container\n const scaledHeight = containedImageHeight * currentScale\n const excessHeight = scaledHeight - availableWindowHeight\n const maxTranslateY = Math.max(DEFAULT_TRANSLATE_Y, excessHeight / 2)\n\n const currentTranslateY = translateY.value\n const panPositionTolerance = 1 // buffer to account for translateY being at a subpixel position\n\n const atTopBoundry = currentTranslateY >= maxTranslateY - panPositionTolerance\n const atBottomBoundry = currentTranslateY <= -maxTranslateY + panPositionTolerance\n\n return atTopBoundry || atBottomBoundry\n }\n\n /* ============================\n UTILITY FLATLIST FUNCTIONS\n Supports the image gallery layout and swipe functionality.\n ============================ */\n\n // Use refs to avoid re-rendering FlatList callbacks...\n const stableCurrentImageIndexRef = useRef(currentImageIndex)\n const stableImageAttachmentsLengthRef = useRef(imageAttachments.length)\n // ...while still ensuring they are updated with the latest values\n stableCurrentImageIndexRef.current = currentImageIndex\n stableImageAttachmentsLengthRef.current = imageAttachments.length\n\n // Used in tandem with FlatList's initialScrollIndex to quickly calculate the position and size of each image before they load.\n const getItemLayout = useCallback(\n (_: unknown, index: number) => ({\n length: WINDOW_WIDTH,\n offset: WINDOW_WIDTH * index,\n index,\n }),\n []\n )\n\n // Captures the current image's index after the FlatList finishes its scroll animation.\n // Used in tandem with onViewableItemsChanged to ensure the final value for currentImageIndex is set.\n const onMomentumScrollEnd = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\n // Calculate the index of the image that is currently visible\n const imageOffsetX = event.nativeEvent.contentOffset.x\n const newImageIndex = Math.round(imageOffsetX / WINDOW_WIDTH)\n\n // Check if the image index has changed and the FlatList didn't scroll past the first or last image\n const didImageIndexChange = newImageIndex !== stableCurrentImageIndexRef.current\n const isImageIndexWithinBounds =\n newImageIndex >= 0 && newImageIndex < stableImageAttachmentsLengthRef.current\n\n if (didImageIndexChange && isImageIndexWithinBounds) {\n setCurrentImageIndex(newImageIndex)\n }\n }, [])\n\n // Supplements onMomentumScrollEnd by capturing the current image's index while the FlatList is actively scrolling.\n // Used in tandem with viewabilityConfig to trigger when the image is 50% visible in the window.\n const onViewableItemsChanged = useCallback(\n ({ viewableItems }: { viewableItems: ViewToken<DenormalizedMessageAttachmentResource>[] }) => {\n if (viewableItems.length === 0) return\n\n // Use the first viewable item which is enforced by the FlatList's pagingEnabled prop that allows only two images to be visible at a time when scrolling.\n const firstViewableItem = viewableItems[0]\n const newIndex = firstViewableItem.index\n\n if (newIndex !== null && newIndex !== stableCurrentImageIndexRef.current) {\n setCurrentImageIndex(newIndex)\n }\n },\n []\n )\n\n /* ============================\n GESTURES\n ============================ */\n const singleTapGesture = Gesture.Tap()\n .minPointers(SINGLE_FINGER_POINTER)\n .numberOfTaps(1)\n .onStart(() => {\n lightboxToolbarVisible.value = withSpring(\n lightboxToolbarVisible.value > 0.5 ? 0 : 1,\n RESET_SPRING_CONFIG\n )\n })\n\n const doubleTapGesture = Gesture.Tap()\n .minPointers(SINGLE_FINGER_POINTER)\n .numberOfTaps(2)\n .onStart(e => {\n const isZoomedIn = scale.value > DEFAULT_SCALE\n if (isZoomedIn) {\n runOnJS(resetAllGestures)()\n } else {\n // Hide toolbar when starting to zoom\n lightboxToolbarVisible.value = withSpring(0, RESET_SPRING_CONFIG)\n\n // Zoom to 2x at tap location\n const newTranslation = zoomToFocalPoint({\n focalPointX: e.x,\n focalPointY: e.y,\n targetScale: DOUBLE_TAP_ZOOM_SCALE,\n currentSavedScale: savedScale.value,\n currentSavedTranslateX: savedTranslateX.value,\n currentSavedTranslateY: savedTranslateY.value,\n })\n\n // Apply clamping to ensure image edges remain within window boundaries\n const clampedTranslate = clampTranslation({\n x: newTranslation.translateX,\n y: newTranslation.translateY,\n currentScale: DOUBLE_TAP_ZOOM_SCALE,\n })\n\n // Animate to new scale and translation\n scale.value = withSpring(DOUBLE_TAP_ZOOM_SCALE, RESET_SPRING_CONFIG)\n translateX.value = withSpring(clampedTranslate.x, RESET_SPRING_CONFIG)\n translateY.value = withSpring(clampedTranslate.y, RESET_SPRING_CONFIG)\n\n // Update saved state for next gesture\n savedScale.value = DOUBLE_TAP_ZOOM_SCALE\n savedTranslateX.value = clampedTranslate.x\n savedTranslateY.value = clampedTranslate.y\n\n // Disable FlatList scroll since image is now zoomed\n runOnJS(enableFlatListScroll)(false)\n }\n })\n\n const pinchGesture = Gesture.Pinch()\n .onStart(e => {\n focalX.value = e.focalX\n focalY.value = e.focalY\n\n // Hide toolbar when starting to zoom\n lightboxToolbarVisible.value = withSpring(0, RESET_SPRING_CONFIG)\n\n // Ensure that pinch accounts for the decay animation and starts from the true current position.\n savedTranslateX.value = translateX.value\n savedTranslateY.value = translateY.value\n })\n .onUpdate(e => {\n // Zoom image in/out within scale limits\n const newScale = savedScale.value * e.scale\n const newScaleClamped = Math.min(\n MAX_SCALE + MAX_SCALE_OVERSHOOT,\n Math.max(MIN_SCALE, newScale)\n )\n scale.value = newScaleClamped\n\n // Calculate new translation to keep focal point under fingers\n const newTranslation = zoomToFocalPoint({\n focalPointX: focalX.value,\n focalPointY: focalY.value,\n targetScale: newScaleClamped,\n currentSavedScale: savedScale.value,\n currentSavedTranslateX: savedTranslateX.value,\n currentSavedTranslateY: savedTranslateY.value,\n })\n\n // Apply translation without clamping to ensure focal point doesn't jump during gesture\n translateX.value = newTranslation.translateX\n translateY.value = newTranslation.translateY\n })\n .onEnd(() => {\n const currentScale = scale.value\n\n // Dismiss modal if fully zoomed out\n if (currentScale <= MIN_SCALE) {\n runOnJS(handleCloseModal)()\n return\n }\n\n // Reset all gestures if image is near default scale\n const isNearDefaultScale = currentScale <= DEFAULT_SCALE + 0.1\n if (isNearDefaultScale) {\n runOnJS(resetAllGestures)()\n return\n }\n\n // Check if overshooting the max scale and clamp it\n const finalScale = currentScale > MAX_SCALE ? MAX_SCALE : currentScale\n\n // Recalculate translation using focal point to always return to the same position when image is overshooting the max scale\n const newTranslation = zoomToFocalPoint({\n focalPointX: focalX.value,\n focalPointY: focalY.value,\n targetScale: finalScale,\n currentSavedScale: savedScale.value,\n currentSavedTranslateX: savedTranslateX.value,\n currentSavedTranslateY: savedTranslateY.value,\n })\n\n // Ensure image edges remain within window boundaries\n const clampedTranslate = clampTranslation({\n x: newTranslation.translateX,\n y: newTranslation.translateY,\n currentScale: finalScale,\n })\n\n // Animate to position and scale limits with a spring\n scale.value = withSpring(finalScale, RESET_SPRING_CONFIG)\n translateX.value = withSpring(clampedTranslate.x, RESET_SPRING_CONFIG)\n translateY.value = withSpring(clampedTranslate.y, RESET_SPRING_CONFIG)\n\n // Save state for next gesture\n savedScale.value = finalScale\n savedTranslateX.value = clampedTranslate.x\n savedTranslateY.value = clampedTranslate.y\n\n // Disable FlatList scroll since image is still zoomed\n runOnJS(enableFlatListScroll)(false)\n })\n\n const panGesture = Gesture.Pan()\n .minDistance(MIN_DISTANCE_FOR_PAN)\n .minPointers(SINGLE_FINGER_POINTER)\n .maxPointers(SINGLE_FINGER_POINTER)\n .onStart(() => {\n // Only start pan if image is zoomed in - prevents conflicts with FlatList\n if (scale.value <= DEFAULT_SCALE) return\n\n // Update saved position to current animated position\n // This ensures smooth continuation if decay is running\n savedTranslateX.value = translateX.value\n savedTranslateY.value = translateY.value\n })\n .onUpdate(e => {\n // Only pan if image is zoomed in - prevents conflicts with FlatList\n if (scale.value <= DEFAULT_SCALE) return\n\n const newTranslateX = savedTranslateX.value + e.translationX\n const newTranslateY = savedTranslateY.value + e.translationY\n\n // Ensure image edges remain within window boundaries\n const clampedTranslate = clampTranslation({\n x: newTranslateX,\n y: newTranslateY,\n currentScale: scale.value,\n })\n translateX.value = clampedTranslate.x\n translateY.value = clampedTranslate.y\n })\n .onEnd(e => {\n // Prevents saving pan position if image is zoomed out while panning\n if (scale.value <= DEFAULT_SCALE) return\n\n const clampDecayBounds = clampDecay(scale.value)\n\n translateX.value = withDecay(\n {\n velocity: e.velocityX * DECAY_VELOCITY_FACTOR,\n clamp: clampDecayBounds.x,\n deceleration: 0.996,\n },\n finished => {\n if (finished) {\n savedTranslateX.value = translateX.value\n }\n }\n )\n\n translateY.value = withDecay(\n {\n velocity: e.velocityY * DECAY_VELOCITY_FACTOR,\n clamp: clampDecayBounds.y,\n deceleration: 0.996,\n },\n finished => {\n if (finished) {\n savedTranslateY.value = translateY.value\n }\n }\n )\n })\n\n const panToDismissModalGesture = Gesture.Pan()\n .onUpdate(e => {\n const atDefaultScale = scale.value === DEFAULT_SCALE\n\n // Calculate zoom conditions for dismissing modal\n const atVerticalBoundry = isImageAtVerticalBoundry(scale.value)\n const panDirectionIsPrimarilyVertical = Math.abs(e.translationY) > Math.abs(e.translationX)\n const canDismissWhileZoomed = atVerticalBoundry && panDirectionIsPrimarilyVertical\n\n if (!(atDefaultScale || canDismissWhileZoomed)) return\n\n // Fade image if its been panned past 50% of the dismiss threshold\n const panDistance = Math.abs(e.translationY)\n const halfThreshold = DISMISS_PAN_THRESHOLD / 2\n const fadeDistance = Math.max(0, panDistance - halfThreshold)\n const fadeProgress = fadeDistance / halfThreshold\n\n opacity.value = Math.max(0, DEFAULT_OPACITY - fadeProgress)\n dismissY.value = e.translationY\n })\n .onEnd(() => {\n const exceededDismissThreshold = Math.abs(dismissY.value) > DISMISS_PAN_THRESHOLD\n\n if (exceededDismissThreshold) {\n runOnJS(handleCloseModal)()\n } else {\n runOnJS(resetDismissGestures)()\n }\n })\n\n /* ==============================\n COMPOSE GESTURES\n ================================= */\n // Race between pinch and pan ensures only one is active at a time, preserving focal point logic\n const pinchOrPanGestures = Gesture.Race(pinchGesture, panGesture)\n\n // Exclusive race ensures single tap doesn't interfere with double tap\n const tapGestures = Gesture.Exclusive(doubleTapGesture, singleTapGesture)\n\n // Race between tap gestures and pinch/pan\n const transformImageGestures = Gesture.Race(tapGestures, pinchOrPanGestures)\n\n // Dismiss can work simultaneously with all gestures\n const composedGesture = Gesture.Simultaneous(transformImageGestures, panToDismissModalGesture)\n\n return (\n <Modal visible={visible} transparent animationType=\"fade\" onRequestClose={handleCloseModal}>\n <StatusBar\n barStyle=\"light-content\"\n hidden={isStatusBarHidden}\n animated\n showHideTransition=\"slide\"\n />\n <GestureHandlerRootView>\n <GestureDetector gesture={composedGesture}>\n <FlatList\n data={imageAttachments}\n renderItem={({ item, index }) => (\n <GestureImage\n item={item}\n gesturesEnabled={index === currentImageIndex}\n scale={scale}\n translateX={translateX}\n translateY={translateY}\n dismissY={dismissY}\n opacity={opacity}\n />\n )}\n keyExtractor={(item, index) => `${item.id}-${index}`}\n horizontal\n pagingEnabled\n scrollEnabled={flatListScrollEnabled}\n showsHorizontalScrollIndicator={false}\n initialScrollIndex={initialImageIndex}\n getItemLayout={getItemLayout}\n onMomentumScrollEnd={onMomentumScrollEnd}\n onViewableItemsChanged={onViewableItemsChanged}\n viewabilityConfig={{\n itemVisiblePercentThreshold: 50, // 50% of the image must be visible in the window to be considered viewable\n }}\n style={styles.gallery}\n contentContainerStyle={styles.galleryContentContainer}\n />\n </GestureDetector>\n </GestureHandlerRootView>\n <LightboxToolbarHeader\n metaProps={metaProps}\n lightboxToolbarVisible={lightboxToolbarVisible}\n isStatusBarHidden={isStatusBarHidden}\n handleOpenInBrowser={handleOpenInBrowser}\n handleCloseModal={handleCloseModal}\n />\n {imageAttachments.length > 1 && (\n <LightboxToolbarFooter\n lightboxToolbarVisible={lightboxToolbarVisible}\n totalImages={imageAttachments.length}\n currentImageIndex={currentImageIndex}\n />\n )}\n </Modal>\n )\n}\n\ninterface GestureImageProps {\n item: DenormalizedMessageAttachmentResource\n gesturesEnabled: boolean\n scale: SharedValue<number>\n translateX: SharedValue<number>\n translateY: SharedValue<number>\n dismissY: SharedValue<number>\n opacity: SharedValue<number>\n}\n\nconst GestureImage = ({\n item,\n gesturesEnabled,\n scale,\n translateX,\n translateY,\n dismissY,\n opacity,\n}: GestureImageProps) => {\n const styles = useStyles()\n const { url: itemUrl, urlMedium: itemUrlMedium } = item.attributes\n\n const animatedImageStyles = useAnimatedStyle(() => {\n return {\n transform: [\n { translateX: gesturesEnabled ? translateX.value : DEFAULT_TRANSLATE_X },\n { translateY: gesturesEnabled ? translateY.value + dismissY.value : DEFAULT_TRANSLATE_Y },\n { scale: gesturesEnabled ? scale.value : DEFAULT_SCALE },\n ],\n opacity: opacity.value,\n }\n })\n\n return (\n <TouchEventIsolator>\n <Image\n source={{ uri: itemUrlMedium || itemUrl }}\n style={styles.gestureImage}\n animatedImageStyle={animatedImageStyles}\n loadingBackgroundStyles={styles.gestureImageLoading}\n resizeMode=\"contain\"\n alt=\"\"\n />\n </TouchEventIsolator>\n )\n}\n\nconst TouchEventIsolator = ({ children }: { children: React.ReactNode }) => {\n const styles = useStyles()\n\n return (\n <View style={styles.touchEventIsolator} onStartShouldSetResponder={() => true}>\n {children}\n </View>\n )\n}\n\ninterface LightboxToolbarHeaderProps {\n metaProps: MetaProps\n lightboxToolbarVisible: SharedValue<number>\n isStatusBarHidden: boolean\n handleOpenInBrowser: () => void\n handleCloseModal: () => void\n}\n\nconst LightboxToolbarHeader = ({\n metaProps,\n lightboxToolbarVisible,\n isStatusBarHidden,\n handleOpenInBrowser,\n handleCloseModal,\n}: LightboxToolbarHeaderProps) => {\n const styles = useStyles()\n const { authorName, createdAt } = metaProps\n\n const animatedHeaderStyles = useAnimatedStyle(() => ({\n opacity: lightboxToolbarVisible.value,\n transform: [\n { translateY: (1 - lightboxToolbarVisible.value) * -20 }, // slide up when hiding\n ],\n }))\n\n return (\n <Animated.View\n style={[styles.lightboxToolbar, styles.lightboxToolbarHeader, animatedHeaderStyles]}\n accessibilityRole=\"toolbar\"\n >\n <View style={styles.lightboxToolbarHeaderMetaContainer}>\n <Heading variant=\"h3\" style={styles.lightboxToolbarHeaderTitle} numberOfLines={1}>\n {authorName}\n </Heading>\n <Text variant=\"tertiary\" style={styles.lightboxToolbarHeaderSubtitle}>\n {formatDatePreview(createdAt)}\n </Text>\n </View>\n <IconButton\n onPress={handleOpenInBrowser}\n disabled={isStatusBarHidden}\n name=\"general.newWindow\"\n accessibilityRole=\"link\"\n accessibilityLabel=\"Open image in browser\"\n accessibilityHint=\"Image can be downloaded and shared through the browser.\"\n style={styles.lightboxToolbarButton}\n iconStyle={styles.lightboxToolbarButtonIcon}\n size=\"lg\"\n />\n <IconButton\n onPress={handleCloseModal}\n disabled={isStatusBarHidden}\n name=\"general.x\"\n accessibilityLabel=\"Close image\"\n style={styles.lightboxToolbarButton}\n iconStyle={styles.lightboxToolbarButtonIcon}\n size=\"lg\"\n />\n </Animated.View>\n )\n}\n\ninterface LightboxToolbarFooterProps {\n lightboxToolbarVisible: SharedValue<number>\n totalImages: number\n currentImageIndex: number\n}\n\nconst LightboxToolbarFooter = ({\n lightboxToolbarVisible,\n totalImages,\n currentImageIndex,\n}: LightboxToolbarFooterProps) => {\n const styles = useStyles()\n\n const animatedFooterStyles = useAnimatedStyle(() => ({\n opacity: lightboxToolbarVisible.value,\n transform: [\n { translateY: (1 - lightboxToolbarVisible.value) * 20 }, // slide down when showing\n ],\n }))\n\n return (\n <Animated.View\n style={[styles.lightboxToolbar, styles.lightboxToolbarFooter, animatedFooterStyles]}\n accessibilityRole=\"toolbar\"\n >\n <Text style={styles.lightboxToolbarFooterText}>\n {currentImageIndex + 1} of {totalImages}\n </Text>\n </Animated.View>\n )\n}\n\ninterface UseStylesProps {\n imageWidth?: number\n imageHeight?: number\n}\n\nconst useStyles = ({ imageWidth = 100, imageHeight = 100 }: UseStylesProps = {}) => {\n const { top, bottom } = useSafeAreaInsets()\n const backgroundColor = tokens.colorNeutral7\n const transparentBackgroundColor = useMemo(\n () => colorFunction(backgroundColor).alpha(0.8).toString(),\n [backgroundColor]\n )\n\n return StyleSheet.create({\n container: {\n maxWidth: '100%',\n },\n touchEventIsolator: {\n flex: 1,\n },\n attachmentImageWrapper: {\n width: '100%',\n minWidth: 200,\n aspectRatio: imageWidth / imageHeight,\n },\n image: {\n borderRadius: 8,\n },\n gallery: {\n backgroundColor,\n },\n galleryContentContainer: {\n paddingTop: top,\n paddingBottom: bottom,\n },\n gestureImage: {\n height: '100%',\n width: WINDOW_WIDTH,\n backgroundColor: 'transparent',\n },\n gestureImageLoading: {\n backgroundColor,\n },\n lightboxToolbar: {\n width: '100%',\n position: 'absolute',\n flexDirection: 'row',\n alignItems: 'center',\n gap: 20,\n paddingHorizontal: 16,\n backgroundColor: transparentBackgroundColor,\n },\n lightboxToolbarButton: {\n backgroundColor,\n height: 40,\n width: 40,\n borderRadius: 50,\n borderWidth: 1,\n borderColor: tokens.colorNeutral24,\n },\n lightboxToolbarButtonIcon: {\n color: tokens.colorNeutral88,\n },\n lightboxToolbarHeader: {\n top: 0,\n paddingTop: top + 16,\n paddingBottom: 8,\n },\n lightboxToolbarHeaderMetaContainer: {\n flex: 1,\n },\n lightboxToolbarHeaderTitle: {\n marginRight: 'auto',\n flexShrink: 1,\n color: tokens.colorNeutral88,\n },\n lightboxToolbarHeaderSubtitle: {\n color: tokens.colorNeutral68,\n },\n lightboxToolbarFooter: {\n justifyContent: 'center',\n bottom: 0,\n paddingTop: 8,\n paddingBottom: bottom + 16,\n },\n lightboxToolbarFooterText: {\n color: tokens.colorNeutral88,\n fontWeight: platformFontWeightMedium,\n },\n })\n}\n"]}
|
|
1
|
+
{"version":3,"file":"image_attachment.js","sourceRoot":"","sources":["../../../../src/components/conversation/attachments/image_attachment.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useMemo, useState, Dispatch, SetStateAction, useCallback, useRef } from 'react'\nimport {\n StatusBar,\n StyleSheet,\n Modal,\n View,\n Linking,\n Dimensions,\n NativeSyntheticEvent,\n NativeScrollEvent,\n ViewToken,\n} from 'react-native'\nimport { useSafeAreaInsets, SafeAreaProvider } from 'react-native-safe-area-context'\nimport {\n FlatList,\n Gesture,\n GestureDetector,\n GestureHandlerRootView,\n} from 'react-native-gesture-handler'\nimport Animated, {\n runOnJS,\n useAnimatedStyle,\n useAnimatedReaction,\n useSharedValue,\n withSpring,\n withDecay,\n SharedValue,\n} from 'react-native-reanimated'\nimport { tokens } from '../../../vendor/tapestry/tokens'\nimport { IconButton, Image, Heading, Text } from '../../display'\nimport colorFunction from 'color'\nimport { formatDatePreview } from '../../../utils/date'\nimport { DenormalizedMessageAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'\nimport { PlatformPressable } from '@react-navigation/elements'\nimport { useTheme } from '../../../hooks'\nimport { platformFontWeightMedium } from '../../../utils'\n\nconst { width: WINDOW_WIDTH, height: WINDOW_HEIGHT } = Dimensions.get('window')\nconst DISMISS_PAN_THRESHOLD = 250\nconst MIN_DISTANCE_FOR_PAN = 10 // Higher threshold gives pinching priority\nconst SINGLE_FINGER_POINTER = 1 // Single-finger panning / tapping helps to avoid conflicts with pinching\nconst DEFAULT_OPACITY = 1\nconst DEFAULT_TRANSLATE_X = 0\nconst DEFAULT_TRANSLATE_Y = 0\nconst DEFAULT_SCALE = 1\nconst MIN_SCALE = 0.5\nconst MAX_SCALE = 5\nconst MAX_SCALE_OVERSHOOT = 5\nconst DOUBLE_TAP_ZOOM_SCALE = 2\nconst DECAY_VELOCITY_FACTOR = 0.4\nconst RESET_SPRING_CONFIG = {\n damping: 20,\n stiffness: 150,\n}\n\nexport type MetaProps = {\n authorName: string\n createdAt: string\n}\n\nexport function ImageAttachment({\n attachment,\n imageAttachments,\n currentImageIndex,\n metaProps,\n onMessageAttachmentLongPress,\n}: {\n attachment: DenormalizedMessageAttachmentResource\n imageAttachments: DenormalizedMessageAttachmentResource[]\n currentImageIndex: number\n metaProps: MetaProps\n onMessageAttachmentLongPress: (attachment: DenormalizedMessageAttachmentResource) => void\n}) {\n const { attributes } = attachment\n const { url, urlMedium, filename, metadata = {} } = attributes\n const { colors } = useTheme()\n\n const styles = useStyles({ imageWidth: metadata.width, imageHeight: metadata.height })\n const [visible, setVisible] = useState(false)\n\n // Force modal to remount with fresh state\n // Fixes a bug where dismissing the modal too quickly causes the Reanimated shared values (like toolbarVisible) to not reset.\n const [modalKey, setModalKey] = useState(0)\n\n return (\n <>\n <PlatformPressable\n style={styles.container}\n onPress={() => {\n setModalKey(prev => prev + 1)\n setVisible(true)\n }}\n onLongPress={() => onMessageAttachmentLongPress(attachment)}\n android_ripple={{ color: colors.androidRippleNeutral, foreground: true }}\n accessibilityHint=\"Long press for more options\"\n >\n <Image\n source={{ uri: urlMedium || url }}\n style={styles.image}\n wrapperStyle={styles.attachmentImageWrapper}\n alt={filename}\n />\n </PlatformPressable>\n <LightboxModal\n key={modalKey}\n visible={visible}\n setModalVisible={setVisible}\n imageAttachments={imageAttachments}\n initialImageIndex={currentImageIndex}\n metaProps={metaProps}\n />\n </>\n )\n}\n\ninterface LightboxModalProps {\n visible: boolean\n setModalVisible: Dispatch<SetStateAction<boolean>>\n imageAttachments: DenormalizedMessageAttachmentResource[]\n initialImageIndex: number\n metaProps: MetaProps\n}\n\nconst LightboxModal = ({\n visible,\n setModalVisible,\n imageAttachments,\n initialImageIndex,\n metaProps,\n}: LightboxModalProps) => {\n const onRequestClose = useCallback(() => {\n setModalVisible(false)\n }, [setModalVisible])\n\n return (\n <Modal visible={visible} transparent animationType=\"fade\" onRequestClose={onRequestClose}>\n <SafeAreaProvider>\n <LightboxGallery\n imageAttachments={imageAttachments}\n initialImageIndex={initialImageIndex}\n metaProps={metaProps}\n onRequestClose={onRequestClose}\n />\n </SafeAreaProvider>\n </Modal>\n )\n}\n\ninterface LightboxGalleryProps {\n imageAttachments: DenormalizedMessageAttachmentResource[]\n initialImageIndex: number\n metaProps: MetaProps\n onRequestClose: () => void\n}\nconst LightboxGallery = ({\n imageAttachments,\n initialImageIndex,\n metaProps,\n onRequestClose,\n}: LightboxGalleryProps) => {\n const styles = useStyles()\n const insets = useSafeAreaInsets()\n const [currentImageIndex, setCurrentImageIndex] = useState(initialImageIndex)\n\n // Get current image data\n const currentImage = imageAttachments[currentImageIndex]\n const { url, urlMedium, metadata = {} } = currentImage.attributes\n const imageWidth = metadata.width\n const imageHeight = metadata.height\n\n // Calculate available space for image display\n const availableWindowWidth = WINDOW_WIDTH\n const availableWindowHeight = WINDOW_HEIGHT - insets.top - insets.bottom\n\n /* ============================\n ANIMATION VALUES\n ============================ */\n // Native State:\n const dismissY = useSharedValue(0) // vertical distance to dismiss modal\n const opacity = useSharedValue(DEFAULT_OPACITY) // opacity of modal\n const scale = useSharedValue(DEFAULT_SCALE) // zoom level of image\n const focalX = useSharedValue(0) // focal point of image between fingers\n const focalY = useSharedValue(0) // focal point of image between fingers\n const translateX = useSharedValue(DEFAULT_TRANSLATE_X) // horizontal distance to pan image\n const translateY = useSharedValue(DEFAULT_TRANSLATE_Y) // vertical distance to pan image\n const savedScale = useSharedValue(DEFAULT_SCALE) // previous zoom level\n const savedTranslateX = useSharedValue(DEFAULT_TRANSLATE_X) // previous horizontal position\n const savedTranslateY = useSharedValue(DEFAULT_TRANSLATE_Y) // previous vertical position\n const lightboxToolbarVisible = useSharedValue(1) // toolbar visibility state\n\n // React (JS) State:\n const [isStatusBarHidden, setIsStatusBarHidden] = useState(false)\n const [flatListScrollEnabled, setFlatListScrollEnabled] = useState(true)\n\n // Syncs toolbar useSharedValue state with React's state so that the status bar can be hidden/shown based on the toolbar's animation\n useAnimatedReaction(\n () => lightboxToolbarVisible.value,\n value => {\n runOnJS(setIsStatusBarHidden)(value === 0)\n }\n )\n\n /* ============================\n HANDLERS\n ============================ */\n const handleOpenInBrowser = useCallback(() => {\n Linking.openURL(urlMedium || url)\n }, [urlMedium, url])\n\n // Helper to enable or disable FlatList scroll state after gestures have ended\n const enableFlatListScroll = useCallback((enableScroll: boolean) => {\n setFlatListScrollEnabled(enableScroll)\n }, [])\n\n const resetDismissGestures = useCallback(() => {\n dismissY.value = withSpring(0, RESET_SPRING_CONFIG)\n opacity.value = withSpring(DEFAULT_OPACITY, RESET_SPRING_CONFIG)\n }, [dismissY, opacity])\n\n const resetAllGestures = useCallback(() => {\n resetDismissGestures()\n scale.value = withSpring(DEFAULT_SCALE, RESET_SPRING_CONFIG)\n translateX.value = withSpring(DEFAULT_TRANSLATE_X, RESET_SPRING_CONFIG)\n translateY.value = withSpring(DEFAULT_TRANSLATE_Y, RESET_SPRING_CONFIG)\n savedScale.value = DEFAULT_SCALE\n savedTranslateX.value = DEFAULT_TRANSLATE_X\n savedTranslateY.value = DEFAULT_TRANSLATE_Y\n lightboxToolbarVisible.value = withSpring(1, RESET_SPRING_CONFIG)\n enableFlatListScroll(true)\n }, [\n resetDismissGestures,\n scale,\n translateX,\n translateY,\n savedScale,\n savedTranslateX,\n savedTranslateY,\n lightboxToolbarVisible,\n enableFlatListScroll,\n ])\n\n const handleCloseModal = useCallback(() => {\n onRequestClose()\n resetAllGestures()\n }, [onRequestClose, resetAllGestures])\n\n /* ============================\n UTILITY WORKLET FUNCTIONS\n 'worklet' runs functions on the UI thread, instead of the JS thread for better performance.\n ============================ */\n const getImageContainedToWindowDimensions = () => {\n 'worklet'\n\n if (!imageWidth || !imageHeight) {\n return { width: availableWindowWidth, height: availableWindowHeight }\n }\n\n const imageAspectRatio = imageWidth / imageHeight\n const windowAspectRatio = availableWindowWidth / availableWindowHeight\n\n // Constrain image width if its wider than window\n if (imageAspectRatio > windowAspectRatio) {\n return {\n width: availableWindowWidth,\n height: availableWindowWidth / imageAspectRatio,\n }\n }\n\n // Constrain image height if its taller than window\n return {\n width: availableWindowHeight * imageAspectRatio,\n height: availableWindowHeight,\n }\n }\n\n const zoomToFocalPoint = ({\n focalPointX,\n focalPointY,\n targetScale,\n currentSavedScale,\n currentSavedTranslateX,\n currentSavedTranslateY,\n }: {\n focalPointX: number\n focalPointY: number\n targetScale: number\n currentSavedScale: number\n currentSavedTranslateX: number\n currentSavedTranslateY: number\n }) => {\n 'worklet'\n\n // How far the focal point is from the center of the window\n const windowCenterX = WINDOW_WIDTH / 2\n const windowCenterY = WINDOW_HEIGHT / 2\n\n // Position of focal point relative to current image position\n const focalRelativeX = focalPointX - windowCenterX - currentSavedTranslateX\n const focalRelativeY = focalPointY - windowCenterY - currentSavedTranslateY\n\n // Calculate new translation to keep focal point under fingers\n const scaleRatio = targetScale / currentSavedScale\n const newTranslateX = currentSavedTranslateX + focalRelativeX * (1 - scaleRatio)\n const newTranslateY = currentSavedTranslateY + focalRelativeY * (1 - scaleRatio)\n\n return {\n translateX: newTranslateX,\n translateY: newTranslateY,\n }\n }\n\n const getMaxTranslationLimits = (currentScale: number) => {\n 'worklet'\n\n const { width: containedImageWidth, height: containedImageHeight } =\n getImageContainedToWindowDimensions()\n\n // Image dimensions after scaling/zooming\n const scaledWidth = containedImageWidth * currentScale\n const scaledHeight = containedImageHeight * currentScale\n\n // How much the scaled image exceeds the window container\n const excessWidth = scaledWidth - availableWindowWidth\n const excessHeight = scaledHeight - availableWindowHeight\n\n // How far the image can move in each direction before hitting window edges\n const maxTranslateX = Math.max(DEFAULT_TRANSLATE_X, excessWidth / 2)\n const maxTranslateY = Math.max(DEFAULT_TRANSLATE_Y, excessHeight / 2)\n\n return { maxTranslateX, maxTranslateY }\n }\n\n const clampDecay = (currentScale: number): { x: [number, number]; y: [number, number] } => {\n 'worklet'\n\n const { maxTranslateX, maxTranslateY } = getMaxTranslationLimits(currentScale)\n\n return {\n x: [-maxTranslateX, maxTranslateX],\n y: [-maxTranslateY, maxTranslateY],\n }\n }\n\n const clampTranslation = ({\n x,\n y,\n currentScale,\n }: {\n x: number\n y: number\n currentScale: number\n }) => {\n 'worklet'\n\n const { maxTranslateX, maxTranslateY } = getMaxTranslationLimits(currentScale)\n\n return {\n x: Math.min(maxTranslateX, Math.max(-maxTranslateX, x)),\n y: Math.min(maxTranslateY, Math.max(-maxTranslateY, y)),\n }\n }\n\n const isImageAtVerticalBoundry = (currentScale: number) => {\n 'worklet'\n\n const { height: containedImageHeight } = getImageContainedToWindowDimensions()\n\n // Calculate how much the image can exceed the window container\n const scaledHeight = containedImageHeight * currentScale\n const excessHeight = scaledHeight - availableWindowHeight\n const maxTranslateY = Math.max(DEFAULT_TRANSLATE_Y, excessHeight / 2)\n\n const currentTranslateY = translateY.value\n const panPositionTolerance = 1 // buffer to account for translateY being at a subpixel position\n\n const atTopBoundry = currentTranslateY >= maxTranslateY - panPositionTolerance\n const atBottomBoundry = currentTranslateY <= -maxTranslateY + panPositionTolerance\n\n return atTopBoundry || atBottomBoundry\n }\n\n /* ============================\n UTILITY FLATLIST FUNCTIONS\n Supports the image gallery layout and swipe functionality.\n ============================ */\n\n // Use refs to avoid re-rendering FlatList callbacks...\n const stableCurrentImageIndexRef = useRef(currentImageIndex)\n const stableImageAttachmentsLengthRef = useRef(imageAttachments.length)\n // ...while still ensuring they are updated with the latest values\n stableCurrentImageIndexRef.current = currentImageIndex\n stableImageAttachmentsLengthRef.current = imageAttachments.length\n\n // Used in tandem with FlatList's initialScrollIndex to quickly calculate the position and size of each image before they load.\n const getItemLayout = useCallback(\n (_: unknown, index: number) => ({\n length: WINDOW_WIDTH,\n offset: WINDOW_WIDTH * index,\n index,\n }),\n []\n )\n\n // Captures the current image's index after the FlatList finishes its scroll animation.\n // Used in tandem with onViewableItemsChanged to ensure the final value for currentImageIndex is set.\n const onMomentumScrollEnd = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {\n // Calculate the index of the image that is currently visible\n const imageOffsetX = event.nativeEvent.contentOffset.x\n const newImageIndex = Math.round(imageOffsetX / WINDOW_WIDTH)\n\n // Check if the image index has changed and the FlatList didn't scroll past the first or last image\n const didImageIndexChange = newImageIndex !== stableCurrentImageIndexRef.current\n const isImageIndexWithinBounds =\n newImageIndex >= 0 && newImageIndex < stableImageAttachmentsLengthRef.current\n\n if (didImageIndexChange && isImageIndexWithinBounds) {\n setCurrentImageIndex(newImageIndex)\n }\n }, [])\n\n // Supplements onMomentumScrollEnd by capturing the current image's index while the FlatList is actively scrolling.\n // Used in tandem with viewabilityConfig to trigger when the image is 50% visible in the window.\n const onViewableItemsChanged = useCallback(\n ({ viewableItems }: { viewableItems: ViewToken<DenormalizedMessageAttachmentResource>[] }) => {\n if (viewableItems.length === 0) return\n\n // Use the first viewable item which is enforced by the FlatList's pagingEnabled prop that allows only two images to be visible at a time when scrolling.\n const firstViewableItem = viewableItems[0]\n const newIndex = firstViewableItem.index\n\n if (newIndex !== null && newIndex !== stableCurrentImageIndexRef.current) {\n setCurrentImageIndex(newIndex)\n }\n },\n []\n )\n\n /* ============================\n GESTURES\n ============================ */\n const singleTapGesture = Gesture.Tap()\n .minPointers(SINGLE_FINGER_POINTER)\n .numberOfTaps(1)\n .onStart(() => {\n lightboxToolbarVisible.value = withSpring(\n lightboxToolbarVisible.value > 0.5 ? 0 : 1,\n RESET_SPRING_CONFIG\n )\n })\n\n const doubleTapGesture = Gesture.Tap()\n .minPointers(SINGLE_FINGER_POINTER)\n .numberOfTaps(2)\n .onStart(e => {\n const isZoomedIn = scale.value > DEFAULT_SCALE\n if (isZoomedIn) {\n runOnJS(resetAllGestures)()\n } else {\n // Hide toolbar when starting to zoom\n lightboxToolbarVisible.value = withSpring(0, RESET_SPRING_CONFIG)\n\n // Zoom to 2x at tap location\n const newTranslation = zoomToFocalPoint({\n focalPointX: e.x,\n focalPointY: e.y,\n targetScale: DOUBLE_TAP_ZOOM_SCALE,\n currentSavedScale: savedScale.value,\n currentSavedTranslateX: savedTranslateX.value,\n currentSavedTranslateY: savedTranslateY.value,\n })\n\n // Apply clamping to ensure image edges remain within window boundaries\n const clampedTranslate = clampTranslation({\n x: newTranslation.translateX,\n y: newTranslation.translateY,\n currentScale: DOUBLE_TAP_ZOOM_SCALE,\n })\n\n // Animate to new scale and translation\n scale.value = withSpring(DOUBLE_TAP_ZOOM_SCALE, RESET_SPRING_CONFIG)\n translateX.value = withSpring(clampedTranslate.x, RESET_SPRING_CONFIG)\n translateY.value = withSpring(clampedTranslate.y, RESET_SPRING_CONFIG)\n\n // Update saved state for next gesture\n savedScale.value = DOUBLE_TAP_ZOOM_SCALE\n savedTranslateX.value = clampedTranslate.x\n savedTranslateY.value = clampedTranslate.y\n\n // Disable FlatList scroll since image is now zoomed\n runOnJS(enableFlatListScroll)(false)\n }\n })\n\n const pinchGesture = Gesture.Pinch()\n .onStart(e => {\n focalX.value = e.focalX\n focalY.value = e.focalY\n\n // Hide toolbar when starting to zoom\n lightboxToolbarVisible.value = withSpring(0, RESET_SPRING_CONFIG)\n\n // Ensure that pinch accounts for the decay animation and starts from the true current position.\n savedTranslateX.value = translateX.value\n savedTranslateY.value = translateY.value\n })\n .onUpdate(e => {\n // Zoom image in/out within scale limits\n const newScale = savedScale.value * e.scale\n const newScaleClamped = Math.min(\n MAX_SCALE + MAX_SCALE_OVERSHOOT,\n Math.max(MIN_SCALE, newScale)\n )\n scale.value = newScaleClamped\n\n // Calculate new translation to keep focal point under fingers\n const newTranslation = zoomToFocalPoint({\n focalPointX: focalX.value,\n focalPointY: focalY.value,\n targetScale: newScaleClamped,\n currentSavedScale: savedScale.value,\n currentSavedTranslateX: savedTranslateX.value,\n currentSavedTranslateY: savedTranslateY.value,\n })\n\n // Apply translation without clamping to ensure focal point doesn't jump during gesture\n translateX.value = newTranslation.translateX\n translateY.value = newTranslation.translateY\n })\n .onEnd(() => {\n const currentScale = scale.value\n\n // Dismiss modal if fully zoomed out\n if (currentScale <= MIN_SCALE) {\n runOnJS(handleCloseModal)()\n return\n }\n\n // Reset all gestures if image is near default scale\n const isNearDefaultScale = currentScale <= DEFAULT_SCALE + 0.1\n if (isNearDefaultScale) {\n runOnJS(resetAllGestures)()\n return\n }\n\n // Check if overshooting the max scale and clamp it\n const finalScale = currentScale > MAX_SCALE ? MAX_SCALE : currentScale\n\n // Recalculate translation using focal point to always return to the same position when image is overshooting the max scale\n const newTranslation = zoomToFocalPoint({\n focalPointX: focalX.value,\n focalPointY: focalY.value,\n targetScale: finalScale,\n currentSavedScale: savedScale.value,\n currentSavedTranslateX: savedTranslateX.value,\n currentSavedTranslateY: savedTranslateY.value,\n })\n\n // Ensure image edges remain within window boundaries\n const clampedTranslate = clampTranslation({\n x: newTranslation.translateX,\n y: newTranslation.translateY,\n currentScale: finalScale,\n })\n\n // Animate to position and scale limits with a spring\n scale.value = withSpring(finalScale, RESET_SPRING_CONFIG)\n translateX.value = withSpring(clampedTranslate.x, RESET_SPRING_CONFIG)\n translateY.value = withSpring(clampedTranslate.y, RESET_SPRING_CONFIG)\n\n // Save state for next gesture\n savedScale.value = finalScale\n savedTranslateX.value = clampedTranslate.x\n savedTranslateY.value = clampedTranslate.y\n\n // Disable FlatList scroll since image is still zoomed\n runOnJS(enableFlatListScroll)(false)\n })\n\n const panGesture = Gesture.Pan()\n .minDistance(MIN_DISTANCE_FOR_PAN)\n .minPointers(SINGLE_FINGER_POINTER)\n .maxPointers(SINGLE_FINGER_POINTER)\n .onStart(() => {\n // Only start pan if image is zoomed in - prevents conflicts with FlatList\n if (scale.value <= DEFAULT_SCALE) return\n\n // Update saved position to current animated position\n // This ensures smooth continuation if decay is running\n savedTranslateX.value = translateX.value\n savedTranslateY.value = translateY.value\n })\n .onUpdate(e => {\n // Only pan if image is zoomed in - prevents conflicts with FlatList\n if (scale.value <= DEFAULT_SCALE) return\n\n const newTranslateX = savedTranslateX.value + e.translationX\n const newTranslateY = savedTranslateY.value + e.translationY\n\n // Ensure image edges remain within window boundaries\n const clampedTranslate = clampTranslation({\n x: newTranslateX,\n y: newTranslateY,\n currentScale: scale.value,\n })\n translateX.value = clampedTranslate.x\n translateY.value = clampedTranslate.y\n })\n .onEnd(e => {\n // Prevents saving pan position if image is zoomed out while panning\n if (scale.value <= DEFAULT_SCALE) return\n\n const clampDecayBounds = clampDecay(scale.value)\n\n translateX.value = withDecay(\n {\n velocity: e.velocityX * DECAY_VELOCITY_FACTOR,\n clamp: clampDecayBounds.x,\n deceleration: 0.996,\n },\n finished => {\n if (finished) {\n savedTranslateX.value = translateX.value\n }\n }\n )\n\n translateY.value = withDecay(\n {\n velocity: e.velocityY * DECAY_VELOCITY_FACTOR,\n clamp: clampDecayBounds.y,\n deceleration: 0.996,\n },\n finished => {\n if (finished) {\n savedTranslateY.value = translateY.value\n }\n }\n )\n })\n\n const panToDismissModalGesture = Gesture.Pan()\n .onUpdate(e => {\n const atDefaultScale = scale.value === DEFAULT_SCALE\n\n // Calculate zoom conditions for dismissing modal\n const atVerticalBoundry = isImageAtVerticalBoundry(scale.value)\n const panDirectionIsPrimarilyVertical = Math.abs(e.translationY) > Math.abs(e.translationX)\n const canDismissWhileZoomed = atVerticalBoundry && panDirectionIsPrimarilyVertical\n\n if (!(atDefaultScale || canDismissWhileZoomed)) return\n\n // Fade image if its been panned past 50% of the dismiss threshold\n const panDistance = Math.abs(e.translationY)\n const halfThreshold = DISMISS_PAN_THRESHOLD / 2\n const fadeDistance = Math.max(0, panDistance - halfThreshold)\n const fadeProgress = fadeDistance / halfThreshold\n\n opacity.value = Math.max(0, DEFAULT_OPACITY - fadeProgress)\n dismissY.value = e.translationY\n })\n .onEnd(() => {\n const exceededDismissThreshold = Math.abs(dismissY.value) > DISMISS_PAN_THRESHOLD\n\n if (exceededDismissThreshold) {\n runOnJS(handleCloseModal)()\n } else {\n runOnJS(resetDismissGestures)()\n }\n })\n\n /* ==============================\n COMPOSE GESTURES\n ================================= */\n // Race between pinch and pan ensures only one is active at a time, preserving focal point logic\n const pinchOrPanGestures = Gesture.Race(pinchGesture, panGesture)\n\n // Exclusive race ensures single tap doesn't interfere with double tap\n const tapGestures = Gesture.Exclusive(doubleTapGesture, singleTapGesture)\n\n // Race between tap gestures and pinch/pan\n const transformImageGestures = Gesture.Race(tapGestures, pinchOrPanGestures)\n\n // Dismiss can work simultaneously with all gestures\n const composedGesture = Gesture.Simultaneous(transformImageGestures, panToDismissModalGesture)\n\n return (\n <>\n <StatusBar\n barStyle=\"light-content\"\n hidden={isStatusBarHidden}\n animated\n showHideTransition=\"slide\"\n />\n <GestureHandlerRootView>\n <GestureDetector gesture={composedGesture}>\n <FlatList\n data={imageAttachments}\n renderItem={({ item, index }) => (\n <GestureImage\n item={item}\n gesturesEnabled={index === currentImageIndex}\n scale={scale}\n translateX={translateX}\n translateY={translateY}\n dismissY={dismissY}\n opacity={opacity}\n />\n )}\n keyExtractor={(item, index) => `${item.id}-${index}`}\n horizontal\n pagingEnabled\n scrollEnabled={flatListScrollEnabled}\n showsHorizontalScrollIndicator={false}\n initialScrollIndex={initialImageIndex}\n getItemLayout={getItemLayout}\n onMomentumScrollEnd={onMomentumScrollEnd}\n onViewableItemsChanged={onViewableItemsChanged}\n viewabilityConfig={{\n itemVisiblePercentThreshold: 50, // 50% of the image must be visible in the window to be considered viewable\n }}\n style={styles.gallery}\n contentContainerStyle={styles.galleryContentContainer}\n />\n </GestureDetector>\n </GestureHandlerRootView>\n <LightboxToolbarHeader\n metaProps={metaProps}\n lightboxToolbarVisible={lightboxToolbarVisible}\n isStatusBarHidden={isStatusBarHidden}\n handleOpenInBrowser={handleOpenInBrowser}\n handleCloseModal={handleCloseModal}\n />\n {imageAttachments.length > 1 && (\n <LightboxToolbarFooter\n lightboxToolbarVisible={lightboxToolbarVisible}\n totalImages={imageAttachments.length}\n currentImageIndex={currentImageIndex}\n />\n )}\n </>\n )\n}\n\ninterface GestureImageProps {\n item: DenormalizedMessageAttachmentResource\n gesturesEnabled: boolean\n scale: SharedValue<number>\n translateX: SharedValue<number>\n translateY: SharedValue<number>\n dismissY: SharedValue<number>\n opacity: SharedValue<number>\n}\n\nconst GestureImage = ({\n item,\n gesturesEnabled,\n scale,\n translateX,\n translateY,\n dismissY,\n opacity,\n}: GestureImageProps) => {\n const styles = useStyles()\n const { url: itemUrl, urlMedium: itemUrlMedium } = item.attributes\n\n const animatedImageStyles = useAnimatedStyle(() => {\n return {\n transform: [\n { translateX: gesturesEnabled ? translateX.value : DEFAULT_TRANSLATE_X },\n { translateY: gesturesEnabled ? translateY.value + dismissY.value : DEFAULT_TRANSLATE_Y },\n { scale: gesturesEnabled ? scale.value : DEFAULT_SCALE },\n ],\n opacity: opacity.value,\n }\n })\n\n return (\n <TouchEventIsolator>\n <Image\n source={{ uri: itemUrlMedium || itemUrl }}\n style={styles.gestureImage}\n animatedImageStyle={animatedImageStyles}\n loadingBackgroundStyles={styles.gestureImageLoading}\n resizeMode=\"contain\"\n alt=\"\"\n />\n </TouchEventIsolator>\n )\n}\n\nconst TouchEventIsolator = ({ children }: { children: React.ReactNode }) => {\n const styles = useStyles()\n\n return (\n <View style={styles.touchEventIsolator} onStartShouldSetResponder={() => true}>\n {children}\n </View>\n )\n}\n\ninterface LightboxToolbarHeaderProps {\n metaProps: MetaProps\n lightboxToolbarVisible: SharedValue<number>\n isStatusBarHidden: boolean\n handleOpenInBrowser: () => void\n handleCloseModal: () => void\n}\n\nconst LightboxToolbarHeader = ({\n metaProps,\n lightboxToolbarVisible,\n isStatusBarHidden,\n handleOpenInBrowser,\n handleCloseModal,\n}: LightboxToolbarHeaderProps) => {\n const styles = useStyles()\n const { authorName, createdAt } = metaProps\n\n const animatedHeaderStyles = useAnimatedStyle(() => ({\n opacity: lightboxToolbarVisible.value,\n transform: [\n { translateY: (1 - lightboxToolbarVisible.value) * -20 }, // slide up when hiding\n ],\n }))\n\n return (\n <Animated.View\n style={[styles.lightboxToolbar, styles.lightboxToolbarHeader, animatedHeaderStyles]}\n accessibilityRole=\"toolbar\"\n >\n <View style={styles.lightboxToolbarHeaderMetaContainer}>\n <Heading variant=\"h3\" style={styles.lightboxToolbarHeaderTitle} numberOfLines={1}>\n {authorName}\n </Heading>\n <Text variant=\"tertiary\" style={styles.lightboxToolbarHeaderSubtitle}>\n {formatDatePreview(createdAt)}\n </Text>\n </View>\n <IconButton\n onPress={handleOpenInBrowser}\n disabled={isStatusBarHidden}\n name=\"general.newWindow\"\n accessibilityRole=\"link\"\n accessibilityLabel=\"Open image in browser\"\n accessibilityHint=\"Image can be downloaded and shared through the browser.\"\n style={styles.lightboxToolbarButton}\n iconStyle={styles.lightboxToolbarButtonIcon}\n size=\"lg\"\n />\n <IconButton\n onPress={handleCloseModal}\n disabled={isStatusBarHidden}\n name=\"general.x\"\n accessibilityLabel=\"Close image\"\n style={styles.lightboxToolbarButton}\n iconStyle={styles.lightboxToolbarButtonIcon}\n size=\"lg\"\n />\n </Animated.View>\n )\n}\n\ninterface LightboxToolbarFooterProps {\n lightboxToolbarVisible: SharedValue<number>\n totalImages: number\n currentImageIndex: number\n}\n\nconst LightboxToolbarFooter = ({\n lightboxToolbarVisible,\n totalImages,\n currentImageIndex,\n}: LightboxToolbarFooterProps) => {\n const styles = useStyles()\n\n const animatedFooterStyles = useAnimatedStyle(() => ({\n opacity: lightboxToolbarVisible.value,\n transform: [\n { translateY: (1 - lightboxToolbarVisible.value) * 20 }, // slide down when showing\n ],\n }))\n\n return (\n <Animated.View\n style={[styles.lightboxToolbar, styles.lightboxToolbarFooter, animatedFooterStyles]}\n accessibilityRole=\"toolbar\"\n >\n <Text style={styles.lightboxToolbarFooterText}>\n {currentImageIndex + 1} of {totalImages}\n </Text>\n </Animated.View>\n )\n}\n\ninterface UseStylesProps {\n imageWidth?: number\n imageHeight?: number\n}\n\nconst useStyles = ({ imageWidth = 100, imageHeight = 100 }: UseStylesProps = {}) => {\n const { top, bottom } = useSafeAreaInsets()\n const backgroundColor = tokens.colorNeutral7\n const transparentBackgroundColor = useMemo(\n () => colorFunction(backgroundColor).alpha(0.8).toString(),\n [backgroundColor]\n )\n\n return StyleSheet.create({\n container: {\n maxWidth: '100%',\n },\n touchEventIsolator: {\n flex: 1,\n },\n attachmentImageWrapper: {\n width: '100%',\n minWidth: 200,\n aspectRatio: imageWidth / imageHeight,\n },\n image: {\n borderRadius: 8,\n },\n gallery: {\n backgroundColor,\n },\n galleryContentContainer: {\n paddingTop: top,\n paddingBottom: bottom,\n },\n gestureImage: {\n height: '100%',\n width: WINDOW_WIDTH,\n backgroundColor: 'transparent',\n },\n gestureImageLoading: {\n backgroundColor,\n },\n lightboxToolbar: {\n width: '100%',\n position: 'absolute',\n flexDirection: 'row',\n alignItems: 'center',\n gap: 20,\n paddingHorizontal: 16,\n backgroundColor: transparentBackgroundColor,\n },\n lightboxToolbarButton: {\n backgroundColor,\n height: 40,\n width: 40,\n borderRadius: 50,\n borderWidth: 1,\n borderColor: tokens.colorNeutral24,\n },\n lightboxToolbarButtonIcon: {\n color: tokens.colorNeutral88,\n },\n lightboxToolbarHeader: {\n top: 0,\n paddingTop: top + 16,\n paddingBottom: 8,\n },\n lightboxToolbarHeaderMetaContainer: {\n flex: 1,\n },\n lightboxToolbarHeaderTitle: {\n marginRight: 'auto',\n flexShrink: 1,\n color: tokens.colorNeutral88,\n },\n lightboxToolbarHeaderSubtitle: {\n color: tokens.colorNeutral68,\n },\n lightboxToolbarFooter: {\n justifyContent: 'center',\n bottom: 0,\n paddingTop: 8,\n paddingBottom: bottom + 16,\n },\n lightboxToolbarFooterText: {\n color: tokens.colorNeutral88,\n fontWeight: platformFontWeightMedium,\n },\n })\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.12.2
|
|
3
|
+
"version": "3.12.2",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -55,5 +55,5 @@
|
|
|
55
55
|
"react-native-url-polyfill": "^2.0.0",
|
|
56
56
|
"typescript": "<5.6.0"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "bc21db666c21fbbf7e654776bb40d4ec15e5ba6b"
|
|
59
59
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
NativeScrollEvent,
|
|
11
11
|
ViewToken,
|
|
12
12
|
} from 'react-native'
|
|
13
|
-
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
13
|
+
import { useSafeAreaInsets, SafeAreaProvider } from 'react-native-safe-area-context'
|
|
14
14
|
import {
|
|
15
15
|
FlatList,
|
|
16
16
|
Gesture,
|
|
@@ -128,6 +128,36 @@ const LightboxModal = ({
|
|
|
128
128
|
initialImageIndex,
|
|
129
129
|
metaProps,
|
|
130
130
|
}: LightboxModalProps) => {
|
|
131
|
+
const onRequestClose = useCallback(() => {
|
|
132
|
+
setModalVisible(false)
|
|
133
|
+
}, [setModalVisible])
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<Modal visible={visible} transparent animationType="fade" onRequestClose={onRequestClose}>
|
|
137
|
+
<SafeAreaProvider>
|
|
138
|
+
<LightboxGallery
|
|
139
|
+
imageAttachments={imageAttachments}
|
|
140
|
+
initialImageIndex={initialImageIndex}
|
|
141
|
+
metaProps={metaProps}
|
|
142
|
+
onRequestClose={onRequestClose}
|
|
143
|
+
/>
|
|
144
|
+
</SafeAreaProvider>
|
|
145
|
+
</Modal>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface LightboxGalleryProps {
|
|
150
|
+
imageAttachments: DenormalizedMessageAttachmentResource[]
|
|
151
|
+
initialImageIndex: number
|
|
152
|
+
metaProps: MetaProps
|
|
153
|
+
onRequestClose: () => void
|
|
154
|
+
}
|
|
155
|
+
const LightboxGallery = ({
|
|
156
|
+
imageAttachments,
|
|
157
|
+
initialImageIndex,
|
|
158
|
+
metaProps,
|
|
159
|
+
onRequestClose,
|
|
160
|
+
}: LightboxGalleryProps) => {
|
|
131
161
|
const styles = useStyles()
|
|
132
162
|
const insets = useSafeAreaInsets()
|
|
133
163
|
const [currentImageIndex, setCurrentImageIndex] = useState(initialImageIndex)
|
|
@@ -210,9 +240,9 @@ const LightboxModal = ({
|
|
|
210
240
|
])
|
|
211
241
|
|
|
212
242
|
const handleCloseModal = useCallback(() => {
|
|
213
|
-
|
|
243
|
+
onRequestClose()
|
|
214
244
|
resetAllGestures()
|
|
215
|
-
}, [
|
|
245
|
+
}, [onRequestClose, resetAllGestures])
|
|
216
246
|
|
|
217
247
|
/* ============================
|
|
218
248
|
UTILITY WORKLET FUNCTIONS
|
|
@@ -654,7 +684,7 @@ const LightboxModal = ({
|
|
|
654
684
|
const composedGesture = Gesture.Simultaneous(transformImageGestures, panToDismissModalGesture)
|
|
655
685
|
|
|
656
686
|
return (
|
|
657
|
-
|
|
687
|
+
<>
|
|
658
688
|
<StatusBar
|
|
659
689
|
barStyle="light-content"
|
|
660
690
|
hidden={isStatusBarHidden}
|
|
@@ -707,7 +737,7 @@ const LightboxModal = ({
|
|
|
707
737
|
currentImageIndex={currentImageIndex}
|
|
708
738
|
/>
|
|
709
739
|
)}
|
|
710
|
-
|
|
740
|
+
</>
|
|
711
741
|
)
|
|
712
742
|
}
|
|
713
743
|
|