Use new listConvoRequests endpoint (#10755)

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
This commit is contained in:
DS Boyce
2026-06-08 04:36:34 -07:00
committed by GitHub
parent c02f2a1eda
commit e60e31733a
12 changed files with 628 additions and 180 deletions
+2
View File
@@ -11,6 +11,7 @@ import {findAllProfilesInQueryData as findAllProfilesInContactMatchesQueryData}
import {findAllProfilesInQueryData as findAllProfilesInKnownFollowersQueryData} from '#/state/queries/known-followers'
import {findAllProfilesInQueryData as findAllProfilesInListMembersQueryData} from '#/state/queries/list-members'
import {findAllProfilesInQueryData as findAllProfilesInGetConvoQueryData} from '#/state/queries/messages/conversation'
import {findAllProfilesInQueryData as findAllProfilesInListConvoRequestsQueryData} from '#/state/queries/messages/list-conversation-requests'
import {findAllProfilesInQueryData as findAllProfilesInListConvosQueryData} from '#/state/queries/messages/list-conversations'
import {findAllProfilesInQueryData as findAllProfilesInMessagesQueryData} from '#/state/queries/messages/list-convo-members'
import {findAllProfilesInQueryData as findAllProfilesInMyBlockedAccountsQueryData} from '#/state/queries/my-blocked-accounts'
@@ -259,6 +260,7 @@ function* findProfilesInCache(
yield* findAllProfilesInSuggestedFollowsQueryData(queryClient, did)
yield* findAllProfilesInActorSearchQueryData(queryClient, did)
yield* findAllProfilesInListConvosQueryData(queryClient, did)
yield* findAllProfilesInListConvoRequestsQueryData(queryClient, did)
yield* findAllProfilesInFeedsQueryData(queryClient, did)
yield* findAllProfilesInPostThreadV2QueryData(queryClient, did)
yield* findAllProfilesInKnownFollowersQueryData(queryClient, did)
@@ -7,6 +7,11 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger'
import {useAgent} from '#/state/session'
import {
type ConvoRequestListQueryData,
optimisticDelete as optimisticDeleteRequest,
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
} from './list-conversation-requests'
import {
RQKEY as CONVO_LIST_KEY,
RQKEY_ROOT as CONVO_LIST_ROOT_KEY,
@@ -96,11 +101,20 @@ export function useAcceptConversation(
}
},
)
const prevRequestsQueries =
queryClient.getQueriesData<ConvoRequestListQueryData>({
queryKey: [REQUESTS_RQKEY_ROOT],
})
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticDeleteRequest(convoId, old),
)
onMutate?.()
return {prevAcceptedPages, prevInboxPages}
return {prevAcceptedPages, prevInboxPages, prevRequestsQueries}
},
onSuccess: data => {
queryClient.invalidateQueries({queryKey: [CONVO_LIST_KEY]})
void queryClient.invalidateQueries({queryKey: [CONVO_LIST_KEY]})
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
onSuccess?.(data)
},
onError: (error, _, context) => {
@@ -131,7 +145,13 @@ export function useAcceptConversation(
}
},
)
queryClient.invalidateQueries({queryKey: [CONVO_LIST_ROOT_KEY]})
if (context?.prevRequestsQueries) {
for (const [queryKey, prevData] of context.prevRequestsQueries) {
queryClient.setQueryData(queryKey, prevData)
}
}
void queryClient.invalidateQueries({queryKey: [CONVO_LIST_ROOT_KEY]})
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
onError?.(error)
},
})
@@ -0,0 +1,165 @@
import {
ChatBskyConvoDefs,
type ChatBskyConvoListConvoRequests,
ChatBskyGroupDefs,
} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
useInfiniteQuery,
} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {useAgent} from '#/state/session'
const DEFAULT_LIMIT = 10
export const RQKEY_ROOT = 'convo-request-list'
export const RQKEY = (limit: number = DEFAULT_LIMIT) => [RQKEY_ROOT, limit]
type RQPageParam = string | undefined
export function useListConvoRequests({
enabled = true,
limit = DEFAULT_LIMIT,
}: {
enabled?: boolean
limit?: number
} = {}) {
const agent = useAgent()
return useInfiniteQuery({
enabled,
queryKey: RQKEY(limit),
queryFn: async ({pageParam}) => {
const {data} = await agent.chat.bsky.convo.listConvoRequests(
{limit, cursor: pageParam},
{headers: DM_SERVICE_HEADERS},
)
return data
},
initialPageParam: undefined as RQPageParam,
getNextPageParam: lastPage => lastPage.cursor,
})
}
export type ConvoRequestListQueryData = {
pageParams: Array<string | undefined>
pages: Array<ChatBskyConvoListConvoRequests.OutputSchema>
}
export type ConvoRequestItem =
ChatBskyConvoListConvoRequests.OutputSchema['requests'][number]
export function optimisticUpdate(
chatId: string,
old: ConvoRequestListQueryData | undefined,
updateFn: (convo: ChatBskyConvoDefs.ConvoView) => ChatBskyConvoDefs.ConvoView,
): ConvoRequestListQueryData | undefined {
if (!old) return old
return {
...old,
pages: old.pages.map(page => ({
...page,
requests: page.requests.map((item): ConvoRequestItem => {
if (ChatBskyConvoDefs.isConvoView(item) && item.id === chatId) {
return {
...updateFn(item),
$type: 'chat.bsky.convo.defs#convoView',
}
}
return item
}),
})),
}
}
export function optimisticDelete(
chatId: string,
old: ConvoRequestListQueryData | undefined,
) {
if (!old) return old
return {
...old,
pages: old.pages.map(page => ({
...page,
requests: page.requests.filter(
item => !ChatBskyConvoDefs.isConvoView(item) || item.id !== chatId,
),
})),
}
}
export function markAllRead(
old: ConvoRequestListQueryData | undefined,
): ConvoRequestListQueryData | undefined {
if (!old) return old
return {
...old,
pages: old.pages.map(page => ({
...page,
requests: page.requests.map((item): ConvoRequestItem => {
if (ChatBskyConvoDefs.isConvoView(item)) {
return {
...item,
$type: 'chat.bsky.convo.defs#convoView',
unreadCount: 0,
}
}
return item
}),
})),
}
}
export function optimisticDeleteJoinRequest(
convoId: string,
old: ConvoRequestListQueryData | undefined,
) {
if (!old) return old
return {
...old,
pages: old.pages.map(page => ({
...page,
requests: page.requests.filter(
item =>
!ChatBskyGroupDefs.isJoinRequestConvoView(item) ||
item.convoId !== convoId,
),
})),
}
}
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
) {
const queryDatas = queryClient.getQueriesData<
InfiniteData<ChatBskyConvoListConvoRequests.OutputSchema>
>({
queryKey: [RQKEY_ROOT],
})
for (const [_queryKey, queryData] of queryDatas) {
if (!queryData?.pages) continue
for (const page of queryData.pages) {
for (const item of page.requests) {
if (ChatBskyConvoDefs.isConvoView(item)) {
for (const member of item.members) {
if (member.did === did) {
yield member
}
}
} else if (ChatBskyGroupDefs.isJoinRequestConvoView(item)) {
if (item.owner.did === did) {
yield item.owner
}
}
}
}
}
}
+215 -133
View File
@@ -23,6 +23,13 @@ import {parseConvoView} from '#/components/dms/util'
import * as bsky from '#/types/bsky'
import {RQKEY as CONVO_KEY} from './conversation'
import {useLeftConvos} from './leave-conversation'
import {
type ConvoRequestListQueryData,
optimisticDelete as optimisticDeleteRequest,
optimisticDeleteJoinRequest,
optimisticUpdate as optimisticUpdateRequest,
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
} from './list-conversation-requests'
import {listConvoMembersQueryKey} from './list-convo-members'
const DEFAULT_LIMIT = 10
@@ -130,6 +137,7 @@ export function ListConvosProviderInner({
const refetchAndInvalidate = () => {
void refetch()
void queryClient.invalidateQueries({queryKey: [RQKEY_ROOT]})
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
}
return throttle(refetchAndInvalidate, 500, {
leading: true,
@@ -157,6 +165,22 @@ export function ListConvosProviderInner({
)
}
function updateConvoInAllLists(
convoId: string,
fn: (
convo: ChatBskyConvoDefs.ConvoView,
) => ChatBskyConvoDefs.ConvoView,
) {
queryClient.setQueriesData<ConvoListQueryData>(
{queryKey: [RQKEY_ROOT]},
old => optimisticUpdate(convoId, old, fn),
)
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticUpdateRequest(convoId, old, fn),
)
}
function mutateConvoView(
convoId: string,
fn: (
@@ -167,9 +191,17 @@ export function ListConvosProviderInner({
CONVO_KEY(convoId),
old => (old ? fn(old) : old),
)
updateConvoInAllLists(convoId, fn)
}
function deleteConvoFromAllLists(convoId: string) {
queryClient.setQueriesData<ConvoListQueryData>(
{queryKey: [RQKEY_ROOT]},
old => optimisticUpdate(convoId, old, fn),
old => optimisticDelete(convoId, old),
)
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticDeleteRequest(convoId, old),
)
}
@@ -220,35 +252,26 @@ export function ListConvosProviderInner({
if (ChatBskyConvoDefs.isLogBeginConvo(log)) {
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogLeaveConvo(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) => optimisticDelete(log.convoId, old),
)
deleteConvoFromAllLists(log.convoId)
} else if (ChatBskyConvoDefs.isLogDeleteMessage(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
optimisticUpdate(log.convoId, old, convo => {
if (
(ChatBskyConvoDefs.isDeletedMessageView(log.message) ||
ChatBskyConvoDefs.isMessageView(log.message)) &&
(ChatBskyConvoDefs.isDeletedMessageView(
convo.lastMessage,
) ||
ChatBskyConvoDefs.isMessageView(convo.lastMessage))
) {
return log.message.id === convo.lastMessage.id
? {
...convo,
rev: log.rev,
lastMessage: log.message,
}
: convo
} else {
return convo
}
}),
)
updateConvoInAllLists(log.convoId, convo => {
if (
(ChatBskyConvoDefs.isDeletedMessageView(log.message) ||
ChatBskyConvoDefs.isMessageView(log.message)) &&
(ChatBskyConvoDefs.isDeletedMessageView(convo.lastMessage) ||
ChatBskyConvoDefs.isMessageView(convo.lastMessage))
) {
return log.message.id === convo.lastMessage.id
? {
...convo,
rev: log.rev,
lastMessage: log.message,
}
: convo
} else {
return convo
}
})
} else if (ChatBskyConvoDefs.isLogCreateMessage(log)) {
// Store in a new var to avoid TS errors due to closures.
const logRef: ChatBskyConvoDefs.LogCreateMessage = log
@@ -335,27 +358,24 @@ export function ListConvosProviderInner({
)
} else if (updatedConvo.status === 'request') {
queryClient.setQueriesData({queryKey: RQKEY('request')}, updateFn)
// also move-to-top in the new requests cache
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => moveConvoToTopInRequests(updatedConvo, old),
)
}
} else if (ChatBskyConvoDefs.isLogReadMessage(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
optimisticUpdate(log.convoId, old, convo => ({
...convo,
unreadCount: 0,
rev: log.rev,
})),
)
updateConvoInAllLists(log.convoId, convo => ({
...convo,
unreadCount: 0,
rev: log.rev,
}))
} else if (ChatBskyConvoDefs.isLogReadConvo(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
optimisticUpdate(log.convoId, old, convo => ({
...convo,
unreadCount: 0,
rev: log.rev,
})),
)
updateConvoInAllLists(log.convoId, convo => ({
...convo,
unreadCount: 0,
rev: log.rev,
}))
} else if (ChatBskyConvoDefs.isLogAcceptConvo(log)) {
const requests = queryClient.getQueryData<ConvoListQueryData>(
RQKEY('request'),
@@ -373,6 +393,11 @@ export function ListConvosProviderInner({
RQKEY('request'),
(old?: ConvoListQueryData) => optimisticDelete(log.convoId, old),
)
// also remove from the new requests cache
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticDeleteRequest(log.convoId, old),
)
queryClient.setQueriesData(
{queryKey: RQKEY('accepted')},
(old?: ConvoListQueryData) => {
@@ -398,55 +423,50 @@ export function ListConvosProviderInner({
},
)
} else if (ChatBskyConvoDefs.isLogMuteConvo(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
optimisticUpdate(log.convoId, old, convo => ({
...convo,
muted: true,
rev: log.rev,
})),
)
updateConvoInAllLists(log.convoId, convo => ({
...convo,
muted: true,
rev: log.rev,
}))
} else if (ChatBskyConvoDefs.isLogUnmuteConvo(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
optimisticUpdate(log.convoId, old, convo => ({
...convo,
muted: false,
rev: log.rev,
})),
)
updateConvoInAllLists(log.convoId, convo => ({
...convo,
muted: false,
rev: log.rev,
}))
} else if (ChatBskyConvoDefs.isLogLockConvo(log)) {
mutateConvoView(log.convoId, convo =>
ChatBskyConvoDefs.isGroupConvo(convo.kind)
? {
...convo,
kind: {...convo.kind, lockStatus: 'locked'},
rev: log.rev,
}
: {...convo, rev: log.rev},
)
mutateConvoView(log.convoId, convo => {
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
return {
...convo,
kind: {...convo.kind, lockStatus: 'locked'},
rev: log.rev,
}
}
return {...convo, rev: log.rev}
})
} else if (ChatBskyConvoDefs.isLogUnlockConvo(log)) {
mutateConvoView(log.convoId, convo =>
ChatBskyConvoDefs.isGroupConvo(convo.kind)
? {
...convo,
kind: {...convo.kind, lockStatus: 'unlocked'},
rev: log.rev,
}
: {...convo, rev: log.rev},
)
mutateConvoView(log.convoId, convo => {
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
return {
...convo,
kind: {...convo.kind, lockStatus: 'unlocked'},
rev: log.rev,
}
}
return {...convo, rev: log.rev}
})
} else if (ChatBskyConvoDefs.isLogLockConvoPermanently(log)) {
mutateConvoView(log.convoId, convo =>
ChatBskyConvoDefs.isGroupConvo(convo.kind)
? {
...convo,
kind: {...convo.kind, lockStatus: 'locked-permanently'},
rev: log.rev,
}
: {...convo, rev: log.rev},
)
mutateConvoView(log.convoId, convo => {
if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
return {
...convo,
kind: {...convo.kind, lockStatus: 'locked-permanently'},
rev: log.rev,
}
}
return {...convo, rev: log.rev}
})
} else if (
ChatBskyConvoDefs.isLogCreateJoinLink(log) ||
ChatBskyConvoDefs.isLogEditJoinLink(log) ||
@@ -455,37 +475,68 @@ export function ListConvosProviderInner({
) {
// Join link data not included in the log event, trigger refetch to get it
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogEditGroup(log)) {
// Updated group details (name etc.) aren't included in the log
// event, so refetch to pick them up.
debouncedRefetch()
} else if (
ChatBskyConvoDefs.isLogApproveJoinRequest(log) ||
ChatBskyConvoDefs.isLogRejectJoinRequest(log)
) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
updateGroupConvoJoinRequestCount(log, old, -1),
// Route through mutateConvoView (not updateConvoInAllLists) so the
// single-convo cache updates too, keeping the in-convo requests
// banner in sync.
mutateConvoView(log.convoId, convo =>
applyJoinRequestCountDelta(convo, log.rev, -1),
)
} else if (ChatBskyConvoDefs.isLogIncomingJoinRequest(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
updateGroupConvoJoinRequestCount(log, old, 1),
// Route through mutateConvoView (not updateConvoInAllLists) so the
// single-convo cache updates too, letting the in-convo requests
// banner appear live.
mutateConvoView(log.convoId, convo =>
applyJoinRequestCountDelta(convo, log.rev, 1),
)
} else if (ChatBskyConvoDefs.isLogReadJoinRequests(log)) {
// The owner marked join requests as read (possibly on another
// device). Zero the unread count but keep the total, mirroring the
// useMarkJoinRequestsRead mutation.
mutateConvoView(log.convoId, convo => {
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
return {...convo, rev: log.rev}
}
return {
...convo,
kind: {...convo.kind, unreadJoinRequestCount: 0},
rev: log.rev,
}
})
} else if (ChatBskyConvoDefs.isLogOutgoingJoinRequest(log)) {
// Viewer isn't in the chat yet, no need to do anything
} else if (ChatBskyConvoDefs.isLogAddReaction(log)) {
queryClient.setQueriesData(
{queryKey: [RQKEY_ROOT]},
(old?: ConvoListQueryData) =>
optimisticUpdate(log.convoId, old, convo => ({
...convo,
lastReaction: {
$type: 'chat.bsky.convo.defs#messageAndReactionView',
reaction: log.reaction,
message: log.message,
},
rev: log.rev,
})),
// Viewer isn't in the chat yet, but the inbox surfaces outgoing
// requests, so refetch to pick up the new entry.
debouncedRefetch()
} else if (ChatBskyConvoDefs.isLogWithdrawIncomingJoinRequest(log)) {
// A requester rescinded their request to a group the viewer owns.
// Mirror of isLogIncomingJoinRequest: decrement the counts.
mutateConvoView(log.convoId, convo =>
applyJoinRequestCountDelta(convo, log.rev, -1),
)
} else if (ChatBskyConvoDefs.isLogWithdrawOutgoingJoinRequest(log)) {
// The viewer rescinded their own outgoing join request (possibly on
// another device). Remove it from the requests inbox cache.
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticDeleteJoinRequest(log.convoId, old),
)
} else if (ChatBskyConvoDefs.isLogAddReaction(log)) {
updateConvoInAllLists(log.convoId, convo => ({
...convo,
lastReaction: {
$type: 'chat.bsky.convo.defs#messageAndReactionView',
reaction: log.reaction,
message: log.message,
},
rev: log.rev,
}))
} else if (ChatBskyConvoDefs.isLogAddMember(log)) {
const data = log.message.data
if (
@@ -739,27 +790,58 @@ function optimisticUpdate(
}
}
function updateGroupConvoJoinRequestCount(
log: {convoId: string; rev: string},
old: ConvoListQueryData | undefined,
function applyJoinRequestCountDelta(
convo: ChatBskyConvoDefs.ConvoView,
rev: string,
delta: 1 | -1,
) {
return optimisticUpdate(log.convoId, old, convo => {
// Join requests are only meaningful for group convos.
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
return {...convo, rev: log.rev}
): ChatBskyConvoDefs.ConvoView {
// Join requests are only meaningful for group convos.
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
return {...convo, rev}
}
// Bump the total and unread counts together. Both are clamped at 0 and
// collapse to undefined when empty, matching the server's shape.
const bump = (current: number | undefined) => {
const next = Math.max(0, (current ?? 0) + delta)
return next === 0 ? undefined : next
}
return {
...convo,
kind: {
...convo.kind,
joinRequestCount: bump(convo.kind.joinRequestCount),
unreadJoinRequestCount: bump(convo.kind.unreadJoinRequestCount),
},
rev,
}
}
function moveConvoToTopInRequests(
updatedConvo: ChatBskyConvoDefs.ConvoView,
old: ConvoRequestListQueryData | undefined,
): ConvoRequestListQueryData | undefined {
if (!old) return old
const typedConvo: ConvoRequestListQueryData['pages'][number]['requests'][number] =
{
$type: 'chat.bsky.convo.defs#convoView',
...updatedConvo,
}
const current = convo.kind.joinRequestCount ?? 0
const next = Math.max(0, current + delta)
return {
...convo,
kind: {
...convo.kind,
joinRequestCount: next === 0 ? undefined : next,
},
rev: log.rev,
}
})
return {
...old,
pages: old.pages.map((page, i) => {
const filtered = page.requests.filter(
item =>
!ChatBskyConvoDefs.isConvoView(item) || item.id !== updatedConvo.id,
)
if (i === 0) {
return {
...page,
requests: [typedConvo, ...filtered],
}
}
return {...page, requests: filtered}
}),
}
}
function removeMemberFromConvoView(
@@ -1,9 +1,10 @@
import {type ChatBskyGroupRequestJoin} from '@atproto/api'
import {useMutation} from '@tanstack/react-query'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger'
import {useAgent, useSession} from '#/state/session'
import {RQKEY_ROOT as REQUESTS_RQKEY_ROOT} from './list-conversation-requests'
export function useRequestJoinGroupChat({
onSuccess,
@@ -13,6 +14,7 @@ export function useRequestJoinGroupChat({
onError?: (error: Error) => void
} = {}) {
const agent = useAgent()
const queryClient = useQueryClient()
const {hasSession} = useSession()
return useMutation({
@@ -27,6 +29,7 @@ export function useRequestJoinGroupChat({
return res.data
},
onSuccess: data => {
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
onSuccess?.(data)
},
onError: error => {
+35 -4
View File
@@ -4,6 +4,11 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger'
import {useAgent} from '#/state/session'
import {
type ConvoRequestListQueryData,
markAllRead as markAllRequestsRead,
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
} from './list-conversation-requests'
import {RQKEY as CONVO_LIST_KEY} from './list-conversations'
export function useUpdateAllRead(
@@ -32,6 +37,9 @@ export function useUpdateAllRead(
},
onMutate: () => {
let prevPages: ChatBskyConvoListConvos.OutputSchema[] = []
let prevRequestsQueries: Array<
[readonly unknown[], ConvoRequestListQueryData | undefined]
> = []
queryClient.setQueryData(
CONVO_LIST_KEY(status),
(old?: {
@@ -75,11 +83,24 @@ export function useUpdateAllRead(
}
},
)
if (status === 'request') {
prevRequestsQueries =
queryClient.getQueriesData<ConvoRequestListQueryData>({
queryKey: [REQUESTS_RQKEY_ROOT],
})
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
markAllRequestsRead,
)
}
onMutate?.()
return {prevPages}
return {prevPages, prevRequestsQueries}
},
onSuccess: () => {
queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
void queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
if (status === 'request') {
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
}
onSuccess?.()
},
onError: (error, _, context) => {
@@ -97,8 +118,18 @@ export function useUpdateAllRead(
}
},
)
queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY('all', 'unread')})
if (status === 'request' && context?.prevRequestsQueries) {
for (const [queryKey, prevData] of context.prevRequestsQueries) {
queryClient.setQueryData(queryKey, prevData)
}
}
void queryClient.invalidateQueries({queryKey: CONVO_LIST_KEY(status)})
void queryClient.invalidateQueries({
queryKey: CONVO_LIST_KEY('all', 'unread'),
})
if (status === 'request') {
void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]})
}
onError?.(error)
},
})
@@ -1,9 +1,14 @@
import {type ChatBskyGroupWithdrawJoinRequest} from '@atproto/api'
import {useMutation} from '@tanstack/react-query'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger'
import {useAgent, useSession} from '#/state/session'
import {
type ConvoRequestListQueryData,
optimisticDeleteJoinRequest,
RQKEY_ROOT as REQUESTS_RQKEY_ROOT,
} from './list-conversation-requests'
export function useWithdrawJoinGroupChatRequest({
onSuccess,
@@ -13,6 +18,7 @@ export function useWithdrawJoinGroupChatRequest({
onError?: (error: Error) => void
} = {}) {
const agent = useAgent()
const queryClient = useQueryClient()
const {hasSession} = useSession()
return useMutation({
@@ -27,7 +33,11 @@ export function useWithdrawJoinGroupChatRequest({
)
return res.data
},
onSuccess: data => {
onSuccess: (data, {convoId}) => {
queryClient.setQueriesData<ConvoRequestListQueryData>(
{queryKey: [REQUESTS_RQKEY_ROOT]},
old => optimisticDeleteJoinRequest(convoId, old),
)
onSuccess?.(data)
},
onError: error => {