Skip to content

Commit 01626e6

Browse files
committed
Let the client only send UpdateState if the widget supports it.
1 parent d6e682d commit 01626e6

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

src/ClientWidgetApi.ts

Lines changed: 35 additions & 8 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");
@@ -1013,7 +1032,7 @@ export class ClientWidgetApi extends EventEmitter {
10131032
public async feedEvent(rawEvent: IRoomEvent, currentViewedRoomId: string): Promise<void>;
10141033
/**
10151034
* Feeds an event to the widget. As a client you are expected to call this
1016-
* for every new event in every room to which you are joined or invited.
1035+
* for every new event (including state events) in every room to which you are joined or invited.
10171036
* @param {IRoomEvent} rawEvent The event to (try to) send to the widget.
10181037
* @returns {Promise<void>} Resolves when delivered or if the widget is not
10191038
* able to read the event due to permissions, rejects if the widget failed
@@ -1082,6 +1101,7 @@ export class ClientWidgetApi extends EventEmitter {
10821101
}
10831102

10841103
private async flushRoomState(): Promise<void> {
1104+
const useUpdateState = (await this.getWidgetVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE);
10851105
try {
10861106
// Only send a single action once all concurrent tasks have completed
10871107
do await Promise.all([...this.pushRoomStateTasks]);
@@ -1093,9 +1113,11 @@ export class ClientWidgetApi extends EventEmitter {
10931113
events.push(...stateKeyMap.values());
10941114
}
10951115
}
1096-
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1097-
state: events,
1098-
});
1116+
if (useUpdateState) {
1117+
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1118+
state: events,
1119+
});
1120+
}
10991121
} finally {
11001122
this.flushRoomStateTask = null;
11011123
}
@@ -1161,6 +1183,8 @@ export class ClientWidgetApi extends EventEmitter {
11611183
widget failed to handle the update.
11621184
*/
11631185
public async feedStateUpdate(rawEvent: IRoomEvent): Promise<void> {
1186+
const useUpdateState = (await this.getWidgetVersions()).includes(UnstableApiVersion.MSC2762_UPDATE_STATE);
1187+
11641188
if (rawEvent.state_key === undefined) throw new Error("Not a state event");
11651189
if (
11661190
(rawEvent.room_id === this.viewedRoomId || this.canUseRoomTimeline(rawEvent.room_id)) &&
@@ -1169,9 +1193,12 @@ export class ClientWidgetApi extends EventEmitter {
11691193
// Updates could race with the initial push of the room's state
11701194
if (this.pushRoomStateTasks.size === 0) {
11711195
// No initial push tasks are pending; safe to send immediately
1172-
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1173-
state: [rawEvent],
1174-
});
1196+
if (useUpdateState) {
1197+
// Only send state updates when using UpdateState. Otherwise we will use SendEvent.
1198+
await this.transport.send<IUpdateStateToWidgetRequestData>(WidgetApiToWidgetAction.UpdateState, {
1199+
state: [rawEvent],
1200+
});
1201+
}
11751202
} else {
11761203
// Lump the update in with whatever data will be sent in the
11771204
// initial push later. Even if we set it to an "outdated" entry

0 commit comments

Comments
 (0)