@@ -308,10 +308,14 @@ export default class InviteDialog extends React.PureComponent {
308308
309309 // The room ID this dialog is for. Only required for KIND_INVITE.
310310 roomId : PropTypes . string ,
311+
312+ // Initial value to populate the filter with
313+ initialText : PropTypes . string ,
311314 } ;
312315
313316 static defaultProps = {
314317 kind : KIND_DM ,
318+ initialText : "" ,
315319 } ;
316320
317321 _debounceTimer : number = null ;
@@ -338,7 +342,7 @@ export default class InviteDialog extends React.PureComponent {
338342
339343 this . state = {
340344 targets : [ ] , // array of Member objects (see interface above)
341- filterText : "" ,
345+ filterText : this . props . initialText ,
342346 recents : InviteDialog . buildRecents ( alreadyInvited ) ,
343347 numRecentsShown : INITIAL_ROOMS_SHOWN ,
344348 suggestions : this . _buildSuggestions ( alreadyInvited ) ,
@@ -356,6 +360,12 @@ export default class InviteDialog extends React.PureComponent {
356360 this . _editorRef = createRef ( ) ;
357361 }
358362
363+ componentDidMount ( ) {
364+ if ( this . props . initialText ) {
365+ this . _updateSuggestions ( this . props . initialText ) ;
366+ }
367+ }
368+
359369 static buildRecents ( excludedTargetIds : Set < string > ) : { userId : string , user : RoomMember , lastActive : number } {
360370 const rooms = DMRoomMap . shared ( ) . getUniqueRoomsWithIndividuals ( ) ; // map of userId => js-sdk Room
361371
@@ -687,123 +697,127 @@ export default class InviteDialog extends React.PureComponent {
687697 }
688698 } ;
689699
690- _updateFilter = ( e ) => {
691- const term = e . target . value ;
692- this . setState ( { filterText : term } ) ;
700+ _updateSuggestions = async ( term ) => {
701+ MatrixClientPeg . get ( ) . searchUserDirectory ( { term} ) . then ( async r => {
702+ if ( term !== this . state . filterText ) {
703+ // Discard the results - we were probably too slow on the server-side to make
704+ // these results useful. This is a race we want to avoid because we could overwrite
705+ // more accurate results.
706+ return ;
707+ }
693708
694- // Debounce server lookups to reduce spam. We don't clear the existing server
695- // results because they might still be vaguely accurate, likewise for races which
696- // could happen here.
697- if ( this . _debounceTimer ) {
698- clearTimeout ( this . _debounceTimer ) ;
699- }
700- this . _debounceTimer = setTimeout ( async ( ) => {
701- MatrixClientPeg . get ( ) . searchUserDirectory ( { term} ) . then ( async r => {
702- if ( term !== this . state . filterText ) {
703- // Discard the results - we were probably too slow on the server-side to make
704- // these results useful. This is a race we want to avoid because we could overwrite
705- // more accurate results.
706- return ;
707- }
709+ if ( ! r . results ) r . results = [ ] ;
708710
709- if ( ! r . results ) r . results = [ ] ;
710-
711- // While we're here, try and autocomplete a search result for the mxid itself
712- // if there's no matches (and the input looks like a mxid).
713- if ( term [ 0 ] === '@' && term . indexOf ( ':' ) > 1 ) {
714- try {
715- const profile = await MatrixClientPeg . get ( ) . getProfileInfo ( term ) ;
716- if ( profile ) {
717- // If we have a profile, we have enough information to assume that
718- // the mxid can be invited - add it to the list. We stick it at the
719- // top so it is most obviously presented to the user.
720- r . results . splice ( 0 , 0 , {
721- user_id : term ,
722- display_name : profile [ 'displayname' ] ,
723- avatar_url : profile [ 'avatar_url' ] ,
724- } ) ;
725- }
726- } catch ( e ) {
727- console . warn ( "Non-fatal error trying to make an invite for a user ID" ) ;
728- console . warn ( e ) ;
729-
730- // Add a result anyways, just without a profile. We stick it at the
711+ // While we're here, try and autocomplete a search result for the mxid itself
712+ // if there's no matches (and the input looks like a mxid).
713+ if ( term [ 0 ] === '@' && term . indexOf ( ':' ) > 1 ) {
714+ try {
715+ const profile = await MatrixClientPeg . get ( ) . getProfileInfo ( term ) ;
716+ if ( profile ) {
717+ // If we have a profile, we have enough information to assume that
718+ // the mxid can be invited - add it to the list. We stick it at the
731719 // top so it is most obviously presented to the user.
732720 r . results . splice ( 0 , 0 , {
733721 user_id : term ,
734- display_name : term ,
735- avatar_url : null ,
722+ display_name : profile [ 'displayname' ] ,
723+ avatar_url : profile [ 'avatar_url' ] ,
736724 } ) ;
737725 }
726+ } catch ( e ) {
727+ console . warn ( "Non-fatal error trying to make an invite for a user ID" ) ;
728+ console . warn ( e ) ;
729+
730+ // Add a result anyways, just without a profile. We stick it at the
731+ // top so it is most obviously presented to the user.
732+ r . results . splice ( 0 , 0 , {
733+ user_id : term ,
734+ display_name : term ,
735+ avatar_url : null ,
736+ } ) ;
738737 }
738+ }
739739
740- this . setState ( {
741- serverResultsMixin : r . results . map ( u => ( {
742- userId : u . user_id ,
743- user : new DirectoryMember ( u ) ,
744- } ) ) ,
745- } ) ;
746- } ) . catch ( e => {
747- console . error ( "Error searching user directory:" ) ;
748- console . error ( e ) ;
749- this . setState ( { serverResultsMixin : [ ] } ) ; // clear results because it's moderately fatal
740+ this . setState ( {
741+ serverResultsMixin : r . results . map ( u => ( {
742+ userId : u . user_id ,
743+ user : new DirectoryMember ( u ) ,
744+ } ) ) ,
750745 } ) ;
746+ } ) . catch ( e => {
747+ console . error ( "Error searching user directory:" ) ;
748+ console . error ( e ) ;
749+ this . setState ( { serverResultsMixin : [ ] } ) ; // clear results because it's moderately fatal
750+ } ) ;
751751
752- // Whenever we search the directory, also try to search the identity server. It's
753- // all debounced the same anyways.
754- if ( ! this . state . canUseIdentityServer ) {
755- // The user doesn't have an identity server set - warn them of that.
756- this . setState ( { tryingIdentityServer : true } ) ;
757- return ;
758- }
759- if ( term . indexOf ( '@' ) > 0 && Email . looksValid ( term ) && SettingsStore . getValue ( UIFeature . IdentityServer ) ) {
760- // Start off by suggesting the plain email while we try and resolve it
761- // to a real account.
762- this . setState ( {
763- // per above: the userId is a lie here - it's just a regular identifier
764- threepidResultsMixin : [ { user : new ThreepidMember ( term ) , userId : term } ] ,
765- } ) ;
766- try {
767- const authClient = new IdentityAuthClient ( ) ;
768- const token = await authClient . getAccessToken ( ) ;
769- if ( term !== this . state . filterText ) return ; // abandon hope
770-
771- const lookup = await MatrixClientPeg . get ( ) . lookupThreePid (
772- 'email' ,
773- term ,
774- undefined , // callback
775- token ,
776- ) ;
777- if ( term !== this . state . filterText ) return ; // abandon hope
778-
779- if ( ! lookup || ! lookup . mxid ) {
780- // We weren't able to find anyone - we're already suggesting the plain email
781- // as an alternative, so do nothing.
782- return ;
783- }
752+ // Whenever we search the directory, also try to search the identity server. It's
753+ // all debounced the same anyways.
754+ if ( ! this . state . canUseIdentityServer ) {
755+ // The user doesn't have an identity server set - warn them of that.
756+ this . setState ( { tryingIdentityServer : true } ) ;
757+ return ;
758+ }
759+ if ( term . indexOf ( '@' ) > 0 && Email . looksValid ( term ) && SettingsStore . getValue ( UIFeature . IdentityServer ) ) {
760+ // Start off by suggesting the plain email while we try and resolve it
761+ // to a real account.
762+ this . setState ( {
763+ // per above: the userId is a lie here - it's just a regular identifier
764+ threepidResultsMixin : [ { user : new ThreepidMember ( term ) , userId : term } ] ,
765+ } ) ;
766+ try {
767+ const authClient = new IdentityAuthClient ( ) ;
768+ const token = await authClient . getAccessToken ( ) ;
769+ if ( term !== this . state . filterText ) return ; // abandon hope
770+
771+ const lookup = await MatrixClientPeg . get ( ) . lookupThreePid (
772+ 'email' ,
773+ term ,
774+ undefined , // callback
775+ token ,
776+ ) ;
777+ if ( term !== this . state . filterText ) return ; // abandon hope
784778
785- // We append the user suggestion to give the user an option to click
786- // the email anyways, and so we don't cause things to jump around. In
787- // theory, the user would see the user pop up and think "ah yes, that
788- // person!"
789- const profile = await MatrixClientPeg . get ( ) . getProfileInfo ( lookup . mxid ) ;
790- if ( term !== this . state . filterText || ! profile ) return ; // abandon hope
791- this . setState ( {
792- threepidResultsMixin : [ ...this . state . threepidResultsMixin , {
793- user : new DirectoryMember ( {
794- user_id : lookup . mxid ,
795- display_name : profile . displayname ,
796- avatar_url : profile . avatar_url ,
797- } ) ,
798- userId : lookup . mxid ,
799- } ] ,
800- } ) ;
801- } catch ( e ) {
802- console . error ( "Error searching identity server:" ) ;
803- console . error ( e ) ;
804- this . setState ( { threepidResultsMixin : [ ] } ) ; // clear results because it's moderately fatal
779+ if ( ! lookup || ! lookup . mxid ) {
780+ // We weren't able to find anyone - we're already suggesting the plain email
781+ // as an alternative, so do nothing.
782+ return ;
805783 }
784+
785+ // We append the user suggestion to give the user an option to click
786+ // the email anyways, and so we don't cause things to jump around. In
787+ // theory, the user would see the user pop up and think "ah yes, that
788+ // person!"
789+ const profile = await MatrixClientPeg . get ( ) . getProfileInfo ( lookup . mxid ) ;
790+ if ( term !== this . state . filterText || ! profile ) return ; // abandon hope
791+ this . setState ( {
792+ threepidResultsMixin : [ ...this . state . threepidResultsMixin , {
793+ user : new DirectoryMember ( {
794+ user_id : lookup . mxid ,
795+ display_name : profile . displayname ,
796+ avatar_url : profile . avatar_url ,
797+ } ) ,
798+ userId : lookup . mxid ,
799+ } ] ,
800+ } ) ;
801+ } catch ( e ) {
802+ console . error ( "Error searching identity server:" ) ;
803+ console . error ( e ) ;
804+ this . setState ( { threepidResultsMixin : [ ] } ) ; // clear results because it's moderately fatal
806805 }
806+ }
807+ } ;
808+
809+ _updateFilter = ( e ) => {
810+ const term = e . target . value ;
811+ this . setState ( { filterText : term } ) ;
812+
813+ // Debounce server lookups to reduce spam. We don't clear the existing server
814+ // results because they might still be vaguely accurate, likewise for races which
815+ // could happen here.
816+ if ( this . _debounceTimer ) {
817+ clearTimeout ( this . _debounceTimer ) ;
818+ }
819+ this . _debounceTimer = setTimeout ( ( ) => {
820+ this . _updateSuggestions ( term ) ;
807821 } , 150 ) ; // 150ms debounce (human reaction time + some)
808822 } ;
809823
0 commit comments