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

Configure Feed

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

at main 132 lines 3.9 kB view raw
1import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' 2import {type AnimatedRef} from 'react-native-reanimated' 3import {Image, type ImageStyle} from 'expo-image' 4import {type AppBskyEmbedImages} from '@atproto/api' 5import {utils} from '@bsky.app/alf' 6import {msg} from '@lingui/macro' 7import {useLingui} from '@lingui/react' 8 9import {type Dimensions} from '#/lib/media/types' 10import { 11 maybeModifyHighQualityImage, 12 useHighQualityImages, 13} from '#/state/preferences/high-quality-images' 14import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' 15import {atoms as a, useTheme} from '#/alf' 16import {MediaInsetBorder} from '#/components/MediaInsetBorder' 17import {PostEmbedViewContext} from '#/components/Post/Embed/types' 18import {Text} from '#/components/Typography' 19 20type EventFunction = (index: number) => void 21 22interface Props { 23 images: AppBskyEmbedImages.ViewImage[] 24 index: number 25 onPress?: ( 26 index: number, 27 containerRefs: AnimatedRef<any>[], 28 fetchedDims: (Dimensions | null)[], 29 ) => void 30 onLongPress?: EventFunction 31 onPressIn?: EventFunction 32 imageStyle?: StyleProp<ImageStyle> 33 viewContext?: PostEmbedViewContext 34 insetBorderStyle?: StyleProp<ViewStyle> 35 containerRefs: AnimatedRef<any>[] 36 thumbDimsRef: React.RefObject<(Dimensions | null)[]> 37} 38 39export function GalleryItem({ 40 images, 41 index, 42 imageStyle, 43 onPress, 44 onPressIn, 45 onLongPress, 46 viewContext, 47 insetBorderStyle, 48 containerRefs, 49 thumbDimsRef, 50}: Props) { 51 const t = useTheme() 52 const {_} = useLingui() 53 const largeAltBadge = useLargeAltBadgeEnabled() 54 const highQualityImages = useHighQualityImages() 55 const image = images[index] 56 const hasAlt = !!image.alt 57 const hideBadges = 58 viewContext === PostEmbedViewContext.FeedEmbedRecordWithMedia 59 return ( 60 <View style={a.flex_1} ref={containerRefs[index]} collapsable={false}> 61 <Pressable 62 onPress={ 63 onPress 64 ? () => onPress(index, containerRefs, thumbDimsRef.current.slice()) 65 : undefined 66 } 67 onPressIn={onPressIn ? () => onPressIn(index) : undefined} 68 onLongPress={onLongPress ? () => onLongPress(index) : undefined} 69 android_ripple={{ 70 color: utils.alpha(t.atoms.bg.backgroundColor, 0.2), 71 foreground: true, 72 }} 73 style={[ 74 a.flex_1, 75 a.overflow_hidden, 76 t.atoms.bg_contrast_25, 77 imageStyle, 78 ]} 79 accessibilityRole="button" 80 accessibilityLabel={image.alt || _(msg`Image`)} 81 accessibilityHint=""> 82 <Image 83 source={{ 84 uri: maybeModifyHighQualityImage(image.thumb, highQualityImages), 85 }} 86 style={[a.flex_1]} 87 accessible={true} 88 accessibilityLabel={image.alt} 89 accessibilityHint="" 90 accessibilityIgnoresInvertColors 91 onLoad={e => { 92 thumbDimsRef.current[index] = { 93 width: e.source.width, 94 height: e.source.height, 95 } 96 }} 97 loading="lazy" 98 /> 99 <MediaInsetBorder style={insetBorderStyle} /> 100 </Pressable> 101 {hasAlt && !hideBadges ? ( 102 <View 103 accessible={false} 104 style={[ 105 a.absolute, 106 a.flex_row, 107 a.align_center, 108 a.rounded_xs, 109 t.atoms.bg_contrast_25, 110 { 111 gap: 3, 112 padding: 3, 113 bottom: a.p_xs.padding, 114 right: a.p_xs.padding, 115 opacity: 0.8, 116 }, 117 largeAltBadge && [ 118 { 119 gap: 4, 120 padding: 5, 121 }, 122 ], 123 ]}> 124 <Text 125 style={[a.font_bold, largeAltBadge ? a.text_xs : {fontSize: 8}]}> 126 ALT 127 </Text> 128 </View> 129 ) : null} 130 </View> 131 ) 132}