@@ -756,6 +756,99 @@ export class EventTimelineSet extends TypedEventEmitter<EmittedEvents, EventTime
756756 this . emit ( RoomEvent . Timeline , event , this . room , Boolean ( toStartOfTimeline ) , false , data ) ;
757757 }
758758
759+ /**
760+ * Insert event to the given timeline, and emit Room.timeline. Assumes
761+ * we have already checked we don't know about this event.
762+ *
763+ * TEMPORARY: until we have recursive relations, we need this function
764+ * to exist to allow us to insert events in timeline order, which is our
765+ * best guess for Sync Order.
766+ * This is a copy of addEventToTimeline above, modified to insert the event
767+ * after the event it relates to, and before any event with a later
768+ * timestamp. This is our best guess at Sync Order.
769+ *
770+ * Will fire "Room.timeline" for each event added.
771+ *
772+ * @param options - addEventToTimeline options
773+ *
774+ * @remarks
775+ * Fires {@link RoomEvent.Timeline}
776+ */
777+ public insertEventIntoTimeline ( event : MatrixEvent , timeline : EventTimeline , roomState : RoomState ) : void {
778+ if ( timeline . getTimelineSet ( ) !== this ) {
779+ throw new Error ( `EventTimelineSet.addEventToTimeline: Timeline=${ timeline . toString ( ) } does not belong " +
780+ "in timelineSet(threadId=${ this . thread ?. id } )` ) ;
781+ }
782+
783+ // Make sure events don't get mixed in timelines they shouldn't be in (e.g. a
784+ // threaded message should not be in the main timeline).
785+ //
786+ // We can only run this check for timelines with a `room` because `canContain`
787+ // requires it
788+ if ( this . room && ! this . canContain ( event ) ) {
789+ let eventDebugString = `event=${ event . getId ( ) } ` ;
790+ if ( event . threadRootId ) {
791+ eventDebugString += `(belongs to thread=${ event . threadRootId } )` ;
792+ }
793+ logger . warn (
794+ `EventTimelineSet.addEventToTimeline: Ignoring ${ eventDebugString } that does not belong ` +
795+ `in timeline=${ timeline . toString ( ) } timelineSet(threadId=${ this . thread ?. id } )` ,
796+ ) ;
797+ return ;
798+ }
799+
800+ // Find the event that this event is related to - the "parent"
801+ const parentEventId = event . relationEventId ;
802+ if ( ! parentEventId ) {
803+ // Not related to anything - we just append
804+ this . addEventToTimeline ( event , timeline , {
805+ toStartOfTimeline : false ,
806+ fromCache : false ,
807+ timelineWasEmpty : false ,
808+ roomState,
809+ } ) ;
810+ return ;
811+ }
812+
813+ const parentEvent = this . findEventById ( parentEventId ) ;
814+ if ( ! parentEvent ) {
815+ // Not related to anything we know about - just append
816+ this . addEventToTimeline ( event , timeline , {
817+ toStartOfTimeline : false ,
818+ fromCache : false ,
819+ timelineWasEmpty : false ,
820+ roomState,
821+ } ) ;
822+ return ;
823+ }
824+
825+ const timelineEvents = timeline . getEvents ( ) ;
826+ const parentIndex = timelineEvents . indexOf ( parentEvent ) ;
827+ let insertIndex = parentIndex ;
828+ for ( ; insertIndex < timelineEvents . length ; insertIndex ++ ) {
829+ const nextEvent = timelineEvents [ insertIndex ] ;
830+ if ( nextEvent . getTs ( ) > event . getTs ( ) ) {
831+ // We found an event later than ours, so insert before that.
832+ break ;
833+ }
834+ }
835+ // If we got to the end of the loop, insertIndex points at the end of
836+ // the list.
837+
838+ const eventId = event . getId ( ) ! ;
839+ timeline . insertEvent ( event , insertIndex , roomState ) ;
840+ this . _eventIdToTimeline . set ( eventId , timeline ) ;
841+
842+ this . relations . aggregateParentEvent ( event ) ;
843+ this . relations . aggregateChildEvent ( event , this ) ;
844+
845+ const data : IRoomTimelineData = {
846+ timeline : timeline ,
847+ liveEvent : timeline == this . liveTimeline ,
848+ } ;
849+ this . emit ( RoomEvent . Timeline , event , this . room , false , false , data ) ;
850+ }
851+
759852 /**
760853 * Replaces event with ID oldEventId with one with newEventId, if oldEventId is
761854 * recognised. Otherwise, add to the live timeline. Used to handle remote echos.
0 commit comments