@100mslive/roomkit-react 0.1.14-alpha.1 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{HLSView-JTO7E2KW.js → HLSView-662T7R7H.js} +2 -2
- package/dist/Prebuilt/common/constants.d.ts +1 -0
- package/dist/Prebuilt/common/hooks.d.ts +24 -0
- package/dist/Prebuilt/components/Chat/{Navigation.d.ts → ArrowNavigation.d.ts} +1 -2
- package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +2 -4
- package/dist/Prebuilt/components/Chat/ChatSelector.d.ts +5 -0
- package/dist/Prebuilt/components/Chat/ChatSelectorContainer.d.ts +2 -0
- package/dist/Prebuilt/components/Chat/ChatStates.d.ts +3 -0
- package/dist/Prebuilt/components/Chat/StickIndicator.d.ts +5 -0
- package/dist/Prebuilt/components/Chat/useUnreadCount.d.ts +4 -0
- package/dist/Prebuilt/components/ChatSettings.d.ts +2 -0
- package/dist/Prebuilt/components/Preview/PreviewForm.d.ts +2 -1
- package/dist/Prebuilt/components/SidePaneTabs.d.ts +0 -2
- package/dist/Prebuilt/components/TileMenu/TileMenuContent.d.ts +19 -0
- package/dist/Prebuilt/components/VirtualBackground/VBOption.d.ts +2 -1
- package/dist/Prebuilt/components/hooks/useChatBlacklist.d.ts +2 -1
- package/dist/Prebuilt/components/hooks/useSetPinnedMessages.d.ts +1 -1
- package/dist/Prebuilt/layouts/SidePane.d.ts +1 -3
- package/dist/{chunk-TOKLXTAS.js → chunk-2B7YYNHQ.js} +1651 -1229
- package/dist/chunk-2B7YYNHQ.js.map +7 -0
- package/dist/index.cjs.js +2074 -1609
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +451 -115
- package/dist/meta.esbuild.json +457 -121
- package/package.json +6 -6
- package/src/Prebuilt/common/constants.ts +1 -0
- package/src/Prebuilt/common/{hooks.js → hooks.ts} +4 -5
- package/src/Prebuilt/components/AppData/AppData.tsx +1 -0
- package/src/Prebuilt/components/AppData/useUISettings.js +2 -1
- package/src/Prebuilt/components/AuthToken.jsx +16 -8
- package/src/Prebuilt/components/Chat/{Navigation.tsx → ArrowNavigation.tsx} +3 -19
- package/src/Prebuilt/components/Chat/Chat.jsx +15 -44
- package/src/Prebuilt/components/Chat/ChatBody.jsx +114 -69
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +128 -130
- package/src/Prebuilt/components/Chat/ChatSelector.tsx +225 -0
- package/src/Prebuilt/components/Chat/ChatSelectorContainer.tsx +158 -0
- package/src/Prebuilt/components/Chat/{ChatStates.jsx → ChatStates.tsx} +4 -4
- package/src/Prebuilt/components/Chat/PinnedMessage.tsx +59 -41
- package/src/Prebuilt/components/Chat/StickIndicator.tsx +24 -0
- package/src/Prebuilt/components/Chat/useUnreadCount.ts +19 -0
- package/src/Prebuilt/components/ChatSettings.tsx +68 -0
- package/src/Prebuilt/components/Footer/ParticipantList.jsx +2 -1
- package/src/Prebuilt/components/Header/ParticipantFilter.jsx +2 -1
- package/src/Prebuilt/components/Notifications/ChatNotifications.tsx +1 -1
- package/src/Prebuilt/components/Preview/PreviewForm.tsx +3 -0
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +2 -1
- package/src/Prebuilt/components/SidePaneTabs.tsx +48 -50
- package/src/Prebuilt/components/TileMenu/{TileMenuContent.jsx → TileMenuContent.tsx} +72 -41
- package/src/Prebuilt/components/VirtualBackground/VBCollection.tsx +2 -1
- package/src/Prebuilt/components/VirtualBackground/VBOption.tsx +3 -0
- package/src/Prebuilt/components/VirtualBackground/VBToggle.jsx +1 -1
- package/src/Prebuilt/components/hooks/useChatBlacklist.ts +8 -6
- package/src/Prebuilt/components/hooks/useSetPinnedMessages.ts +2 -7
- package/src/Prebuilt/layouts/SidePane.tsx +1 -5
- package/src/Prebuilt/provider/roomLayoutProvider/constants/index.ts +1 -0
- package/dist/chunk-TOKLXTAS.js.map +0 -7
- package/src/Prebuilt/components/Chat/ChatSelector.jsx +0 -161
- package/src/Prebuilt/components/Chat/ChatSelectorContainer.jsx +0 -81
- package/src/Prebuilt/components/Chat/useUnreadCount.js +0 -17
- /package/dist/{HLSView-JTO7E2KW.js.map → HLSView-662T7R7H.js.map} +0 -0
@@ -2,20 +2,22 @@ import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'reac
|
|
2
2
|
import { useMedia } from 'react-use';
|
3
3
|
import data from '@emoji-mart/data';
|
4
4
|
import Picker from '@emoji-mart/react';
|
5
|
-
import { selectLocalPeer, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
|
5
|
+
import { selectLocalPeer, selectPeerNameByID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
|
6
6
|
import { EmojiIcon, PauseCircleIcon, SendIcon, VerticalMenuIcon } from '@100mslive/react-icons';
|
7
7
|
import { Box, config as cssConfig, Flex, IconButton as BaseIconButton, Popover, styled, Text } from '../../..';
|
8
8
|
import { IconButton } from '../../../IconButton';
|
9
9
|
// @ts-ignore
|
10
10
|
import { ToastManager } from '../Toast/ToastManager';
|
11
|
+
import { ChatSelectorContainer } from './ChatSelectorContainer';
|
11
12
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
12
13
|
// import { ChatSelectorContainer } from './ChatSelectorContainer';
|
13
14
|
// @ts-ignore
|
14
15
|
import { useChatDraftMessage } from '../AppData/useChatState';
|
15
16
|
// @ts-ignore
|
16
|
-
import {
|
17
|
+
import { useSubscribeChatSelector } from '../AppData/useUISettings';
|
17
18
|
// @ts-ignore
|
18
|
-
import {
|
19
|
+
import { useEmojiPickerStyles } from './useEmojiPickerStyles';
|
20
|
+
import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
|
19
21
|
|
20
22
|
const TextArea = styled('textarea', {
|
21
23
|
width: '100%',
|
@@ -69,17 +71,7 @@ function EmojiPicker({ onSelect }: { onSelect: (emoji: any) => void }) {
|
|
69
71
|
);
|
70
72
|
}
|
71
73
|
|
72
|
-
export const ChatFooter = ({
|
73
|
-
role,
|
74
|
-
peerId,
|
75
|
-
onSend,
|
76
|
-
children /* onSelect, selection, screenType */,
|
77
|
-
}: {
|
78
|
-
role: any;
|
79
|
-
peerId: string;
|
80
|
-
onSend: any;
|
81
|
-
children: ReactNode;
|
82
|
-
}) => {
|
74
|
+
export const ChatFooter = ({ onSend, children }: { onSend: () => void; children: ReactNode }) => {
|
83
75
|
const hmsActions = useHMSActions();
|
84
76
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
85
77
|
const [draftMessage, setDraftMessage] = useChatDraftMessage();
|
@@ -89,17 +81,21 @@ export const ChatFooter = ({
|
|
89
81
|
const localPeer = useHMSStore(selectLocalPeer);
|
90
82
|
const isOverlayChat = elements?.chat?.is_overlay;
|
91
83
|
const canDisableChat = !!elements?.chat?.real_time_controls?.can_disable_chat;
|
92
|
-
|
84
|
+
const isPublicChatEnabled = !!elements?.chat?.public_chat_enabled;
|
85
|
+
const selectedPeer = useSubscribeChatSelector(CHAT_SELECTOR.PEER_ID);
|
86
|
+
const selectedRole = useSubscribeChatSelector(CHAT_SELECTOR.ROLE);
|
87
|
+
const selectorPeerName = useHMSStore(selectPeerNameByID(selectedPeer));
|
88
|
+
const selection = selectorPeerName || selectedRole || CHAT_SELECTOR.EVERYONE;
|
93
89
|
const sendMessage = useCallback(async () => {
|
94
90
|
const message = inputRef?.current?.value;
|
95
91
|
if (!message || !message.trim().length) {
|
96
92
|
return;
|
97
93
|
}
|
98
94
|
try {
|
99
|
-
if (
|
100
|
-
await hmsActions.sendGroupMessage(message, [
|
101
|
-
} else if (
|
102
|
-
await hmsActions.sendDirectMessage(message,
|
95
|
+
if (selectedRole) {
|
96
|
+
await hmsActions.sendGroupMessage(message, [selectedRole]);
|
97
|
+
} else if (selectedPeer) {
|
98
|
+
await hmsActions.sendDirectMessage(message, selectedPeer);
|
103
99
|
} else {
|
104
100
|
await hmsActions.sendBroadcastMessage(message);
|
105
101
|
}
|
@@ -111,7 +107,7 @@ export const ChatFooter = ({
|
|
111
107
|
const err = error as Error;
|
112
108
|
ToastManager.addToast({ title: err.message });
|
113
109
|
}
|
114
|
-
}, [
|
110
|
+
}, [selectedRole, selectedPeer, hmsActions, onSend]);
|
115
111
|
|
116
112
|
useEffect(() => {
|
117
113
|
const messageElement = inputRef.current;
|
@@ -129,122 +125,124 @@ export const ChatFooter = ({
|
|
129
125
|
|
130
126
|
return (
|
131
127
|
<Box>
|
132
|
-
|
133
|
-
<ChatSelectorContainer
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
</
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
</
|
174
|
-
</Popover.
|
175
|
-
</Popover.
|
176
|
-
</
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
<Flex
|
181
|
-
|
182
|
-
|
183
|
-
bg: isOverlayChat && isMobile ? '$surface_dim' : '$surface_default',
|
184
|
-
minHeight: '$16',
|
185
|
-
maxHeight: '$24',
|
186
|
-
position: 'relative',
|
187
|
-
py: '$6',
|
188
|
-
pl: '$8',
|
189
|
-
flexGrow: 1,
|
190
|
-
r: '$1',
|
191
|
-
'@md': {
|
192
|
-
minHeight: 'unset',
|
193
|
-
h: '$14',
|
194
|
-
boxSizing: 'border-box',
|
195
|
-
},
|
196
|
-
}}
|
197
|
-
>
|
198
|
-
{children}
|
199
|
-
<TextArea
|
128
|
+
<Flex>
|
129
|
+
<ChatSelectorContainer />
|
130
|
+
{canDisableChat && isMobile && isOverlayChat ? (
|
131
|
+
<Flex align="center" justify="end" css={{ mb: '$4' }}>
|
132
|
+
<Popover.Root>
|
133
|
+
<Popover.Trigger asChild>
|
134
|
+
<IconButton css={{ border: '1px solid $border_bright' }}>
|
135
|
+
<VerticalMenuIcon height="16" width="16" />
|
136
|
+
</IconButton>
|
137
|
+
</Popover.Trigger>
|
138
|
+
<Popover.Portal>
|
139
|
+
<Popover.Content
|
140
|
+
align="end"
|
141
|
+
side="top"
|
142
|
+
onClick={() => {
|
143
|
+
const chatState = {
|
144
|
+
enabled: false,
|
145
|
+
updatedBy: {
|
146
|
+
peerId: localPeer?.id,
|
147
|
+
userId: localPeer?.customerUserId,
|
148
|
+
userName: localPeer?.name,
|
149
|
+
},
|
150
|
+
updatedAt: Date.now(),
|
151
|
+
};
|
152
|
+
hmsActions.sessionStore.set(SESSION_STORE_KEY.CHAT_STATE, chatState);
|
153
|
+
}}
|
154
|
+
css={{
|
155
|
+
backgroundColor: '$surface_default',
|
156
|
+
display: 'flex',
|
157
|
+
alignItems: 'center',
|
158
|
+
gap: '$4',
|
159
|
+
borderRadius: '$1',
|
160
|
+
color: '$on_surface_high',
|
161
|
+
cursor: 'pointer',
|
162
|
+
'&:hover': { backgroundColor: '$surface_dim' },
|
163
|
+
}}
|
164
|
+
>
|
165
|
+
<PauseCircleIcon />
|
166
|
+
<Text variant="sm" css={{ fontWeight: '$semiBold' }}>
|
167
|
+
Pause Chat
|
168
|
+
</Text>
|
169
|
+
</Popover.Content>
|
170
|
+
</Popover.Portal>
|
171
|
+
</Popover.Root>
|
172
|
+
</Flex>
|
173
|
+
) : null}
|
174
|
+
</Flex>
|
175
|
+
{!(selection === CHAT_SELECTOR.EVERYONE && !isPublicChatEnabled) && (
|
176
|
+
<Flex align="center" css={{ gap: '$4', w: '100%' }}>
|
177
|
+
<Flex
|
178
|
+
align="center"
|
200
179
|
css={{
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
180
|
+
bg: isOverlayChat && isMobile ? '$surface_dim' : '$surface_default',
|
181
|
+
minHeight: '$16',
|
182
|
+
maxHeight: '$24',
|
183
|
+
position: 'relative',
|
184
|
+
py: '$6',
|
185
|
+
pl: '$8',
|
186
|
+
flexGrow: 1,
|
187
|
+
r: '$1',
|
188
|
+
'@md': {
|
189
|
+
minHeight: 'unset',
|
190
|
+
h: '$14',
|
191
|
+
boxSizing: 'border-box',
|
192
|
+
},
|
205
193
|
}}
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
}
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
<EmojiPicker
|
226
|
-
onSelect={(emoji: any) => {
|
227
|
-
if (inputRef.current) {
|
228
|
-
inputRef.current.value += ` ${emoji.native} `;
|
194
|
+
>
|
195
|
+
{children}
|
196
|
+
<TextArea
|
197
|
+
css={{
|
198
|
+
c: '$on_surface_high',
|
199
|
+
'&:valid ~ .send-msg': { color: '$on_surface_high' },
|
200
|
+
'& ~ .send-msg': { color: '$on_surface_low' },
|
201
|
+
'&::placeholder': { color: '$on_surface_medium' },
|
202
|
+
}}
|
203
|
+
placeholder={message_placeholder}
|
204
|
+
ref={inputRef}
|
205
|
+
required
|
206
|
+
autoFocus={!isMobile}
|
207
|
+
onKeyPress={async event => {
|
208
|
+
if (event.key === 'Enter') {
|
209
|
+
if (!event.shiftKey) {
|
210
|
+
event.preventDefault();
|
211
|
+
await sendMessage();
|
212
|
+
}
|
229
213
|
}
|
230
214
|
}}
|
215
|
+
autoComplete="off"
|
216
|
+
aria-autocomplete="none"
|
217
|
+
onPaste={e => e.stopPropagation()}
|
218
|
+
onCut={e => e.stopPropagation()}
|
219
|
+
onCopy={e => e.stopPropagation()}
|
231
220
|
/>
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
221
|
+
{!isMobile ? (
|
222
|
+
<EmojiPicker
|
223
|
+
onSelect={emoji => {
|
224
|
+
if (inputRef.current) {
|
225
|
+
inputRef.current.value += ` ${emoji.native} `;
|
226
|
+
}
|
227
|
+
}}
|
228
|
+
/>
|
229
|
+
) : null}
|
230
|
+
<BaseIconButton
|
231
|
+
className="send-msg"
|
232
|
+
onClick={sendMessage}
|
233
|
+
css={{
|
234
|
+
ml: 'auto',
|
235
|
+
height: 'max-content',
|
236
|
+
mr: '$4',
|
237
|
+
'&:hover': { c: isMobile ? '' : '$on_surface_medium' },
|
238
|
+
}}
|
239
|
+
data-testid="send_msg_btn"
|
240
|
+
>
|
241
|
+
<SendIcon />
|
242
|
+
</BaseIconButton>
|
243
|
+
</Flex>
|
246
244
|
</Flex>
|
247
|
-
|
245
|
+
)}
|
248
246
|
</Box>
|
249
247
|
);
|
250
248
|
};
|
@@ -0,0 +1,225 @@
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
2
|
+
import { useMedia } from 'react-use';
|
3
|
+
import {
|
4
|
+
HMSPeer,
|
5
|
+
selectMessagesUnreadCountByPeerID,
|
6
|
+
selectMessagesUnreadCountByRole,
|
7
|
+
selectRemotePeers,
|
8
|
+
selectUnreadHMSMessagesCount,
|
9
|
+
useHMSStore,
|
10
|
+
} from '@100mslive/react-sdk';
|
11
|
+
import { CheckIcon, PeopleIcon } from '@100mslive/react-icons';
|
12
|
+
import { Box, CSS, Dropdown, Flex, HorizontalDivider, Text, Tooltip } from '../../..';
|
13
|
+
import { config as cssConfig } from '../../../Theme';
|
14
|
+
// @ts-ignore
|
15
|
+
import { ParticipantSearch } from '../Footer/ParticipantList';
|
16
|
+
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
17
|
+
// @ts-ignore
|
18
|
+
import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
|
19
|
+
import { useFilteredRoles } from '../../common/hooks';
|
20
|
+
import { CHAT_SELECTOR } from '../../common/constants';
|
21
|
+
|
22
|
+
const ChatDotIcon = () => {
|
23
|
+
return <Box css={{ size: '$6', bg: '$primary_default', mx: '$2', r: '$round' }} />;
|
24
|
+
};
|
25
|
+
|
26
|
+
const SelectorItem = ({
|
27
|
+
value,
|
28
|
+
active,
|
29
|
+
onClick,
|
30
|
+
unreadCount,
|
31
|
+
icon = undefined,
|
32
|
+
}: {
|
33
|
+
value: string;
|
34
|
+
active: boolean;
|
35
|
+
onClick: () => void;
|
36
|
+
unreadCount: number;
|
37
|
+
icon?: React.JSX.Element;
|
38
|
+
}) => {
|
39
|
+
const isMobile = useMedia(cssConfig.media.md);
|
40
|
+
|
41
|
+
const Root = !isMobile
|
42
|
+
? Dropdown.Item
|
43
|
+
: ({ children, ...rest }: { children: React.ReactNode; css: CSS }) => (
|
44
|
+
<Flex {...rest} css={{ p: '$6 $8', ...rest.css }}>
|
45
|
+
{children}
|
46
|
+
</Flex>
|
47
|
+
);
|
48
|
+
return (
|
49
|
+
<Root
|
50
|
+
data-testid="chat_members"
|
51
|
+
css={{ align: 'center', px: '$10', py: '$4', bg: '$surface_default' }}
|
52
|
+
onClick={onClick}
|
53
|
+
>
|
54
|
+
<Text
|
55
|
+
variant="sm"
|
56
|
+
css={{ display: 'flex', alignItems: 'center', gap: '$4', fontWeight: '$semiBold', color: '$on_surface_high' }}
|
57
|
+
>
|
58
|
+
{icon}
|
59
|
+
{value}
|
60
|
+
</Text>
|
61
|
+
<Flex align="center" css={{ ml: 'auto', color: '$on_primary_high' }}>
|
62
|
+
{unreadCount > 0 && (
|
63
|
+
<Tooltip title={`${unreadCount} unread`}>
|
64
|
+
<Box css={{ mr: active ? '$3' : 0 }}>
|
65
|
+
<ChatDotIcon />
|
66
|
+
</Box>
|
67
|
+
</Tooltip>
|
68
|
+
)}
|
69
|
+
{active && <CheckIcon width={16} height={16} />}
|
70
|
+
</Flex>
|
71
|
+
</Root>
|
72
|
+
);
|
73
|
+
};
|
74
|
+
|
75
|
+
const SelectorHeader = React.memo(
|
76
|
+
({ isHorizontalDivider = true, children }: { isHorizontalDivider?: boolean; children: React.ReactNode }) => {
|
77
|
+
return (
|
78
|
+
<Box css={{ flexShrink: 0 }}>
|
79
|
+
{isHorizontalDivider && <HorizontalDivider space={4} />}
|
80
|
+
<Text
|
81
|
+
variant="overline"
|
82
|
+
css={{ p: '$4 $10', fontWeight: '$semiBold', textTransform: 'uppercase', color: '$on_surface_medium' }}
|
83
|
+
>
|
84
|
+
{children}
|
85
|
+
</Text>
|
86
|
+
</Box>
|
87
|
+
);
|
88
|
+
},
|
89
|
+
);
|
90
|
+
|
91
|
+
const Everyone = React.memo(({ active }: { active: boolean }) => {
|
92
|
+
const unreadCount: number = useHMSStore(selectUnreadHMSMessagesCount);
|
93
|
+
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
|
94
|
+
const [, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
95
|
+
return (
|
96
|
+
<SelectorItem
|
97
|
+
value="Everyone"
|
98
|
+
icon={<PeopleIcon />}
|
99
|
+
active={active}
|
100
|
+
unreadCount={unreadCount}
|
101
|
+
onClick={() => {
|
102
|
+
setPeerSelector('');
|
103
|
+
setRoleSelector('');
|
104
|
+
}}
|
105
|
+
/>
|
106
|
+
);
|
107
|
+
});
|
108
|
+
|
109
|
+
const RoleItem = React.memo(({ role, active }: { role: string; active: boolean }) => {
|
110
|
+
const unreadCount: number = useHMSStore(selectMessagesUnreadCountByRole(role));
|
111
|
+
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
|
112
|
+
const [, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
113
|
+
return (
|
114
|
+
<SelectorItem
|
115
|
+
value={role}
|
116
|
+
active={active}
|
117
|
+
unreadCount={unreadCount}
|
118
|
+
onClick={() => {
|
119
|
+
setPeerSelector('');
|
120
|
+
setRoleSelector(role);
|
121
|
+
}}
|
122
|
+
/>
|
123
|
+
);
|
124
|
+
});
|
125
|
+
|
126
|
+
const PeerItem = ({ peerId, name, active }: { name: string; peerId: string; active: boolean }) => {
|
127
|
+
const unreadCount: number = useHMSStore(selectMessagesUnreadCountByPeerID(peerId));
|
128
|
+
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
|
129
|
+
const [, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
130
|
+
|
131
|
+
return (
|
132
|
+
<SelectorItem
|
133
|
+
value={name}
|
134
|
+
active={active}
|
135
|
+
unreadCount={unreadCount}
|
136
|
+
onClick={() => {
|
137
|
+
setPeerSelector(peerId);
|
138
|
+
setRoleSelector('');
|
139
|
+
}}
|
140
|
+
/>
|
141
|
+
);
|
142
|
+
};
|
143
|
+
|
144
|
+
const VirtualizedSelectItemList = ({
|
145
|
+
peers,
|
146
|
+
selectedRole,
|
147
|
+
selectedPeerId,
|
148
|
+
searchValue,
|
149
|
+
}: {
|
150
|
+
peers: HMSPeer[];
|
151
|
+
selectedRole: string;
|
152
|
+
selectedPeerId: string;
|
153
|
+
searchValue: string;
|
154
|
+
}) => {
|
155
|
+
const roles = useFilteredRoles();
|
156
|
+
const isMobile = useMedia(cssConfig.media.md);
|
157
|
+
const filteredPeers = useMemo(
|
158
|
+
() =>
|
159
|
+
peers.filter(
|
160
|
+
// search should be empty or search phrase should be included in name
|
161
|
+
peer => !searchValue || peer.name.toLowerCase().includes(searchValue.toLowerCase()),
|
162
|
+
),
|
163
|
+
[peers, searchValue],
|
164
|
+
);
|
165
|
+
|
166
|
+
const listItems = useMemo(() => {
|
167
|
+
const selectItems = !searchValue ? [<Everyone active={!selectedRole && !selectedPeerId} />] : [];
|
168
|
+
|
169
|
+
roles.length > 0 && !searchValue && selectItems.push(<SelectorHeader>Roles</SelectorHeader>);
|
170
|
+
!searchValue &&
|
171
|
+
roles.forEach(userRole =>
|
172
|
+
selectItems.push(<RoleItem key={userRole} active={selectedRole === userRole} role={userRole} />),
|
173
|
+
);
|
174
|
+
|
175
|
+
filteredPeers.length > 0 && selectItems.push(<SelectorHeader>Participants</SelectorHeader>);
|
176
|
+
filteredPeers.forEach(peer =>
|
177
|
+
selectItems.push(
|
178
|
+
<PeerItem key={peer.id} name={peer.name} peerId={peer.id} active={peer.id === selectedPeerId} />,
|
179
|
+
),
|
180
|
+
);
|
181
|
+
|
182
|
+
return selectItems;
|
183
|
+
}, [searchValue, selectedRole, selectedPeerId, roles, filteredPeers]);
|
184
|
+
|
185
|
+
if (!isMobile) {
|
186
|
+
return (
|
187
|
+
<Dropdown.Group css={{ overflowY: 'auto', maxHeight: '$64', bg: '$surface_default' }}>
|
188
|
+
{listItems.map((item, index) => (
|
189
|
+
<Box key={index}>{item}</Box>
|
190
|
+
))}
|
191
|
+
</Dropdown.Group>
|
192
|
+
);
|
193
|
+
}
|
194
|
+
return (
|
195
|
+
<>
|
196
|
+
{listItems.map((item, index) => (
|
197
|
+
<Box key={index}>{item}</Box>
|
198
|
+
))}
|
199
|
+
</>
|
200
|
+
);
|
201
|
+
};
|
202
|
+
|
203
|
+
export const ChatSelector = ({ role, peerId }: { role: string; peerId: string }) => {
|
204
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
205
|
+
const peers = useHMSStore(selectRemotePeers);
|
206
|
+
const [search, setSearch] = useState('');
|
207
|
+
|
208
|
+
const isPrivateChatEnabled = !!elements?.chat?.private_chat_enabled;
|
209
|
+
|
210
|
+
return (
|
211
|
+
<>
|
212
|
+
{peers.length > 0 && isPrivateChatEnabled && (
|
213
|
+
<Box css={{ px: '$4' }}>
|
214
|
+
<ParticipantSearch onSearch={setSearch} placeholder="Search for participants" />
|
215
|
+
</Box>
|
216
|
+
)}
|
217
|
+
<VirtualizedSelectItemList
|
218
|
+
selectedRole={role}
|
219
|
+
selectedPeerId={peerId}
|
220
|
+
peers={isPrivateChatEnabled ? peers : []}
|
221
|
+
searchValue={search}
|
222
|
+
/>
|
223
|
+
</>
|
224
|
+
);
|
225
|
+
};
|