57 lines
1.8 KiB
TypeScript
57 lines
1.8 KiB
TypeScript
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 };
|
||
|
|
};
|