Support group chats across other surfaces (#10266)
This commit is contained in:
@@ -77,6 +77,15 @@ export function NewChat({
|
||||
[control, createGroupChat],
|
||||
)
|
||||
|
||||
const onSelectExistingChat = useCallback(
|
||||
(chatId: string) => {
|
||||
control.close(() => {
|
||||
onNewChat(chatId)
|
||||
})
|
||||
},
|
||||
[control, onNewChat],
|
||||
)
|
||||
|
||||
const onPress = useCallback(() => {
|
||||
control.open()
|
||||
}, [control])
|
||||
@@ -112,7 +121,13 @@ export function NewChat({
|
||||
) : (
|
||||
<SearchablePeopleList
|
||||
title={l`Start a new chat`}
|
||||
onSelectChat={onCreateChat}
|
||||
onSelectChat={chat => {
|
||||
if (chat.kind === 'user') {
|
||||
onCreateChat(chat.did)
|
||||
} else {
|
||||
onSelectExistingChat(chat.id)
|
||||
}
|
||||
}}
|
||||
sortByMessageDeclaration
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -53,6 +53,13 @@ function SendViaChatDialogInner({
|
||||
},
|
||||
})
|
||||
|
||||
const onSelectExistingChat = useCallback(
|
||||
(chatId: string) => {
|
||||
control.close(() => onSelectChat(chatId))
|
||||
},
|
||||
[control, onSelectChat],
|
||||
)
|
||||
|
||||
const onCreateChat = useCallback(
|
||||
(did: string) => {
|
||||
control.close(() => createChat([did]))
|
||||
@@ -63,7 +70,13 @@ function SendViaChatDialogInner({
|
||||
return (
|
||||
<SearchablePeopleList
|
||||
title={_(msg`Send post to...`)}
|
||||
onSelectChat={onCreateChat}
|
||||
onSelectChat={chat => {
|
||||
if (chat.kind === 'user') {
|
||||
onCreateChat(chat.did)
|
||||
} else {
|
||||
onSelectExistingChat(chat.id)
|
||||
}
|
||||
}}
|
||||
showRecentConvos
|
||||
sortByMessageDeclaration
|
||||
/>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export {BottomSheetTextInput as TextInput} from '@discord/bottom-sheet/src'
|
||||
@@ -1 +0,0 @@
|
||||
export {TextInput} from 'react-native'
|
||||
@@ -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