Remove `getProfile` calls when loading feed (#3881)

* remove unnecessary `getProfile()` calls from feed load

add comments

ensure only if first

simplify

nit

handle cases where the parent is removed

add a comment

remove unnecessary `getProfile()` calls from feed load

limit only to the first post in the returned items

move the logic out of the render and into the query

add the grandparent properly

update `FeedItem`

bump package

update `FeedItem`

update `post-feed` query

update `FeedSlice`

* nit

* simplify logic

* always pass `parentAuthor`

* oops!

* update `DebugMod`
zio/stable
Hailey 2024-05-23 11:35:49 -07:00 committed by GitHub
parent 6d647551cd
commit 70f190d44f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 78 additions and 56 deletions

View File

@ -1,6 +1,7 @@
import React, {useCallback, useEffect, useRef} from 'react'
import {AppState} from 'react-native'
import {
AppBskyActorDefs,
AppBskyFeedDefs,
AppBskyFeedPost,
AtUri,
@ -72,6 +73,7 @@ export interface FeedPostSliceItem {
reason?: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource
feedContext: string | undefined
moderation: ModerationDecision
parentAuthor?: AppBskyActorDefs.ProfileViewBasic
}
export interface FeedPostSlice {
@ -302,6 +304,10 @@ export function usePostFeedQuery(
AppBskyFeedPost.validateRecord(item.post.record)
.success
) {
const parentAuthor =
item.reply?.parent?.author ??
slice.items[i + 1]?.reply?.grandparentAuthor
return {
_reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
uri: item.post.uri,
@ -313,6 +319,7 @@ export function usePostFeedQuery(
: item.reason,
feedContext: item.feedContext || slice.feedContext,
moderation: moderations[i],
parentAuthor,
}
}
return undefined

View File

@ -1,6 +1,7 @@
import React, {memo, useMemo, useState} from 'react'
import {StyleSheet, View} from 'react-native'
import {
AppBskyActorDefs,
AppBskyFeedDefs,
AppBskyFeedPost,
AtUri,
@ -40,7 +41,18 @@ import {PostEmbeds} from '../util/post-embeds'
import {PostMeta} from '../util/PostMeta'
import {Text} from '../util/text/Text'
import {PreviewableUserAvatar} from '../util/UserAvatar'
import {UserInfoText} from '../util/UserInfoText'
interface FeedItemProps {
record: AppBskyFeedPost.Record
reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
moderation: ModerationDecision
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
showReplyTo: boolean
isThreadChild?: boolean
isThreadLastChild?: boolean
isThreadParent?: boolean
feedContext: string | undefined
}
export function FeedItem({
post,
@ -48,19 +60,12 @@ export function FeedItem({
reason,
feedContext,
moderation,
parentAuthor,
showReplyTo,
isThreadChild,
isThreadLastChild,
isThreadParent,
}: {
post: AppBskyFeedDefs.PostView
record: AppBskyFeedPost.Record
reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
feedContext: string | undefined
moderation: ModerationDecision
isThreadChild?: boolean
isThreadLastChild?: boolean
isThreadParent?: boolean
}) {
}: FeedItemProps & {post: AppBskyFeedDefs.PostView}): React.ReactNode {
const postShadowed = usePostShadow(post)
const richText = useMemo(
() =>
@ -83,6 +88,8 @@ export function FeedItem({
reason={reason}
feedContext={feedContext}
richText={richText}
parentAuthor={parentAuthor}
showReplyTo={showReplyTo}
moderation={moderation}
isThreadChild={isThreadChild}
isThreadLastChild={isThreadLastChild}
@ -100,19 +107,14 @@ let FeedItemInner = ({
feedContext,
richText,
moderation,
parentAuthor,
showReplyTo,
isThreadChild,
isThreadLastChild,
isThreadParent,
}: {
post: Shadow<AppBskyFeedDefs.PostView>
record: AppBskyFeedPost.Record
reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
feedContext: string | undefined
}: FeedItemProps & {
richText: RichTextAPI
moderation: ModerationDecision
isThreadChild?: boolean
isThreadLastChild?: boolean
isThreadParent?: boolean
post: Shadow<AppBskyFeedDefs.PostView>
}): React.ReactNode => {
const queryClient = useQueryClient()
const {openComposer} = useComposerControls()
@ -124,14 +126,6 @@ let FeedItemInner = ({
}, [post.uri, post.author])
const {sendInteraction} = useFeedFeedbackContext()
const replyAuthorDid = useMemo(() => {
if (!record?.reply) {
return ''
}
const urip = new AtUri(record.reply.parent?.uri || record.reply.root.uri)
return urip.hostname
}, [record?.reply])
const onPressReply = React.useCallback(() => {
sendInteraction({
item: post.uri,
@ -318,34 +312,8 @@ let FeedItemInner = ({
postHref={href}
onOpenAuthor={onOpenAuthor}
/>
{!isThreadChild && replyAuthorDid !== '' && (
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
<FontAwesomeIcon
icon="reply"
size={9}
style={[
{color: pal.colors.textLight} as FontAwesomeIconStyle,
s.mr5,
]}
/>
<Text
type="md"
style={[pal.textLight, s.mr2]}
lineHeight={1.2}
numberOfLines={1}>
<Trans context="description">
Reply to{' '}
<ProfileHoverCard inline did={replyAuthorDid}>
<UserInfoText
type="md"
did={replyAuthorDid}
attr="displayName"
style={[pal.textLight]}
/>
</ProfileHoverCard>
</Trans>
</Text>
</View>
{!isThreadChild && showReplyTo && parentAuthor && (
<ReplyToLabel profile={parentAuthor} />
)}
<LabelsOnMyPost post={post} />
<PostContent
@ -434,6 +402,43 @@ let PostContent = ({
}
PostContent = memo(PostContent)
function ReplyToLabel({profile}: {profile: AppBskyActorDefs.ProfileViewBasic}) {
const pal = usePalette('default')
return (
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
<FontAwesomeIcon
icon="reply"
size={9}
style={[{color: pal.colors.textLight} as FontAwesomeIconStyle, s.mr5]}
/>
<Text
type="md"
style={[pal.textLight, s.mr2]}
lineHeight={1.2}
numberOfLines={1}>
<Trans context="description">
Reply to{' '}
<ProfileHoverCard inline did={profile.did}>
<TextLinkOnWebOnly
type="md"
style={pal.textLight}
lineHeight={1.2}
numberOfLines={1}
href={makeProfileLink(profile)}
text={
profile.displayName
? sanitizeDisplayName(profile.displayName)
: sanitizeHandle(profile.handle)
}
/>
</ProfileHoverCard>
</Trans>
</Text>
</View>
)
}
const styles = StyleSheet.create({
outer: {
borderTopWidth: 1,

View File

@ -22,6 +22,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
record={slice.items[0].record}
reason={slice.items[0].reason}
feedContext={slice.items[0].feedContext}
parentAuthor={slice.items[0].parentAuthor}
showReplyTo={true}
moderation={slice.items[0].moderation}
isThreadParent={isThreadParentAt(slice.items, 0)}
isThreadChild={isThreadChildAt(slice.items, 0)}
@ -32,6 +34,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
record={slice.items[1].record}
reason={slice.items[1].reason}
feedContext={slice.items[1].feedContext}
parentAuthor={slice.items[1].parentAuthor}
showReplyTo={false}
moderation={slice.items[1].moderation}
isThreadParent={isThreadParentAt(slice.items, 1)}
isThreadChild={isThreadChildAt(slice.items, 1)}
@ -43,6 +47,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
record={slice.items[last].record}
reason={slice.items[last].reason}
feedContext={slice.items[last].feedContext}
parentAuthor={slice.items[2].parentAuthor}
showReplyTo={false}
moderation={slice.items[last].moderation}
isThreadParent={isThreadParentAt(slice.items, last)}
isThreadChild={isThreadChildAt(slice.items, last)}
@ -62,6 +68,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
reason={slice.items[i].reason}
feedContext={slice.items[i].feedContext}
moderation={slice.items[i].moderation}
parentAuthor={slice.items[i].parentAuthor}
showReplyTo={i === 0}
isThreadParent={isThreadParentAt(slice.items, i)}
isThreadChild={isThreadChildAt(slice.items, i)}
isThreadLastChild={

View File

@ -803,6 +803,8 @@ function MockPostFeedItem({
post={post}
record={post.record as AppBskyFeedPost.Record}
moderation={moderation}
parentAuthor={undefined}
showReplyTo={false}
reason={undefined}
feedContext={''}
/>