@@ -212,6 +212,23 @@ export class RoomWidgetClient extends MatrixClient {
212212 )
213213 : Promise . resolve ( ) ;
214214
215+ this . requestInitialCapabilities ( capabilities , roomId ) ;
216+
217+ widgetApi . on ( `action:${ WidgetApiToWidgetAction . SendEvent } ` , this . onEvent ) ;
218+ widgetApi . on ( `action:${ WidgetApiToWidgetAction . SendToDevice } ` , this . onToDevice ) ;
219+ widgetApi . on ( `action:${ WidgetApiToWidgetAction . UpdateState } ` , this . onStateUpdate ) ;
220+
221+ // Open communication with the host
222+ widgetApi . start ( ) ;
223+ // Send a content loaded event now we've started the widget API
224+ // Note that element-web currently does not use waitForIFrameLoad=false and so
225+ // does *not* (yes, that is the right way around) wait for this event. Let's
226+ // start sending this, then once this has rolled out, we can change element-web to
227+ // use waitForIFrameLoad=false and have a widget API that's less racy.
228+ if ( sendContentLoaded ) widgetApi . sendContentLoaded ( ) ;
229+ }
230+
231+ private requestInitialCapabilities ( capabilities : ICapabilities , roomId : string ) : void {
215232 // Request capabilities for the functionality this client needs to support
216233 if (
217234 capabilities . sendEvent ?. length ||
@@ -223,68 +240,58 @@ export class RoomWidgetClient extends MatrixClient {
223240 capabilities . sendState ?. length ||
224241 capabilities . receiveState ?. length
225242 ) {
226- widgetApi . requestCapabilityForRoomTimeline ( roomId ) ;
243+ this . widgetApi . requestCapabilityForRoomTimeline ( roomId ) ;
227244 }
228- capabilities . sendEvent ?. forEach ( ( eventType ) => widgetApi . requestCapabilityToSendEvent ( eventType ) ) ;
229- capabilities . receiveEvent ?. forEach ( ( eventType ) => widgetApi . requestCapabilityToReceiveEvent ( eventType ) ) ;
245+ capabilities . sendEvent ?. forEach ( ( eventType ) => this . widgetApi . requestCapabilityToSendEvent ( eventType ) ) ;
246+ capabilities . receiveEvent ?. forEach ( ( eventType ) => this . widgetApi . requestCapabilityToReceiveEvent ( eventType ) ) ;
230247 if ( capabilities . sendMessage === true ) {
231- widgetApi . requestCapabilityToSendMessage ( ) ;
248+ this . widgetApi . requestCapabilityToSendMessage ( ) ;
232249 } else if ( Array . isArray ( capabilities . sendMessage ) ) {
233- capabilities . sendMessage . forEach ( ( msgType ) => widgetApi . requestCapabilityToSendMessage ( msgType ) ) ;
250+ capabilities . sendMessage . forEach ( ( msgType ) => this . widgetApi . requestCapabilityToSendMessage ( msgType ) ) ;
234251 }
235252 if ( capabilities . receiveMessage === true ) {
236- widgetApi . requestCapabilityToReceiveMessage ( ) ;
253+ this . widgetApi . requestCapabilityToReceiveMessage ( ) ;
237254 } else if ( Array . isArray ( capabilities . receiveMessage ) ) {
238- capabilities . receiveMessage . forEach ( ( msgType ) => widgetApi . requestCapabilityToReceiveMessage ( msgType ) ) ;
255+ capabilities . receiveMessage . forEach ( ( msgType ) => this . widgetApi . requestCapabilityToReceiveMessage ( msgType ) ) ;
239256 }
240257 capabilities . sendState ?. forEach ( ( { eventType, stateKey } ) =>
241- widgetApi . requestCapabilityToSendState ( eventType , stateKey ) ,
258+ this . widgetApi . requestCapabilityToSendState ( eventType , stateKey ) ,
242259 ) ;
243260 capabilities . receiveState ?. forEach ( ( { eventType, stateKey } ) =>
244- widgetApi . requestCapabilityToReceiveState ( eventType , stateKey ) ,
261+ this . widgetApi . requestCapabilityToReceiveState ( eventType , stateKey ) ,
262+ ) ;
263+ capabilities . sendToDevice ?. forEach ( ( eventType ) => this . widgetApi . requestCapabilityToSendToDevice ( eventType ) ) ;
264+ capabilities . receiveToDevice ?. forEach ( ( eventType ) =>
265+ this . widgetApi . requestCapabilityToReceiveToDevice ( eventType ) ,
245266 ) ;
246- capabilities . sendToDevice ?. forEach ( ( eventType ) => widgetApi . requestCapabilityToSendToDevice ( eventType ) ) ;
247- capabilities . receiveToDevice ?. forEach ( ( eventType ) => widgetApi . requestCapabilityToReceiveToDevice ( eventType ) ) ;
248267 if (
249268 capabilities . sendDelayedEvents &&
250269 ( capabilities . sendEvent ?. length ||
251270 capabilities . sendMessage === true ||
252271 ( Array . isArray ( capabilities . sendMessage ) && capabilities . sendMessage . length ) ||
253272 capabilities . sendState ?. length )
254273 ) {
255- widgetApi . requestCapability ( MatrixCapabilities . MSC4157SendDelayedEvent ) ;
274+ this . widgetApi . requestCapability ( MatrixCapabilities . MSC4157SendDelayedEvent ) ;
256275 }
257276 if ( capabilities . updateDelayedEvents ) {
258- widgetApi . requestCapability ( MatrixCapabilities . MSC4157UpdateDelayedEvent ) ;
277+ this . widgetApi . requestCapability ( MatrixCapabilities . MSC4157UpdateDelayedEvent ) ;
259278 }
260279 if ( capabilities . sendSticky ) {
261- widgetApi . requestCapability ( MatrixCapabilities . MSC4407SendStickyEvent ) ;
280+ this . widgetApi . requestCapability ( MatrixCapabilities . MSC4407SendStickyEvent ) ;
262281 }
263282 if ( capabilities . receiveSticky ) {
264- widgetApi . requestCapability ( MatrixCapabilities . MSC4407ReceiveStickyEvent ) ;
283+ this . widgetApi . requestCapability ( MatrixCapabilities . MSC4407ReceiveStickyEvent ) ;
265284 }
266285 if ( capabilities . turnServers ) {
267- widgetApi . requestCapability ( MatrixCapabilities . MSC3846TurnServers ) ;
286+ this . widgetApi . requestCapability ( MatrixCapabilities . MSC3846TurnServers ) ;
268287 }
269-
270- widgetApi . on ( `action:${ WidgetApiToWidgetAction . SendEvent } ` , this . onEvent ) ;
271- widgetApi . on ( `action:${ WidgetApiToWidgetAction . SendToDevice } ` , this . onToDevice ) ;
272- widgetApi . on ( `action:${ WidgetApiToWidgetAction . UpdateState } ` , this . onStateUpdate ) ;
273-
274- // Open communication with the host
275- widgetApi . start ( ) ;
276- // Send a content loaded event now we've started the widget API
277- // Note that element-web currently does not use waitForIFrameLoad=false and so
278- // does *not* (yes, that is the right way around) wait for this event. Let's
279- // start sending this, then once this has rolled out, we can change element-web to
280- // use waitForIFrameLoad=false and have a widget API that's less racy.
281- if ( sendContentLoaded ) widgetApi . sendContentLoaded ( ) ;
282288 }
283289
284290 public async supportUpdateState ( ) : Promise < boolean > {
285291 return ( await this . widgetApi . getClientVersions ( ) ) . includes ( UnstableApiVersion . MSC2762_UPDATE_STATE ) ;
286292 }
287293
294+ private readonly syncApiResolver = Promise . withResolvers < void > ( ) ;
288295 public async startClient ( opts : IStartClientOpts = { } ) : Promise < void > {
289296 this . lifecycle = new AbortController ( ) ;
290297
@@ -303,6 +310,7 @@ export class RoomWidgetClient extends MatrixClient {
303310 } else {
304311 this . syncApi = new SyncApi ( this , opts , this . buildSyncApiOptions ( ) ) ;
305312 }
313+ this . syncApiResolver . resolve ( ) ;
306314
307315 this . room = this . syncApi . createRoom ( this . roomId ) ;
308316 this . store . storeRoom ( this . room ) ;
@@ -729,7 +737,7 @@ export class RoomWidgetClient extends MatrixClient {
729737
730738 // Only inject once we have update the txId
731739 await this . updateTxId ( event ) ;
732-
740+ await this . syncApiResolver . promise ;
733741 if ( this . syncApi instanceof SyncApi ) {
734742 if ( await this . supportUpdateState ( ) ) {
735743 await this . syncApi . injectRoomEvents ( this . room ! , undefined , [ ] , [ event ] ) ;
@@ -784,6 +792,7 @@ export class RoomWidgetClient extends MatrixClient {
784792 "received update_state widget action but the widget driver did not claim to support 'org.matrix.msc2762_update_state'" ,
785793 ) ;
786794 }
795+ await this . syncApiResolver . promise ;
787796 for ( const rawEvent of ev . detail . data . state ) {
788797 // Verify the room ID matches, since it's possible for the client to
789798 // send us state updates from other rooms if this widget is always
0 commit comments