import React, {useMemo} from 'react' import {observer} from 'mobx-react-lite' import {StyleSheet, Text, View} from 'react-native' import {AtUri} from '../../../third-party/uri' import {FontAwesomeIcon, 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 {UpIconSolid} from '../../lib/icons' import {UserAvatar} from '../util/UserAvatar' import {ErrorMessage} from '../util/ErrorMessage' import {Post} from '../post/Post' import {Link} from '../util/Link' import {InviteAccepter} from './InviteAccepter' const MAX_AUTHORS = 8 export const FeedItem = observer(function FeedItem({ item, }: { item: NotificationsViewItemModel }) { const itemHref = useMemo(() => { if (item.isUpvote || item.isRepost || item.isTrend) { const urip = new AtUri(item.subjectUri) return `/profile/${urip.host}/post/${urip.rkey}` } else if (item.isFollow || item.isAssertion) { return `/profile/${item.author.handle}` } else if (item.isReply) { const urip = new AtUri(item.uri) return `/profile/${urip.host}/post/${urip.rkey}` } return '' }, [item]) const itemTitle = useMemo(() => { if (item.isUpvote || item.isRepost) { return 'Post' } else if (item.isFollow || item.isAssertion) { return item.author.handle } else if (item.isReply) { return 'Post' } }, [item]) if (item.additionalPost?.notFound) { // don't render anything if the target post was deleted or unfindable return } if (item.isReply) { return ( ) } let action = '' let icon: Props['icon'] | 'UpIconSolid' let iconStyle: Props['style'] = [] if (item.isUpvote) { action = 'upvoted your post' icon = 'UpIconSolid' iconStyle = [s.red3, {position: 'relative', top: -4}] } else if (item.isRepost) { action = 'reposted your post' icon = 'retweet' iconStyle = [s.green3] } else if (item.isTrend) { action = 'Your post is trending with' icon = 'arrow-trend-up' iconStyle = [s.red3] } else if (item.isReply) { action = 'replied to your post' icon = ['far', 'comment'] } else if (item.isFollow) { action = 'followed you' icon = 'user-plus' iconStyle = [s.blue3] } else if (item.isInvite) { icon = 'users' iconStyle = [s.blue3] action = 'invited you to join their scene' } else { return <> } let authors: {href: string; handle: string; displayName?: string}[] = [ { href: `/profile/${item.author.handle}`, handle: item.author.handle, displayName: item.author.displayName, }, ] if (item.additional?.length) { authors = authors.concat( item.additional.map(item2 => ({ href: `/profile/${item2.author.handle}`, handle: item2.author.handle, displayName: item2.author.displayName, })), ) } return ( {icon === 'UpIconSolid' ? ( ) : ( )} {authors.slice(0, MAX_AUTHORS).map(author => ( ))} {authors.length > MAX_AUTHORS ? ( +{authors.length - MAX_AUTHORS} ) : undefined} {item.isTrend && ( {action} )} {authors[0].displayName || authors[0].handle} {authors.length > 1 ? ( <> and {authors.length - 1} {pluralize(authors.length - 1, 'other')} ) : undefined} {!item.isTrend && ( {action} )} {ago(item.indexedAt)} {item.isUpvote || item.isRepost || item.isTrend ? ( ) : ( <> )} {item.isInvite && ( )} ) }) function AdditionalPostText({ additionalPost, }: { additionalPost?: PostThreadViewModel }) { if (!additionalPost) { return } if (additionalPost.error) { return } return {additionalPost.thread?.record.text} } const styles = StyleSheet.create({ outer: { backgroundColor: colors.white, padding: 10, borderRadius: 6, margin: 2, marginBottom: 0, }, outerMinimal: { backgroundColor: colors.white, borderRadius: 6, margin: 2, marginBottom: 0, }, outerUnread: { backgroundColor: colors.unreadNotifBg, borderWidth: 1, borderColor: colors.blue1, }, layout: { flexDirection: 'row', }, layoutIcon: { width: 35, alignItems: 'flex-end', }, icon: { marginRight: 10, marginTop: 4, }, avis: { flexDirection: 'row', alignItems: 'center', }, aviExtraCount: { fontWeight: 'bold', paddingLeft: 6, color: colors.gray5, }, layoutContent: { flex: 1, }, meta: { flexDirection: 'row', flexWrap: 'wrap', paddingTop: 6, paddingBottom: 2, }, metaItem: { paddingRight: 3, }, postText: { paddingBottom: 5, }, addedContainer: { paddingTop: 4, paddingLeft: 36, }, })