From de20188f08499919c2edb0dae92354bba8a61c60 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Fri, 10 Mar 2023 16:11:56 +0000 Subject: [PATCH] Cache more calls to shouldShowEvent --- src/components/structures/MessagePanel.tsx | 96 ++++++++++++---------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/src/components/structures/MessagePanel.tsx b/src/components/structures/MessagePanel.tsx index f2b57c89e7f7..cd023706ca57 100644 --- a/src/components/structures/MessagePanel.tsx +++ b/src/components/structures/MessagePanel.tsx @@ -578,10 +578,10 @@ export default class MessagePanel extends React.Component { private getNextEventInfo( events: EventAndShouldShow[], i: number, - ): { nextEvent: MatrixEvent | null; nextTile: MatrixEvent | null } { + ): { nextEvent: EventAndShouldShow | null; nextTile: MatrixEvent | null } { // WARNING: this method is on a hot path. - const nextEvent = i < events.length - 1 ? events[i + 1].event : null; + const nextEvent = i < events.length - 1 ? events[i + 1] : null; const nextTile = findFirstShownAfter(i, events); @@ -647,14 +647,15 @@ export default class MessagePanel extends React.Component { let grouper: BaseGrouper | null = null; for (let i = 0; i < events.length; i++) { - const { event, shouldShow } = events[i]; + const ev = events[i]; + const { event, shouldShow } = ev; const eventId = event.getId(); const last = event === lastShownEvent; const { nextEvent, nextTile } = this.getNextEventInfo(events, i); if (grouper) { - if (grouper.shouldGroup(event)) { - grouper.add(event); + if (grouper.shouldGroup(ev)) { + grouper.add(ev); continue; } else { // not part of group, so get the group tiles, close the @@ -666,8 +667,8 @@ export default class MessagePanel extends React.Component { } for (const Grouper of groupers) { - if (Grouper.canStartGroup(this, event) && !this.props.disableGrouping) { - grouper = new Grouper(this, event, prevEvent, lastShownEvent, nextEvent, nextTile); + if (Grouper.canStartGroup(this, ev) && !this.props.disableGrouping) { + grouper = new Grouper(this, ev, prevEvent, lastShownEvent, nextEvent, nextTile); break; // break on first grouper } } @@ -698,7 +699,7 @@ export default class MessagePanel extends React.Component { mxEv: MatrixEvent, last = false, isGrouped = false, - nextEvent?: MatrixEvent, + nextEvent?: EventAndShouldShow, nextEventWithTile?: MatrixEvent, ): ReactNode[] { const ret: ReactNode[] = []; @@ -747,10 +748,10 @@ export default class MessagePanel extends React.Component { let isLastSuccessful = false; const isSentState = (s: EventStatus): boolean => !s || s === EventStatus.SENT; const isSent = isSentState(mxEv.getAssociatedStatus()); - const hasNextEvent = nextEvent && this.shouldShowEvent(nextEvent); + const hasNextEvent = nextEvent?.shouldShow; if (!hasNextEvent && isSent) { isLastSuccessful = true; - } else if (hasNextEvent && isSent && !isSentState(nextEvent.getAssociatedStatus())) { + } else if (hasNextEvent && isSent && !isSentState(nextEvent.event.getAssociatedStatus())) { isLastSuccessful = true; } @@ -758,7 +759,7 @@ export default class MessagePanel extends React.Component { // hidden then we're not the last successful. if ( nextEventWithTile && - nextEventWithTile !== nextEvent && + nextEventWithTile !== nextEvent?.event && isSentState(nextEventWithTile.getAssociatedStatus()) ) { isLastSuccessful = false; @@ -1065,7 +1066,7 @@ interface EventAndShouldShow { } abstract class BaseGrouper { - public static canStartGroup = (panel: MessagePanel, ev: MatrixEvent): boolean => true; + public static canStartGroup = (panel: MessagePanel, ev: EventAndShouldShow): boolean => true; public events: MatrixEvent[] = []; // events that we include in the group but then eject out and place above the group. @@ -1074,17 +1075,17 @@ abstract class BaseGrouper { public constructor( public readonly panel: MessagePanel, - public readonly event: MatrixEvent, + public readonly event: EventAndShouldShow, public readonly prevEvent: MatrixEvent | null, public readonly lastShownEvent: MatrixEvent, - public readonly nextEvent?: MatrixEvent, + public readonly nextEvent?: EventAndShouldShow, public readonly nextEventTile?: MatrixEvent, ) { - this.readMarker = panel.readMarkerForEvent(event.getId(), event === lastShownEvent); + this.readMarker = panel.readMarkerForEvent(event.event.getId(), event.event === lastShownEvent); } - public abstract shouldGroup(ev: MatrixEvent): boolean; - public abstract add(ev: MatrixEvent): void; + public abstract shouldGroup(ev: EventAndShouldShow): boolean; + public abstract add(ev: EventAndShouldShow): void; public abstract getTiles(): ReactNode[]; public abstract getNewPrevEvent(): MatrixEvent; } @@ -1105,28 +1106,30 @@ abstract class BaseGrouper { // Grouping only events sent by the same user that sent the `m.room.create` and only until // the first non-state event, beacon_info event or membership event which is not regarding the sender of the `m.room.create` event class CreationGrouper extends BaseGrouper { - public static canStartGroup = function (panel: MessagePanel, ev: MatrixEvent): boolean { + public static canStartGroup = function ( + panel: MessagePanel, + { event: ev, shouldShow }: EventAndShouldShow, + ): boolean { return ev.getType() === EventType.RoomCreate; }; - public shouldGroup(ev: MatrixEvent): boolean { + public shouldGroup({ event: ev, shouldShow }: EventAndShouldShow): boolean { const panel = this.panel; const createEvent = this.event; - if (!panel.shouldShowEvent(ev)) { + if (!shouldShow) { return true; } - if (panel.wantsDateSeparator(this.event, ev.getDate())) { + if (panel.wantsDateSeparator(this.event.event, ev.getDate())) { return false; } + const eventType = ev.getType(); if ( - ev.getType() === EventType.RoomMember && - (ev.getStateKey() !== createEvent.getSender() || ev.getContent()["membership"] !== "join") + eventType === EventType.RoomMember && + (ev.getStateKey() !== createEvent.event.getSender() || ev.getContent()["membership"] !== "join") ) { return false; } - const eventType = ev.getType(); - // beacons are not part of room creation configuration // should be shown in timeline if (M_BEACON_INFO.matches(eventType)) { @@ -1138,17 +1141,17 @@ class CreationGrouper extends BaseGrouper { return false; } - if (ev.isState() && ev.getSender() === createEvent.getSender()) { + if (ev.isState() && ev.getSender() === createEvent.event.getSender()) { return true; } return false; } - public add(ev: MatrixEvent): void { + public add({ event: ev, shouldShow }: EventAndShouldShow): void { const panel = this.panel; this.readMarker = this.readMarker || panel.readMarkerForEvent(ev.getId(), ev === this.lastShownEvent); - if (!panel.shouldShowEvent(ev)) { + if (!shouldShow) { return; } if (ev.getType() === EventType.RoomEncryption) { @@ -1170,23 +1173,25 @@ class CreationGrouper extends BaseGrouper { const createEvent = this.event; const lastShownEvent = this.lastShownEvent; - if (panel.wantsDateSeparator(this.prevEvent, createEvent.getDate())) { - const ts = createEvent.getTs(); + if (panel.wantsDateSeparator(this.prevEvent, createEvent.event.getDate())) { + const ts = createEvent.event.getTs(); ret.push(
  • - +
  • , ); } // If this m.room.create event should be shown (room upgrade) then show it before the summary - if (panel.shouldShowEvent(createEvent)) { + if (createEvent.shouldShow) { // pass in the createEvent as prevEvent as well so no extra DateSeparator is rendered - ret.push(...panel.getTilesForEvent(createEvent, createEvent)); + ret.push(...panel.getTilesForEvent(createEvent.event, createEvent.event)); } for (const ejected of this.ejectedEvents) { - ret.push(...panel.getTilesForEvent(createEvent, ejected, createEvent === lastShownEvent, isGrouped)); + ret.push( + ...panel.getTilesForEvent(createEvent.event, ejected, createEvent.event === lastShownEvent, isGrouped), + ); } const eventTiles = this.events @@ -1233,14 +1238,17 @@ class CreationGrouper extends BaseGrouper { } public getNewPrevEvent(): MatrixEvent { - return this.event; + return this.event.event; } } // Wrap consecutive grouped events in a ListSummary class MainGrouper extends BaseGrouper { - public static canStartGroup = function (panel: MessagePanel, ev: MatrixEvent): boolean { - if (!panel.shouldShowEvent(ev)) return false; + public static canStartGroup = function ( + panel: MessagePanel, + { event: ev, shouldShow }: EventAndShouldShow, + ): boolean { + if (!shouldShow) return false; if (ev.isState() && groupedStateEvents.includes(ev.getType() as EventType)) { return true; @@ -1259,18 +1267,18 @@ class MainGrouper extends BaseGrouper { public constructor( public readonly panel: MessagePanel, - public readonly event: MatrixEvent, + public readonly event: EventAndShouldShow, public readonly prevEvent: MatrixEvent | null, public readonly lastShownEvent: MatrixEvent, - nextEvent: MatrixEvent, + nextEvent: EventAndShouldShow, nextEventTile: MatrixEvent, ) { super(panel, event, prevEvent, lastShownEvent, nextEvent, nextEventTile); - this.events = [event]; + this.events = [event.event]; } - public shouldGroup(ev: MatrixEvent): boolean { - if (!this.panel.shouldShowEvent(ev)) { + public shouldGroup({ event: ev, shouldShow }: EventAndShouldShow): boolean { + if (!shouldShow) { // absorb hidden events so that they do not break up streams of messages & redaction events being grouped return true; } @@ -1289,13 +1297,13 @@ class MainGrouper extends BaseGrouper { return false; } - public add(ev: MatrixEvent): void { + public add({ event: ev, shouldShow }: EventAndShouldShow): void { if (ev.getType() === EventType.RoomMember) { // We can ignore any events that don't actually have a message to display if (!hasText(ev, this.panel.showHiddenEvents)) return; } this.readMarker = this.readMarker || this.panel.readMarkerForEvent(ev.getId(), ev === this.lastShownEvent); - if (!this.panel.showHiddenEvents && !this.panel.shouldShowEvent(ev)) { + if (!this.panel.showHiddenEvents && !shouldShow) { // absorb hidden events to not split the summary return; }