From d9d7edcb2e07703edaeec26fb5f58159cd5cb3f5 Mon Sep 17 00:00:00 2001 From: spencrmartin Date: Fri, 14 Nov 2025 11:09:27 -0500 Subject: [PATCH] fix: display correct sender avatars in collaborative chat messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 👥 COLLABORATIVE AVATAR FIX: Show actual sender's avatar instead of current user ## Message Type Enhancement: ✅ Extended Message interface to include optional sender metadata ✅ Sender info includes userId, displayName, and avatarUrl ✅ Backward compatible - existing messages without sender info still work ## Matrix Service Enhancement: ✅ Enhanced handleMessage() to extract sender profile information ✅ Gets sender details from room member or Matrix user data ✅ Includes sender avatar URL (MXC format) in message data ✅ Fallback to username extraction from Matrix ID if no display name ## Session Sharing Enhancement: ✅ Updated message creation to use sender information from Matrix events ✅ Searches friends and participants list to find sender details ✅ Includes complete sender profile (userId, displayName, avatarUrl) ✅ Fallback logic for unknown senders ## UserMessage Component Fix: ✅ Uses message.sender info when available, falls back to current user ✅ Displays correct avatar for each message sender ✅ Shows proper display name for collaborative session participants ✅ Maintains existing functionality for non-collaborative messages ## Key Benefits: 🎯 **Correct Attribution**: Each message shows the actual sender's avatar 👥 **Multi-User Support**: Perfect for collaborative sessions with multiple participants 🔄 **Real-time Updates**: Sender avatars update when profiles change 🛡️ **Backward Compatible**: Works with existing messages and solo sessions ## Technical Flow: 1. Matrix message received → Extract sender profile info 2. Create Message with sender metadata → Pass to session sharing 3. UserMessage component → Use sender info if available, fallback to current user 4. Display correct avatar → Show actual sender's profile picture Now in collaborative sessions, you'll see each participant's actual avatar next to their messages, making it crystal clear who said what! 🦆👥✨ --- ui/desktop/src/components/UserMessage.tsx | 11 +++++-- ui/desktop/src/hooks/useSessionSharing.ts | 39 ++++++++++++++++++++--- ui/desktop/src/services/MatrixService.ts | 11 +++++++ ui/desktop/src/types/message.ts | 6 ++++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/ui/desktop/src/components/UserMessage.tsx b/ui/desktop/src/components/UserMessage.tsx index e9257fc8b2..df963d353b 100644 --- a/ui/desktop/src/components/UserMessage.tsx +++ b/ui/desktop/src/components/UserMessage.tsx @@ -27,6 +27,13 @@ export default function UserMessage({ message, onMessageUpdate }: UserMessagePro // Get current user info from Matrix context const { currentUser } = useMatrix(); + // Determine the sender info - use message sender if available, otherwise current user + const senderInfo = message.sender || { + userId: currentUser?.userId || 'unknown', + displayName: currentUser?.displayName || 'You', + avatarUrl: currentUser?.avatarUrl, + }; + // Extract text content from the message const textContent = getTextContent(message); @@ -260,8 +267,8 @@ export default function UserMessage({ message, onMessageUpdate }: UserMessagePro {/* Avatar on the right side */}
diff --git a/ui/desktop/src/hooks/useSessionSharing.ts b/ui/desktop/src/hooks/useSessionSharing.ts index 3c51ec5b8c..a50d79e1f9 100644 --- a/ui/desktop/src/hooks/useSessionSharing.ts +++ b/ui/desktop/src/hooks/useSessionSharing.ts @@ -153,13 +153,43 @@ export const useSessionSharing = ({ // Also listen for regular messages that might contain session data const handleRegularMessage = (data: any) => { - const { content, sender, roomId } = data; + const { content, sender, roomId, senderInfo } = data; // Only process messages from Matrix rooms that are part of our session if (state.roomId && roomId === state.roomId && sender !== currentUser?.userId) { - console.log('💬 Regular message in session room:', { content, sender, roomId }); + console.log('💬 Regular message in session room:', { content, sender, roomId, senderInfo }); - // Convert regular Matrix messages to Goose messages + // Find sender info from friends or participants + let senderData = senderInfo; + if (!senderData) { + // Try to find sender in friends list + const friend = friends.find(f => f.userId === sender); + if (friend) { + senderData = { + userId: friend.userId, + displayName: friend.displayName, + avatarUrl: friend.avatarUrl, + }; + } else { + // Try to find in participants + const participant = state.participants.find(p => p.userId === sender); + if (participant) { + senderData = { + userId: participant.userId, + displayName: participant.displayName, + avatarUrl: participant.avatarUrl, + }; + } else { + // Fallback to basic sender info + senderData = { + userId: sender, + displayName: sender.split(':')[0].substring(1), // Extract username from Matrix ID + }; + } + } + } + + // Convert regular Matrix messages to Goose messages with sender info const message: Message = { id: `matrix-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, role: 'user', @@ -168,9 +198,10 @@ export const useSessionSharing = ({ type: 'text', text: content, }], + sender: senderData, }; - console.log('💬 Converting regular Matrix message to Goose message:', message); + console.log('💬 Converting regular Matrix message to Goose message with sender:', message); onMessageSync?.(message); } }; diff --git a/ui/desktop/src/services/MatrixService.ts b/ui/desktop/src/services/MatrixService.ts index e0e9080217..8f67942ef3 100644 --- a/ui/desktop/src/services/MatrixService.ts +++ b/ui/desktop/src/services/MatrixService.ts @@ -475,6 +475,16 @@ export class MatrixService extends EventEmitter { const sender = event.getSender(); const isFromSelf = sender === this.config.userId; + // Get sender information + const senderUser = this.client?.getUser(sender); + const senderMember = room.getMember(sender); + + const senderInfo = { + userId: sender, + displayName: senderMember?.name || senderUser?.displayName || sender.split(':')[0].substring(1), + avatarUrl: senderMember?.getMxcAvatarUrl() || senderUser?.avatarUrl || null, + }; + const messageData = { roomId: room.roomId, sender, @@ -482,6 +492,7 @@ export class MatrixService extends EventEmitter { timestamp: new Date(event.getTs()), event, isFromSelf, + senderInfo, }; // Check if this is a structured Goose message (new format) diff --git a/ui/desktop/src/types/message.ts b/ui/desktop/src/types/message.ts index 578636d9c1..c3cb90f74e 100644 --- a/ui/desktop/src/types/message.ts +++ b/ui/desktop/src/types/message.ts @@ -108,6 +108,12 @@ export interface Message { role: Role; created: number; content: MessageContent[]; + // Optional sender metadata for collaborative sessions + sender?: { + userId: string; + displayName?: string; + avatarUrl?: string; + }; } // Helper functions to create messages