Files
cinny/src/app/hooks/useMemberAvatar.ts
T

57 lines
1.8 KiB
TypeScript
Raw Normal View History

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 };
};