@@ -15,22 +15,25 @@ limitations under the License.
1515*/
1616import React from 'react' ;
1717import classNames from 'classnames' ;
18+ import { Room } from 'matrix-js-sdk/src/models/room' ;
1819import { _t , _td } from '../../../languageHandler' ;
1920import AppTile from '../elements/AppTile' ;
2021import { MatrixClientPeg } from '../../../MatrixClientPeg' ;
2122import * as sdk from '../../../index' ;
2223import dis from '../../../dispatcher/dispatcher' ;
2324import AccessibleButton from '../elements/AccessibleButton' ;
24- import WidgetUtils from '../../../utils/WidgetUtils' ;
25+ import WidgetUtils , { IWidgetEvent } from '../../../utils/WidgetUtils' ;
2526import PersistedElement from "../elements/PersistedElement" ;
2627import { IntegrationManagers } from "../../../integrations/IntegrationManagers" ;
2728import SettingsStore from "../../../settings/SettingsStore" ;
28- import { ContextMenu } from "../../structures/ContextMenu" ;
29+ import { ChevronFace , ContextMenu } from "../../structures/ContextMenu" ;
2930import { WidgetType } from "../../../widgets/WidgetType" ;
3031import AccessibleTooltipButton from "../elements/AccessibleTooltipButton" ;
3132import { Action } from "../../../dispatcher/actions" ;
3233import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore" ;
3334import { replaceableComponent } from "../../../utils/replaceableComponent" ;
35+ import { ActionPayload } from '../../../dispatcher/payloads' ;
36+ import ScalarAuthClient from '../../../ScalarAuthClient' ;
3437
3538// This should be below the dialog level (4000), but above the rest of the UI (1000-2000).
3639// We sit in a context menu, so this should be given to the context menu.
@@ -39,27 +42,35 @@ const STICKERPICKER_Z_INDEX = 3500;
3942// Key to store the widget's AppTile under in PersistedElement
4043const PERSISTED_ELEMENT_KEY = "stickerPicker" ;
4144
45+ interface IProps {
46+ room : Room ;
47+ }
48+
49+ interface IState {
50+ showStickers : boolean ;
51+ imError : string ;
52+ stickerpickerX : number ;
53+ stickerpickerY : number ;
54+ stickerpickerChevronOffset ?: number ;
55+ stickerpickerWidget : IWidgetEvent ;
56+ widgetId : string ;
57+ }
58+
4259@replaceableComponent ( "views.rooms.Stickerpicker" )
43- export default class Stickerpicker extends React . PureComponent {
60+ export default class Stickerpicker extends React . PureComponent < IProps , IState > {
4461 static currentWidget ;
4562
46- constructor ( props ) {
47- super ( props ) ;
48- this . _onShowStickersClick = this . _onShowStickersClick . bind ( this ) ;
49- this . _onHideStickersClick = this . _onHideStickersClick . bind ( this ) ;
50- this . _launchManageIntegrations = this . _launchManageIntegrations . bind ( this ) ;
51- this . _removeStickerpickerWidgets = this . _removeStickerpickerWidgets . bind ( this ) ;
52- this . _updateWidget = this . _updateWidget . bind ( this ) ;
53- this . _onWidgetAction = this . _onWidgetAction . bind ( this ) ;
54- this . _onResize = this . _onResize . bind ( this ) ;
55- this . _onFinished = this . _onFinished . bind ( this ) ;
63+ private dispatcherRef : string ;
5664
57- this . popoverWidth = 300 ;
58- this . popoverHeight = 300 ;
65+ private prevSentVisibility : boolean ;
5966
60- // This is loaded by _acquireScalarClient on an as-needed basis.
61- this . scalarClient = null ;
67+ private popoverWidth = 300 ;
68+ private popoverHeight = 300 ;
69+ // This is loaded by _acquireScalarClient on an as-needed basis.
70+ private scalarClient : ScalarAuthClient = null ;
6271
72+ constructor ( props : IProps ) {
73+ super ( props ) ;
6374 this . state = {
6475 showStickers : false ,
6576 imError : null ,
@@ -70,7 +81,7 @@ export default class Stickerpicker extends React.PureComponent {
7081 } ;
7182 }
7283
73- _acquireScalarClient ( ) {
84+ private acquireScalarClient ( ) : Promise < void | ScalarAuthClient > {
7485 if ( this . scalarClient ) return Promise . resolve ( this . scalarClient ) ;
7586 // TODO: Pick the right manager for the widget
7687 if ( IntegrationManagers . sharedInstance ( ) . hasManager ( ) ) {
@@ -79,15 +90,15 @@ export default class Stickerpicker extends React.PureComponent {
7990 this . forceUpdate ( ) ;
8091 return this . scalarClient ;
8192 } ) . catch ( ( e ) => {
82- this . _imError ( _td ( "Failed to connect to integration manager" ) , e ) ;
93+ this . imError ( _td ( "Failed to connect to integration manager" ) , e ) ;
8394 } ) ;
8495 } else {
8596 IntegrationManagers . sharedInstance ( ) . openNoManagerDialog ( ) ;
8697 }
8798 }
8899
89- async _removeStickerpickerWidgets ( ) {
90- const scalarClient = await this . _acquireScalarClient ( ) ;
100+ private removeStickerpickerWidgets = async ( ) : Promise < void > => {
101+ const scalarClient = await this . acquireScalarClient ( ) ;
91102 console . log ( 'Removing Stickerpicker widgets' ) ;
92103 if ( this . state . widgetId ) {
93104 if ( scalarClient ) {
@@ -109,44 +120,44 @@ export default class Stickerpicker extends React.PureComponent {
109120 } ) . catch ( ( e ) => {
110121 console . error ( 'Failed to remove sticker picker widget' , e ) ;
111122 } ) ;
112- }
123+ } ;
113124
114- componentDidMount ( ) {
125+ public componentDidMount ( ) : void {
115126 // Close the sticker picker when the window resizes
116- window . addEventListener ( 'resize' , this . _onResize ) ;
127+ window . addEventListener ( 'resize' , this . onResize ) ;
117128
118- this . dispatcherRef = dis . register ( this . _onWidgetAction ) ;
129+ this . dispatcherRef = dis . register ( this . onWidgetAction ) ;
119130
120131 // Track updates to widget state in account data
121- MatrixClientPeg . get ( ) . on ( 'accountData' , this . _updateWidget ) ;
132+ MatrixClientPeg . get ( ) . on ( 'accountData' , this . updateWidget ) ;
122133
123134 // Initialise widget state from current account data
124- this . _updateWidget ( ) ;
135+ this . updateWidget ( ) ;
125136 }
126137
127- componentWillUnmount ( ) {
138+ public componentWillUnmount ( ) : void {
128139 const client = MatrixClientPeg . get ( ) ;
129- if ( client ) client . removeListener ( 'accountData' , this . _updateWidget ) ;
140+ if ( client ) client . removeListener ( 'accountData' , this . updateWidget ) ;
130141
131- window . removeEventListener ( 'resize' , this . _onResize ) ;
142+ window . removeEventListener ( 'resize' , this . onResize ) ;
132143 if ( this . dispatcherRef ) {
133144 dis . unregister ( this . dispatcherRef ) ;
134145 }
135146 }
136147
137- componentDidUpdate ( prevProps , prevState ) {
138- this . _sendVisibilityToWidget ( this . state . showStickers ) ;
148+ public componentDidUpdate ( prevProps : IProps , prevState : IState ) : void {
149+ this . sendVisibilityToWidget ( this . state . showStickers ) ;
139150 }
140151
141- _imError ( errorMsg , e ) {
152+ private imError ( errorMsg : string , e : Error ) : void {
142153 console . error ( errorMsg , e ) ;
143154 this . setState ( {
144155 showStickers : false ,
145156 imError : _t ( errorMsg ) ,
146157 } ) ;
147158 }
148159
149- _updateWidget ( ) {
160+ private updateWidget = ( ) : void => {
150161 const stickerpickerWidget = WidgetUtils . getStickerpickerWidgets ( ) [ 0 ] ;
151162 if ( ! stickerpickerWidget ) {
152163 Stickerpicker . currentWidget = null ;
@@ -175,9 +186,9 @@ export default class Stickerpicker extends React.PureComponent {
175186 stickerpickerWidget,
176187 widgetId : stickerpickerWidget ? stickerpickerWidget . id : null ,
177188 } ) ;
178- }
189+ } ;
179190
180- _onWidgetAction ( payload ) {
191+ private onWidgetAction = ( payload : ActionPayload ) : void => {
181192 switch ( payload . action ) {
182193 case "user_widget_updated" :
183194 this . forceUpdate ( ) ;
@@ -191,11 +202,11 @@ export default class Stickerpicker extends React.PureComponent {
191202 this . setState ( { showStickers : false } ) ;
192203 break ;
193204 }
194- }
205+ } ;
195206
196- _defaultStickerpickerContent ( ) {
207+ private defaultStickerpickerContent ( ) : JSX . Element {
197208 return (
198- < AccessibleButton onClick = { this . _launchManageIntegrations }
209+ < AccessibleButton onClick = { this . launchManageIntegrations }
199210 className = 'mx_Stickers_contentPlaceholder' >
200211 < p > { _t ( "You don't currently have any stickerpacks enabled" ) } </ p >
201212 < p className = 'mx_Stickers_addLink' > { _t ( "Add some now" ) } </ p >
@@ -204,29 +215,29 @@ export default class Stickerpicker extends React.PureComponent {
204215 ) ;
205216 }
206217
207- _errorStickerpickerContent ( ) {
218+ private errorStickerpickerContent ( ) : JSX . Element {
208219 return (
209- < div style = { { "text-align" : "center" } } className = "error" >
220+ < div style = { { textAlign : "center" } } className = "error" >
210221 < p > { this . state . imError } </ p >
211222 </ div >
212223 ) ;
213224 }
214225
215- _sendVisibilityToWidget ( visible ) {
226+ private sendVisibilityToWidget ( visible : boolean ) : void {
216227 if ( ! this . state . stickerpickerWidget ) return ;
217228 const messaging = WidgetMessagingStore . instance . getMessagingForId ( this . state . stickerpickerWidget . id ) ;
218- if ( messaging && visible !== this . _prevSentVisibility ) {
229+ if ( messaging && visible !== this . prevSentVisibility ) {
219230 messaging . updateVisibility ( visible ) . catch ( err => {
220231 console . error ( "Error updating widget visibility: " , err ) ;
221232 } ) ;
222- this . _prevSentVisibility = visible ;
233+ this . prevSentVisibility = visible ;
223234 }
224235 }
225236
226- _getStickerpickerContent ( ) {
237+ public getStickerpickerContent ( ) : JSX . Element {
227238 // Handle integration manager errors
228- if ( this . state . _imError ) {
229- return this . _errorStickerpickerContent ( ) ;
239+ if ( this . state . imError ) {
240+ return this . errorStickerpickerContent ( ) ;
230241 }
231242
232243 // Stickers
@@ -244,7 +255,7 @@ export default class Stickerpicker extends React.PureComponent {
244255 // Load stickerpack content
245256 if ( stickerpickerWidget && stickerpickerWidget . content && stickerpickerWidget . content . url ) {
246257 // Set default name
247- stickerpickerWidget . content . name = stickerpickerWidget . name || _t ( "Stickerpack" ) ;
258+ stickerpickerWidget . content . name = stickerpickerWidget . content . name || _t ( "Stickerpack" ) ;
248259
249260 // FIXME: could this use the same code as other apps?
250261 const stickerApp = {
@@ -275,12 +286,12 @@ export default class Stickerpicker extends React.PureComponent {
275286 creatorUserId = { stickerpickerWidget . sender || MatrixClientPeg . get ( ) . credentials . userId }
276287 waitForIframeLoad = { true }
277288 showMenubar = { true }
278- onEditClick = { this . _launchManageIntegrations }
279- onDeleteClick = { this . _removeStickerpickerWidgets }
289+ onEditClick = { this . launchManageIntegrations }
290+ onDeleteClick = { this . removeStickerpickerWidgets }
280291 showTitle = { false }
281292 showCancel = { false }
282293 showPopout = { false }
283- onMinimiseClick = { this . _onHideStickersClick }
294+ onMinimiseClick = { this . onHideStickersClick }
284295 handleMinimisePointerEvents = { true }
285296 userWidget = { true }
286297 />
@@ -290,7 +301,7 @@ export default class Stickerpicker extends React.PureComponent {
290301 ) ;
291302 } else {
292303 // Default content to show if stickerpicker widget not added
293- stickersContent = this . _defaultStickerpickerContent ( ) ;
304+ stickersContent = this . defaultStickerpickerContent ( ) ;
294305 }
295306 return stickersContent ;
296307 }
@@ -300,15 +311,15 @@ export default class Stickerpicker extends React.PureComponent {
300311 * Show the sticker picker overlay
301312 * If no stickerpacks have been added, show a link to the integration manager add sticker packs page.
302313 */
303- _onShowStickersClick ( e ) {
314+ private onShowStickersClick = ( e : React . MouseEvent < HTMLElement > ) : void => {
304315 if ( ! SettingsStore . getValue ( "integrationProvisioning" ) ) {
305316 // Intercept this case and spawn a warning.
306317 return IntegrationManagers . sharedInstance ( ) . showDisabledDialog ( ) ;
307318 }
308319
309320 // XXX: Simplify by using a context menu that is positioned relative to the sticker picker button
310321
311- const buttonRect = e . target . getBoundingClientRect ( ) ;
322+ const buttonRect = e . currentTarget . getBoundingClientRect ( ) ;
312323
313324 // The window X and Y offsets are to adjust position when zoomed in to page
314325 let x = buttonRect . right + window . pageXOffset - 41 ;
@@ -324,50 +335,50 @@ export default class Stickerpicker extends React.PureComponent {
324335 // Offset the chevron location, which is relative to the left of the context menu
325336 // (10 = offset when context menu would not be displayed off viewport)
326337 // (2 = context menu borders)
327- const stickerPickerChevronOffset = Math . max ( 10 , 2 + window . pageXOffset + buttonRect . left - x ) ;
338+ const stickerpickerChevronOffset = Math . max ( 10 , 2 + window . pageXOffset + buttonRect . left - x ) ;
328339
329340 const y = ( buttonRect . top + ( buttonRect . height / 2 ) + window . pageYOffset ) - 19 ;
330341
331342 this . setState ( {
332343 showStickers : true ,
333- stickerPickerX : x ,
334- stickerPickerY : y ,
335- stickerPickerChevronOffset ,
344+ stickerpickerX : x ,
345+ stickerpickerY : y ,
346+ stickerpickerChevronOffset ,
336347 } ) ;
337- }
348+ } ;
338349
339350 /**
340351 * Trigger hiding of the sticker picker overlay
341352 * @param {Event } ev Event that triggered the function call
342353 */
343- _onHideStickersClick ( ev ) {
354+ private onHideStickersClick = ( ev : React . MouseEvent ) : void => {
344355 if ( this . state . showStickers ) {
345356 this . setState ( { showStickers : false } ) ;
346357 }
347- }
358+ } ;
348359
349360 /**
350361 * Called when the window is resized
351362 */
352- _onResize ( ) {
363+ private onResize = ( ) : void => {
353364 if ( this . state . showStickers ) {
354365 this . setState ( { showStickers : false } ) ;
355366 }
356- }
367+ } ;
357368
358369 /**
359370 * The stickers picker was hidden
360371 */
361- _onFinished ( ) {
372+ private onFinished = ( ) : void => {
362373 if ( this . state . showStickers ) {
363374 this . setState ( { showStickers : false } ) ;
364375 }
365- }
376+ } ;
366377
367378 /**
368379 * Launch the integration manager on the stickers integration page
369380 */
370- _launchManageIntegrations = ( ) => {
381+ private launchManageIntegrations = ( ) : void => {
371382 // TODO: Open the right integration manager for the widget
372383 if ( SettingsStore . getValue ( "feature_many_integration_managers" ) ) {
373384 IntegrationManagers . sharedInstance ( ) . openAll (
@@ -384,7 +395,7 @@ export default class Stickerpicker extends React.PureComponent {
384395 }
385396 } ;
386397
387- render ( ) {
398+ public render ( ) : JSX . Element {
388399 let stickerPicker ;
389400 let stickersButton ;
390401 const className = classNames (
@@ -400,26 +411,25 @@ export default class Stickerpicker extends React.PureComponent {
400411 id = 'stickersButton'
401412 key = "controls_hide_stickers"
402413 className = { className }
403- onClick = { this . _onHideStickersClick }
404- active = { this . state . showStickers . toString ( ) }
414+ onClick = { this . onHideStickersClick }
405415 title = { _t ( "Hide Stickers" ) }
406416 /> ;
407417
408418 const GenericElementContextMenu = sdk . getComponent ( 'context_menus.GenericElementContextMenu' ) ;
409419 stickerPicker = < ContextMenu
410- chevronOffset = { this . state . stickerPickerChevronOffset }
411- chevronFace = "bottom"
412- left = { this . state . stickerPickerX }
413- top = { this . state . stickerPickerY }
420+ chevronOffset = { this . state . stickerpickerChevronOffset }
421+ chevronFace = { ChevronFace . Bottom }
422+ left = { this . state . stickerpickerX }
423+ top = { this . state . stickerpickerY }
414424 menuWidth = { this . popoverWidth }
415425 menuHeight = { this . popoverHeight }
416- onFinished = { this . _onFinished }
426+ onFinished = { this . onFinished }
417427 menuPaddingTop = { 0 }
418428 menuPaddingLeft = { 0 }
419429 menuPaddingRight = { 0 }
420430 zIndex = { STICKERPICKER_Z_INDEX }
421431 >
422- < GenericElementContextMenu element = { this . _getStickerpickerContent ( ) } onResize = { this . _onFinished } />
432+ < GenericElementContextMenu element = { this . getStickerpickerContent ( ) } onResize = { this . onFinished } />
423433 </ ContextMenu > ;
424434 } else {
425435 // Show show-stickers button
@@ -428,7 +438,7 @@ export default class Stickerpicker extends React.PureComponent {
428438 id = 'stickersButton'
429439 key = "controls_show_stickers"
430440 className = "mx_MessageComposer_button mx_MessageComposer_stickers"
431- onClick = { this . _onShowStickersClick }
441+ onClick = { this . onShowStickersClick }
432442 title = { _t ( "Show Stickers" ) }
433443 /> ;
434444 }
0 commit comments