From 0cf15d27dc9dd427615a9ec7c6733a512fd6ce12 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 14 Feb 2022 23:58:29 +0000 Subject: [PATCH] Fix edge cases around event list summaries with hidden events and redactions (#7797) --- src/components/structures/MessagePanel.tsx | 35 ++++++++----------- .../views/elements/EventListSummary.tsx | 30 ++++++++++++---- src/utils/EventUtils.ts | 1 + 3 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index a9493da532..034297edae 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -681,15 +681,7 @@ export default class MessagePanel extends React.Component { for (const Grouper of groupers) { if (Grouper.canStartGroup(this, mxEv) && !this.props.disableGrouping) { - grouper = new Grouper( - this, - mxEv, - prevEvent, - lastShownEvent, - this.props.layout, - nextEvent, - nextTile, - ); + grouper = new Grouper(this, mxEv, prevEvent, lastShownEvent, nextEvent, nextTile); } } if (!grouper) { @@ -1056,7 +1048,6 @@ abstract class BaseGrouper { public readonly event: MatrixEvent, public readonly prevEvent: MatrixEvent, public readonly lastShownEvent: MatrixEvent, - protected readonly layout: Layout, public readonly nextEvent?: MatrixEvent, public readonly nextEventTile?: MatrixEvent, ) { @@ -1183,7 +1174,7 @@ class CreationGrouper extends BaseGrouper { onToggle={panel.onHeightChanged} // Update scroll state summaryMembers={[ev.sender]} summaryText={summaryText} - layout={this.layout} + layout={this.panel.props.layout} > { eventTiles } , @@ -1226,11 +1217,10 @@ class MainGrouper extends BaseGrouper { public readonly event: MatrixEvent, public readonly prevEvent: MatrixEvent, public readonly lastShownEvent: MatrixEvent, - protected readonly layout: Layout, nextEvent: MatrixEvent, nextEventTile: MatrixEvent, ) { - super(panel, event, prevEvent, lastShownEvent, layout, nextEvent, nextEventTile); + super(panel, event, prevEvent, lastShownEvent, nextEvent, nextEventTile); this.events = [event]; } @@ -1296,15 +1286,18 @@ class MainGrouper extends BaseGrouper { const key = "eventlistsummary-" + (this.prevEvent ? this.events[0].getId() : "initial"); let highlightInSummary = false; - let eventTiles = this.events.map((e) => { + let eventTiles = this.events.map((e, i) => { if (e.getId() === panel.props.highlightedEventId) { highlightInSummary = true; } - // In order to prevent DateSeparators from appearing in the expanded form - // of EventListSummary, render each member event as if the previous - // one was itself. This way, the timestamp of the previous event === the - // timestamp of the current event, and no DateSeparator is inserted. - return panel.getTilesForEvent(e, e, e === lastShownEvent, isGrouped, this.nextEvent, this.nextEventTile); + return panel.getTilesForEvent( + i === 0 ? this.prevEvent : this.events[i - 1], + e, + e === lastShownEvent, + isGrouped, + this.nextEvent, + this.nextEventTile, + ); }).reduce((a, b) => a.concat(b), []); if (eventTiles.length === 0) { @@ -1323,7 +1316,7 @@ class MainGrouper extends BaseGrouper { events={this.events} onToggle={panel.onHeightChanged} // Update scroll state startExpanded={highlightInSummary} - layout={this.layout} + layout={this.panel.props.layout} > { eventTiles } , @@ -1337,7 +1330,7 @@ class MainGrouper extends BaseGrouper { } public getNewPrevEvent(): MatrixEvent { - return this.events[0]; + return this.events[this.events.length - 1]; } } diff --git a/src/components/views/elements/EventListSummary.tsx b/src/components/views/elements/EventListSummary.tsx index d2b9aba3d9..82f1e64a43 100644 --- a/src/components/views/elements/EventListSummary.tsx +++ b/src/components/views/elements/EventListSummary.tsx @@ -31,6 +31,7 @@ import { jsxJoin } from '../../../utils/ReactUtils'; import { Layout } from '../../../settings/enums/Layout'; import RightPanelStore from '../../../stores/right-panel/RightPanelStore'; import AccessibleButton from './AccessibleButton'; +import RoomContext from "../../../contexts/RoomContext"; const onPinnedMessagesClick = (): void => { RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false); @@ -80,6 +81,9 @@ const SEP = ","; @replaceableComponent("views.elements.EventListSummary") export default class EventListSummary extends React.Component { + static contextType = RoomContext; + public context!: React.ContextType; + static defaultProps = { summaryLength: 1, threshold: 3, @@ -477,25 +481,37 @@ export default class EventListSummary extends React.Component { const userEvents: Record = {}; eventsToRender.forEach((e, index) => { const type = e.getType(); - const userId = type === EventType.RoomServerAcl ? e.getSender() : e.getStateKey(); + + let userId = e.getSender(); + if (type === EventType.RoomMember) { + userId = e.getStateKey(); + } else if (e.isRedacted()) { + userId = e.getUnsigned()?.redacted_because?.sender; + } + // Initialise a user's events if (!userEvents[userId]) { userEvents[userId] = []; } - if (e.target && TARGET_AS_DISPLAY_NAME_EVENTS.includes(type as EventType)) { - latestUserAvatarMember.set(userId, e.target); - } else if (e.sender) { - latestUserAvatarMember.set(userId, e.sender); - } - let displayName = userId; if (type === EventType.RoomThirdPartyInvite) { displayName = e.getContent().display_name; + if (e.sender) { + latestUserAvatarMember.set(userId, e.sender); + } + } else if (e.isRedacted()) { + const sender = this.context?.room.getMember(userId); + if (sender) { + displayName = sender.name; + latestUserAvatarMember.set(userId, sender); + } } else if (e.target && TARGET_AS_DISPLAY_NAME_EVENTS.includes(type as EventType)) { displayName = e.target.name; + latestUserAvatarMember.set(userId, e.target); } else if (e.sender) { displayName = e.sender.name; + latestUserAvatarMember.set(userId, e.sender); } userEvents[userId].push({ diff --git a/src/utils/EventUtils.ts b/src/utils/EventUtils.ts index 3e109ed045..5bb07cf1e5 100644 --- a/src/utils/EventUtils.ts +++ b/src/utils/EventUtils.ts @@ -226,6 +226,7 @@ export function getEventDisplayInfo(mxEvent: MatrixEvent, hideEvent?: boolean): !isBubbleMessage && !isLeftAlignedBubbleMessage && eventType !== EventType.RoomMessage && + eventType !== EventType.RoomMessageEncrypted && eventType !== EventType.Sticker && eventType !== EventType.RoomCreate && !M_POLL_START.matches(eventType)