Improve thread rendering

This commit is contained in:
Paul Frazee 2022-12-18 18:54:05 -06:00
parent 69b86255c6
commit ae3099dfca
5 changed files with 194 additions and 101 deletions

View file

@ -90,14 +90,17 @@ export const PostThread = observer(function PostThread({
function* flattenThread(
post: PostThreadViewPostModel,
isAscending = false,
): Generator<PostThreadViewPostModel, void> {
if (post.parent) {
yield* flattenThread(post.parent)
yield* flattenThread(post.parent, true)
}
yield post
if (post.replies?.length) {
for (const reply of post.replies) {
yield* flattenThread(reply)
}
} else if (!isAscending && !post.parent && post.replyCount > 0) {
post._hasMore = true
}
}

View file

@ -226,71 +226,82 @@ export const PostThreadItem = observer(function PostThreadItem({
)
} else {
return (
<Link style={styles.outer} href={itemHref} title={itemTitle} noFeedback>
{!item.replyingTo && item.record.reply && (
<View style={styles.parentReplyLine} />
)}
{item.replies?.length !== 0 && <View style={styles.childReplyLine} />}
{item.replyingTo ? (
<View style={styles.replyingTo}>
<View style={styles.replyingToLine} />
<View style={styles.replyingToAvatar}>
<UserAvatar
handle={item.replyingTo.author.handle}
displayName={item.replyingTo.author.displayName}
avatar={item.replyingTo.author.avatar}
size={30}
<>
<Link style={styles.outer} href={itemHref} title={itemTitle} noFeedback>
{!item.replyingTo && item.record.reply && (
<View style={styles.parentReplyLine} />
)}
{item.replies?.length !== 0 && <View style={styles.childReplyLine} />}
{item.replyingTo ? (
<View style={styles.replyingTo}>
<View style={styles.replyingToLine} />
<View style={styles.replyingToAvatar}>
<UserAvatar
handle={item.replyingTo.author.handle}
displayName={item.replyingTo.author.displayName}
avatar={item.replyingTo.author.avatar}
size={30}
/>
</View>
<Text style={styles.replyingToText} numberOfLines={2}>
{item.replyingTo.text}
</Text>
</View>
) : undefined}
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<Link href={authorHref} title={authorTitle}>
<UserAvatar
size={50}
displayName={item.author.displayName}
handle={item.author.handle}
avatar={item.author.avatar}
/>
</Link>
</View>
<View style={styles.layoutContent}>
<PostMeta
itemHref={itemHref}
itemTitle={itemTitle}
authorHref={authorHref}
authorHandle={item.author.handle}
authorDisplayName={item.author.displayName}
timestamp={item.indexedAt}
isAuthor={item.author.did === store.me.did}
onCopyPostText={onCopyPostText}
onDeletePost={onDeletePost}
/>
<View style={styles.postTextContainer}>
<RichText
text={record.text}
entities={record.entities}
style={[styles.postText]}
/>
</View>
<PostEmbeds embed={item.embed} style={{marginBottom: 10}} />
<PostCtrls
replyCount={item.replyCount}
repostCount={item.repostCount}
upvoteCount={item.upvoteCount}
isReposted={!!item.myState.repost}
isUpvoted={!!item.myState.upvote}
onPressReply={onPressReply}
onPressToggleRepost={onPressToggleRepost}
onPressToggleUpvote={onPressToggleUpvote}
/>
</View>
<Text style={styles.replyingToText} numberOfLines={2}>
{item.replyingTo.text}
</Text>
</View>
</Link>
{item._hasMore ? (
<Link
style={styles.loadMore}
href={itemHref}
title={itemTitle}
noFeedback>
<Text style={styles.loadMoreText}>Load more</Text>
</Link>
) : undefined}
<View style={styles.layout}>
<View style={styles.layoutAvi}>
<Link href={authorHref} title={authorTitle}>
<UserAvatar
size={50}
displayName={item.author.displayName}
handle={item.author.handle}
avatar={item.author.avatar}
/>
</Link>
</View>
<View style={styles.layoutContent}>
<PostMeta
itemHref={itemHref}
itemTitle={itemTitle}
authorHref={authorHref}
authorHandle={item.author.handle}
authorDisplayName={item.author.displayName}
timestamp={item.indexedAt}
isAuthor={item.author.did === store.me.did}
onCopyPostText={onCopyPostText}
onDeletePost={onDeletePost}
/>
<View style={styles.postTextContainer}>
<RichText
text={record.text}
entities={record.entities}
style={[styles.postText]}
/>
</View>
<PostEmbeds embed={item.embed} style={{marginBottom: 10}} />
<PostCtrls
replyCount={item.replyCount}
repostCount={item.repostCount}
upvoteCount={item.upvoteCount}
isReposted={!!item.myState.repost}
isUpvoted={!!item.myState.upvote}
onPressReply={onPressReply}
onPressToggleRepost={onPressToggleRepost}
onPressToggleUpvote={onPressToggleUpvote}
/>
</View>
</View>
</Link>
</>
)
}
})
@ -398,4 +409,16 @@ const styles = StyleSheet.create({
expandedInfoItem: {
marginRight: 10,
},
loadMore: {
paddingLeft: 28,
paddingVertical: 10,
backgroundColor: colors.white,
borderRadius: 6,
margin: 2,
marginBottom: 0,
},
loadMoreText: {
fontSize: 17,
color: colors.blue3,
},
})

View file

@ -2,6 +2,7 @@ import React, {useMemo, useState} from 'react'
import {observer} from 'mobx-react-lite'
import {StyleSheet, Text, View} from 'react-native'
import Clipboard from '@react-native-clipboard/clipboard'
import Svg, {Circle} from 'react-native-svg'
import {AtUri} from '../../../third-party/uri'
import * as PostType from '../../../third-party/api/src/client/types/app/bsky/feed/post'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
@ -207,6 +208,22 @@ export const FeedItem = observer(function FeedItem({
</View>
</View>
</Link>
{item._isThreadChildElided ? (
<Link
style={styles.viewFullThread}
href={itemHref}
title={itemTitle}
noFeedback>
<View style={styles.viewFullThreadDots}>
<Svg width="4" height="30">
<Circle x="2" y="5" r="1.5" fill={colors.gray3} />
<Circle x="2" y="11" r="1.5" fill={colors.gray3} />
<Circle x="2" y="17" r="1.5" fill={colors.gray3} />
</Svg>
</View>
<Text style={styles.viewFullThreadText}>View full thread</Text>
</Link>
) : undefined}
</>
)
})
@ -281,4 +298,18 @@ const styles = StyleSheet.create({
postEmbeds: {
marginBottom: 10,
},
viewFullThread: {
backgroundColor: colors.white,
paddingTop: 4,
paddingLeft: 72,
},
viewFullThreadDots: {
position: 'absolute',
left: 35,
top: 0,
},
viewFullThreadText: {
color: colors.blue3,
fontSize: 16,
},
})