mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at samuel/exp-cli 106 lines 3.0 kB view raw
1import {InteractionManager, View} from 'react-native' 2import { 3 type AnimatedRef, 4 measure, 5 type MeasuredDimensions, 6 runOnJS, 7 runOnUI, 8} from 'react-native-reanimated' 9import {Image} from 'expo-image' 10 11import {useLightboxControls} from '#/state/lightbox' 12import {type Dimensions} from '#/view/com/lightbox/ImageViewing/@types' 13import {AutoSizedImage} from '#/view/com/util/images/AutoSizedImage' 14import {ImageLayoutGrid} from '#/view/com/util/images/ImageLayoutGrid' 15import {atoms as a} from '#/alf' 16import {PostEmbedViewContext} from '#/components/Post/Embed/types' 17import {type EmbedType} from '#/types/bsky/post' 18import {type CommonProps} from './types' 19 20export function ImageEmbed({ 21 embed, 22 ...rest 23}: CommonProps & { 24 embed: EmbedType<'images'> 25}) { 26 const {openLightbox} = useLightboxControls() 27 const {images} = embed.view 28 29 if (images.length > 0) { 30 const items = images.map(img => ({ 31 uri: img.fullsize, 32 thumbUri: img.thumb, 33 alt: img.alt, 34 dimensions: img.aspectRatio ?? null, 35 })) 36 const _openLightbox = ( 37 index: number, 38 thumbRects: (MeasuredDimensions | null)[], 39 fetchedDims: (Dimensions | null)[], 40 ) => { 41 openLightbox({ 42 images: items.map((item, i) => ({ 43 ...item, 44 thumbRect: thumbRects[i] ?? null, 45 thumbDimensions: fetchedDims[i] ?? null, 46 type: 'image', 47 })), 48 index, 49 }) 50 } 51 const onPress = ( 52 index: number, 53 refs: AnimatedRef<any>[], 54 fetchedDims: (Dimensions | null)[], 55 ) => { 56 runOnUI(() => { 57 'worklet' 58 const rects: (MeasuredDimensions | null)[] = [] 59 for (const r of refs) { 60 rects.push(measure(r)) 61 } 62 runOnJS(_openLightbox)(index, rects, fetchedDims) 63 })() 64 } 65 const onPressIn = (_: number) => { 66 InteractionManager.runAfterInteractions(() => { 67 Image.prefetch(items.map(i => i.uri)) 68 }) 69 } 70 71 if (images.length === 1) { 72 const image = images[0] 73 return ( 74 <View style={[a.mt_sm, rest.style]}> 75 <AutoSizedImage 76 crop={ 77 rest.viewContext === PostEmbedViewContext.ThreadHighlighted 78 ? 'none' 79 : rest.viewContext === 80 PostEmbedViewContext.FeedEmbedRecordWithMedia 81 ? 'square' 82 : 'constrained' 83 } 84 image={image} 85 onPress={(containerRef, dims) => onPress(0, [containerRef], [dims])} 86 onPressIn={() => onPressIn(0)} 87 hideBadge={ 88 rest.viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia 89 } 90 /> 91 </View> 92 ) 93 } 94 95 return ( 96 <View style={[a.mt_sm, rest.style]}> 97 <ImageLayoutGrid 98 images={images} 99 onPress={onPress} 100 onPressIn={onPressIn} 101 viewContext={rest.viewContext} 102 /> 103 </View> 104 ) 105 } 106}