about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/view/com/util/images/Gallery.tsx17
-rw-r--r--src/view/com/util/images/ImageLayoutGrid.tsx114
2 files changed, 65 insertions, 66 deletions
diff --git a/src/view/com/util/images/Gallery.tsx b/src/view/com/util/images/Gallery.tsx
index 679f71c99..094b0c56c 100644
--- a/src/view/com/util/images/Gallery.tsx
+++ b/src/view/com/util/images/Gallery.tsx
@@ -23,19 +23,19 @@ export const GalleryItem: FC<GalleryItemProps> = ({
   onLongPress,
 }) => {
   const image = images[index]
-
   return (
-    <View>
+    <View style={styles.fullWidth}>
       <Pressable
         onPress={onPress ? () => onPress(index) : undefined}
         onPressIn={onPressIn ? () => onPressIn(index) : undefined}
         onLongPress={onLongPress ? () => onLongPress(index) : undefined}
+        style={styles.fullWidth}
         accessibilityRole="button"
         accessibilityLabel={image.alt || 'Image'}
         accessibilityHint="">
         <Image
           source={{uri: image.thumb}}
-          style={imageStyle}
+          style={[styles.image, imageStyle]}
           accessible={true}
           accessibilityLabel={image.alt}
           accessibilityHint=""
@@ -54,14 +54,21 @@ export const GalleryItem: FC<GalleryItemProps> = ({
 }
 
 const styles = StyleSheet.create({
+  fullWidth: {
+    flex: 1,
+  },
+  image: {
+    flex: 1,
+    borderRadius: 4,
+  },
   altContainer: {
     backgroundColor: 'rgba(0, 0, 0, 0.75)',
     borderRadius: 6,
     paddingHorizontal: 6,
     paddingVertical: 3,
     position: 'absolute',
-    left: 6,
-    bottom: 6,
+    left: 8,
+    bottom: 8,
   },
   alt: {
     color: 'white',
diff --git a/src/view/com/util/images/ImageLayoutGrid.tsx b/src/view/com/util/images/ImageLayoutGrid.tsx
index 4c0901304..2e352d086 100644
--- a/src/view/com/util/images/ImageLayoutGrid.tsx
+++ b/src/view/com/util/images/ImageLayoutGrid.tsx
@@ -1,13 +1,5 @@
-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 React from 'react'
+import {StyleProp, StyleSheet, View, ViewStyle} from 'react-native'
 import {AppBskyEmbedImages} from '@atproto/api'
 import {GalleryItem} from './Gallery'
 
@@ -20,21 +12,11 @@ interface ImageLayoutGridProps {
 }
 
 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 style={style}>
+      <View style={styles.container}>
+        <ImageLayoutGridInner {...props} />
+      </View>
     </View>
   )
 }
@@ -44,70 +26,80 @@ interface ImageLayoutGridInnerProps {
   onPress?: (index: number) => void
   onLongPress?: (index: number) => void
   onPressIn?: (index: number) => void
-  containerInfo: Dimensions
 }
 
-function ImageLayoutGridInner({
-  containerInfo,
-  ...props
-}: ImageLayoutGridInnerProps) {
+function ImageLayoutGridInner(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 style={styles.smallItem}>
+            <GalleryItem {...props} index={0} imageStyle={styles.image} />
+          </View>
+          <View style={styles.smallItem}>
+            <GalleryItem {...props} index={1} imageStyle={styles.image} />
+          </View>
         </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 style={{flex: 2, aspectRatio: 1}}>
+            <GalleryItem {...props} index={0} imageStyle={styles.image} />
+          </View>
+          <View style={{flex: 1}}>
+            <View style={styles.smallItem}>
+              <GalleryItem {...props} index={1} imageStyle={styles.image} />
+            </View>
+            <View style={styles.smallItem}>
+              <GalleryItem {...props} index={2} imageStyle={styles.image} />
+            </View>
           </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 style={{flex: 1}}>
+            <View style={styles.smallItem}>
+              <GalleryItem {...props} index={0} imageStyle={styles.image} />
+            </View>
+            <View style={styles.smallItem}>
+              <GalleryItem {...props} index={2} imageStyle={styles.image} />
+            </View>
           </View>
-          <View style={styles.flexColumn}>
-            <GalleryItem index={1} {...props} imageStyle={size1} />
-            <GalleryItem index={3} {...props} imageStyle={size1} />
+          <View style={{flex: 1}}>
+            <View style={styles.smallItem}>
+              <GalleryItem {...props} index={1} imageStyle={styles.image} />
+            </View>
+            <View style={styles.smallItem}>
+              <GalleryItem {...props} index={3} imageStyle={styles.image} />
+            </View>
           </View>
         </View>
       )
+
     default:
       return null
   }
 }
 
+// This is used to compute margins (rather than flexbox gap) due to Yoga bugs:
+// https://github.com/facebook/yoga/issues/1418
+const IMAGE_GAP = 5
+
 const styles = StyleSheet.create({
-  flexRow: {flexDirection: 'row', gap: 5},
-  flexColumn: {flexDirection: 'column', gap: 5},
+  container: {
+    marginHorizontal: -IMAGE_GAP / 2,
+    marginVertical: -IMAGE_GAP / 2,
+  },
+  flexRow: {flexDirection: 'row'},
+  smallItem: {flex: 1, aspectRatio: 1},
+  image: {
+    margin: IMAGE_GAP / 2,
+  },
 })