From b58d09aa9a7a3578c43185becb41ab0b17ce0f98 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 12 Apr 2022 09:42:55 +0100 Subject: [PATCH] Prevent duplicated re-emitter setups in event-mapper (#2293) --- spec/unit/matrix-client.spec.ts | 3 +++ src/client.ts | 9 +++++++++ src/event-mapper.ts | 4 +++- src/models/thread.ts | 26 ++++++++++++++------------ 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index b8659bd9b..680e14ed5 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -816,6 +816,9 @@ describe("MatrixClient", function() { }, addPendingEvent: jest.fn(), updatePendingEvent: jest.fn(), + reEmitter: { + reEmit: jest.fn(), + }, }; beforeEach(() => { diff --git a/src/client.ts b/src/client.ts index 60d3f3704..154e947b5 100644 --- a/src/client.ts +++ b/src/client.ts @@ -3779,6 +3779,15 @@ export class MatrixClient extends TypedEventEmitter) { @@ -43,6 +43,8 @@ export function eventMapperFor(client: MatrixClient, options: MapperOpts): Event } else { // merge the latest unsigned data from the server event.setUnsigned({ ...event.getUnsigned(), ...plainOldJsObject.unsigned }); + // prevent doubling up re-emitters + preventReEmit = true; } const thread = room?.findThreadForEvent(event); diff --git a/src/models/thread.ts b/src/models/thread.ts index 549336b4f..14a036b30 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -95,6 +95,7 @@ export class Thread extends TypedEventEmitter { ]); this.room.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction); + this.room.on(RoomEvent.Redaction, this.onRedaction); this.room.on(RoomEvent.LocalEchoUpdated, this.onEcho); this.timelineSet.on(RoomEvent.Timeline, this.onEcho); @@ -115,23 +116,24 @@ export class Thread extends TypedEventEmitter { } } - private onBeforeRedaction = (event: MatrixEvent) => { + private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent) => { if (event?.isRelation(THREAD_RELATION_TYPE.name) && - this.room.eventShouldLiveIn(event).threadId === this.id + this.room.eventShouldLiveIn(event).threadId === this.id && + !redaction.status // only respect it when it succeeds ) { this.replyCount--; this.emit(ThreadEvent.Update, this); } + }; - if (this.lastEvent?.getId() === event.getId()) { - const events = [...this.timelineSet.getLiveTimeline().getEvents()].reverse(); - this.lastEvent = events.find(e => ( - !e.isRedacted() && - e.getId() !== event.getId() && - e.isRelation(THREAD_RELATION_TYPE.name) - )) ?? this.rootEvent; - this.emit(ThreadEvent.NewReply, this, this.lastEvent); - } + private onRedaction = (event: MatrixEvent) => { + if (event.threadRootId !== this.id) return; // ignore redactions for other timelines + const events = [...this.timelineSet.getLiveTimeline().getEvents()].reverse(); + this.lastEvent = events.find(e => ( + !e.isRedacted() && + e.isRelation(THREAD_RELATION_TYPE.name) + )) ?? this.rootEvent; + this.emit(ThreadEvent.Update, this); }; private onEcho = (event: MatrixEvent) => { @@ -142,7 +144,7 @@ export class Thread extends TypedEventEmitter { // when threads are used over federation. That could result in the reply // count value drifting away from the value returned by the server const isThreadReply = event.isRelation(THREAD_RELATION_TYPE.name); - if (!this.lastEvent || (isThreadReply + if (!this.lastEvent || this.lastEvent.isRedacted() || (isThreadReply && (event.getId() !== this.lastEvent.getId()) && (event.localTimestamp > this.lastEvent.localTimestamp)) ) {