diff --git a/web/src/api/types/mxtypes.ts b/web/src/api/types/mxtypes.ts index 8605239..77f036a 100644 --- a/web/src/api/types/mxtypes.ts +++ b/web/src/api/types/mxtypes.ts @@ -111,6 +111,12 @@ export interface ACLEventContent { deny?: string[] } +export interface PolicyRuleContent { + entity: string + reason: string + recommendation: string +} + export interface PowerLevelEventContent { users?: Record users_default?: number diff --git a/web/src/ui/timeline/content/PolicyRuleBody.tsx b/web/src/ui/timeline/content/PolicyRuleBody.tsx new file mode 100644 index 0000000..cd2e577 --- /dev/null +++ b/web/src/ui/timeline/content/PolicyRuleBody.tsx @@ -0,0 +1,28 @@ +import { PolicyRuleContent } from "@/api/types" +import EventContentProps from "./props.ts" + +const BanPolicyBody = ({ event, sender }: EventContentProps) => { + const content = event.content as PolicyRuleContent + const prevContent = event.unsigned.prev_content as PolicyRuleContent | undefined + + if (prevContent !== undefined) { + // all fields for content are missing (this is against spec?) so we need to use the prev event's content + if (content.entity === undefined) { + // unban + return
+ {sender?.content.displayname ?? event.sender} Removed the policy rule banning {prevContent.entity} +
+ } + // update + return
+ {sender?.content.displayname ?? event.sender} Updated a policy rule banning {content.entity} for + {content.reason} +
+ } + // add + return
+ {sender?.content.displayname ?? event.sender} Added a policy rule banning {content.entity} for {content.reason} +
+} + +export default BanPolicyBody diff --git a/web/src/ui/timeline/content/index.ts b/web/src/ui/timeline/content/index.ts index 108d44a..b3c77f7 100644 --- a/web/src/ui/timeline/content/index.ts +++ b/web/src/ui/timeline/content/index.ts @@ -7,6 +7,7 @@ import LocationMessageBody from "./LocationMessageBody.tsx" import MediaMessageBody from "./MediaMessageBody.tsx" import MemberBody from "./MemberBody.tsx" import PinnedEventsBody from "./PinnedEventsBody.tsx" +import PolicyRuleBody from "./PolicyRuleBody.tsx" import PowerLevelBody from "./PowerLevelBody.tsx" import RedactedBody from "./RedactedBody.tsx" import RoomAvatarBody from "./RoomAvatarBody.tsx" @@ -24,6 +25,7 @@ export { default as MediaMessageBody } from "./MediaMessageBody.tsx" export { default as LocationMessageBody } from "./LocationMessageBody.tsx" export { default as MemberBody } from "./MemberBody.tsx" export { default as PinnedEventsBody } from "./PinnedEventsBody.tsx" +export { default as PolicyRuleBody } from "./PolicyRuleBody.tsx" export { default as PowerLevelBody } from "./PowerLevelBody.tsx" export { default as RedactedBody } from "./RedactedBody.tsx" export { default as RoomAvatarBody } from "./RoomAvatarBody.tsx" @@ -82,6 +84,12 @@ export function getBodyType(evt: MemDBEvent, forReply = false): React.FunctionCo return RoomAvatarBody case "m.room.server_acl": return ACLBody + case "m.policy.rule.user": + return PolicyRuleBody + case "m.policy.rule.room": + return PolicyRuleBody + case "m.policy.rule.server": + return PolicyRuleBody case "m.room.pinned_events": return PinnedEventsBody case "m.room.power_levels": @@ -97,6 +105,7 @@ export function isSmallEvent(bodyType: React.FunctionComponent