about summary refs log tree commit diff
path: root/src/view/com/util/images
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/util/images')
-rw-r--r--src/view/com/util/images/AutoSizedImage.tsx36
-rw-r--r--src/view/com/util/images/ImageLayoutGrid.tsx148
2 files changed, 169 insertions, 15 deletions
diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx
index 9de443b7f..a711323a9 100644
--- a/src/view/com/util/images/AutoSizedImage.tsx
+++ b/src/view/com/util/images/AutoSizedImage.tsx
@@ -10,7 +10,8 @@ import {
   ViewStyle,
 } from 'react-native'
 import {Text} from '../text/Text'
-import {colors} from '../../../lib/styles'
+import {useTheme} from '../../../lib/ThemeContext'
+import {usePalette} from '../../../lib/hooks/usePalette'
 
 const MAX_HEIGHT = 300
 
@@ -23,12 +24,16 @@ export function AutoSizedImage({
   uri,
   onPress,
   style,
+  containerStyle,
 }: {
   uri: string
   onPress?: () => void
-  style: StyleProp<ImageStyle>
+  style?: StyleProp<ImageStyle>
+  containerStyle?: StyleProp<ViewStyle>
 }) {
-  const [error, setError] = useState<string | undefined>()
+  const theme = useTheme()
+  const errPal = usePalette('error')
+  const [error, setError] = useState<string | undefined>('')
   const [imgInfo, setImgInfo] = useState<Dim | undefined>()
   const [containerInfo, setContainerInfo] = useState<Dim | undefined>()
 
@@ -77,15 +82,22 @@ export function AutoSizedImage({
     <View style={style}>
       <TouchableWithoutFeedback onPress={onPress}>
         {error ? (
-          <View style={[styles.container, styles.errorContainer]}>
-            <Text style={styles.error}>{error}</Text>
+          <View style={[styles.errorContainer, errPal.view, containerStyle]}>
+            <Text style={errPal.text}>{error}</Text>
           </View>
         ) : calculatedStyle ? (
-          <View style={styles.container}>
+          <View style={[styles.container, containerStyle]}>
             <Image style={calculatedStyle} source={{uri}} />
           </View>
         ) : (
-          <View style={[style, styles.placeholder]} onLayout={onLayout} />
+          <View
+            style={[
+              style,
+              styles.placeholder,
+              {backgroundColor: theme.palette.default.backgroundLight},
+            ]}
+            onLayout={onLayout}
+          />
         )}
       </TouchableWithoutFeedback>
     </View>
@@ -96,18 +108,12 @@ const styles = StyleSheet.create({
   placeholder: {
     width: '100%',
     aspectRatio: 1,
-    backgroundColor: colors.gray1,
   },
   errorContainer: {
-    backgroundColor: colors.red1,
-    paddingHorizontal: 8,
-    paddingVertical: 4,
+    paddingHorizontal: 12,
+    paddingVertical: 8,
   },
   container: {
-    borderRadius: 8,
     overflow: 'hidden',
   },
-  error: {
-    color: colors.red5,
-  },
 })
diff --git a/src/view/com/util/images/ImageLayoutGrid.tsx b/src/view/com/util/images/ImageLayoutGrid.tsx
new file mode 100644
index 000000000..cb560dd35
--- /dev/null
+++ b/src/view/com/util/images/ImageLayoutGrid.tsx
@@ -0,0 +1,148 @@
+import React from 'react'
+import {
+  Image,
+  ImageStyle,
+  LayoutChangeEvent,
+  StyleProp,
+  StyleSheet,
+  TouchableWithoutFeedback,
+  View,
+  ViewStyle,
+} from 'react-native'
+
+interface Dim {
+  width: number
+  height: number
+}
+
+export type ImageLayoutGridType = 'two' | 'three' | 'four'
+
+export function ImageLayoutGrid({
+  type,
+  uris,
+  onPress,
+  style,
+}: {
+  type: ImageLayoutGridType
+  uris: string
+  onPress?: (index: number) => void
+  style?: StyleProp<ViewStyle>
+}) {
+  const [containerInfo, setContainerInfo] = React.useState<Dim | undefined>()
+
+  const onLayout = (evt: LayoutChangeEvent) => {
+    setContainerInfo({
+      width: evt.nativeEvent.layout.width,
+      height: evt.nativeEvent.layout.height,
+    })
+  }
+
+  return (
+    <View style={style} onLayout={onLayout}>
+      {containerInfo ? (
+        <ImageLayoutGridInner
+          type={type}
+          uris={uris}
+          onPress={onPress}
+          containerInfo={containerInfo}
+        />
+      ) : undefined}
+    </View>
+  )
+}
+
+function ImageLayoutGridInner({
+  type,
+  uris,
+  onPress,
+  containerInfo,
+}: {
+  type: ImageLayoutGridType
+  uris: string
+  onPress?: (index: number) => void
+  containerInfo: Dim
+}) {
+  const size1 = React.useMemo<ImageStyle>(() => {
+    if (type === 'three') {
+      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}
+    }
+  }, [type, containerInfo])
+  const size2 = React.useMemo<ImageStyle>(() => {
+    if (type === 'three') {
+      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}
+    }
+  }, [type, containerInfo])
+
+  if (type === 'two') {
+    return (
+      <View style={styles.flexRow}>
+        <TouchableWithoutFeedback onPress={() => onPress?.(0)}>
+          <Image source={{uri: uris[0]}} style={size1} />
+        </TouchableWithoutFeedback>
+        <View style={styles.wSpace} />
+        <TouchableWithoutFeedback onPress={() => onPress?.(1)}>
+          <Image source={{uri: uris[1]}} style={size1} />
+        </TouchableWithoutFeedback>
+      </View>
+    )
+  }
+  if (type === 'three') {
+    return (
+      <View style={styles.flexRow}>
+        <TouchableWithoutFeedback onPress={() => onPress?.(0)}>
+          <Image source={{uri: uris[0]}} style={size2} />
+        </TouchableWithoutFeedback>
+        <View style={styles.wSpace} />
+        <View>
+          <TouchableWithoutFeedback onPress={() => onPress?.(1)}>
+            <Image source={{uri: uris[1]}} style={size1} />
+          </TouchableWithoutFeedback>
+          <View style={{height: 5}} />
+          <TouchableWithoutFeedback onPress={() => onPress?.(2)}>
+            <Image source={{uri: uris[2]}} style={size1} />
+          </TouchableWithoutFeedback>
+        </View>
+      </View>
+    )
+  }
+  if (type === 'four') {
+    return (
+      <View style={styles.flexRow}>
+        <View>
+          <TouchableWithoutFeedback onPress={() => onPress?.(0)}>
+            <Image source={{uri: uris[0]}} style={size1} />
+          </TouchableWithoutFeedback>
+          <View style={styles.hSpace} />
+          <TouchableWithoutFeedback onPress={() => onPress?.(1)}>
+            <Image source={{uri: uris[1]}} style={size1} />
+          </TouchableWithoutFeedback>
+        </View>
+        <View style={styles.wSpace} />
+        <View>
+          <TouchableWithoutFeedback onPress={() => onPress?.(2)}>
+            <Image source={{uri: uris[2]}} style={size1} />
+          </TouchableWithoutFeedback>
+          <View style={styles.hSpace} />
+          <TouchableWithoutFeedback onPress={() => onPress?.(3)}>
+            <Image source={{uri: uris[3]}} style={size1} />
+          </TouchableWithoutFeedback>
+        </View>
+      </View>
+    )
+  }
+  return <View />
+}
+
+const styles = StyleSheet.create({
+  flexRow: {flexDirection: 'row'},
+  wSpace: {width: 5},
+  hSpace: {height: 5},
+})