@@ -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" ;
4444import { IScreenshotActionResponseData } from "./interfaces/ScreenshotAction" ;
4545import { IVisibilityActionRequestData } from "./interfaces/VisibilityAction" ;
4646import { IWidgetApiAcknowledgeResponseData , IWidgetApiResponseData } from "./interfaces/IWidgetApiResponse" ;
@@ -138,6 +138,7 @@ import { IUpdateStateToWidgetRequestData } from "./interfaces/UpdateStateAction"
138138export 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,10 +1113,11 @@ export class ClientWidgetApi extends EventEmitter {
10931113 events . push ( ...stateKeyMap . values ( ) ) ;
10941114 }
10951115 }
1096- await this . transport . send < IUpdateStateToWidgetRequestData > (
1097- WidgetApiToWidgetAction . UpdateState ,
1098- { state : events } ,
1099- ) ;
1116+ if ( useUpdateState ) {
1117+ await this . transport . send < IUpdateStateToWidgetRequestData > ( WidgetApiToWidgetAction . UpdateState , {
1118+ state : events ,
1119+ } ) ;
1120+ }
11001121 } finally {
11011122 this . flushRoomStateTask = null ;
11021123 }
@@ -1146,7 +1167,7 @@ export class ClientWidgetApi extends EventEmitter {
11461167 // Assuming no other tasks are already happening concurrently,
11471168 // schedule the widget action that actually pushes the events
11481169 this . flushRoomStateTask ??= this . flushRoomState ( ) ;
1149- this . flushRoomStateTask . catch ( e => console . error ( ' Failed to push room state' , e ) ) ;
1170+ this . flushRoomStateTask . catch ( ( e ) => console . error ( " Failed to push room state" , e ) ) ;
11501171 }
11511172 }
11521173 }
@@ -1162,18 +1183,22 @@ export class ClientWidgetApi extends EventEmitter {
11621183 widget failed to handle the update.
11631184 */
11641185 public async feedStateUpdate ( rawEvent : IRoomEvent ) : Promise < void > {
1165- if ( rawEvent . state_key === undefined ) throw new Error ( 'Not a state event' ) ;
1186+ const useUpdateState = ( await this . getWidgetVersions ( ) ) . includes ( UnstableApiVersion . MSC2762_UPDATE_STATE ) ;
1187+
1188+ if ( rawEvent . state_key === undefined ) throw new Error ( "Not a state event" ) ;
11661189 if (
1167- ( rawEvent . room_id === this . viewedRoomId || this . canUseRoomTimeline ( rawEvent . room_id ) )
1168- && this . canReceiveStateEvent ( rawEvent . type , rawEvent . state_key )
1190+ ( rawEvent . room_id === this . viewedRoomId || this . canUseRoomTimeline ( rawEvent . room_id ) ) &&
1191+ this . canReceiveStateEvent ( rawEvent . type , rawEvent . state_key )
11691192 ) {
11701193 // Updates could race with the initial push of the room's state
11711194 if ( this . pushRoomStateTasks . size === 0 ) {
11721195 // No initial push tasks are pending; safe to send immediately
1173- await this . transport . send < IUpdateStateToWidgetRequestData > (
1174- WidgetApiToWidgetAction . UpdateState ,
1175- { state : [ rawEvent ] } ,
1176- ) ;
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+ }
11771202 } else {
11781203 // Lump the update in with whatever data will be sent in the
11791204 // initial push later. Even if we set it to an "outdated" entry
0 commit comments