From b0dc8ce6b20c53299e548e1eb998afbd986ec1b4 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Thu, 4 Aug 2022 15:14:24 +0200 Subject: [PATCH] Add an action to read relations according to MSC3869 Signed-off-by: Dominik Henneke --- src/stores/widgets/StopGapWidgetDriver.ts | 43 ++++++ .../widgets/StopGapWidgetDriver-test.ts | 124 +++++++++++++++++- 2 files changed, 165 insertions(+), 2 deletions(-) diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 8fe18dbc8c05..7a19676453c5 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -37,6 +37,7 @@ import { IContent, IEvent, MatrixEvent } from "matrix-js-sdk/src/models/event"; import { Room } from "matrix-js-sdk/src/models/room"; import { logger } from "matrix-js-sdk/src/logger"; import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread"; +import { Direction } from "matrix-js-sdk/src/matrix"; import { iterableDiff, iterableIntersection } from "../../utils/iterables"; import { MatrixClientPeg } from "../../MatrixClientPeg"; @@ -271,6 +272,48 @@ export class StopGapWidgetDriver extends WidgetDriver { return allResults; } + public async readEventRelations( + eventId: string, + roomId?: string, + relationType?: string, + eventType?: string, + from?: string, + to?: string, + limit?: number, + direction?: 'f' | 'b', + ): Promise<{ originalEvent?: IRoomEvent, chunk: IRoomEvent[], nextBatch?: string, prevBatch?: string }> { + const client = MatrixClientPeg.get(); + const dir = + Object.values(Direction as Record).includes(direction) + ? direction as Direction + : undefined; + const room = roomId !== undefined ? roomId : RoomViewStore.instance.getRoomId(); + + const { + originalEvent, + events, + nextBatch, + prevBatch, + } = await client.relations( + room, + eventId, + relationType ?? null, + eventType ?? null, + { + from, + to, + limit, + direction: dir, + }); + + return { + originalEvent: originalEvent?.getEffectiveEvent(), + chunk: events.map(e => e.getEffectiveEvent()), + nextBatch, + prevBatch, + }; + } + public async readStateEvents( eventType: string, stateKey: string | undefined, diff --git a/test/stores/widgets/StopGapWidgetDriver-test.ts b/test/stores/widgets/StopGapWidgetDriver-test.ts index 790462942821..d6f857bc4a2c 100644 --- a/test/stores/widgets/StopGapWidgetDriver-test.ts +++ b/test/stores/widgets/StopGapWidgetDriver-test.ts @@ -15,11 +15,13 @@ limitations under the License. */ import { mocked, MockedObject } from "jest-mock"; -import { Widget, WidgetKind, WidgetDriver, ITurnServer } from "matrix-widget-api"; -import { MatrixClient, ClientEvent, ITurnServer as IClientTurnServer } from "matrix-js-sdk/src/client"; +import { ClientEvent, ITurnServer as IClientTurnServer, MatrixClient } from "matrix-js-sdk/src/client"; import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; +import { Direction, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { ITurnServer, Widget, WidgetDriver, WidgetKind } from "matrix-widget-api"; import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; +import { RoomViewStore } from "../../../src/stores/RoomViewStore"; import { StopGapWidgetDriver } from "../../../src/stores/widgets/StopGapWidgetDriver"; import { stubClient } from "../../test-utils"; @@ -131,4 +133,122 @@ describe("StopGapWidgetDriver", () => { await servers.return(undefined); }); }); + + describe("readEventRelations", () => { + it('reads related events from the current room', async () => { + jest.spyOn(RoomViewStore.instance, 'getRoomId').mockReturnValue('!this-room-id'); + + client.relations.mockResolvedValue({ + originalEvent: undefined, + events: [], + }); + + await expect(driver.readEventRelations('$event')).resolves.toEqual({ + originalEvent: undefined, + chunk: [], + nextBatch: undefined, + prevBatch: undefined, + }); + + expect(client.relations).toBeCalledWith('!this-room-id', '$event', null, null, {}); + }); + + it('reads related events if the original event is missing', async () => { + client.relations.mockResolvedValue({ + originalEvent: undefined, + events: [], + }); + + await expect(driver.readEventRelations('$event', '!room-id')).resolves.toEqual({ + originalEvent: undefined, + chunk: [], + nextBatch: undefined, + prevBatch: undefined, + }); + + expect(client.relations).toBeCalledWith('!room-id', '$event', null, null, {}); + }); + + it('reads related events from a selected room', async () => { + client.relations.mockResolvedValue({ + originalEvent: new MatrixEvent(), + events: [new MatrixEvent(), new MatrixEvent()], + nextBatch: 'next-batch-token', + }); + + await expect(driver.readEventRelations('$event', '!room-id')).resolves.toEqual({ + originalEvent: expect.objectContaining({ content: {} }), + chunk: [ + expect.objectContaining({ content: {} }), + expect.objectContaining({ content: {} }), + ], + nextBatch: 'next-batch-token', + prevBatch: undefined, + }); + + expect(client.relations).toBeCalledWith('!room-id', '$event', null, null, {}); + }); + + it('reads related events with custom parameters', async () => { + client.relations.mockResolvedValue({ + originalEvent: new MatrixEvent(), + events: [], + }); + + await expect(driver.readEventRelations( + '$event', + '!room-id', + 'm.reference', + 'm.room.message', + 'from-token', + 'to-token', + 25, + 'f', + )).resolves.toEqual({ + originalEvent: expect.objectContaining({ content: {} }), + chunk: [], + nextBatch: undefined, + prevBatch: undefined, + }); + + expect(client.relations).toBeCalledWith( + '!room-id', + '$event', + 'm.reference', + 'm.room.message', + { + limit: 25, + from: 'from-token', + to: 'to-token', + direction: Direction.Forward, + }, + ); + }); + + it('should ignore invalid direction', async () => { + client.relations.mockResolvedValue({ + originalEvent: new MatrixEvent(), + events: [], + }); + + await driver.readEventRelations( + '$event', + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + 'q' as any, + ); + + expect(client.relations).toBeCalledWith( + '!this-room-id', + '$event', + null, + null, + { direction: undefined }, + ); + }); + }); });