Skip to content

Commit 9cf15e4

Browse files
committed
Check for MSC2762_UPDATE_STATE version to decide if read_event (state events) reads from the state or the timeline
1 parent 71b14fc commit 9cf15e4

File tree

2 files changed

+90
-28
lines changed

2 files changed

+90
-28
lines changed

src/ClientWidgetApi.ts

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ export class ClientWidgetApi extends EventEmitter {
354354
});
355355
}
356356

357+
private async supportsUpdateState(): Promise<boolean> {
358+
return (await this.getWidgetVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE);
359+
}
360+
357361
private handleCapabilitiesRenegotiate(request: IRenegotiateCapabilitiesActionRequest): void {
358362
// acknowledge first
359363
this.transport.reply<IWidgetApiAcknowledgeResponseData>(request, {});
@@ -527,34 +531,43 @@ export class ClientWidgetApi extends EventEmitter {
527531
}
528532
}
529533

530-
// For backwards compatibility we still call the deprecated
531-
// readRoomEvents and readStateEvents methods in case the client isn't
532-
// letting us know the currently viewed room via setViewedRoomId
533-
const events =
534-
request.data.room_ids === undefined && askRoomIds.length === 0
535-
? await // This returns [] with the current driver of Element Web.
536-
// Add default implementations of the `readRoomEvents` and `readStateEvents`
537-
// methods to use `readRoomTimeline` and `readRoomState` if they are not overwritten.
538-
(request.data.state_key === undefined
539-
? this.driver.readRoomEvents(request.data.type, msgtype, limit, null, since)
540-
: this.driver.readStateEvents(request.data.type, stateKey, limit, null))
541-
: (request.data.state_key === undefined
542-
? await Promise.all(
543-
askRoomIds.map((roomId) =>
544-
this.driver.readRoomTimeline(
545-
roomId,
546-
request.data.type,
547-
msgtype,
548-
stateKey,
549-
limit,
550-
since,
551-
),
552-
),
553-
)
554-
: await Promise.all(
555-
askRoomIds.map((roomId) => this.driver.readRoomState(roomId, request.data.type, stateKey)),
556-
)
557-
).flat(1);
534+
let events: IRoomEvent[];
535+
536+
if (request.data.room_ids === undefined && askRoomIds.length === 0) {
537+
// For backwards compatibility we still call the deprecated
538+
// readRoomEvents and readStateEvents methods in case the client isn't
539+
// letting us know the currently viewed room via setViewedRoomId
540+
events = await // This returns [] with the current driver of Element Web.
541+
// Add default implementations of the `readRoomEvents` and `readStateEvents`
542+
// methods to use `readRoomTimeline` and `readRoomState` if they are not overwritten.
543+
(request.data.state_key === undefined
544+
? this.driver.readRoomEvents(request.data.type, msgtype, limit, null, since)
545+
: this.driver.readStateEvents(request.data.type, stateKey, limit, null));
546+
} else if (await this.supportsUpdateState()) {
547+
// Calling read_events with a stateKey still reads from the rooms timeline (not the room state).
548+
events = (
549+
await Promise.all(
550+
askRoomIds.map((roomId) =>
551+
this.driver.readRoomTimeline(roomId, request.data.type, msgtype, stateKey, limit, since),
552+
),
553+
)
554+
).flat(1);
555+
} else {
556+
// TODO: remove this once `UnstableApiVersion.MSC2762_UPDATE_STATE` becomes stable.
557+
// Before version `MSC2762_UPDATE_STATE` we used readRoomState for read_events actions.
558+
events = (
559+
request.data.state_key === undefined
560+
? await Promise.all(
561+
askRoomIds.map((roomId) =>
562+
this.driver.readRoomTimeline(roomId, request.data.type, msgtype, stateKey, limit, since),
563+
),
564+
)
565+
: await Promise.all(
566+
askRoomIds.map((roomId) => this.driver.readRoomState(roomId, request.data.type, stateKey)),
567+
)
568+
).flat(1);
569+
}
570+
558571
this.transport.reply<IReadEventFromWidgetResponseData>(request, { events });
559572
}
560573

