From 9fd7fe15a3f6a4903e756ff81b8b779866dca5e9 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Tue, 4 Apr 2023 11:09:57 +0200 Subject: [PATCH 1/9] Implement MSC 3891 --- src/@types/requests.ts | 1 + src/client.ts | 14 +++++++++----- src/feature.ts | 4 ++++ src/models/thread.ts | 41 ++++++++++++++++++++++------------------- 4 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/@types/requests.ts b/src/@types/requests.ts index 12f4d8eb00a..78be3a6dfd3 100644 --- a/src/@types/requests.ts +++ b/src/@types/requests.ts @@ -186,6 +186,7 @@ export interface IRelationsRequestOpts { to?: string; limit?: number; dir?: Direction; + recurse?: boolean; } export interface IRelationsResponse { diff --git a/src/client.ts b/src/client.ts index 514be982b72..a5343dff807 100644 --- a/src/client.ts +++ b/src/client.ts @@ -5748,14 +5748,14 @@ export class MatrixClient extends TypedEventEmitter = res.end; @@ -5813,7 +5813,7 @@ export class MatrixClient extends TypedEventEmitter { const mapper = this.getEventMapper(); @@ -7956,6 +7957,9 @@ export class MatrixClient extends TypedEventEmitter = { [Feature.AccountDataDeletion]: { unstablePrefixes: ["org.matrix.msc3391"], }, + [Feature.RelationsRecursion]: { + unstablePrefixes: ["org.matrix.msc3981"], + }, }; export async function buildFeatureSupportMap(versions: IServerVersions): Promise> { diff --git a/src/models/thread.ts b/src/models/thread.ts index 9a4ead33bc9..0010db5bb99 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -28,6 +28,7 @@ import { ServerControlledNamespacedValue } from "../NamespacedValue"; import { logger } from "../logger"; import { ReadReceipt } from "./read-receipt"; import { CachedReceiptStructure, ReceiptType } from "../@types/read_receipts"; +import { Feature } from "../feature"; export enum ThreadEvent { New = "Thread.new", @@ -458,25 +459,27 @@ export class Thread extends ReadReceipt { // XXX: Workaround for /~https://github.com/matrix-org/matrix-spec-proposals/pull/2676/files#r827240084 private async fetchEditsWhereNeeded(...events: MatrixEvent[]): Promise { - return Promise.all( - events - .filter((e) => e.isEncrypted()) - .map((event: MatrixEvent) => { - if (event.isRelation()) return; // skip - relations don't get edits - return this.client - .relations(this.roomId, event.getId()!, RelationType.Replace, event.getType(), { - limit: 1, - }) - .then((relations) => { - if (relations.events.length) { - event.makeReplaced(relations.events[0]); - } - }) - .catch((e) => { - logger.error("Failed to load edits for encrypted thread event", e); - }); - }), - ); + if (!this.client.canSupport.get(Feature.RelationsRecursion)) { + return Promise.all( + events + .filter((e) => e.isEncrypted()) + .map((event: MatrixEvent) => { + if (event.isRelation()) return; // skip - relations don't get edits + return this.client + .relations(this.roomId, event.getId()!, RelationType.Replace, event.getType(), { + limit: 1, + }) + .then((relations) => { + if (relations.events.length) { + event.makeReplaced(relations.events[0]); + } + }) + .catch((e) => { + logger.error("Failed to load edits for encrypted thread event", e); + }); + }), + ); + } } public setEventMetadata(event: Optional): void { From 8b729106b26700a9ad3457b930c711a039d11778 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Tue, 4 Apr 2023 11:40:40 +0200 Subject: [PATCH 2/9] Add necessary mocks to tests --- spec/unit/event-timeline-set.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/unit/event-timeline-set.spec.ts b/spec/unit/event-timeline-set.spec.ts index 4a624268c8a..a099aba0370 100644 --- a/spec/unit/event-timeline-set.spec.ts +++ b/spec/unit/event-timeline-set.spec.ts @@ -82,6 +82,7 @@ describe("EventTimelineSet", () => { beforeEach(() => { client = utils.mock(MatrixClient, "MatrixClient"); client.reEmitter = utils.mock(ReEmitter, "ReEmitter"); + client.canSupport = new Map(); room = new Room(roomId, client, userA); eventTimelineSet = new EventTimelineSet(room); eventTimeline = new EventTimeline(eventTimelineSet); From d6883d54ce25ec09c2c7301e24bc5d64b14ac6a0 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Tue, 4 Apr 2023 11:55:02 +0200 Subject: [PATCH 3/9] Only set recurse parameter if supported --- src/client.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/client.ts b/src/client.ts index a5343dff807..be9ede84559 100644 --- a/src/client.ts +++ b/src/client.ts @@ -5736,6 +5736,7 @@ export class MatrixClient extends TypedEventEmitter = res.end; @@ -5813,7 +5814,7 @@ export class MatrixClient extends TypedEventEmitter { const mapper = this.getEventMapper(); From 4ce49e87e87496f9198dc4f3fe49f0bc640b40d8 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Tue, 25 Apr 2023 15:30:44 +0200 Subject: [PATCH 4/9] fix: address review comments --- src/@types/requests.ts | 2 +- src/models/thread.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/@types/requests.ts b/src/@types/requests.ts index 78be3a6dfd3..364b9f12c2a 100644 --- a/src/@types/requests.ts +++ b/src/@types/requests.ts @@ -186,7 +186,7 @@ export interface IRelationsRequestOpts { to?: string; limit?: number; dir?: Direction; - recurse?: boolean; + recurse?: boolean; // MSC3981 Relations Recursion /~https://github.com/matrix-org/matrix-spec-proposals/pull/3981 } export interface IRelationsResponse { diff --git a/src/models/thread.ts b/src/models/thread.ts index 0010db5bb99..c31499b2b34 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -28,7 +28,7 @@ import { ServerControlledNamespacedValue } from "../NamespacedValue"; import { logger } from "../logger"; import { ReadReceipt } from "./read-receipt"; import { CachedReceiptStructure, ReceiptType } from "../@types/read_receipts"; -import { Feature } from "../feature"; +import { Feature, ServerSupport } from "../feature"; export enum ThreadEvent { New = "Thread.new", @@ -459,7 +459,8 @@ export class Thread extends ReadReceipt { // XXX: Workaround for /~https://github.com/matrix-org/matrix-spec-proposals/pull/2676/files#r827240084 private async fetchEditsWhereNeeded(...events: MatrixEvent[]): Promise { - if (!this.client.canSupport.get(Feature.RelationsRecursion)) { + const recursionSupport = this.client.canSupport.get(Feature.RelationsRecursion) ?? ServerSupport.Unsupported; + if (recursionSupport !== ServerSupport.Unsupported) { return Promise.all( events .filter((e) => e.isEncrypted()) From f7401e05defbbfc6c88085a4e2f85d1203158bd1 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Thu, 27 Apr 2023 13:16:53 +0200 Subject: [PATCH 5/9] task: unify unstable prefix code between client and tests --- .../matrix-client-event-timeline.spec.ts | 19 +++++++++---------- src/client.ts | 10 ++-------- src/utils.ts | 12 ++++++++++++ 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index dbcb48acda7..ae542149338 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -29,9 +29,10 @@ import { Room, } from "../../src/matrix"; import { logger } from "../../src/logger"; -import { encodeParams, encodeUri, QueryDict, replaceParam } from "../../src/utils"; +import { encodeParams, encodeUri, prefixUnstableParameters, QueryDict } from "../../src/utils"; import { TestClient } from "../TestClient"; import { FeatureSupport, Thread, THREAD_RELATION_TYPE, ThreadEvent } from "../../src/models/thread"; +import { Feature, ServerSupport } from "../../src/feature"; import { emitPromise } from "../test-utils/test-utils"; const userId = "@alice:localhost"; @@ -49,13 +50,11 @@ const withoutRoomId = (e: Partial): Partial => { /** * Our httpBackend only allows matching calls if we have the exact same query, in the exact same order * This method allows building queries with the exact same parameter order as the fetchRelations method in client + * @param supports features supported by our client * @param params query parameters */ -const buildRelationPaginationQuery = (params: QueryDict): string => { - if (Thread.hasServerSideFwdPaginationSupport === FeatureSupport.Experimental) { - params = replaceParam("dir", "org.matrix.msc3715.dir", params); - } - return "?" + encodeParams(params).toString(); +const buildRelationPaginationQuery = (supports: Map, params: QueryDict): string => { + return "?" + encodeParams(prefixUnstableParameters(supports, params)).toString(); }; const USER_MEMBERSHIP_EVENT = utils.mkMembership({ @@ -619,7 +618,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery({ dir: Direction.Backward, limit: 1 }), + buildRelationPaginationQuery(client.canSupport, { dir: Direction.Backward, limit: 1 }), ) .respond(200, function () { return { @@ -1789,7 +1788,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery({ dir: Direction.Backward, limit: 1 }), + buildRelationPaginationQuery(client.canSupport, { dir: Direction.Backward, limit: 1 }), ) .respond(200, function () { return { @@ -1847,7 +1846,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery({ dir: Direction.Backward, from: "start_token" }), + buildRelationPaginationQuery(client.canSupport, { dir: Direction.Backward, from: "start_token" }), ) .respond(200, function () { return { @@ -1861,7 +1860,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery({ dir: Direction.Forward, from: "end_token" }), + buildRelationPaginationQuery(client.canSupport, { dir: Direction.Forward, from: "end_token" }), ) .respond(200, function () { return { diff --git a/src/client.ts b/src/client.ts index be9ede84559..0be03b81979 100644 --- a/src/client.ts +++ b/src/client.ts @@ -38,7 +38,7 @@ import { Filter, IFilterDefinition, IRoomEventFilter } from "./filter"; import { CallEventHandlerEvent, CallEventHandler, CallEventHandlerEventHandlerMap } from "./webrtc/callEventHandler"; import { GroupCallEventHandlerEvent, GroupCallEventHandlerEventHandlerMap } from "./webrtc/groupCallEventHandler"; import * as utils from "./utils"; -import { replaceParam, QueryDict, sleep, noUnsafeEventProps, safeSet } from "./utils"; +import { QueryDict, sleep, noUnsafeEventProps, safeSet } from "./utils"; import { Direction, EventTimeline } from "./models/event-timeline"; import { IActionsObject, PushProcessor } from "./pushprocessor"; import { AutoDiscovery, AutoDiscoveryAction } from "./autodiscovery"; @@ -7956,13 +7956,7 @@ export class MatrixClient extends TypedEventEmitter { - let params = opts as QueryDict; - if (Thread.hasServerSideFwdPaginationSupport === FeatureSupport.Experimental) { - params = replaceParam("dir", "org.matrix.msc3715.dir", params); - } - if (this.canSupport.get(Feature.RelationsRecursion) === ServerSupport.Unstable) { - params = replaceParam("recurse", "org.matrix.msc3981.recurse", params); - } + const params = utils.prefixUnstableParameters(this.canSupport, opts as QueryDict); const queryString = utils.encodeParams(params); let templatedUrl = "/rooms/$roomId/relations/$eventId"; diff --git a/src/utils.ts b/src/utils.ts index 326f87c38bc..1a0d6b7d137 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -25,6 +25,8 @@ import { Optional } from "matrix-events-sdk"; import { IEvent, MatrixEvent } from "./models/event"; import { M_TIMESTAMP } from "./@types/location"; import { ReceiptType } from "./@types/read_receipts"; +import { Feature, ServerSupport } from "./feature"; +import { FeatureSupport, Thread } from "./models/thread"; const interns = new Map(); @@ -87,6 +89,16 @@ export function replaceParam(stable: string, unstable: string, dict: QueryDict): return result; } +export function prefixUnstableParameters(supports: Map, params: QueryDict): QueryDict { + if (Thread.hasServerSideFwdPaginationSupport === FeatureSupport.Experimental) { + params = replaceParam("dir", "org.matrix.msc3715.dir", params); + } + if (supports.get(Feature.RelationsRecursion) === ServerSupport.Unstable) { + params = replaceParam("recurse", "org.matrix.msc3981.recurse", params); + } + return params; +} + /** * Decode a query string in `application/x-www-form-urlencoded` format. * @param query - A query string to decode e.g. From 861cea1c67352a7396b6bb905b8a160876e205c9 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Thu, 27 Apr 2023 13:17:25 +0200 Subject: [PATCH 6/9] Add test for relations recursion --- .../matrix-client-event-timeline.spec.ts | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index ae542149338..fb2f4c1dbd9 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -21,11 +21,13 @@ import { EventStatus, EventTimeline, EventTimelineSet, + EventType, Filter, IEvent, MatrixClient, MatrixEvent, PendingEventOrdering, + RelationType, Room, } from "../../src/matrix"; import { logger } from "../../src/logger"; @@ -1163,6 +1165,115 @@ describe("MatrixClient event timelines", function () { ]); }); + it("should ensure thread events don't get reordered with recursive relations", async () => { + // Test data for a second reply to the first thread + const THREAD_REPLY2 = utils.mkEvent({ + room: roomId, + user: userId, + type: "m.room.message", + content: { + "body": "thread reply 2", + "msgtype": "m.text", + "m.relates_to": { + // We can't use the const here because we change server support mode for test + rel_type: "io.element.thread", + event_id: THREAD_ROOT.event_id, + }, + }, + event: true, + }); + THREAD_REPLY2.localTimestamp += 1000; + const THREAD_ROOT_REACTION = utils.mkEvent( + { + event: true, + type: EventType.Reaction, + user: userId, + room: roomId, + content: { + "m.relates_to": { + rel_type: RelationType.Annotation, + event_id: THREAD_ROOT.event_id!, + key: Math.random().toString(), + }, + }, + }, + ); + THREAD_ROOT_REACTION.localTimestamp += 2000; + + // Test data for a second reply to the first thread + const THREAD_REPLY3 = utils.mkEvent({ + room: roomId, + user: userId, + type: "m.room.message", + content: { + "body": "thread reply 3", + "msgtype": "m.text", + "m.relates_to": { + // We can't use the const here because we change server support mode for test + rel_type: "io.element.thread", + event_id: THREAD_ROOT.event_id, + }, + }, + event: true, + }); + THREAD_REPLY3.localTimestamp += 3000; + + // Test data for the first thread, with the second reply + const THREAD_ROOT_UPDATED = { + ...THREAD_ROOT, + unsigned: { + ...THREAD_ROOT.unsigned, + "m.relations": { + ...THREAD_ROOT.unsigned!["m.relations"], + "io.element.thread": { + ...THREAD_ROOT.unsigned!["m.relations"]!["io.element.thread"], + count: 3, + latest_event: THREAD_REPLY3.event, + }, + }, + }, + }; + + // @ts-ignore + client.clientOpts.threadSupport = true; + client.canSupport.set(Feature.RelationsRecursion, ServerSupport.Unstable); + Thread.setServerSideSupport(FeatureSupport.Stable); + Thread.setServerSideListSupport(FeatureSupport.Stable); + Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); + + client.fetchRoomEvent = () => Promise.resolve(THREAD_ROOT_UPDATED); + + await client.stopClient(); // we don't need the client to be syncing at this time + const room = client.getRoom(roomId)!; + + const prom = emitPromise(room, ThreadEvent.Update); + // Assume we're seeing the reply while loading backlog + room.addLiveEvents([THREAD_REPLY2]); + httpBackend + .when( + "GET", + "/_matrix/client/v1/rooms/!foo%3Abar/relations/" + + encodeURIComponent(THREAD_ROOT_UPDATED.event_id!) + + "/" + + encodeURIComponent(THREAD_RELATION_TYPE.name) + + buildRelationPaginationQuery(client.canSupport, { recurse: true , dir: Direction.Backward, limit: 3 }), + ) + .respond(200, { + chunk: [THREAD_REPLY3.event, THREAD_ROOT_REACTION, THREAD_REPLY2.event, THREAD_REPLY], + }); + await flushHttp(prom); + // but while loading the metadata, a new reply has arrived + room.addLiveEvents([THREAD_REPLY3]); + const thread = room.getThread(THREAD_ROOT_UPDATED.event_id!)!; + // then the events should still be all in the right order + expect(thread.events.map((it) => it.getId())).toEqual([ + THREAD_ROOT.event_id, + THREAD_REPLY.event_id, + THREAD_REPLY2.getId(), + THREAD_REPLY3.getId(), + ]); + }); + describe("paginateEventTimeline for thread list timeline", function () { const RANDOM_TOKEN = "7280349c7bee430f91defe2a38a0a08c"; From 2011cc63c22f1050d2e389a0033bc8c198106e96 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Thu, 27 Apr 2023 13:25:30 +0200 Subject: [PATCH 7/9] Make prettier happier :) --- .../matrix-client-event-timeline.spec.ts | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index fb2f4c1dbd9..0b2d8745162 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -1183,21 +1183,19 @@ describe("MatrixClient event timelines", function () { event: true, }); THREAD_REPLY2.localTimestamp += 1000; - const THREAD_ROOT_REACTION = utils.mkEvent( - { - event: true, - type: EventType.Reaction, - user: userId, - room: roomId, - content: { - "m.relates_to": { - rel_type: RelationType.Annotation, - event_id: THREAD_ROOT.event_id!, - key: Math.random().toString(), - }, + const THREAD_ROOT_REACTION = utils.mkEvent({ + event: true, + type: EventType.Reaction, + user: userId, + room: roomId, + content: { + "m.relates_to": { + rel_type: RelationType.Annotation, + event_id: THREAD_ROOT.event_id!, + key: Math.random().toString(), }, }, - ); + }); THREAD_ROOT_REACTION.localTimestamp += 2000; // Test data for a second reply to the first thread @@ -1253,10 +1251,14 @@ describe("MatrixClient event timelines", function () { .when( "GET", "/_matrix/client/v1/rooms/!foo%3Abar/relations/" + - encodeURIComponent(THREAD_ROOT_UPDATED.event_id!) + - "/" + - encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { recurse: true , dir: Direction.Backward, limit: 3 }), + encodeURIComponent(THREAD_ROOT_UPDATED.event_id!) + + "/" + + encodeURIComponent(THREAD_RELATION_TYPE.name) + + buildRelationPaginationQuery(client.canSupport, { + recurse: true, + dir: Direction.Backward, + limit: 3, + }), ) .respond(200, { chunk: [THREAD_REPLY3.event, THREAD_ROOT_REACTION, THREAD_REPLY2.event, THREAD_REPLY], @@ -1957,7 +1959,10 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { dir: Direction.Backward, from: "start_token" }), + buildRelationPaginationQuery(client.canSupport, { + dir: Direction.Backward, + from: "start_token", + }), ) .respond(200, function () { return { From f6f324e1bacbe158c8da7852170482d5546797b6 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Thu, 27 Apr 2023 13:58:40 +0200 Subject: [PATCH 8/9] Revert "task: unify unstable prefix code between client and tests" This reverts commit f7401e05 --- .../matrix-client-event-timeline.spec.ts | 24 ++++++++++--------- src/client.ts | 10 ++++++-- src/utils.ts | 12 ---------- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index 0b2d8745162..142dd18a02c 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -31,11 +31,11 @@ import { Room, } from "../../src/matrix"; import { logger } from "../../src/logger"; -import { encodeParams, encodeUri, prefixUnstableParameters, QueryDict } from "../../src/utils"; +import { encodeParams, encodeUri, QueryDict, replaceParam } from "../../src/utils"; import { TestClient } from "../TestClient"; import { FeatureSupport, Thread, THREAD_RELATION_TYPE, ThreadEvent } from "../../src/models/thread"; -import { Feature, ServerSupport } from "../../src/feature"; import { emitPromise } from "../test-utils/test-utils"; +import { Feature, ServerSupport } from "../../lib/feature"; const userId = "@alice:localhost"; const userName = "Alice"; @@ -52,11 +52,13 @@ const withoutRoomId = (e: Partial): Partial => { /** * Our httpBackend only allows matching calls if we have the exact same query, in the exact same order * This method allows building queries with the exact same parameter order as the fetchRelations method in client - * @param supports features supported by our client * @param params query parameters */ -const buildRelationPaginationQuery = (supports: Map, params: QueryDict): string => { - return "?" + encodeParams(prefixUnstableParameters(supports, params)).toString(); +const buildRelationPaginationQuery = (params: QueryDict): string => { + if (Thread.hasServerSideFwdPaginationSupport === FeatureSupport.Experimental) { + params = replaceParam("dir", "org.matrix.msc3715.dir", params); + } + return "?" + encodeParams(params).toString(); }; const USER_MEMBERSHIP_EVENT = utils.mkMembership({ @@ -620,7 +622,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { dir: Direction.Backward, limit: 1 }), + buildRelationPaginationQuery({ dir: Direction.Backward, limit: 1 }), ) .respond(200, function () { return { @@ -1234,7 +1236,7 @@ describe("MatrixClient event timelines", function () { // @ts-ignore client.clientOpts.threadSupport = true; - client.canSupport.set(Feature.RelationsRecursion, ServerSupport.Unstable); + client.canSupport.set(Feature.RelationsRecursion, ServerSupport.Stable); Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); @@ -1254,7 +1256,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT_UPDATED.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { + buildRelationPaginationQuery({ recurse: true, dir: Direction.Backward, limit: 3, @@ -1901,7 +1903,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { dir: Direction.Backward, limit: 1 }), + buildRelationPaginationQuery({ dir: Direction.Backward, limit: 1 }), ) .respond(200, function () { return { @@ -1959,7 +1961,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { + buildRelationPaginationQuery({ dir: Direction.Backward, from: "start_token", }), @@ -1976,7 +1978,7 @@ describe("MatrixClient event timelines", function () { encodeURIComponent(THREAD_ROOT.event_id!) + "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + - buildRelationPaginationQuery(client.canSupport, { dir: Direction.Forward, from: "end_token" }), + buildRelationPaginationQuery({ dir: Direction.Forward, from: "end_token" }), ) .respond(200, function () { return { diff --git a/src/client.ts b/src/client.ts index 11fc4cc5a74..c545c2bbd49 100644 --- a/src/client.ts +++ b/src/client.ts @@ -38,7 +38,7 @@ import { Filter, IFilterDefinition, IRoomEventFilter } from "./filter"; import { CallEventHandlerEvent, CallEventHandler, CallEventHandlerEventHandlerMap } from "./webrtc/callEventHandler"; import { GroupCallEventHandlerEvent, GroupCallEventHandlerEventHandlerMap } from "./webrtc/groupCallEventHandler"; import * as utils from "./utils"; -import { QueryDict, sleep, noUnsafeEventProps, safeSet } from "./utils"; +import { replaceParam, QueryDict, sleep, noUnsafeEventProps, safeSet } from "./utils"; import { Direction, EventTimeline } from "./models/event-timeline"; import { IActionsObject, PushProcessor } from "./pushprocessor"; import { AutoDiscovery, AutoDiscoveryAction } from "./autodiscovery"; @@ -7956,7 +7956,13 @@ export class MatrixClient extends TypedEventEmitter { - const params = utils.prefixUnstableParameters(this.canSupport, opts as QueryDict); + let params = opts as QueryDict; + if (Thread.hasServerSideFwdPaginationSupport === FeatureSupport.Experimental) { + params = replaceParam("dir", "org.matrix.msc3715.dir", params); + } + if (this.canSupport.get(Feature.RelationsRecursion) === ServerSupport.Unstable) { + params = replaceParam("recurse", "org.matrix.msc3981.recurse", params); + } const queryString = utils.encodeParams(params); let templatedUrl = "/rooms/$roomId/relations/$eventId"; diff --git a/src/utils.ts b/src/utils.ts index 05c8a63652c..e2b29bdd4d1 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -25,8 +25,6 @@ import { Optional } from "matrix-events-sdk"; import { IEvent, MatrixEvent } from "./models/event"; import { M_TIMESTAMP } from "./@types/location"; import { ReceiptType } from "./@types/read_receipts"; -import { Feature, ServerSupport } from "./feature"; -import { FeatureSupport, Thread } from "./models/thread"; const interns = new Map(); @@ -89,16 +87,6 @@ export function replaceParam(stable: string, unstable: string, dict: QueryDict): return result; } -export function prefixUnstableParameters(supports: Map, params: QueryDict): QueryDict { - if (Thread.hasServerSideFwdPaginationSupport === FeatureSupport.Experimental) { - params = replaceParam("dir", "org.matrix.msc3715.dir", params); - } - if (supports.get(Feature.RelationsRecursion) === ServerSupport.Unstable) { - params = replaceParam("recurse", "org.matrix.msc3981.recurse", params); - } - return params; -} - /** * Decode a query string in `application/x-www-form-urlencoded` format. * @param query - A query string to decode e.g. From d0129a63bab0303c31a13a66b3b1de944684dc93 Mon Sep 17 00:00:00 2001 From: Janne Mareike Koschinski Date: Thu, 27 Apr 2023 14:05:54 +0200 Subject: [PATCH 9/9] Fix broken tests --- spec/integ/matrix-client-event-timeline.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index 142dd18a02c..bb4e9563431 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -35,7 +35,7 @@ import { encodeParams, encodeUri, QueryDict, replaceParam } from "../../src/util import { TestClient } from "../TestClient"; import { FeatureSupport, Thread, THREAD_RELATION_TYPE, ThreadEvent } from "../../src/models/thread"; import { emitPromise } from "../test-utils/test-utils"; -import { Feature, ServerSupport } from "../../lib/feature"; +import { Feature, ServerSupport } from "../../src/feature"; const userId = "@alice:localhost"; const userName = "Alice"; @@ -1257,9 +1257,9 @@ describe("MatrixClient event timelines", function () { "/" + encodeURIComponent(THREAD_RELATION_TYPE.name) + buildRelationPaginationQuery({ - recurse: true, dir: Direction.Backward, limit: 3, + recurse: true, }), ) .respond(200, {