diff options
Diffstat (limited to 'src/view/com/notifications')
-rw-r--r-- | src/view/com/notifications/Feed.tsx | 82 | ||||
-rw-r--r-- | src/view/com/notifications/FeedItem.tsx | 29 |
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 |