1
+ import type { TokenizationPayload } from './textMiddlewareUtils' ;
1
2
import {
2
3
getTokenizedSuggestionDisplayName ,
3
4
getTriggerCharWithToken ,
@@ -23,7 +24,7 @@ import type { Channel } from '../../../channel';
23
24
import { MAX_CHANNEL_MEMBER_COUNT_IN_CHANNEL_QUERY } from '../../../constants' ;
24
25
import type { TextComposerSuggestion } from '../../types' ;
25
26
26
- export type UserSuggestion = TextComposerSuggestion < UserResponse > ;
27
+ export type UserSuggestion = TextComposerSuggestion < UserResponse & TokenizationPayload > ;
27
28
28
29
// todo: the map is too small - Slavic letters with diacritics are missing for example
29
30
export const accentsMap : { [ key : string ] : string } = {
@@ -152,57 +153,53 @@ export class MentionsSearchSource extends BaseSearchSource<UserSuggestion> {
152
153
153
154
searchMembersLocally = ( searchQuery : string ) => {
154
155
const { textComposerText } = this . config ;
155
- if ( ! textComposerText ) return { items : [ ] } ;
156
+ if ( ! textComposerText ) return [ ] ;
156
157
157
- return {
158
- items : this . getMembersAndWatchers ( )
159
- . filter ( ( user ) => {
160
- if ( user . id === this . client . userID ) return false ;
161
- if ( ! searchQuery ) return true ;
162
-
163
- const updatedId = this . transliterate ( removeDiacritics ( user . id ) ) . toLowerCase ( ) ;
164
- const updatedName = this . transliterate (
165
- removeDiacritics ( user . name ) ,
166
- ) . toLowerCase ( ) ;
167
- const updatedQuery = this . transliterate (
168
- removeDiacritics ( searchQuery ) ,
169
- ) . toLowerCase ( ) ;
170
-
171
- const maxDistance = 3 ;
172
- const lastDigits = textComposerText . slice ( - ( maxDistance + 1 ) ) . includes ( '@' ) ;
173
-
174
- if ( updatedName ) {
175
- const levenshtein = calculateLevenshtein ( updatedQuery , updatedName ) ;
176
- if (
177
- updatedName . includes ( updatedQuery ) ||
178
- ( levenshtein <= maxDistance && lastDigits )
179
- ) {
180
- return true ;
181
- }
158
+ return this . getMembersAndWatchers ( )
159
+ . filter ( ( user ) => {
160
+ if ( user . id === this . client . userID ) return false ;
161
+ if ( ! searchQuery ) return true ;
162
+
163
+ const updatedId = this . transliterate ( removeDiacritics ( user . id ) ) . toLowerCase ( ) ;
164
+ const updatedName = this . transliterate ( removeDiacritics ( user . name ) ) . toLowerCase ( ) ;
165
+ const updatedQuery = this . transliterate (
166
+ removeDiacritics ( searchQuery ) ,
167
+ ) . toLowerCase ( ) ;
168
+
169
+ const maxDistance = 3 ;
170
+ const lastDigits = textComposerText . slice ( - ( maxDistance + 1 ) ) . includes ( '@' ) ;
171
+
172
+ if ( updatedName ) {
173
+ const levenshtein = calculateLevenshtein ( updatedQuery , updatedName ) ;
174
+ if (
175
+ updatedName . includes ( updatedQuery ) ||
176
+ ( levenshtein <= maxDistance && lastDigits )
177
+ ) {
178
+ return true ;
182
179
}
180
+ }
183
181
184
- const levenshtein = calculateLevenshtein ( updatedQuery , updatedId ) ;
182
+ const levenshtein = calculateLevenshtein ( updatedQuery , updatedId ) ;
185
183
186
- return (
187
- updatedId . includes ( updatedQuery ) || ( levenshtein <= maxDistance && lastDigits )
188
- ) ;
189
- } )
190
- . sort ( ( a , b ) => {
191
- if ( ! this . memberSort ) return ( a . name || '' ) . localeCompare ( b . name || '' ) ;
184
+ return (
185
+ updatedId . includes ( updatedQuery ) || ( levenshtein <= maxDistance && lastDigits )
186
+ ) ;
187
+ } )
188
+ . sort ( ( a , b ) => {
189
+ if ( ! this . memberSort ) return ( a . name || '' ) . localeCompare ( b . name || '' ) ;
192
190
193
- // Apply each sort criteria in order
194
- for ( const [ field , direction ] of Object . entries ( this . memberSort ) ) {
195
- const aValue = a [ field as keyof UserResponse ] ;
196
- const bValue = b [ field as keyof UserResponse ] ;
191
+ // Apply each sort criteria in order
192
+ for ( const [ field , direction ] of Object . entries ( this . memberSort ) ) {
193
+ const aValue = a [ field as keyof UserResponse ] ;
194
+ const bValue = b [ field as keyof UserResponse ] ;
197
195
198
- if ( aValue === bValue ) continue ;
199
- return direction === 1
200
- ? String ( aValue || '' ) . localeCompare ( String ( bValue || '' ) )
201
- : String ( bValue || '' ) . localeCompare ( String ( aValue || '' ) ) ;
202
- }
203
- return 0 ;
204
- } ) ,
205
- } ;
196
+ if ( aValue === bValue ) continue ;
197
+ return direction === 1
198
+ ? String ( aValue || '' ) . localeCompare ( String ( bValue || '' ) )
199
+ : String ( bValue || '' ) . localeCompare ( String ( aValue || '' ) ) ;
200
+ }
201
+ return 0 ;
202
+ } ) ;
206
203
} ;
207
204
208
205
prepareQueryUsersParams = ( searchQuery : string ) => ( {
@@ -240,32 +237,44 @@ export class MentionsSearchSource extends BaseSearchSource<UserSuggestion> {
240
237
queryUsers = async ( searchQuery : string ) => {
241
238
const { filters, sort, options } = this . prepareQueryUsersParams ( searchQuery ) ;
242
239
const { users } = await this . client . queryUsers ( filters , sort , options ) ;
243
- return { items : users } ;
240
+ return users ;
244
241
} ;
245
242
246
243
queryMembers = async ( searchQuery : string ) => {
247
244
const { filters, sort, options } = this . prepareQueryMembersParams ( searchQuery ) ;
248
245
const response = await this . channel . queryMembers ( filters , sort , options ) ;
249
246
250
- return { items : response . members . map ( ( member ) => member . user ) as UserResponse [ ] } ;
247
+ return response . members . map ( ( member ) => member . user ) as UserResponse [ ] ;
251
248
} ;
252
249
253
250
async query ( searchQuery : string ) {
254
- if ( this . config . mentionAllAppUsers ) {
255
- return await this . queryUsers ( searchQuery ) ;
256
- }
257
-
251
+ let users : UserResponse [ ] ;
258
252
const shouldSearchLocally =
259
253
this . allMembersLoadedWithInitialChannelQuery || ! searchQuery ;
260
254
261
- if ( shouldSearchLocally ) {
262
- return this . searchMembersLocally ( searchQuery ) ;
255
+ if ( this . config . mentionAllAppUsers ) {
256
+ users = await this . queryUsers ( searchQuery ) ;
257
+ } else if ( shouldSearchLocally ) {
258
+ users = this . searchMembersLocally ( searchQuery ) ;
259
+ } else {
260
+ users = await this . queryMembers ( searchQuery ) ;
263
261
}
264
262
265
- return await this . queryMembers ( searchQuery ) ;
263
+ return {
264
+ items : users . map (
265
+ ( user ) =>
266
+ ( {
267
+ ...user ,
268
+ ...getTokenizedSuggestionDisplayName ( {
269
+ displayName : user . name || user . id ,
270
+ searchToken : this . searchQuery ,
271
+ } ) ,
272
+ } ) as UserSuggestion ,
273
+ ) ,
274
+ } ;
266
275
}
267
276
268
- filterMutes = ( data : UserResponse [ ] ) => {
277
+ filterMutes = ( data : UserSuggestion [ ] ) => {
269
278
const { textComposerText } = this . config ;
270
279
if ( ! textComposerText ) return [ ] ;
271
280
@@ -285,19 +294,19 @@ export class MentionsSearchSource extends BaseSearchSource<UserSuggestion> {
285
294
) ;
286
295
} ;
287
296
288
- filterQueryResults ( items : UserResponse [ ] ) {
289
- return this . filterMutes ( items ) . map ( ( item ) => ( {
290
- ...item ,
291
- ...getTokenizedSuggestionDisplayName ( {
292
- displayName : item . name || item . id ,
293
- searchToken : this . searchQuery ,
294
- } ) ,
295
- } ) ) ;
297
+ filterQueryResults ( items : UserSuggestion [ ] ) {
298
+ return this . filterMutes ( items ) ;
296
299
}
297
300
}
298
301
299
302
const DEFAULT_OPTIONS : TextComposerMiddlewareOptions = { minChars : 1 , trigger : '@' } ;
300
303
304
+ const userSuggestionToUserResponse = ( suggestion : UserSuggestion ) : UserResponse => {
305
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
306
+ const { tokenizedDisplayName, ...userResponse } = suggestion ;
307
+ return userResponse ;
308
+ } ;
309
+
301
310
/**
302
311
* TextComposer middleware for mentions
303
312
* Usage:
@@ -397,7 +406,9 @@ export const createMentionsMiddleware = (
397
406
text : state . text ,
398
407
trigger : finalOptions . trigger ,
399
408
} ) ,
400
- mentionedUsers : state . mentionedUsers . concat ( selectedSuggestion ) ,
409
+ mentionedUsers : state . mentionedUsers . concat (
410
+ userSuggestionToUserResponse ( selectedSuggestion ) ,
411
+ ) ,
401
412
suggestions : undefined , // Clear suggestions after selection
402
413
} ,
403
414
} ) ;
0 commit comments