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
parent
6d647551cd
commit
70f190d44f
|
@ -1,6 +1,7 @@
|
||||||
import React, {useCallback, useEffect, useRef} from 'react'
|
import React, {useCallback, useEffect, useRef} from 'react'
|
||||||
import {AppState} from 'react-native'
|
import {AppState} from 'react-native'
|
||||||
import {
|
import {
|
||||||
|
AppBskyActorDefs,
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
AtUri,
|
AtUri,
|
||||||
|
@ -72,6 +73,7 @@ export interface FeedPostSliceItem {
|
||||||
reason?: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource
|
reason?: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource
|
||||||
feedContext: string | undefined
|
feedContext: string | undefined
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
|
parentAuthor?: AppBskyActorDefs.ProfileViewBasic
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FeedPostSlice {
|
export interface FeedPostSlice {
|
||||||
|
@ -302,6 +304,10 @@ export function usePostFeedQuery(
|
||||||
AppBskyFeedPost.validateRecord(item.post.record)
|
AppBskyFeedPost.validateRecord(item.post.record)
|
||||||
.success
|
.success
|
||||||
) {
|
) {
|
||||||
|
const parentAuthor =
|
||||||
|
item.reply?.parent?.author ??
|
||||||
|
slice.items[i + 1]?.reply?.grandparentAuthor
|
||||||
|
|
||||||
return {
|
return {
|
||||||
_reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
|
_reactKey: `${slice._reactKey}-${i}-${item.post.uri}`,
|
||||||
uri: item.post.uri,
|
uri: item.post.uri,
|
||||||
|
@ -313,6 +319,7 @@ export function usePostFeedQuery(
|
||||||
: item.reason,
|
: item.reason,
|
||||||
feedContext: item.feedContext || slice.feedContext,
|
feedContext: item.feedContext || slice.feedContext,
|
||||||
moderation: moderations[i],
|
moderation: moderations[i],
|
||||||
|
parentAuthor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, {memo, useMemo, useState} from 'react'
|
import React, {memo, useMemo, useState} from 'react'
|
||||||
import {StyleSheet, View} from 'react-native'
|
import {StyleSheet, View} from 'react-native'
|
||||||
import {
|
import {
|
||||||
|
AppBskyActorDefs,
|
||||||
AppBskyFeedDefs,
|
AppBskyFeedDefs,
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
AtUri,
|
AtUri,
|
||||||
|
@ -40,7 +41,18 @@ import {PostEmbeds} from '../util/post-embeds'
|
||||||
import {PostMeta} from '../util/PostMeta'
|
import {PostMeta} from '../util/PostMeta'
|
||||||
import {Text} from '../util/text/Text'
|
import {Text} from '../util/text/Text'
|
||||||
import {PreviewableUserAvatar} from '../util/UserAvatar'
|
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({
|
export function FeedItem({
|
||||||
post,
|
post,
|
||||||
|
@ -48,19 +60,12 @@ export function FeedItem({
|
||||||
reason,
|
reason,
|
||||||
feedContext,
|
feedContext,
|
||||||
moderation,
|
moderation,
|
||||||
|
parentAuthor,
|
||||||
|
showReplyTo,
|
||||||
isThreadChild,
|
isThreadChild,
|
||||||
isThreadLastChild,
|
isThreadLastChild,
|
||||||
isThreadParent,
|
isThreadParent,
|
||||||
}: {
|
}: FeedItemProps & {post: AppBskyFeedDefs.PostView}): React.ReactNode {
|
||||||
post: AppBskyFeedDefs.PostView
|
|
||||||
record: AppBskyFeedPost.Record
|
|
||||||
reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
|
|
||||||
feedContext: string | undefined
|
|
||||||
moderation: ModerationDecision
|
|
||||||
isThreadChild?: boolean
|
|
||||||
isThreadLastChild?: boolean
|
|
||||||
isThreadParent?: boolean
|
|
||||||
}) {
|
|
||||||
const postShadowed = usePostShadow(post)
|
const postShadowed = usePostShadow(post)
|
||||||
const richText = useMemo(
|
const richText = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
@ -83,6 +88,8 @@ export function FeedItem({
|
||||||
reason={reason}
|
reason={reason}
|
||||||
feedContext={feedContext}
|
feedContext={feedContext}
|
||||||
richText={richText}
|
richText={richText}
|
||||||
|
parentAuthor={parentAuthor}
|
||||||
|
showReplyTo={showReplyTo}
|
||||||
moderation={moderation}
|
moderation={moderation}
|
||||||
isThreadChild={isThreadChild}
|
isThreadChild={isThreadChild}
|
||||||
isThreadLastChild={isThreadLastChild}
|
isThreadLastChild={isThreadLastChild}
|
||||||
|
@ -100,19 +107,14 @@ let FeedItemInner = ({
|
||||||
feedContext,
|
feedContext,
|
||||||
richText,
|
richText,
|
||||||
moderation,
|
moderation,
|
||||||
|
parentAuthor,
|
||||||
|
showReplyTo,
|
||||||
isThreadChild,
|
isThreadChild,
|
||||||
isThreadLastChild,
|
isThreadLastChild,
|
||||||
isThreadParent,
|
isThreadParent,
|
||||||
}: {
|
}: FeedItemProps & {
|
||||||
post: Shadow<AppBskyFeedDefs.PostView>
|
|
||||||
record: AppBskyFeedPost.Record
|
|
||||||
reason: AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | undefined
|
|
||||||
feedContext: string | undefined
|
|
||||||
richText: RichTextAPI
|
richText: RichTextAPI
|
||||||
moderation: ModerationDecision
|
post: Shadow<AppBskyFeedDefs.PostView>
|
||||||
isThreadChild?: boolean
|
|
||||||
isThreadLastChild?: boolean
|
|
||||||
isThreadParent?: boolean
|
|
||||||
}): React.ReactNode => {
|
}): React.ReactNode => {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const {openComposer} = useComposerControls()
|
const {openComposer} = useComposerControls()
|
||||||
|
@ -124,14 +126,6 @@ let FeedItemInner = ({
|
||||||
}, [post.uri, post.author])
|
}, [post.uri, post.author])
|
||||||
const {sendInteraction} = useFeedFeedbackContext()
|
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(() => {
|
const onPressReply = React.useCallback(() => {
|
||||||
sendInteraction({
|
sendInteraction({
|
||||||
item: post.uri,
|
item: post.uri,
|
||||||
|
@ -318,34 +312,8 @@ let FeedItemInner = ({
|
||||||
postHref={href}
|
postHref={href}
|
||||||
onOpenAuthor={onOpenAuthor}
|
onOpenAuthor={onOpenAuthor}
|
||||||
/>
|
/>
|
||||||
{!isThreadChild && replyAuthorDid !== '' && (
|
{!isThreadChild && showReplyTo && parentAuthor && (
|
||||||
<View style={[s.flexRow, s.mb2, s.alignCenter]}>
|
<ReplyToLabel profile={parentAuthor} />
|
||||||
<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>
|
|
||||||
)}
|
)}
|
||||||
<LabelsOnMyPost post={post} />
|
<LabelsOnMyPost post={post} />
|
||||||
<PostContent
|
<PostContent
|
||||||
|
@ -434,6 +402,43 @@ let PostContent = ({
|
||||||
}
|
}
|
||||||
PostContent = memo(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({
|
const styles = StyleSheet.create({
|
||||||
outer: {
|
outer: {
|
||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
|
|
|
@ -22,6 +22,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
|
||||||
record={slice.items[0].record}
|
record={slice.items[0].record}
|
||||||
reason={slice.items[0].reason}
|
reason={slice.items[0].reason}
|
||||||
feedContext={slice.items[0].feedContext}
|
feedContext={slice.items[0].feedContext}
|
||||||
|
parentAuthor={slice.items[0].parentAuthor}
|
||||||
|
showReplyTo={true}
|
||||||
moderation={slice.items[0].moderation}
|
moderation={slice.items[0].moderation}
|
||||||
isThreadParent={isThreadParentAt(slice.items, 0)}
|
isThreadParent={isThreadParentAt(slice.items, 0)}
|
||||||
isThreadChild={isThreadChildAt(slice.items, 0)}
|
isThreadChild={isThreadChildAt(slice.items, 0)}
|
||||||
|
@ -32,6 +34,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
|
||||||
record={slice.items[1].record}
|
record={slice.items[1].record}
|
||||||
reason={slice.items[1].reason}
|
reason={slice.items[1].reason}
|
||||||
feedContext={slice.items[1].feedContext}
|
feedContext={slice.items[1].feedContext}
|
||||||
|
parentAuthor={slice.items[1].parentAuthor}
|
||||||
|
showReplyTo={false}
|
||||||
moderation={slice.items[1].moderation}
|
moderation={slice.items[1].moderation}
|
||||||
isThreadParent={isThreadParentAt(slice.items, 1)}
|
isThreadParent={isThreadParentAt(slice.items, 1)}
|
||||||
isThreadChild={isThreadChildAt(slice.items, 1)}
|
isThreadChild={isThreadChildAt(slice.items, 1)}
|
||||||
|
@ -43,6 +47,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
|
||||||
record={slice.items[last].record}
|
record={slice.items[last].record}
|
||||||
reason={slice.items[last].reason}
|
reason={slice.items[last].reason}
|
||||||
feedContext={slice.items[last].feedContext}
|
feedContext={slice.items[last].feedContext}
|
||||||
|
parentAuthor={slice.items[2].parentAuthor}
|
||||||
|
showReplyTo={false}
|
||||||
moderation={slice.items[last].moderation}
|
moderation={slice.items[last].moderation}
|
||||||
isThreadParent={isThreadParentAt(slice.items, last)}
|
isThreadParent={isThreadParentAt(slice.items, last)}
|
||||||
isThreadChild={isThreadChildAt(slice.items, last)}
|
isThreadChild={isThreadChildAt(slice.items, last)}
|
||||||
|
@ -62,6 +68,8 @@ let FeedSlice = ({slice}: {slice: FeedPostSlice}): React.ReactNode => {
|
||||||
reason={slice.items[i].reason}
|
reason={slice.items[i].reason}
|
||||||
feedContext={slice.items[i].feedContext}
|
feedContext={slice.items[i].feedContext}
|
||||||
moderation={slice.items[i].moderation}
|
moderation={slice.items[i].moderation}
|
||||||
|
parentAuthor={slice.items[i].parentAuthor}
|
||||||
|
showReplyTo={i === 0}
|
||||||
isThreadParent={isThreadParentAt(slice.items, i)}
|
isThreadParent={isThreadParentAt(slice.items, i)}
|
||||||
isThreadChild={isThreadChildAt(slice.items, i)}
|
isThreadChild={isThreadChildAt(slice.items, i)}
|
||||||
isThreadLastChild={
|
isThreadLastChild={
|
||||||
|
|
|
@ -803,6 +803,8 @@ function MockPostFeedItem({
|
||||||
post={post}
|
post={post}
|
||||||
record={post.record as AppBskyFeedPost.Record}
|
record={post.record as AppBskyFeedPost.Record}
|
||||||
moderation={moderation}
|
moderation={moderation}
|
||||||
|
parentAuthor={undefined}
|
||||||
|
showReplyTo={false}
|
||||||
reason={undefined}
|
reason={undefined}
|
||||||
feedContext={''}
|
feedContext={''}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Reference in New Issue