Skip to content

Commit 3928fed

Browse files
toger5robintown
authored andcommitted
Allow the embedded client to work without UpdateState version
1 parent 9398271 commit 3928fed

File tree

1 file changed

+54
-5
lines changed

1 file changed

+54
-5
lines changed

src/embedded.ts

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
type IWidgetApiResponse,
3030
type IWidgetApiResponseData,
3131
type IUpdateStateToWidgetActionRequest,
32+
UnstableApiVersion,
3233
} from "matrix-widget-api";
3334

3435
import { MatrixEvent, type IEvent, type IContent, EventStatus } from "./models/event.ts";
@@ -259,6 +260,10 @@ export class RoomWidgetClient extends MatrixClient {
259260
if (sendContentLoaded) widgetApi.sendContentLoaded();
260261
}
261262

263+
public async supportUpdateState(): Promise<boolean> {
264+
return (await this.widgetApi.getClientVersions())?.includes(UnstableApiVersion.MSC2762_UPDATE_STATE);
265+
}
266+
262267
public async startClient(opts: IStartClientOpts = {}): Promise<void> {
263268
this.lifecycle = new AbortController();
264269

@@ -283,14 +288,41 @@ export class RoomWidgetClient extends MatrixClient {
283288

284289
await this.widgetApiReady;
285290

291+
// sync room state:
292+
if (await this.supportUpdateState()) {
293+
// This will resolve once the client driver has sent us all the allowed room state.
294+
await this.roomStateSynced;
295+
} else {
296+
// Backfill the requested events
297+
// We only get the most recent event for every type + state key combo,
298+
// so it doesn't really matter what order we inject them in
299+
await Promise.all(
300+
this.capabilities.receiveState?.map(async ({ eventType, stateKey }) => {
301+
const rawEvents = await this.widgetApi.readStateEvents(eventType, undefined, stateKey, [
302+
this.roomId,
303+
]);
304+
const events = rawEvents.map((rawEvent) => new MatrixEvent(rawEvent as Partial<IEvent>));
305+
306+
if (this.syncApi instanceof SyncApi) {
307+
// Passing events as `stateAfterEventList` will update the state.
308+
await this.syncApi.injectRoomEvents(this.room!, undefined, events);
309+
} else {
310+
await this.syncApi!.injectRoomEvents(this.room!, events); // Sliding Sync
311+
}
312+
events.forEach((event) => {
313+
this.emit(ClientEvent.Event, event);
314+
logger.info(`Backfilled event ${event.getId()} ${event.getType()} ${event.getStateKey()}`);
315+
});
316+
}) ?? [],
317+
);
318+
}
319+
286320
if (opts.clientWellKnownPollPeriod !== undefined) {
287321
this.clientWellKnownIntervalID = setInterval(() => {
288322
this.fetchClientWellKnown();
289323
}, 1000 * opts.clientWellKnownPollPeriod);
290324
this.fetchClientWellKnown();
291325
}
292-
293-
await this.roomStateSynced;
294326
this.setSyncState(SyncState.Syncing);
295327
logger.info("Finished initial sync");
296328

@@ -589,11 +621,24 @@ export class RoomWidgetClient extends MatrixClient {
589621
await this.updateTxId(event);
590622

591623
if (this.syncApi instanceof SyncApi) {
592-
await this.syncApi.injectRoomEvents(this.room!, undefined, [], [event]);
624+
if (await this.supportUpdateState()) {
625+
await this.syncApi.injectRoomEvents(this.room!, undefined, [], [event]);
626+
} else {
627+
// Passing undefined for `stateAfterEventList` will make `injectRoomEvents` run in legacy mode
628+
// -> state events in `timelineEventList` will update the state.
629+
await this.syncApi.injectRoomEvents(this.room!, [], undefined, [event]);
630+
}
593631
} else {
594632
// Sliding Sync
595-
await this.syncApi!.injectRoomEvents(this.room!, [], [event]);
633+
if (await this.supportUpdateState()) {
634+
await this.syncApi!.injectRoomEvents(this.room!, [], [event]);
635+
} else {
636+
logger.error(
637+
"slididng sync cannot be used in widget mode if the client widget driver does not support the version: 'org.matrix.msc2762_update_state'",
638+
);
639+
}
596640
}
641+
597642
this.emit(ClientEvent.Event, event);
598643
this.setSyncState(SyncState.Syncing);
599644
logger.info(`Received event ${event.getId()} ${event.getType()}`);
@@ -623,7 +668,11 @@ export class RoomWidgetClient extends MatrixClient {
623668

624669
private onStateUpdate = async (ev: CustomEvent<IUpdateStateToWidgetActionRequest>): Promise<void> => {
625670
ev.preventDefault();
626-
671+
if (!(await this.supportUpdateState())) {
672+
logger.warn(
673+
"received update_state widget action but the widget driver did not claim to support 'org.matrix.msc2762_update_state'",
674+
);
675+
}
627676
for (const rawEvent of ev.detail.data.state) {
628677
// Verify the room ID matches, since it's possible for the client to
629678
// send us state updates from other rooms if this widget is always

0 commit comments

Comments
 (0)