···2424 isDeleted: boolean
2525 embed: AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined
2626 pinned: boolean
2727+ optimisticReplyCount: number | undefined
2728}
28292930export const POST_TOMBSTONE = Symbol('PostTombstone')
···3334 AppBskyFeedDefs.PostView,
3435 Partial<PostShadow>
3536> = new WeakMap()
3737+3838+/**
3939+ * Use with caution! This function returns the raw shadow data for a post.
4040+ * Prefer using `usePostShadow`.
4141+ */
4242+export function dangerousGetPostShadow(post: AppBskyFeedDefs.PostView) {
4343+ return shadows.get(post)
4444+}
36453746export function usePostShadow(
3847 post: AppBskyFeedDefs.PostView,
···95104 repostCount = Math.max(0, repostCount)
96105 }
97106107107+ let replyCount = post.replyCount ?? 0
108108+ if ('optimisticReplyCount' in shadow) {
109109+ replyCount = shadow.optimisticReplyCount ?? replyCount
110110+ }
111111+98112 let embed: typeof post.embed
99113 if ('embed' in shadow) {
100114 if (
···112126 embed: embed || post.embed,
113127 likeCount: likeCount,
114128 repostCount: repostCount,
129129+ replyCount: replyCount,
115130 viewer: {
116131 ...(post.viewer || {}),
117132 like: 'likeUri' in shadow ? shadow.likeUri : post.viewer?.like,
+25-4
src/state/queries/usePostThread/queryCache.ts
···99} from '@atproto/api'
1010import {type QueryClient} from '@tanstack/react-query'
11111212+import {
1313+ dangerousGetPostShadow,
1414+ updatePostShadow,
1515+} from '#/state/cache/post-shadow'
1216import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} from '#/state/queries/explore-feed-previews'
1317import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/queries/notifications/feed'
1418import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed'
···8589 /*
8690 * Update parent data
8791 */
8888- parent.value.post = {
8989- ...parent.value.post,
9090- replyCount: (parent.value.post.replyCount || 0) + 1,
9191- }
9292+ const shadow = dangerousGetPostShadow(parent.value.post)
9393+ const prevOptimisticCount = shadow?.optimisticReplyCount
9494+ const prevReplyCount = parent.value.post.replyCount
9595+ // prefer optimistic count, if we already have some
9696+ const currentReplyCount =
9797+ (prevOptimisticCount ?? prevReplyCount ?? 0) + 1
9898+9999+ /*
100100+ * We must update the value in the query cache in order for thread
101101+ * traversal to properly compute required metadata.
102102+ */
103103+ parent.value.post.replyCount = currentReplyCount
104104+105105+ /**
106106+ * Additionally, we need to update the post shadow to keep track of
107107+ * these new values, since mutating the post object above does not
108108+ * cause a re-render.
109109+ */
110110+ updatePostShadow(queryClient, parent.value.post.uri, {
111111+ optimisticReplyCount: currentReplyCount,
112112+ })
9211393114 const opDid = getRootPostAtUri(parent.value.post)?.host
94115 const nextPreexistingItem = thread.at(i + 1)