Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at cope-settings-sync 121 lines 3.5 kB view raw
1import {InteractionManager, View} from 'react-native' 2import {type AnimatedRef} from 'react-native-reanimated' 3import {Image} from 'expo-image' 4 5import {useLightboxControls} from '#/state/lightbox' 6import {useHighQualityImages} from '#/state/preferences/high-quality-images' 7import { 8 applyImageTransforms, 9 useImageCdnHost, 10} from '#/state/preferences/image-cdn-host' 11import {type Dimensions} from '#/view/com/lightbox/ImageViewing/@types' 12import {atoms as a, tokens} from '#/alf' 13import {AutoSizedImage} from '#/components/images/AutoSizedImage' 14import {Gallery} from '#/components/images/Gallery' 15import {ImageLayoutGrid} from '#/components/images/ImageLayoutGrid' 16import {PostEmbedViewContext} from '#/components/Post/Embed/types' 17import {useAnalytics} from '#/analytics' 18import {type EmbedType} from '#/types/bsky/post' 19import {type CommonProps} from './types' 20 21export function ImageEmbed({ 22 embed, 23 ...rest 24}: CommonProps & { 25 embed: EmbedType<'images'> 26}) { 27 const ax = useAnalytics() 28 const {openLightbox} = useLightboxControls() 29 const highQualityImages = useHighQualityImages() 30 const imageCdnHost = useImageCdnHost() 31 const {images} = embed.view 32 const galleryEnabled = ax.features.enabled(ax.features.PostGalleryEmbedEnable) 33 34 if (images.length > 0) { 35 const items = images.map(img => ({ 36 uri: applyImageTransforms(img.fullsize, { 37 imageCdnHost, 38 highQualityImages, 39 }), 40 thumbUri: applyImageTransforms(img.thumb, { 41 imageCdnHost, 42 highQualityImages, 43 }), 44 alt: img.alt, 45 dimensions: img.aspectRatio ?? null, 46 })) 47 const onPress = ( 48 index: number, 49 refs: AnimatedRef<any>[], 50 fetchedDims: (Dimensions | null)[], 51 ) => { 52 openLightbox({ 53 images: items.map((item, i) => ({ 54 ...item, 55 thumbRect: null, 56 thumbRef: refs[i] ?? null, 57 thumbDimensions: fetchedDims[i] ?? null, 58 thumbBorderRadius: tokens.borderRadius.md, 59 type: 'image', 60 })), 61 index, 62 }) 63 } 64 const onPressIn = (_: number) => { 65 InteractionManager.runAfterInteractions(() => { 66 Image.prefetch( 67 items.map(i => i.uri), 68 'memory', 69 ) 70 }) 71 } 72 73 if (images.length === 1) { 74 const image = images[0] 75 return ( 76 <View style={[a.mt_sm, rest.style]}> 77 <AutoSizedImage 78 crop={ 79 rest.viewContext === PostEmbedViewContext.ThreadHighlighted 80 ? 'none' 81 : rest.viewContext === 82 PostEmbedViewContext.FeedEmbedRecordWithMedia 83 ? 'square' 84 : 'constrained' 85 } 86 image={image} 87 onPress={(containerRef, dims) => onPress(0, [containerRef], [dims])} 88 onPressIn={() => onPressIn(0)} 89 hideBadge={ 90 rest.viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia 91 } 92 /> 93 </View> 94 ) 95 } 96 97 if (galleryEnabled) { 98 return ( 99 <View style={[a.mt_sm, rest.style]}> 100 <Gallery 101 images={images} 102 onPress={onPress} 103 onPressIn={onPressIn} 104 viewContext={rest.viewContext} 105 /> 106 </View> 107 ) 108 } 109 110 return ( 111 <View style={[a.mt_sm, rest.style]}> 112 <ImageLayoutGrid 113 images={images} 114 onPress={onPress} 115 onPressIn={onPressIn} 116 viewContext={rest.viewContext} 117 /> 118 </View> 119 ) 120 } 121}