@@ -28,7 +28,6 @@ import {
2828 WidgetApiAction ,
2929 IWidgetApiResponse ,
3030 IWidgetApiResponseData ,
31- IUpdateStateToWidgetActionRequest ,
3231} from "matrix-widget-api" ;
3332
3433import { MatrixEvent , IEvent , IContent , EventStatus } from "./models/event.ts" ;
@@ -137,7 +136,6 @@ export type EventHandlerMap = { [RoomWidgetClientEvent.PendingEventsChanged]: ()
137136export class RoomWidgetClient extends MatrixClient {
138137 private room ?: Room ;
139138 private readonly widgetApiReady : Promise < void > ;
140- private readonly roomStateSynced : Promise < void > ;
141139 private lifecycle ?: AbortController ;
142140 private syncState : SyncState | null = null ;
143141
@@ -191,11 +189,6 @@ export class RoomWidgetClient extends MatrixClient {
191189 } ;
192190
193191 this . widgetApiReady = new Promise < void > ( ( resolve ) => this . widgetApi . once ( "ready" , resolve ) ) ;
194- this . roomStateSynced = capabilities . receiveState ?. length
195- ? new Promise < void > ( ( resolve ) =>
196- this . widgetApi . once ( `action:${ WidgetApiToWidgetAction . UpdateState } ` , resolve ) ,
197- )
198- : Promise . resolve ( ) ;
199192
200193 // Request capabilities for the functionality this client needs to support
201194 if (
@@ -248,7 +241,6 @@ export class RoomWidgetClient extends MatrixClient {
248241
249242 widgetApi . on ( `action:${ WidgetApiToWidgetAction . SendEvent } ` , this . onEvent ) ;
250243 widgetApi . on ( `action:${ WidgetApiToWidgetAction . SendToDevice } ` , this . onToDevice ) ;
251- widgetApi . on ( `action:${ WidgetApiToWidgetAction . UpdateState } ` , this . onStateUpdate ) ;
252244
253245 // Open communication with the host
254246 widgetApi . start ( ) ;
@@ -284,16 +276,37 @@ export class RoomWidgetClient extends MatrixClient {
284276
285277 await this . widgetApiReady ;
286278
279+ // Backfill the requested events
280+ // We only get the most recent event for every type + state key combo,
281+ // so it doesn't really matter what order we inject them in
282+ await Promise . all (
283+ this . capabilities . receiveState ?. map ( async ( { eventType, stateKey } ) => {
284+ const rawEvents = await this . widgetApi . readStateEvents ( eventType , undefined , stateKey , [ this . roomId ] ) ;
285+ const events = rawEvents . map ( ( rawEvent ) => new MatrixEvent ( rawEvent as Partial < IEvent > ) ) ;
286+
287+ if ( this . syncApi instanceof SyncApi ) {
288+ // Passing undefined for `stateAfterEventList` allows will make `injectRoomEvents` run in legacy mode
289+ // -> state events in `timelineEventList` will update the state.
290+ await this . syncApi . injectRoomEvents ( this . room ! , undefined , events ) ;
291+ } else {
292+ await this . syncApi ! . injectRoomEvents ( this . room ! , events ) ; // Sliding Sync
293+ }
294+ events . forEach ( ( event ) => {
295+ this . emit ( ClientEvent . Event , event ) ;
296+ logger . info ( `Backfilled event ${ event . getId ( ) } ${ event . getType ( ) } ${ event . getStateKey ( ) } ` ) ;
297+ } ) ;
298+ } ) ?? [ ] ,
299+ ) ;
300+
287301 if ( opts . clientWellKnownPollPeriod !== undefined ) {
288302 this . clientWellKnownIntervalID = setInterval ( ( ) => {
289303 this . fetchClientWellKnown ( ) ;
290304 } , 1000 * opts . clientWellKnownPollPeriod ) ;
291305 this . fetchClientWellKnown ( ) ;
292306 }
293307
294- await this . roomStateSynced ;
295308 this . setSyncState ( SyncState . Syncing ) ;
296- logger . info ( "Finished initial sync " ) ;
309+ logger . info ( "Finished backfilling events " ) ;
297310
298311 this . matrixRTC . start ( ) ;
299312
@@ -304,7 +317,6 @@ export class RoomWidgetClient extends MatrixClient {
304317 public stopClient ( ) : void {
305318 this . widgetApi . off ( `action:${ WidgetApiToWidgetAction . SendEvent } ` , this . onEvent ) ;
306319 this . widgetApi . off ( `action:${ WidgetApiToWidgetAction . SendToDevice } ` , this . onToDevice ) ;
307- this . widgetApi . off ( `action:${ WidgetApiToWidgetAction . UpdateState } ` , this . onStateUpdate ) ;
308320
309321 super . stopClient ( ) ;
310322 this . lifecycle ! . abort ( ) ; // Signal to other async tasks that the client has stopped
@@ -562,15 +574,36 @@ export class RoomWidgetClient extends MatrixClient {
562574 // Only inject once we have update the txId
563575 await this . updateTxId ( event ) ;
564576
577+ // The widget API does not tell us whether a state event came from `state_after` or not so we assume legacy behaviour for now.
565578 if ( this . syncApi instanceof SyncApi ) {
566- await this . syncApi . injectRoomEvents ( this . room ! , undefined , [ ] , [ event ] ) ;
579+ // The code will want to be something like:
580+ // ```
581+ // if (!params.addToTimeline && !params.addToState) {
582+ // // Passing undefined for `stateAfterEventList` makes `injectRoomEvents` run in "legacy mode"
583+ // // -> state events part of the `timelineEventList` parameter will update the state.
584+ // this.injectRoomEvents(this.room!, [], undefined, [event]);
585+ // } else {
586+ // this.injectRoomEvents(this.room!, undefined, params.addToState ? [event] : [], params.addToTimeline ? [event] : []);
587+ // }
588+ // ```
589+
590+ // Passing undefined for `stateAfterEventList` allows will make `injectRoomEvents` run in legacy mode
591+ // -> state events in `timelineEventList` will update the state.
592+ await this . syncApi . injectRoomEvents ( this . room ! , [ ] , undefined , [ event ] ) ;
567593 } else {
568- // Sliding Sync
569- await this . syncApi ! . injectRoomEvents ( this . room ! , [ ] , [ event ] ) ;
594+ // The code will want to be something like:
595+ // ```
596+ // if (!params.addToTimeline && !params.addToState) {
597+ // this.injectRoomEvents(this.room!, [], [event]);
598+ // } else {
599+ // this.injectRoomEvents(this.room!, params.addToState ? [event] : [], params.addToTimeline ? [event] : []);
600+ // }
601+ // ```
602+ await this . syncApi ! . injectRoomEvents ( this . room ! , [ ] , [ event ] ) ; // Sliding Sync
570603 }
571604 this . emit ( ClientEvent . Event , event ) ;
572605 this . setSyncState ( SyncState . Syncing ) ;
573- logger . info ( `Received event ${ event . getId ( ) } ${ event . getType ( ) } ` ) ;
606+ logger . info ( `Received event ${ event . getId ( ) } ${ event . getType ( ) } ${ event . getStateKey ( ) } ` ) ;
574607 } else {
575608 const { event_id : eventId , room_id : roomId } = ev . detail . data ;
576609 logger . info ( `Received event ${ eventId } for a different room ${ roomId } ; discarding` ) ;
@@ -595,32 +628,6 @@ export class RoomWidgetClient extends MatrixClient {
595628 await this . ack ( ev ) ;
596629 } ;
597630
598- private onStateUpdate = async ( ev : CustomEvent < IUpdateStateToWidgetActionRequest > ) : Promise < void > => {
599- ev . preventDefault ( ) ;
600-
601- for ( const rawEvent of ev . detail . data . state ) {
602- // Verify the room ID matches, since it's possible for the client to
603- // send us state updates from other rooms if this widget is always
604- // on screen
605- if ( rawEvent . room_id === this . roomId ) {
606- const event = new MatrixEvent ( rawEvent as Partial < IEvent > ) ;
607-
608- if ( this . syncApi instanceof SyncApi ) {
609- await this . syncApi . injectRoomEvents ( this . room ! , undefined , [ event ] ) ;
610- } else {
611- // Sliding Sync
612- await this . syncApi ! . injectRoomEvents ( this . room ! , [ event ] ) ;
613- }
614- logger . info ( `Updated state entry ${ event . getType ( ) } ${ event . getStateKey ( ) } to ${ event . getId ( ) } ` ) ;
615- } else {
616- const { event_id : eventId , room_id : roomId } = ev . detail . data ;
617- logger . info ( `Received state entry ${ eventId } for a different room ${ roomId } ; discarding` ) ;
618- }
619- }
620-
621- await this . ack ( ev ) ;
622- } ;
623-
624631 private async watchTurnServers ( ) : Promise < void > {
625632 const servers = this . widgetApi . getTurnServers ( ) ;
626633 const onClientStopped = ( ) : void => {
0 commit comments