[Chat] Fix optimistic updates by using partial keys (#10838)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
type ChatBskyConvoAcceptConvo,
|
type ChatBskyConvoAcceptConvo,
|
||||||
type ChatBskyConvoListConvos,
|
type ChatBskyConvoDefs,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
@@ -13,7 +13,11 @@ import {
|
|||||||
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
|
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
|
||||||
} from './list-conversation-requests'
|
} from './list-conversation-requests'
|
||||||
import {
|
import {
|
||||||
RQKEY as CONVO_LIST_KEY,
|
type ConvoListQueryData,
|
||||||
|
convoListQueryPredicate,
|
||||||
|
getConvoFromQueryData,
|
||||||
|
optimisticDelete,
|
||||||
|
RQKEY_PARTIAL as CONVO_LIST_PARTIAL_KEY,
|
||||||
RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
|
RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
|
||||||
} from './list-conversations'
|
} from './list-conversations'
|
||||||
|
|
||||||
@@ -42,65 +46,49 @@ export function useAcceptConversation(
|
|||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
onMutate: () => {
|
onMutate: () => {
|
||||||
let prevAcceptedPages: ChatBskyConvoListConvos.OutputSchema[] = []
|
// snapshot every convo-list cache up front so onError can restore them
|
||||||
let prevInboxPages: ChatBskyConvoListConvos.OutputSchema[] = []
|
// all by their exact keys
|
||||||
let convoBeingAccepted:
|
const prevConvoListQueries =
|
||||||
| ChatBskyConvoListConvos.OutputSchema['convos'][number]
|
queryClient.getQueriesData<ConvoListQueryData>({
|
||||||
| undefined
|
queryKey: [CONVO_LIST_ROOT_KEY],
|
||||||
queryClient.setQueryData(
|
})
|
||||||
CONVO_LIST_KEY('request'),
|
let convoBeingAccepted: ChatBskyConvoDefs.ConvoView | null = null
|
||||||
(old?: {
|
for (const [_key, data] of queryClient.getQueriesData<ConvoListQueryData>(
|
||||||
pageParams: Array<string | undefined>
|
{queryKey: CONVO_LIST_PARTIAL_KEY('request')},
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
)) {
|
||||||
}) => {
|
if (!data) continue
|
||||||
if (!old) return old
|
convoBeingAccepted = getConvoFromQueryData(convoId, data)
|
||||||
prevInboxPages = old.pages
|
if (convoBeingAccepted) break
|
||||||
return {
|
}
|
||||||
...old,
|
queryClient.setQueriesData(
|
||||||
pages: old.pages.map(page => {
|
{queryKey: CONVO_LIST_PARTIAL_KEY('request')},
|
||||||
const found = page.convos.find(convo => convo.id === convoId)
|
(old?: ConvoListQueryData) => optimisticDelete(convoId, old),
|
||||||
if (found) {
|
|
||||||
convoBeingAccepted = found
|
|
||||||
return {
|
|
||||||
...page,
|
|
||||||
convos: page.convos.filter(convo => convo.id !== convoId),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return page
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
queryClient.setQueryData(
|
if (convoBeingAccepted) {
|
||||||
CONVO_LIST_KEY('accepted'),
|
const acceptedConvo: ChatBskyConvoDefs.ConvoView = {
|
||||||
(old?: {
|
...convoBeingAccepted,
|
||||||
pageParams: Array<string | undefined>
|
status: 'accepted',
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
}
|
||||||
}) => {
|
queryClient.setQueriesData(
|
||||||
if (!old) return old
|
{
|
||||||
prevAcceptedPages = old.pages
|
queryKey: CONVO_LIST_PARTIAL_KEY('accepted'),
|
||||||
if (convoBeingAccepted) {
|
predicate: convoListQueryPredicate(acceptedConvo),
|
||||||
|
},
|
||||||
|
(old?: ConvoListQueryData) => {
|
||||||
|
if (!old) return old
|
||||||
return {
|
return {
|
||||||
...old,
|
...old,
|
||||||
pages: [
|
pages: old.pages.map((page, i) => {
|
||||||
{
|
const convos = page.convos.filter(c => c.id !== convoId)
|
||||||
...old.pages[0],
|
if (i === 0) {
|
||||||
convos: [
|
return {...page, convos: [acceptedConvo, ...convos]}
|
||||||
{
|
}
|
||||||
...convoBeingAccepted,
|
return {...page, convos}
|
||||||
status: 'accepted',
|
}),
|
||||||
},
|
|
||||||
...old.pages[0].convos,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
...old.pages.slice(1),
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
} else {
|
},
|
||||||
return old
|
)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
)
|
|
||||||
const prevRequestsQueries =
|
const prevRequestsQueries =
|
||||||
queryClient.getQueriesData<ConvoRequestListQueryData>({
|
queryClient.getQueriesData<ConvoRequestListQueryData>({
|
||||||
queryKey: [REQUESTS_RQKEY_ROOT],
|
queryKey: [REQUESTS_RQKEY_ROOT],
|
||||||
@@ -110,41 +98,20 @@ export function useAcceptConversation(
|
|||||||
old => optimisticDeleteRequest(convoId, old),
|
old => optimisticDeleteRequest(convoId, old),
|
||||||
)
|
)
|
||||||
onMutate?.()
|
onMutate?.()
|
||||||
return {prevAcceptedPages, prevInboxPages, prevRequestsQueries}
|
return {prevConvoListQueries, prevRequestsQueries}
|
||||||
},
|
},
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
void queryClient.invalidateQueries({queryKey: [CONVO_LIST_KEY]})
|
void queryClient.invalidateQueries({queryKey: [CONVO_LIST_ROOT_KEY]})
|
||||||
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
|
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
|
||||||
onSuccess?.(data)
|
onSuccess?.(data)
|
||||||
},
|
},
|
||||||
onError: (error, _, context) => {
|
onError: (error, _, context) => {
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
queryClient.setQueryData(
|
if (context?.prevConvoListQueries) {
|
||||||
CONVO_LIST_KEY('accepted'),
|
for (const [queryKey, prevData] of context.prevConvoListQueries) {
|
||||||
(old?: {
|
queryClient.setQueryData(queryKey, prevData)
|
||||||
pageParams: Array<string | undefined>
|
}
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
}
|
||||||
}) => {
|
|
||||||
if (!old) return old
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
pages: context?.prevAcceptedPages || old.pages,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
queryClient.setQueryData(
|
|
||||||
CONVO_LIST_KEY('request'),
|
|
||||||
(old?: {
|
|
||||||
pageParams: Array<string | undefined>
|
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
|
||||||
}) => {
|
|
||||||
if (!old) return old
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
pages: context?.prevInboxPages || old.pages,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if (context?.prevRequestsQueries) {
|
if (context?.prevRequestsQueries) {
|
||||||
for (const [queryKey, prevData] of context.prevRequestsQueries) {
|
for (const [queryKey, prevData] of context.prevRequestsQueries) {
|
||||||
queryClient.setQueryData(queryKey, prevData)
|
queryClient.setQueryData(queryKey, prevData)
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import {
|
|||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
import {
|
import {
|
||||||
type InfiniteData,
|
type InfiniteData,
|
||||||
|
type Query,
|
||||||
type QueryClient,
|
type QueryClient,
|
||||||
|
type QueryKey,
|
||||||
useInfiniteQuery,
|
useInfiniteQuery,
|
||||||
useQueryClient,
|
useQueryClient,
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
@@ -48,7 +50,60 @@ export const RQKEY = (
|
|||||||
| 'locked-permanently'
|
| 'locked-permanently'
|
||||||
| undefined = undefined,
|
| undefined = undefined,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
) => [RQKEY_ROOT, status, readState, kind, lockStatus, limit]
|
) => [RQKEY_ROOT, status, readState, kind, lockStatus, limit] as const
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix key matching every convo-list query with the given status (and
|
||||||
|
* optionally readState), regardless of the remaining params (kind,
|
||||||
|
* lockStatus, limit). Only valid with prefix-matching APIs (setQueriesData,
|
||||||
|
* getQueriesData, invalidateQueries) - exact-match APIs (getQueryData,
|
||||||
|
* setQueryData) hash the full key and will never match a prefix.
|
||||||
|
*/
|
||||||
|
export const RQKEY_PARTIAL = (
|
||||||
|
status: 'accepted' | 'request' | 'all',
|
||||||
|
readState?: 'all' | 'unread',
|
||||||
|
) => (readState ? [RQKEY_ROOT, status, readState] : [RQKEY_ROOT, status])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a convo satisfies the filters encoded in a convo-list query key.
|
||||||
|
* Caches are server-filtered, so optimistic inserts must apply the same
|
||||||
|
* filters client-side or convos leak into lists that should exclude them.
|
||||||
|
*/
|
||||||
|
export function convoMatchesQueryKey(
|
||||||
|
convo: ChatBskyConvoDefs.ConvoView,
|
||||||
|
queryKey: QueryKey,
|
||||||
|
): boolean {
|
||||||
|
const [, status, readState, kind, lockStatus] = queryKey as ReturnType<
|
||||||
|
typeof RQKEY
|
||||||
|
>
|
||||||
|
if (status !== 'all' && status !== convo.status) return false
|
||||||
|
if (readState === 'unread' && convo.unreadCount === 0) return false
|
||||||
|
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
|
||||||
|
if (kind === 'direct') return false
|
||||||
|
if (lockStatus && convo.kind.lockStatus !== lockStatus) return false
|
||||||
|
} else {
|
||||||
|
if (kind === 'group') return false
|
||||||
|
// direct convos are never locked
|
||||||
|
if (lockStatus && lockStatus !== 'unlocked') return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query predicate for optimistically upserting a convo into convo-list
|
||||||
|
* caches. Targets caches whose filters the convo satisfies, plus caches the
|
||||||
|
* convo is already in - those get updated in place even if the convo no
|
||||||
|
* longer matches (e.g. unreadCount dropped to 0), mirroring how read/mute
|
||||||
|
* log events update convos in place everywhere.
|
||||||
|
*/
|
||||||
|
export function convoListQueryPredicate(convo: ChatBskyConvoDefs.ConvoView) {
|
||||||
|
return (query: Query): boolean => {
|
||||||
|
const data = query.state.data as ConvoListQueryData | undefined
|
||||||
|
if (data && getConvoFromQueryData(convo.id, data)) return true
|
||||||
|
return convoMatchesQueryKey(convo, query.queryKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type RQPageParam = string | undefined
|
type RQPageParam = string | undefined
|
||||||
|
|
||||||
export function useListConvosQuery({
|
export function useListConvosQuery({
|
||||||
@@ -347,9 +402,12 @@ export function ListConvosProviderInner({
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// always update the unread one
|
// always update the unread ones, where the convo qualifies
|
||||||
queryClient.setQueriesData(
|
queryClient.setQueriesData(
|
||||||
{queryKey: RQKEY('all', 'unread')},
|
{
|
||||||
|
queryKey: RQKEY_PARTIAL('all', 'unread'),
|
||||||
|
predicate: convoListQueryPredicate(updatedConvo),
|
||||||
|
},
|
||||||
(old?: ConvoListQueryData) =>
|
(old?: ConvoListQueryData) =>
|
||||||
old
|
old
|
||||||
? updateFn(old)
|
? updateFn(old)
|
||||||
@@ -361,11 +419,20 @@ export function ListConvosProviderInner({
|
|||||||
// update the other ones based on status of the incoming message
|
// update the other ones based on status of the incoming message
|
||||||
if (updatedConvo.status === 'accepted') {
|
if (updatedConvo.status === 'accepted') {
|
||||||
queryClient.setQueriesData(
|
queryClient.setQueriesData(
|
||||||
{queryKey: RQKEY('accepted')},
|
{
|
||||||
|
queryKey: RQKEY_PARTIAL('accepted'),
|
||||||
|
predicate: convoListQueryPredicate(updatedConvo),
|
||||||
|
},
|
||||||
updateFn,
|
updateFn,
|
||||||
)
|
)
|
||||||
} else if (updatedConvo.status === 'request') {
|
} else if (updatedConvo.status === 'request') {
|
||||||
queryClient.setQueriesData({queryKey: RQKEY('request')}, updateFn)
|
queryClient.setQueriesData(
|
||||||
|
{
|
||||||
|
queryKey: RQKEY_PARTIAL('request'),
|
||||||
|
predicate: convoListQueryPredicate(updatedConvo),
|
||||||
|
},
|
||||||
|
updateFn,
|
||||||
|
)
|
||||||
// also move-to-top in the new requests cache
|
// also move-to-top in the new requests cache
|
||||||
queryClient.setQueriesData<ConvoRequestListQueryData>(
|
queryClient.setQueriesData<ConvoRequestListQueryData>(
|
||||||
{queryKey: [REQUESTS_RQKEY_ROOT]},
|
{queryKey: [REQUESTS_RQKEY_ROOT]},
|
||||||
@@ -385,20 +452,26 @@ export function ListConvosProviderInner({
|
|||||||
rev: log.rev,
|
rev: log.rev,
|
||||||
}))
|
}))
|
||||||
} else if (ChatBskyConvoDefs.isLogAcceptConvo(log)) {
|
} else if (ChatBskyConvoDefs.isLogAcceptConvo(log)) {
|
||||||
const requests = queryClient.getQueryData<ConvoListQueryData>(
|
const requestQueries =
|
||||||
RQKEY('request'),
|
queryClient.getQueriesData<ConvoListQueryData>({
|
||||||
)
|
queryKey: RQKEY_PARTIAL('request'),
|
||||||
if (!requests) {
|
})
|
||||||
|
let foundConvo: ChatBskyConvoDefs.ConvoView | null = null
|
||||||
|
for (const [_key, data] of requestQueries) {
|
||||||
|
if (!data) continue
|
||||||
|
foundConvo = getConvoFromQueryData(log.convoId, data)
|
||||||
|
if (foundConvo) break
|
||||||
|
}
|
||||||
|
if (!foundConvo) {
|
||||||
debouncedRefetch()
|
debouncedRefetch()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const acceptedConvo = getConvoFromQueryData(log.convoId, requests)
|
const acceptedConvo: ChatBskyConvoDefs.ConvoView = {
|
||||||
if (!acceptedConvo) {
|
...foundConvo,
|
||||||
debouncedRefetch()
|
status: 'accepted',
|
||||||
return
|
|
||||||
}
|
}
|
||||||
queryClient.setQueryData(
|
queryClient.setQueriesData(
|
||||||
RQKEY('request'),
|
{queryKey: RQKEY_PARTIAL('request')},
|
||||||
(old?: ConvoListQueryData) => optimisticDelete(log.convoId, old),
|
(old?: ConvoListQueryData) => optimisticDelete(log.convoId, old),
|
||||||
)
|
)
|
||||||
// also remove from the new requests cache
|
// also remove from the new requests cache
|
||||||
@@ -407,7 +480,10 @@ export function ListConvosProviderInner({
|
|||||||
old => optimisticDeleteRequest(log.convoId, old),
|
old => optimisticDeleteRequest(log.convoId, old),
|
||||||
)
|
)
|
||||||
queryClient.setQueriesData(
|
queryClient.setQueriesData(
|
||||||
{queryKey: RQKEY('accepted')},
|
{
|
||||||
|
queryKey: RQKEY_PARTIAL('accepted'),
|
||||||
|
predicate: convoListQueryPredicate(acceptedConvo),
|
||||||
|
},
|
||||||
(old?: ConvoListQueryData) => {
|
(old?: ConvoListQueryData) => {
|
||||||
if (!old) {
|
if (!old) {
|
||||||
debouncedRefetch()
|
debouncedRefetch()
|
||||||
@@ -420,12 +496,15 @@ export function ListConvosProviderInner({
|
|||||||
return {
|
return {
|
||||||
...page,
|
...page,
|
||||||
convos: [
|
convos: [
|
||||||
{...acceptedConvo, status: 'accepted'},
|
acceptedConvo,
|
||||||
...page.convos,
|
...page.convos.filter(c => c.id !== log.convoId),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return page
|
return {
|
||||||
|
...page,
|
||||||
|
convos: page.convos.filter(c => c.id !== log.convoId),
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -723,7 +802,14 @@ export function useUnreadMessageCount() {
|
|||||||
hasNew: false,
|
hasNew: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [accepted, request, currentAccount?.did, currentConvoId, moderationOpts])
|
}, [
|
||||||
|
accepted,
|
||||||
|
request,
|
||||||
|
currentAccount?.did,
|
||||||
|
currentConvoId,
|
||||||
|
moderationOpts,
|
||||||
|
aa.flags,
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateCount(
|
function calculateCount(
|
||||||
@@ -911,7 +997,7 @@ function addMemberToConvoView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function optimisticDelete(chatId: string, old?: ConvoListQueryData) {
|
export function optimisticDelete(chatId: string, old?: ConvoListQueryData) {
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import {type ChatBskyConvoListConvos} from '@atproto/api'
|
|
||||||
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
import {useMutation, useQueryClient} from '@tanstack/react-query'
|
||||||
|
|
||||||
import {DM_SERVICE_HEADERS} from '#/lib/constants'
|
import {DM_SERVICE_HEADERS} from '#/lib/constants'
|
||||||
@@ -9,7 +8,11 @@ import {
|
|||||||
markAllRead as markAllRequestsRead,
|
markAllRead as markAllRequestsRead,
|
||||||
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
|
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
|
||||||
} from './list-conversation-requests'
|
} from './list-conversation-requests'
|
||||||
import {RQKEY as CONVO_LIST_KEY} from './list-conversations'
|
import {
|
||||||
|
type ConvoListQueryData,
|
||||||
|
RQKEY_PARTIAL as CONVO_LIST_PARTIAL_KEY,
|
||||||
|
RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
|
||||||
|
} from './list-conversations'
|
||||||
|
|
||||||
export function useUpdateAllRead(
|
export function useUpdateAllRead(
|
||||||
status: 'accepted' | 'request',
|
status: 'accepted' | 'request',
|
||||||
@@ -36,18 +39,19 @@ export function useUpdateAllRead(
|
|||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
onMutate: () => {
|
onMutate: () => {
|
||||||
let prevPages: ChatBskyConvoListConvos.OutputSchema[] = []
|
// snapshot every convo-list cache up front so onError can restore them
|
||||||
|
// all by their exact keys
|
||||||
|
const prevConvoListQueries =
|
||||||
|
queryClient.getQueriesData<ConvoListQueryData>({
|
||||||
|
queryKey: [CONVO_LIST_ROOT_KEY],
|
||||||
|
})
|
||||||
let prevRequestsQueries: Array<
|
let prevRequestsQueries: Array<
|
||||||
[readonly unknown[], ConvoRequestListQueryData | undefined]
|
[readonly unknown[], ConvoRequestListQueryData | undefined]
|
||||||
> = []
|
> = []
|
||||||
queryClient.setQueryData(
|
queryClient.setQueriesData(
|
||||||
CONVO_LIST_KEY(status),
|
{queryKey: CONVO_LIST_PARTIAL_KEY(status)},
|
||||||
(old?: {
|
(old?: ConvoListQueryData) => {
|
||||||
pageParams: Array<string | undefined>
|
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
|
||||||
}) => {
|
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
prevPages = old.pages
|
|
||||||
return {
|
return {
|
||||||
...old,
|
...old,
|
||||||
pages: old.pages.map(page => {
|
pages: old.pages.map(page => {
|
||||||
@@ -64,13 +68,10 @@ export function useUpdateAllRead(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
// remove unread convos from the badge query
|
// remove unread convos from the badge queries
|
||||||
queryClient.setQueryData(
|
queryClient.setQueriesData(
|
||||||
CONVO_LIST_KEY('all', 'unread'),
|
{queryKey: CONVO_LIST_PARTIAL_KEY('all', 'unread')},
|
||||||
(old?: {
|
(old?: ConvoListQueryData) => {
|
||||||
pageParams: Array<string | undefined>
|
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
|
||||||
}) => {
|
|
||||||
if (!old) return old
|
if (!old) return old
|
||||||
return {
|
return {
|
||||||
...old,
|
...old,
|
||||||
@@ -94,10 +95,15 @@ export function useUpdateAllRead(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
onMutate?.()
|
onMutate?.()
|
||||||
return {prevPages, prevRequestsQueries}
|
return {prevConvoListQueries, prevRequestsQueries}
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
void queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
|
void queryClient.invalidateQueries({
|
||||||
|
queryKey: CONVO_LIST_PARTIAL_KEY(status),
|
||||||
|
})
|
||||||
|
void queryClient.invalidateQueries({
|
||||||
|
queryKey: CONVO_LIST_PARTIAL_KEY('all', 'unread'),
|
||||||
|
})
|
||||||
if (status === 'request') {
|
if (status === 'request') {
|
||||||
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
|
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
|
||||||
}
|
}
|
||||||
@@ -105,28 +111,17 @@ export function useUpdateAllRead(
|
|||||||
},
|
},
|
||||||
onError: (error, _, context) => {
|
onError: (error, _, context) => {
|
||||||
logger.error(error)
|
logger.error(error)
|
||||||
queryClient.setQueryData(
|
if (context?.prevConvoListQueries) {
|
||||||
CONVO_LIST_KEY(status),
|
for (const [queryKey, prevData] of context.prevConvoListQueries) {
|
||||||
(old?: {
|
queryClient.setQueryData(queryKey, prevData)
|
||||||
pageParams: Array<string | undefined>
|
}
|
||||||
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
}
|
||||||
}) => {
|
if (context?.prevRequestsQueries) {
|
||||||
if (!old) return old
|
|
||||||
return {
|
|
||||||
...old,
|
|
||||||
pages: context?.prevPages || old.pages,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
if (status === 'request' && context?.prevRequestsQueries) {
|
|
||||||
for (const [queryKey, prevData] of context.prevRequestsQueries) {
|
for (const [queryKey, prevData] of context.prevRequestsQueries) {
|
||||||
queryClient.setQueryData(queryKey, prevData)
|
queryClient.setQueryData(queryKey, prevData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
|
void queryClient.invalidateQueries({queryKey: [CONVO_LIST_ROOT_KEY]})
|
||||||
void queryClient.invalidateQueries({
|
|
||||||
queryKey: CONVO_LIST_KEY('all', 'unread'),
|
|
||||||
})
|
|
||||||
if (status === 'request') {
|
if (status === 'request') {
|
||||||
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
|
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user