Support group chats across other surfaces (#10266)
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
import {type ChatBskyConvoDefs} from '@atproto/api'
|
||||
import {type $Typed, ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
|
||||
|
||||
import {EMOJI_REACTION_LIMIT} from '#/lib/constants'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {logger} from '#/logger'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
export function canBeMessaged(profile: bsky.profile.AnyProfileView) {
|
||||
switch (profile.associated?.chat?.allowIncoming) {
|
||||
@@ -54,3 +55,99 @@ export function hasReachedReactionLimit(
|
||||
)
|
||||
return myReactions.length >= EMOJI_REACTION_LIMIT
|
||||
}
|
||||
|
||||
type GroupConvoMember = ChatBskyActorDefs.ProfileViewBasic & {
|
||||
// can be missing if account deleted
|
||||
kind?: $Typed<ChatBskyActorDefs.GroupConvoMember>
|
||||
}
|
||||
|
||||
type DirectConvoMember = ChatBskyActorDefs.ProfileViewBasic & {
|
||||
kind: $Typed<ChatBskyActorDefs.DirectConvoMember>
|
||||
}
|
||||
|
||||
export type ConvoWithDetails = {view: ChatBskyConvoDefs.ConvoView} & (
|
||||
| {
|
||||
kind: 'group'
|
||||
details: ChatBskyConvoDefs.GroupConvo
|
||||
primaryMember: GroupConvoMember // the owner
|
||||
members: Array<GroupConvoMember>
|
||||
}
|
||||
| {
|
||||
kind: 'direct'
|
||||
details: ChatBskyConvoDefs.DirectConvo
|
||||
primaryMember: DirectConvoMember // the other user
|
||||
members: Array<DirectConvoMember>
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Converts a raw convoView into something easier to use (i.e. extracts chat owner)
|
||||
* and enforces the correct type for convo members.
|
||||
*/
|
||||
export function parseConvoView(
|
||||
convoView: ChatBskyConvoDefs.ConvoView,
|
||||
ownDid: string | undefined,
|
||||
): ConvoWithDetails | null {
|
||||
if (
|
||||
bsky.dangerousIsType<ChatBskyConvoDefs.GroupConvo>(
|
||||
convoView.kind,
|
||||
ChatBskyConvoDefs.isGroupConvo,
|
||||
)
|
||||
) {
|
||||
let owner: GroupConvoMember | undefined = undefined
|
||||
|
||||
for (const member of convoView.members) {
|
||||
if (
|
||||
bsky.dangerousIsType<ChatBskyActorDefs.GroupConvoMember>(
|
||||
member.kind,
|
||||
ChatBskyActorDefs.isGroupConvoMember,
|
||||
)
|
||||
) {
|
||||
if (member.kind.role === 'owner') {
|
||||
// have to do a type assertion here
|
||||
// this works: {...member, kind: member.kind}
|
||||
// however that's creating a new object for no good reason
|
||||
owner = member as GroupConvoMember
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
'Expected a GroupConvoMember, got an unknown kind of member',
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (!owner) {
|
||||
throw new Error('No owner found in group convo')
|
||||
}
|
||||
|
||||
return {
|
||||
view: convoView,
|
||||
kind: 'group',
|
||||
details: convoView.kind,
|
||||
primaryMember: owner,
|
||||
members: convoView.members as Array<GroupConvoMember>,
|
||||
}
|
||||
} else if (
|
||||
bsky.dangerousIsType<ChatBskyConvoDefs.DirectConvo>(
|
||||
convoView.kind,
|
||||
ChatBskyConvoDefs.isDirectConvo,
|
||||
)
|
||||
) {
|
||||
const otherUser = convoView.members.find(m => m.did !== ownDid)
|
||||
|
||||
if (!otherUser) {
|
||||
throw new Error('No other user found in direct convo')
|
||||
}
|
||||
|
||||
return {
|
||||
view: convoView,
|
||||
kind: 'direct',
|
||||
details: convoView.kind,
|
||||
primaryMember: otherUser as DirectConvoMember,
|
||||
members: convoView.members as Array<DirectConvoMember>,
|
||||
}
|
||||
} else {
|
||||
logger.warn('Unknown convo kind: ' + JSON.stringify(convoView.kind))
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user