diff --git a/spec/integ/matrix-client-event-timeline.spec.ts b/spec/integ/matrix-client-event-timeline.spec.ts index 0c553e77f..dbcb48acd 100644 --- a/spec/integ/matrix-client-event-timeline.spec.ts +++ b/spec/integ/matrix-client-event-timeline.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +Copyright 2022 - 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. @@ -590,7 +590,7 @@ describe("MatrixClient event timelines", function () { it("should handle thread replies with server support by fetching a contiguous thread timeline", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); await client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId)!; @@ -647,7 +647,7 @@ describe("MatrixClient event timelines", function () { it("should return relevant timeline from non-thread timelineSet when asking for the thread root", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId)!; @@ -680,7 +680,7 @@ describe("MatrixClient event timelines", function () { it("should return undefined when event is not in the thread that the given timelineSet is representing", () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId)!; @@ -709,7 +709,7 @@ describe("MatrixClient event timelines", function () { it("should return undefined when event is within a thread but timelineSet is not", () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); client.stopClient(); // we don't need the client to be syncing at this time const room = client.getRoom(roomId)!; @@ -1127,7 +1127,7 @@ describe("MatrixClient event timelines", function () { }; // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); @@ -1263,7 +1263,7 @@ describe("MatrixClient event timelines", function () { describe("with server compatibility", function () { beforeEach(() => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); @@ -1421,7 +1421,7 @@ describe("MatrixClient event timelines", function () { }; // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); @@ -1473,7 +1473,7 @@ describe("MatrixClient event timelines", function () { describe("without server compatibility", function () { beforeEach(() => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); Thread.setServerSideListSupport(FeatureSupport.None); }); @@ -1539,7 +1539,7 @@ describe("MatrixClient event timelines", function () { it("should add lazy loading filter", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); Thread.setServerSideListSupport(FeatureSupport.Stable); // @ts-ignore @@ -1567,7 +1567,7 @@ describe("MatrixClient event timelines", function () { it("should correctly pass pagination token", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); Thread.setServerSideListSupport(FeatureSupport.Stable); @@ -1892,7 +1892,7 @@ describe("MatrixClient event timelines", function () { it("in stable mode", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); @@ -1902,7 +1902,7 @@ describe("MatrixClient event timelines", function () { it("in backwards compatible unstable mode", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); Thread.setServerSideListSupport(FeatureSupport.Experimental); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Experimental); @@ -1912,7 +1912,7 @@ describe("MatrixClient event timelines", function () { it("in backwards compatible mode", async () => { // @ts-ignore - client.clientOpts.experimentalThreadSupport = true; + client.clientOpts.threadSupport = true; Thread.setServerSideSupport(FeatureSupport.Experimental); Thread.setServerSideListSupport(FeatureSupport.None); Thread.setServerSideFwdPaginationSupport(FeatureSupport.None); diff --git a/spec/integ/matrix-client-methods.spec.ts b/spec/integ/matrix-client-methods.spec.ts index 01e24ded4..c5ea7fe5d 100644 --- a/spec/integ/matrix-client-methods.spec.ts +++ b/spec/integ/matrix-client-methods.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +Copyright 2022 - 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. @@ -35,7 +35,7 @@ describe("MatrixClient", function () { let store: MemoryStore | undefined; const defaultClientOpts: IStoredClientOpts = { - experimentalThreadSupport: false, + threadSupport: false, }; const setupTests = (): [MatrixClient, HttpBackend, MemoryStore] => { const store = new MemoryStore(); @@ -671,7 +671,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const eventPollResponseReference = buildEventPollResponseReference(); @@ -702,7 +702,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const eventPollStartThreadRoot = buildEventPollStartThreadRoot(); @@ -726,7 +726,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const eventPollResponseReference = buildEventPollResponseReference(); @@ -750,7 +750,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const eventPollStartThreadRoot = buildEventPollStartThreadRoot(); @@ -774,7 +774,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; // This is based on recording the events in a real room: @@ -831,7 +831,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const threadRootEvent = buildEventPollStartThreadRoot(); @@ -857,7 +857,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const threadRootEvent = buildEventPollStartThreadRoot(); @@ -878,7 +878,7 @@ describe("MatrixClient", function () { // @ts-ignore setting private property client!.clientOpts = { ...defaultClientOpts, - experimentalThreadSupport: true, + threadSupport: true, }; const threadRootEvent = buildEventPollStartThreadRoot(); diff --git a/spec/test-utils/webrtc.ts b/spec/test-utils/webrtc.ts index ed6e408ab..8bc8825a4 100644 --- a/spec/test-utils/webrtc.ts +++ b/spec/test-utils/webrtc.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +Copyright 2022 - 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. @@ -476,7 +476,7 @@ export class MockCallMatrixClient extends TypedEventEmitter().mockReturnValue([]); public getRoom = jest.fn(); - public supportsExperimentalThreads(): boolean { + public supportsThreads(): boolean { return true; } public async decryptEventIfNeeded(): Promise {} diff --git a/spec/unit/event-timeline-set.spec.ts b/spec/unit/event-timeline-set.spec.ts index 05b80fe57..6322289f0 100644 --- a/spec/unit/event-timeline-set.spec.ts +++ b/spec/unit/event-timeline-set.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +Copyright 2022 - 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. @@ -147,7 +147,7 @@ describe("EventTimelineSet", () => { let thread: Thread; beforeEach(() => { - (client.supportsExperimentalThreads as jest.Mock).mockReturnValue(true); + (client.supportsThreads as jest.Mock).mockReturnValue(true); thread = new Thread("!thread_id:server", messageEvent, { room, client }); }); @@ -206,7 +206,7 @@ describe("EventTimelineSet", () => { }); it("should allow edits to be added to thread timeline", async () => { - jest.spyOn(client, "supportsExperimentalThreads").mockReturnValue(true); + jest.spyOn(client, "supportsThreads").mockReturnValue(true); jest.spyOn(client, "getEventMapper").mockReturnValue(eventMapperFor(client, {})); Thread.hasServerSideSupport = FeatureSupport.Stable; @@ -393,7 +393,7 @@ describe("EventTimelineSet", () => { let thread: Thread; beforeEach(() => { - (client.supportsExperimentalThreads as jest.Mock).mockReturnValue(true); + (client.supportsThreads as jest.Mock).mockReturnValue(true); thread = new Thread("!thread_id:server", messageEvent, { room, client }); }); diff --git a/spec/unit/matrix-client.spec.ts b/spec/unit/matrix-client.spec.ts index 24d3fed77..e78d2eab1 100644 --- a/spec/unit/matrix-client.spec.ts +++ b/spec/unit/matrix-client.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2022 The Matrix.org Foundation C.I.C. +Copyright 2022 - 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. @@ -17,7 +17,7 @@ limitations under the License. import { mocked } from "jest-mock"; import { logger } from "../../src/logger"; -import { ClientEvent, ITurnServerResponse, MatrixClient, Store } from "../../src/client"; +import { ClientEvent, IMatrixClientCreateOpts, ITurnServerResponse, MatrixClient, Store } from "../../src/client"; import { Filter } from "../../src/filter"; import { DEFAULT_TREE_POWER_LEVELS_TEMPLATE } from "../../src/models/MSC3089TreeSpace"; import { @@ -276,7 +276,7 @@ describe("MatrixClient", function () { ); } - function makeClient() { + function makeClient(opts?: Partial) { client = new MatrixClient({ baseUrl: "https://my.home.server", idBaseUrl: identityServerUrl, @@ -285,6 +285,7 @@ describe("MatrixClient", function () { store: store, scheduler: scheduler, userId: userId, + ...(opts || {}), }); // FIXME: We shouldn't be yanking http like this. client.http = (["authedRequest", "getContentUri", "request", "uploadContent"] as const).reduce((r, k) => { @@ -1456,9 +1457,20 @@ describe("MatrixClient", function () { }); describe("threads", () => { + it.each([ + { startOpts: {}, hasThreadSupport: false }, + { startOpts: { threadSupport: true }, hasThreadSupport: true }, + { startOpts: { threadSupport: false }, hasThreadSupport: false }, + { startOpts: { experimentalThreadSupport: true }, hasThreadSupport: true }, + { startOpts: { experimentalThreadSupport: true, threadSupport: false }, hasThreadSupport: false }, + ])("enabled thread support for the SDK instance ", async ({ startOpts, hasThreadSupport }) => { + await client.startClient(startOpts); + expect(client.supportsThreads()).toBe(hasThreadSupport); + }); + it("partitions root events to room timeline and thread timeline", () => { - const supportsExperimentalThreads = client.supportsExperimentalThreads; - client.supportsExperimentalThreads = () => true; + const supportsThreads = client.supportsThreads; + client.supportsThreads = () => true; const room = new Room("!room1:matrix.org", client, userId); const rootEvent = new MatrixEvent({ @@ -1487,7 +1499,7 @@ describe("MatrixClient", function () { expect(threadEvents).toHaveLength(1); // Restore method - client.supportsExperimentalThreads = supportsExperimentalThreads; + client.supportsThreads = supportsThreads; }); }); diff --git a/spec/unit/models/thread.spec.ts b/spec/unit/models/thread.spec.ts index 4dd5a681b..0583bf391 100644 --- a/spec/unit/models/thread.spec.ts +++ b/spec/unit/models/thread.spec.ts @@ -84,7 +84,7 @@ describe("Thread", () => { ...mockClientMethodsUser(), getRoom: jest.fn().mockImplementation(() => room), decryptEventIfNeeded: jest.fn().mockResolvedValue(void 0), - supportsExperimentalThreads: jest.fn().mockReturnValue(true), + supportsThreads: jest.fn().mockReturnValue(true), }); client.reEmitter = mock(ReEmitter, "ReEmitter"); client.canSupport = new Map(); @@ -195,7 +195,7 @@ describe("Thread", () => { ...mockClientMethodsUser(), getRoom: jest.fn().mockImplementation(() => room), decryptEventIfNeeded: jest.fn().mockResolvedValue(void 0), - supportsExperimentalThreads: jest.fn().mockReturnValue(true), + supportsThreads: jest.fn().mockReturnValue(true), }); client.reEmitter = mock(ReEmitter, "ReEmitter"); client.canSupport = new Map(); diff --git a/spec/unit/notifications.spec.ts b/spec/unit/notifications.spec.ts index 594740e28..aefe5777a 100644 --- a/spec/unit/notifications.spec.ts +++ b/spec/unit/notifications.spec.ts @@ -56,7 +56,7 @@ describe("fixNotificationCountOnDecryption", () => { getPushActionsForEvent: jest.fn().mockReturnValue(mkPushAction(true, true)), getRoom: jest.fn().mockImplementation(() => room), decryptEventIfNeeded: jest.fn().mockResolvedValue(void 0), - supportsExperimentalThreads: jest.fn().mockReturnValue(true), + supportsThreads: jest.fn().mockReturnValue(true), }); mockClient.reEmitter = mock(ReEmitter, "ReEmitter"); mockClient.canSupport = new Map(); diff --git a/spec/unit/room.spec.ts b/spec/unit/room.spec.ts index fb5aca126..83ae123ff 100644 --- a/spec/unit/room.spec.ts +++ b/spec/unit/room.spec.ts @@ -1,5 +1,5 @@ /* -Copyright 2022, 2023 The Matrix.org Foundation C.I.C. +Copyright 2022 - 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. @@ -1624,7 +1624,7 @@ describe("Room", function () { describe("addPendingEvent", function () { it("should add pending events to the pendingEventList if " + "pendingEventOrdering == 'detached'", function () { const client = new TestClient("@alice:example.com", "alicedevice").client; - client.supportsExperimentalThreads = () => true; + client.supportsThreads = () => true; const room = new Room(roomId, client, userA, { pendingEventOrdering: PendingEventOrdering.Detached, }); @@ -2470,7 +2470,7 @@ describe("Room", function () { }); it("Edits update the lastReply event", async () => { - room.client.supportsExperimentalThreads = () => true; + room.client.supportsThreads = () => true; Thread.setServerSideSupport(FeatureSupport.Stable); const randomMessage = mkMessage(); @@ -2541,7 +2541,7 @@ describe("Room", function () { }); it("Redactions to thread responses decrement the length", async () => { - room.client.supportsExperimentalThreads = () => true; + room.client.supportsThreads = () => true; Thread.setServerSideSupport(FeatureSupport.Stable); const threadRoot = mkMessage(); @@ -2608,7 +2608,7 @@ describe("Room", function () { }); it("Redactions to reactions in threads do not decrement the length", async () => { - room.client.supportsExperimentalThreads = () => true; + room.client.supportsThreads = () => true; Thread.setServerSideSupport(FeatureSupport.Stable); const threadRoot = mkMessage(); @@ -2648,7 +2648,7 @@ describe("Room", function () { }); it("should not decrement the length when the thread root is redacted", async () => { - room.client.supportsExperimentalThreads = () => true; + room.client.supportsThreads = () => true; Thread.setServerSideSupport(FeatureSupport.Stable); const threadRoot = mkMessage(); @@ -2689,7 +2689,7 @@ describe("Room", function () { }); it("Redacting the lastEvent finds a new lastEvent", async () => { - room.client.supportsExperimentalThreads = () => true; + room.client.supportsThreads = () => true; Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable); @@ -2796,7 +2796,7 @@ describe("Room", function () { describe("eventShouldLiveIn", () => { const client = new TestClient(userA).client; - client.supportsExperimentalThreads = () => true; + client.supportsThreads = () => true; Thread.setServerSideSupport(FeatureSupport.Stable); const room = new Room(roomId, client, userA); @@ -3307,7 +3307,7 @@ describe("Room", function () { beforeEach(() => { client = getMockClientWithEventEmitter({ ...mockClientMethodsUser(), - supportsExperimentalThreads: jest.fn().mockReturnValue(true), + supportsThreads: jest.fn().mockReturnValue(true), }); }); diff --git a/src/client.ts b/src/client.ts index 70ee1be6f..22a0a1d06 100644 --- a/src/client.ts +++ b/src/client.ts @@ -1,5 +1,5 @@ /* -Copyright 2015-2022 The Matrix.org Foundation C.I.C. +Copyright 2015-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. @@ -446,10 +446,16 @@ export interface IStartClientOpts { clientWellKnownPollPeriod?: number; /** - * @experimental + * @deprecated use `threadSupport` instead */ experimentalThreadSupport?: boolean; + /** + * Will organises events in threaded conversations when + * a thread relation is encountered + */ + threadSupport?: boolean; + /** * @experimental */ @@ -1448,6 +1454,19 @@ export class MatrixClient extends TypedEventEmitter { - if (!this.supportsExperimentalThreads()) { + if (!this.supportsThreads()) { throw new Error("could not get thread timeline: no client support"); } @@ -9337,12 +9356,21 @@ export class MatrixClient extends TypedEventEmitter(THREAD_RELATION_TYPE.name); @@ -1557,7 +1555,8 @@ export class MatrixEvent extends TypedEventEmitter { public readonly relations = new RelationsContainer(this.client, this); /** - * @experimental + * A collection of events known by the client + * This is not a comprehensive list of the threads that exist in this room */ private threads = new Map(); public lastThread?: Thread; @@ -483,7 +484,7 @@ export class Room extends ReadReceipt { return this.threadTimelineSetsPromise; } - if (this.client?.supportsExperimentalThreads()) { + if (this.client?.supportsThreads()) { try { this.threadTimelineSetsPromise = Promise.all([ this.createThreadTimelineSet(), @@ -1330,7 +1331,6 @@ export class Room extends ReadReceipt { } /** - * @experimental * Get one of the notification counts for a thread * @param threadId - the root event ID * @param type - The type of notification count to get. default: 'total' @@ -1342,7 +1342,6 @@ export class Room extends ReadReceipt { } /** - * @experimental * Checks if the current room has unread thread notifications * @returns */ @@ -1356,7 +1355,6 @@ export class Room extends ReadReceipt { } /** - * @experimental * Swet one of the notification count for a thread * @param threadId - the root event ID * @param type - The type of notification count to get. default: 'total' @@ -1377,7 +1375,6 @@ export class Room extends ReadReceipt { } /** - * @experimental * @returns the notification count type for all the threads in the room */ public get threadsAggregateNotificationType(): NotificationCountType | null { @@ -1393,7 +1390,6 @@ export class Room extends ReadReceipt { } /** - * @experimental * Resets the thread notifications for this room */ public resetThreadUnreadNotificationCount(notificationsToKeep?: string[]): void { @@ -1553,14 +1549,16 @@ export class Room extends ReadReceipt { } /** - * @experimental + * Get the instance of the thread associated with the current event + * @param eventId - the ID of the current event + * @returns a thread instance if known */ public getThread(eventId: string): Thread | null { return this.threads.get(eventId) ?? null; } /** - * @experimental + * Get all the known threads in the room */ public getThreads(): Thread[] { return Array.from(this.threads.values()); @@ -1827,7 +1825,7 @@ export class Room extends ReadReceipt { * Without server support that means fetching as much at once as the server allows us to. */ public async fetchRoomThreads(): Promise { - if (this.threadsReady || !this.client.supportsExperimentalThreads()) { + if (this.threadsReady || !this.client.supportsThreads()) { return; } @@ -2004,7 +2002,7 @@ export class Room extends ReadReceipt { shouldLiveInThread: boolean; threadId?: string; } { - if (!this.client?.supportsExperimentalThreads()) { + if (!this.client?.supportsThreads()) { return { shouldLiveInRoom: true, shouldLiveInThread: false, @@ -2073,7 +2071,6 @@ export class Room extends ReadReceipt { /** * Adds events to a thread's timeline. Will fire "Thread.update" - * @experimental */ public processThreadedEvents(events: MatrixEvent[], toStartOfTimeline: boolean): void { events.forEach(this.applyRedaction); @@ -2702,7 +2699,7 @@ export class Room extends ReadReceipt { // Indices to the events array, for readability const ROOM = 0; const THREAD = 1; - if (this.client.supportsExperimentalThreads()) { + if (this.client.supportsThreads()) { const threadRoots = this.findThreadRoots(events); return events.reduce( (memo, event: MatrixEvent) => { diff --git a/src/models/thread.ts b/src/models/thread.ts index b688d12ac..e6420a659 100644 --- a/src/models/thread.ts +++ b/src/models/thread.ts @@ -69,9 +69,6 @@ export function determineFeatureSupport(stable: boolean, unstable: boolean): Fea } } -/** - * @experimental - */ export class Thread extends ReadReceipt { public static hasServerSideSupport = FeatureSupport.None; public static hasServerSideListSupport = FeatureSupport.None; diff --git a/src/sync.ts b/src/sync.ts index 11fe3cc10..81892e64f 100644 --- a/src/sync.ts +++ b/src/sync.ts @@ -1,5 +1,5 @@ /* -Copyright 2015 - 2022 The Matrix.org Foundation C.I.C. +Copyright 2015 - 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. @@ -198,7 +198,7 @@ export function defaultClientOpts(opts?: IStoredClientOpts): IStoredClientOpts { resolveInvitesToProfiles: false, pollTimeout: 30 * 1000, pendingEventOrdering: PendingEventOrdering.Chronological, - experimentalThreadSupport: false, + threadSupport: false, ...opts, }; }