about summary refs log tree commit diff
path: root/src/view/com/notifications
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/notifications')
-rw-r--r--src/view/com/notifications/Feed.tsx82
-rw-r--r--src/view/com/notifications/FeedItem.tsx29
2 files changed, 70 insertions, 41 deletions
diff --git a/src/view/com/notifications/Feed.tsx b/src/view/com/notifications/Feed.tsx
index 55e958c2b..5c1ee935b 100644
--- a/src/view/com/notifications/Feed.tsx
+++ b/src/view/com/notifications/Feed.tsx
@@ -1,31 +1,61 @@
-import React from 'react'
+import React, {MutableRefObject} from 'react'
 import {observer} from 'mobx-react-lite'
-import {StyleSheet, View} from 'react-native'
 import {CenteredView, FlatList} from '../util/Views'
-import {NotificationsViewModel} from '../../../state/models/notifications-view'
+import {ActivityIndicator, StyleSheet, View} from 'react-native'
+import {NotificationsViewModel} from 'state/models/notifications-view'
 import {FeedItem} from './FeedItem'
 import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
 import {ErrorMessage} from '../util/error/ErrorMessage'
 import {EmptyState} from '../util/EmptyState'
-import {OnScrollCb} from '../../lib/hooks/useOnMainScroll'
-import {s} from '../../lib/styles'
+import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
+import {s} from 'lib/styles'
 
 const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
 
 export const Feed = observer(function Feed({
   view,
+  scrollElRef,
   onPressTryAgain,
   onScroll,
 }: {
   view: NotificationsViewModel
+  scrollElRef?: MutableRefObject<FlatList<any> | null>
   onPressTryAgain?: () => void
   onScroll?: OnScrollCb
 }) {
+  const data = React.useMemo(() => {
+    let feedItems
+    if (view.hasLoaded) {
+      if (view.isEmpty) {
+        feedItems = [EMPTY_FEED_ITEM]
+      } else {
+        feedItems = view.notifications
+      }
+    }
+    return feedItems
+  }, [view.hasLoaded, view.isEmpty, view.notifications])
+
+  const onRefresh = React.useCallback(async () => {
+    try {
+      await view.refresh()
+      await view.markAllRead()
+    } catch (err) {
+      view.rootStore.log.error('Failed to refresh notifications feed', err)
+    }
+  }, [view])
+  const onEndReached = React.useCallback(async () => {
+    try {
+      await view.loadMore()
+    } catch (err) {
+      view.rootStore.log.error('Failed to load more notifications', err)
+    }
+  }, [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 = ({item}: {item: any}) => {
+  const renderItem = React.useCallback(({item}: {item: any}) => {
     if (item === EMPTY_FEED_ITEM) {
       return (
         <EmptyState
@@ -36,29 +66,20 @@ export const Feed = observer(function Feed({
       )
     }
     return <FeedItem item={item} />
-  }
-  const onRefresh = () => {
-    view
-      .refresh()
-      .catch(err =>
-        view.rootStore.log.error('Failed to refresh notifications feed', err),
-      )
-  }
-  const onEndReached = () => {
-    view
-      .loadMore()
-      .catch(err =>
-        view.rootStore.log.error('Failed to load more notifications', err),
-      )
-  }
-  let data
-  if (view.hasLoaded) {
-    if (view.isEmpty) {
-      data = [EMPTY_FEED_ITEM]
-    } else {
-      data = view.notifications
-    }
-  }
+  }, [])
+
+  const FeedFooter = React.useCallback(
+    () =>
+      view.isLoading ? (
+        <View style={styles.feedFooter}>
+          <ActivityIndicator />
+        </View>
+      ) : (
+        <View />
+      ),
+    [view],
+  )
+
   return (
     <View style={s.h100pct}>
       <CenteredView>
@@ -72,9 +93,11 @@ export const Feed = observer(function Feed({
       </CenteredView>
       {data && (
         <FlatList
+          ref={scrollElRef}
           data={data}
           keyExtractor={item => item._reactKey}
           renderItem={renderItem}
+          ListFooterComponent={FeedFooter}
           refreshing={view.isRefreshing}
           onRefresh={onRefresh}
           onEndReached={onEndReached}
@@ -87,5 +110,6 @@ export const Feed = observer(function Feed({
 })
 
 const styles = StyleSheet.create({
+  feedFooter: {paddingTop: 20},
   emptyState: {paddingVertical: 40},
 })
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx
index da6fc7d35..94bedc46f 100644
--- a/src/view/com/notifications/FeedItem.tsx
+++ b/src/view/com/notifications/FeedItem.tsx
@@ -14,19 +14,19 @@ import {
   FontAwesomeIconStyle,
   Props,
 } from '@fortawesome/react-native-fontawesome'
-import {NotificationsViewItemModel} from '../../../state/models/notifications-view'
-import {PostThreadViewModel} from '../../../state/models/post-thread-view'
-import {s, colors} from '../../lib/styles'
-import {ago, pluralize} from '../../../lib/strings'
-import {HeartIconSolid} from '../../lib/icons'
+import {NotificationsViewItemModel} from 'state/models/notifications-view'
+import {PostThreadViewModel} from 'state/models/post-thread-view'
+import {s, colors} from 'lib/styles'
+import {ago} from 'lib/strings/time'
+import {pluralize} from 'lib/strings/helpers'
+import {HeartIconSolid} from 'lib/icons'
 import {Text} from '../util/text/Text'
 import {UserAvatar} from '../util/UserAvatar'
 import {ImageHorzList} from '../util/images/ImageHorzList'
-import {ErrorMessage} from '../util/error/ErrorMessage'
 import {Post} from '../post/Post'
 import {Link} from '../util/Link'
-import {usePalette} from '../../lib/hooks/usePalette'
-import {useAnimatedValue} from '../../lib/hooks/useAnimatedValue'
+import {usePalette} from 'lib/hooks/usePalette'
+import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
 
 const MAX_AUTHORS = 5
 
@@ -78,6 +78,10 @@ export const FeedItem = observer(function FeedItem({
   }
 
   if (item.isReply || item.isMention) {
+    if (item.additionalPost?.error) {
+      // hide errors - it doesnt help the user to show them
+      return <View />
+    }
     return (
       <Link href={itemHref} title={itemTitle} noFeedback>
         <Post
@@ -347,12 +351,13 @@ function AdditionalPostText({
   additionalPost?: PostThreadViewModel
 }) {
   const pal = usePalette('default')
-  if (!additionalPost || !additionalPost.thread?.postRecord) {
+  if (
+    !additionalPost ||
+    !additionalPost.thread?.postRecord ||
+    additionalPost.error
+  ) {
     return <View />
   }
-  if (additionalPost.error) {
-    return <ErrorMessage message={additionalPost.error} />
-  }
   const text = additionalPost.thread?.postRecord.text
   const images = (
     additionalPost.thread.post.embed as AppBskyEmbedImages.Presented