Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[APP-1398] Fix post shadow/like shadow state when replying (#8866)

* Add optimisticReplyCount to post shadow

* Add special util

* Fix subtle bug in query cache

authored by

Eric Bailey and committed by
GitHub
16701392 ef7c222e

+40 -4
+15
src/state/cache/post-shadow.ts
··· 24 24 isDeleted: boolean 25 25 embed: AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined 26 26 pinned: boolean 27 + optimisticReplyCount: number | undefined 27 28 } 28 29 29 30 export const POST_TOMBSTONE = Symbol('PostTombstone') ··· 33 34 AppBskyFeedDefs.PostView, 34 35 Partial<PostShadow> 35 36 > = new WeakMap() 37 + 38 + /** 39 + * Use with caution! This function returns the raw shadow data for a post. 40 + * Prefer using `usePostShadow`. 41 + */ 42 + export function dangerousGetPostShadow(post: AppBskyFeedDefs.PostView) { 43 + return shadows.get(post) 44 + } 36 45 37 46 export function usePostShadow( 38 47 post: AppBskyFeedDefs.PostView, ··· 95 104 repostCount = Math.max(0, repostCount) 96 105 } 97 106 107 + let replyCount = post.replyCount ?? 0 108 + if ('optimisticReplyCount' in shadow) { 109 + replyCount = shadow.optimisticReplyCount ?? replyCount 110 + } 111 + 98 112 let embed: typeof post.embed 99 113 if ('embed' in shadow) { 100 114 if ( ··· 112 126 embed: embed || post.embed, 113 127 likeCount: likeCount, 114 128 repostCount: repostCount, 129 + replyCount: replyCount, 115 130 viewer: { 116 131 ...(post.viewer || {}), 117 132 like: 'likeUri' in shadow ? shadow.likeUri : post.viewer?.like,
+25 -4
src/state/queries/usePostThread/queryCache.ts
··· 9 9 } from '@atproto/api' 10 10 import {type QueryClient} from '@tanstack/react-query' 11 11 12 + import { 13 + dangerousGetPostShadow, 14 + updatePostShadow, 15 + } from '#/state/cache/post-shadow' 12 16 import {findAllPostsInQueryData as findAllPostsInExploreFeedPreviewsQueryData} from '#/state/queries/explore-feed-previews' 13 17 import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/queries/notifications/feed' 14 18 import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed' ··· 85 89 /* 86 90 * Update parent data 87 91 */ 88 - parent.value.post = { 89 - ...parent.value.post, 90 - replyCount: (parent.value.post.replyCount || 0) + 1, 91 - } 92 + const shadow = dangerousGetPostShadow(parent.value.post) 93 + const prevOptimisticCount = shadow?.optimisticReplyCount 94 + const prevReplyCount = parent.value.post.replyCount 95 + // prefer optimistic count, if we already have some 96 + const currentReplyCount = 97 + (prevOptimisticCount ?? prevReplyCount ?? 0) + 1 98 + 99 + /* 100 + * We must update the value in the query cache in order for thread 101 + * traversal to properly compute required metadata. 102 + */ 103 + parent.value.post.replyCount = currentReplyCount 104 + 105 + /** 106 + * Additionally, we need to update the post shadow to keep track of 107 + * these new values, since mutating the post object above does not 108 + * cause a re-render. 109 + */ 110 + updatePostShadow(queryClient, parent.value.post.uri, { 111 + optimisticReplyCount: currentReplyCount, 112 + }) 92 113 93 114 const opDid = getRootPostAtUri(parent.value.post)?.host 94 115 const nextPreexistingItem = thread.at(i + 1)