Pass thumbnail ref through peek commit so lightbox return animates

The lightbox's close animation needs the original thumbnail ref/dims to know
where to animate back to. The peek-commit path was passing null, so the
lightbox dropped to a fade instead of the usual return-to-thumb animation.

Rework each embed path so the tap handler and the peek-commit handler
invoke the same openLightbox call with the same ref + dims:

- Grid and scrollable Gallery: derive `openLightboxAtIndex` once per cell
  and hand it to both Pressable.onPress and ContextMenu.onPreviewPress.
- Single image: add onContainerRef / onDimsChange callbacks to
  AutoSizedImage, capture them in ImageEmbed, and use them for the peek
  commit. Drops the now-redundant onPreviewPress prop chain.

https://claude.ai/code/session_015REmux3R9uuEMMJUHxTyQT
This commit is contained in:
Claude
2026-04-19 08:38:13 +00:00
committed by Samuel Newman
parent 1856c36221
commit 723b20bfce
5 changed files with 59 additions and 52 deletions
+18 -15
View File
@@ -1,3 +1,4 @@
import {useRef} from 'react'
import {InteractionManager, View} from 'react-native'
import {type AnimatedRef} from 'react-native-reanimated'
import {Image} from 'expo-image'
@@ -25,6 +26,11 @@ export function ImageEmbed({
const {images} = embed.view
const galleryEnabled = ax.features.enabled(ax.features.PostGalleryEmbedEnable)
// Captured from AutoSizedImage so the peek-commit handler can reuse the same
// ref + dims that a tap would — keeps the lightbox's return animation intact.
const singleContainerRef = useRef<AnimatedRef<any> | null>(null)
const singleDimsRef = useRef<Dimensions | null>(null)
if (images.length > 0) {
const items = images.map(img => ({
uri: img.fullsize,
@@ -57,18 +63,6 @@ export function ImageEmbed({
)
})
}
const onPreviewPress = (index: number) =>
openLightbox({
images: items.map(item => ({
...item,
thumbRect: null,
thumbRef: null,
thumbDimensions: null,
thumbBorderRadius: tokens.borderRadius.md,
type: 'image',
})),
index,
})
if (images.length === 1) {
const image = images[0]
@@ -76,6 +70,11 @@ export function ImageEmbed({
image.aspectRatio && image.aspectRatio.height > 0
? image.aspectRatio.width / image.aspectRatio.height
: undefined
const openFromSingle = () => {
if (singleContainerRef.current) {
onPress(0, [singleContainerRef.current], [singleDimsRef.current])
}
}
return (
<View style={[a.mt_sm, rest.style]}>
<ImageContextMenu
@@ -83,7 +82,7 @@ export function ImageEmbed({
thumbUri={image.thumb}
aspectRatio={aspect}
borderRadius={tokens.borderRadius.md}
onPreviewPress={() => onPreviewPress(0)}>
onPreviewPress={openFromSingle}>
<AutoSizedImage
crop={
rest.viewContext === PostEmbedViewContext.ThreadHighlighted
@@ -94,6 +93,12 @@ export function ImageEmbed({
: 'constrained'
}
image={image}
onContainerRef={ref => {
singleContainerRef.current = ref
}}
onDimsChange={dims => {
singleDimsRef.current = dims
}}
onPress={(containerRef, dims) =>
onPress(0, [containerRef], [dims])
}
@@ -115,7 +120,6 @@ export function ImageEmbed({
images={images}
onPress={onPress}
onPressIn={onPressIn}
onPreviewPress={onPreviewPress}
viewContext={rest.viewContext}
/>
</View>
@@ -128,7 +132,6 @@ export function ImageEmbed({
images={images}
onPress={onPress}
onPressIn={onPressIn}
onPreviewPress={onPreviewPress}
viewContext={rest.viewContext}
/>
</View>