@@ -7,6 +7,7 @@ import Reportable from 'interfaces/reportable';
77import UserJson from 'interfaces/user-json' ;
88import { route } from 'laroute' ;
99import * as _ from 'lodash' ;
10+ import { observer } from 'mobx-react' ;
1011import core from 'osu-core-singleton' ;
1112import * as React from 'react' ;
1213import { classWithModifiers , Modifiers } from 'utils/css' ;
@@ -42,6 +43,7 @@ interface State {
4243 backgroundLoaded : boolean ;
4344}
4445
46+ @observer
4547export class UserCard extends React . PureComponent < Props , State > {
4648 static defaultProps = {
4749 activated : false ,
@@ -70,6 +72,7 @@ export class UserCard extends React.PureComponent<Props, State> {
7072 backgroundLoaded : false ,
7173 } ;
7274
75+ private readonly popupMenuState = new PopupMenuState ( ) ;
7376 private url ?: string ;
7477
7578 private get canMessage ( ) {
@@ -123,7 +126,7 @@ export class UserCard extends React.PureComponent<Props, State> {
123126 this . props . modifiers ,
124127 this . props . mode ,
125128 // Setting the active modifiers from the parent causes unwanted renders unless deep comparison is used.
126- this . props . activated ? 'active' : 'highlightable' ,
129+ this . popupMenuState . active || this . props . activated ? 'active' : 'highlightable' ,
127130 ) ;
128131
129132 this . url = this . isUserVisible ? route ( 'users.show' , { user : this . user . id } ) : undefined ;
@@ -285,50 +288,15 @@ export class UserCard extends React.PureComponent<Props, State> {
285288 }
286289
287290 renderMenuButton ( ) {
288- if ( this . isSelf ) {
289- return null ;
290- }
291-
292- const items = ( state : PopupMenuState ) => (
293- < div className = 'simple-menu' >
294- { this . canMessage && (
295- < a
296- className = 'simple-menu__item js-login-required--click'
297- href = { route ( 'messages.users.show' , { user : this . user . id } ) }
298- onClick = { state . dismiss }
299- >
300- < span className = 'fas fa-envelope' />
301- { ` ${ trans ( 'users.card.send_message' ) } ` }
302- </ a >
303- ) }
304-
305- < a
306- className = 'simple-menu__item'
307- href = { giftSupporterTagUrl ( this . user ) }
308- onClick = { state . dismiss }
309- >
310- < span className = 'fas fa-gift' />
311- { ` ${ trans ( 'users.card.gift_supporter' ) } ` }
312- </ a >
313-
314- < BlockButton modifiers = 'inline' onClick = { state . dismiss } userId = { this . user . id } wrapperClass = 'simple-menu__item' />
315-
316- < ReportReportable
317- className = 'simple-menu__item'
318- icon
319- onFormOpen = { state . dismiss }
320- reportableId = { this . props . reportable ?. id ?? this . user . id . toString ( ) }
321- reportableType = { this . props . reportable ?. type ?? 'user' }
322- user = { this . user }
323- />
324- </ div >
325- ) ;
326-
327- return (
328- < div className = 'user-card__icon user-card__icon--menu' >
329- < PopupMenuPersistent > { items } </ PopupMenuPersistent >
330- </ div >
331- ) ;
291+ return this . isSelf
292+ ? null
293+ : (
294+ < div className = 'user-card__icon user-card__icon--menu' >
295+ < PopupMenuPersistent state = { this . popupMenuState } >
296+ { this . renderMenuItems }
297+ </ PopupMenuPersistent >
298+ </ div >
299+ ) ;
332300 }
333301
334302 renderStatusBar ( ) {
@@ -377,6 +345,46 @@ export class UserCard extends React.PureComponent<Props, State> {
377345 ) ;
378346 }
379347
348+ private readonly renderMenuItems = ( ) => (
349+ < div className = 'simple-menu' >
350+ { this . canMessage && (
351+ < a
352+ className = 'simple-menu__item js-login-required--click'
353+ href = { route ( 'messages.users.show' , { user : this . user . id } ) }
354+ onClick = { this . popupMenuState . dismiss }
355+ >
356+ < span className = 'fas fa-envelope' />
357+ { ` ${ trans ( 'users.card.send_message' ) } ` }
358+ </ a >
359+ ) }
360+
361+ < a
362+ className = 'simple-menu__item'
363+ href = { giftSupporterTagUrl ( this . user ) }
364+ onClick = { this . popupMenuState . dismiss }
365+ >
366+ < span className = 'fas fa-gift' />
367+ { ` ${ trans ( 'users.card.gift_supporter' ) } ` }
368+ </ a >
369+
370+ < BlockButton
371+ modifiers = 'inline'
372+ onClick = { this . popupMenuState . dismiss }
373+ userId = { this . user . id }
374+ wrapperClass = 'simple-menu__item'
375+ />
376+
377+ < ReportReportable
378+ className = 'simple-menu__item'
379+ icon
380+ onFormOpen = { this . popupMenuState . dismiss }
381+ reportableId = { this . props . reportable ?. id ?? this . user . id . toString ( ) }
382+ reportableType = { this . props . reportable ?. type ?? 'user' }
383+ user = { this . user }
384+ />
385+ </ div >
386+ ) ;
387+
380388 private renderUsername ( ) {
381389 const displayName = this . user . is_deleted ? trans ( 'users.deleted' ) : this . user . username ;
382390
0 commit comments