@@ -4,59 +4,64 @@ import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
44import { escapeRegExp } from '@rocket.chat/string-helpers' ;
55import { RoomAvatar , UserAvatar } from '@rocket.chat/ui-avatar' ;
66import { useUser , useUserSubscriptions } from '@rocket.chat/ui-contexts' ;
7- import type { ComponentProps , ReactElement } from 'react' ;
8- import { memo , useCallback , useMemo , useState } from 'react' ;
7+ import type { ComponentProps } from 'react' ;
8+ import { memo , useMemo , useState } from 'react' ;
99
1010import { Rooms } from '../../../app/models/client' ;
11- import { useReactiveValue } from '../../hooks/useReactiveValue' ;
1211import { roomCoordinator } from '../../lib/rooms/roomCoordinator' ;
1312
14- type UserAndRoomAutoCompleteMultipleProps = Omit < ComponentProps < typeof AutoComplete > , 'filter' > ;
13+ type UserAndRoomAutoCompleteMultipleProps = Omit < ComponentProps < typeof AutoComplete > , 'filter' > & { limit ?: number } ;
1514
16- const UserAndRoomAutoCompleteMultiple = ( { value, onChange, ...props } : UserAndRoomAutoCompleteMultipleProps ) : ReactElement => {
15+ const UserAndRoomAutoCompleteMultiple = ( { value, onChange, limit , ...props } : UserAndRoomAutoCompleteMultipleProps ) => {
1716 const user = useUser ( ) ;
1817 const [ filter , setFilter ] = useState ( '' ) ;
1918 const debouncedFilter = useDebouncedValue ( filter , 1000 ) ;
2019
21- const subscriptions = useUserSubscriptions (
22- useMemo (
23- ( ) => ( {
24- open : { $ne : false } ,
25- $or : [
26- { lowerCaseFName : new RegExp ( escapeRegExp ( debouncedFilter ) , 'i' ) } ,
27- { lowerCaseName : new RegExp ( escapeRegExp ( debouncedFilter ) , 'i' ) } ,
28- ] ,
29- } ) ,
20+ const rooms = useUserSubscriptions (
21+ ...useMemo < Parameters < typeof useUserSubscriptions > > (
22+ ( ) => [
23+ {
24+ open : { $ne : false } ,
25+ $or : [
26+ { lowerCaseFName : new RegExp ( escapeRegExp ( debouncedFilter ) , 'i' ) } ,
27+ { lowerCaseName : new RegExp ( escapeRegExp ( debouncedFilter ) , 'i' ) } ,
28+ ] ,
29+ } ,
30+ // We are using a higher limit here to take advantage of the amount that
31+ // will be filtered below into a smaller set respecting the limit prop.
32+ { limit : 100 } ,
33+ ] ,
3034 [ debouncedFilter ] ,
3135 ) ,
3236 ) ;
3337
34- const rooms = useReactiveValue (
35- useCallback (
36- ( ) =>
37- subscriptions . filter ( ( subscription ) => {
38- if ( ! user ) {
39- return ;
40- }
38+ const options = useMemo ( ( ) => {
39+ if ( ! user ) {
40+ return [ ] ;
41+ }
4142
42- if ( isDirectMessageRoom ( subscription ) && ( subscription . blocked || subscription . blocker ) ) {
43- return ;
44- }
43+ return rooms . reduce < Exclude < UserAndRoomAutoCompleteMultipleProps [ 'options' ] , undefined > > ( ( acc , room ) => {
44+ if ( acc . length === limit ) return acc ;
4545
46- return ! roomCoordinator . readOnly ( Rooms . state . get ( subscription . rid ) , user ) ;
47- } ) ,
48- [ subscriptions , user ] ,
49- ) ,
50- ) ;
46+ if ( isDirectMessageRoom ( room ) && ( room . blocked || room . blocker ) ) {
47+ return acc ;
48+ }
5149
52- const options = useMemo (
53- ( ) =>
54- rooms . map ( ( { rid, fname, name, avatarETag, t } ) => ( {
55- value : rid ,
56- label : { name : fname || name , avatarETag, type : t } ,
57- } ) ) ,
58- [ rooms ] ,
59- ) ;
50+ if ( roomCoordinator . readOnly ( Rooms . state . get ( room . rid ) , user ) ) return acc ;
51+
52+ return [
53+ ...acc ,
54+ {
55+ value : room . rid ,
56+ label : {
57+ name : room . fname || room . name ,
58+ avatarETag : room . avatarETag ,
59+ type : room . t ,
60+ } ,
61+ } ,
62+ ] ;
63+ } , [ ] ) ;
64+ } , [ limit , rooms , user ] ) ;
6065
6166 return (
6267 < AutoComplete
@@ -66,7 +71,7 @@ const UserAndRoomAutoCompleteMultiple = ({ value, onChange, ...props }: UserAndR
6671 filter = { filter }
6772 setFilter = { setFilter }
6873 multiple
69- renderSelected = { ( { selected : { value, label } , onRemove, ...props } ) : ReactElement => (
74+ renderSelected = { ( { selected : { value, label } , onRemove, ...props } ) => (
7075 < Chip { ...props } height = 'x20' value = { value } onClick = { onRemove } mie = { 4 } >
7176 { label . t === 'd' ? (
7277 < UserAvatar size = 'x20' username = { value } />
@@ -78,7 +83,7 @@ const UserAndRoomAutoCompleteMultiple = ({ value, onChange, ...props }: UserAndR
7883 </ Box >
7984 </ Chip >
8085 ) }
81- renderItem = { ( { value, label, ...props } ) : ReactElement => (
86+ renderItem = { ( { value, label, ...props } ) => (
8287 < Option key = { value } { ...props } >
8388 < OptionAvatar >
8489 { label . t === 'd' ? (
0 commit comments