@@ -23,6 +23,11 @@ import {
2323 IModalWidgetCloseRequest ,
2424 IModalWidgetOpenRequestData ,
2525 IModalWidgetReturnData ,
26+ ISetModalButtonEnabledActionRequest ,
27+ IWidgetApiAcknowledgeResponseData ,
28+ IWidgetApiErrorResponseData ,
29+ BuiltInModalButtonID ,
30+ ModalButtonID ,
2631 ModalButtonKind ,
2732 Widget ,
2833 WidgetApiFromWidgetAction ,
@@ -31,6 +36,7 @@ import {StopGapWidgetDriver} from "../../../stores/widgets/StopGapWidgetDriver";
3136import { MatrixClientPeg } from "../../../MatrixClientPeg" ;
3237import RoomViewStore from "../../../stores/RoomViewStore" ;
3338import { OwnProfileStore } from "../../../stores/OwnProfileStore" ;
39+ import { arrayFastClone } from "../../../utils/arrays" ;
3440
3541interface IProps {
3642 widgetDefinition : IModalWidgetOpenRequestData ;
@@ -40,15 +46,19 @@ interface IProps {
4046
4147interface IState {
4248 messaging ?: ClientWidgetApi ;
49+ disabledButtonIds : ModalButtonID [ ] ;
4350}
4451
4552const MAX_BUTTONS = 3 ;
4653
4754export default class ModalWidgetDialog extends React . PureComponent < IProps , IState > {
4855 private readonly widget : Widget ;
56+ private readonly possibleButtons : ModalButtonID [ ] ;
4957 private appFrame : React . RefObject < HTMLIFrameElement > = React . createRef ( ) ;
5058
51- state : IState = { } ;
59+ state : IState = {
60+ disabledButtonIds : [ ] ,
61+ } ;
5262
5363 constructor ( props ) {
5464 super ( props ) ;
@@ -58,6 +68,7 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
5868 creatorUserId : MatrixClientPeg . get ( ) . getUserId ( ) ,
5969 id : `modal_${ this . props . sourceWidgetId } ` ,
6070 } ) ;
71+ this . possibleButtons = ( this . props . widgetDefinition . buttons || [ ] ) . map ( b => b . id ) ;
6172 }
6273
6374 public componentDidMount ( ) {
@@ -79,12 +90,35 @@ export default class ModalWidgetDialog extends React.PureComponent<IProps, IStat
7990 private onLoad = ( ) => {
8091 this . state . messaging . once ( "ready" , this . onReady ) ;
8192 this . state . messaging . on ( `action:${ WidgetApiFromWidgetAction . CloseModalWidget } ` , this . onWidgetClose ) ;
93+ this . state . messaging . on ( `action:${ WidgetApiFromWidgetAction . SetModalButtonEnabled } ` , this . onButtonEnableToggle ) ;
8294 } ;
8395
8496 private onWidgetClose = ( ev : CustomEvent < IModalWidgetCloseRequest > ) => {
8597 this . props . onFinished ( true , ev . detail . data ) ;
8698 }
8799
100+ private onButtonEnableToggle = ( ev : CustomEvent < ISetModalButtonEnabledActionRequest > ) => {
101+ ev . preventDefault ( ) ;
102+ const isClose = ev . detail . data . button === BuiltInModalButtonID . Close ;
103+ if ( isClose || ! this . possibleButtons . includes ( ev . detail . data . button ) ) {
104+ return this . state . messaging . transport . reply ( ev . detail , {
105+ error : { message : "Invalid button" } ,
106+ } as IWidgetApiErrorResponseData ) ;
107+ }
108+
109+ let buttonIds : ModalButtonID [ ] ;
110+ if ( ev . detail . data . enabled ) {
111+ buttonIds = arrayFastClone ( this . state . disabledButtonIds ) . filter ( i => i !== ev . detail . data . button ) ;
112+ } else {
113+ // use a set to swap the operation to avoid memory leaky arrays.
114+ const tempSet = new Set ( this . state . disabledButtonIds ) ;
115+ tempSet . add ( ev . detail . data . button ) ;
116+ buttonIds = Array . from ( tempSet ) ;
117+ }
118+ this . setState ( { disabledButtonIds : buttonIds } ) ;
119+ this . state . messaging . transport . reply ( ev . detail , { } as IWidgetApiAcknowledgeResponseData ) ;
120+ } ;
121+
88122 public render ( ) {
89123 const templated = this . widget . getCompleteUrl ( {
90124 currentRoomId : RoomViewStore . getRoomId ( ) ,
0 commit comments