about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAnsh <anshnanda10@gmail.com>2023-04-24 16:45:02 -0700
committerGitHub <noreply@github.com>2023-04-24 18:45:02 -0500
commitc5222db38b4520d495d942ae0b6e57d631b40d7b (patch)
tree45e4c2d09c171efb96abf5118a9de2b92d003657 /src
parent1b356556c91ed07025927d4cb0be90a269396822 (diff)
downloadvoidsky-c5222db38b4520d495d942ae0b6e57d631b40d7b.tar.zst
memoize things, clean code, and replace deprecated resizeMode with contentFit (#526)
Diffstat (limited to 'src')
-rw-r--r--src/view/com/notifications/FeedItem.tsx63
-rw-r--r--src/view/com/util/UserAvatar.tsx110
2 files changed, 95 insertions, 78 deletions
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx
index 02dea4204..a5c0ecba0 100644
--- a/src/view/com/notifications/FeedItem.tsx
+++ b/src/view/com/notifications/FeedItem.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, {useMemo, useState, useEffect} from 'react'
 import {observer} from 'mobx-react-lite'
 import {
   Animated,
@@ -47,8 +47,8 @@ export const FeedItem = observer(function FeedItem({
   item: NotificationsFeedItemModel
 }) {
   const pal = usePalette('default')
-  const [isAuthorsExpanded, setAuthorsExpanded] = React.useState<boolean>(false)
-  const itemHref = React.useMemo(() => {
+  const [isAuthorsExpanded, setAuthorsExpanded] = useState<boolean>(false)
+  const itemHref = useMemo(() => {
     if (item.isLike || item.isRepost) {
       const urip = new AtUri(item.subjectUri)
       return `/profile/${urip.host}/post/${urip.rkey}`
@@ -60,7 +60,7 @@ export const FeedItem = observer(function FeedItem({
     }
     return ''
   }, [item])
-  const itemTitle = React.useMemo(() => {
+  const itemTitle = useMemo(() => {
     if (item.isLike || item.isRepost) {
       return 'Post'
     } else if (item.isFollow) {
@@ -74,6 +74,35 @@ export const FeedItem = observer(function FeedItem({
     setAuthorsExpanded(!isAuthorsExpanded)
   }
 
+  const authors: Author[] = useMemo(() => {
+    return [
+      {
+        href: `/profile/${item.author.handle}`,
+        handle: item.author.handle,
+        displayName: item.author.displayName,
+        avatar: item.author.avatar,
+        labels: item.author.labels,
+      },
+      ...(item.additional?.map(
+        ({author: {avatar, labels, handle, displayName}}) => {
+          return {
+            href: `/profile/${handle}`,
+            handle,
+            displayName,
+            avatar,
+            labels,
+          }
+        },
+      ) || []),
+    ]
+  }, [
+    item.additional,
+    item.author.avatar,
+    item.author.displayName,
+    item.author.handle,
+    item.author.labels,
+  ])
+
   if (item.additionalPost?.notFound) {
     // don't render anything if the target post was deleted or unfindable
     return <View />
@@ -125,30 +154,9 @@ export const FeedItem = observer(function FeedItem({
     icon = 'user-plus'
     iconStyle = [s.blue3 as FontAwesomeIconStyle]
   } else {
-    return <></>
+    return null
   }
 
-  const authors: Author[] = [
-    {
-      href: `/profile/${item.author.handle}`,
-      handle: item.author.handle,
-      displayName: item.author.displayName,
-      avatar: item.author.avatar,
-      labels: item.author.labels,
-    },
-    ...(item.additional?.map(
-      ({author: {avatar, labels, handle, displayName}}) => {
-        return {
-          href: `/profile/${handle}`,
-          handle,
-          displayName,
-          avatar,
-          labels,
-        }
-      },
-    ) || []),
-  ]
-
   return (
     <Link
       testID={`feedItem-by-${item.author.handle}`}
@@ -301,13 +309,14 @@ function ExpandedAuthorsList({
   const heightStyle = {
     height: Animated.multiply(heightInterp, targetHeight),
   }
-  React.useEffect(() => {
+  useEffect(() => {
     Animated.timing(heightInterp, {
       toValue: visible ? 1 : 0,
       duration: 200,
       useNativeDriver: false,
     }).start()
   }, [heightInterp, visible])
+
   return (
     <Animated.View
       style={[
diff --git a/src/view/com/util/UserAvatar.tsx b/src/view/com/util/UserAvatar.tsx
index e13d49e61..9c0fe9297 100644
--- a/src/view/com/util/UserAvatar.tsx
+++ b/src/view/com/util/UserAvatar.tsx
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, {useMemo} from 'react'
 import {StyleSheet, View} from 'react-native'
 import Svg, {Circle, Path} from 'react-native-svg'
 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
@@ -53,61 +53,69 @@ export function UserAvatar({
   const {requestCameraAccessIfNeeded} = useCameraPermission()
   const {requestPhotoAccessIfNeeded} = usePhotoLibraryPermission()
 
-  const dropdownItems = [
-    !isWeb && {
-      testID: 'changeAvatarCameraBtn',
-      label: 'Camera',
-      icon: 'camera' as IconProp,
-      onPress: async () => {
-        if (!(await requestCameraAccessIfNeeded())) {
-          return
-        }
-        onSelectNewAvatar?.(
-          await openCamera(store, {
-            width: 1000,
-            height: 1000,
-            cropperCircleOverlay: true,
-          }),
-        )
+  const dropdownItems = useMemo(
+    () => [
+      !isWeb && {
+        testID: 'changeAvatarCameraBtn',
+        label: 'Camera',
+        icon: 'camera' as IconProp,
+        onPress: async () => {
+          if (!(await requestCameraAccessIfNeeded())) {
+            return
+          }
+          onSelectNewAvatar?.(
+            await openCamera(store, {
+              width: 1000,
+              height: 1000,
+              cropperCircleOverlay: true,
+            }),
+          )
+        },
       },
-    },
-    {
-      testID: 'changeAvatarLibraryBtn',
-      label: 'Library',
-      icon: 'image' as IconProp,
-      onPress: async () => {
-        if (!(await requestPhotoAccessIfNeeded())) {
-          return
-        }
-        const items = await openPicker(store, {
-          mediaType: 'photo',
-          multiple: false,
-        })
-
-        onSelectNewAvatar?.(
-          await openCropper(store, {
+      {
+        testID: 'changeAvatarLibraryBtn',
+        label: 'Library',
+        icon: 'image' as IconProp,
+        onPress: async () => {
+          if (!(await requestPhotoAccessIfNeeded())) {
+            return
+          }
+          const items = await openPicker(store, {
             mediaType: 'photo',
-            path: items[0].path,
-            width: 1000,
-            height: 1000,
-            cropperCircleOverlay: true,
-          }),
-        )
+            multiple: false,
+          })
+
+          onSelectNewAvatar?.(
+            await openCropper(store, {
+              mediaType: 'photo',
+              path: items[0].path,
+              width: 1000,
+              height: 1000,
+              cropperCircleOverlay: true,
+            }),
+          )
+        },
       },
-    },
-    {
-      testID: 'changeAvatarRemoveBtn',
-      label: 'Remove',
-      icon: ['far', 'trash-can'] as IconProp,
-      onPress: async () => {
-        onSelectNewAvatar?.(null)
+      {
+        testID: 'changeAvatarRemoveBtn',
+        label: 'Remove',
+        icon: ['far', 'trash-can'] as IconProp,
+        onPress: async () => {
+          onSelectNewAvatar?.(null)
+        },
       },
-    },
-  ]
+    ],
+    [
+      onSelectNewAvatar,
+      requestCameraAccessIfNeeded,
+      requestPhotoAccessIfNeeded,
+      store,
+    ],
+  )
 
-  const warning = React.useMemo(() => {
+  const warning = useMemo(() => {
     if (!hasWarning) {
-      return <></>
+      return null
     }
     return (
       <View style={[styles.warningIconContainer, pal.view]}>
@@ -156,7 +164,7 @@ export function UserAvatar({
       <HighPriorityImage
         testID="userAvatarImage"
         style={{width: size, height: size, borderRadius: Math.floor(size / 2)}}
-        resizeMode="stretch"
+        contentFit="cover"
         source={{uri: avatar}}
       />
       {warning}