about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/view/com/composer/ComposePost.tsx197
-rw-r--r--src/view/com/composer/PhotoCarouselPicker.tsx192
2 files changed, 220 insertions, 169 deletions
diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx
index ce42ee17e..2f8c29e7c 100644
--- a/src/view/com/composer/ComposePost.tsx
+++ b/src/view/com/composer/ComposePost.tsx
@@ -9,13 +9,10 @@ import {
   TextInput,
   TouchableOpacity,
   View,
-  ScrollView,
-  Image,
 } from 'react-native'
 import LinearGradient from 'react-native-linear-gradient'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
 import {UserAutocompleteViewModel} from '../../../state/models/user-autocomplete-view'
-import {UserLocalPhotosModel} from '../../../state/models/user-local-photos'
 import {Autocomplete} from './Autocomplete'
 import * as Toast from '../util/Toast'
 import ProgressCircle from '../util/ProgressCircle'
@@ -26,7 +23,8 @@ import * as apilib from '../../../state/lib/api'
 import {ComposerOpts} from '../../../state/models/shell-ui'
 import {s, colors, gradients} from '../../lib/styles'
 import {detectLinkables} from '../../../lib/strings'
-import {openPicker, openCamera} from 'react-native-image-crop-picker'
+import {PhotoCarouselPicker} from './PhotoCarouselPicker'
+import {UserLocalPhotosModel} from '../../../state/models/user-local-photos'
 
 const MAX_TEXT_LENGTH = 256
 const DANGER_TEXT_LENGTH = MAX_TEXT_LENGTH
