Compare commits

...

1 Commits

Author SHA1 Message Date
Half-Shot
0f16ac7589 Add module APIs for rendering the information on the user's profile. 2025-09-01 07:56:47 +01:00
3 changed files with 72 additions and 19 deletions

View File

@@ -12,7 +12,9 @@ import { type MatrixEvent, MsgType } from "matrix-js-sdk/src/matrix";
import DisambiguatedProfile from "./DisambiguatedProfile"; import DisambiguatedProfile from "./DisambiguatedProfile";
import { useRoomMemberProfile } from "../../../hooks/room/useRoomMemberProfile"; import { useRoomMemberProfile } from "../../../hooks/room/useRoomMemberProfile";
import ModuleApi from "../../../modules/Api";
import { CustomComponentsApi } from "../../../modules/customComponentApi";
import { MessageProfileComponentProps } from "@element-hq/element-web-module-api";
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
onClick?(): void; onClick?(): void;
@@ -25,16 +27,24 @@ export default function SenderProfile({ mxEvent, onClick, withTooltip }: IProps)
member: mxEvent.sender, member: mxEvent.sender,
}); });
return mxEvent.getContent().msgtype !== MsgType.Emote ? ( if (mxEvent.getContent().msgtype === MsgType.Emote) {
<DisambiguatedProfile return <></>;
fallbackName={mxEvent.getSender() ?? ""} }
onClick={onClick} const moduleRenderer = ModuleApi.customComponents.messageProfileRenderer;
member={member} const renderFn = (moduleProps: MessageProfileComponentProps) => <DisambiguatedProfile
fallbackName={moduleProps.mxEvent.sender ?? ""}
onClick={moduleProps.onClick}
member={moduleProps.member}
colored={true} colored={true}
emphasizeDisplayName={true} emphasizeDisplayName={true}
withTooltip={withTooltip} withTooltip={withTooltip}
/> />;
) : (
<></> const modProps = {
); onClick,
mxEvent: CustomComponentsApi.getModuleMatrixEvent(mxEvent)!,
member: member || undefined,
};
return moduleRenderer ? moduleRenderer(modProps, renderFn) : renderFn(modProps);
} }

View File

@@ -16,6 +16,7 @@ import { Flex } from "../../../../shared-components/utils/Flex";
import PresenceLabel from "../../rooms/PresenceLabel"; import PresenceLabel from "../../rooms/PresenceLabel";
import CopyableText from "../../elements/CopyableText"; import CopyableText from "../../elements/CopyableText";
import { UserInfoHeaderVerificationView } from "./UserInfoHeaderVerificationView"; import { UserInfoHeaderVerificationView } from "./UserInfoHeaderVerificationView";
import ModuleApi from "../../../../modules/Api";
export interface UserInfoHeaderViewProps { export interface UserInfoHeaderViewProps {
member: Member; member: Member;
@@ -48,6 +49,27 @@ export const UserInfoHeaderView: React.FC<UserInfoHeaderViewProps> = ({
); );
} }
const moduleRenderer = ModuleApi.customComponents.userInfoRenderer;
let usernameSection;
if (moduleRenderer && vm.userIdentifier) {
usernameSection = moduleRenderer(
{
userId: vm.userIdentifier,
},
(props) => <Text size="sm" weight="semibold" className="mx_UserInfo_profile_mxid">
<CopyableText getTextToCopy={() => props.userId} border={false}>
{props.userId}
</CopyableText>
</Text>,
);
} else {
usernameSection = <Text size="sm" weight="semibold" className="mx_UserInfo_profile_mxid">
<CopyableText getTextToCopy={() => vm.userIdentifier} border={false}>
{vm.userIdentifier}
</CopyableText>
</Text>;
}
return ( return (
<React.Fragment> <React.Fragment>
<div className="mx_UserInfo_avatar"> <div className="mx_UserInfo_avatar">
@@ -83,11 +105,7 @@ export const UserInfoHeaderView: React.FC<UserInfoHeaderViewProps> = ({
</Flex> </Flex>
</Tooltip> </Tooltip>
)} )}
<Text size="sm" weight="semibold" className="mx_UserInfo_profile_mxid"> {usernameSection}
<CopyableText getTextToCopy={() => vm.userIdentifier} border={false}>
{vm.userIdentifier}
</CopyableText>
</Text>
</Flex> </Flex>
{!hideVerificationSection && <UserInfoHeaderVerificationView member={member} devices={devices} />} {!hideVerificationSection && <UserInfoHeaderVerificationView member={member} devices={devices} />}
</Container> </Container>

View File

@@ -16,6 +16,8 @@ import type {
CustomMessageRenderHints as ModuleCustomCustomMessageRenderHints, CustomMessageRenderHints as ModuleCustomCustomMessageRenderHints,
MatrixEvent as ModuleMatrixEvent, MatrixEvent as ModuleMatrixEvent,
CustomRoomPreviewBarRenderFunction, CustomRoomPreviewBarRenderFunction,
MessageProfileRenderFunction,
UserInfoRenderFunction,
} from "@element-hq/element-web-module-api"; } from "@element-hq/element-web-module-api";
import type React from "react"; import type React from "react";
@@ -42,7 +44,7 @@ export class CustomComponentsApi implements ICustomComponentsApi {
* @param mxEvent * @param mxEvent
* @returns An event object, or `null` if the event was not a message event. * @returns An event object, or `null` if the event was not a message event.
*/ */
private static getModuleMatrixEvent(mxEvent: MatrixEvent): ModuleMatrixEvent | null { public static getModuleMatrixEvent(mxEvent: MatrixEvent): ModuleMatrixEvent | null {
const eventId = mxEvent.getId(); const eventId = mxEvent.getId();
const roomId = mxEvent.getRoomId(); const roomId = mxEvent.getRoomId();
const sender = mxEvent.sender; const sender = mxEvent.sender;
@@ -138,6 +140,8 @@ export class CustomComponentsApi implements ICustomComponentsApi {
} }
private _roomPreviewBarRenderer?: CustomRoomPreviewBarRenderFunction; private _roomPreviewBarRenderer?: CustomRoomPreviewBarRenderFunction;
private _userInfoRenderer?: UserInfoRenderFunction;
private _messageProfileRenderer?: MessageProfileRenderFunction;
/** /**
* Get the custom room preview bar renderer, if any has been registered. * Get the custom room preview bar renderer, if any has been registered.
@@ -153,4 +157,25 @@ export class CustomComponentsApi implements ICustomComponentsApi {
public registerRoomPreviewBar(renderer: CustomRoomPreviewBarRenderFunction): void { public registerRoomPreviewBar(renderer: CustomRoomPreviewBarRenderFunction): void {
this._roomPreviewBarRenderer = renderer; this._roomPreviewBarRenderer = renderer;
} }
/**
* Get the custom user info renderer, if any has been registered.
*/
public get messageProfileRenderer(): MessageProfileRenderFunction | undefined {
return this._messageProfileRenderer;
}
public registerMessageProfile(renderer: MessageProfileRenderFunction): void {
this._messageProfileRenderer = renderer;
}
/**
* Get the custom user info renderer, if any has been registered.
*/
public get userInfoRenderer(): UserInfoRenderFunction | undefined {
return this._userInfoRenderer;
}
public registerUserInfo(renderer: UserInfoRenderFunction): void {
this._userInfoRenderer = renderer;
}
} }