(wip) restructure convo data dependencies - checkpoint

This commit is contained in:
Samuel Newman
2026-04-18 17:27:25 +03:00
parent bc3672ceeb
commit 528c91d8af
5 changed files with 90 additions and 101 deletions
+8 -46
View File
@@ -86,9 +86,10 @@ export class Convo {
private emitter = new EventEmitter<{event: [ConvoEvent]}>()
convoId: string
convo: ChatBskyConvoDefs.ConvoView | undefined
sender: ChatBskyActorDefs.ProfileViewBasic | undefined
recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
data: {
convoView: ChatBskyConvoDefs.ConvoView | undefined
memberList: ChatBskyActorDefs.ProfileViewBasic[]
}
snapshot: ConvoState | undefined
constructor(params: ConvoParams) {
@@ -97,10 +98,7 @@ export class Convo {
this.agent = params.agent
this.events = params.events
this.senderUserDid = params.agent.assertDid
if (params.placeholderData) {
this.setupPlaceholderData(params.placeholderData)
}
this.data = params.data
this.subscribe = this.subscribe.bind(this)
this.getSnapshot = this.getSnapshot.bind(this)
@@ -572,42 +570,6 @@ export class Convo {
}
}
private pendingFetchConvo:
| Promise<{
convo: ChatBskyConvoDefs.ConvoView
sender: ChatBskyActorDefs.ProfileViewBasic | undefined
recipients: ChatBskyActorDefs.ProfileViewBasic[]
}>
| undefined
async fetchConvo() {
if (this.pendingFetchConvo) return this.pendingFetchConvo
this.pendingFetchConvo = (async () => {
try {
const response = await networkRetry(2, () => {
return this.agent.api.chat.bsky.convo.getConvo(
{
convoId: this.convoId,
},
{headers: DM_SERVICE_HEADERS},
)
})
const convo = response.data.convo
return {
convo,
sender: convo.members.find(m => m.did === this.senderUserDid),
recipients: convo.members.filter(m => m.did !== this.senderUserDid),
}
} finally {
this.pendingFetchConvo = undefined
}
})()
return this.pendingFetchConvo
}
async refreshConvo() {
try {
const {convo, sender, recipients} = await this.fetchConvo()
@@ -930,7 +892,7 @@ export class Convo {
const {id, message} = pendingMessage
const response = await this.agent.api.chat.bsky.convo.sendMessage(
const response = await this.agent.chat.bsky.convo.sendMessage(
{
convoId: this.convoId,
message,
@@ -1025,7 +987,7 @@ export class Convo {
)
try {
const {data} = await this.agent.api.chat.bsky.convo.sendMessageBatch(
const {data} = await this.agent.chat.bsky.convo.sendMessageBatch(
{
items: messageArray.map(({message}) => ({
convoId: this.convoId,
@@ -1067,7 +1029,7 @@ export class Convo {
try {
await networkRetry(2, () => {
return this.agent.api.chat.bsky.convo.deleteMessageForSelf(
return this.agent.chat.bsky.convo.deleteMessageForSelf(
{
convoId: this.convoId,
messageId,
+17 -6
View File
@@ -24,6 +24,7 @@ import {isConvoActive} from '#/state/messages/convo/util'
import {useMessagesEventBus} from '#/state/messages/events'
import {
RQKEY as getConvoKey,
useConvoQuery,
useMarkAsReadMutation,
} from '#/state/queries/messages/conversation'
import {RQKEY_ROOT as ListConvosQueryKeyRoot} from '#/state/queries/messages/list-conversations'
@@ -72,20 +73,30 @@ export function ConvoProvider({
const queryClient = useQueryClient()
const agent = useAgent()
const events = useMessagesEventBus()
const {data: convoView} = useConvoQuery({convoId})
// const {data: convoMembers} = useListConvoMembersQuery({convoId})
// eslint-disable-next-line react/hook-use-state
const [convo] = useState(() => {
const placeholder = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
getConvoKey(convoId),
)
return new Convo({
convoId,
agent,
events,
placeholderData: placeholder ? {convo: placeholder} : undefined,
data: {
convoView,
// convoMembers,
},
})
})
const service = useSyncExternalStore(convo.subscribe, convo.getSnapshot)
const {mutate: markAsRead} = useMarkAsReadMutation()
useEffect(() => {
if (convoView) {
service.updateData({convoView})
}
}, [service, convoView])
const appState = useAppState()
const isActive = appState === 'active'
useFocusEffect(
@@ -107,11 +118,11 @@ export function ConvoProvider({
switch (event.type) {
case 'invalidate-block-state': {
for (const did of event.accountDids) {
queryClient.invalidateQueries({
void queryClient.invalidateQueries({
queryKey: createProfileQueryKey(did),
})
}
queryClient.invalidateQueries({
void queryClient.invalidateQueries({
queryKey: [ListConvosQueryKeyRoot],
})
}
+20 -48
View File
@@ -6,13 +6,15 @@ import {
} from '@atproto/api'
import {type MessagesEventBus} from '#/state/messages/events/agent'
import {type ConvoWithDetails} from '#/components/dms/util'
export type ConvoParams = {
convoId: string
agent: BskyAgent
events: MessagesEventBus
placeholderData?: {
convo: ChatBskyConvoDefs.ConvoView
data: {
convoView?: ChatBskyConvoDefs.ConvoView
memberList?: ChatBskyActorDefs.ProfileViewBasic[]
}
}
@@ -136,6 +138,7 @@ export type ConvoItem =
retry?: () => void
}
type UpdateConvoData = (data: ConvoParams['data']) => void
type DeleteMessage = (messageId: string) => Promise<void>
type SendMessage = (
message: ChatBskyConvoSendMessage.InputSchema['message'],
@@ -144,17 +147,13 @@ type FetchMessageHistory = () => Promise<void>
type MarkConvoAccepted = () => void
type AddReaction = (messageId: string, reaction: string) => Promise<void>
type RemoveReaction = (messageId: string, reaction: string) => Promise<void>
type IsGroup = () => boolean | undefined
type GetGroupInfo = () => ChatBskyConvoDefs.GroupConvo | undefined
type GetPrimaryMember = () => ChatBskyActorDefs.ProfileViewBasic | undefined
export type ConvoStateUninitialized = {
status: ConvoStatus.Uninitialized
items: []
convo: ChatBskyConvoDefs.ConvoView | undefined
convo: ConvoWithDetails | undefined
updateData: UpdateConvoData
error: undefined
sender: ChatBskyActorDefs.ProfileViewBasic | undefined
recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
isFetchingHistory: false
hasAllHistory: boolean
deleteMessage: undefined
@@ -163,17 +162,13 @@ export type ConvoStateUninitialized = {
markConvoAccepted: undefined
addReaction: undefined
removeReaction: undefined
isGroup: IsGroup
getGroupInfo: GetGroupInfo
getPrimaryMember: GetPrimaryMember
}
export type ConvoStateInitializing = {
status: ConvoStatus.Initializing
items: []
convo: ChatBskyConvoDefs.ConvoView | undefined
convo: ConvoWithDetails | undefined
updateData: UpdateConvoData
error: undefined
sender: ChatBskyActorDefs.ProfileViewBasic | undefined
recipients: ChatBskyActorDefs.ProfileViewBasic[] | undefined
isFetchingHistory: boolean
hasAllHistory: boolean
deleteMessage: undefined
@@ -182,17 +177,13 @@ export type ConvoStateInitializing = {
markConvoAccepted: undefined
addReaction: undefined
removeReaction: undefined
isGroup: IsGroup
getGroupInfo: GetGroupInfo
getPrimaryMember: GetPrimaryMember
}
export type ConvoStateReady = {
status: ConvoStatus.Ready
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
convo: ConvoWithDetails
updateData: UpdateConvoData
error: undefined
sender: ChatBskyActorDefs.ProfileViewBasic
recipients: ChatBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
hasAllHistory: boolean
deleteMessage: DeleteMessage
@@ -201,17 +192,13 @@ export type ConvoStateReady = {
markConvoAccepted: MarkConvoAccepted
addReaction: AddReaction
removeReaction: RemoveReaction
isGroup: IsGroup
getGroupInfo: GetGroupInfo
getPrimaryMember: GetPrimaryMember
}
export type ConvoStateBackgrounded = {
status: ConvoStatus.Backgrounded
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
convo: ConvoWithDetails
updateData: UpdateConvoData
error: undefined
sender: ChatBskyActorDefs.ProfileViewBasic
recipients: ChatBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
hasAllHistory: boolean
deleteMessage: DeleteMessage
@@ -220,17 +207,13 @@ export type ConvoStateBackgrounded = {
markConvoAccepted: MarkConvoAccepted
addReaction: AddReaction
removeReaction: RemoveReaction
isGroup: IsGroup
getGroupInfo: GetGroupInfo
getPrimaryMember: GetPrimaryMember
}
export type ConvoStateSuspended = {
status: ConvoStatus.Suspended
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
convo: ConvoWithDetails
updateData: UpdateConvoData
error: undefined
sender: ChatBskyActorDefs.ProfileViewBasic
recipients: ChatBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
hasAllHistory: boolean
deleteMessage: DeleteMessage
@@ -239,17 +222,13 @@ export type ConvoStateSuspended = {
markConvoAccepted: MarkConvoAccepted
addReaction: AddReaction
removeReaction: RemoveReaction
isGroup: IsGroup
getGroupInfo: GetGroupInfo
getPrimaryMember: GetPrimaryMember
}
export type ConvoStateError = {
status: ConvoStatus.Error
items: []
convo: undefined
items: ConvoItem[]
convo: ConvoWithDetails | undefined
updateData: UpdateConvoData
error: ConvoError
sender: undefined
recipients: undefined
isFetchingHistory: false
hasAllHistory: false
deleteMessage: undefined
@@ -258,17 +237,13 @@ export type ConvoStateError = {
markConvoAccepted: undefined
addReaction: undefined
removeReaction: undefined
isGroup: undefined
getGroupInfo: undefined
getPrimaryMember: undefined
}
export type ConvoStateDisabled = {
status: ConvoStatus.Disabled
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
convo: ConvoWithDetails
updateData: UpdateConvoData
error: undefined
sender: ChatBskyActorDefs.ProfileViewBasic
recipients: ChatBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
hasAllHistory: boolean
deleteMessage: DeleteMessage
@@ -277,9 +252,6 @@ export type ConvoStateDisabled = {
markConvoAccepted: MarkConvoAccepted
addReaction: AddReaction
removeReaction: RemoveReaction
isGroup: IsGroup
getGroupInfo: GetGroupInfo
getPrimaryMember: GetPrimaryMember
}
export type ConvoState =
| ConvoStateUninitialized
+2 -1
View File
@@ -31,7 +31,8 @@ export function useConvoQuery({convoId}: {convoId: string}) {
)
return data.convo
},
staleTime: STALE.INFINITY,
staleTime: STALE.MINUTES.THIRTY,
retry: 2,
})
}
@@ -0,0 +1,43 @@
// FOR WHEN WE ADD THE ENDPOINT TO LIST MEMBERS
// import {type ChatBskyActorDefs} from '@atproto/api'
// import {useQuery} from '@tanstack/react-query'
// import {DM_SERVICE_HEADERS} from '#/lib/constants'
// import {STALE} from '#/state/queries'
// import {useAgent} from '#/state/session'
// import {RQKEY as getConvoKey} from './conversation'
// const LIMIT = 50
// const RQKEY_SEGMENT = 'members'
// // invalidating a convo will also invalidate its member query
// export const listConvoMembersKey = (convoId: string) => [
// ...getConvoKey(convoId),
// RQKEY_SEGMENT,
// ]
// export function useListConvoMembersQuery({convoId}: {convoId: string}) {
// const agent = useAgent()
// return useQuery({
// queryKey: listConvoMembersKey(convoId),
// queryFn: async () => {
// const members: ChatBskyActorDefs.ProfileViewBasic[] = []
// let cursor
// do {
// const {data} = await agent.chat.bsky.group.listMembers(
// {convoId, cursor, limit: LIMIT},
// {headers: DM_SERVICE_HEADERS},
// )
// for (const member of data.members) {
// members.push(member)
// }
// cursor = data.cursor
// } while (cursor)
// return members
// },
// staleTime: STALE.MINUTES.THIRTY,
// retry: 2,
// })
// }