Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 71cece7

Browse files
maheichykMikhail Aheichyk
and
Mikhail Aheichyk
authored
Feeds event with relation to unknown to the widget (#12283)
* Feeds event with relation to unknown to the widget Signed-off-by: Mikhail Aheichyk <[email protected]> * Smaller changes Signed-off-by: Mikhail Aheichyk <[email protected]> --------- Signed-off-by: Mikhail Aheichyk <[email protected]> Co-authored-by: Mikhail Aheichyk <[email protected]>
1 parent 29b79ef commit 71cece7

File tree

2 files changed

+117
-7
lines changed

2 files changed

+117
-7
lines changed

src/stores/widgets/StopGapWidget.ts

+17-6
Original file line numberDiff line numberDiff line change
@@ -495,14 +495,20 @@ export class StopGapWidget extends EventEmitter {
495495
//
496496
// This approach of "read up to" prevents widgets receiving decryption spam from startup or
497497
// receiving out-of-order events from backfill and such.
498+
//
499+
// Skip marker timeline check for events with relations to unknown parent because these
500+
// events are not added to the timeline here and will be ignored otherwise:
501+
// https://github.com/matrix-org/matrix-js-sdk/blob/d3dfcd924201d71b434af3d77343b5229b6ed75e/src/models/room.ts#L2207-L2213
502+
let isRelationToUnknown: boolean | undefined = undefined;
498503
const upToEventId = this.readUpToMap[ev.getRoomId()!];
499504
if (upToEventId) {
500505
// Small optimization for exact match (prevent search)
501506
if (upToEventId === ev.getId()) {
502507
return;
503508
}
504509

505-
let isBeforeMark = true;
510+
// should be true to forward the event to the widget
511+
let shouldForward = false;
506512

507513
const room = this.client.getRoom(ev.getRoomId()!);
508514
if (!room) return;
@@ -515,14 +521,19 @@ export class StopGapWidget extends EventEmitter {
515521
if (timelineEvent.getId() === upToEventId) {
516522
break;
517523
} else if (timelineEvent.getId() === ev.getId()) {
518-
isBeforeMark = false;
524+
shouldForward = true;
519525
break;
520526
}
521527
}
522528

523-
if (isBeforeMark) {
524-
// Ignore the event: it is before our interest.
525-
return;
529+
if (!shouldForward) {
530+
// checks that the event has a relation to unknown event
531+
isRelationToUnknown =
532+
!ev.replyEventId && !!ev.relationEventId && !room.findEventById(ev.relationEventId);
533+
if (!isRelationToUnknown) {
534+
// Ignore the event: it is before our interest.
535+
return;
536+
}
526537
}
527538
}
528539

@@ -533,7 +544,7 @@ export class StopGapWidget extends EventEmitter {
533544
const evId = ev.getId();
534545
if (evRoomId && evId) {
535546
const room = this.client.getRoom(evRoomId);
536-
if (room && room.getMyMembership() === "join") {
547+
if (room && room.getMyMembership() === "join" && !isRelationToUnknown) {
537548
this.readUpToMap[evRoomId] = evId;
538549
}
539550
}

test/stores/widgets/StopGapWidget-test.ts

+100-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ limitations under the License.
1616

1717
import { mocked, MockedObject } from "jest-mock";
1818
import { last } from "lodash";
19-
import { MatrixEvent, MatrixClient, ClientEvent } from "matrix-js-sdk/src/matrix";
19+
import { MatrixEvent, MatrixClient, ClientEvent, EventTimeline } from "matrix-js-sdk/src/matrix";
2020
import { ClientWidgetApi, WidgetApiFromWidgetAction } from "matrix-widget-api";
2121
import { waitFor } from "@testing-library/react";
2222

@@ -88,6 +88,105 @@ describe("StopGapWidget", () => {
8888
expect(messaging.feedToDevice).toHaveBeenCalledWith(event.getEffectiveEvent(), false);
8989
});
9090

91+
describe("feed event", () => {
92+
let event1: MatrixEvent;
93+
let event2: MatrixEvent;
94+
95+
beforeEach(() => {
96+
event1 = mkEvent({
97+
event: true,
98+
id: "$event-id1",
99+
type: "org.example.foo",
100+
user: "@alice:example.org",
101+
content: { hello: "world" },
102+
room: "!1:example.org",
103+
});
104+
105+
event2 = mkEvent({
106+
event: true,
107+
id: "$event-id2",
108+
type: "org.example.foo",
109+
user: "@alice:example.org",
110+
content: { hello: "world" },
111+
room: "!1:example.org",
112+
});
113+
114+
const room = mkRoom(client, "!1:example.org");
115+
client.getRoom.mockImplementation((roomId) => (roomId === "!1:example.org" ? room : null));
116+
room.getLiveTimeline.mockReturnValue({
117+
getEvents: (): MatrixEvent[] => [event1, event2],
118+
} as unknown as EventTimeline);
119+
120+
messaging.feedEvent.mockResolvedValue();
121+
});
122+
123+
it("feeds incoming event to the widget", async () => {
124+
client.emit(ClientEvent.Event, event1);
125+
expect(messaging.feedEvent).toHaveBeenCalledWith(event1.getEffectiveEvent(), "!1:example.org");
126+
127+
client.emit(ClientEvent.Event, event2);
128+
expect(messaging.feedEvent).toHaveBeenCalledTimes(2);
129+
expect(messaging.feedEvent).toHaveBeenLastCalledWith(event2.getEffectiveEvent(), "!1:example.org");
130+
});
131+
132+
it("should not feed incoming event to the widget if seen already", async () => {
133+
client.emit(ClientEvent.Event, event1);
134+
expect(messaging.feedEvent).toHaveBeenCalledWith(event1.getEffectiveEvent(), "!1:example.org");
135+
136+
client.emit(ClientEvent.Event, event2);
137+
expect(messaging.feedEvent).toHaveBeenCalledTimes(2);
138+
expect(messaging.feedEvent).toHaveBeenLastCalledWith(event2.getEffectiveEvent(), "!1:example.org");
139+
140+
client.emit(ClientEvent.Event, event1);
141+
expect(messaging.feedEvent).toHaveBeenCalledTimes(2);
142+
expect(messaging.feedEvent).toHaveBeenLastCalledWith(event2.getEffectiveEvent(), "!1:example.org");
143+
});
144+
145+
it("should not feed incoming event if not in timeline", () => {
146+
const event = mkEvent({
147+
event: true,
148+
id: "$event-id",
149+
type: "org.example.foo",
150+
user: "@alice:example.org",
151+
content: {
152+
hello: "world",
153+
},
154+
room: "!1:example.org",
155+
});
156+
157+
client.emit(ClientEvent.Event, event);
158+
expect(messaging.feedEvent).toHaveBeenCalledWith(event.getEffectiveEvent(), "!1:example.org");
159+
});
160+
161+
it("feeds incoming event that is not in timeline but relates to unknown parent to the widget", async () => {
162+
const event = mkEvent({
163+
event: true,
164+
id: "$event-idRelation",
165+
type: "org.example.foo",
166+
user: "@alice:example.org",
167+
content: {
168+
"hello": "world",
169+
"m.relates_to": {
170+
event_id: "$unknown-parent",
171+
rel_type: "m.reference",
172+
},
173+
},
174+
room: "!1:example.org",
175+
});
176+
177+
client.emit(ClientEvent.Event, event1);
178+
expect(messaging.feedEvent).toHaveBeenCalledWith(event1.getEffectiveEvent(), "!1:example.org");
179+
180+
client.emit(ClientEvent.Event, event);
181+
expect(messaging.feedEvent).toHaveBeenCalledTimes(2);
182+
expect(messaging.feedEvent).toHaveBeenLastCalledWith(event.getEffectiveEvent(), "!1:example.org");
183+
184+
client.emit(ClientEvent.Event, event1);
185+
expect(messaging.feedEvent).toHaveBeenCalledTimes(2);
186+
expect(messaging.feedEvent).toHaveBeenLastCalledWith(event.getEffectiveEvent(), "!1:example.org");
187+
});
188+
});
189+
91190
describe("when there is a voice broadcast recording", () => {
92191
let voiceBroadcastInfoEvent: MatrixEvent;
93192
let voiceBroadcastRecording: VoiceBroadcastRecording;

0 commit comments

Comments
 (0)