@@ -406,9 +406,51 @@ export class SlidingSyncSdk {
406406 // this helps large account to speed up faster
407407 // room::decryptCriticalEvent is in charge of decrypting all the events
408408 // required for a client to function properly
409- const timelineEvents = mapEvents ( this . client , room . roomId , roomData . timeline , false ) ;
409+ let timelineEvents = mapEvents ( this . client , room . roomId , roomData . timeline , false ) ;
410410 const ephemeralEvents = [ ] ; // TODO this.mapSyncEventsFormat(joinObj.ephemeral);
411411
412+ // TODO: handle threaded / beacon events
413+
414+ if ( roomData . initial ) {
415+ // we should not know about any of these timeline entries if this is a genuinely new room.
416+ // If we do, then we've effectively done scrollback (e.g requesting timeline_limit: 1 for
417+ // this room, then timeline_limit: 50).
418+ const knownEvents = new Set < string > ( ) ;
419+ room . getLiveTimeline ( ) . getEvents ( ) . forEach ( ( e ) => {
420+ knownEvents . add ( e . getId ( ) ) ;
421+ } ) ;
422+ // all unknown events BEFORE a known event must be scrollback e.g:
423+ // D E <-- what we know
424+ // A B C D E F <-- what we just received
425+ // means:
426+ // A B C <-- scrollback
427+ // D E <-- dupes
428+ // F <-- new event
429+ // We bucket events based on if we have seen a known event yet.
430+ const oldEvents : MatrixEvent [ ] = [ ] ;
431+ const newEvents : MatrixEvent [ ] = [ ] ;
432+ let seenKnownEvent = false ;
433+ for ( let i = timelineEvents . length - 1 ; i >= 0 ; i -- ) {
434+ const recvEvent = timelineEvents [ i ] ;
435+ if ( knownEvents . has ( recvEvent . getId ( ) ) ) {
436+ seenKnownEvent = true ;
437+ continue ; // don't include this event, it's a dupe
438+ }
439+ if ( seenKnownEvent ) {
440+ // old -> new
441+ oldEvents . push ( recvEvent ) ;
442+ } else {
443+ // old -> new
444+ newEvents . unshift ( recvEvent ) ;
445+ }
446+ }
447+ timelineEvents = newEvents ;
448+ if ( oldEvents . length > 0 ) {
449+ // old events are scrollback, insert them now
450+ room . addEventsToTimeline ( oldEvents , true , room . getLiveTimeline ( ) , roomData . prev_batch ) ;
451+ }
452+ }
453+
412454 const encrypted = this . client . isRoomEncrypted ( room . roomId ) ;
413455 // we do this first so it's correct when any of the events fire
414456 if ( roomData . notification_count != null ) {
0 commit comments