diff --git a/src/models/event.ts b/src/models/event.ts index 983cb15d8..317377b1a 100644 --- a/src/models/event.ts +++ b/src/models/event.ts @@ -412,9 +412,12 @@ export class MatrixEvent extends EventEmitter { * or in the main room timeline */ public get replyInThread(): boolean { - const relations = this.getWireContent()["m.relates_to"]; - return this.replyEventId - && relations[UNSTABLE_ELEMENT_REPLY_IN_THREAD.name]; + const replyTo = this.getWireContent() + ?.["m.relates_to"] + ?.["m.in_reply_to"]; + return (this.replyEventId + && replyTo[UNSTABLE_ELEMENT_REPLY_IN_THREAD.name]) + || this.thread instanceof Thread; } /** diff --git a/src/models/room.ts b/src/models/room.ts index 1bb2bb118..2ada8454c 100644 --- a/src/models/room.ts +++ b/src/models/room.ts @@ -1104,16 +1104,17 @@ export class Room extends EventEmitter { * @experimental */ private dedupeThreads = (readyThread): void => { - const threads = Array.from(this.threads); - if (threads.includes(readyThread)) { - this.threads = new Set(threads.filter(thread => { - if (readyThread.id === thread.id && readyThread !== thread) { - return false; - } else { - return true; - } - })); - } + const deduped = Array.from(this.threads).reduce((dedupedThreads, thread) => { + if (dedupedThreads.has(thread.id)) { + dedupedThreads.get(thread.id).merge(thread); + } else { + dedupedThreads.set(thread.id, thread); + } + + return dedupedThreads; + }, new Map()); + + this.threads = new Set(deduped.values()); }; /** diff --git a/src/models/thread.ts b/src/models/thread.ts index 043ff7dc7..098696892 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -31,7 +31,7 @@ export class Thread extends EventEmitter { /** * A reference to all the events ID at the bottom of the threads */ - public tail = new Set(); + public readonly tail = new Set(); private _timelineSet: EventTimelineSet; constructor( @@ -155,7 +155,7 @@ export class Thread extends EventEmitter { * The number of messages in the thread */ public get length(): number { - return this._timelineSet.getLiveTimeline().getEvents().length; + return this.events.length; } /** @@ -163,7 +163,7 @@ export class Thread extends EventEmitter { */ public get participants(): Set { const participants = new Set(); - this._timelineSet.getLiveTimeline().getEvents().forEach(event => { + this.events.forEach(event => { participants.add(event.getSender()); }); return participants; @@ -180,7 +180,18 @@ export class Thread extends EventEmitter { * A getter for the last event added to the thread */ public get replyToEvent(): MatrixEvent { - const events = this._timelineSet.getLiveTimeline().getEvents(); + const events = this.events; return events[events.length -1]; } + + public get events(): MatrixEvent[] { + return this._timelineSet.getLiveTimeline().getEvents(); + } + + public merge(thread: Thread): void { + thread.events.forEach(event => { + this.addEvent(event); + }); + this.events.forEach(event => event.setThread(this)); + } } diff --git a/src/sync.ts b/src/sync.ts index 29e25765f..5cbe5c2eb 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -1718,11 +1718,27 @@ export class SyncApi { * @experimental */ private processThreadEvents(room: Room, threadedEvents: MatrixEvent[]): void { - threadedEvents.forEach(event => { - room.addThreadedEvent(event); - }); + threadedEvents + .sort((a, b) => a.getTs() - b.getTs()) + .forEach(event => { + room.addThreadedEvent(event); + }); } + // extractRelatedEvents(event: MatrixEvent, events: MatrixEvent[], relatedEvents: MatrixEvent[] = []): MatrixEvent[] { + // relatedEvents.push(event); + + // const parentEventId = event.parentEventId; + // const parentEventIndex = events.findIndex(event => event.getId() === parentEventId); + + // if (parentEventIndex > -1) { + // const [relatedEvent] = events.splice(parentEventIndex, 1); + // return this.extractRelatedEvents(relatedEvent, events, relatedEvents); + // } else { + // return relatedEvents; + // } + // } + /** * Takes a list of timelineEvents and adds and adds to notifEvents * as appropriate.