@@ -97,6 +97,11 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
97
97
private readonly pendingEventOrdering : PendingEventOrdering ;
98
98
99
99
public initialEventsFetched = ! Thread . hasServerSideSupport ;
100
+ /**
101
+ * An array of events to add to the timeline once the thread has been initialised
102
+ * with server suppport.
103
+ */
104
+ public replayEvents : MatrixEvent [ ] | null = [ ] ;
100
105
101
106
public constructor ( public readonly id : string , public rootEvent : MatrixEvent | undefined , opts : IThreadOpts ) {
102
107
super ( ) ;
@@ -136,7 +141,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
136
141
this . setEventMetadata ( this . rootEvent ) ;
137
142
}
138
143
139
- private async fetchRootEvent ( ) : Promise < void > {
144
+ public async fetchRootEvent ( ) : Promise < void > {
140
145
this . rootEvent = this . room . findEventById ( this . id ) ;
141
146
// If the rootEvent does not exist in the local stores, then fetch it from the server.
142
147
try {
@@ -266,9 +271,23 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
266
271
this . addEventToTimeline ( event , false ) ;
267
272
this . fetchEditsWhereNeeded ( event ) ;
268
273
} else if ( event . isRelation ( RelationType . Annotation ) || event . isRelation ( RelationType . Replace ) ) {
269
- // Apply annotations and replace relations to the relations of the timeline only
270
- this . timelineSet . relations ?. aggregateParentEvent ( event ) ;
271
- this . timelineSet . relations ?. aggregateChildEvent ( event , this . timelineSet ) ;
274
+ if ( ! this . initialEventsFetched ) {
275
+ /**
276
+ * A thread can be fully discovered via a single sync response
277
+ * And when that's the case we still ask the server to do an initialisation
278
+ * as it's the safest to ensure we have everything.
279
+ * However when we are in that scenario we might loose annotation or edits
280
+ *
281
+ * This fix keeps a reference to those events and replay them once the thread
282
+ * has been initialised properly.
283
+ */
284
+ this . replayEvents ?. push ( event ) ;
285
+ } else {
286
+ this . addEventToTimeline ( event , toStartOfTimeline ) ;
287
+ // Apply annotations and replace relations to the relations of the timeline only
288
+ this . timelineSet . relations ?. aggregateParentEvent ( event ) ;
289
+ this . timelineSet . relations ?. aggregateChildEvent ( event , this . timelineSet ) ;
290
+ }
272
291
return ;
273
292
}
274
293
@@ -316,7 +335,7 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
316
335
return rootEvent ?. getServerAggregatedRelation < IThreadBundledRelationship > ( THREAD_RELATION_TYPE . name ) ;
317
336
}
318
337
319
- private async processRootEvent ( ) : Promise < void > {
338
+ public async processRootEvent ( ) : Promise < void > {
320
339
const bundledRelationship = this . getRootEventBundledRelationship ( ) ;
321
340
if ( Thread . hasServerSideSupport && bundledRelationship ) {
322
341
this . replyCount = bundledRelationship . count ;
@@ -375,6 +394,10 @@ export class Thread extends ReadReceipt<EmittedEvents, EventHandlerMap> {
375
394
limit : Math . max ( 1 , this . length ) ,
376
395
} ) ;
377
396
}
397
+ for ( const event of this . replayEvents ! ) {
398
+ this . addEvent ( event , false ) ;
399
+ }
400
+ this . replayEvents = null ;
378
401
// just to make sure that, if we've created a timeline window for this thread before the thread itself
379
402
// existed (e.g. when creating a new thread), we'll make sure the panel is force refreshed correctly.
380
403
this . emit ( RoomEvent . TimelineReset , this . room , this . timelineSet , true ) ;
0 commit comments