Add relatedProfiles to convo
This commit is contained in:
@@ -4,23 +4,29 @@ import {useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {atoms as a} from '#/alf'
|
||||
import {MessageContextMenu} from '#/components/dms/MessageContextMenu'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
export function ActionsWrapper({
|
||||
message,
|
||||
isFromSelf,
|
||||
senderProfile,
|
||||
children,
|
||||
onTap,
|
||||
}: {
|
||||
message: ChatBskyConvoDefs.MessageView
|
||||
hasReactions?: boolean
|
||||
isFromSelf: boolean
|
||||
senderProfile?: bsky.profile.AnyProfileView
|
||||
children: React.ReactNode
|
||||
onTap?: () => void
|
||||
}) {
|
||||
const {t: l} = useLingui()
|
||||
|
||||
return (
|
||||
<MessageContextMenu message={message} onTap={onTap}>
|
||||
<MessageContextMenu
|
||||
message={message}
|
||||
senderProfile={senderProfile}
|
||||
onTap={onTap}>
|
||||
{trigger =>
|
||||
// will always be true, since this file is platform split
|
||||
trigger.IS_NATIVE && (
|
||||
|
||||
@@ -10,6 +10,7 @@ import {MessageContextMenu} from '#/components/dms/MessageContextMenu'
|
||||
import {DotGrid3x1_Stroke2_Corner0_Rounded as DotsHorizontalIcon} from '#/components/icons/DotGrid'
|
||||
import {EmojiSmile_Stroke2_Corner0_Rounded as EmojiSmileIcon} from '#/components/icons/Emoji'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {EmojiReactionPicker} from './EmojiReactionPicker'
|
||||
import {hasReachedReactionLimit} from './util'
|
||||
|
||||
@@ -17,12 +18,14 @@ export function ActionsWrapper({
|
||||
message,
|
||||
hasReactions,
|
||||
isFromSelf,
|
||||
senderProfile,
|
||||
children,
|
||||
onTap,
|
||||
}: {
|
||||
message: ChatBskyConvoDefs.MessageView
|
||||
hasReactions?: boolean
|
||||
isFromSelf: boolean
|
||||
senderProfile?: bsky.profile.AnyProfileView
|
||||
children: React.ReactNode
|
||||
onTap?: () => void
|
||||
}) {
|
||||
@@ -114,7 +117,7 @@ export function ActionsWrapper({
|
||||
)
|
||||
}}
|
||||
</EmojiReactionPicker>
|
||||
<MessageContextMenu message={message}>
|
||||
<MessageContextMenu message={message} senderProfile={senderProfile}>
|
||||
{({props, state, IS_NATIVE, control}) => {
|
||||
// always false, file is platform split
|
||||
if (IS_NATIVE) return null
|
||||
|
||||
@@ -25,15 +25,18 @@ import {usePromptControl} from '#/components/Prompt'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {EmojiReactionPicker} from './EmojiReactionPicker'
|
||||
import {hasReachedReactionLimit} from './util'
|
||||
|
||||
export let MessageContextMenu = ({
|
||||
message,
|
||||
senderProfile,
|
||||
children,
|
||||
onTap,
|
||||
}: {
|
||||
message: ChatBskyConvoDefs.MessageView
|
||||
senderProfile?: bsky.profile.AnyProfileView
|
||||
children: TriggerProps['children']
|
||||
onTap?: () => void
|
||||
}): React.ReactNode => {
|
||||
@@ -110,9 +113,7 @@ export let MessageContextMenu = ({
|
||||
[l, convo, message, currentAccount?.did],
|
||||
)
|
||||
|
||||
const sender = convo.convo.members.find(
|
||||
member => member.did === message.sender.did,
|
||||
)
|
||||
const sender = senderProfile
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -30,7 +30,6 @@ import {useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
|
||||
import {makeProfileLink} from '#/lib/routes/links'
|
||||
import {useConvoActive} from '#/state/messages/convo'
|
||||
import {type ConvoItem} from '#/state/messages/convo/types'
|
||||
import {useModerationOpts} from '#/state/preferences/moderation-opts'
|
||||
import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache'
|
||||
@@ -43,7 +42,6 @@ import {InlineLinkText, Link} from '#/components/Link'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {RichText} from '#/components/RichText'
|
||||
import {Text} from '#/components/Typography'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {DateDivider} from './DateDivider'
|
||||
import {useDateDividerToggle} from './DateDividerToggle'
|
||||
import {MessageItemEmbed} from './MessageItemEmbed'
|
||||
@@ -93,19 +91,20 @@ function isWithinClusterBoundary({
|
||||
let MessageItem = ({
|
||||
item,
|
||||
isGroupChat = false,
|
||||
profile,
|
||||
}: {
|
||||
item: ConvoItem & {type: 'message' | 'pending-message'}
|
||||
isGroupChat?: boolean
|
||||
profile?: bsky.profile.AnyProfileView
|
||||
}): React.ReactNode => {
|
||||
const t = useTheme()
|
||||
const {currentAccount} = useSession()
|
||||
const {t: l} = useLingui()
|
||||
const {convo} = useConvoActive()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const profile = item.relatedProfiles.find(
|
||||
p => p.did === item.message.sender.did,
|
||||
)
|
||||
|
||||
const reactionsControl = useDialogControl()
|
||||
const reactionTapRef = useRef(false)
|
||||
|
||||
@@ -277,9 +276,7 @@ let MessageItem = ({
|
||||
return l`You reacted ${reaction.value}`
|
||||
} else {
|
||||
const senderDid = reaction.sender.did
|
||||
const memberSender = convo.members.find(
|
||||
member => member.did === senderDid,
|
||||
)
|
||||
const memberSender = item.relatedProfiles.find(p => p.did === senderDid)
|
||||
if (memberSender) {
|
||||
return l`${createSanitizedDisplayName(memberSender)} reacted ${reaction.value}`
|
||||
}
|
||||
@@ -290,7 +287,13 @@ let MessageItem = ({
|
||||
one: '# person',
|
||||
other: '# people',
|
||||
})} reacted – ${groupedReactions.map(g => g.value).join(' ')}`
|
||||
}, [reactions, groupedReactions, currentAccount?.did, convo.members, l])
|
||||
}, [
|
||||
reactions,
|
||||
groupedReactions,
|
||||
currentAccount?.did,
|
||||
item.relatedProfiles,
|
||||
l,
|
||||
])
|
||||
|
||||
const appliedReactions = (
|
||||
<LayoutAnimationConfig skipEntering skipExiting>
|
||||
@@ -375,7 +378,7 @@ let MessageItem = ({
|
||||
) : null}
|
||||
<ReactionsDialog
|
||||
control={reactionsControl}
|
||||
members={convo.members}
|
||||
members={item.relatedProfiles}
|
||||
message={message}
|
||||
reactions={message.reactions}
|
||||
groupedReactions={groupedReactions}
|
||||
@@ -436,6 +439,7 @@ let MessageItem = ({
|
||||
hasReactions={hasReactions}
|
||||
isFromSelf={isFromSelf}
|
||||
message={message}
|
||||
senderProfile={profile}
|
||||
onTap={() => {
|
||||
if (reactionTapRef.current) return
|
||||
if (!hasLargeGapFromPrev) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api'
|
||||
import {ChatBskyConvoDefs} from '@atproto/api'
|
||||
import {type MessageDescriptor} from '@lingui/core'
|
||||
import {msg} from '@lingui/core/macro'
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
Unlock_Stroke2_Corner2_Rounded as UnlockIcon,
|
||||
} from '#/components/icons/Lock'
|
||||
import {PencilLine_Stroke2_Corner0_Rounded as PencilIcon} from '#/components/icons/Pencil'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
export type SystemMessageInfo = {
|
||||
message: MessageDescriptor
|
||||
@@ -23,7 +24,7 @@ export type SystemMessageInfo = {
|
||||
|
||||
function getReferredDisplayName(
|
||||
user: ChatBskyConvoDefs.SystemMessageReferredUser,
|
||||
relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[],
|
||||
relatedProfiles: bsky.profile.AnyProfileView[],
|
||||
): string | null {
|
||||
const profile = relatedProfiles.find(p => p.did === user.did)
|
||||
return profile ? createSanitizedDisplayName(profile) : null
|
||||
@@ -31,7 +32,7 @@ function getReferredDisplayName(
|
||||
|
||||
export function getSystemMessageInfo(
|
||||
data: ChatBskyConvoDefs.SystemMessageView['data'],
|
||||
relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[],
|
||||
relatedProfiles: bsky.profile.AnyProfileView[],
|
||||
): SystemMessageInfo | null {
|
||||
if (ChatBskyConvoDefs.isSystemMessageDataAddMember(data)) {
|
||||
const name = getReferredDisplayName(data.member, relatedProfiles)
|
||||
|
||||
@@ -374,9 +374,6 @@ export function MessagesList({
|
||||
return (
|
||||
<MessageItem
|
||||
item={item}
|
||||
profile={convoState.convo.members.find(
|
||||
member => member.did === item.message.sender.did,
|
||||
)}
|
||||
isGroupChat={convoState.convo.kind === 'group'}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -43,6 +43,7 @@ import {
|
||||
parseConvoView,
|
||||
} from '#/components/dms/util'
|
||||
import {IS_NATIVE} from '#/env'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
const logger = Logger.create(Logger.Context.ConversationAgent)
|
||||
|
||||
@@ -107,10 +108,7 @@ export class Convo {
|
||||
{id: string; message: ChatBskyConvoSendMessage.InputSchema['message']}
|
||||
> = new Map()
|
||||
private deletedMessages: Set<string> = new Set()
|
||||
private systemMessageProfiles: Map<
|
||||
string,
|
||||
ChatBskyActorDefs.ProfileViewBasic
|
||||
> = new Map()
|
||||
private relatedProfiles: Map<string, bsky.profile.AnyProfileView> = new Map()
|
||||
|
||||
private isProcessingPendingMessages = false
|
||||
|
||||
@@ -483,7 +481,7 @@ export class Convo {
|
||||
this.newMessages = new Map()
|
||||
this.pendingMessages = new Map()
|
||||
this.deletedMessages = new Set()
|
||||
this.systemMessageProfiles = new Map()
|
||||
this.relatedProfiles = new Map()
|
||||
|
||||
this.pendingMessageFailure = null
|
||||
this.fetchMessageHistoryError = undefined
|
||||
@@ -510,6 +508,11 @@ export class Convo {
|
||||
|
||||
private setConvo(convo: ChatBskyConvoDefs.ConvoView) {
|
||||
this.convo = parseConvoView(convo, this.senderUserDid) ?? this.convo
|
||||
if (this.convo) {
|
||||
for (const member of this.convo.members) {
|
||||
this.relatedProfiles.set(member.did, member)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private updateConvo(convo: Partial<ChatBskyConvoDefs.ConvoView>) {
|
||||
@@ -517,6 +520,9 @@ export class Convo {
|
||||
this.convo =
|
||||
parseConvoView({...this.convo.view, ...convo}, this.senderUserDid) ??
|
||||
this.convo
|
||||
for (const member of this.convo.members) {
|
||||
this.relatedProfiles.set(member.did, member)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -704,7 +710,7 @@ export class Convo {
|
||||
|
||||
if (relatedProfiles) {
|
||||
for (const profile of relatedProfiles) {
|
||||
this.systemMessageProfiles.set(profile.did, profile)
|
||||
this.relatedProfiles.set(profile.did, profile)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,6 +830,12 @@ export class Convo {
|
||||
*/
|
||||
this.latestRev = ev.rev
|
||||
|
||||
if ('relatedProfiles' in ev && Array.isArray(ev.relatedProfiles)) {
|
||||
for (const profile of ev.relatedProfiles) {
|
||||
this.relatedProfiles.set(profile.did, profile)
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
ChatBskyConvoDefs.isLogCreateMessage(ev) &&
|
||||
ChatBskyConvoDefs.isMessageView(ev.message)
|
||||
@@ -876,14 +888,6 @@ export class Convo {
|
||||
const systemView = toSystemMessageView(ev)
|
||||
if (systemView) {
|
||||
this.newMessages.set(systemView.id, systemView)
|
||||
if (
|
||||
'relatedProfiles' in ev &&
|
||||
Array.isArray(ev.relatedProfiles)
|
||||
) {
|
||||
for (const profile of ev.relatedProfiles) {
|
||||
this.systemMessageProfiles.set(profile.did, profile)
|
||||
}
|
||||
}
|
||||
needsCommit = true
|
||||
}
|
||||
}
|
||||
@@ -1168,6 +1172,44 @@ export class Convo {
|
||||
}
|
||||
}
|
||||
|
||||
private getRelatedProfilesForItem(
|
||||
m:
|
||||
| ChatBskyConvoDefs.MessageView
|
||||
| ChatBskyConvoDefs.DeletedMessageView
|
||||
| ChatBskyConvoDefs.SystemMessageView,
|
||||
): bsky.profile.AnyProfileView[] {
|
||||
const seen = new Set<string>()
|
||||
const profiles: bsky.profile.AnyProfileView[] = []
|
||||
|
||||
const add = (did: string) => {
|
||||
if (seen.has(did)) return
|
||||
seen.add(did)
|
||||
const p = this.relatedProfiles.get(did)
|
||||
if (p) profiles.push(p)
|
||||
}
|
||||
|
||||
if (ChatBskyConvoDefs.isMessageView(m)) {
|
||||
add(m.sender.did)
|
||||
if (m.reactions) {
|
||||
for (const reaction of m.reactions) {
|
||||
add(reaction.sender.did)
|
||||
}
|
||||
}
|
||||
} else if (ChatBskyConvoDefs.isDeletedMessageView(m)) {
|
||||
add(m.sender.did)
|
||||
} else if (ChatBskyConvoDefs.isSystemMessageView(m)) {
|
||||
const data = m.data
|
||||
if ('member' in data && data.member?.did) {
|
||||
add(data.member.did)
|
||||
}
|
||||
if ('addedBy' in data && data.addedBy?.did) {
|
||||
add(data.addedBy.did)
|
||||
}
|
||||
}
|
||||
|
||||
return profiles
|
||||
}
|
||||
|
||||
/*
|
||||
* Items in reverse order, since FlatList inverts
|
||||
*/
|
||||
@@ -1180,6 +1222,7 @@ export class Convo {
|
||||
type: 'message',
|
||||
key: m.id,
|
||||
message: m,
|
||||
relatedProfiles: this.getRelatedProfilesForItem(m),
|
||||
nextMessage: null,
|
||||
prevMessage: null,
|
||||
})
|
||||
@@ -1188,6 +1231,7 @@ export class Convo {
|
||||
type: 'deleted-message',
|
||||
key: m.id,
|
||||
message: m,
|
||||
relatedProfiles: this.getRelatedProfilesForItem(m),
|
||||
nextMessage: null,
|
||||
prevMessage: null,
|
||||
})
|
||||
@@ -1196,7 +1240,7 @@ export class Convo {
|
||||
type: 'system-message',
|
||||
key: m.id,
|
||||
message: m,
|
||||
relatedProfiles: Array.from(this.systemMessageProfiles.values()),
|
||||
relatedProfiles: this.getRelatedProfilesForItem(m),
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1218,6 +1262,7 @@ export class Convo {
|
||||
type: 'message',
|
||||
key: m.id,
|
||||
message: m,
|
||||
relatedProfiles: this.getRelatedProfilesForItem(m),
|
||||
nextMessage: null,
|
||||
prevMessage: null,
|
||||
})
|
||||
@@ -1226,6 +1271,7 @@ export class Convo {
|
||||
type: 'deleted-message',
|
||||
key: m.id,
|
||||
message: m,
|
||||
relatedProfiles: this.getRelatedProfilesForItem(m),
|
||||
nextMessage: null,
|
||||
prevMessage: null,
|
||||
})
|
||||
@@ -1234,12 +1280,13 @@ export class Convo {
|
||||
type: 'system-message',
|
||||
key: m.id,
|
||||
message: m,
|
||||
relatedProfiles: Array.from(this.systemMessageProfiles.values()),
|
||||
relatedProfiles: this.getRelatedProfilesForItem(m),
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
this.pendingMessages.forEach(m => {
|
||||
const senderProfile = this.relatedProfiles.get(this.senderUserDid)
|
||||
items.push({
|
||||
type: 'pending-message',
|
||||
key: m.id,
|
||||
@@ -1255,6 +1302,7 @@ export class Convo {
|
||||
did: this.senderUserDid,
|
||||
},
|
||||
},
|
||||
relatedProfiles: senderProfile ? [senderProfile] : [],
|
||||
nextMessage: null,
|
||||
prevMessage: null,
|
||||
failed: this.pendingMessageFailure !== null,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {
|
||||
type BskyAgent,
|
||||
type ChatBskyActorDefs,
|
||||
type ChatBskyConvoDefs,
|
||||
type ChatBskyConvoSendMessage,
|
||||
} from '@atproto/api'
|
||||
|
||||
import {type MessagesEventBus} from '#/state/messages/events/agent'
|
||||
import {type ConvoWithDetails} from '#/components/dms/util'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
|
||||
export type ConvoParams = {
|
||||
convoId: string
|
||||
@@ -87,6 +87,7 @@ export type ConvoItem =
|
||||
type: 'message'
|
||||
key: string
|
||||
message: ChatBskyConvoDefs.MessageView
|
||||
relatedProfiles: bsky.profile.AnyProfileView[]
|
||||
nextMessage:
|
||||
| ChatBskyConvoDefs.MessageView
|
||||
| ChatBskyConvoDefs.DeletedMessageView
|
||||
@@ -100,6 +101,7 @@ export type ConvoItem =
|
||||
type: 'pending-message'
|
||||
key: string
|
||||
message: ChatBskyConvoDefs.MessageView
|
||||
relatedProfiles: bsky.profile.AnyProfileView[]
|
||||
nextMessage:
|
||||
| ChatBskyConvoDefs.MessageView
|
||||
| ChatBskyConvoDefs.DeletedMessageView
|
||||
@@ -118,6 +120,7 @@ export type ConvoItem =
|
||||
type: 'deleted-message'
|
||||
key: string
|
||||
message: ChatBskyConvoDefs.DeletedMessageView
|
||||
relatedProfiles: bsky.profile.AnyProfileView[]
|
||||
nextMessage:
|
||||
| ChatBskyConvoDefs.MessageView
|
||||
| ChatBskyConvoDefs.DeletedMessageView
|
||||
@@ -131,7 +134,7 @@ export type ConvoItem =
|
||||
type: 'system-message'
|
||||
key: string
|
||||
message: ChatBskyConvoDefs.SystemMessageView
|
||||
relatedProfiles: ChatBskyActorDefs.ProfileViewBasic[]
|
||||
relatedProfiles: bsky.profile.AnyProfileView[]
|
||||
}
|
||||
| {
|
||||
type: 'error'
|
||||
|
||||
Reference in New Issue
Block a user