@@ -564,35 +564,26 @@ export default class MessagePanel extends React.Component<IProps, IState> {
564564 /**
565565 * Find the next event in the list, and the next visible event in the list.
566566 *
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)
567+ * @param event - the list of events to look in and whether they are shown
570568 * @param i - where in the list we are now
571569 *
572570 * @returns { nextEvent, nextTile }
573571 *
574- * nextEvent is the last event in the supplied array.
572+ * nextEvent is the event after i in the supplied array.
575573 *
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.
574+ * nextTile is the first event in the array after i that we will show a tile
575+ * for. It is used to to determine the 'last successful' flag when rendering
576+ * the tile.
579577 */
580578 private getNextEventInfo (
581- arr : MatrixEvent [ ] ,
582- shouldShow : boolean [ ] ,
579+ events : EventAndShouldShow [ ] ,
583580 i : number ,
584- ) : { nextEvent : MatrixEvent ; nextTile : MatrixEvent } {
581+ ) : { nextEvent : MatrixEvent | null ; nextTile : MatrixEvent | null } {
585582 // WARNING: this method is on a hot path.
586583
587- const nextEvent = i < arr . length - 1 ? arr [ i + 1 ] : null ;
584+ const nextEvent = i < events . length - 1 ? events [ i + 1 ] . event : null ;
588585
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- }
586+ const nextTile = findFirstShownAfter ( i , events ) ;
596587
597588 return { nextEvent, nextTile } ;
598589 }
@@ -618,14 +609,16 @@ export default class MessagePanel extends React.Component<IProps, IState> {
618609 // we also need to figure out which is the last event we show which isn't
619610 // a local echo, to manage the read-marker.
620611 let lastShownEvent : MatrixEvent | undefined ;
621- const shouldShow = this . props . events . map ( ( e ) => this . shouldShowEvent ( e ) ) ;
612+ const events : EventAndShouldShow [ ] = this . props . events . map ( ( event ) => {
613+ return { event, shouldShow : this . shouldShowEvent ( event ) } ;
614+ } ) ;
622615
623616 let lastShownNonLocalEchoIndex = - 1 ;
624- for ( let i = this . props . events . length - 1 ; i >= 0 ; i -- ) {
625- if ( ! shouldShow [ i ] ) {
617+ for ( let i = events . length - 1 ; i >= 0 ; i -- ) {
618+ const { event : mxEv , shouldShow } = events [ i ] ;
619+ if ( ! shouldShow ) {
626620 continue ;
627621 }
628- const mxEv = this . props . events [ i ] ;
629622
630623 if ( lastShownEvent === undefined ) {
631624 lastShownEvent = mxEv ;
@@ -654,12 +647,11 @@ export default class MessagePanel extends React.Component<IProps, IState> {
654647
655648 let grouper : BaseGrouper = null ;
656649
657- for ( let i = 0 ; i < this . props . events . length ; i ++ ) {
658- const mxEv = this . props . events [ i ] ;
659- const shouldShowEv = shouldShow [ i ] ;
650+ for ( let i = 0 ; i < events . length ; i ++ ) {
651+ const { event : mxEv , shouldShow } = events [ i ] ;
660652 const eventId = mxEv . getId ( ) ;
661653 const last = mxEv === lastShownEvent ;
662- const { nextEvent, nextTile } = this . getNextEventInfo ( this . props . events , shouldShow , i ) ;
654+ const { nextEvent, nextTile } = this . getNextEventInfo ( events , i ) ;
663655
664656 if ( grouper ) {
665657 if ( grouper . shouldGroup ( mxEv ) ) {
@@ -682,7 +674,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
682674 }
683675
684676 if ( ! grouper ) {
685- if ( shouldShowEv ) {
677+ if ( shouldShow ) {
686678 // make sure we unpack the array returned by getTilesForEvent,
687679 // otherwise React will auto-generate keys, and we will end up
688680 // replacing all the DOM elements every time we paginate.
@@ -1064,6 +1056,15 @@ export default class MessagePanel extends React.Component<IProps, IState> {
10641056 }
10651057}
10661058
1059+ /**
1060+ * Holds on to an event, caching the information about whether it should be
1061+ * shown. Avoids calling shouldShowEvent more times than we need to.
1062+ */
1063+ interface EventAndShouldShow {
1064+ event : MatrixEvent ;
1065+ shouldShow : boolean ;
1066+ }
1067+
10671068abstract class BaseGrouper {
10681069 public static canStartGroup = ( panel : MessagePanel , ev : MatrixEvent ) : boolean => true ;
10691070
@@ -1393,3 +1394,17 @@ class MainGrouper extends BaseGrouper {
13931394
13941395// all the grouper classes that we use, ordered by priority
13951396const groupers = [ CreationGrouper , MainGrouper ] ;
1397+
1398+ /**
1399+ * Look through the supplied list of EventAndShouldShow, and return the first
1400+ * event that is >start items through the list, and is shown.
1401+ */
1402+ function findFirstShownAfter ( start : number , events : EventAndShouldShow [ ] ) : MatrixEvent | null {
1403+ for ( let n = start + 1 ; n < events . length ; n ++ ) {
1404+ const { event, shouldShow } = events [ n ] ;
1405+ if ( shouldShow ) {
1406+ return event ;
1407+ }
1408+ }
1409+ return null ;
1410+ }
0 commit comments