Skip to content

Commit 8cb34be

Browse files
committed
Merge branch 'master' into toger5/prettier-config
2 parents 7b9643e + 70326db commit 8cb34be

File tree

5 files changed

+76
-12
lines changed

5 files changed

+76
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ lib/
33
dist/
44
.npmrc
55
.idea
6+
.vscode
67

78
# Logs
89
logs

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "matrix-widget-api",
3-
"version": "1.12.0",
3+
"version": "1.13.0",
44
"description": "Matrix Widget API SDK",
55
"main": "./lib/index.js",
66
"types": "./lib/index.d.ts",

src/ClientWidgetApi.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import {
4040
ISupportedVersionsActionRequest,
4141
ISupportedVersionsActionResponseData,
4242
} from "./interfaces/SupportedVersionsAction";
43-
import { CurrentApiVersions } from "./interfaces/ApiVersion";
43+
import { ApiVersion, CurrentApiVersions, UnstableApiVersion } from "./interfaces/ApiVersion";
4444
import { IScreenshotActionResponseData } from "./interfaces/ScreenshotAction";
4545
import { IVisibilityActionRequestData } from "./interfaces/VisibilityAction";
4646
import { IWidgetApiAcknowledgeResponseData, IWidgetApiResponseData } from "./interfaces/IWidgetApiResponse";
@@ -138,6 +138,7 @@ import { IUpdateStateToWidgetRequestData } from "./interfaces/UpdateStateAction"
138138
export class ClientWidgetApi extends EventEmitter {
139139
public readonly transport: ITransport;
140140

141+
private cachedWidgetVersions: ApiVersion[] | null = null;
141142
// contentLoadedActionSent is used to check that only one ContentLoaded request is send.
142143
private contentLoadedActionSent = false;
143144
private allowedCapabilities = new Set<Capability>();
@@ -227,6 +228,24 @@ export class ClientWidgetApi extends EventEmitter {
227228
this.transport.stop();
228229
}
229230

231+
public async getWidgetVersions(): Promise<ApiVersion[]> {
232+
if (Array.isArray(this.cachedWidgetVersions)) {
233+
return Promise.resolve(this.cachedWidgetVersions);
234+
}
235+
236+
try {
237+
const r = await this.transport.send<IWidgetApiRequestEmptyData, ISupportedVersionsActionResponseData>(
238+
WidgetApiToWidgetAction.SupportedApiVersions,
239+
{},
240+
);
241+
this.cachedWidgetVersions = r.supported_versions;
242+
return r.supported_versions;
243+
} catch (e) {
244+
console.warn("non-fatal error getting supported widget versions: ", e);
245+
return [];
246+
}
247+
}
248+
230249
private beginCapabilities(): void {
231250
// widget has loaded - tell all the listeners that
232251
this.emit("preparing");
@@ -287,7 +306,7 @@ export class ClientWidgetApi extends EventEmitter {
287306

288307
private onIframeLoad(ev: Event): void {
289308
if (this.widget.waitForIframeLoad) {
290-
// If the widget is set to waitForIframeLoad the capabilities immediatly get setup after load.
309+
// If the widget is set to waitForIframeLoad the capabilities immediately get setup after load.
291310
// The client does not wait for the ContentLoaded action.
292311
this.beginCapabilities();
293312
} else {
@@ -1037,7 +1056,7 @@ export class ClientWidgetApi extends EventEmitter {
10371056
public async feedEvent(rawEvent: IRoomEvent, currentViewedRoomId: string): Promise<void>;
10381057
/**
10391058
* Feeds an event to the widget. As a client you are expected to call this
1040-
* for every new event in every room to which you are joined or invited.
1059+
* for every new event (including state events) in every room to which you are joined or invited.
10411060
* @param {IRoomEvent} rawEvent The event to (try to) send to the widget.
10421061
* @returns {Promise<void>} Resolves when delivered or if the widget is not
10431062
* able to read the event due to permissions, rejects if the widget failed
@@ -1117,9 +1136,12 @@ export class ClientWidgetApi extends EventEmitter {
11171136
events.push(...stateKeyMap.values());
11181137
}
11191138
}
1120-
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1121-
state: events,
1122-
});
1139+
if ((await this.getWidgetVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE)) {
1140+
// Only send state updates when using UpdateState. Otherwise the SendEvent action will be responsible for state updates.
1141+
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1142+
state: events,
1143+
});
1144+
}
11231145
} finally {
11241146
this.flushRoomStateTask = null;
11251147
}
@@ -1182,7 +1204,7 @@ export class ClientWidgetApi extends EventEmitter {
11821204
* room state entry.
11831205
* @returns {Promise<void>} Resolves when delivered or if the widget is not
11841206
* able to receive the room state due to permissions, rejects if the
1185-
widget failed to handle the update.
1207+
* widget failed to handle the update.
11861208
*/
11871209
public async feedStateUpdate(rawEvent: IRoomEvent): Promise<void> {
11881210
if (rawEvent.state_key === undefined) throw new Error("Not a state event");
@@ -1193,9 +1215,12 @@ export class ClientWidgetApi extends EventEmitter {
11931215
// Updates could race with the initial push of the room's state
11941216
if (this.pushRoomStateTasks.size === 0) {
11951217
// No initial push tasks are pending; safe to send immediately
1196-
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1197-
state: [rawEvent],
1198-
});
1218+
if ((await this.getWidgetVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE)) {
1219+
// Only send state updates when using UpdateState. Otherwise the SendEvent action will be responsible for state updates.
1220+
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1221+
state: [rawEvent],
1222+
});
1223+
}
11991224
} else {
12001225
// Lump the update in with whatever data will be sent in the
12011226
// initial push later. Even if we set it to an "outdated" entry

src/interfaces/ApiVersion.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export enum MatrixApiVersion {
2222

2323
export enum UnstableApiVersion {
2424
MSC2762 = "org.matrix.msc2762",
25+
MSC2762_UPDATE_STATE = "org.matrix.msc2762_update_state",
2526
MSC2871 = "org.matrix.msc2871",
2627
MSC2873 = "org.matrix.msc2873",
2728
MSC2931 = "org.matrix.msc2931",
@@ -41,6 +42,7 @@ export const CurrentApiVersions: ApiVersion[] = [
4142
MatrixApiVersion.Prerelease2,
4243
//MatrixApiVersion.V010,
4344
UnstableApiVersion.MSC2762,
45+
UnstableApiVersion.MSC2762_UPDATE_STATE,
4446
UnstableApiVersion.MSC2871,
4547
UnstableApiVersion.MSC2873,
4648
UnstableApiVersion.MSC2931,

test/ClientWidgetApi-test.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { waitFor } from "@testing-library/dom";
1919

2020
import { ClientWidgetApi } from "../src/ClientWidgetApi";
2121
import { WidgetDriver } from "../src/driver/WidgetDriver";
22-
import { UnstableApiVersion } from "../src/interfaces/ApiVersion";
22+
import { CurrentApiVersions, UnstableApiVersion } from "../src/interfaces/ApiVersion";
2323
import { Capability } from "../src/interfaces/Capabilities";
2424
import { IRoomEvent } from "../src/interfaces/IRoomEvent";
2525
import { IWidgetApiRequest } from "../src/interfaces/IWidgetApiRequest";
@@ -762,6 +762,14 @@ describe("ClientWidgetApi", () => {
762762
const roomId = "!room:example.org";
763763
const otherRoomId = "!other-room:example.org";
764764
clientWidgetApi.setViewedRoomId(roomId);
765+
766+
jest.spyOn(transport, "send").mockImplementation((action, data) => {
767+
if (action === WidgetApiToWidgetAction.SupportedApiVersions) {
768+
return Promise.resolve({ supported_versions: CurrentApiVersions });
769+
}
770+
return Promise.resolve({});
771+
});
772+
765773
const topicEvent = createRoomEvent({
766774
room_id: roomId,
767775
type: "m.room.topic",
@@ -869,6 +877,34 @@ describe("ClientWidgetApi", () => {
869877
});
870878
});
871879

880+
describe("dont receive UpdateState if version not supported", () => {
881+
it("syncs initial state and feeds updates", async () => {
882+
const roomId = "!room:example.org";
883+
clientWidgetApi.setViewedRoomId(roomId);
884+
jest.spyOn(transport, "send").mockImplementation((action, data) => {
885+
if (action === WidgetApiToWidgetAction.SupportedApiVersions) {
886+
return Promise.resolve({ supported_versions: [] });
887+
}
888+
return Promise.resolve({});
889+
});
890+
891+
await loadIframe(["org.matrix.msc2762.receive.state_event:m.room.join_rules#"]);
892+
893+
const newJoinRulesEvent = createRoomEvent({
894+
room_id: roomId,
895+
type: "m.room.join_rules",
896+
state_key: "",
897+
content: { join_rule: "invite" },
898+
});
899+
clientWidgetApi.feedStateUpdate(newJoinRulesEvent);
900+
901+
await waitFor(() => {
902+
// Only the updated join rules should have been delivered
903+
expect(transport.send).not.toHaveBeenCalledWith(WidgetApiToWidgetAction.UpdateState);
904+
});
905+
});
906+
});
907+
872908
describe("update_delayed_event action", () => {
873909
it("fails to update delayed events", async () => {
874910
const event: IUpdateDelayedEventFromWidgetActionRequest = {

0 commit comments

Comments
 (0)