Skip to content

Commit b58d09a

Browse files
authored
Prevent duplicated re-emitter setups in event-mapper (#2293)
1 parent 3b33237 commit b58d09a

File tree

4 files changed

+29
-13
lines changed

4 files changed

+29
-13
lines changed

spec/unit/matrix-client.spec.ts

+3
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,9 @@ describe("MatrixClient", function() {
816816
},
817817
addPendingEvent: jest.fn(),
818818
updatePendingEvent: jest.fn(),
819+
reEmitter: {
820+
reEmit: jest.fn(),
821+
},
819822
};
820823

821824
beforeEach(() => {

src/client.ts

+9
Original file line numberDiff line numberDiff line change
@@ -3779,6 +3779,15 @@ export class MatrixClient extends TypedEventEmitter<EmittedEvents, ClientEventHa
37793779
localEvent.setThreadId(thread.id);
37803780
}
37813781

3782+
// set up re-emitter for this new event - this is normally the job of EventMapper but we don't use it here
3783+
this.reEmitter.reEmit(localEvent, [
3784+
MatrixEventEvent.Replaced,
3785+
MatrixEventEvent.VisibilityChange,
3786+
]);
3787+
room?.reEmitter.reEmit(localEvent, [
3788+
MatrixEventEvent.BeforeRedaction,
3789+
]);
3790+
37823791
// if this is a relation or redaction of an event
37833792
// that hasn't been sent yet (e.g. with a local id starting with a ~)
37843793
// then listen for the remote echo of that event so that by the time

src/event-mapper.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export interface MapperOpts {
2525
}
2626

2727
export function eventMapperFor(client: MatrixClient, options: MapperOpts): EventMapper {
28-
const preventReEmit = Boolean(options.preventReEmit);
28+
let preventReEmit = Boolean(options.preventReEmit);
2929
const decrypt = options.decrypt !== false;
3030

3131
function mapper(plainOldJsObject: Partial<IEvent>) {
@@ -43,6 +43,8 @@ export function eventMapperFor(client: MatrixClient, options: MapperOpts): Event
4343
} else {
4444
// merge the latest unsigned data from the server
4545
event.setUnsigned({ ...event.getUnsigned(), ...plainOldJsObject.unsigned });
46+
// prevent doubling up re-emitters
47+
preventReEmit = true;
4648
}
4749

4850
const thread = room?.findThreadForEvent(event);

src/models/thread.ts

+14-12
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export class Thread extends TypedEventEmitter<EmittedEvents, EventHandlerMap> {
9595
]);
9696

9797
this.room.on(MatrixEventEvent.BeforeRedaction, this.onBeforeRedaction);
98+
this.room.on(RoomEvent.Redaction, this.onRedaction);
9899
this.room.on(RoomEvent.LocalEchoUpdated, this.onEcho);
99100
this.timelineSet.on(RoomEvent.Timeline, this.onEcho);
100101

@@ -115,23 +116,24 @@ export class Thread extends TypedEventEmitter<EmittedEvents, EventHandlerMap> {
115116
}
116117
}
117118

118-
private onBeforeRedaction = (event: MatrixEvent) => {
119+
private onBeforeRedaction = (event: MatrixEvent, redaction: MatrixEvent) => {
119120
if (event?.isRelation(THREAD_RELATION_TYPE.name) &&
120-
this.room.eventShouldLiveIn(event).threadId === this.id
121+
this.room.eventShouldLiveIn(event).threadId === this.id &&
122+
!redaction.status // only respect it when it succeeds
121123
) {
122124
this.replyCount--;
123125
this.emit(ThreadEvent.Update, this);
124126
}
127+
};
125128

126-
if (this.lastEvent?.getId() === event.getId()) {
127-
const events = [...this.timelineSet.getLiveTimeline().getEvents()].reverse();
128-
this.lastEvent = events.find(e => (
129-
!e.isRedacted() &&
130-
e.getId() !== event.getId() &&
131-
e.isRelation(THREAD_RELATION_TYPE.name)
132-
)) ?? this.rootEvent;
133-
this.emit(ThreadEvent.NewReply, this, this.lastEvent);
134-
}
129+
private onRedaction = (event: MatrixEvent) => {
130+
if (event.threadRootId !== this.id) return; // ignore redactions for other timelines
131+
const events = [...this.timelineSet.getLiveTimeline().getEvents()].reverse();
132+
this.lastEvent = events.find(e => (
133+
!e.isRedacted() &&
134+
e.isRelation(THREAD_RELATION_TYPE.name)
135+
)) ?? this.rootEvent;
136+
this.emit(ThreadEvent.Update, this);
135137
};
136138

137139
private onEcho = (event: MatrixEvent) => {
@@ -142,7 +144,7 @@ export class Thread extends TypedEventEmitter<EmittedEvents, EventHandlerMap> {
142144
// when threads are used over federation. That could result in the reply
143145
// count value drifting away from the value returned by the server
144146
const isThreadReply = event.isRelation(THREAD_RELATION_TYPE.name);
145-
if (!this.lastEvent || (isThreadReply
147+
if (!this.lastEvent || this.lastEvent.isRedacted() || (isThreadReply
146148
&& (event.getId() !== this.lastEvent.getId())
147149
&& (event.localTimestamp > this.lastEvent.localTimestamp))
148150
) {

0 commit comments

Comments
 (0)