Pillify event permalinks (#10392)

This commit is contained in:
Michael Weimann 2023-03-21 10:23:20 +01:00 committed by GitHub
parent d8acdd1750
commit 96d1b74ffc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 742 additions and 144 deletions

View file

@ -17,6 +17,7 @@ limitations under the License.
import React, { ReactElement, useState } from "react";
import classNames from "classnames";
import { Room } from "matrix-js-sdk/src/models/room";
import { RoomMember } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
@ -24,11 +25,16 @@ import Tooltip, { Alignment } from "../elements/Tooltip";
import { usePermalink } from "../../../hooks/usePermalink";
import RoomAvatar from "../avatars/RoomAvatar";
import MemberAvatar from "../avatars/MemberAvatar";
import { _t } from "../../../languageHandler";
import { Icon as LinkIcon } from "../../../../res/img/element-icons/room/composer/link.svg";
import { Icon as UserIcon } from "../../../../res/img/compound/user.svg";
export enum PillType {
UserMention = "TYPE_USER_MENTION",
RoomMention = "TYPE_ROOM_MENTION",
AtRoomMention = "TYPE_AT_ROOM_MENTION", // '@room' mention
EventInSameRoom = "TYPE_EVENT_IN_SAME_ROOM",
EventInOtherRoom = "TYPE_EVENT_IN_OTHER_ROOM",
}
export const pillRoomNotifPos = (text: string): number => {
@ -39,6 +45,34 @@ export const pillRoomNotifLen = (): number => {
return "@room".length;
};
const PillRoomAvatar: React.FC<{
shouldShowPillAvatar: boolean;
room: Room | null;
}> = ({ shouldShowPillAvatar, room }) => {
if (!shouldShowPillAvatar) {
return null;
}
if (room) {
return <RoomAvatar room={room} width={16} height={16} aria-hidden="true" />;
}
return <LinkIcon className="mx_Pill_LinkIcon mx_BaseAvatar mx_BaseAvatar_image" />;
};
const PillMemberAvatar: React.FC<{
shouldShowPillAvatar: boolean;
member: RoomMember | null;
}> = ({ shouldShowPillAvatar, member }) => {
if (!shouldShowPillAvatar) {
return null;
}
if (member) {
return <MemberAvatar member={member} width={16} height={16} aria-hidden="true" hideTitle />;
}
return <UserIcon className="mx_Pill_UserIcon mx_BaseAvatar mx_BaseAvatar_image" />;
};
export interface PillProps {
// The Type of this Pill. If url is given, this is auto-detected.
type?: PillType;
@ -52,7 +86,7 @@ export interface PillProps {
shouldShowPillAvatar?: boolean;
}
export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room, shouldShowPillAvatar }) => {
export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room, shouldShowPillAvatar = true }) => {
const [hover, setHover] = useState(false);
const { member, onClick, resourceId, targetRoom, text, type } = usePermalink({
room,
@ -70,6 +104,7 @@ export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room
mx_SpacePill: type === "space",
mx_UserPill: type === PillType.UserMention,
mx_UserPill_me: resourceId === MatrixClientPeg.get().getUserId(),
mx_EventPill: type === PillType.EventInOtherRoom || type === PillType.EventInSameRoom,
});
const onMouseOver = (): void => {
@ -81,28 +116,40 @@ export const Pill: React.FC<PillProps> = ({ type: propType, url, inMessage, room
};
const tip = hover && resourceId ? <Tooltip label={resourceId} alignment={Alignment.Right} /> : null;
let avatar: ReactElement | null = null;
let content: (ReactElement | string)[] = [];
const textElement = <span className="mx_Pill_text">{text}</span>;
switch (type) {
case PillType.EventInOtherRoom:
{
const avatar = <PillRoomAvatar shouldShowPillAvatar={shouldShowPillAvatar} room={targetRoom} />;
content = [_t("Message in"), avatar || " ", textElement];
}
break;
case PillType.EventInSameRoom:
{
const avatar = <PillMemberAvatar shouldShowPillAvatar={shouldShowPillAvatar} member={member} />;
content = [_t("Message from"), avatar || " ", textElement];
}
break;
case PillType.AtRoomMention:
case PillType.RoomMention:
case "space":
avatar = targetRoom ? <RoomAvatar room={targetRoom} width={16} height={16} aria-hidden="true" /> : null;
{
const avatar = <PillRoomAvatar shouldShowPillAvatar={shouldShowPillAvatar} room={targetRoom} />;
content = [avatar, textElement];
}
break;
case PillType.UserMention:
avatar = <MemberAvatar member={member} width={16} height={16} aria-hidden="true" hideTitle />;
{
const avatar = <PillMemberAvatar shouldShowPillAvatar={shouldShowPillAvatar} member={member} />;
content = [avatar, textElement];
}
break;
default:
return null;
}
const content = (
<>
{shouldShowPillAvatar && avatar}
<span className="mx_Pill_linkText">{text}</span>
</>
);
return (
<bdi>
<MatrixClientContext.Provider value={MatrixClientPeg.get()}>