about summary refs log tree commit diff
path: root/src/view/com/composer/photos/Gallery.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/composer/photos/Gallery.tsx')
-rw-r--r--src/view/com/composer/photos/Gallery.tsx244
1 files changed, 135 insertions, 109 deletions
diff --git a/src/view/com/composer/photos/Gallery.tsx b/src/view/com/composer/photos/Gallery.tsx
index f46c05333..c226d25cc 100644
--- a/src/view/com/composer/photos/Gallery.tsx
+++ b/src/view/com/composer/photos/Gallery.tsx
@@ -1,16 +1,16 @@
-import React, {useCallback} from 'react'
+import React from 'react'
 import {ImageStyle, Keyboard} from 'react-native'
 import {GalleryModel} from 'state/models/media/gallery'
 import {observer} from 'mobx-react-lite'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
-import {colors} from 'lib/styles'
+import {s, colors} from 'lib/styles'
 import {StyleSheet, TouchableOpacity, View} from 'react-native'
-import {ImageModel} from 'state/models/media/image'
 import {Image} from 'expo-image'
 import {Text} from 'view/com/util/text/Text'
 import {isDesktopWeb} from 'platform/detection'
 import {openAltTextModal} from 'lib/media/alt-text'
 import {useStores} from 'state/index'
+import {usePalette} from 'lib/hooks/usePalette'
 
 interface Props {
   gallery: GalleryModel
@@ -18,67 +18,39 @@ interface Props {
 
 export const Gallery = observer(function ({gallery}: Props) {
   const store = useStores()
-  const getImageStyle = useCallback(() => {
-    let side: number
+  const pal = usePalette('default')
 
-    if (gallery.size === 1) {
-      side = 250
-    } else {
-      side = (isDesktopWeb ? 560 : 350) / gallery.size
-    }
+  let side: number
 
-    return {
-      height: side,
-      width: side,
-    }
-  }, [gallery])
-
-  const imageStyle = getImageStyle()
-  const handleAddImageAltText = useCallback(
-    (image: ImageModel) => {
-      Keyboard.dismiss()
-      openAltTextModal(store, image)
-    },
-    [store],
-  )
-  const handleRemovePhoto = useCallback(
-    (image: ImageModel) => {
-      gallery.remove(image)
-    },
-    [gallery],
-  )
+  if (gallery.size === 1) {
+    side = 250
+  } else {
+    side = (isDesktopWeb ? 560 : 350) / gallery.size
+  }
 
-  const handleEditPhoto = useCallback(
-    (image: ImageModel) => {
-      gallery.edit(image)
-    },
-    [gallery],
-  )
+  const imageStyle = {
+    height: side,
+    width: side,
+  }
 
   const isOverflow = !isDesktopWeb && gallery.size > 2
 
-  const imageControlLabelStyle = {
-    borderRadius: 5,
-    paddingHorizontal: 10,
-    position: 'absolute' as const,
-    zIndex: 1,
-    ...(isOverflow
-      ? {
-          left: 4,
-          bottom: 4,
-        }
-      : isDesktopWeb && gallery.size < 3
-      ? {
-          left: 8,
-          top: 8,
-        }
-      : {
-          left: 4,
-          top: 4,
-        }),
-  }
+  const altTextControlStyle = isOverflow
+    ? {
+        left: 4,
+        bottom: 4,
+      }
+    : isDesktopWeb && gallery.size < 3
+    ? {
+        left: 8,
+        top: 8,
+      }
+    : {
+        left: 4,
+        top: 4,
+      }
 
-  const imageControlsSubgroupStyle = {
+  const imageControlsStyle = {
     display: 'flex' as const,
     flexDirection: 'row' as const,
     position: 'absolute' as const,
@@ -103,63 +75,90 @@ export const Gallery = observer(function ({gallery}: Props) {
   }
 
   return !gallery.isEmpty ? (
-    <View testID="selectedPhotosView" style={styles.gallery}>
-      {gallery.images.map(image => (
-        <View key={`selected-image-${image.path}`} style={[imageStyle]}>
-          <TouchableOpacity
-            testID="altTextButton"
-            accessibilityRole="button"
-            accessibilityLabel="Add alt text"
-            accessibilityHint=""
-            onPress={() => {
-              handleAddImageAltText(image)
-            }}
-            style={imageControlLabelStyle}>
-            <Text style={styles.imageControlTextContent}>ALT</Text>
-          </TouchableOpacity>
-          <View style={imageControlsSubgroupStyle}>
+    <>
+      <View testID="selectedPhotosView" style={styles.gallery}>
+        {gallery.images.map(image => (
+          <View key={`selected-image-${image.path}`} style={[imageStyle]}>
             <TouchableOpacity
-              testID="editPhotoButton"
+              testID="altTextButton"
               accessibilityRole="button"
-              accessibilityLabel="Edit image"
+              accessibilityLabel="Add alt text"
               accessibilityHint=""
               onPress={() => {
-                handleEditPhoto(image)
+                Keyboard.dismiss()
+                openAltTextModal(store, image)
               }}
-              style={styles.imageControl}>
-              <FontAwesomeIcon
-                icon="pen"
-                size={12}
-                style={{color: colors.white}}
-              />
+              style={[styles.altTextControl, altTextControlStyle]}>
+              <Text style={styles.altTextControlLabel}>ALT</Text>
+              {image.altText.length > 0 ? (
+                <FontAwesomeIcon
+                  icon="check"
+                  size={10}
+                  style={{color: colors.green3}}
+                />
+              ) : undefined}
             </TouchableOpacity>
+            <View style={imageControlsStyle}>
+              <TouchableOpacity
+                testID="editPhotoButton"
+                accessibilityRole="button"
+                accessibilityLabel="Edit image"
+                accessibilityHint=""
+                onPress={() => gallery.edit(image)}
+                style={styles.imageControl}>
+                <FontAwesomeIcon
+                  icon="pen"
+                  size={12}
+                  style={{color: colors.white}}
+                />
+              </TouchableOpacity>
+              <TouchableOpacity
+                testID="removePhotoButton"
+                accessibilityRole="button"
+                accessibilityLabel="Remove image"
+                accessibilityHint=""
+                onPress={() => gallery.remove(image)}
+                style={styles.imageControl}>
+                <FontAwesomeIcon
+                  icon="xmark"
+                  size={16}
+                  style={{color: colors.white}}
+                />
+              </TouchableOpacity>
+            </View>
             <TouchableOpacity
-              testID="removePhotoButton"
               accessibilityRole="button"
-              accessibilityLabel="Remove image"
+              accessibilityLabel="Add alt text"
               accessibilityHint=""
-              onPress={() => handleRemovePhoto(image)}
-              style={styles.imageControl}>
-              <FontAwesomeIcon
-                icon="xmark"
-                size={16}
-                style={{color: colors.white}}
-              />
-            </TouchableOpacity>
-          </View>
+              onPress={() => {
+                Keyboard.dismiss()
+                openAltTextModal(store, image)
+              }}
+              style={styles.altTextHiddenRegion}
+            />
 
-          <Image
-            testID="selectedPhotoImage"
-            style={[styles.image, imageStyle] as ImageStyle}
-            source={{
-              uri: image.cropped?.path ?? image.path,
-            }}
-            accessible={true}
-            accessibilityIgnoresInvertColors
-          />
+            <Image
+              testID="selectedPhotoImage"
+              style={[styles.image, imageStyle] as ImageStyle}
+              source={{
+                uri: image.cropped?.path ?? image.path,
+              }}
+              accessible={true}
+              accessibilityIgnoresInvertColors
+            />
+          </View>
+        ))}
+      </View>
+      <View style={[styles.reminder]}>
+        <View style={[styles.infoIcon, pal.viewLight]}>
+          <FontAwesomeIcon icon="info" size={12} color={pal.colors.text} />
         </View>
-      ))}
-    </View>
+        <Text type="sm" style={[pal.textLight, s.flex1]}>
+          Alt text describes images for blind and low-vision users, and helps
+          give context to everyone.
+        </Text>
+      </View>
+    </>
   ) : null
 })
 
@@ -179,19 +178,46 @@ const styles = StyleSheet.create({
     height: 24,
     borderRadius: 12,
     backgroundColor: 'rgba(0, 0, 0, 0.75)',
-    borderWidth: 0.5,
     alignItems: 'center',
     justifyContent: 'center',
   },
-  imageControlTextContent: {
+  altTextControl: {
+    position: 'absolute',
+    zIndex: 1,
     borderRadius: 6,
+    backgroundColor: 'rgba(0, 0, 0, 0.75)',
+    paddingHorizontal: 8,
+    paddingVertical: 3,
+    flexDirection: 'row',
+    alignItems: 'center',
+  },
+  altTextControlLabel: {
     color: 'white',
     fontSize: 12,
     fontWeight: 'bold',
     letterSpacing: 1,
-    backgroundColor: 'rgba(0, 0, 0, 0.75)',
-    borderWidth: 0.5,
-    paddingHorizontal: 10,
-    paddingVertical: 3,
+  },
+  altTextHiddenRegion: {
+    position: 'absolute',
+    left: 4,
+    right: 4,
+    bottom: 4,
+    top: 30,
+    zIndex: 1,
+  },
+
+  reminder: {
+    flexDirection: 'row',
+    alignItems: 'center',
+    gap: 8,
+    borderRadius: 8,
+    paddingVertical: 14,
+  },
+  infoIcon: {
+    width: 22,
+    height: 22,
+    borderRadius: 12,
+    alignItems: 'center',
+    justifyContent: 'center',
   },
 })