1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
import React, {useMemo, useState} from 'react'
import {
LayoutChangeEvent,
StyleProp,
StyleSheet,
View,
ViewStyle,
} from 'react-native'
import {ImageStyle} from 'expo-image'
import {Dimensions} from 'lib/media/types'
import {AppBskyEmbedImages} from '@atproto/api'
import {GalleryItem} from './Gallery'
interface ImageLayoutGridProps {
images: AppBskyEmbedImages.ViewImage[]
onPress?: (index: number) => void
onLongPress?: (index: number) => void
onPressIn?: (index: number) => void
style?: StyleProp<ViewStyle>
}
export function ImageLayoutGrid({style, ...props}: ImageLayoutGridProps) {
const [containerInfo, setContainerInfo] = useState<Dimensions | undefined>()
const onLayout = (evt: LayoutChangeEvent) => {
const {width, height} = evt.nativeEvent.layout
setContainerInfo({
width,
height,
})
}
return (
<View style={style} onLayout={onLayout}>
{containerInfo ? (
<ImageLayoutGridInner {...props} containerInfo={containerInfo} />
) : undefined}
</View>
)
}
interface ImageLayoutGridInnerProps {
images: AppBskyEmbedImages.ViewImage[]
onPress?: (index: number) => void
onLongPress?: (index: number) => void
onPressIn?: (index: number) => void
containerInfo: Dimensions
}
function ImageLayoutGridInner({
containerInfo,
...props
}: ImageLayoutGridInnerProps) {
const count = props.images.length
const size1 = useMemo<ImageStyle>(() => {
if (count === 3) {
const size = (containerInfo.width - 10) / 3
return {width: size, height: size, resizeMode: 'cover', borderRadius: 4}
} else {
const size = (containerInfo.width - 5) / 2
return {width: size, height: size, resizeMode: 'cover', borderRadius: 4}
}
}, [count, containerInfo])
const size2 = React.useMemo<ImageStyle>(() => {
if (count === 3) {
const size = ((containerInfo.width - 10) / 3) * 2 + 5
return {width: size, height: size, resizeMode: 'cover', borderRadius: 4}
} else {
const size = (containerInfo.width - 5) / 2
return {width: size, height: size, resizeMode: 'cover', borderRadius: 4}
}
}, [count, containerInfo])
switch (count) {
case 2:
return (
<View style={styles.flexRow}>
<GalleryItem index={0} {...props} imageStyle={size1} />
<GalleryItem index={1} {...props} imageStyle={size1} />
</View>
)
case 3:
return (
<View style={styles.flexRow}>
<GalleryItem index={0} {...props} imageStyle={size2} />
<View style={styles.flexColumn}>
<GalleryItem index={1} {...props} imageStyle={size1} />
<GalleryItem index={2} {...props} imageStyle={size1} />
</View>
</View>
)
case 4:
return (
<View style={styles.flexRow}>
<View style={styles.flexColumn}>
<GalleryItem index={0} {...props} imageStyle={size1} />
<GalleryItem index={2} {...props} imageStyle={size1} />
</View>
<View style={styles.flexColumn}>
<GalleryItem index={1} {...props} imageStyle={size1} />
<GalleryItem index={3} {...props} imageStyle={size1} />
</View>
</View>
)
default:
return null
}
}
const styles = StyleSheet.create({
flexRow: {flexDirection: 'row', gap: 5},
flexColumn: {flexDirection: 'column', gap: 5},
})
|