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.tsx111
-rw-r--r--src/view/com/composer/PhotoCarouselPicker.tsx11
-rw-r--r--src/view/com/posts/FeedItem.tsx5
-rw-r--r--src/view/com/util/images/AutoSizedImage.tsx59
-rw-r--r--src/view/index.ts10
5 files changed, 116 insertions, 80 deletions
diff --git a/src/view/com/composer/ComposePost.tsx b/src/view/com/composer/ComposePost.tsx
index c6d371bc6..65120b663 100644
--- a/src/view/com/composer/ComposePost.tsx
+++ b/src/view/com/composer/ComposePost.tsx
@@ -4,6 +4,7 @@ import {
   ActivityIndicator,
   KeyboardAvoidingView,
   SafeAreaView,
+  ScrollView,
   StyleSheet,
   Text,
   TextInput,
@@ -32,6 +33,7 @@ import {SelectedPhoto} from './SelectedPhoto'
 
 const MAX_TEXT_LENGTH = 256
 const DANGER_TEXT_LENGTH = MAX_TEXT_LENGTH
+const HITSLOP = {left: 10, top: 10, right: 10, bottom: 10}
 
 export const ComposePost = observer(function ComposePost({
   replyTo,
@@ -48,6 +50,7 @@ export const ComposePost = observer(function ComposePost({
   const [processingState, setProcessingState] = useState('')
   const [error, setError] = useState('')
   const [text, setText] = useState('')
+  const [isSelectingPhotos, setIsSelectingPhotos] = useState(false)
   const [selectedPhotos, setSelectedPhotos] = useState<string[]>([])
 
   const autocompleteView = useMemo<UserAutocompleteViewModel>(
@@ -81,10 +84,17 @@ export const ComposePost = observer(function ComposePost({
     }
   }, [])
 
+  const onPressSelectPhotos = () => {
+    if (isSelectingPhotos) {
+      setIsSelectingPhotos(false)
+    } else if (selectedPhotos.length < 4) {
+      setIsSelectingPhotos(true)
+    }
+  }
   const onSelectPhotos = (photos: string[]) => {
     setSelectedPhotos(photos)
+    setIsSelectingPhotos(false)
   }
-
   const onChangeText = (newText: string) => {
     setText(newText)
 
@@ -211,55 +221,71 @@ export const ComposePost = observer(function ComposePost({
             <Text style={[s.red4, s.flex1]}>{error}</Text>
           </View>
         )}
-        {replyTo ? (
-          <View style={styles.replyToLayout}>
+        <ScrollView style={s.flex1}>
+          {replyTo ? (
+            <View style={styles.replyToLayout}>
+              <UserAvatar
+                handle={replyTo.author.handle}
+                displayName={replyTo.author.displayName}
+                avatar={replyTo.author.avatar}
+                size={50}
+              />
+              <View style={styles.replyToPost}>
+                <TextLink
+                  href={`/profile/${replyTo.author.handle}`}
+                  text={replyTo.author.displayName || replyTo.author.handle}
+                  style={[s.f16, s.bold]}
+                />
+                <Text style={[s.f16, s['lh16-1.3']]} numberOfLines={6}>
+                  {replyTo.text}
+                </Text>
+              </View>
+            </View>
+          ) : undefined}
+          <View style={[styles.textInputLayout, selectTextInputLayout]}>
             <UserAvatar
-              handle={replyTo.author.handle}
-              displayName={replyTo.author.displayName}
-              avatar={replyTo.author.avatar}
+              handle={store.me.handle || ''}
+              displayName={store.me.displayName}
+              avatar={store.me.avatar}
               size={50}
             />
-            <View style={styles.replyToPost}>
-              <TextLink
-                href={`/profile/${replyTo.author.handle}`}
-                text={replyTo.author.displayName || replyTo.author.handle}
-                style={[s.f16, s.bold]}
-              />
-              <Text style={[s.f16, s['lh16-1.3']]} numberOfLines={6}>
-                {replyTo.text}
-              </Text>
-            </View>
+            <TextInput
+              ref={textInput}
+              multiline
+              scrollEnabled
+              onChangeText={(text: string) => onChangeText(text)}
+              placeholder={selectTextInputPlaceholder}
+              style={styles.textInput}>
+              {textDecorated}
+            </TextInput>
           </View>
-        ) : undefined}
-        <View style={[styles.textInputLayout, selectTextInputLayout]}>
-          <UserAvatar
-            handle={store.me.handle || ''}
-            displayName={store.me.displayName}
-            avatar={store.me.avatar}
-            size={50}
-          />
-          <TextInput
-            ref={textInput}
-            multiline
-            scrollEnabled
-            onChangeText={(text: string) => onChangeText(text)}
-            placeholder={selectTextInputPlaceholder}
-            style={styles.textInput}>
-            {textDecorated}
-          </TextInput>
-        </View>
-        <SelectedPhoto
-          selectedPhotos={selectedPhotos}
-          onSelectPhotos={onSelectPhotos}
-        />
-        {localPhotos.photos != null && selectedPhotos.length < 4 && (
-          <PhotoCarouselPicker
+          <SelectedPhoto
             selectedPhotos={selectedPhotos}
             onSelectPhotos={onSelectPhotos}
-            localPhotos={localPhotos}
           />
-        )}
+        </ScrollView>
+        {isSelectingPhotos &&
+          localPhotos.photos != null &&
+          selectedPhotos.length < 4 && (
+            <PhotoCarouselPicker
+              selectedPhotos={selectedPhotos}
+              onSelectPhotos={onSelectPhotos}
+              localPhotos={localPhotos}
+            />
+          )}
         <View style={styles.bottomBar}>
+          <TouchableOpacity
+            onPress={onPressSelectPhotos}
+            style={[s.pl5]}
+            hitSlop={HITSLOP}>
+            <FontAwesomeIcon
+              icon={['far', 'image']}
+              style={{
+                color: selectedPhotos.length < 4 ? colors.blue3 : colors.gray3,
+              }}
+              size={24}
+            />
+          </TouchableOpacity>
           <View style={s.flex1} />
           <Text style={[s.mr10, {color: progressColor}]}>
             {MAX_TEXT_LENGTH - text.length}
@@ -392,5 +418,6 @@ const styles = StyleSheet.create({
     alignItems: 'center',
     borderTopWidth: 1,
     borderTopColor: colors.gray2,
+    backgroundColor: colors.white,
   },
 })
diff --git a/src/view/com/composer/PhotoCarouselPicker.tsx b/src/view/com/composer/PhotoCarouselPicker.tsx
index 7095e9dd1..86d23313d 100644
--- a/src/view/com/composer/PhotoCarouselPicker.tsx
+++ b/src/view/com/composer/PhotoCarouselPicker.tsx
@@ -86,6 +86,11 @@ export const PhotoCarouselPicker = ({
           style={{color: colors.blue3}}
         />
       </TouchableOpacity>
+      <TouchableOpacity
+        style={[styles.galleryButton, styles.photo]}
+        onPress={handleOpenGallery}>
+        <FontAwesomeIcon icon="image" style={{color: colors.blue3}} size={24} />
+      </TouchableOpacity>
       {localPhotos.photos.map((item: any, index: number) => (
         <TouchableOpacity
           key={`local-image-${index}`}
@@ -94,11 +99,6 @@ export const PhotoCarouselPicker = ({
           <Image style={styles.photo} source={{uri: item.node.image.uri}} />
         </TouchableOpacity>
       ))}
-      <TouchableOpacity
-        style={[styles.galleryButton, styles.photo]}
-        onPress={handleOpenGallery}>
-        <FontAwesomeIcon icon="image" style={{color: colors.blue3}} size={24} />
-      </TouchableOpacity>
     </ScrollView>
   )
 }
@@ -109,6 +109,7 @@ const styles = StyleSheet.create({
     maxHeight: 96,
     padding: 8,
     overflow: 'hidden',
+    backgroundColor: colors.white,
   },
   galleryButton: {
     borderWidth: 1,
diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx
index e66858ff6..984fde289 100644
--- a/src/view/com/posts/FeedItem.tsx
+++ b/src/view/com/posts/FeedItem.tsx
@@ -193,7 +193,7 @@ export const FeedItem = observer(function FeedItem({
                 style={styles.postText}
               />
             </View>
-            <PostEmbeds embed={item.embed} style={{marginBottom: 10}} />
+            <PostEmbeds embed={item.embed} style={styles.postEmbeds} />
             <PostCtrls
               replyCount={item.replyCount}
               repostCount={item.repostCount}
@@ -278,4 +278,7 @@ const styles = StyleSheet.create({
     fontSize: 16,
     lineHeight: 20.8, // 1.3 of 16px
   },
+  postEmbeds: {
+    marginBottom: 10,
+  },
 })
diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx
index 4728f42df..a60ddb89c 100644
--- a/src/view/com/util/images/AutoSizedImage.tsx
+++ b/src/view/com/util/images/AutoSizedImage.tsx
@@ -1,4 +1,4 @@
-import React, {useState, useEffect, useMemo} from 'react'
+import React, {useState, useEffect} from 'react'
 import {
   Image,
   ImageStyle,
@@ -8,6 +8,7 @@ import {
   Text,
   TouchableWithoutFeedback,
   View,
+  ViewStyle,
 } from 'react-native'
 import {colors} from '../../../lib/styles'
 
@@ -30,39 +31,29 @@ export function AutoSizedImage({
   const [error, setError] = useState<string | undefined>()
   const [imgInfo, setImgInfo] = useState<Dim | undefined>()
   const [containerInfo, setContainerInfo] = useState<Dim | undefined>()
-  const calculatedStyle = useMemo(() => {
-    if (imgInfo && containerInfo) {
-      // imgInfo.height / imgInfo.width = x / containerInfo.width
-      // x = imgInfo.height / imgInfo.width * containerInfo.width
-      return {
-        height: Math.min(
-          MAX_HEIGHT,
-          (imgInfo.height / imgInfo.width) * containerInfo.width,
-        ),
-      }
-    }
-    return undefined
-  }, [imgInfo, containerInfo])
 
   useEffect(() => {
     let aborted = false
-    Image.getSize(
-      uri,
-      (width: number, height: number) => {
-        if (!aborted) {
-          setImgInfo({width, height})
-        }
-      },
-      (error: any) => {
-        if (!aborted) {
-          setError(String(error))
-        }
-      },
-    )
+    if (!imgInfo) {
+      Image.getSize(
+        uri,
+        (width: number, height: number) => {
+          console.log('gotSize')
+          if (!aborted) {
+            setImgInfo({width, height})
+          }
+        },
+        (error: any) => {
+          if (!aborted) {
+            setError(String(error))
+          }
+        },
+      )
+    }
     return () => {
       aborted = true
     }
-  }, [uri])
+  }, [uri, imgInfo])
 
   const onLayout = (evt: LayoutChangeEvent) => {
     setContainerInfo({
@@ -71,6 +62,18 @@ export function AutoSizedImage({
     })
   }
 
+  let calculatedStyle: StyleProp<ViewStyle> | undefined
+  if (imgInfo && containerInfo) {
+    // imgInfo.height / imgInfo.width = x / containerInfo.width
+    // x = imgInfo.height / imgInfo.width * containerInfo.width
+    calculatedStyle = {
+      height: Math.min(
+        MAX_HEIGHT,
+        (imgInfo.height / imgInfo.width) * containerInfo.width,
+      ),
+    }
+  }
+
   return (
     <View style={style}>
       <TouchableWithoutFeedback onPress={onPress}>
diff --git a/src/view/index.ts b/src/view/index.ts
index 71769471b..8f119cd16 100644
--- a/src/view/index.ts
+++ b/src/view/index.ts
@@ -18,6 +18,7 @@ import {faBell} from '@fortawesome/free-solid-svg-icons/faBell'
 import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell'
 import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark'
 import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark'
+import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera'
 import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
 import {faCircleCheck} from '@fortawesome/free-regular-svg-icons/faCircleCheck'
 import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
@@ -33,6 +34,8 @@ import {faGlobe} from '@fortawesome/free-solid-svg-icons/faGlobe'
 import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
 import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart'
 import {faHouse} from '@fortawesome/free-solid-svg-icons/faHouse'
+import {faImage as farImage} from '@fortawesome/free-regular-svg-icons/faImage'
+import {faImage} from '@fortawesome/free-solid-svg-icons/faImage'
 import {faLink} from '@fortawesome/free-solid-svg-icons/faLink'
 import {faLock} from '@fortawesome/free-solid-svg-icons/faLock'
 import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass'
@@ -58,8 +61,6 @@ import {faUserXmark} from '@fortawesome/free-solid-svg-icons/faUserXmark'
 import {faTicket} from '@fortawesome/free-solid-svg-icons/faTicket'
 import {faTrashCan} from '@fortawesome/free-regular-svg-icons/faTrashCan'
 import {faX} from '@fortawesome/free-solid-svg-icons/faX'
-import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera'
-import {faImage} from '@fortawesome/free-solid-svg-icons/faImage'
 import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark'
 
 export function setup() {
@@ -82,6 +83,7 @@ export function setup() {
     farBell,
     faBookmark,
     farBookmark,
+    faCamera,
     faCheck,
     faCircleCheck,
     faCircleUser,
@@ -97,6 +99,8 @@ export function setup() {
     faHeart,
     fasHeart,
     faHouse,
+    faImage,
+    farImage,
     faLink,
     faLock,
     faMagnifyingGlass,
@@ -122,8 +126,6 @@ export function setup() {
     faTicket,
     faTrashCan,
     faX,
-    faCamera,
-    faImage,
     faXmark,
   )
 }