feat: real-time user profile updates and propagate avatarColor to all Avatar callsites
Broadcast user_updated events over WebSocket when profile fields change, updating members, DM participants, friends, and cached messages in real time. Widen useVoiceParticipantMeta to return the full user object and add a standalone avatarColor prop to Avatar so all ~16 callsites now resolve the user's chosen gradient color instead of falling back to hash-based colors.
This commit is contained in:
@@ -2,9 +2,10 @@ import { useMemo } from 'react';
|
||||
import { useSpaceStore } from '../stores/spaceStore';
|
||||
import { parseFederatedUsername } from '../utils/identity';
|
||||
import type { ParticipantInfo } from './useLiveKit';
|
||||
import type { User } from '@backspace/shared';
|
||||
|
||||
/**
|
||||
* Resolves display metadata (displayName, avatar) for a voice participant
|
||||
* Resolves display metadata (displayName, avatar, user) for a voice participant
|
||||
* by looking up member data from the space/DM stores.
|
||||
*
|
||||
* Reactive — re-renders when member data changes (e.g. user updates avatar mid-call).
|
||||
@@ -21,6 +22,7 @@ export function useVoiceParticipantMeta(participant: ParticipantInfo) {
|
||||
return {
|
||||
displayName: member.user.displayName ?? baseName,
|
||||
avatar: member.user.avatar ?? null,
|
||||
user: member.user as User,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -32,12 +34,13 @@ export function useVoiceParticipantMeta(participant: ParticipantInfo) {
|
||||
return {
|
||||
displayName: dmMember.displayName ?? baseName,
|
||||
avatar: dmMember.avatar ?? null,
|
||||
user: dmMember as User,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Final fallback — parse username from LiveKit identity
|
||||
const { baseName } = parseFederatedUsername(participant.username);
|
||||
return { displayName: baseName, avatar: null };
|
||||
return { displayName: baseName, avatar: null, user: null as User | null };
|
||||
}, [members, dmChannels, participant.userId, participant.username]);
|
||||
}
|
||||
|
||||
@@ -310,6 +310,21 @@ function handleEvent(origin: string, event: ServerEvent): void {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'user_updated': {
|
||||
if (!isHome) normalizeUserAssets(event.user, origin);
|
||||
useSpaceStore.getState().updateUserEverywhere(event.user);
|
||||
useSocialStore.getState().updateFriendProfile(event.user);
|
||||
useChatStore.getState().updateUserInMessages(event.user);
|
||||
// If this is the current user (other tab changed profile), update authStore
|
||||
const myId = isHome
|
||||
? useAuthStore.getState().user?.id
|
||||
: getMyUserIdForOrigin(origin);
|
||||
if (event.user.id === myId && isHome) {
|
||||
setUser(event.user);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'voice_state_update':
|
||||
if (event.action === 'join') {
|
||||
addVoiceUser(event.channelId, event.userId);
|
||||
|
||||
Reference in New Issue
Block a user