@@ -45,7 +43,8 @@ export const ComposePost = observer(function ComposePost({
   const [isProcessing, setIsProcessing] = useState(false)
   const [error, setError] = useState('')
   const [text, setText] = useState('')
-  const [photoUris, setPhotoUris] = useState<string[]>([])
+  const [selectedPhotos, setSelectedPhotos] = useState<string[]>([])
+
   const autocompleteView = useMemo<UserAutocompleteViewModel>(
     () => new UserAutocompleteViewModel(store),
     [],
@@ -58,6 +57,11 @@ export const ComposePost = observer(function ComposePost({
   useEffect(() => {
     autocompleteView.setup()
   })
+
+  useEffect(() => {
+    localPhotos.setup()
+  }, [])
+
   useEffect(() => {
     // HACK
     // wait a moment before focusing the input to resolve some layout bugs with the keyboard-avoiding-view
@@ -75,10 +79,6 @@ export const ComposePost = observer(function ComposePost({
     }
   }, [textInput.current])
 
-  useEffect(() => {
-    localPhotos.setup()
-  }, [])
-
   const onChangeText = (newText: string) => {
     setText(newText)
 
@@ -207,7 +207,13 @@ export const ComposePost = observer(function ComposePost({
             </View>
           </View>
         ) : undefined}
-        <View style={styles.textInputLayout}>
+        <View
+          style={[
+            styles.textInputLayout,
+            selectedPhotos.length !== 0
+              ? styles.textInputLayoutWithPhoto
+              : styles.textInputLayoutWithoutPhoto,
+          ]}>
           <UserAvatar
             handle={store.me.handle || ''}
             displayName={store.me.displayName}
@@ -223,100 +229,12 @@ export const ComposePost = observer(function ComposePost({
             {textDecorated}
           </TextInput>
         </View>
-        {photoUris.length !== 0 && (
-          <View style={styles.selectedImageContainer}>
-            {photoUris.length !== 0 &&
-              photoUris.map((item, index) => (
-                <View
-                  key={`selected-image-${index}`}
-                  style={[
-                    styles.selectedImage,
-                    photoUris.length === 1
-                      ? styles.selectedImage250
-                      : photoUris.length === 2
-                      ? styles.selectedImage175
-                      : styles.selectedImage85,
-                  ]}>
-                  <TouchableOpacity
-                    onPress={() => {
-                      setPhotoUris(
-                        photoUris.filter(filterItem => filterItem !== item),
-                      )
-                    }}
-                    style={styles.removePhotoButton}>
-                    <FontAwesomeIcon
-                      icon="xmark"
-                      size={16}
-                      style={{color: colors.white}}
-                    />
-                  </TouchableOpacity>
-
-                  <Image
-                    style={[
-                      styles.selectedImage,
-                      photoUris.length === 1
-                        ? styles.selectedImage250
-                        : photoUris.length === 2
-                        ? styles.selectedImage175
-                        : styles.selectedImage85,
-                    ]}
-                    source={{uri: item}}
-                  />
-                </View>
-              ))}
-          </View>
-        )}
-        {localPhotos.photos != null && text === '' && photoUris.length === 0 && (
-          <ScrollView
-            horizontal
-            style={styles.photosContainer}
-            showsHorizontalScrollIndicator={false}>
-            <TouchableOpacity
-              style={[styles.galleryButton, styles.photo]}
-              onPress={() => {
-                openCamera({multiple: true, maxFiles: 4}).then()
-              }}>
-              <FontAwesomeIcon
-                icon="camera"
-                size={24}
-                style={{color: colors.blue3}}
-              />
-            </TouchableOpacity>
-            {localPhotos.photos.map((item, index) => (
-              <TouchableOpacity
-                key={`local-image-${index}`}
-                style={styles.photoButton}
-                onPress={() => {
-                  setPhotoUris([item.node.image.uri, ...photoUris])
-                }}>
-                <Image
-                  style={styles.photo}
-                  source={{uri: item.node.image.uri}}
-                />
-              </TouchableOpacity>
-            ))}
-            <TouchableOpacity
-              style={[styles.galleryButton, styles.photo]}
-              onPress={() => {
-                openPicker({multiple: true, maxFiles: 4}).then(items => {
-                  setPhotoUris([
-                    ...items.reduce(
-                      (accum, cur) => accum.concat(cur.sourceURL!),
-                      [] as string[],
-                    ),
-                    ...photoUris,
-                  ])
-                })
-              }}>
-              <FontAwesomeIcon
-                icon="image"
-                style={{color: colors.blue3}}
-                size={24}
-              />
-            </TouchableOpacity>
-          </ScrollView>
-        )}
-        <View style={styles.separator} />
+        <PhotoCarouselPicker
+          selectedPhotos={selectedPhotos}
+          setSelectedPhotos={setSelectedPhotos}
+          localPhotos={localPhotos}
+          inputText={text}
+        />
         <View style={[s.flexRow, s.pt10, s.pb10, s.pr5, styles.contentCenter]}>
           <View style={s.flex1} />
           <Text style={[s.mr10, {color: progressColor}]}>
@@ -390,9 +308,14 @@ const styles = StyleSheet.create({
     justifyContent: 'center',
     marginRight: 5,
   },
+  textInputLayoutWithPhoto: {
+    flexWrap: 'wrap',
+  },
+  textInputLayoutWithoutPhoto: {
+    flex: 1,
+  },
   textInputLayout: {
     flexDirection: 'row',
-    flex: 1,
     borderTopWidth: 1,
     borderTopColor: colors.gray2,
     paddingTop: 16,
@@ -416,68 +339,4 @@ const styles = StyleSheet.create({
     paddingRight: 8,
   },
   contentCenter: {alignItems: 'center'},
-  selectedImageContainer: {
-    flex: 10,
-    flexDirection: 'row',
-  },
-  selectedImage: {
-    borderRadius: 8,
-    margin: 2,
-  },
-  selectedImage250: {
-    width: 250,
-    height: 250,
-  },
-  selectedImage175: {
-    width: 175,
-    height: 175,
-  },
-  selectedImage85: {
-    width: 85,
-    height: 85,
-  },
-  photosContainer: {
-    width: '100%',
-    maxHeight: 96,
-    padding: 8,
-    overflow: 'hidden',
-  },
-  removePhotoButton: {
-    position: 'absolute',
-    top: 8,
-    right: 8,
-    width: 24,
-    height: 24,
-    borderRadius: 12,
-    alignItems: 'center',
-    justifyContent: 'center',
-    backgroundColor: colors.black,
-    zIndex: 1,
-  },
-  galleryButton: {
-    borderWidth: 1,
-    borderColor: colors.gray3,
-    alignItems: 'center',
-    justifyContent: 'center',
-  },
-  photoButton: {
-    width: 75,
-    height: 75,
-    marginRight: 8,
-    borderWidth: 1,
-    borderRadius: 16,
-    borderColor: colors.gray3,
-  },
-  photo: {
-    width: 75,
-    height: 75,
-    marginRight: 8,
-    borderRadius: 16,
-  },
-  separator: {
-    borderBottomColor: 'black',
-    borderBottomWidth: StyleSheet.hairlineWidth,
-    width: '110%',
-    marginLeft: -16,
-  },
 })
diff --git a/src/view/com/composer/PhotoCarouselPicker.tsx b/src/view/com/composer/PhotoCarouselPicker.tsx
new file mode 100644
index 000000000..f3c3b89c0
--- /dev/null
+++ b/src/view/com/composer/PhotoCarouselPicker.tsx
@@ -0,0 +1,192 @@
+import React from 'react'
+import {
+  Image,
+  StyleSheet,
+  TouchableOpacity,
+  View,
+  ScrollView,
+} from 'react-native'
+import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
+import {colors} from '../../lib/styles'
+import {openPicker, openCamera} from 'react-native-image-crop-picker'
+import {observer} from 'mobx-react-lite'
+
+export const PhotoCarouselPicker = observer(function PhotoCarouselPicker({
+  selectedPhotos,
+  setSelectedPhotos,
+  inputText,
+  localPhotos,
+}: {
+  selectedPhotos: string[]
+  setSelectedPhotos: React.Dispatch<React.SetStateAction<string[]>>
+  inputText: string
+  localPhotos: any
+}) {
+  return (
+    <>
+      {selectedPhotos.length !== 0 && (
+        <View style={styles.selectedImageContainer}>
+          {selectedPhotos.length !== 0 &&
+            selectedPhotos.map((item, index) => (
+              <View
+                key={`selected-image-${index}`}
+                style={[
+                  styles.selectedImage,
+                  selectedPhotos.length === 1
+                    ? styles.selectedImage250
+                    : selectedPhotos.length === 2
+                    ? styles.selectedImage175
+                    : styles.selectedImage85,
+                ]}>
+                <TouchableOpacity
+                  onPress={() => {
+                    setSelectedPhotos(
+                      selectedPhotos.filter(filterItem => filterItem !== item),
+                    )
+                  }}
+                  style={styles.removePhotoButton}>
+                  <FontAwesomeIcon
+                    icon="xmark"
+                    size={16}
+                    style={{color: colors.white}}
+                  />
+                </TouchableOpacity>
+
+                <Image
+                  style={[
+                    styles.selectedImage,
+                    selectedPhotos.length === 1
+                      ? styles.selectedImage250
+                      : selectedPhotos.length === 2
+                      ? styles.selectedImage175
+                      : styles.selectedImage85,
+                  ]}
+                  source={{uri: item}}
+                />
+              </View>
+            ))}
+        </View>
+      )}
+      {localPhotos.photos != null &&
+        inputText === '' &&
+        selectedPhotos.length === 0 && (
+          <ScrollView
+            horizontal
+            style={styles.photosContainer}
+            showsHorizontalScrollIndicator={false}>
+            <TouchableOpacity
+              style={[styles.galleryButton, styles.photo]}
+              onPress={() => {
+                openCamera({multiple: true, maxFiles: 4}).then()
+              }}>
+              <FontAwesomeIcon
+                icon="camera"
+                size={24}
+                style={{color: colors.blue3}}
+              />
+            </TouchableOpacity>
+            {localPhotos.photos.map((item: any, index: number) => (
+              <TouchableOpacity
+                key={`local-image-${index}`}
+                style={styles.photoButton}
+                onPress={() => {
+                  setSelectedPhotos([item.node.image.uri, ...selectedPhotos])
+                }}>
+                <Image
+                  style={styles.photo}
+                  source={{uri: item.node.image.uri}}
+                />
+              </TouchableOpacity>
+            ))}
+            <TouchableOpacity
+              style={[styles.galleryButton, styles.photo]}
+              onPress={() => {
+                openPicker({multiple: true, maxFiles: 4}).then(items => {
+                  setSelectedPhotos([
+                    ...items.reduce(
+                      (accum, cur) => accum.concat(cur.sourceURL!),
+                      [] as string[],
+                    ),
+                    ...selectedPhotos,
+                  ])
+                })
+              }}>
+              <FontAwesomeIcon
+                icon="image"
+                style={{color: colors.blue3}}
+                size={24}
+              />
+            </TouchableOpacity>
+          </ScrollView>
+        )}
+      <View style={styles.separator} />
+    </>
+  )
+})
+
+const styles = StyleSheet.create({
+  selectedImageContainer: {
+    flex: 1,
+    flexDirection: 'row',
+    marginTop: 16,
+  },
+  selectedImage: {
+    borderRadius: 8,
+    margin: 2,
+  },
+  selectedImage250: {
+    width: 250,
+    height: 250,
+  },
+  selectedImage175: {
+    width: 175,
+    height: 175,
+  },
+  selectedImage85: {
+    width: 85,
+    height: 85,
+  },
+  photosContainer: {
+    width: '100%',
+    maxHeight: 96,
+    padding: 8,
+    overflow: 'hidden',
+  },
+  removePhotoButton: {
+    position: 'absolute',
+    top: 8,
+    right: 8,
+    width: 24,
+    height: 24,
+    borderRadius: 12,
+    alignItems: 'center',
+    justifyContent: 'center',
+    backgroundColor: colors.black,
+    zIndex: 1,
+  },
+  galleryButton: {
+    borderWidth: 1,
+    borderColor: colors.gray3,
+    alignItems: 'center',
+    justifyContent: 'center',
+  },
+  photoButton: {
+    width: 75,
+    height: 75,
+    marginRight: 8,
+    borderWidth: 1,
+    borderRadius: 16,
+    borderColor: colors.gray3,
+  },
+  photo: {
+    width: 75,
+    height: 75,
+    marginRight: 8,
+    borderRadius: 16,
+  },
+  separator: {
+    borderBottomColor: 'black',
+    borderBottomWidth: StyleSheet.hairlineWidth,
+    width: '100%',
+  },
+})