@@ -49,6 +49,11 @@ import {
4949 ISendEventFromWidgetResponseData ,
5050 ISendEventToWidgetRequestData ,
5151} from "./interfaces/SendEventAction" ;
52+ import {
53+ ISendToDeviceFromWidgetActionRequest ,
54+ ISendToDeviceFromWidgetResponseData ,
55+ ISendToDeviceToWidgetRequestData ,
56+ } from "./interfaces/SendToDeviceAction" ;
5257import { EventDirection , WidgetEventCapability } from "./models/WidgetEventCapability" ;
5358import { IRoomEvent } from "./interfaces/IRoomEvent" ;
5459import {
@@ -143,23 +148,27 @@ export class ClientWidgetApi extends EventEmitter {
143148 }
144149
145150 public canSendRoomEvent ( eventType : string , msgtype : string = null ) : boolean {
146- return this . allowedEvents . some ( e =>
147- e . matchesAsRoomEvent ( eventType , msgtype ) && e . direction === EventDirection . Send ) ;
151+ return this . allowedEvents . some ( e => e . matchesAsRoomEvent ( EventDirection . Send , eventType , msgtype ) ) ;
148152 }
149153
150154 public canSendStateEvent ( eventType : string , stateKey : string ) : boolean {
151- return this . allowedEvents . some ( e =>
152- e . matchesAsStateEvent ( eventType , stateKey ) && e . direction === EventDirection . Send ) ;
155+ return this . allowedEvents . some ( e => e . matchesAsStateEvent ( EventDirection . Send , eventType , stateKey ) ) ;
156+ }
157+
158+ public canSendToDeviceEvent ( eventType : string ) : boolean {
159+ return this . allowedEvents . some ( e => e . matchesAsToDeviceEvent ( EventDirection . Send , eventType ) ) ;
153160 }
154161
155162 public canReceiveRoomEvent ( eventType : string , msgtype : string = null ) : boolean {
156- return this . allowedEvents . some ( e =>
157- e . matchesAsRoomEvent ( eventType , msgtype ) && e . direction === EventDirection . Receive ) ;
163+ return this . allowedEvents . some ( e => e . matchesAsRoomEvent ( EventDirection . Receive , eventType , msgtype ) ) ;
158164 }
159165
160166 public canReceiveStateEvent ( eventType : string , stateKey : string ) : boolean {
161- return this . allowedEvents . some ( e =>
162- e . matchesAsStateEvent ( eventType , stateKey ) && e . direction === EventDirection . Receive ) ;
167+ return this . allowedEvents . some ( e => e . matchesAsStateEvent ( EventDirection . Receive , eventType , stateKey ) ) ;
168+ }
169+
170+ public canReceiveToDeviceEvent ( eventType : string ) : boolean {
171+ return this . allowedEvents . some ( e => e . matchesAsToDeviceEvent ( EventDirection . Receive , eventType ) ) ;
163172 }
164173
165174 public stop ( ) {
@@ -453,6 +462,32 @@ export class ClientWidgetApi extends EventEmitter {
453462 } ) ;
454463 }
455464
465+ private async handleSendToDevice ( request : ISendToDeviceFromWidgetActionRequest ) : Promise < void > {
466+ if ( ! request . data . type ) {
467+ await this . transport . reply < IWidgetApiErrorResponseData > ( request , {
468+ error : { message : "Invalid request - missing event type" } ,
469+ } ) ;
470+ } else if ( ! request . data . messages ) {
471+ await this . transport . reply < IWidgetApiErrorResponseData > ( request , {
472+ error : { message : "Invalid request - missing event contents" } ,
473+ } ) ;
474+ } else if ( ! this . canSendToDeviceEvent ( request . data . type ) ) {
475+ await this . transport . reply < IWidgetApiErrorResponseData > ( request , {
476+ error : { message : "Cannot send to-device events of this type" } ,
477+ } ) ;
478+ } else {
479+ try {
480+ await this . driver . sendToDevice ( request . data . type , request . data . messages ) ;
481+ await this . transport . reply < ISendToDeviceFromWidgetResponseData > ( request , { } ) ;
482+ } catch ( e ) {
483+ console . error ( "error sending to-device event" , e ) ;
484+ await this . transport . reply < IWidgetApiErrorResponseData > ( request , {
485+ error : { message : "Error sending event" } ,
486+ } ) ;
487+ }
488+ }
489+ }
490+
456491 private handleMessage ( ev : CustomEvent < IWidgetApiRequest > ) {
457492 if ( this . isStopped ) return ;
458493 const actionEv = new CustomEvent ( `action:${ ev . detail . action } ` , {
@@ -468,6 +503,8 @@ export class ClientWidgetApi extends EventEmitter {
468503 return this . replyVersions ( < ISupportedVersionsActionRequest > ev . detail ) ;
469504 case WidgetApiFromWidgetAction . SendEvent :
470505 return this . handleSendEvent ( < ISendEventFromWidgetActionRequest > ev . detail ) ;
506+ case WidgetApiFromWidgetAction . SendToDevice :
507+ return this . handleSendToDevice ( < ISendToDeviceFromWidgetActionRequest > ev . detail ) ;
471508 case WidgetApiFromWidgetAction . GetOpenIDCredentials :
472509 return this . handleOIDC ( < IGetOpenIDActionRequest > ev . detail ) ;
473510 case WidgetApiFromWidgetAction . MSC2931Navigate :
@@ -531,27 +568,43 @@ export class ClientWidgetApi extends EventEmitter {
531568 * Not the room ID of the event.
532569 * @returns {Promise<void> } Resolves when complete, rejects if there was an error sending.
533570 */
534- public feedEvent ( rawEvent : IRoomEvent , currentViewedRoomId : string ) : Promise < void > {
571+ public async feedEvent ( rawEvent : IRoomEvent , currentViewedRoomId : string ) : Promise < void > {
535572 if ( rawEvent . room_id !== currentViewedRoomId && ! this . canUseRoomTimeline ( rawEvent . room_id ) ) {
536- return Promise . resolve ( ) ; // no-op
573+ return ; // no-op
537574 }
538575
539576 if ( rawEvent . state_key !== undefined && rawEvent . state_key !== null ) {
540577 // state event
541578 if ( ! this . canReceiveStateEvent ( rawEvent . type , rawEvent . state_key ) ) {
542- return Promise . resolve ( ) ; // no-op
579+ return ; // no-op
543580 }
544581 } else {
545582 // message event
546- if ( ! this . canReceiveRoomEvent ( rawEvent . type , ( rawEvent . content || { } ) [ ' msgtype' ] ) ) {
547- return Promise . resolve ( ) ; // no-op
583+ if ( ! this . canReceiveRoomEvent ( rawEvent . type , rawEvent . content ?. [ " msgtype" ] ) ) {
584+ return ; // no-op
548585 }
549586 }
550587
551588 // Feed the event into the widget
552- return this . transport . send < ISendEventToWidgetRequestData > (
589+ await this . transport . send < ISendEventToWidgetRequestData > (
553590 WidgetApiToWidgetAction . SendEvent ,
554591 rawEvent as ISendEventToWidgetRequestData , // it's compatible, but missing the index signature
555- ) . then ( ) ;
592+ ) ;
593+ }
594+
595+ /**
596+ * Feeds a to-device event to the widget. If the widget is not able to accept the
597+ * event due to permissions, this will no-op and return calmly. If the widget failed
598+ * to handle the event, this will raise an error.
599+ * @param {IRoomEvent } rawEvent The event to (try to) send to the widget.
600+ * @returns {Promise<void> } Resolves when complete, rejects if there was an error sending.
601+ */
602+ public async feedToDevice ( rawEvent : IRoomEvent ) : Promise < void > {
603+ if ( this . canReceiveToDeviceEvent ( rawEvent . type ) ) {
604+ await this . transport . send < ISendToDeviceToWidgetRequestData > (
605+ WidgetApiToWidgetAction . SendToDevice ,
606+ rawEvent as ISendToDeviceToWidgetRequestData , // it's compatible, but missing the index signature
607+ ) ;
608+ }
556609 }
557610}
0 commit comments