diff --git a/spec/unit/thread-utils.spec.ts b/spec/unit/thread-utils.spec.ts new file mode 100644 index 00000000000..eba63d86e8e --- /dev/null +++ b/spec/unit/thread-utils.spec.ts @@ -0,0 +1,51 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { IEvent } from "../../src"; +import { randomString } from "../../src/randomstring"; +import { getRelationsThreadFilter } from "../../src/thread-utils"; + +function makeEvent(relatesToEvent: string, relType: string): Partial { + return { + event_id: randomString(10), + type: "m.room.message", + content: { + "msgtype": "m.text", + "body": "foo", + "m.relates_to": { + rel_type: relType, + event_id: relatesToEvent, + }, + }, + }; +} + +describe("getRelationsThreadFilter", () => { + it("should filter out relations directly to the thread root event", () => { + const threadId = "thisIsMyThreadRoot"; + + const reactionToRoot = makeEvent(threadId, "m.annotation"); + const editToRoot = makeEvent(threadId, "m.replace"); + const firstThreadedReply = makeEvent(threadId, "m.thread"); + const reactionToThreadedEvent = makeEvent(firstThreadedReply.event_id!, "m.annotation"); + + const filteredEvents = [reactionToRoot, editToRoot, firstThreadedReply, reactionToThreadedEvent].filter( + getRelationsThreadFilter(threadId), + ); + + expect(filteredEvents).toEqual([firstThreadedReply, reactionToThreadedEvent]); + }); +}); diff --git a/src/client.ts b/src/client.ts index 9ef4550d412..b10949e2242 100644 --- a/src/client.ts +++ b/src/client.ts @@ -221,6 +221,7 @@ import { } from "./secret-storage"; import { RegisterRequest, RegisterResponse } from "./@types/registration"; import { MatrixRTCSessionManager } from "./matrixrtc/MatrixRTCSessionManager"; +import { getRelationsThreadFilter } from "./thread-utils"; export type Store = IStore; @@ -5968,14 +5969,14 @@ export class MatrixClient extends TypedEventEmitter { const mapper = this.getEventMapper(); - const matrixEvents = res.chunk.filter(noUnsafeEventProps).map(mapper); + const matrixEvents = res.chunk + .filter(noUnsafeEventProps) + .filter(getRelationsThreadFilter(thread.id)) + .map(mapper); // Process latest events first for (const event of matrixEvents.slice().reverse()) { @@ -7591,7 +7597,7 @@ export class MatrixClient extends TypedEventEmitter { diff --git a/src/models/thread.ts b/src/models/thread.ts index e4cfdaadb83..71e5d749dbe 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -609,7 +609,6 @@ export class Thread extends ReadReceipt) => boolean { + return (e: Partial) => + e.content?.["m.relates_to"]?.event_id !== threadId || + e.content?.["m.relates_to"]?.rel_type === THREAD_RELATION_TYPE.name; +}