22import * as React from 'react' ;
33import compose from 'recompose/compose' ;
44import { connect } from 'react-redux' ;
5- import { Mention } from 'react-mentions' ;
6- import { withApollo } from 'react-apollo' ;
75import Icon from 'src/components/icons' ;
8- import { FlexRow } from 'src/components/globals' ;
96import { addToastWithTimeout } from 'src/actions/toasts' ;
107import { openModal } from 'src/actions/modals' ;
118import { replyToMessage } from 'src/actions/message' ;
129import { withCurrentUser } from 'src/components/withCurrentUser' ;
13- import { UserAvatar } from 'src/components/avatar' ;
1410import {
1511 Form ,
1612 ChatInputContainer ,
@@ -23,30 +19,13 @@ import {
2319 Preformatted ,
2420 PreviewWrapper ,
2521 RemovePreviewButton ,
26- StyledMentionSuggestion ,
27- SuggestionsWrapper ,
28- MentionUsername ,
29- MentionContent ,
30- MentionName ,
3122} from './style' ;
3223import sendMessage from 'shared/graphql/mutations/message/sendMessage' ;
3324import sendDirectMessage from 'shared/graphql/mutations/message/sendDirectMessage' ;
34- import { searchUsersQuery } from 'shared/graphql/queries/search/searchUsers' ;
3525import { getMessageById } from 'shared/graphql/queries/message/getMessage' ;
3626import MediaUploader from './components/mediaUploader' ;
3727import { QuotedMessage as QuotedMessageComponent } from '../message/view' ;
3828import type { Dispatch } from 'redux' ;
39- import { ESC , BACKSPACE , DELETE } from 'src/helpers/keycodes' ;
40-
41- const MentionSuggestion = ( { entry, search, focused } ) => (
42- < StyledMentionSuggestion focused = { focused } >
43- < UserAvatar size = { 32 } user = { entry } />
44- < MentionContent >
45- < MentionName focused = { focused } > { entry . name } </ MentionName >
46- < MentionUsername focused = { focused } > @{ entry . username } </ MentionUsername >
47- </ MentionContent >
48- </ StyledMentionSuggestion >
49- ) ;
5029
5130const QuotedMessage = connect ( ) (
5231 getMessageById ( props => {
@@ -93,6 +72,16 @@ type Props = {
9372 onBlur : ?Function ,
9473} ;
9574
75+ export const cleanSuggestionUserObject = ( user : ?Object ) => {
76+ if ( ! user ) return null ;
77+ return {
78+ ...user ,
79+ id : user . username ,
80+ display : user . username ,
81+ filterName : user . name . toLowerCase ( ) ,
82+ } ;
83+ } ;
84+
9685// $FlowFixMe
9786const ChatInput = ( props : Props ) => {
9887 const cacheKey = `last-content-${ props . thread } ` ;
@@ -243,7 +232,9 @@ const ChatInput = (props: Props) => {
243232
244233 if ( text . length === 0 ) return ;
245234
246- sendMessage ( { body : text } )
235+ // workaround react-mentions bug by replacing @[username] with @username
236+ // @see withspectrum/spectrum#4587
237+ sendMessage ( { body : text . replace ( / @ \[ ( [ a - z 0 - 9 _ - ] + ) \] / g, '@$1' ) } )
247238 . then ( ( ) => {
248239 // If we're viewing a thread and the user sends a message as a non-member, we need to refetch the thread data
249240 if (
@@ -297,85 +288,6 @@ const ChatInput = (props: Props) => {
297288 ) ;
298289 } ;
299290
300- const sortSuggestions = ( a , b , queryString ) = > {
301- const aUsernameIndex = a . username . indexOf ( queryString || '' ) ;
302- const bUsernameIndex = b . username . indexOf ( queryString || '' ) ;
303- const aNameIndex = a . filterName . indexOf ( queryString || '' ) ;
304- const bNameIndex = b . filterName . indexOf ( queryString || '' ) ;
305- if ( aNameIndex === 0 ) return - 1 ;
306- if ( aUsernameIndex === 0 ) return - 1 ;
307- if ( aNameIndex === 0 ) return - 1 ;
308- if ( aUsernameIndex === 0 ) return - 1 ;
309- return aNameIndex - bNameIndex || aUsernameIndex - bUsernameIndex ;
310- } ;
311-
312- const searchUsers = async ( queryString , callback ) => {
313- const filteredParticipants = props . participants
314- ? props . participants
315- . filter ( Boolean )
316- . filter ( participant => {
317- return (
318- participant . username &&
319- ( participant . username . indexOf ( queryString || '' ) > - 1 ||
320- participant . filterName . indexOf ( queryString || '' ) > - 1 )
321- ) ;
322- } )
323- . sort ( ( a , b ) => {
324- return sortSuggestions ( a , b , queryString ) ;
325- } )
326- . slice ( 0 , 8 )
327- : [ ] ;
328-
329- callback ( filteredParticipants ) ;
330-
331- if ( ! queryString || queryString . length === 0 )
332- return callback ( filteredParticipants ) ;
333-
334- const {
335- data : { search } ,
336- } = await props . client . query ( {
337- query : searchUsersQuery ,
338- variables : {
339- queryString,
340- type : 'USERS' ,
341- } ,
342- } ) ;
343-
344- if ( ! search || ! search . searchResultsConnection ) {
345- if ( filteredParticipants && filteredParticipants . length > 0 )
346- return filteredParticipants ;
347- return ;
348- }
349-
350- let searchUsers = search . searchResultsConnection . edges
351- . filter ( Boolean )
352- . filter ( edge => edge . node . username )
353- . map ( edge => {
354- const user = edge . node ;
355- return {
356- ...user ,
357- id : user . username ,
358- display : user . username ,
359- username : user . username ,
360- filterName : user . name . toLowerCase ( ) ,
361- } ;
362- } ) ;
363-
364- // Prepend the filtered participants in case a user is tabbing down right now
365- const fullResults = [ ...filteredParticipants , ...searchUsers ] ;
366- const uniqueResults = [ ] ;
367- const done = [ ] ;
368-
369- fullResults . forEach ( item => {
370- if ( done . indexOf ( item . username ) === - 1 ) {
371- uniqueResults . push ( item ) ;
372- done . push ( item . username ) ;
373- }
374- } ) ;
375-
376- return callback ( uniqueResults . slice ( 0 , 8 ) ) ;
377- } ;
378-
379291 const networkDisabled =
380292 ! props . networkOnline ||
381293 ( props . websocketConnection !== 'connected' &&
@@ -443,28 +355,8 @@ const ChatInput = (props: Props) => {
443355 if ( props . onRef ) props . onRef ( node ) ;
444356 setInputRef ( node ) ;
445357 } }
446- >
447- < Mention
448- trigger = "@"
449- data = { searchUsers }
450- appendSpaceOnAdd = { true }
451- renderSuggestion = { (
452- entry ,
453- search ,
454- highlightedDisplay ,
455- index ,
456- focused
457- ) => (
458- < MentionSuggestion
459- entry = { entry }
460- highlightedDisplay = { highlightedDisplay }
461- focused = { focused }
462- search = { search }
463- index = { index }
464- />
465- ) }
466- />
467- </ Input >
358+ staticSuggestions = { props . participants }
359+ />
468360 </ InputWrapper >
469361 < SendButton
470362 data-cy = "chat-input-send-button"
@@ -494,7 +386,6 @@ const map = (state, ownProps) => ({
494386
495387export default compose (
496388 withCurrentUser ,
497- withApollo ,
498389 sendMessage ,
499390 sendDirectMessage ,
500391 // $FlowIssue
0 commit comments