1
- import { useEndpoint } from '@rocket.chat/ui-contexts' ;
2
- import { useInfiniteQuery } from '@tanstack/react-query' ;
1
+ import type { IRole , IUser , AtLeast } from '@rocket.chat/core-typings' ;
2
+ import { useEndpoint , useSetting , useStream } from '@rocket.chat/ui-contexts' ;
3
+ import type { InfiniteData , QueryClient } from '@tanstack/react-query' ;
4
+ import { useInfiniteQuery , useQueryClient } from '@tanstack/react-query' ;
5
+ import { useEffect } from 'react' ;
3
6
4
7
type MembersListOptions = {
5
8
rid : string ;
@@ -11,12 +14,104 @@ type MembersListOptions = {
11
14
12
15
const endpointsByRoomType = {
13
16
d : '/v1/im.members' ,
14
- p : '/v1/groups.members ' ,
15
- c : '/v1/channels.members ' ,
17
+ p : '/v1/rooms.membersOrderedByRole ' ,
18
+ c : '/v1/rooms.membersOrderedByRole ' ,
16
19
} as const ;
17
20
21
+ type RoomMember = Pick < IUser , 'username' | '_id' | 'name' | 'status' | 'freeSwitchExtension' > & { roles ?: IRole [ '_id' ] [ ] } ;
22
+
23
+ const getSortedMembers = ( members : RoomMember [ ] , useRealName = false ) => {
24
+ return members . sort ( ( a , b ) => {
25
+ const aRoles = a . roles ?? [ ] ;
26
+ const bRoles = b . roles ?? [ ] ;
27
+ const isOwnerA = aRoles . includes ( 'owner' ) ;
28
+ const isOwnerB = bRoles . includes ( 'owner' ) ;
29
+ const isModeratorA = aRoles . includes ( 'moderator' ) ;
30
+ const isModeratorB = bRoles . includes ( 'moderator' ) ;
31
+
32
+ if ( isOwnerA !== isOwnerB ) {
33
+ return isOwnerA ? - 1 : 1 ;
34
+ }
35
+
36
+ if ( isModeratorA !== isModeratorB ) {
37
+ return isModeratorA ? - 1 : 1 ;
38
+ }
39
+
40
+ if ( ( a . status === 'online' || b . status === 'online' ) && a . status !== b . status ) {
41
+ return a . status === 'online' ? - 1 : 1 ;
42
+ }
43
+
44
+ if ( useRealName && a . name && b . name ) {
45
+ return a . name . localeCompare ( b . name ) ;
46
+ }
47
+
48
+ const aUsername = a . username ?? '' ;
49
+ const bUsername = b . username ?? '' ;
50
+ return aUsername . localeCompare ( bUsername ) ;
51
+ } ) ;
52
+ } ;
53
+
54
+ const updateMemberInCache = (
55
+ options : MembersListOptions ,
56
+ queryClient : QueryClient ,
57
+ memberId : string ,
58
+ role : AtLeast < IRole , '_id' > ,
59
+ type : 'removed' | 'changed' | 'added' ,
60
+ useRealName = false ,
61
+ ) => {
62
+ queryClient . setQueryData (
63
+ [ options . roomType , 'members' , options . rid , options . type , options . debouncedText ] ,
64
+ ( oldData : InfiniteData < { members : RoomMember [ ] } > ) => {
65
+ if ( ! oldData ) {
66
+ return oldData ;
67
+ }
68
+
69
+ const newPages = oldData . pages . map ( ( page ) => {
70
+ const members = page . members . map ( ( member ) => {
71
+ if ( member . _id === memberId ) {
72
+ member . roles = member . roles ?? [ ] ;
73
+ if ( type === 'added' && ! member . roles . includes ( role . _id ) ) {
74
+ member . roles . push ( role . _id ) ;
75
+ } else if ( type === 'removed' ) {
76
+ member . roles = member . roles . filter ( ( roleId ) => roleId !== role . _id ) ;
77
+ }
78
+ }
79
+ return member ;
80
+ } ) ;
81
+ return {
82
+ ...page ,
83
+ members : getSortedMembers ( members , useRealName ) ,
84
+ } ;
85
+ } ) ;
86
+
87
+ return {
88
+ ...oldData ,
89
+ pages : newPages ,
90
+ } ;
91
+ } ,
92
+ ) ;
93
+ } ;
94
+
18
95
export const useMembersList = ( options : MembersListOptions ) => {
19
96
const getMembers = useEndpoint ( 'GET' , endpointsByRoomType [ options . roomType ] ) ;
97
+ const useRealName = useSetting < boolean > ( 'UI_Use_Real_Name' , false ) ;
98
+ const queryClient = useQueryClient ( ) ;
99
+
100
+ const subscribeToNotifyLoggedIn = useStream ( 'notify-logged' ) ;
101
+ useEffect ( ( ) => {
102
+ const unsubscribe = subscribeToNotifyLoggedIn ( 'roles-change' , ( { type, ...role } ) => {
103
+ if ( ! role . scope ) {
104
+ return ;
105
+ }
106
+
107
+ if ( ! role . u ?. _id ) {
108
+ return ;
109
+ }
110
+
111
+ updateMemberInCache ( options , queryClient , role . u . _id , role as IRole , type , useRealName ) ;
112
+ } ) ;
113
+ return unsubscribe ;
114
+ } , [ options , queryClient , subscribeToNotifyLoggedIn , useRealName ] ) ;
20
115
21
116
return useInfiniteQuery ( {
22
117
queryKey : [ options . roomType , 'members' , options . rid , options . type , options . debouncedText ] ,
0 commit comments