Hook up lightbox

This commit is contained in:
Eric Bailey
2026-04-14 15:59:01 -05:00
parent 2c579e5308
commit 3b91d9612d
+67 -21
View File
@@ -10,7 +10,7 @@ import {
import {FlatList, Pressable, useWindowDimensions, View} from 'react-native' import {FlatList, Pressable, useWindowDimensions, View} from 'react-native'
import {DrawerGestureContext} from 'react-native-drawer-layout' import {DrawerGestureContext} from 'react-native-drawer-layout'
import {Gesture, GestureDetector} from 'react-native-gesture-handler' import {Gesture, GestureDetector} from 'react-native-gesture-handler'
import {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated' import Animated, {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated'
import {Image} from 'expo-image' import {Image} from 'expo-image'
import {type AppBskyEmbedImages} from '@atproto/api' import {type AppBskyEmbedImages} from '@atproto/api'
import {utils} from '@bsky.app/alf' import {utils} from '@bsky.app/alf'
@@ -132,6 +132,8 @@ export function Gallery({
const flatListRef = useRef<FlatList>(null) const flatListRef = useRef<FlatList>(null)
const itemWidthsRef = useRef<Map<number, number>>(new Map()) const itemWidthsRef = useRef<Map<number, number>>(new Map())
const itemRefsRef = useRef<Map<number, View>>(new Map()) const itemRefsRef = useRef<Map<number, View>>(new Map())
const containerRefsRef = useRef<Map<number, AnimatedRef<any>>>(new Map())
const thumbDimsRef = useRef<Map<number, Dimensions>>(new Map())
const currentIndexRef = useRef(0) const currentIndexRef = useRef(0)
const setCurrentIndex = (index: number) => { const setCurrentIndex = (index: number) => {
@@ -215,6 +217,30 @@ export function Gallery({
itemRefsRef.current.delete(index) itemRefsRef.current.delete(index)
} }
}} }}
onContainerRef={(i, ref) => {
containerRefsRef.current.set(i, ref)
}}
onThumbDims={(i, dims) => {
thumbDimsRef.current.set(i, dims)
}}
onPress={
onPress
? () => {
ax.metric('post:gallery:openLightbox', {
imageIndex: index,
totalImages: images.length,
})
const refs: AnimatedRef<any>[] = []
const dims: (Dimensions | null)[] = []
for (let i = 0; i < images.length; i++) {
refs.push(containerRefsRef.current.get(i)!)
dims.push(thumbDimsRef.current.get(i) ?? null)
}
onPress(index, refs, dims)
}
: undefined
}
onPressIn={onPressIn ? () => onPressIn(index) : undefined}
/> />
) )
}} }}
@@ -283,42 +309,62 @@ function GalleryImage({
index, index,
onWidthChange, onWidthChange,
itemRef, itemRef,
onContainerRef,
onThumbDims,
onPress,
onPressIn,
}: { }: {
contentHeight: number contentHeight: number
image: AppBskyEmbedImages.ViewImage image: AppBskyEmbedImages.ViewImage
index: number index: number
onWidthChange: (index: number, width: number) => void onWidthChange: (index: number, width: number) => void
itemRef: (node: View | null) => void itemRef: (node: View | null) => void
onContainerRef: (index: number, ref: AnimatedRef<any>) => void
onThumbDims: (index: number, dims: Dimensions) => void
onPress?: () => void
onPressIn?: () => void
}) { }) {
const t = useTheme() const t = useTheme()
const containerRef = useAnimatedRef()
const [aspectRatio, setAspectRatio] = useState(() => const [aspectRatio, setAspectRatio] = useState(() =>
getAspectRatio(image.aspectRatio), getAspectRatio(image.aspectRatio),
) )
const dims = computeDims({height, aspectRatio}) const dims = computeDims({height, aspectRatio})
onWidthChange(index, dims.width) onWidthChange(index, dims.width)
onContainerRef(index, containerRef)
return ( return (
<Pressable <Animated.View ref={containerRef} collapsable={false}>
ref={itemRef} <Pressable
style={[a.rounded_md, a.overflow_hidden, t.atoms.bg_contrast_25]}> ref={itemRef}
<Image onPress={onPress}
source={{uri: image.thumb}} onPressIn={onPressIn}
contentFit="cover" accessibilityRole="button"
accessible={true} accessibilityLabel={image.alt || undefined}
accessibilityLabel={image.alt}
accessibilityHint="" accessibilityHint=""
accessibilityIgnoresInvertColors style={[a.rounded_md, a.overflow_hidden, t.atoms.bg_contrast_25]}>
loading="eager" <Image
// loading={index === 0 ? 'eager' : 'lazy'} source={{uri: image.thumb}}
style={[dims]} contentFit="cover"
onLoad={e => { accessible={true}
const ar = getAspectRatio(e.source) accessibilityLabel={image.alt}
if (ar && ar !== aspectRatio) { accessibilityHint=""
setAspectRatio(ar) accessibilityIgnoresInvertColors
} loading="eager"
}} style={[dims]}
/> onLoad={e => {
</Pressable> const ar = getAspectRatio(e.source)
if (ar && ar !== aspectRatio) {
setAspectRatio(ar)
}
onThumbDims(index, {
width: e.source.width,
height: e.source.height,
})
}}
/>
</Pressable>
</Animated.View>
) )
} }