Optimistic hidden replies (#4977)
This commit is contained in:
parent
5ec8761b29
commit
425dd5f27f
9 changed files with 70 additions and 129 deletions
13
src/state/cache/post-shadow.ts
vendored
13
src/state/cache/post-shadow.ts
vendored
|
@ -21,7 +21,6 @@ export interface PostShadow {
|
|||
repostUri: string | undefined
|
||||
isDeleted: boolean
|
||||
embed: AppBskyEmbedRecord.View | AppBskyEmbedRecordWithMedia.View | undefined
|
||||
threadgateView: AppBskyFeedDefs.ThreadgateView | undefined
|
||||
}
|
||||
|
||||
export const POST_TOMBSTONE = Symbol('PostTombstone')
|
||||
|
@ -105,16 +104,6 @@ function mergeShadow(
|
|||
}
|
||||
}
|
||||
|
||||
let threadgateView: typeof post.threadgate
|
||||
if ('threadgateView' in shadow && !post.threadgate) {
|
||||
if (
|
||||
AppBskyFeedDefs.isThreadgateView(shadow.threadgateView) ||
|
||||
shadow.threadgateView === undefined
|
||||
) {
|
||||
threadgateView = shadow.threadgateView
|
||||
}
|
||||
}
|
||||
|
||||
return castAsShadow({
|
||||
...post,
|
||||
embed: embed || post.embed,
|
||||
|
@ -125,8 +114,6 @@ function mergeShadow(
|
|||
like: 'likeUri' in shadow ? shadow.likeUri : post.viewer?.like,
|
||||
repost: 'repostUri' in shadow ? shadow.repostUri : post.viewer?.repost,
|
||||
},
|
||||
// always prefer real post data
|
||||
threadgate: post.threadgate || threadgateView,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,10 @@ export type ThreadModerationCache = WeakMap<ThreadNode, ModerationDecision>
|
|||
export function usePostThreadQuery(uri: string | undefined) {
|
||||
const queryClient = useQueryClient()
|
||||
const agent = useAgent()
|
||||
return useQuery<ThreadNode, Error>({
|
||||
return useQuery<
|
||||
{thread: ThreadNode; threadgate?: AppBskyFeedDefs.ThreadgateView},
|
||||
Error
|
||||
>({
|
||||
gcTime: 0,
|
||||
queryKey: RQKEY(uri || ''),
|
||||
async queryFn() {
|
||||
|
@ -99,16 +102,21 @@ export function usePostThreadQuery(uri: string | undefined) {
|
|||
if (res.success) {
|
||||
const thread = responseToThreadNodes(res.data.thread)
|
||||
annotateSelfThread(thread)
|
||||
return thread
|
||||
return {
|
||||
thread,
|
||||
threadgate: res.data.threadgate as
|
||||
| AppBskyFeedDefs.ThreadgateView
|
||||
| undefined,
|
||||
}
|
||||
}
|
||||
return {type: 'unknown', uri: uri!}
|
||||
return {thread: {type: 'unknown', uri: uri!}}
|
||||
},
|
||||
enabled: !!uri,
|
||||
placeholderData: () => {
|
||||
if (!uri) return
|
||||
const post = findPostInQueryData(queryClient, uri)
|
||||
if (post) {
|
||||
return post
|
||||
return {thread: post}
|
||||
}
|
||||
return undefined
|
||||
},
|
||||
|
|
|
@ -9,12 +9,10 @@ import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
|
|||
|
||||
import {networkRetry, retry} from '#/lib/async/retry'
|
||||
import {until} from '#/lib/async/until'
|
||||
import {updatePostShadow} from '#/state/cache/post-shadow'
|
||||
import {STALE} from '#/state/queries'
|
||||
import {RQKEY_ROOT as postThreadQueryKeyRoot} from '#/state/queries/post-thread'
|
||||
import {ThreadgateAllowUISetting} from '#/state/queries/threadgate/types'
|
||||
import {
|
||||
createTempThreadgateView,
|
||||
createThreadgateRecord,
|
||||
mergeThreadgateRecords,
|
||||
threadgateAllowUISettingToAllowRecordValue,
|
||||
|
@ -33,18 +31,16 @@ export const createThreadgateRecordQueryKey = (uri: string) => [
|
|||
]
|
||||
|
||||
export function useThreadgateRecordQuery({
|
||||
enabled,
|
||||
postUri,
|
||||
initialData,
|
||||
}: {
|
||||
enabled?: boolean
|
||||
postUri?: string
|
||||
initialData?: AppBskyFeedThreadgate.Record
|
||||
} = {}) {
|
||||
const agent = useAgent()
|
||||
|
||||
return useQuery({
|
||||
enabled: enabled ?? !!postUri,
|
||||
enabled: !!postUri,
|
||||
queryKey: createThreadgateRecordQueryKey(postUri || ''),
|
||||
placeholderData: initialData,
|
||||
staleTime: STALE.MINUTES.ONE,
|
||||
|
@ -344,26 +340,17 @@ export function useToggleReplyVisibilityMutation() {
|
|||
}
|
||||
})
|
||||
},
|
||||
onSuccess(_, {postUri, replyUri}) {
|
||||
updatePostShadow(queryClient, postUri, {
|
||||
threadgateView: createTempThreadgateView({
|
||||
postUri,
|
||||
hiddenReplies: [replyUri],
|
||||
}),
|
||||
})
|
||||
onSuccess() {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [threadgateRecordQueryKeyRoot],
|
||||
})
|
||||
},
|
||||
onError(_, {postUri, replyUri, action}) {
|
||||
onError(_, {replyUri, action}) {
|
||||
if (action === 'hide') {
|
||||
hiddenReplies.removeHiddenReplyUri(replyUri)
|
||||
} else if (action === 'show') {
|
||||
hiddenReplies.addHiddenReplyUri(replyUri)
|
||||
}
|
||||
updatePostShadow(queryClient, postUri, {
|
||||
threadgateView: undefined,
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
|
|
@ -139,23 +139,3 @@ export function createThreadgateRecord(
|
|||
hiddenReplies: threadgate.hiddenReplies || [],
|
||||
}
|
||||
}
|
||||
|
||||
export function createTempThreadgateView({
|
||||
postUri,
|
||||
hiddenReplies,
|
||||
}: Pick<AppBskyFeedThreadgate.Record, 'hiddenReplies'> & {
|
||||
postUri: string
|
||||
}): AppBskyFeedDefs.ThreadgateView {
|
||||
const record: AppBskyFeedThreadgate.Record = {
|
||||
$type: 'app.bsky.feed.threadgate',
|
||||
post: postUri,
|
||||
allow: undefined,
|
||||
hiddenReplies,
|
||||
createdAt: new Date().toISOString(),
|
||||
}
|
||||
return {
|
||||
$type: 'app.bsky.feed.defs#threadgateView',
|
||||
uri: postUri,
|
||||
record,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react'
|
||||
import {AppBskyFeedThreadgate} from '@atproto/api'
|
||||
|
||||
type StateContext = {
|
||||
uris: Set<string>
|
||||
|
@ -67,3 +68,18 @@ export function useThreadgateHiddenReplyUris() {
|
|||
export function useThreadgateHiddenReplyUrisAPI() {
|
||||
return React.useContext(ApiContext)
|
||||
}
|
||||
|
||||
export function useMergedThreadgateHiddenReplies({
|
||||
threadgateRecord,
|
||||
}: {
|
||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||
}) {
|
||||
const {uris, recentlyUnhiddenUris} = useThreadgateHiddenReplyUris()
|
||||
return React.useMemo(() => {
|
||||
const set = new Set([...(threadgateRecord?.hiddenReplies || []), ...uris])
|
||||
for (const uri of recentlyUnhiddenUris) {
|
||||
set.delete(uri)
|
||||
}
|
||||
return set
|
||||
}, [uris, recentlyUnhiddenUris, threadgateRecord])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue