@100mslive/roomkit-react 0.1.12-alpha.0 → 0.1.13-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{HLSView-J2MIS3H2.js → HLSView-AIPLCDXY.js} +2 -2
- package/dist/Prebuilt/App.d.ts +0 -2
- package/dist/Prebuilt/AppContext.d.ts +0 -2
- package/dist/Prebuilt/common/constants.d.ts +110 -0
- package/dist/Prebuilt/components/AppData/AppData.d.ts +2 -0
- package/dist/Prebuilt/components/Chat/MwebChatOption.d.ts +7 -0
- package/dist/Prebuilt/components/Chat/Navigation.d.ts +8 -0
- package/dist/Prebuilt/components/Chat/PinnedMessage.d.ts +4 -0
- package/dist/Prebuilt/components/Footer/Footer.d.ts +3 -2
- package/dist/Prebuilt/components/Preview/PreviewJoin.d.ts +2 -1
- package/dist/Prebuilt/components/VirtualBackground/VBCollection.d.ts +2 -1
- package/dist/Prebuilt/components/VirtualBackground/VBPicker.d.ts +3 -0
- package/dist/Prebuilt/components/VirtualBackground/constants.d.ts +0 -6
- package/dist/Prebuilt/components/hooks/useChatBlacklist.d.ts +4 -0
- package/dist/Prebuilt/components/hooks/useSetPinnedMessages.d.ts +16 -0
- package/dist/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.d.ts +3 -2
- package/dist/Theme/stitches.config.d.ts +226 -226
- package/dist/{chunk-OYSYEA6R.js → chunk-5DCII2TP.js} +2248 -1269
- package/dist/chunk-5DCII2TP.js.map +7 -0
- package/dist/index.cjs.js +2943 -1902
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +819 -313
- package/dist/meta.esbuild.json +826 -320
- package/package.json +8 -8
- package/src/Prebuilt/App.tsx +3 -14
- package/src/Prebuilt/AppContext.tsx +0 -2
- package/src/Prebuilt/common/{constants.js → constants.ts} +22 -20
- package/src/Prebuilt/components/AppData/{AppData.jsx → AppData.tsx} +8 -22
- package/src/Prebuilt/components/AppData/useUISettings.js +0 -4
- package/src/Prebuilt/components/AuthToken.jsx +4 -4
- package/src/Prebuilt/components/Chat/Chat.jsx +51 -73
- package/src/Prebuilt/components/Chat/ChatBody.jsx +219 -48
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +50 -6
- package/src/Prebuilt/components/Chat/ChatStates.jsx +66 -0
- package/src/Prebuilt/components/Chat/MwebChatOption.tsx +24 -0
- package/src/Prebuilt/components/Chat/Navigation.tsx +60 -0
- package/src/Prebuilt/components/Chat/PinnedMessage.tsx +118 -0
- package/src/Prebuilt/components/Footer/Footer.tsx +4 -7
- package/src/Prebuilt/components/Header/common.jsx +1 -1
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +6 -8
- package/src/Prebuilt/components/RoleChangeRequest/RoleChangeRequestModal.tsx +4 -1
- package/src/Prebuilt/components/Settings/DeviceSettings.jsx +1 -1
- package/src/Prebuilt/components/SidePaneTabs.tsx +3 -2
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +20 -0
- package/src/Prebuilt/components/VirtualBackground/VBCollection.tsx +4 -4
- package/src/Prebuilt/components/VirtualBackground/{VBPicker.jsx → VBPicker.tsx} +27 -18
- package/src/Prebuilt/components/VirtualBackground/constants.ts +0 -8
- package/src/Prebuilt/components/hooks/useAutoStartStreaming.tsx +10 -1
- package/src/Prebuilt/components/hooks/useChatBlacklist.ts +21 -0
- package/src/Prebuilt/components/hooks/useSetPinnedMessages.ts +76 -0
- package/src/Prebuilt/layouts/SidePane.tsx +1 -1
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +30 -2
- package/src/Prebuilt/plugins/whiteboard/PusherCommunicationProvider.js +1 -1
- package/src/Prebuilt/plugins/whiteboard/README.md +1 -1
- package/src/Prebuilt/primitives/DialogContent.jsx +1 -1
- package/src/Prebuilt/provider/roomLayoutProvider/constants/index.ts +12 -1
- package/src/Prebuilt/provider/roomLayoutProvider/hooks/useRoomLayoutScreen.ts +5 -1
- package/src/Theme/stitches.config.ts +1 -2
- package/dist/chunk-OYSYEA6R.js.map +0 -7
- package/src/Prebuilt/components/hooks/useSetPinnedMessage.js +0 -38
- package/src/Prebuilt/services/tokenService.js +0 -49
- /package/dist/{HLSView-J2MIS3H2.js.map → HLSView-AIPLCDXY.js.map} +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { Fragment, useCallback, useEffect, useLayoutEffect,
|
1
|
+
import React, { Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
2
2
|
import { useInView } from 'react-intersection-observer';
|
3
3
|
import { useMedia } from 'react-use';
|
4
4
|
import AutoSizer from 'react-virtualized-auto-sizer';
|
@@ -6,25 +6,34 @@ import { VariableSizeList } from 'react-window';
|
|
6
6
|
import {
|
7
7
|
selectHMSMessages,
|
8
8
|
selectLocalPeerID,
|
9
|
+
selectLocalPeerName,
|
9
10
|
selectLocalPeerRoleName,
|
10
11
|
selectMessagesByPeerID,
|
11
12
|
selectMessagesByRole,
|
12
13
|
selectPeerNameByID,
|
13
14
|
selectPermissions,
|
15
|
+
selectSessionStore,
|
14
16
|
useHMSActions,
|
15
17
|
useHMSStore,
|
16
18
|
} from '@100mslive/react-sdk';
|
17
|
-
import { PinIcon, VerticalMenuIcon } from '@100mslive/react-icons';
|
19
|
+
import { CopyIcon, CrossCircleIcon, CrossIcon, EyeCloseIcon, PinIcon, VerticalMenuIcon } from '@100mslive/react-icons';
|
18
20
|
import { Dropdown } from '../../../Dropdown';
|
19
21
|
import { IconButton } from '../../../IconButton';
|
20
22
|
import { Box, Flex } from '../../../Layout';
|
23
|
+
import { Sheet } from '../../../Sheet';
|
21
24
|
import { Text } from '../../../Text';
|
22
25
|
import { config as cssConfig, styled } from '../../../Theme';
|
23
26
|
import { Tooltip } from '../../../Tooltip';
|
24
27
|
import emptyChat from '../../images/empty-chat.svg';
|
28
|
+
import { ToastManager } from '../Toast/ToastManager';
|
29
|
+
import { MwebChatOption } from './MwebChatOption';
|
25
30
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
26
|
-
import {
|
31
|
+
import { useChatBlacklist } from '../hooks/useChatBlacklist';
|
32
|
+
import { useSetPinnedMessages } from '../hooks/useSetPinnedMessages';
|
27
33
|
import { useUnreadCount } from './useUnreadCount';
|
34
|
+
import { SESSION_STORE_KEY } from '../../common/constants';
|
35
|
+
|
36
|
+
const iconStyle = { height: '1.125rem', width: '1.125rem' };
|
28
37
|
|
29
38
|
const formatTime = date => {
|
30
39
|
if (!(date instanceof Date)) {
|
@@ -127,56 +136,176 @@ const getMessageType = ({ roles, receiver }) => {
|
|
127
136
|
}
|
128
137
|
return receiver ? 'private' : '';
|
129
138
|
};
|
130
|
-
const ChatActions = ({ onPin, showPinAction }) => {
|
139
|
+
const ChatActions = ({ onPin, showPinAction, message, peerId, sentByLocalPeer, isMobile, openSheet, setOpenSheet }) => {
|
140
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
141
|
+
const { can_hide_message, can_block_user } = elements?.chat?.real_time_controls || {
|
142
|
+
can_hide_message: false,
|
143
|
+
can_block_user: false,
|
144
|
+
};
|
131
145
|
const [open, setOpen] = useState(false);
|
132
|
-
|
133
|
-
|
146
|
+
const blacklistedPeerIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST)) || [];
|
147
|
+
const { blacklistItem: blacklistMessage } = useChatBlacklist(SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST);
|
148
|
+
|
149
|
+
const blacklistedMessageIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST)) || [];
|
150
|
+
const { blacklistItem: blacklistPeer } = useChatBlacklist(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST);
|
151
|
+
const { unpinBlacklistedMessages } = useSetPinnedMessages();
|
152
|
+
|
153
|
+
const pinnedMessages = useHMSStore(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGES)) || [];
|
154
|
+
|
155
|
+
useEffect(() => {
|
156
|
+
if (!(blacklistedPeerIDs.length || blacklistedMessageIDs.length)) {
|
157
|
+
return;
|
158
|
+
}
|
159
|
+
const blacklistedMessageIDSet = new Set(blacklistedMessageIDs);
|
160
|
+
const blacklistedPeerIDSet = new Set(blacklistedPeerIDs);
|
161
|
+
|
162
|
+
unpinBlacklistedMessages(pinnedMessages, blacklistedPeerIDSet, blacklistedMessageIDSet);
|
163
|
+
}, [blacklistedMessageIDs, blacklistedPeerIDs, pinnedMessages, unpinBlacklistedMessages]);
|
164
|
+
|
165
|
+
const copyMessageContent = useCallback(() => {
|
166
|
+
try {
|
167
|
+
navigator?.clipboard.writeText(message.message);
|
168
|
+
ToastManager.addToast({
|
169
|
+
title: 'Message copied successfully',
|
170
|
+
});
|
171
|
+
} catch (e) {
|
172
|
+
console.log(e);
|
173
|
+
ToastManager.addToast({
|
174
|
+
title: 'Could not copy message',
|
175
|
+
});
|
176
|
+
}
|
177
|
+
}, [message]);
|
178
|
+
|
179
|
+
const options = {
|
180
|
+
pin: {
|
181
|
+
text: 'Pin message',
|
182
|
+
icon: <PinIcon style={iconStyle} />,
|
183
|
+
onClick: onPin,
|
184
|
+
show: showPinAction,
|
185
|
+
},
|
186
|
+
copy: {
|
187
|
+
text: 'Copy text',
|
188
|
+
icon: <CopyIcon style={iconStyle} />,
|
189
|
+
onClick: copyMessageContent,
|
190
|
+
show: true,
|
191
|
+
},
|
192
|
+
hide: {
|
193
|
+
text: 'Hide for everyone',
|
194
|
+
icon: <EyeCloseIcon style={iconStyle} />,
|
195
|
+
onClick: async () => blacklistMessage(blacklistedPeerIDs, message.id),
|
196
|
+
show: can_hide_message,
|
197
|
+
},
|
198
|
+
block: {
|
199
|
+
text: 'Block from chat',
|
200
|
+
icon: <CrossCircleIcon style={iconStyle} />,
|
201
|
+
onClick: async () => blacklistPeer(blacklistedMessageIDs, peerId),
|
202
|
+
color: '$alert_error_default',
|
203
|
+
show: can_block_user && !sentByLocalPeer,
|
204
|
+
},
|
205
|
+
};
|
206
|
+
|
207
|
+
if (isMobile) {
|
208
|
+
return (
|
209
|
+
<Sheet.Root open={openSheet} onOpenChange={setOpenSheet}>
|
210
|
+
<Sheet.Content css={{ bg: '$surface_default', pb: '$14' }} onClick={() => setOpenSheet(false)}>
|
211
|
+
<Sheet.Title
|
212
|
+
css={{
|
213
|
+
display: 'flex',
|
214
|
+
color: '$on_surface_high',
|
215
|
+
w: '100%',
|
216
|
+
justifyContent: 'space-between',
|
217
|
+
mt: '$8',
|
218
|
+
fontSize: '$md',
|
219
|
+
px: '$10',
|
220
|
+
pb: '$8',
|
221
|
+
borderBottom: '1px solid $border_bright',
|
222
|
+
alignItems: 'center',
|
223
|
+
}}
|
224
|
+
>
|
225
|
+
Message options
|
226
|
+
<Sheet.Close css={{ color: '$on_surface_high' }} onClick={() => setOpenSheet(false)}>
|
227
|
+
<CrossIcon />
|
228
|
+
</Sheet.Close>
|
229
|
+
</Sheet.Title>
|
230
|
+
|
231
|
+
{Object.keys(options).map(optionKey => {
|
232
|
+
const option = options[optionKey];
|
233
|
+
return option.show ? (
|
234
|
+
<MwebChatOption
|
235
|
+
key={optionKey}
|
236
|
+
text={option.text}
|
237
|
+
icon={option.icon}
|
238
|
+
onClick={option.onClick}
|
239
|
+
color={option?.color}
|
240
|
+
/>
|
241
|
+
) : null;
|
242
|
+
})}
|
243
|
+
</Sheet.Content>
|
244
|
+
</Sheet.Root>
|
245
|
+
);
|
134
246
|
}
|
135
247
|
|
136
248
|
return (
|
137
|
-
<Dropdown.Root open={open} onOpenChange={setOpen}>
|
138
|
-
<
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
249
|
+
<Dropdown.Root open={open} onOpenChange={setOpen} css={{ '@md': { display: 'none' } }}>
|
250
|
+
<Flex
|
251
|
+
className="chat_actions"
|
252
|
+
css={{
|
253
|
+
background: '$surface_bright',
|
254
|
+
borderRadius: '$1',
|
255
|
+
p: '$2',
|
256
|
+
opacity: open ? 1 : 0,
|
257
|
+
'@md': { opacity: 1 },
|
258
|
+
}}
|
259
|
+
>
|
260
|
+
{options.pin.show ? (
|
261
|
+
<IconButton data-testid="pin_message_btn" onClick={options.pin.onClick}>
|
262
|
+
{options.pin.icon}
|
263
|
+
</IconButton>
|
264
|
+
) : null}
|
265
|
+
|
266
|
+
{options.copy.show ? (
|
267
|
+
<IconButton onClick={options.copy.onClick} data-testid="copy_message_btn">
|
268
|
+
<CopyIcon style={iconStyle} />
|
269
|
+
</IconButton>
|
270
|
+
) : null}
|
271
|
+
|
272
|
+
{options.block.show || options.hide.show ? (
|
273
|
+
<Dropdown.Trigger asChild>
|
274
|
+
<IconButton>
|
275
|
+
<Tooltip title="More options">
|
276
|
+
<VerticalMenuIcon style={iconStyle} />
|
277
|
+
</Tooltip>
|
278
|
+
</IconButton>
|
279
|
+
</Dropdown.Trigger>
|
280
|
+
) : null}
|
281
|
+
</Flex>
|
145
282
|
<Dropdown.Portal>
|
146
283
|
<Dropdown.Content
|
147
284
|
sideOffset={5}
|
148
285
|
align="end"
|
149
286
|
css={{ width: '$48', backgroundColor: '$surface_bright', py: '$0', border: '1px solid $border_bright' }}
|
150
287
|
>
|
151
|
-
|
152
|
-
<
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
288
|
+
{options.hide.show ? (
|
289
|
+
<Dropdown.Item data-testid="hide_message_btn" onClick={options.hide.onClick}>
|
290
|
+
{options.hide.icon}
|
291
|
+
<Text variant="sm" css={{ ml: '$4', fontWeight: '$semiBold' }}>
|
292
|
+
{options.hide.text}
|
293
|
+
</Text>
|
294
|
+
</Dropdown.Item>
|
295
|
+
) : null}
|
296
|
+
|
297
|
+
{options.block.show ? (
|
158
298
|
<Dropdown.Item
|
159
|
-
data-testid="
|
160
|
-
onClick={
|
161
|
-
|
162
|
-
navigator?.clipboard.writeText(messageContent);
|
163
|
-
ToastManager.addToast({
|
164
|
-
title: 'Message copied successfully',
|
165
|
-
});
|
166
|
-
} catch (e) {
|
167
|
-
console.log(e);
|
168
|
-
ToastManager.addToast({
|
169
|
-
title: 'Could not copy message',
|
170
|
-
});
|
171
|
-
}
|
172
|
-
}}
|
299
|
+
data-testid="block_peer_btn"
|
300
|
+
onClick={options.block.onClick}
|
301
|
+
css={{ color: options.block.color }}
|
173
302
|
>
|
174
|
-
|
175
|
-
<Text variant="sm" css={{ ml: '$4' }}>
|
176
|
-
|
303
|
+
{options.block.icon}
|
304
|
+
<Text variant="sm" css={{ ml: '$4', color: 'inherit', fontWeight: '$semiBold' }}>
|
305
|
+
{options.block.text}
|
177
306
|
</Text>
|
178
307
|
</Dropdown.Item>
|
179
|
-
) : null}
|
308
|
+
) : null}
|
180
309
|
</Dropdown.Content>
|
181
310
|
</Dropdown.Portal>
|
182
311
|
</Dropdown.Root>
|
@@ -212,6 +341,7 @@ const ChatMessage = React.memo(
|
|
212
341
|
roles: message.recipientRoles,
|
213
342
|
receiver: message.recipientPeer,
|
214
343
|
});
|
344
|
+
const [openSheet, setOpenSheet] = useState(false);
|
215
345
|
// show pin action only if peer has remove others permission and the message is of broadcast type
|
216
346
|
const showPinAction = permissions.removeOthers && !messageType && elements?.chat?.allow_pinning_messages;
|
217
347
|
|
@@ -231,7 +361,12 @@ const ChatMessage = React.memo(
|
|
231
361
|
<Box
|
232
362
|
ref={ref}
|
233
363
|
as="div"
|
234
|
-
css={{
|
364
|
+
css={{
|
365
|
+
mb: '$10',
|
366
|
+
pr: '$10',
|
367
|
+
mt: '$8',
|
368
|
+
'&:hover .chat_actions': { opacity: 1 },
|
369
|
+
}}
|
235
370
|
style={style}
|
236
371
|
>
|
237
372
|
<Flex
|
@@ -245,9 +380,17 @@ const ChatMessage = React.memo(
|
|
245
380
|
px: messageType ? '$4' : '$2',
|
246
381
|
py: messageType ? '$4' : 0,
|
247
382
|
userSelect: 'none',
|
383
|
+
'@md': {
|
384
|
+
cursor: 'pointer',
|
385
|
+
},
|
248
386
|
}}
|
249
387
|
key={message.time}
|
250
388
|
data-testid="chat_msg"
|
389
|
+
onClick={() => {
|
390
|
+
if (isMobile) {
|
391
|
+
setOpenSheet(true);
|
392
|
+
}
|
393
|
+
}}
|
251
394
|
>
|
252
395
|
<Text
|
253
396
|
css={{
|
@@ -291,7 +434,17 @@ const ChatMessage = React.memo(
|
|
291
434
|
receiver={message.recipientPeer}
|
292
435
|
roles={message.recipientRoles}
|
293
436
|
/>
|
294
|
-
|
437
|
+
|
438
|
+
<ChatActions
|
439
|
+
onPin={onPin}
|
440
|
+
showPinAction={showPinAction}
|
441
|
+
message={message}
|
442
|
+
peerId={message.sender}
|
443
|
+
sentByLocalPeer={message.sender === localPeerId}
|
444
|
+
isMobile={isMobile}
|
445
|
+
openSheet={openSheet}
|
446
|
+
setOpenSheet={setOpenSheet}
|
447
|
+
/>
|
295
448
|
</Text>
|
296
449
|
<Text
|
297
450
|
variant="sm"
|
@@ -303,7 +456,10 @@ const ChatMessage = React.memo(
|
|
303
456
|
userSelect: 'all',
|
304
457
|
color: isOverlay ? '#FFF' : '$on_surface_high',
|
305
458
|
}}
|
306
|
-
onClick={e =>
|
459
|
+
onClick={e => {
|
460
|
+
e.stopPropagation();
|
461
|
+
setOpenSheet(true);
|
462
|
+
}}
|
307
463
|
>
|
308
464
|
<AnnotisedMessage message={message.message} />
|
309
465
|
</Text>
|
@@ -314,7 +470,9 @@ const ChatMessage = React.memo(
|
|
314
470
|
);
|
315
471
|
const ChatList = React.forwardRef(
|
316
472
|
({ width, height, setRowHeight, getRowHeight, messages, unreadCount = 0, scrollToBottom }, listRef) => {
|
317
|
-
const {
|
473
|
+
const { setPinnedMessages } = useSetPinnedMessages();
|
474
|
+
const pinnedMessages = useHMSStore(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGES)) || [];
|
475
|
+
const localPeerName = useHMSStore(selectLocalPeerName);
|
318
476
|
useLayoutEffect(() => {
|
319
477
|
if (listRef.current && listRef.current.scrollToItem) {
|
320
478
|
scrollToBottom(1);
|
@@ -343,7 +501,7 @@ const ChatList = React.forwardRef(
|
|
343
501
|
unreadCount={unreadCount}
|
344
502
|
isLast={index >= messages.length - 2}
|
345
503
|
scrollToBottom={scrollToBottom}
|
346
|
-
onPin={() =>
|
504
|
+
onPin={() => setPinnedMessages(pinnedMessages, messages[index], localPeerName)}
|
347
505
|
/>
|
348
506
|
)}
|
349
507
|
</VariableSizeList>
|
@@ -397,14 +555,27 @@ const VirtualizedChatMessages = React.forwardRef(({ messages, unreadCount = 0, s
|
|
397
555
|
);
|
398
556
|
});
|
399
557
|
|
400
|
-
export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom }, listRef) => {
|
558
|
+
export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom, blacklistedPeerIDs }, listRef) => {
|
401
559
|
const storeMessageSelector = role
|
402
560
|
? selectMessagesByRole(role)
|
403
561
|
: peerId
|
404
562
|
? selectMessagesByPeerID(peerId)
|
405
563
|
: selectHMSMessages;
|
406
|
-
let messages = useHMSStore(storeMessageSelector);
|
407
|
-
|
564
|
+
let messages = useHMSStore(storeMessageSelector) || [];
|
565
|
+
const blacklistedMessageIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST)) || [];
|
566
|
+
const getFilteredMessages = () => {
|
567
|
+
const blacklistedMessageIDSet = new Set(blacklistedMessageIDs);
|
568
|
+
const blacklistedPeerIDSet = new Set(blacklistedPeerIDs);
|
569
|
+
return (
|
570
|
+
messages?.filter(
|
571
|
+
message =>
|
572
|
+
message.type === 'chat' &&
|
573
|
+
!blacklistedMessageIDSet.has(message.id) &&
|
574
|
+
!blacklistedPeerIDSet.has(message.sender),
|
575
|
+
) || []
|
576
|
+
);
|
577
|
+
};
|
578
|
+
|
408
579
|
const isMobile = useMedia(cssConfig.media.md);
|
409
580
|
const { elements } = useRoomLayoutConferencingScreen();
|
410
581
|
const unreadCount = useUnreadCount({ role, peerId });
|
@@ -440,7 +611,7 @@ export const ChatBody = React.forwardRef(({ role, peerId, scrollToBottom }, list
|
|
440
611
|
return (
|
441
612
|
<Fragment>
|
442
613
|
<VirtualizedChatMessages
|
443
|
-
messages={
|
614
|
+
messages={getFilteredMessages()}
|
444
615
|
scrollToBottom={scrollToBottom}
|
445
616
|
unreadCount={unreadCount}
|
446
617
|
ref={listRef}
|
@@ -2,9 +2,10 @@ 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 { useHMSActions } from '@100mslive/react-sdk';
|
6
|
-
import { EmojiIcon, SendIcon } from '@100mslive/react-icons';
|
7
|
-
import { Box, config as cssConfig, Flex, IconButton as BaseIconButton, Popover, styled } from '../../..';
|
5
|
+
import { selectLocalPeerName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
|
6
|
+
import { EmojiIcon, PauseCircleIcon, SendIcon, VerticalMenuIcon } from '@100mslive/react-icons';
|
7
|
+
import { Box, config as cssConfig, Flex, IconButton as BaseIconButton, Popover, styled, Text } from '../../..';
|
8
|
+
import { IconButton } from '../../../IconButton';
|
8
9
|
// @ts-ignore
|
9
10
|
import { ToastManager } from '../Toast/ToastManager';
|
10
11
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
@@ -13,6 +14,8 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
|
|
13
14
|
import { useChatDraftMessage } from '../AppData/useChatState';
|
14
15
|
// @ts-ignore
|
15
16
|
import { useEmojiPickerStyles } from './useEmojiPickerStyles';
|
17
|
+
// @ts-ignore
|
18
|
+
import { SESSION_STORE_KEY } from '../../common/constants';
|
16
19
|
|
17
20
|
const TextArea = styled('textarea', {
|
18
21
|
width: '100%',
|
@@ -82,7 +85,10 @@ export const ChatFooter = ({
|
|
82
85
|
const [draftMessage, setDraftMessage] = useChatDraftMessage();
|
83
86
|
const isMobile = useMedia(cssConfig.media.md);
|
84
87
|
const { elements } = useRoomLayoutConferencingScreen();
|
88
|
+
const message_placeholder = elements?.chat?.message_placeholder || 'Send a message';
|
89
|
+
const localPeerName = useHMSStore(selectLocalPeerName);
|
85
90
|
const isOverlayChat = elements?.chat?.is_overlay;
|
91
|
+
const can_disable_chat = !!elements?.chat?.real_time_controls?.can_disable_chat;
|
86
92
|
|
87
93
|
const sendMessage = useCallback(async () => {
|
88
94
|
const message = inputRef?.current?.value;
|
@@ -122,10 +128,48 @@ export const ChatFooter = ({
|
|
122
128
|
}, [setDraftMessage]);
|
123
129
|
|
124
130
|
return (
|
125
|
-
|
131
|
+
<Box>
|
126
132
|
{/* {screenType !== 'hls_live_streaming' ? (
|
127
133
|
<ChatSelectorContainer onSelect={onSelect} role={role} peerId={peerId} selection={selection} />
|
128
134
|
) : null} */}
|
135
|
+
{can_disable_chat ? (
|
136
|
+
<Flex align="center" justify="end" css={{ w: '100%', mb: '$4' }}>
|
137
|
+
<Popover.Root>
|
138
|
+
<Popover.Trigger asChild>
|
139
|
+
<IconButton css={{ border: '1px solid $border_bright' }}>
|
140
|
+
<VerticalMenuIcon height="16" width="16" />
|
141
|
+
</IconButton>
|
142
|
+
</Popover.Trigger>
|
143
|
+
<Popover.Portal>
|
144
|
+
<Popover.Content
|
145
|
+
align="end"
|
146
|
+
side="top"
|
147
|
+
onClick={() => {
|
148
|
+
hmsActions.sessionStore.set(SESSION_STORE_KEY.CHAT_STATE, {
|
149
|
+
enabled: false,
|
150
|
+
updatedBy: localPeerName,
|
151
|
+
});
|
152
|
+
}}
|
153
|
+
css={{
|
154
|
+
backgroundColor: '$surface_default',
|
155
|
+
display: 'flex',
|
156
|
+
alignItems: 'center',
|
157
|
+
gap: '$4',
|
158
|
+
borderRadius: '$1',
|
159
|
+
color: '$on_surface_high',
|
160
|
+
cursor: 'pointer',
|
161
|
+
'&:hover': { backgroundColor: '$surface_dim' },
|
162
|
+
}}
|
163
|
+
>
|
164
|
+
<PauseCircleIcon />
|
165
|
+
<Text variant="sm" css={{ fontWeight: '$semiBold' }}>
|
166
|
+
Pause Chat
|
167
|
+
</Text>
|
168
|
+
</Popover.Content>
|
169
|
+
</Popover.Portal>
|
170
|
+
</Popover.Root>
|
171
|
+
</Flex>
|
172
|
+
) : null}
|
129
173
|
<Flex align="center" css={{ gap: '$4', w: '100%' }}>
|
130
174
|
<Flex
|
131
175
|
align="center"
|
@@ -153,7 +197,7 @@ export const ChatFooter = ({
|
|
153
197
|
'& ~ .send-msg': { color: '$on_surface_low' },
|
154
198
|
'&::placeholder': { color: '$on_surface_medium' },
|
155
199
|
}}
|
156
|
-
placeholder=
|
200
|
+
placeholder={message_placeholder}
|
157
201
|
ref={inputRef}
|
158
202
|
required
|
159
203
|
autoFocus={!isMobile}
|
@@ -195,6 +239,6 @@ export const ChatFooter = ({
|
|
195
239
|
</BaseIconButton>
|
196
240
|
</Flex>
|
197
241
|
</Flex>
|
198
|
-
|
242
|
+
</Box>
|
199
243
|
);
|
200
244
|
};
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import React, { useCallback } from 'react';
|
2
|
+
import { selectLocalPeerName, selectSessionStore, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
|
3
|
+
import { Button } from '../../../Button';
|
4
|
+
import { Box, Flex } from '../../../Layout';
|
5
|
+
import { Text } from '../../../Text';
|
6
|
+
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
7
|
+
import { SESSION_STORE_KEY } from '../../common/constants';
|
8
|
+
|
9
|
+
export const ChatPaused = () => {
|
10
|
+
const hmsActions = useHMSActions();
|
11
|
+
const { elements } = useRoomLayoutConferencingScreen();
|
12
|
+
const { can_disable_chat } = elements?.chat.real_time_controls || false;
|
13
|
+
const { enabled: isChatEnabled = true, updatedBy: chatStateUpdatedBy = '' } =
|
14
|
+
useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)) || {};
|
15
|
+
const localPeerName = useHMSStore(selectLocalPeerName);
|
16
|
+
|
17
|
+
const unPauseChat = useCallback(
|
18
|
+
async () =>
|
19
|
+
await hmsActions.sessionStore.set(SESSION_STORE_KEY.CHAT_STATE, {
|
20
|
+
enabled: true,
|
21
|
+
updatedBy: localPeerName,
|
22
|
+
}),
|
23
|
+
[hmsActions, localPeerName],
|
24
|
+
);
|
25
|
+
|
26
|
+
return isChatEnabled ? null : (
|
27
|
+
<Flex
|
28
|
+
align="center"
|
29
|
+
justify="between"
|
30
|
+
css={{ borderRadius: '$1', bg: '$surface_default', p: '$4 $4 $4 $8', w: '100%' }}
|
31
|
+
>
|
32
|
+
<Box>
|
33
|
+
<Text variant="sm" css={{ fontWeight: '$semiBold', color: '$on_surface_high' }}>
|
34
|
+
Chat paused
|
35
|
+
</Text>
|
36
|
+
<Text
|
37
|
+
variant="xs"
|
38
|
+
css={{ color: '$on_surface_medium', maxWidth: '100%', overflow: 'hidden', textOverflow: 'ellipsis' }}
|
39
|
+
>
|
40
|
+
Chat has been paused by {chatStateUpdatedBy}
|
41
|
+
</Text>
|
42
|
+
</Box>
|
43
|
+
{can_disable_chat ? (
|
44
|
+
<Button css={{ fontWeight: '$semiBold', fontSize: '$sm', borderRadius: '$2' }} onClick={unPauseChat}>
|
45
|
+
Resume
|
46
|
+
</Button>
|
47
|
+
) : (
|
48
|
+
<></>
|
49
|
+
)}
|
50
|
+
</Flex>
|
51
|
+
);
|
52
|
+
};
|
53
|
+
|
54
|
+
export const ChatBlocked = () => {
|
55
|
+
return (
|
56
|
+
<Flex
|
57
|
+
align="center"
|
58
|
+
justify="between"
|
59
|
+
css={{ borderRadius: '$1', bg: '$surface_default', p: '$4 $4 $4 $8', w: '100%' }}
|
60
|
+
>
|
61
|
+
<Text variant="sm" css={{ color: '$on_surface_medium', textAlign: 'center', w: '100%' }}>
|
62
|
+
You've been blocked from sending messages
|
63
|
+
</Text>
|
64
|
+
</Flex>
|
65
|
+
);
|
66
|
+
};
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Flex } from '../../../Layout';
|
3
|
+
import { Text } from '../../../Text';
|
4
|
+
|
5
|
+
export const MwebChatOption = ({
|
6
|
+
icon,
|
7
|
+
text,
|
8
|
+
onClick,
|
9
|
+
color = '$on_surface_high',
|
10
|
+
}: {
|
11
|
+
icon: any;
|
12
|
+
text: string;
|
13
|
+
onClick: () => void | Promise<void>;
|
14
|
+
color: string;
|
15
|
+
}) => {
|
16
|
+
return (
|
17
|
+
<Flex align="center" css={{ w: '100%', color, cursor: 'pointer', gap: '$4', p: '$8' }} onClick={onClick}>
|
18
|
+
{icon}
|
19
|
+
<Text variant="sm" css={{ color, fontWeight: '$semiBold' }}>
|
20
|
+
{text}
|
21
|
+
</Text>
|
22
|
+
</Flex>
|
23
|
+
);
|
24
|
+
};
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { ChevronDownIcon, ChevronUpIcon } from '@100mslive/react-icons';
|
3
|
+
import { Box, Flex } from '../../../Layout';
|
4
|
+
|
5
|
+
export const Navigation = ({
|
6
|
+
total,
|
7
|
+
index,
|
8
|
+
showPrevious,
|
9
|
+
showNext,
|
10
|
+
isMobile,
|
11
|
+
}: {
|
12
|
+
total: number;
|
13
|
+
index: number;
|
14
|
+
showPrevious: () => void;
|
15
|
+
showNext: () => void;
|
16
|
+
isMobile: boolean;
|
17
|
+
}) => {
|
18
|
+
const sticksCount = Math.min(3, total);
|
19
|
+
|
20
|
+
if (total < 2) {
|
21
|
+
return null;
|
22
|
+
}
|
23
|
+
|
24
|
+
return isMobile ? (
|
25
|
+
<Flex direction="column" css={{ gap: '$1' }}>
|
26
|
+
{[...Array(sticksCount)].map((_, i) => (
|
27
|
+
<Box
|
28
|
+
css={{
|
29
|
+
borderLeft: '2px solid',
|
30
|
+
height: '$8',
|
31
|
+
borderColor: i === index ? '$on_surface_high' : '$on_surface_low',
|
32
|
+
}}
|
33
|
+
/>
|
34
|
+
))}
|
35
|
+
</Flex>
|
36
|
+
) : (
|
37
|
+
<Flex direction="column" css={{ gap: '$4' }}>
|
38
|
+
<Flex
|
39
|
+
onClick={showPrevious}
|
40
|
+
css={
|
41
|
+
index === 0
|
42
|
+
? { cursor: 'not-allowed', color: '$on_surface_low' }
|
43
|
+
: { cursor: 'pointer', color: '$on_surface_medium' }
|
44
|
+
}
|
45
|
+
>
|
46
|
+
<ChevronUpIcon height={20} width={20} />
|
47
|
+
</Flex>
|
48
|
+
<Flex
|
49
|
+
onClick={showNext}
|
50
|
+
css={
|
51
|
+
index === total - 1
|
52
|
+
? { cursor: 'not-allowed', color: '$on_surface_low' }
|
53
|
+
: { cursor: 'pointer', color: '$on_surface_medium' }
|
54
|
+
}
|
55
|
+
>
|
56
|
+
<ChevronDownIcon height={20} width={20} />
|
57
|
+
</Flex>
|
58
|
+
</Flex>
|
59
|
+
);
|
60
|
+
};
|