mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
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})