diff options
author | dan <dan.abramov@gmail.com> | 2024-11-09 22:41:14 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-09 22:41:14 +0000 |
commit | 42abd97f61b6813ab7dc6126d167b4130532326a (patch) | |
tree | ed027d346a27170ce60862cbd6849bbc63302157 | |
parent | 2d73c5a24cf8ad06dbebcf44c8f4f053eedda5a4 (diff) | |
download | voidsky-42abd97f61b6813ab7dc6126d167b4130532326a.tar.zst |
[Lightbox] Always rely on Expo Image cache (#6189)
* Inline useImageAspectRatio * Switch AutoSizedImage to read dimensions from Expo Image cache * Include thumbnail dimensions in image data * Use dims from Expo Image cache in lightbox * Fix wiring so all thumbnails get dimensions * Fix type * Oops
-rw-r--r-- | src/lib/media/image-sizes.ts | 93 | ||||
-rw-r--r-- | src/screens/Profile/Header/Shell.tsx | 1 | ||||
-rw-r--r-- | src/view/com/lightbox/ImageViewing/@types/index.ts | 3 | ||||
-rw-r--r-- | src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx | 10 | ||||
-rw-r--r-- | src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx | 13 | ||||
-rw-r--r-- | src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.tsx | 2 | ||||
-rw-r--r-- | src/view/com/lightbox/ImageViewing/index.tsx | 22 | ||||
-rw-r--r-- | src/view/com/profile/ProfileSubpageHeader.tsx | 1 | ||||
-rw-r--r-- | src/view/com/util/images/AutoSizedImage.tsx | 67 | ||||
-rw-r--r-- | src/view/com/util/images/Gallery.tsx | 16 | ||||
-rw-r--r-- | src/view/com/util/images/ImageLayoutGrid.tsx | 13 | ||||
-rw-r--r-- | src/view/com/util/post-embeds/index.tsx | 10 |
12 files changed, 105 insertions, 146 deletions
diff --git a/src/lib/media/image-sizes.ts b/src/lib/media/image-sizes.ts deleted file mode 100644 index 8eaa9467f..000000000 --- a/src/lib/media/image-sizes.ts +++ /dev/null @@ -1,93 +0,0 @@ -import {useEffect, useState} from 'react' -import {Image} from 'react-native' - -import type {Dimensions} from '#/lib/media/types' - -type CacheStorageItem<T> = {key: string; value: T} -const createCache = <T>(cacheSize: number) => ({ - _storage: [] as CacheStorageItem<T>[], - get(key: string) { - const {value} = - this._storage.find(({key: storageKey}) => storageKey === key) || {} - return value - }, - set(key: string, value: T) { - if (this._storage.length >= cacheSize) { - this._storage.shift() - } - this._storage.push({key, value}) - }, -}) - -const sizes = createCache<Dimensions>(50) -const activeRequests: Map<string, Promise<Dimensions>> = new Map() - -export function get(uri: string): Dimensions | undefined { - return sizes.get(uri) -} - -export function fetch(uri: string): Promise<Dimensions> { - const dims = sizes.get(uri) - if (dims) { - return Promise.resolve(dims) - } - const activeRequest = activeRequests.get(uri) - if (activeRequest) { - return activeRequest - } - const prom = new Promise<Dimensions>((resolve, reject) => { - Image.getSize( - uri, - (width: number, height: number) => { - const size = {width, height} - sizes.set(uri, size) - resolve(size) - }, - (err: any) => { - console.error('Failed to fetch image dimensions for', uri, err) - reject(new Error('Could not fetch dimensions')) - }, - ) - }).finally(() => { - activeRequests.delete(uri) - }) - activeRequests.set(uri, prom) - return prom -} - -export function useImageDimensions({ - src, - knownDimensions, -}: { - src: string - knownDimensions: Dimensions | null -}): [number | undefined, Dimensions | undefined] { - const [dims, setDims] = useState(() => knownDimensions ?? get(src)) - const [prevSrc, setPrevSrc] = useState(src) - if (src !== prevSrc) { - setDims(knownDimensions ?? get(src)) - setPrevSrc(src) - } - - useEffect(() => { - let aborted = false - if (dims !== undefined) return - fetch(src).then(newDims => { - if (aborted) return - setDims(newDims) - }) - return () => { - aborted = true - } - }, [dims, setDims, src]) - - let aspectRatio: number | undefined - if (dims) { - aspectRatio = dims.width / dims.height - if (Number.isNaN(aspectRatio)) { - aspectRatio = undefined - } - } - - return [aspectRatio, dims] -} diff --git a/src/screens/Profile/Header/Shell.tsx b/src/screens/Profile/Header/Shell.tsx index 093b9190a..1a1e7d4a2 100644 --- a/src/screens/Profile/Header/Shell.tsx +++ b/src/screens/Profile/Header/Shell.tsx @@ -72,6 +72,7 @@ let ProfileHeaderShell = ({ height: 1000, width: 1000, }, + thumbDimensions: null, type: 'circle-avi', }, ], diff --git a/src/view/com/lightbox/ImageViewing/@types/index.ts b/src/view/com/lightbox/ImageViewing/@types/index.ts index 1a3543c26..779b95bfc 100644 --- a/src/view/com/lightbox/ImageViewing/@types/index.ts +++ b/src/view/com/lightbox/ImageViewing/@types/index.ts @@ -21,10 +21,11 @@ export type Position = { export type ImageSource = { uri: string + dimensions: Dimensions | null thumbUri: string + thumbDimensions: Dimensions | null thumbRect: MeasuredDimensions | null alt?: string - dimensions: Dimensions | null type: 'image' | 'circle-avi' | 'rect-avi' } diff --git a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx index 069f9eb40..4652cb606 100644 --- a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx +++ b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx @@ -41,6 +41,7 @@ type Props = { onRequestClose: () => void onTap: () => void onZoom: (isZoomed: boolean) => void + onLoad: (dims: ImageDimensions) => void isScrollViewBeingDragged: boolean showControls: boolean measureSafeArea: () => { @@ -66,6 +67,7 @@ const ImageItem = ({ imageSrc, onTap, onZoom, + onLoad, isScrollViewBeingDragged, measureSafeArea, imageAspect, @@ -330,8 +332,8 @@ const ImageItem = ({ transform: scaleAndMoveTransform.concat(manipulationTransform), width: screenSize.width, maxHeight: screenSize.height, - aspectRatio: imageAspect, alignSelf: 'center', + aspectRatio: imageAspect ?? 1 /* force onLoad */, } }) @@ -349,6 +351,7 @@ const ImageItem = ({ return { flex: 1, transform: cropContentTransform, + opacity: imageAspect === undefined ? 0 : 1, } }) @@ -393,7 +396,10 @@ const ImageItem = ({ placeholderContentFit="cover" placeholder={{uri: imageSrc.thumbUri}} accessibilityLabel={imageSrc.alt} - onLoad={() => setHasLoaded(false)} + onLoad={e => { + setHasLoaded(true) + onLoad({width: e.source.width, height: e.source.height}) + }} style={{flex: 1, borderRadius}} accessibilityHint="" accessibilityIgnoresInvertColors diff --git a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx index 7a9a18b91..e6ec64c3d 100644 --- a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx +++ b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx @@ -38,6 +38,7 @@ type Props = { onRequestClose: () => void onTap: () => void onZoom: (scaled: boolean) => void + onLoad: (dims: ImageDimensions) => void isScrollViewBeingDragged: boolean showControls: boolean measureSafeArea: () => { @@ -64,6 +65,7 @@ const ImageItem = ({ imageSrc, onTap, onZoom, + onLoad, showControls, measureSafeArea, imageAspect, @@ -162,8 +164,9 @@ const ImageItem = ({ transform: cropFrameTransform, width: screenSize.width, maxHeight: screenSize.height, - aspectRatio: imageAspect, alignSelf: 'center', + aspectRatio: imageAspect ?? 1 /* force onLoad */, + opacity: imageAspect === undefined ? 0 : 1, } }) @@ -172,7 +175,8 @@ const ImageItem = ({ return { transform: cropContentTransform, width: '100%', - aspectRatio: imageAspect, + aspectRatio: imageAspect ?? 1 /* force onLoad */, + opacity: imageAspect === undefined ? 0 : 1, } }) @@ -224,7 +228,10 @@ const ImageItem = ({ accessibilityHint="" enableLiveTextInteraction={showControls && !scaled} accessibilityIgnoresInvertColors - onLoad={() => setHasLoaded(true)} + onLoad={e => { + setHasLoaded(true) + onLoad({width: e.source.width, height: e.source.height}) + }} /> </Animated.View> </Animated.View> diff --git a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.tsx b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.tsx index 543fad772..b41e16383 100644 --- a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.tsx +++ b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.tsx @@ -5,6 +5,7 @@ import {View} from 'react-native' import {PanGesture} from 'react-native-gesture-handler' import {SharedValue} from 'react-native-reanimated' +import {Dimensions} from '#/lib/media/types' import { Dimensions as ImageDimensions, ImageSource, @@ -16,6 +17,7 @@ type Props = { onRequestClose: () => void onTap: () => void onZoom: (scaled: boolean) => void + onLoad: (dims: Dimensions) => void isScrollViewBeingDragged: boolean showControls: boolean measureSafeArea: () => { diff --git a/src/view/com/lightbox/ImageViewing/index.tsx b/src/view/com/lightbox/ImageViewing/index.tsx index 030c8dcf3..ab8306b36 100644 --- a/src/view/com/lightbox/ImageViewing/index.tsx +++ b/src/view/com/lightbox/ImageViewing/index.tsx @@ -42,7 +42,7 @@ import { import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {Trans} from '@lingui/macro' -import {useImageDimensions} from '#/lib/media/image-sizes' +import {Dimensions} from '#/lib/media/types' import {colors, s} from '#/lib/styles' import {isIOS} from '#/platform/detection' import {Lightbox} from '#/state/lightbox' @@ -92,7 +92,9 @@ export default function ImageViewRoot({ const canAnimate = !PlatformInfo.getIsReducedMotionEnabled() && - nextLightbox.images.every(img => img.dimensions && img.thumbRect) + nextLightbox.images.every( + img => img.thumbRect && (img.dimensions || img.thumbDimensions), + ) // https://github.com/software-mansion/react-native-reanimated/issues/6677 requestAnimationFrame(() => { @@ -345,10 +347,15 @@ function LightboxImage({ openProgress: SharedValue<number> dismissSwipeTranslateY: SharedValue<number> }) { - const [imageAspect, imageDimensions] = useImageDimensions({ - src: imageSrc.uri, - knownDimensions: imageSrc.dimensions, - }) + const [fetchedDims, setFetchedDims] = React.useState<Dimensions | null>(null) + const dims = fetchedDims ?? imageSrc.dimensions ?? imageSrc.thumbDimensions + let imageAspect: number | undefined + if (dims) { + imageAspect = dims.width / dims.height + if (Number.isNaN(imageAspect)) { + imageAspect = undefined + } + } const safeFrameDelayedForJSThreadOnly = useSafeAreaFrame() const safeInsetsDelayedForJSThreadOnly = useSafeAreaInsets() @@ -452,11 +459,12 @@ function LightboxImage({ onTap={onTap} onZoom={onZoom} onRequestClose={onRequestClose} + onLoad={setFetchedDims} isScrollViewBeingDragged={isScrollViewBeingDragged} showControls={showControls} measureSafeArea={measureSafeArea} imageAspect={imageAspect} - imageDimensions={imageDimensions} + imageDimensions={dims ?? undefined} dismissSwipePan={dismissSwipePan} transforms={transforms} /> diff --git a/src/view/com/profile/ProfileSubpageHeader.tsx b/src/view/com/profile/ProfileSubpageHeader.tsx index 13d14ec50..d73b322f2 100644 --- a/src/view/com/profile/ProfileSubpageHeader.tsx +++ b/src/view/com/profile/ProfileSubpageHeader.tsx @@ -87,6 +87,7 @@ export function ProfileSubpageHeader({ height: 1000, width: 1000, }, + thumbDimensions: null, type: 'rect-avi', }, ], diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx index 21f6c529e..c26df8335 100644 --- a/src/view/com/util/images/AutoSizedImage.tsx +++ b/src/view/com/util/images/AutoSizedImage.tsx @@ -6,8 +6,7 @@ import {AppBskyEmbedImages} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' -import {useImageDimensions} from '#/lib/media/image-sizes' -import {Dimensions} from '#/lib/media/types' +import type {Dimensions} from '#/lib/media/types' import {isNative} from '#/platform/detection' import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' import {atoms as a, useBreakpoints, useTheme} from '#/alf' @@ -15,30 +14,6 @@ import {ArrowsDiagonalOut_Stroke2_Corner0_Rounded as Fullscreen} from '#/compone import {MediaInsetBorder} from '#/components/MediaInsetBorder' import {Text} from '#/components/Typography' -function useImageAspectRatio({ - src, - knownDimensions, -}: { - src: string - knownDimensions: Dimensions | null -}) { - const [raw] = useImageDimensions({src, knownDimensions}) - let constrained: number | undefined - let max: number | undefined - let isCropped: boolean | undefined - if (raw !== undefined) { - const ratio = 1 / 2 // max of 1:2 ratio in feeds - constrained = Math.max(raw, ratio) - max = Math.max(raw, 0.25) // max of 1:4 in thread - isCropped = raw < constrained - } - return { - constrained, - max, - isCropped, - } -} - export function ConstrainedImage({ aspectRatio, fullBleed, @@ -93,23 +68,38 @@ export function AutoSizedImage({ image: AppBskyEmbedImages.ViewImage crop?: 'none' | 'square' | 'constrained' hideBadge?: boolean - onPress?: (containerRef: AnimatedRef<React.Component<{}, {}, any>>) => void + onPress?: ( + containerRef: AnimatedRef<React.Component<{}, {}, any>>, + fetchedDims: Dimensions | null, + ) => void onLongPress?: () => void onPressIn?: () => void }) { const t = useTheme() const {_} = useLingui() const largeAlt = useLargeAltBadgeEnabled() - const { - constrained, - max, - isCropped: rawIsCropped, - } = useImageAspectRatio({ - src: image.thumb, - knownDimensions: image.aspectRatio ?? null, - }) const containerRef = useAnimatedRef() + const [fetchedDims, setFetchedDims] = React.useState<Dimensions | null>(null) + const dims = fetchedDims ?? image.aspectRatio + let aspectRatio: number | undefined + if (dims) { + aspectRatio = dims.width / dims.height + if (Number.isNaN(aspectRatio)) { + aspectRatio = undefined + } + } + + let constrained: number | undefined + let max: number | undefined + let rawIsCropped: boolean | undefined + if (aspectRatio !== undefined) { + const ratio = 1 / 2 // max of 1:2 ratio in feeds + constrained = Math.max(aspectRatio, ratio) + max = Math.max(aspectRatio, 0.25) // max of 1:4 in thread + rawIsCropped = aspectRatio < constrained + } + const cropDisabled = crop === 'none' const isCropped = rawIsCropped && !cropDisabled const hasAlt = !!image.alt @@ -123,6 +113,9 @@ export function AutoSizedImage({ accessibilityIgnoresInvertColors accessibilityLabel={image.alt} accessibilityHint="" + onLoad={e => { + setFetchedDims({width: e.source.width, height: e.source.height}) + }} /> <MediaInsetBorder /> @@ -194,7 +187,7 @@ export function AutoSizedImage({ if (cropDisabled) { return ( <Pressable - onPress={() => onPress?.(containerRef)} + onPress={() => onPress?.(containerRef, fetchedDims)} onLongPress={onLongPress} onPressIn={onPressIn} // alt here is what screen readers actually use @@ -216,7 +209,7 @@ export function AutoSizedImage({ fullBleed={crop === 'square'} aspectRatio={constrained ?? 1}> <Pressable - onPress={() => onPress?.(containerRef)} + onPress={() => onPress?.(containerRef, fetchedDims)} onLongPress={onLongPress} onPressIn={onPressIn} // alt here is what screen readers actually use diff --git a/src/view/com/util/images/Gallery.tsx b/src/view/com/util/images/Gallery.tsx index 0c691ec9a..9d0817bd2 100644 --- a/src/view/com/util/images/Gallery.tsx +++ b/src/view/com/util/images/Gallery.tsx @@ -6,6 +6,7 @@ import {AppBskyEmbedImages} from '@atproto/api' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' +import {Dimensions} from '#/lib/media/types' import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types' import {atoms as a, useTheme} from '#/alf' @@ -20,6 +21,7 @@ interface Props { onPress?: ( index: number, containerRefs: AnimatedRef<React.Component<{}, {}, any>>[], + fetchedDims: (Dimensions | null)[], ) => void onLongPress?: EventFunction onPressIn?: EventFunction @@ -27,6 +29,7 @@ interface Props { viewContext?: PostEmbedViewContext insetBorderStyle?: StyleProp<ViewStyle> containerRefs: AnimatedRef<React.Component<{}, {}, any>>[] + thumbDimsRef: React.MutableRefObject<(Dimensions | null)[]> } export function GalleryItem({ @@ -39,6 +42,7 @@ export function GalleryItem({ viewContext, insetBorderStyle, containerRefs, + thumbDimsRef, }: Props) { const t = useTheme() const {_} = useLingui() @@ -53,7 +57,11 @@ export function GalleryItem({ ref={containerRefs[index]} collapsable={false}> <Pressable - onPress={onPress ? () => onPress(index, containerRefs) : undefined} + onPress={ + onPress + ? () => onPress(index, containerRefs, thumbDimsRef.current.slice()) + : undefined + } onPressIn={onPressIn ? () => onPressIn(index) : undefined} onLongPress={onLongPress ? () => onLongPress(index) : undefined} style={[ @@ -72,6 +80,12 @@ export function GalleryItem({ accessibilityLabel={image.alt} accessibilityHint="" accessibilityIgnoresInvertColors + onLoad={e => { + thumbDimsRef.current[index] = { + width: e.source.width, + height: e.source.height, + } + }} /> <MediaInsetBorder style={insetBorderStyle} /> </Pressable> diff --git a/src/view/com/util/images/ImageLayoutGrid.tsx b/src/view/com/util/images/ImageLayoutGrid.tsx index b9b966302..dcc330dac 100644 --- a/src/view/com/util/images/ImageLayoutGrid.tsx +++ b/src/view/com/util/images/ImageLayoutGrid.tsx @@ -5,6 +5,7 @@ import {AppBskyEmbedImages} from '@atproto/api' import {PostEmbedViewContext} from '#/view/com/util/post-embeds/types' import {atoms as a, useBreakpoints} from '#/alf' +import {Dimensions} from '../../lightbox/ImageViewing/@types' import {GalleryItem} from './Gallery' interface ImageLayoutGridProps { @@ -12,6 +13,7 @@ interface ImageLayoutGridProps { onPress?: ( index: number, containerRefs: AnimatedRef<React.Component<{}, {}, any>>[], + fetchedDims: (Dimensions | null)[], ) => void onLongPress?: (index: number) => void onPressIn?: (index: number) => void @@ -42,6 +44,7 @@ interface ImageLayoutGridInnerProps { onPress?: ( index: number, containerRefs: AnimatedRef<React.Component<{}, {}, any>>[], + fetchedDims: (Dimensions | null)[], ) => void onLongPress?: (index: number) => void onPressIn?: (index: number) => void @@ -57,6 +60,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { const containerRef2 = useAnimatedRef() const containerRef3 = useAnimatedRef() const containerRef4 = useAnimatedRef() + const thumbDimsRef = React.useRef<(Dimensions | null)[]>([]) switch (count) { case 2: { @@ -69,6 +73,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { index={0} insetBorderStyle={noCorners(['topRight', 'bottomRight'])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> <View style={[a.flex_1, {aspectRatio: 1}]}> @@ -77,6 +82,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { index={1} insetBorderStyle={noCorners(['topLeft', 'bottomLeft'])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> </View> @@ -93,6 +99,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { index={0} insetBorderStyle={noCorners(['topRight', 'bottomRight'])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> <View style={[a.flex_1, {aspectRatio: 1}, gap]}> @@ -106,6 +113,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 'bottomRight', ])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> <View style={[a.flex_1]}> @@ -118,6 +126,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 'topRight', ])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> </View> @@ -145,6 +154,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 'bottomRight', ])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> <View style={[a.flex_1, {aspectRatio: 1.5}]}> @@ -157,6 +167,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 'bottomRight', ])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> </View> @@ -171,6 +182,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 'bottomRight', ])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> <View style={[a.flex_1, {aspectRatio: 1.5}]}> @@ -183,6 +195,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 'topRight', ])} containerRefs={containerRefs} + thumbDimsRef={thumbDimsRef} /> </View> </View> diff --git a/src/view/com/util/post-embeds/index.tsx b/src/view/com/util/post-embeds/index.tsx index ab2471b33..1351a2cbc 100644 --- a/src/view/com/util/post-embeds/index.tsx +++ b/src/view/com/util/post-embeds/index.tsx @@ -35,6 +35,7 @@ import {atoms as a, useTheme} from '#/alf' import * as ListCard from '#/components/ListCard' import {Embed as StarterPackCard} from '#/components/StarterPack/StarterPackCard' import {ContentHider} from '../../../../components/moderation/ContentHider' +import {Dimensions} from '../../lightbox/ImageViewing/@types' import {AutoSizedImage} from '../images/AutoSizedImage' import {ImageLayoutGrid} from '../images/ImageLayoutGrid' import {ExternalLinkEmbed} from './ExternalLinkEmbed' @@ -148,11 +149,13 @@ export function PostEmbeds({ const _openLightbox = ( index: number, thumbRects: (MeasuredDimensions | null)[], + fetchedDims: (Dimensions | null)[], ) => { openLightbox({ images: items.map((item, i) => ({ ...item, thumbRect: thumbRects[i] ?? null, + thumbDimensions: fetchedDims[i] ?? null, type: 'image', })), index, @@ -161,11 +164,12 @@ export function PostEmbeds({ const onPress = ( index: number, refs: AnimatedRef<React.Component<{}, {}, any>>[], + fetchedDims: (Dimensions | null)[], ) => { runOnUI(() => { 'worklet' const rects = refs.map(ref => (ref ? measure(ref) : null)) - runOnJS(_openLightbox)(index, rects) + runOnJS(_openLightbox)(index, rects, fetchedDims) })() } const onPressIn = (_: number) => { @@ -189,7 +193,9 @@ export function PostEmbeds({ : 'constrained' } image={image} - onPress={containerRef => onPress(0, [containerRef])} + onPress={(containerRef, dims) => + onPress(0, [containerRef], [dims]) + } onPressIn={() => onPressIn(0)} hideBadge={ viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia |