diff options
Diffstat (limited to 'src/view/com')
-rw-r--r-- | src/view/com/notifications/FeedItem.tsx | 127 | ||||
-rw-r--r-- | src/view/com/post/Post.tsx | 27 |
2 files changed, 135 insertions, 19 deletions
diff --git a/src/view/com/notifications/FeedItem.tsx b/src/view/com/notifications/FeedItem.tsx index 1eca3806f..e76056067 100644 --- a/src/view/com/notifications/FeedItem.tsx +++ b/src/view/com/notifications/FeedItem.tsx @@ -5,12 +5,14 @@ import {AdxUri} from '../../../third-party/uri' import {FontAwesomeIcon, Props} from '@fortawesome/react-native-fontawesome' import {NotificationsViewItemModel} from '../../../state/models/notifications-view' import {s, colors} from '../../lib/styles' -import {ago} from '../../lib/strings' +import {ago, pluralize} from '../../lib/strings' import {DEF_AVATER} from '../../lib/assets' import {PostText} from '../post/PostText' import {Post} from '../post/Post' import {Link} from '../util/Link' +const MAX_AUTHORS = 8 + export const FeedItem = observer(function FeedItem({ item, }: { @@ -37,39 +39,108 @@ export const FeedItem = observer(function FeedItem({ return 'Post' } }, [item]) - const authorHref = `/profile/${item.author.name}` - const authorTitle = item.author.name + + if (item.isReply) { + return ( + <Link + style={[ + styles.outerMinimal, + item.isRead ? undefined : styles.outerUnread, + ]} + href={itemHref} + title={itemTitle}> + <Post uri={item.uri} /> + </Link> + ) + } let action = '' let icon: Props['icon'] + let iconStyle: Props['style'] = [] if (item.isLike) { action = 'liked your post' - icon = ['far', 'heart'] + icon = ['fas', 'heart'] + iconStyle = [s.blue3] } else if (item.isRepost) { action = 'reposted your post' icon = 'retweet' + iconStyle = [s.blue3] } else if (item.isReply) { action = 'replied to your post' icon = ['far', 'comment'] } else if (item.isFollow) { action = 'followed you' - icon = 'plus' + icon = 'user-plus' + iconStyle = [s.blue3] } else { return <></> } + let authors: {href: string; name: string; displayName?: string}[] = [ + { + href: `/profile/${item.author.name}`, + name: item.author.name, + displayName: item.author.displayName, + }, + ] + if (item.additional?.length) { + authors = authors.concat( + item.additional.map(item2 => ({ + href: `/profile/${item2.author.name}`, + name: item2.author.name, + displayName: item2.author.displayName, + })), + ) + } + return ( - <Link style={styles.outer} href={itemHref} title={itemTitle}> + <Link + style={[styles.outer, item.isRead ? undefined : styles.outerUnread]} + href={itemHref} + title={itemTitle}> <View style={styles.layout}> - <Link style={styles.layoutAvi} href={authorHref} title={authorTitle}> - <Image style={styles.avi} source={DEF_AVATER} /> - </Link> + <View style={styles.layoutIcon}> + <FontAwesomeIcon + icon={icon} + size={22} + style={[styles.icon, ...iconStyle]} + /> + </View> <View style={styles.layoutContent}> + <View style={styles.avis}> + {authors.slice(0, MAX_AUTHORS).map(author => ( + <Link + style={s.mr2} + key={author.href} + href={author.href} + title={`@${author.name}`}> + <Image style={styles.avi} source={DEF_AVATER} /> + </Link> + ))} + {authors.length > MAX_AUTHORS ? ( + <Text style={styles.aviExtraCount}> + +{authors.length - MAX_AUTHORS} + </Text> + ) : undefined} + </View> <View style={styles.meta}> - <FontAwesomeIcon icon={icon} size={14} style={[s.mt2, s.mr5]} /> - <Link style={styles.metaItem} href={authorHref} title={authorTitle}> - <Text style={[s.f14, s.bold]}>{item.author.displayName}</Text> + <Link + key={authors[0].href} + style={styles.metaItem} + href={authors[0].href} + title={`@${authors[0].name}`}> + <Text style={[s.f14, s.bold]}> + {authors[0].displayName || authors[0].name} + </Text> </Link> + {authors.length > 1 ? ( + <> + <Text style={[styles.metaItem, s.f14]}>and</Text> + <Text style={[styles.metaItem, s.f14, s.bold]}> + {authors.length - 1} {pluralize(authors.length - 1, 'other')} + </Text> + </> + ) : undefined} <Text style={[styles.metaItem, s.f14]}>{action}</Text> <Text style={[styles.metaItem, s.f14, s.gray5]}> {ago(item.indexedAt)} @@ -97,13 +168,34 @@ const styles = StyleSheet.create({ outer: { backgroundColor: colors.white, padding: 10, - paddingBottom: 0, + borderRadius: 6, + margin: 2, + marginBottom: 0, + }, + outerMinimal: { + backgroundColor: colors.white, + borderRadius: 6, + margin: 2, + marginBottom: 0, + }, + outerUnread: { + borderWidth: 1, + borderColor: colors.blue2, }, layout: { flexDirection: 'row', }, - layoutAvi: { - width: 40, + layoutIcon: { + width: 35, + alignItems: 'flex-end', + }, + icon: { + marginRight: 10, + marginTop: 4, + }, + avis: { + flexDirection: 'row', + alignItems: 'center', }, avi: { width: 30, @@ -111,6 +203,11 @@ const styles = StyleSheet.create({ borderRadius: 15, resizeMode: 'cover', }, + aviExtraCount: { + fontWeight: 'bold', + paddingLeft: 6, + color: colors.gray5, + }, layoutContent: { flex: 1, }, diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index cdf938d22..92113b50b 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -14,6 +14,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {PostThreadViewModel} from '../../../state/models/post-thread-view' import {ComposePostModel} from '../../../state/models/shell' import {Link} from '../util/Link' +import {UserInfoText} from '../util/UserInfoText' import {useStores} from '../../../state' import {s, colors} from '../../lib/styles' import {ago} from '../../lib/strings' @@ -57,13 +58,18 @@ export const Post = observer(function Post({uri}: {uri: string}) { const item = view.thread const record = view.thread?.record as unknown as PostType.Record - const itemHref = useMemo(() => { - const urip = new AdxUri(item.uri) - return `/profile/${item.author.name}/post/${urip.recordKey}` - }, [item.uri, item.author.name]) + const itemUrip = new AdxUri(item.uri) + const itemHref = `/profile/${item.author.name}/post/${itemUrip.recordKey}` const itemTitle = `Post by ${item.author.name}` const authorHref = `/profile/${item.author.name}` const authorTitle = item.author.name + let replyAuthorDid = '' + let replyHref = '' + if (record.reply) { + const urip = new AdxUri(record.reply.parent || record.reply.root) + replyAuthorDid = urip.hostname + replyHref = `/profile/${urip.hostname}/post/${urip.recordKey}` + } const onPressReply = () => { store.shell.openModal(new ComposePostModel(item.uri)) } @@ -96,6 +102,19 @@ export const Post = observer(function Post({uri}: {uri: string}) { · {ago(item.indexedAt)} </Text> </View> + {replyHref !== '' && ( + <View style={[s.flexRow, s.mb2, {alignItems: 'center'}]}> + <FontAwesomeIcon icon="reply" size={9} style={[s.gray4, s.mr5]} /> + <Text style={[s.gray4, s.f12, s.mr2]}>Reply to</Text> + <Link href={replyHref} title="Parent post"> + <UserInfoText + did={replyAuthorDid} + style={[s.f12, s.gray5]} + prefix="@" + /> + </Link> + </View> + )} <Text style={[styles.postText, s.f15, s['lh15-1.3']]}> {record.text} </Text> |