Implement MSC3869: Read event relations with the Widget API (#9210)

* Add an action to read relations according to MSC3869

Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>

* Apply review comments

Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>

* Fix test

Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>

* Update matrix-widget-api to 1.1.1

Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>

Signed-off-by: Dominik Henneke <dominik.henneke@nordeck.net>
This commit is contained in:
Dominik Henneke 2022-09-14 16:18:51 +02:00 committed by GitHub
parent f20d86b7b8
commit 0c22b15bba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 148 additions and 7 deletions

View file

@ -94,7 +94,7 @@
"matrix-encrypt-attachment": "^1.0.3", "matrix-encrypt-attachment": "^1.0.3",
"matrix-events-sdk": "^0.0.1-beta.7", "matrix-events-sdk": "^0.0.1-beta.7",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-widget-api": "^1.0.0", "matrix-widget-api": "^1.1.1",
"minimist": "^1.2.5", "minimist": "^1.2.5",
"opus-recorder": "^8.0.3", "opus-recorder": "^8.0.3",
"pako": "^2.0.3", "pako": "^2.0.3",

View file

@ -21,6 +21,7 @@ import {
IOpenIDUpdate, IOpenIDUpdate,
ISendEventDetails, ISendEventDetails,
ITurnServer, ITurnServer,
IReadEventRelationsResult,
IRoomEvent, IRoomEvent,
MatrixCapabilities, MatrixCapabilities,
OpenIDRequestState, OpenIDRequestState,
@ -37,6 +38,7 @@ import { IContent, IEvent, MatrixEvent } from "matrix-js-sdk/src/models/event";
import { Room } from "matrix-js-sdk/src/models/room"; import { Room } from "matrix-js-sdk/src/models/room";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { THREAD_RELATION_TYPE } from "matrix-js-sdk/src/models/thread"; 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 { iterableDiff, iterableIntersection } from "../../utils/iterables";
import { MatrixClientPeg } from "../../MatrixClientPeg"; import { MatrixClientPeg } from "../../MatrixClientPeg";
@ -366,4 +368,47 @@ export class StopGapWidgetDriver extends WidgetDriver {
client.off(ClientEvent.TurnServersError, onTurnServersError); client.off(ClientEvent.TurnServersError, onTurnServersError);
} }
} }
public async readEventRelations(
eventId: string,
roomId?: string,
relationType?: string,
eventType?: string,
from?: string,
to?: string,
limit?: number,
direction?: 'f' | 'b',
): Promise<IReadEventRelationsResult> {
const client = MatrixClientPeg.get();
const dir = direction as Direction;
roomId = roomId ?? RoomViewStore.instance.getRoomId() ?? undefined;
if (typeof roomId !== "string") {
throw new Error('Error while reading the current room');
}
const {
originalEvent,
events,
nextBatch,
prevBatch,
} = await client.relations(
roomId,
eventId,
relationType ?? null,
eventType ?? null,
{
from,
to,
limit,
direction: dir,
});
return {
originalEvent: originalEvent?.getEffectiveEvent(),
chunk: events.map(e => e.getEffectiveEvent()),
nextBatch,
prevBatch,
};
}
} }

View file

@ -15,11 +15,13 @@ limitations under the License.
*/ */
import { mocked, MockedObject } from "jest-mock"; import { mocked, MockedObject } from "jest-mock";
import { Widget, WidgetKind, WidgetDriver, ITurnServer } from "matrix-widget-api"; import { ClientEvent, ITurnServer as IClientTurnServer, MatrixClient } from "matrix-js-sdk/src/client";
import { MatrixClient, ClientEvent, ITurnServer as IClientTurnServer } from "matrix-js-sdk/src/client";
import { DeviceInfo } from "matrix-js-sdk/src/crypto/deviceinfo"; 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 { MatrixClientPeg } from "../../../src/MatrixClientPeg";
import { RoomViewStore } from "../../../src/stores/RoomViewStore";
import { StopGapWidgetDriver } from "../../../src/stores/widgets/StopGapWidgetDriver"; import { StopGapWidgetDriver } from "../../../src/stores/widgets/StopGapWidgetDriver";
import { stubClient } from "../../test-utils"; import { stubClient } from "../../test-utils";
@ -131,4 +133,98 @@ describe("StopGapWidgetDriver", () => {
await servers.return(undefined); 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: new MatrixEvent(),
events: [],
});
await expect(driver.readEventRelations('$event')).resolves.toEqual({
originalEvent: expect.objectContaining({ content: {} }),
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({
// the relations function can return an undefined event, even
// though the typings don't permit an undefined value.
originalEvent: undefined as any,
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,
},
);
});
});
}); });

View file

@ -6815,10 +6815,10 @@ matrix-web-i18n@^1.3.0:
"@babel/traverse" "^7.18.5" "@babel/traverse" "^7.18.5"
walk "^2.3.15" walk "^2.3.15"
matrix-widget-api@^1.0.0: matrix-widget-api@^1.1.1:
version "1.0.0" version "1.1.1"
resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.0.0.tgz#0cde6839cca66ad817ab12aca3490ccc8bac97d1" resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.1.1.tgz#d3fec45033d0cbc14387a38ba92dac4dbb1be962"
integrity sha512-cy8p/8EteRPTFIAw7Q9EgPUJc2jD19ZahMR8bMKf2NkILDcjuPMC0UWnsJyB3fSnlGw+VbGepttRpULM31zX8Q== integrity sha512-gNSgmgSwvOsOcWK9k2+tOhEMYBiIMwX95vMZu0JqY7apkM02xrOzUBuPRProzN8CnbIALH7e3GAhatF6QCNvtA==
dependencies: dependencies:
"@types/events" "^3.0.0" "@types/events" "^3.0.0"
events "^3.2.0" events "^3.2.0"