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:
@@ -322,7 +322,7 @@ export function PictureInPicture() {
|
||||
[selectedStream, fallbackParticipant],
|
||||
);
|
||||
|
||||
const { displayName: resolvedName, avatar: resolvedAvatar } =
|
||||
const { displayName: resolvedName, avatar: resolvedAvatar, user: resolvedUser } =
|
||||
useVoiceParticipantMeta(displayParticipant ?? EMPTY_PARTICIPANT);
|
||||
|
||||
if (!shouldShow) return null;
|
||||
@@ -370,6 +370,7 @@ export function PictureInPicture() {
|
||||
name={resolvedName}
|
||||
size={64}
|
||||
userId={displayParticipant.homeUserId ?? displayParticipant.userId}
|
||||
user={resolvedUser ?? undefined}
|
||||
/>
|
||||
{speakingParticipantIds.has(displayParticipant.identity) && (
|
||||
<div className="absolute -inset-1 rounded-full ring-2 ring-status-online animate-pulse" />
|
||||
|
||||
@@ -20,7 +20,7 @@ export function StreamTile({ tile, large }: StreamTileProps) {
|
||||
const isLocal = participant.isLocal;
|
||||
const userId = participant.userId;
|
||||
const avatarUserId = participant.homeUserId ?? userId;
|
||||
const { displayName, avatar } = useVoiceParticipantMeta(participant);
|
||||
const { displayName, avatar, user } = useVoiceParticipantMeta(participant);
|
||||
|
||||
const isWatching = watchingStreams.has(userId);
|
||||
|
||||
@@ -110,7 +110,7 @@ export function StreamTile({ tile, large }: StreamTileProps) {
|
||||
) : (
|
||||
<div className="w-full h-full flex flex-col items-center justify-center gap-3 bg-surface-channel">
|
||||
<div className="relative">
|
||||
<Avatar src={avatar} name={displayName} size={large ? 80 : 48} userId={avatarUserId} />
|
||||
<Avatar src={avatar} name={displayName} size={large ? 80 : 48} userId={avatarUserId} user={user ?? undefined} />
|
||||
</div>
|
||||
<div className="text-center px-4">
|
||||
<p className="text-txt-primary text-sm font-semibold">
|
||||
|
||||
@@ -113,6 +113,7 @@ export function VoiceChannel({ channelId, channelName, onClick, locked }: VoiceC
|
||||
size={24}
|
||||
status={status}
|
||||
userId={member?.user.homeUserId ?? userId}
|
||||
user={member?.user}
|
||||
/>
|
||||
<span className="text-[13px] text-txt-secondary truncate flex-1 min-w-0">{displayName}</span>
|
||||
{/* Status badges */}
|
||||
|
||||
@@ -29,7 +29,7 @@ export function VoiceUser({ tile, large }: VoiceUserProps) {
|
||||
|
||||
const isLocal = participant.isLocal;
|
||||
const avatarUserId = participant.homeUserId ?? participant.userId;
|
||||
const { displayName, avatar } = useVoiceParticipantMeta(participant);
|
||||
const { displayName, avatar, user } = useVoiceParticipantMeta(participant);
|
||||
|
||||
// --- VIDEO & UI ---
|
||||
|
||||
@@ -98,6 +98,7 @@ export function VoiceUser({ tile, large }: VoiceUserProps) {
|
||||
name={displayName}
|
||||
size={large ? 100 : 64}
|
||||
userId={avatarUserId}
|
||||
user={user ?? undefined}
|
||||
/>
|
||||
{isSpeaking && (
|
||||
<div className="absolute -inset-1.5 rounded-full ring-[3px] ring-status-online animate-pulse" />
|
||||
|
||||
Reference in New Issue
Block a user