about summary refs log tree commit diff
path: root/src/view
diff options
context:
space:
mode:
Diffstat (limited to 'src/view')
-rw-r--r--src/view/com/notifications/Feed.tsx46
-rw-r--r--src/view/com/posts/Feed.tsx33
-rw-r--r--src/view/com/util/LoadMoreRetryBtn.tsx44
-rw-r--r--src/view/index.ts4
4 files changed, 111 insertions, 16 deletions
diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx
index 83fa0a990..2196b3469 100644
--- a/src/view/com/notifications/Feed.tsx
+++ b/src/view/com/notifications/Feed.tsx
@@ -6,12 +6,14 @@ import {NotificationsFeedModel} from 'state/models/feeds/notifications'
 import {FeedItem} from './FeedItem'
 import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
 import {ErrorMessage} from '../util/error/ErrorMessage'
+import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
 import {EmptyState} from '../util/EmptyState'
 import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
 import {s} from 'lib/styles'
 import {usePalette} from 'lib/hooks/usePalette'
 
 const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
+const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
 
 export const Feed = observer(function Feed({
   view,
@@ -34,8 +36,11 @@ export const Feed = observer(function Feed({
         feedItems = view.notifications
       }
     }
+    if (view.loadMoreError) {
+      feedItems = (feedItems || []).concat([LOAD_MORE_ERROR_ITEM])
+    }
     return feedItems
-  }, [view.hasLoaded, view.isEmpty, view.notifications])
+  }, [view.hasLoaded, view.isEmpty, view.notifications, view.loadMoreError])
 
   const onRefresh = React.useCallback(async () => {
     try {
@@ -45,6 +50,7 @@ export const Feed = observer(function Feed({
       view.rootStore.log.error('Failed to refresh notifications feed', err)
     }
   }, [view])
+
   const onEndReached = React.useCallback(async () => {
     try {
       await view.loadMore()
@@ -53,22 +59,36 @@ export const Feed = observer(function Feed({
     }
   }, [view])
 
+  const onPressRetryLoadMore = React.useCallback(() => {
+    view.retryLoadMore()
+  }, [view])
+
   // TODO optimize renderItem or FeedItem, we're getting this notice from RN: -prf
   //   VirtualizedList: You have a large list that is slow to update - make sure your
   //   renderItem function renders components that follow React performance best practices
   //   like PureComponent, shouldComponentUpdate, etc
-  const renderItem = React.useCallback(({item}: {item: any}) => {
-    if (item === EMPTY_FEED_ITEM) {
-      return (
-        <EmptyState
-          icon="bell"
-          message="No notifications yet!"
-          style={styles.emptyState}
-        />
-      )
-    }
-    return <FeedItem item={item} />
-  }, [])
+  const renderItem = React.useCallback(
+    ({item}: {item: any}) => {
+      if (item === EMPTY_FEED_ITEM) {
+        return (
+          <EmptyState
+            icon="bell"
+            message="No notifications yet!"
+            style={styles.emptyState}
+          />
+        )
+      } else if (item === LOAD_MORE_ERROR_ITEM) {
+        return (
+          <LoadMoreRetryBtn
+            label="There was an issue fetching notifications. Tap here to try again."
+            onPress={onPressRetryLoadMore}
+          />
+        )
+      }
+      return <FeedItem item={item} />
+    },
+    [onPressRetryLoadMore],
+  )
 
   const FeedFooter = React.useCallback(
     () =>
diff --git a/src/view/com/posts/Feed.tsx b/src/view/com/posts/Feed.tsx
index ddebe5e09..172124729 100644
--- a/src/view/com/posts/Feed.tsx
+++ b/src/view/com/posts/Feed.tsx
@@ -13,6 +13,7 @@ import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
 import {ErrorMessage} from '../util/error/ErrorMessage'
 import {PostsFeedModel} from 'state/models/feeds/posts'
 import {FeedSlice} from './FeedSlice'
+import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
 import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
 import {s} from 'lib/styles'
 import {useAnalytics} from 'lib/analytics'
@@ -21,6 +22,7 @@ import {usePalette} from 'lib/hooks/usePalette'
 const LOADING_ITEM = {_reactKey: '__loading__'}
 const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
 const ERROR_ITEM = {_reactKey: '__error__'}
+const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
 
 export const Feed = observer(function Feed({
   feed,
@@ -58,11 +60,21 @@ export const Feed = observer(function Feed({
       } else {
         feedItems = feedItems.concat(feed.slices)
       }
+      if (feed.loadMoreError) {
+        feedItems = feedItems.concat([LOAD_MORE_ERROR_ITEM])
+      }
     } else if (feed.isLoading) {
       feedItems = feedItems.concat([LOADING_ITEM])
     }
     return feedItems
-  }, [feed.hasError, feed.hasLoaded, feed.isLoading, feed.isEmpty, feed.slices])
+  }, [
+    feed.hasError,
+    feed.hasLoaded,
+    feed.isLoading,
+    feed.isEmpty,
+    feed.slices,
+    feed.loadMoreError,
+  ])
 
   // events
   // =
@@ -87,6 +99,10 @@ export const Feed = observer(function Feed({
     }
   }, [feed, track])
 
+  const onPressRetryLoadMore = React.useCallback(() => {
+    feed.retryLoadMore()
+  }, [feed])
+
   // rendering
   // =
 
@@ -104,12 +120,25 @@ export const Feed = observer(function Feed({
             onPressTryAgain={onPressTryAgain}
           />
         )
+      } else if (item === LOAD_MORE_ERROR_ITEM) {
+        return (
+          <LoadMoreRetryBtn
+            label="There was an issue fetching posts. Tap here to try again."
+            onPress={onPressRetryLoadMore}
+          />
+        )
       } else if (item === LOADING_ITEM) {
         return <PostFeedLoadingPlaceholder />
       }
       return <FeedSlice slice={item} showFollowBtn={showPostFollowBtn} />
     },
-    [feed, onPressTryAgain, showPostFollowBtn, renderEmptyState],
+    [
+      feed,
+      onPressTryAgain,
+      onPressRetryLoadMore,
+      showPostFollowBtn,
+      renderEmptyState,
+    ],
   )
 
   const FeedFooter = React.useCallback(
diff --git a/src/view/com/util/LoadMoreRetryBtn.tsx b/src/view/com/util/LoadMoreRetryBtn.tsx
new file mode 100644
index 000000000..a2e9838b3
--- /dev/null
+++ b/src/view/com/util/LoadMoreRetryBtn.tsx
@@ -0,0 +1,44 @@
+import React from 'react'
+import {StyleSheet} from 'react-native'
+import {
+  FontAwesomeIcon,
+  FontAwesomeIconStyle,
+} from '@fortawesome/react-native-fontawesome'
+import {Button} from './forms/Button'
+import {Text} from './text/Text'
+import {usePalette} from 'lib/hooks/usePalette'
+
+export function LoadMoreRetryBtn({
+  label,
+  onPress,
+}: {
+  label: string
+  onPress: () => void
+}) {
+  const pal = usePalette('default')
+  return (
+    <Button type="default-light" onPress={onPress} style={styles.loadMoreRetry}>
+      <FontAwesomeIcon
+        icon="arrow-rotate-left"
+        style={pal.textLight as FontAwesomeIconStyle}
+        size={18}
+      />
+      <Text style={[pal.textLight, styles.label]}>{label}</Text>
+    </Button>
+  )
+}
+
+const styles = StyleSheet.create({
+  loadMoreRetry: {
+    flexDirection: 'row',
+    gap: 14,
+    alignItems: 'center',
+    borderRadius: 0,
+    marginTop: 1,
+    paddingVertical: 12,
+    paddingHorizontal: 20,
+  },
+  label: {
+    flex: 1,
+  },
+})
diff --git a/src/view/index.ts b/src/view/index.ts
index 17e9dbbed..47a5f8acf 100644
--- a/src/view/index.ts
+++ b/src/view/index.ts
@@ -1,6 +1,6 @@
 import {library} from '@fortawesome/fontawesome-svg-core'
 
-import {faAddressCard} from '@fortawesome/free-regular-svg-icons/faAddressCard'
+import {faAddressCard} from '@fortawesome/free-regular-svg-icons'
 import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown'
 import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft'
 import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight'
@@ -14,6 +14,7 @@ import {
 } from '@fortawesome/free-solid-svg-icons'
 import {faArrowUpFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowUpFromBracket'
 import {faArrowUpRightFromSquare} from '@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare'
+import {faArrowRotateLeft} from '@fortawesome/free-solid-svg-icons/faArrowRotateLeft'
 import {faArrowsRotate} from '@fortawesome/free-solid-svg-icons/faArrowsRotate'
 import {faAt} from '@fortawesome/free-solid-svg-icons/faAt'
 import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
@@ -86,6 +87,7 @@ export function setup() {
     faArrowRightFromBracket,
     faArrowUpFromBracket,
     faArrowUpRightFromSquare,
+    faArrowRotateLeft,
     faArrowsRotate,
     faAt,
     faBars,