test/ClientWidgetApi-test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,7 @@ describe("ClientWidgetApi", () => {
14371437
describe("org.matrix.msc2876.read_events action", () => {
14381438
it("reads events from a specific room", async () => {
14391439
const roomId = "!room:example.org";
1440+
jest.spyOn(clientWidgetApi, "getWidgetVersions").mockReturnValue(new Promise((r) => r([])));
14401441
const event = createRoomEvent({ room_id: roomId, type: "net.example.test", content: "test" });
14411442
driver.readRoomTimeline.mockImplementation(async (rId) => {
14421443
if (rId === roomId) return [event];
@@ -1481,6 +1482,7 @@ describe("ClientWidgetApi", () => {
14811482
it("reads events from all rooms", async () => {
14821483
const roomId = "!room:example.org";
14831484
const otherRoomId = "!other-room:example.org";
1485+
jest.spyOn(clientWidgetApi, "getWidgetVersions").mockReturnValue(new Promise((r) => r([])));
14841486
const event = createRoomEvent({ room_id: roomId, type: "net.example.test", content: "test" });
14851487
const otherRoomEvent = createRoomEvent({ room_id: otherRoomId, type: "net.example.test", content: "hi" });
14861488
driver.getKnownRooms.mockReturnValue([roomId, otherRoomId]);
@@ -1534,6 +1536,7 @@ describe("ClientWidgetApi", () => {
15341536
});
15351537

15361538
it("reads state events with any state key", async () => {
1539+
jest.spyOn(clientWidgetApi, "getWidgetVersions").mockReturnValue(new Promise((r) => r([])));
15371540
driver.readRoomState.mockResolvedValue([
15381541
createRoomEvent({ type: "net.example.test", state_key: "A" }),
15391542
createRoomEvent({ type: "net.example.test", state_key: "B" }),
@@ -1593,6 +1596,7 @@ describe("ClientWidgetApi", () => {
15931596
});
15941597

15951598
it("reads state events with a specific state key", async () => {
1599+
jest.spyOn(clientWidgetApi, "getWidgetVersions").mockReturnValue(new Promise((r) => r([])));
15961600
driver.readRoomState.mockResolvedValue([createRoomEvent({ type: "net.example.test", state_key: "B" })]);
15971601

15981602
const event: IReadEventFromWidgetActionRequest = {
@@ -1620,6 +1624,51 @@ describe("ClientWidgetApi", () => {
16201624
expect(driver.readRoomState).toHaveBeenLastCalledWith("!room-id", "net.example.test", "B");
16211625
});
16221626

1627+
it("reads state events with a specific state key from the timeline when using UnstableApiVersion.MSC2762_UPDATE_STATE", async () => {
1628+
jest.spyOn(clientWidgetApi, "getWidgetVersions").mockReturnValue(new Promise((r) => r(CurrentApiVersions)));
1629+
// with version MSC2762_UPDATE_STATE we wan the read Events action to read state events from the timeline.
1630+
driver.readRoomTimeline.mockResolvedValue([createRoomEvent({ type: "net.example.test", state_key: "B" })]);
1631+
1632+
const event: IReadEventFromWidgetActionRequest = {
1633+
api: WidgetApiDirection.FromWidget,
1634+
widgetId: "test",
1635+
requestId: "0",
1636+
action: WidgetApiFromWidgetAction.MSC2876ReadEvents,
1637+
data: {
1638+
type: "net.example.test",
1639+
state_key: "B",
1640+
},
1641+
};
1642+
1643+
await loadIframe(["org.matrix.msc2762.receive.state_event:net.example.test#B"]);
1644+
1645+
clientWidgetApi.setViewedRoomId("!room-id");
1646+
1647+
// we clear the mock here because setViewedRoomId will push the room state and therefore read it
1648+
// from the driver.
1649+
driver.readRoomState.mockClear();
1650+
// clearing this as well so it gets the same treatment as readRoomState for reference
1651+
driver.readRoomTimeline.mockClear();
1652+
1653+
emitEvent(new CustomEvent("", { detail: event }));
1654+
1655+
await waitFor(() => {
1656+
expect(transport.reply).toHaveBeenCalledWith(event, {
1657+
events: [createRoomEvent({ type: "net.example.test", state_key: "B" })],
1658+
});
1659+
});
1660+
1661+
expect(driver.readRoomTimeline).toHaveBeenLastCalledWith(
1662+
"!room-id",
1663+
"net.example.test",
1664+
undefined,
1665+
"B",
1666+
0,
1667+
undefined,
1668+
);
1669+
expect(driver.readRoomState).not.toHaveBeenCalled();
1670+
});
1671+
16231672
it("fails to read state events with a specific state key", async () => {
16241673
const event: IReadEventFromWidgetActionRequest = {
16251674
api: WidgetApiDirection.FromWidget,

0 commit comments

Comments
 (0)