cinny/src/app/hooks/useMemberEventParser.tsx
Ajay Bura 8e4475bb56
fix crash on membership change with invalid data (#2182)
* fix membership change with  invalid data crash

* add more checks around membership change

* fix displayname condition
2025-01-26 22:53:16 +11:00

228 lines
5.8 KiB
TypeScript

import React, { ReactNode } from 'react';
import { IconSrc, Icons } from 'folds';
import { MatrixEvent } from 'matrix-js-sdk';
import { IMemberContent, Membership } from '../../types/matrix/room';
import { getMxIdLocalPart } from '../utils/matrix';
import { isMembershipChanged } from '../utils/room';
export type ParsedResult = {
icon: IconSrc;
body: ReactNode;
};
export type MemberEventParser = (mEvent: MatrixEvent) => ParsedResult;
export const useMemberEventParser = (): MemberEventParser => {
const parseMemberEvent: MemberEventParser = (mEvent) => {
const content = mEvent.getContent<IMemberContent>();
const prevContent = mEvent.getPrevContent() as IMemberContent;
const senderId = mEvent.getSender();
const userId = mEvent.getStateKey();
const reason = typeof content.reason === 'string' ? content.reason : undefined;
if (!senderId || !userId)
return {
icon: Icons.User,
body: 'Broken membership event',
};
const senderName = getMxIdLocalPart(senderId);
const userName =
typeof content.displayname === 'string'
? content.displayname || getMxIdLocalPart(userId)
: getMxIdLocalPart(userId);
if (isMembershipChanged(mEvent)) {
if (content.membership === Membership.Invite) {
if (prevContent.membership === Membership.Knock) {
return {
icon: Icons.ArrowGoRightPlus,
body: (
<>
<b>{senderName}</b>
{' accepted '}
<b>{userName}</b>
{`'s join request `}
{reason}
</>
),
};
}
return {
icon: Icons.ArrowGoRightPlus,
body: (
<>
<b>{senderName}</b>
{' invited '}
<b>{userName}</b> {reason}
</>
),
};
}
if (content.membership === Membership.Knock) {
return {
icon: Icons.ArrowGoRightPlus,
body: (
<>
<b>{userName}</b>
{' request to join room '}
{reason}
</>
),
};
}
if (content.membership === Membership.Join) {
return {
icon: Icons.ArrowGoRight,
body: (
<>
<b>{userName}</b>
{' joined the room'}
</>
),
};
}
if (content.membership === Membership.Leave) {
if (prevContent.membership === Membership.Invite) {
return {
icon: Icons.ArrowGoRightCross,
body:
senderId === userId ? (
<>
<b>{userName}</b>
{' rejected the invitation '}
{reason}
</>
) : (
<>
<b>{senderName}</b>
{' rejected '}
<b>{userName}</b>
{`'s join request `}
{reason}
</>
),
};
}
if (prevContent.membership === Membership.Knock) {
return {
icon: Icons.ArrowGoRightCross,
body:
senderId === userId ? (
<>
<b>{userName}</b>
{' revoked joined request '}
{reason}
</>
) : (
<>
<b>{senderName}</b>
{' revoked '}
<b>{userName}</b>
{`'s invite `}
{reason}
</>
),
};
}
if (prevContent.membership === Membership.Ban) {
return {
icon: Icons.ArrowGoLeft,
body: (
<>
<b>{senderName}</b>
{' unbanned '}
<b>{userName}</b> {reason}
</>
),
};
}
return {
icon: Icons.ArrowGoLeft,
body:
senderId === userId ? (
<>
<b>{userName}</b>
{' left the room '}
{reason}
</>
) : (
<>
<b>{senderName}</b>
{' kicked '}
<b>{userName}</b> {reason}
</>
),
};
}
if (content.membership === Membership.Ban) {
return {
icon: Icons.ArrowGoLeft,
body: (
<>
<b>{senderName}</b>
{' banned '}
<b>{userName}</b> {reason}
</>
),
};
}
}
if (content.displayname !== prevContent.displayname) {
const prevUserName =
typeof prevContent.displayname === 'string'
? prevContent.displayname || getMxIdLocalPart(userId)
: getMxIdLocalPart(userId);
return {
icon: Icons.Mention,
body:
typeof content.displayname === 'string' ? (
<>
<b>{prevUserName}</b>
{' changed display name to '}
<b>{userName}</b>
</>
) : (
<>
<b>{prevUserName}</b>
{' removed their display name '}
</>
),
};
}
if (content.avatar_url !== prevContent.avatar_url) {
return {
icon: Icons.User,
body:
content.avatar_url && typeof content.avatar_url === 'string' ? (
<>
<b>{userName}</b>
{' changed their avatar'}
</>
) : (
<>
<b>{userName}</b>
{' removed their avatar '}
</>
),
};
}
return {
icon: Icons.User,
body: 'Membership event with no changes',
};
};
return parseMemberEvent;
};