From a11193e24301d52909937490306ed3c3fade9151 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Mon, 28 Jun 2021 12:32:38 -0400 Subject: [PATCH] Group ACLs with MELS Signed-off-by: Robin Townsend --- src/components/structures/MessagePanel.js | 7 +++---- .../views/elements/MemberEventListSummary.tsx | 19 +++++++++++++++++-- src/i18n/strings/en_EN.json | 4 ++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/components/structures/MessagePanel.js b/src/components/structures/MessagePanel.js index eb9611a6fc..49855eb99c 100644 --- a/src/components/structures/MessagePanel.js +++ b/src/components/structures/MessagePanel.js @@ -38,6 +38,7 @@ import defaultDispatcher from '../../dispatcher/dispatcher'; const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const continuedTypes = ['m.sticker', 'm.room.message']; +const membershipTypes = ['m.room.member', 'm.room.third_party_invite', 'm.room.server_acl']; // check if there is a previous event and it has the same sender as this event // and the types are the same/is in continuedTypes and the time between them is <= CONTINUATION_MAX_INTERVAL @@ -66,8 +67,6 @@ function shouldFormContinuation(prevEvent, mxEvent) { return true; } -const isMembershipChange = (e) => e.getType() === 'm.room.member' || e.getType() === 'm.room.third_party_invite'; - /* (almost) stateless UI component which builds the event tiles in the room timeline. */ @replaceableComponent("structures.MessagePanel") @@ -1144,7 +1143,7 @@ class RedactionGrouper { // Wrap consecutive member events in a ListSummary, ignore if redacted class MemberGrouper { static canStartGroup = function(panel, ev) { - return panel._shouldShowEvent(ev) && isMembershipChange(ev); + return panel._shouldShowEvent(ev) && membershipTypes.includes(ev.getType()); } constructor(panel, ev, prevEvent, lastShownEvent) { @@ -1162,7 +1161,7 @@ class MemberGrouper { if (this.panel._wantsDateSeparator(this.events[0], ev.getDate())) { return false; } - return isMembershipChange(ev); + return membershipTypes.includes(ev.getType()); } add(ev) { diff --git a/src/components/views/elements/MemberEventListSummary.tsx b/src/components/views/elements/MemberEventListSummary.tsx index f10884ce9d..bf85cee60e 100644 --- a/src/components/views/elements/MemberEventListSummary.tsx +++ b/src/components/views/elements/MemberEventListSummary.tsx @@ -66,6 +66,7 @@ enum TransitionType { ChangedName = "changed_name", ChangedAvatar = "changed_avatar", NoChange = "no_change", + ServerAcl = "server_acl", } const SEP = ","; @@ -298,6 +299,12 @@ export default class MemberEventListSummary extends React.Component { ? _t("%(severalUsers)smade no changes %(count)s times", { severalUsers: "", count: repeats }) : _t("%(oneUser)smade no changes %(count)s times", { oneUser: "", count: repeats }); break; + case "server_acl": + res = (userCount > 1) + ? _t("%(severalUsers)schanged the server ACLs %(count)s times", + { severalUsers: "", count: repeats }) + : _t("%(oneUser)schanged the server ACLs %(count)s times", { oneUser: "", count: repeats }); + break; } return res; @@ -324,6 +331,10 @@ export default class MemberEventListSummary extends React.Component { return TransitionType.Invited; } + if (e.mxEvent.getType() === 'm.room.server_acl') { + return TransitionType.ServerAcl; + } + switch (e.mxEvent.getContent().membership) { case 'invite': return TransitionType.Invited; case 'ban': return TransitionType.Banned; @@ -410,19 +421,23 @@ export default class MemberEventListSummary extends React.Component { // Object mapping user IDs to an array of IUserEvents const userEvents: Record = {}; eventsToRender.forEach((e, index) => { - const userId = e.getStateKey(); + const userId = e.getType() === 'm.room.server_acl' ? e.getSender() : e.getStateKey(); // Initialise a user's events if (!userEvents[userId]) { userEvents[userId] = []; } - if (e.target) { + if (e.getType() === 'm.room.server_acl') { + latestUserAvatarMember.set(userId, e.sender); + } else if (e.target) { latestUserAvatarMember.set(userId, e.target); } let displayName = userId; if (e.getType() === 'm.room.third_party_invite') { displayName = e.getContent().display_name; + } else if (e.getType() === 'm.room.server_acl') { + displayName = e.sender.name; } else if (e.target) { displayName = e.target.name; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bfca730776..d8e7c030d5 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2050,6 +2050,10 @@ "%(severalUsers)smade no changes %(count)s times|one": "%(severalUsers)smade no changes", "%(oneUser)smade no changes %(count)s times|other": "%(oneUser)smade no changes %(count)s times", "%(oneUser)smade no changes %(count)s times|one": "%(oneUser)smade no changes", + "%(severalUsers)schanged the server ACLs %(count)s times|other": "%(severalUsers)schanged the server ACLs %(count)s times", + "%(severalUsers)schanged the server ACLs %(count)s times|one": "%(severalUsers)schanged the server ACLs", + "%(oneUser)schanged the server ACLs %(count)s times|other": "%(oneUser)schanged the server ACLs %(count)s times", + "%(oneUser)schanged the server ACLs %(count)s times|one": "%(oneUser)schanged the server ACLs", "Power level": "Power level", "Custom level": "Custom level", "QR Code": "QR Code",