@@ -29,6 +29,7 @@ import {
29
29
IWidgetApiResponse ,
30
30
IWidgetApiResponseData ,
31
31
IUpdateStateToWidgetActionRequest ,
32
+ UnstableApiVersion ,
32
33
} from "matrix-widget-api" ;
33
34
34
35
import { MatrixEvent , IEvent , IContent , EventStatus } from "./models/event.ts" ;
@@ -260,6 +261,10 @@ export class RoomWidgetClient extends MatrixClient {
260
261
if ( sendContentLoaded ) widgetApi . sendContentLoaded ( ) ;
261
262
}
262
263
264
+ public async supportUpdateState ( ) : Promise < boolean > {
265
+ return ( await this . widgetApi . getClientVersions ( ) ) ?. includes ( UnstableApiVersion . MSC2762_UPDATE_STATE ) ;
266
+ }
267
+
263
268
public async startClient ( opts : IStartClientOpts = { } ) : Promise < void > {
264
269
this . lifecycle = new AbortController ( ) ;
265
270
@@ -284,14 +289,41 @@ export class RoomWidgetClient extends MatrixClient {
284
289
285
290
await this . widgetApiReady ;
286
291
292
+ // sync room state:
293
+ if ( await this . supportUpdateState ( ) ) {
294
+ // This will resolve once the client driver has sent us all the allowed room state.
295
+ await this . roomStateSynced ;
296
+ } else {
297
+ // Backfill the requested events
298
+ // We only get the most recent event for every type + state key combo,
299
+ // so it doesn't really matter what order we inject them in
300
+ await Promise . all (
301
+ this . capabilities . receiveState ?. map ( async ( { eventType, stateKey } ) => {
302
+ const rawEvents = await this . widgetApi . readStateEvents ( eventType , undefined , stateKey , [
303
+ this . roomId ,
304
+ ] ) ;
305
+ const events = rawEvents . map ( ( rawEvent ) => new MatrixEvent ( rawEvent as Partial < IEvent > ) ) ;
306
+
307
+ if ( this . syncApi instanceof SyncApi ) {
308
+ // Passing events as `stateAfterEventList` will update the state.
309
+ await this . syncApi . injectRoomEvents ( this . room ! , undefined , events ) ;
310
+ } else {
311
+ await this . syncApi ! . injectRoomEvents ( this . room ! , events ) ; // Sliding Sync
312
+ }
313
+ events . forEach ( ( event ) => {
314
+ this . emit ( ClientEvent . Event , event ) ;
315
+ logger . info ( `Backfilled event ${ event . getId ( ) } ${ event . getType ( ) } ${ event . getStateKey ( ) } ` ) ;
316
+ } ) ;
317
+ } ) ?? [ ] ,
318
+ ) ;
319
+ }
320
+
287
321
if ( opts . clientWellKnownPollPeriod !== undefined ) {
288
322
this . clientWellKnownIntervalID = setInterval ( ( ) => {
289
323
this . fetchClientWellKnown ( ) ;
290
324
} , 1000 * opts . clientWellKnownPollPeriod ) ;
291
325
this . fetchClientWellKnown ( ) ;
292
326
}
293
-
294
- await this . roomStateSynced ;
295
327
this . setSyncState ( SyncState . Syncing ) ;
296
328
logger . info ( "Finished initial sync" ) ;
297
329
@@ -563,11 +595,24 @@ export class RoomWidgetClient extends MatrixClient {
563
595
await this . updateTxId ( event ) ;
564
596
565
597
if ( this . syncApi instanceof SyncApi ) {
566
- await this . syncApi . injectRoomEvents ( this . room ! , undefined , [ ] , [ event ] ) ;
598
+ if ( await this . supportUpdateState ( ) ) {
599
+ await this . syncApi . injectRoomEvents ( this . room ! , undefined , [ ] , [ event ] ) ;
600
+ } else {
601
+ // Passing undefined for `stateAfterEventList` will make `injectRoomEvents` run in legacy mode
602
+ // -> state events in `timelineEventList` will update the state.
603
+ await this . syncApi . injectRoomEvents ( this . room ! , [ ] , undefined , [ event ] ) ;
604
+ }
567
605
} else {
568
606
// Sliding Sync
569
- await this . syncApi ! . injectRoomEvents ( this . room ! , [ ] , [ event ] ) ;
607
+ if ( await this . supportUpdateState ( ) ) {
608
+ await this . syncApi ! . injectRoomEvents ( this . room ! , [ ] , [ event ] ) ;
609
+ } else {
610
+ logger . error (
611
+ "slididng sync cannot be used in widget mode if the client widget driver does not support the version: 'org.matrix.msc2762_update_state'" ,
612
+ ) ;
613
+ }
570
614
}
615
+
571
616
this . emit ( ClientEvent . Event , event ) ;
572
617
this . setSyncState ( SyncState . Syncing ) ;
573
618
logger . info ( `Received event ${ event . getId ( ) } ${ event . getType ( ) } ` ) ;
@@ -597,7 +642,11 @@ export class RoomWidgetClient extends MatrixClient {
597
642
598
643
private onStateUpdate = async ( ev : CustomEvent < IUpdateStateToWidgetActionRequest > ) : Promise < void > => {
599
644
ev . preventDefault ( ) ;
600
-
645
+ if ( ! ( await this . supportUpdateState ( ) ) ) {
646
+ logger . warn (
647
+ "received update_state widget action but the widget driver did not claim to support 'org.matrix.msc2762_update_state'" ,
648
+ ) ;
649
+ }
601
650
for ( const rawEvent of ev . detail . data . state ) {
602
651
// Verify the room ID matches, since it's possible for the client to
603
652
// send us state updates from other rooms if this widget is always
0 commit comments