mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at session-alignment 126 lines 3.6 kB view raw
1import React from 'react' 2import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native' 3import {AppBskyEmbedImages} from '@atproto/api' 4import {GalleryItem} from './Gallery' 5import {isWeb} from 'platform/detection' 6 7interface ImageLayoutGridProps { 8 images: AppBskyEmbedImages.ViewImage[] 9 onPress?: (index: number) => void 10 onLongPress?: (index: number) => void 11 onPressIn?: (index: number) => void 12 style?: StyleProp<ViewStyle> 13} 14 15export function ImageLayoutGrid({style, ...props}: ImageLayoutGridProps) { 16 return ( 17 <View style={style}> 18 <View style={styles.container}> 19 <ImageLayoutGridInner {...props} /> 20 </View> 21 </View> 22 ) 23} 24 25interface ImageLayoutGridInnerProps { 26 images: AppBskyEmbedImages.ViewImage[] 27 onPress?: (index: number) => void 28 onLongPress?: (index: number) => void 29 onPressIn?: (index: number) => void 30} 31 32function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) { 33 const count = props.images.length 34 35 switch (count) { 36 case 2: 37 return ( 38 <View style={styles.flexRow}> 39 <View style={styles.smallItem}> 40 <GalleryItem {...props} index={0} imageStyle={styles.image} /> 41 </View> 42 <View style={styles.smallItem}> 43 <GalleryItem {...props} index={1} imageStyle={styles.image} /> 44 </View> 45 </View> 46 ) 47 48 case 3: 49 return ( 50 <View style={styles.flexRow}> 51 <View style={styles.threeSingle}> 52 <GalleryItem {...props} index={0} imageStyle={styles.image} /> 53 </View> 54 <View style={styles.threeDouble}> 55 <View style={styles.smallItem}> 56 <GalleryItem {...props} index={1} imageStyle={styles.image} /> 57 </View> 58 <View style={styles.smallItem}> 59 <GalleryItem {...props} index={2} imageStyle={styles.image} /> 60 </View> 61 </View> 62 </View> 63 ) 64 65 case 4: 66 return ( 67 <> 68 <View style={styles.flexRow}> 69 <View style={styles.smallItem}> 70 <GalleryItem {...props} index={0} imageStyle={styles.image} /> 71 </View> 72 <View style={styles.smallItem}> 73 <GalleryItem {...props} index={1} imageStyle={styles.image} /> 74 </View> 75 </View> 76 <View style={styles.flexRow}> 77 <View style={styles.smallItem}> 78 <GalleryItem {...props} index={2} imageStyle={styles.image} /> 79 </View> 80 <View style={styles.smallItem}> 81 <GalleryItem {...props} index={3} imageStyle={styles.image} /> 82 </View> 83 </View> 84 </> 85 ) 86 87 default: 88 return null 89 } 90} 91 92// On web we use margin to calculate gap, as aspectRatio does not properly size 93// all images on web. On native though we cannot rely on margin, since the 94// negative margin interferes with the swipe controls on pagers. 95// https://github.com/facebook/yoga/issues/1418 96// https://github.com/bluesky-social/social-app/issues/2601 97const IMAGE_GAP = 5 98 99const styles = StyleSheet.create({ 100 container: isWeb 101 ? { 102 marginHorizontal: -IMAGE_GAP / 2, 103 marginVertical: -IMAGE_GAP / 2, 104 } 105 : { 106 gap: IMAGE_GAP, 107 }, 108 flexRow: { 109 flexDirection: 'row', 110 gap: isWeb ? undefined : IMAGE_GAP, 111 }, 112 smallItem: {flex: 1, aspectRatio: 1}, 113 image: isWeb 114 ? { 115 margin: IMAGE_GAP / 2, 116 } 117 : {}, 118 threeSingle: { 119 flex: 2, 120 aspectRatio: isWeb ? 1 : undefined, 121 }, 122 threeDouble: { 123 flex: 1, 124 gap: isWeb ? undefined : IMAGE_GAP, 125 }, 126})