@@ -561,14 +561,38 @@ export default class MessagePanel extends React.Component<IProps, IState> {
561561 } ) ;
562562 } ;
563563
564- private getNextEventInfo ( arr : MatrixEvent [ ] , i : number ) : { nextEvent : MatrixEvent ; nextTile : MatrixEvent } {
564+ /**
565+ * Find the next event in the list, and the next visible event in the list.
566+ *
567+ * @param arr - the list of events to look in
568+ * @param shouldShow - which of these events should be shown (a cache of
569+ * calling this.shouldShowEvent(e) for each e in arr)
570+ * @param i - where in the list we are now
571+ *
572+ * @returns { nextEvent, nextTile }
573+ *
574+ * nextEvent is the last event in the supplied array.
575+ *
576+ * nextTile is the last event in the array that we will show a tile for. It
577+ * is used to to determine the 'last successful' flag when rendering the
578+ * tile.
579+ */
580+ private getNextEventInfo (
581+ arr : MatrixEvent [ ] ,
582+ shouldShow : boolean [ ] ,
583+ i : number ,
584+ ) : { nextEvent : MatrixEvent ; nextTile : MatrixEvent } {
585+ // WARNING: this method is on a hot path.
586+
565587 const nextEvent = i < arr . length - 1 ? arr [ i + 1 ] : null ;
566588
567- // The next event with tile is used to to determine the 'last successful' flag
568- // when rendering the tile. The shouldShowEvent function is pretty quick at what
569- // it does, so this should have no significant cost even when a room is used for
570- // not-chat purposes.
571- const nextTile = arr . slice ( i + 1 ) . find ( ( e ) => this . shouldShowEvent ( e ) ) ;
589+ let nextTile = null ;
590+ for ( let n = i + 1 ; n < arr . length ; n ++ ) {
591+ if ( shouldShow [ n ] ) {
592+ nextTile = arr [ n ] ;
593+ break ;
594+ }
595+ }
572596
573597 return { nextEvent, nextTile } ;
574598 }
@@ -587,22 +611,21 @@ export default class MessagePanel extends React.Component<IProps, IState> {
587611 }
588612
589613 private getEventTiles ( ) : ReactNode [ ] {
590- let i ;
591-
592614 // first figure out which is the last event in the list which we're
593615 // actually going to show; this allows us to behave slightly
594616 // differently for the last event in the list. (eg show timestamp)
595617 //
596618 // we also need to figure out which is the last event we show which isn't
597619 // a local echo, to manage the read-marker.
598- let lastShownEvent ;
620+ let lastShownEvent : MatrixEvent | undefined ;
621+ const shouldShow = this . props . events . map ( ( e ) => this . shouldShowEvent ( e ) ) ;
599622
600623 let lastShownNonLocalEchoIndex = - 1 ;
601- for ( i = this . props . events . length - 1 ; i >= 0 ; i -- ) {
602- const mxEv = this . props . events [ i ] ;
603- if ( ! this . shouldShowEvent ( mxEv ) ) {
624+ for ( let i = this . props . events . length - 1 ; i >= 0 ; i -- ) {
625+ if ( ! shouldShow [ i ] ) {
604626 continue ;
605627 }
628+ const mxEv = this . props . events [ i ] ;
606629
607630 if ( lastShownEvent === undefined ) {
608631 lastShownEvent = mxEv ;
@@ -631,11 +654,12 @@ export default class MessagePanel extends React.Component<IProps, IState> {
631654
632655 let grouper : BaseGrouper = null ;
633656
634- for ( i = 0 ; i < this . props . events . length ; i ++ ) {
657+ for ( let i = 0 ; i < this . props . events . length ; i ++ ) {
635658 const mxEv = this . props . events [ i ] ;
659+ const shouldShowEv = shouldShow [ i ] ;
636660 const eventId = mxEv . getId ( ) ;
637661 const last = mxEv === lastShownEvent ;
638- const { nextEvent, nextTile } = this . getNextEventInfo ( this . props . events , i ) ;
662+ const { nextEvent, nextTile } = this . getNextEventInfo ( this . props . events , shouldShow , i ) ;
639663
640664 if ( grouper ) {
641665 if ( grouper . shouldGroup ( mxEv ) ) {
@@ -658,7 +682,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
658682 }
659683
660684 if ( ! grouper ) {
661- if ( this . shouldShowEvent ( mxEv ) ) {
685+ if ( shouldShowEv ) {
662686 // make sure we unpack the array returned by getTilesForEvent,
663687 // otherwise React will auto-generate keys, and we will end up
664688 // replacing all the DOM elements every time we paginate.
0 commit comments