about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-03-15 15:46:39 -0500
committerPaul Frazee <pfrazee@gmail.com>2023-03-15 15:46:39 -0500
commit474b4b7840ce1ee625f19ff02f15ca12b3879c55 (patch)
treef8e27a2ecb4b07c65f348e206a014a5f0ba06f29
parent8a279b8d2cd003755200426e2ab32d0522783744 (diff)
downloadvoidsky-474b4b7840ce1ee625f19ff02f15ca12b3879c55.tar.zst
Optimize and refactor profile rendering a bit
-rw-r--r--src/state/models/ui/profile.ts49
-rw-r--r--src/view/screens/Profile.tsx117
2 files changed, 90 insertions, 76 deletions
diff --git a/src/state/models/ui/profile.ts b/src/state/models/ui/profile.ts
index 1d4fe28cd..eb38509fb 100644
--- a/src/state/models/ui/profile.ts
+++ b/src/state/models/ui/profile.ts
@@ -15,6 +15,10 @@ export interface ProfileUiParams {
 }
 
 export class ProfileUiModel {
+  static LOADING_ITEM = {_reactKey: '__loading__'}
+  static END_ITEM = {_reactKey: '__end__'}
+  static EMPTY_ITEM = {_reactKey: '__empty__'}
+
   // data
   profile: ProfileViewModel
   feed: FeedModel
@@ -76,6 +80,51 @@ export class ProfileUiModel {
     return this.selectorItems[this.selectedViewIndex]
   }
 
+  get uiItems() {
+    let arr: any[] = []
+    if (this.isInitialLoading) {
+      arr = arr.concat([ProfileUiModel.LOADING_ITEM])
+    } else if (this.currentView.hasError) {
+      arr = arr.concat([
+        {
+          _reactKey: '__error__',
+          error: this.currentView.error,
+        },
+      ])
+    } else {
+      if (
+        this.selectedView === Sections.Posts ||
+        this.selectedView === Sections.PostsWithReplies
+      ) {
+        if (this.feed.hasContent) {
+          if (this.selectedView === Sections.Posts) {
+            arr = this.feed.nonReplyFeed
+          } else {
+            arr = this.feed.feed.slice()
+          }
+          if (!this.feed.hasMore) {
+            arr = arr.concat([ProfileUiModel.END_ITEM])
+          }
+        } else if (this.feed.isEmpty) {
+          arr = arr.concat([ProfileUiModel.EMPTY_ITEM])
+        }
+      } else {
+        arr = arr.concat([ProfileUiModel.EMPTY_ITEM])
+      }
+    }
+    return arr
+  }
+
+  get showLoadingMoreFooter() {
+    if (
+      this.selectedView === Sections.Posts ||
+      this.selectedView === Sections.PostsWithReplies
+    ) {
+      return this.feed.hasContent && this.feed.hasMore && this.feed.isLoading
+    }
+    return false
+  }
+
   // public api
   // =
 
diff --git a/src/view/screens/Profile.tsx b/src/view/screens/Profile.tsx
index c686bd266..a27fa6b82 100644
--- a/src/view/screens/Profile.tsx
+++ b/src/view/screens/Profile.tsx
@@ -8,6 +8,7 @@ import {ViewSelector} from '../com/util/ViewSelector'
 import {CenteredView} from '../com/util/Views'
 import {ProfileUiModel, Sections} from 'state/models/ui/profile'
 import {useStores} from 'state/index'
+import {FeedItemModel} from 'state/models/feed-view'
 import {ProfileHeader} from '../com/profile/ProfileHeader'
 import {FeedItem} from '../com/posts/FeedItem'
 import {PostFeedLoadingPlaceholder} from '../com/util/LoadingPlaceholder'
@@ -21,10 +22,6 @@ import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
 import {useAnalytics} from 'lib/analytics'
 import {ComposeIcon2} from 'lib/icons'
 
-const LOADING_ITEM = {_reactKey: '__loading__'}
-const END_ITEM = {_reactKey: '__end__'}
-const EMPTY_ITEM = {_reactKey: '__empty__'}
-
 type Props = NativeStackScreenProps<CommonNavigatorParams, 'Profile'>
 export const ProfileScreen = withAuthRequired(
   observer(({route}: Props) => {
@@ -73,98 +70,66 @@ export const ProfileScreen = withAuthRequired(
     const onSelectView = (index: number) => {
       uiState.setSelectedViewIndex(index)
     }
-    const onRefresh = () => {
+    const onRefresh = React.useCallback(() => {
       uiState
         .refresh()
         .catch((err: any) =>
           store.log.error('Failed to refresh user profile', err),
         )
-    }
-    const onEndReached = () => {
+    }, [uiState, store])
+    const onEndReached = React.useCallback(() => {
       uiState
         .loadMore()
         .catch((err: any) =>
           store.log.error('Failed to load more entries in user profile', err),
         )
-    }
-    const onPressTryAgain = () => {
+    }, [uiState, store])
+    const onPressTryAgain = React.useCallback(() => {
       uiState.setup()
-    }
+    }, [uiState])
 
     // rendering
     // =
 
-    const renderHeader = () => {
+    const renderHeader = React.useCallback(() => {
       if (!uiState) {
         return <View />
       }
       return <ProfileHeader view={uiState.profile} onRefreshAll={onRefresh} />
-    }
-    let renderItem
-    let Footer
-    let items: any[] = []
-    if (uiState) {
-      if (uiState.isInitialLoading) {
-        items = items.concat([LOADING_ITEM])
-        renderItem = () => <PostFeedLoadingPlaceholder />
-      } else if (uiState.currentView.hasError) {
-        items = items.concat([
-          {
-            _reactKey: '__error__',
-            error: uiState.currentView.error,
-          },
-        ])
-        renderItem = (item: any) => (
-          <View style={s.p5}>
-            <ErrorMessage
-              message={item.error}
-              onPressTryAgain={onPressTryAgain}
-            />
-          </View>
-        )
-      } else {
-        if (
-          uiState.selectedView === Sections.Posts ||
-          uiState.selectedView === Sections.PostsWithReplies
-        ) {
-          if (uiState.feed.hasContent) {
-            if (uiState.selectedView === Sections.Posts) {
-              items = uiState.feed.nonReplyFeed
-            } else {
-              items = uiState.feed.feed.slice()
-            }
-            if (!uiState.feed.hasMore) {
-              items = items.concat([END_ITEM])
-            } else if (uiState.feed.isLoading) {
-              Footer = LoadingMoreFooter
-            }
-            renderItem = (item: any) => {
-              if (item === END_ITEM) {
-                return <Text style={styles.endItem}>- end of feed -</Text>
-              }
-              return (
-                <FeedItem item={item} ignoreMuteFor={uiState.profile.did} />
-              )
-            }
-          } else if (uiState.feed.isEmpty) {
-            items = items.concat([EMPTY_ITEM])
-            renderItem = () => (
-              <EmptyState
-                icon={['far', 'message']}
-                message="No posts yet!"
-                style={styles.emptyState}
+    }, [uiState, onRefresh])
+    const Footer = React.useMemo(() => {
+      return uiState.showLoadingMoreFooter ? LoadingMoreFooter : undefined
+    }, [uiState.showLoadingMoreFooter])
+    const renderItem = React.useCallback(
+      (item: any) => {
+        if (item === ProfileUiModel.END_ITEM) {
+          return <Text style={styles.endItem}>- end of feed -</Text>
+        } else if (item === ProfileUiModel.LOADING_ITEM) {
+          return <PostFeedLoadingPlaceholder />
+        } else if (item._reactKey === '__error__') {
+          return (
+            <View style={s.p5}>
+              <ErrorMessage
+                message={item.error}
+                onPressTryAgain={onPressTryAgain}
               />
-            )
-          }
-        } else {
-          items = items.concat([EMPTY_ITEM])
-          renderItem = () => <Text>TODO</Text>
+            </View>
+          )
+        } else if (item === ProfileUiModel.EMPTY_ITEM) {
+          return (
+            <EmptyState
+              icon={['far', 'message']}
+              message="No posts yet!"
+              style={styles.emptyState}
+            />
+          )
+        } else if (item instanceof FeedItemModel) {
+          return <FeedItem item={item} ignoreMuteFor={uiState.profile.did} />
         }
-      }
-    }
-    if (!renderItem) {
-      renderItem = () => <View />
-    }
+        return <View />
+      },
+      [onPressTryAgain, uiState.profile.did],
+    )
 
     return (
       <View testID="profileView" style={styles.container}>
@@ -180,7 +145,7 @@ export const ProfileScreen = withAuthRequired(
           <ViewSelector
             swipeEnabled={false}
             sections={uiState.selectorItems}
-            items={items}
+            items={uiState.uiItems}
             renderHeader={renderHeader}
             renderItem={renderItem}
             ListFooterComponent={Footer}