Add in new optimistic insert logic

This commit is contained in:
Eric Bailey
2025-05-17 14:19:06 -07:00
parent 5f586cbec0
commit 03b5ef162c
5 changed files with 87 additions and 13 deletions
@@ -0,0 +1,4 @@
import {describe, it} from '@jest/globals'
describe(`insert`, () => {
})
+12 -6
View File
@@ -1,7 +1,7 @@
import {useQuery, useQueryClient} from '@tanstack/react-query' import {useQuery, useQueryClient} from '@tanstack/react-query'
import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {getThreadPlaceholder} from '#/state/queries/usePostThread/queryCache' import {getThreadPlaceholder, createCacheMutator} from '#/state/queries/usePostThread/queryCache'
import {flatten,sort} from '#/state/queries/usePostThread/traversal' import {flatten,sort} from '#/state/queries/usePostThread/traversal'
import { import {
createPostThreadQueryKey, createPostThreadQueryKey,
@@ -30,13 +30,14 @@ export function usePostThread({
const mergeThreadgateHiddenReplies = useMergeThreadgateHiddenReplies() const mergeThreadgateHiddenReplies = useMergeThreadgateHiddenReplies()
const enabled = isEnabled !== false && !!uri && !!moderationOpts const enabled = isEnabled !== false && !!uri && !!moderationOpts
const queryKey = createPostThreadQueryKey({
uri,
params,
})
const query = useQuery({ const query = useQuery({
enabled, enabled,
queryKey: createPostThreadQueryKey({ queryKey,
uri,
params,
}),
async queryFn() { async queryFn() {
const {data} = await agent.app.bsky.unspecced.getPostThreadV2({ const {data} = await agent.app.bsky.unspecced.getPostThreadV2({
uri: uri!, uri: uri!,
@@ -82,12 +83,17 @@ export function usePostThread({
}, },
) )
const mutator = createCacheMutator({
queryKey,
queryClient: qc,
})
return { return {
...query, ...query,
data: { data: {
slices: items, slices: items,
threadgate: query.data?.threadgate, threadgate: query.data?.threadgate,
}, },
insertReplies: () => {}, insertReplies: mutator.insertReplies,
} }
} }
+61 -1
View File
@@ -11,13 +11,73 @@ import {findAllPostsInQueryData as findAllPostsInNotifsQueryData} from '#/state/
import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed' import {findAllPostsInQueryData as findAllPostsInFeedQueryData} from '#/state/queries/post-feed'
import {findAllPostsInQueryData as findAllPostsInQuoteQueryData} from '#/state/queries/post-quotes' import {findAllPostsInQueryData as findAllPostsInQuoteQueryData} from '#/state/queries/post-quotes'
import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts' import {findAllPostsInQueryData as findAllPostsInSearchQueryData} from '#/state/queries/search-posts'
import {postThreadQueryKeyRoot} from '#/state/queries/usePostThread/types' import {
postThreadQueryKeyRoot,
createPostThreadQueryKey,
} from '#/state/queries/usePostThread/types'
import { import {
embedViewToThreadPlaceholder, embedViewToThreadPlaceholder,
postViewToThreadPlaceholder, postViewToThreadPlaceholder,
} from '#/state/queries/usePostThread/views' } from '#/state/queries/usePostThread/views'
import {didOrHandleUriMatches, getEmbeddedPost} from '#/state/queries/util' import {didOrHandleUriMatches, getEmbeddedPost} from '#/state/queries/util'
export function createCacheMutator({
queryKey,
queryClient,
}: {
queryKey: ReturnType<typeof createPostThreadQueryKey>
queryClient: QueryClient
}) {
return {
insertReplies(
parent: AppBskyUnspeccedDefs.ThreadItemPost,
replies: AppBskyUnspeccedDefs.ThreadItemPost[],
) {
queryClient.setQueryData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>(
queryKey,
queryData => {
if (!queryData) return
const thread = [...queryData.thread]
for (let i = 0; i < thread.length; i++) {
const anchor = thread[i]
if (!AppBskyUnspeccedDefs.isThreadItemPost(anchor)) continue
if (anchor.uri !== parent.uri) continue
/*
* Update parent data
*/
anchor.post = {
...anchor.post,
replyCount: parent.post.replyCount,
}
/*
* Splice in new replies
*/
for (let ri = 0; ri < replies.length; ri++) {
const reply = replies[ri]
reply.depth = anchor.depth + 1 + ri
const insertIndex = i + 1 + ri
thread.splice(insertIndex, 0, {
$type: 'app.bsky.unspecced.defs#threadItemPost',
...reply,
})
}
}
return {
...queryData,
thread,
}
},
)
},
deletePost(post: AppBskyUnspeccedDefs.ThreadItemPost) {},
}
}
export function getThreadPlaceholder( export function getThreadPlaceholder(
queryClient: QueryClient, queryClient: QueryClient,
uri: string, uri: string,
+4 -4
View File
@@ -407,15 +407,15 @@ export const ComposePost = ({
posts = await retry(5, _e => true, async () => { posts = await retry(5, _e => true, async () => {
const res = await agent.app.bsky.unspecced.getPostThreadV2({ const res = await agent.app.bsky.unspecced.getPostThreadV2({
uri: postUri!, uri: postUri!,
above: 0, above: 1,
below: thread.posts.length - 1, below: thread.posts.length - 1,
branchingFactor: 1, branchingFactor: 1,
}) })
if (res.data.thread.length !== thread.posts.length) { const parent = res.data.thread.at(0)
if (!AppBskyUnspeccedDefs.isThreadItemPost(parent)) {
throw new Error(`Not ready`) throw new Error(`Not ready`)
} }
const anchor = res.data.thread.at(0) if (res.data.thread.length !== thread.posts.length + 1) {
if (!AppBskyUnspeccedDefs.isThreadItemPost(anchor)) {
throw new Error(`Not ready`) throw new Error(`Not ready`)
} }
return res.data.thread return res.data.thread
+6 -2
View File
@@ -161,8 +161,12 @@ export function Inner({uri}: {uri: string | undefined}) {
({post}: {post: AppBskyUnspeccedDefs.ThreadItemPost}) => ({post}: {post: AppBskyUnspeccedDefs.ThreadItemPost}) =>
(_: any, posts: AppBskyUnspeccedDefs.ThreadItemPost[]) => { (_: any, posts: AppBskyUnspeccedDefs.ThreadItemPost[]) => {
if (posts.length) { if (posts.length) {
// TODO get parent and update reply count? console.log('insert', posts)
insertReplies(post.uri, posts) const parent = posts.at(0)
const replies = posts.slice(1)
if (parent && replies.length) {
insertReplies(parent, replies)
}
} }
} }