Integrate post-source

(cherry picked from commit fe053e9b38395a4fcb30a4367bc800f64ea84fe9)
This commit is contained in:
Eric Bailey
2025-06-11 14:15:03 -05:00
parent e16aa197e7
commit ffddc16f5a
2 changed files with 108 additions and 16 deletions
@@ -1,7 +1,7 @@
import {memo, useCallback, useMemo} from 'react'
import {type GestureResponderEvent, Text as RNText, View} from 'react-native'
import {
type AppBskyFeedDefs,
AppBskyFeedDefs,
AppBskyFeedPost,
type AppBskyFeedThreadgate,
AtUri,
@@ -26,11 +26,13 @@ import {
usePostShadow,
} from '#/state/cache/post-shadow'
import {useProfileShadow} from '#/state/cache/profile-shadow'
import {FeedFeedbackProvider, useFeedFeedback} from '#/state/feed-feedback'
import {useLanguagePrefs} from '#/state/preferences'
import {type ThreadItem} from '#/state/queries/usePostThread/types'
import {useSession} from '#/state/session'
import {type OnPostSuccessData} from '#/state/shell/composer'
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
import {type PostSource} from '#/state/unstable-post-source'
import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn'
import {Link} from '#/view/com/util/Link'
import {formatCount} from '#/view/com/util/numeric/format'
@@ -64,10 +66,12 @@ export function ThreadItemAnchor({
item,
onPostSuccess,
threadgateRecord,
postSource,
}: {
item: Extract<ThreadItem, {type: 'threadPost'}>
onPostSuccess?: (data: OnPostSuccessData) => void
threadgateRecord?: AppBskyFeedThreadgate.Record
postSource?: PostSource
}) {
const postShadow = usePostShadow(item.value.post)
const threadRootUri = item.value.post.record.reply?.root?.uri || item.uri
@@ -86,6 +90,7 @@ export function ThreadItemAnchor({
postShadow={postShadow}
onPostSuccess={onPostSuccess}
threadgateRecord={threadgateRecord}
postSource={postSource}
/>
)
}
@@ -161,17 +166,20 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
postShadow,
onPostSuccess,
threadgateRecord,
postSource,
}: {
item: Extract<ThreadItem, {type: 'threadPost'}>
isRoot: boolean
postShadow: Shadow<AppBskyFeedDefs.PostView>
onPostSuccess?: (data: OnPostSuccessData) => void
threadgateRecord?: AppBskyFeedThreadgate.Record
postSource?: PostSource
}) {
const t = useTheme()
const {_, i18n} = useLingui()
const {openComposer} = useOpenComposer()
const {currentAccount} = useSession()
const {currentAccount, hasSession} = useSession()
const feedFeedback = useFeedFeedback(postSource?.feed, hasSession)
const post = item.value.post
const record = item.value.post.record
@@ -228,6 +236,17 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
const showFollowButton =
currentAccount?.did !== post.author.did && !onlyFollowersCanReply
const viaRepost = useMemo(() => {
const reason = postSource?.post.reason
if (AppBskyFeedDefs.isReasonRepost(reason) && reason.uri && reason.cid) {
return {
uri: reason.uri,
cid: reason.cid,
}
}
}, [postSource])
const onPressReply = useCallback(() => {
openComposer({
replyTo: {
@@ -240,7 +259,46 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
},
onPostSuccess: onPostSuccess,
})
}, [openComposer, post, record, onPostSuccess, moderation])
if (postSource) {
feedFeedback.sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#interactionReply',
feedContext: postSource.post.feedContext,
reqId: postSource.post.reqId,
})
}
}, [
openComposer,
post,
record,
onPostSuccess,
moderation,
postSource,
feedFeedback,
])
const onOpenAuthor = () => {
if (postSource) {
feedFeedback.sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughAuthor',
feedContext: postSource.post.feedContext,
reqId: postSource.post.reqId,
})
}
}
const onOpenEmbed = () => {
if (postSource) {
feedFeedback.sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughEmbed',
feedContext: postSource.post.feedContext,
reqId: postSource.post.reqId,
})
}
}
return (
<>
@@ -261,13 +319,15 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
moderation={moderation.ui('avatar')}
type={post.author.associated?.labeler ? 'labeler' : 'user'}
live={live}
onBeforePress={onOpenAuthor}
/>
<View style={[a.flex_1]}>
<View style={[a.flex_row, a.align_center]}>
<Link
style={[a.flex_shrink]}
href={authorHref}
title={authorTitle}>
title={authorTitle}
onBeforePress={onOpenAuthor}>
<Text
emoji
style={[a.text_lg, a.font_bold, a.leading_snug, a.self_start]}
@@ -332,6 +392,7 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
embed={post.embed}
moderation={moderation}
viewContext={PostEmbedViewContext.ThreadHighlighted}
onOpen={onOpenEmbed}
/>
</View>
)}
@@ -411,15 +472,20 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
marginLeft: -5,
},
]}>
<PostControls
big
post={postShadow}
record={record}
richText={richText}
onPressReply={onPressReply}
logContext="PostThreadItem"
threadgateRecord={threadgateRecord}
/>
<FeedFeedbackProvider value={feedFeedback}>
<PostControls
big
post={postShadow}
record={record}
richText={richText}
onPressReply={onPressReply}
logContext="PostThreadItem"
threadgateRecord={threadgateRecord}
feedContext={postSource?.post?.feedContext}
reqId={postSource?.post?.reqId}
viaRepost={viaRepost}
/>
</FeedFeedbackProvider>
</View>
</View>
</View>
+29 -3
View File
@@ -5,11 +5,13 @@ import {Trans} from '@lingui/macro'
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {useFeedFeedback} from '#/state/feed-feedback'
import {type ThreadViewOption} from '#/state/queries/preferences/useThreadPreferences'
import {type ThreadItem, usePostThread} from '#/state/queries/usePostThread'
import {useSession} from '#/state/session'
import {type OnPostSuccessData} from '#/state/shell/composer'
import {useShellLayout} from '#/state/shell/shell-layout'
import {useUnstablePostSource} from '#/state/unstable-post-source'
import {PostThreadComposePrompt} from '#/view/com/post-thread/PostThreadComposePrompt'
import {List, type ListMethods} from '#/view/com/util/List'
import {HeaderDropdown} from '#/screens/PostThread/components/HeaderDropdown'
@@ -40,11 +42,13 @@ import {ListFooter} from '#/components/Lists'
const PARENT_CHUNK_SIZE = 5
const CHILDREN_CHUNK_SIZE = 50
export function PostThread({uri}: {uri: string | undefined}) {
export function PostThread({uri}: {uri: string}) {
const {gtMobile} = useBreakpoints()
const {hasSession} = useSession()
const initialNumToRender = useInitialNumToRender() // TODO
const {height: windowHeight} = useWindowDimensions()
const anchorPostSource = useUnstablePostSource(uri)
const feedFeedback = useFeedFeedback(anchorPostSource?.feed, hasSession)
/*
* One query to rule them all
@@ -87,7 +91,22 @@ export function PostThread({uri}: {uri: string | undefined}) {
},
onPostSuccess: optimisticOnPostReply,
})
}, [anchor, openComposer, optimisticOnPostReply])
if (anchorPostSource) {
feedFeedback.sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#interactionReply',
feedContext: anchorPostSource.post.feedContext,
reqId: anchorPostSource.post.reqId,
})
}
}, [
anchor,
openComposer,
optimisticOnPostReply,
anchorPostSource,
feedFeedback,
])
const isRoot = !!anchor && anchor.value.post.record.reply === undefined
const canReply = !anchor?.value.post?.viewer?.replyDisabled
@@ -380,6 +399,7 @@ export function PostThread({uri}: {uri: string | undefined}) {
item={item}
threadgateRecord={thread.data.threadgate?.record ?? undefined}
onPostSuccess={optimisticOnPostReply}
postSource={anchorPostSource}
/>
</View>
)
@@ -452,7 +472,13 @@ export function PostThread({uri}: {uri: string | undefined}) {
}
return null
},
[thread, optimisticOnPostReply, onReplyToAnchor, gtMobile],
[
thread,
optimisticOnPostReply,
onReplyToAnchor,
gtMobile,
anchorPostSource,
],
)
return (