DP18: add useMemberAvatar hook and adopt it in reader avatars
Add a reactive `useMemberAvatar(room, userId, w?, h?, resize?)` hook
returning { name, avatarUrl }, standardizing the member name + avatar
trio and the RoomStateEvent.Members reactivity pattern (N6). Convert
ReadReceiptAvatars and EventReaders to render per-user avatars via a
small child component using the hook, preserving exact sizes, fallback
rendering, TDS pill/tooltip styling and behavior.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Room, RoomStateEvent, RoomStateEventHandlerMap } from 'matrix-js-sdk';
|
||||
import { useMatrixClient } from './useMatrixClient';
|
||||
import { useMediaAuthentication } from './useMediaAuthentication';
|
||||
import { useForceUpdate } from './useForceUpdate';
|
||||
import { getMemberName } from '../utils/room';
|
||||
import { mxcUrlToHttp } from '../utils/matrix';
|
||||
|
||||
export type MemberAvatar = {
|
||||
name: string;
|
||||
avatarUrl: string | undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve a room member's display name and avatar http url, staying reactive to
|
||||
* that member's profile (name/avatar/membership) changes.
|
||||
*
|
||||
* Mirrors the reactivity pattern in ReadReceiptAvatars (N6): subscribe to
|
||||
* `RoomStateEvent.Members` filtered to this room + userId and force a re-render,
|
||||
* since `RoomMemberEvent` has no dedicated Avatar signal.
|
||||
*/
|
||||
export const useMemberAvatar = (
|
||||
room: Room,
|
||||
userId: string,
|
||||
width = 32,
|
||||
height = 32,
|
||||
resizeMethod = 'crop',
|
||||
): MemberAvatar => {
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const [, forceUpdate] = useForceUpdate();
|
||||
|
||||
useEffect(() => {
|
||||
const handleMembers: RoomStateEventHandlerMap[RoomStateEvent.Members] = (
|
||||
event,
|
||||
_state,
|
||||
member,
|
||||
) => {
|
||||
if (event.getRoomId() === room.roomId && member.userId === userId) {
|
||||
forceUpdate();
|
||||
}
|
||||
};
|
||||
mx.on(RoomStateEvent.Members, handleMembers);
|
||||
return () => {
|
||||
mx.removeListener(RoomStateEvent.Members, handleMembers);
|
||||
};
|
||||
}, [mx, room.roomId, userId, forceUpdate]);
|
||||
|
||||
const name = getMemberName(room, userId);
|
||||
const avatarMxc = room.getMember(userId)?.getMxcAvatarUrl();
|
||||
const avatarUrl = avatarMxc
|
||||
? (mxcUrlToHttp(mx, avatarMxc, useAuthentication, width, height, resizeMethod) ?? undefined)
|
||||
: undefined;
|
||||
|
||||
return { name, avatarUrl };
|
||||
};
|
||||
Reference in New Issue
Block a user