@100mslive/roomkit-react 0.1.14 → 0.1.16
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-662T7R7H.js → HLSView-EMUOLCTM.js} +128 -39
- package/dist/HLSView-EMUOLCTM.js.map +7 -0
- package/dist/Prebuilt/common/PeersSorter.d.ts +1 -0
- package/dist/Prebuilt/common/constants.d.ts +9 -5
- package/dist/Prebuilt/common/hooks.d.ts +1 -0
- package/dist/Prebuilt/components/Footer/ParticipantList.d.ts +17 -0
- package/dist/Prebuilt/components/Footer/RoleAccordion.d.ts +3 -2
- package/dist/Prebuilt/components/Footer/WhiteboardToggle.d.ts +2 -0
- package/dist/Prebuilt/components/HMSVideo/HLSCaptionSelector.d.ts +5 -0
- package/dist/Prebuilt/components/Notifications/HandRaisedNotifications.d.ts +1 -0
- package/dist/Prebuilt/components/Polls/Voting/Leaderboard.d.ts +4 -0
- package/dist/Prebuilt/components/Polls/Voting/LeaderboardEntry.d.ts +9 -0
- package/dist/Prebuilt/components/Polls/Voting/PeerParticipationSummary.d.ts +5 -0
- package/dist/Prebuilt/components/PreviousRoleInMetadata.d.ts +1 -0
- package/dist/Prebuilt/components/RemoveParticipant.d.ts +5 -0
- package/dist/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.d.ts +4 -0
- package/dist/Prebuilt/layouts/WhiteboardView.d.ts +2 -0
- package/dist/{chunk-2B7YYNHQ.js → chunk-ZYR4B4KQ.js} +2240 -1767
- package/dist/chunk-ZYR4B4KQ.js.map +7 -0
- package/dist/index.cjs.js +2805 -2172
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +1 -1
- package/dist/meta.cjs.json +739 -177
- package/dist/meta.esbuild.json +749 -186
- package/package.json +7 -7
- package/src/Prebuilt/AppStateContext.tsx +1 -1
- package/src/Prebuilt/common/PeersSorter.ts +24 -8
- package/src/Prebuilt/common/constants.ts +6 -6
- package/src/Prebuilt/common/hooks.ts +16 -0
- package/src/Prebuilt/common/utils.js +33 -0
- package/src/Prebuilt/components/AppData/AppData.tsx +1 -16
- package/src/Prebuilt/components/Chat/Chat.jsx +10 -34
- package/src/Prebuilt/components/Chat/ChatBody.jsx +107 -66
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +21 -12
- package/src/Prebuilt/components/Chat/ChatSelector.tsx +25 -25
- package/src/Prebuilt/components/Chat/ChatSelectorContainer.tsx +15 -16
- package/src/Prebuilt/components/Chat/PinnedMessage.tsx +7 -2
- package/src/Prebuilt/components/ConferenceScreen.tsx +2 -0
- package/src/Prebuilt/components/Footer/ChatToggle.tsx +30 -7
- package/src/Prebuilt/components/Footer/Footer.tsx +2 -1
- package/src/Prebuilt/components/Footer/PaginatedParticipants.tsx +0 -1
- package/src/Prebuilt/components/Footer/{ParticipantList.jsx → ParticipantList.tsx} +169 -127
- package/src/Prebuilt/components/Footer/RoleAccordion.tsx +23 -13
- package/src/Prebuilt/components/Footer/WhiteboardToggle.tsx +34 -0
- package/src/Prebuilt/components/HMSVideo/HLSCaptionSelector.tsx +13 -0
- package/src/Prebuilt/components/HMSVideo/HMSVideo.jsx +34 -2
- package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +35 -0
- package/src/Prebuilt/components/Notifications/Notifications.tsx +47 -14
- package/src/Prebuilt/components/Notifications/PeerNotifications.tsx +7 -2
- package/src/Prebuilt/components/Polls/CreatePollQuiz/PollsQuizMenu.jsx +3 -9
- package/src/Prebuilt/components/Polls/CreateQuestions/CreateQuestions.jsx +21 -1
- package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.jsx +34 -7
- package/src/Prebuilt/components/Polls/CreateQuestions/SavedQuestion.jsx +2 -2
- package/src/Prebuilt/components/Polls/Polls.tsx +3 -0
- package/src/Prebuilt/components/Polls/Voting/Leaderboard.tsx +115 -0
- package/src/Prebuilt/components/Polls/Voting/LeaderboardEntry.tsx +63 -0
- package/src/Prebuilt/components/Polls/Voting/PeerParticipationSummary.tsx +38 -0
- package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +33 -8
- package/src/Prebuilt/components/Polls/Voting/StandardVoting.jsx +7 -1
- package/src/Prebuilt/components/Polls/Voting/Voting.jsx +31 -13
- package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +33 -21
- package/src/Prebuilt/components/Polls/common/SingleChoiceOptions.jsx +47 -35
- package/src/Prebuilt/components/Polls/common/StatusIndicator.jsx +2 -22
- package/src/Prebuilt/components/Polls/common/VoteCount.jsx +1 -15
- package/src/Prebuilt/components/PreviousRoleInMetadata.tsx +21 -0
- package/src/Prebuilt/components/RemoveParticipant.tsx +35 -0
- package/src/Prebuilt/components/RoleChangeModal.jsx +1 -1
- package/src/Prebuilt/components/SidePaneTabs.tsx +0 -1
- package/src/Prebuilt/components/TileMenu/TileMenuContent.tsx +1 -1
- package/src/Prebuilt/components/Toast/ToastConfig.jsx +15 -3
- package/src/Prebuilt/components/VideoLayouts/EqualProminence.tsx +6 -5
- package/src/Prebuilt/components/VideoLayouts/GridLayout.tsx +27 -5
- package/src/Prebuilt/components/VideoLayouts/ScreenshareLayout.tsx +0 -1
- package/src/Prebuilt/components/hooks/useCloseScreenshareWhiteboard.tsx +24 -0
- package/src/Prebuilt/layouts/HLSView.jsx +51 -3
- package/src/Prebuilt/layouts/VideoStreamingSection.tsx +20 -3
- package/src/Prebuilt/layouts/WhiteboardView.tsx +66 -0
- package/dist/HLSView-662T7R7H.js.map +0 -7
- package/dist/chunk-2B7YYNHQ.js.map +0 -7
- package/src/Prebuilt/components/AppData/useAppLayout.js +0 -6
- package/src/Prebuilt/components/init/initUtils.js +0 -67
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
selectHMSMessages,
|
|
8
8
|
selectLocalPeerID,
|
|
9
9
|
selectLocalPeerName,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
selectLocalPeerRoleName,
|
|
11
|
+
selectPeerNameByID,
|
|
12
12
|
selectPermissions,
|
|
13
13
|
selectSessionStore,
|
|
14
|
+
selectUnreadHMSMessagesCount,
|
|
14
15
|
useHMSActions,
|
|
15
16
|
useHMSStore,
|
|
16
17
|
} from '@100mslive/react-sdk';
|
|
@@ -19,6 +20,7 @@ import {
|
|
|
19
20
|
CrossCircleIcon,
|
|
20
21
|
CrossIcon,
|
|
21
22
|
EyeCloseIcon,
|
|
23
|
+
PeopleRemoveIcon,
|
|
22
24
|
PinIcon,
|
|
23
25
|
ReplyIcon,
|
|
24
26
|
VerticalMenuIcon,
|
|
@@ -34,10 +36,9 @@ import emptyChat from '../../images/empty-chat.svg';
|
|
|
34
36
|
import { ToastManager } from '../Toast/ToastManager';
|
|
35
37
|
import { MwebChatOption } from './MwebChatOption';
|
|
36
38
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
|
37
|
-
import { useSetSubscribedChatSelector
|
|
39
|
+
import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
|
|
38
40
|
import { useChatBlacklist } from '../hooks/useChatBlacklist';
|
|
39
41
|
import { useSetPinnedMessages } from '../hooks/useSetPinnedMessages';
|
|
40
|
-
import { useUnreadCount } from './useUnreadCount';
|
|
41
42
|
import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
|
|
42
43
|
|
|
43
44
|
const iconStyle = { height: '1.125rem', width: '1.125rem' };
|
|
@@ -70,27 +71,28 @@ const MessageTypeContainer = ({ left, right }) => {
|
|
|
70
71
|
<Flex
|
|
71
72
|
align="center"
|
|
72
73
|
css={{
|
|
73
|
-
|
|
74
|
-
right: 0,
|
|
75
|
-
zIndex: 1,
|
|
74
|
+
ml: '$2',
|
|
76
75
|
mr: '$4',
|
|
77
|
-
|
|
78
|
-
border: '1px solid $border_bright',
|
|
79
|
-
r: '$0',
|
|
80
|
-
gap: '$3',
|
|
76
|
+
gap: '$space$2',
|
|
81
77
|
}}
|
|
82
|
-
className="message_type_container"
|
|
83
78
|
>
|
|
84
79
|
{left && (
|
|
85
|
-
<SenderName
|
|
80
|
+
<SenderName
|
|
81
|
+
variant="xs"
|
|
82
|
+
as="span"
|
|
83
|
+
css={{ color: '$on_surface_medium', textTransform: 'capitalize', fontWeight: '$regular' }}
|
|
84
|
+
>
|
|
86
85
|
{left}
|
|
87
86
|
</SenderName>
|
|
88
87
|
)}
|
|
89
88
|
{right && (
|
|
90
89
|
<SenderName
|
|
91
90
|
as="span"
|
|
92
|
-
variant="
|
|
93
|
-
css={{
|
|
91
|
+
variant="overline"
|
|
92
|
+
css={{
|
|
93
|
+
color: '$on_surface_medium',
|
|
94
|
+
fontWeight: '$regular',
|
|
95
|
+
}}
|
|
94
96
|
>
|
|
95
97
|
{right}
|
|
96
98
|
</SenderName>
|
|
@@ -99,13 +101,17 @@ const MessageTypeContainer = ({ left, right }) => {
|
|
|
99
101
|
);
|
|
100
102
|
};
|
|
101
103
|
|
|
102
|
-
const MessageType = ({ roles, receiver }) => {
|
|
104
|
+
const MessageType = ({ roles, hasCurrentUserSent, receiver }) => {
|
|
105
|
+
const peerName = useHMSStore(selectPeerNameByID(receiver));
|
|
106
|
+
const localPeerRoleName = useHMSStore(selectLocalPeerRoleName);
|
|
103
107
|
if (receiver) {
|
|
104
|
-
return
|
|
108
|
+
return (
|
|
109
|
+
<MessageTypeContainer left={hasCurrentUserSent ? `${peerName ? `to ${peerName}` : ''}` : 'to You'} right="(DM)" />
|
|
110
|
+
);
|
|
105
111
|
}
|
|
106
112
|
|
|
107
|
-
if (roles && roles.length
|
|
108
|
-
return <MessageTypeContainer left=
|
|
113
|
+
if (roles && roles.length) {
|
|
114
|
+
return <MessageTypeContainer left={`to ${hasCurrentUserSent ? roles[0] : localPeerRoleName}`} right="(Group)" />;
|
|
109
115
|
}
|
|
110
116
|
return null;
|
|
111
117
|
};
|
|
@@ -153,8 +159,8 @@ const getMessageType = ({ roles, receiver }) => {
|
|
|
153
159
|
const ChatActions = ({
|
|
154
160
|
onPin,
|
|
155
161
|
showPinAction,
|
|
156
|
-
|
|
157
|
-
|
|
162
|
+
onReply,
|
|
163
|
+
showReply,
|
|
158
164
|
message,
|
|
159
165
|
sentByLocalPeer,
|
|
160
166
|
isMobile,
|
|
@@ -167,6 +173,8 @@ const ChatActions = ({
|
|
|
167
173
|
can_block_user: false,
|
|
168
174
|
};
|
|
169
175
|
const [open, setOpen] = useState(false);
|
|
176
|
+
const actions = useHMSActions();
|
|
177
|
+
const canRemoveOthers = useHMSStore(selectPermissions)?.removeOthers;
|
|
170
178
|
const { blacklistItem: blacklistPeer } = useChatBlacklist(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST);
|
|
171
179
|
|
|
172
180
|
const { blacklistItem: blacklistMessage, blacklistedIDs: blacklistedMessageIDs = [] } = useChatBlacklist(
|
|
@@ -199,11 +207,11 @@ const ChatActions = ({
|
|
|
199
207
|
|
|
200
208
|
const options = {
|
|
201
209
|
reply: {
|
|
202
|
-
text: 'Reply Privately',
|
|
203
|
-
tooltipText: 'Reply
|
|
210
|
+
text: message.recipientRoles?.length ? 'Reply to Group' : 'Reply Privately',
|
|
211
|
+
tooltipText: message.recipientRoles?.length ? 'Reply to Group' : 'Reply Privately',
|
|
204
212
|
icon: <ReplyIcon style={iconStyle} />,
|
|
205
|
-
onClick:
|
|
206
|
-
show:
|
|
213
|
+
onClick: onReply,
|
|
214
|
+
show: showReply,
|
|
207
215
|
},
|
|
208
216
|
pin: {
|
|
209
217
|
text: 'Pin message',
|
|
@@ -220,7 +228,7 @@ const ChatActions = ({
|
|
|
220
228
|
show: true,
|
|
221
229
|
},
|
|
222
230
|
hide: {
|
|
223
|
-
text: 'Hide for everyone',
|
|
231
|
+
text: message.recipientPeer ? 'Hide for both' : 'Hide for everyone',
|
|
224
232
|
icon: <EyeCloseIcon style={iconStyle} />,
|
|
225
233
|
onClick: async () => {
|
|
226
234
|
blacklistMessage(message.id);
|
|
@@ -235,6 +243,19 @@ const ChatActions = ({
|
|
|
235
243
|
color: '$alert_error_default',
|
|
236
244
|
show: can_block_user && !sentByLocalPeer,
|
|
237
245
|
},
|
|
246
|
+
remove: {
|
|
247
|
+
text: 'Remove Partipant',
|
|
248
|
+
icon: <PeopleRemoveIcon style={iconStyle} />,
|
|
249
|
+
color: '$alert_error_default',
|
|
250
|
+
show: canRemoveOthers && !sentByLocalPeer,
|
|
251
|
+
onClick: async () => {
|
|
252
|
+
try {
|
|
253
|
+
await actions.removePeer(message.sender, '');
|
|
254
|
+
} catch (error) {
|
|
255
|
+
ToastManager.addToast({ title: error.message, variant: 'error' });
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
},
|
|
238
259
|
};
|
|
239
260
|
|
|
240
261
|
if (isMobile) {
|
|
@@ -316,7 +337,7 @@ const ChatActions = ({
|
|
|
316
337
|
</Tooltip>
|
|
317
338
|
) : null}
|
|
318
339
|
|
|
319
|
-
{options.block.show || options.hide.show ? (
|
|
340
|
+
{options.block.show || options.hide.show || options.remove.show ? (
|
|
320
341
|
<Tooltip boxCss={tooltipBoxCSS} title="More actions">
|
|
321
342
|
<Dropdown.Trigger asChild>
|
|
322
343
|
<IconButton>
|
|
@@ -353,6 +374,18 @@ const ChatActions = ({
|
|
|
353
374
|
</Text>
|
|
354
375
|
</Dropdown.Item>
|
|
355
376
|
) : null}
|
|
377
|
+
{options.remove.show ? (
|
|
378
|
+
<Dropdown.Item
|
|
379
|
+
data-testid="remove_peer_btn"
|
|
380
|
+
onClick={options.remove.onClick}
|
|
381
|
+
css={{ color: options.remove.color }}
|
|
382
|
+
>
|
|
383
|
+
{options.remove.icon}
|
|
384
|
+
<Text variant="sm" css={{ ml: '$4', color: 'inherit', fontWeight: '$semiBold' }}>
|
|
385
|
+
{options.remove.text}
|
|
386
|
+
</Text>
|
|
387
|
+
</Dropdown.Item>
|
|
388
|
+
) : null}
|
|
356
389
|
</Dropdown.Content>
|
|
357
390
|
</Dropdown.Portal>
|
|
358
391
|
</Dropdown.Root>
|
|
@@ -363,7 +396,7 @@ const SenderName = styled(Text, {
|
|
|
363
396
|
overflow: 'hidden',
|
|
364
397
|
textOverflow: 'ellipsis',
|
|
365
398
|
whiteSpace: 'nowrap',
|
|
366
|
-
maxWidth: '
|
|
399
|
+
maxWidth: '14ch',
|
|
367
400
|
minWidth: 0,
|
|
368
401
|
color: '$on_surface_high',
|
|
369
402
|
fontWeight: '$semiBold',
|
|
@@ -381,20 +414,25 @@ const ChatMessage = React.memo(
|
|
|
381
414
|
}, [index, setRowHeight]);
|
|
382
415
|
const isMobile = useMedia(cssConfig.media.md);
|
|
383
416
|
const isPrivateChatEnabled = !!elements?.chat?.private_chat_enabled;
|
|
417
|
+
const roleWhiteList = elements?.chat?.roles_whitelist || [];
|
|
384
418
|
const isOverlay = elements?.chat?.is_overlay && isMobile;
|
|
385
419
|
const hmsActions = useHMSActions();
|
|
386
420
|
const localPeerId = useHMSStore(selectLocalPeerID);
|
|
387
|
-
const
|
|
388
|
-
const selectedPeer =
|
|
389
|
-
const selectedRole = useSubscribeChatSelector(CHAT_SELECTOR.ROLE);
|
|
390
|
-
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER_ID);
|
|
421
|
+
const [selectedRole, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
|
422
|
+
const [selectedPeer, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER);
|
|
391
423
|
const messageType = getMessageType({
|
|
392
424
|
roles: message.recipientRoles,
|
|
393
425
|
receiver: message.recipientPeer,
|
|
394
426
|
});
|
|
395
427
|
const [openSheet, setOpenSheet] = useState(false);
|
|
396
|
-
|
|
397
|
-
|
|
428
|
+
const showPinAction = !!elements?.chat?.allow_pinning_messages;
|
|
429
|
+
let showReply = false;
|
|
430
|
+
if (message.recipientRoles && roleWhiteList.includes(message.recipientRoles[0])) {
|
|
431
|
+
showReply = true;
|
|
432
|
+
} else if (message.sender !== selectedPeer.id && message.sender !== localPeerId && isPrivateChatEnabled) {
|
|
433
|
+
showReply = true;
|
|
434
|
+
}
|
|
435
|
+
|
|
398
436
|
useEffect(() => {
|
|
399
437
|
if (message.id && !message.read && inView) {
|
|
400
438
|
hmsActions.setMessageRead(true, message.id);
|
|
@@ -428,7 +466,7 @@ const ChatMessage = React.memo(
|
|
|
428
466
|
position: 'relative',
|
|
429
467
|
// Theme independent color, token should not be used for transparent chat
|
|
430
468
|
bg:
|
|
431
|
-
messageType && !(selectedPeer || selectedRole)
|
|
469
|
+
messageType && !(selectedPeer.id || selectedRole)
|
|
432
470
|
? isOverlay
|
|
433
471
|
? 'rgba(0, 0, 0, 0.64)'
|
|
434
472
|
: '$surface_default'
|
|
@@ -482,31 +520,45 @@ const ChatMessage = React.memo(
|
|
|
482
520
|
</SenderName>
|
|
483
521
|
</Tooltip>
|
|
484
522
|
)}
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
ml: '$2',
|
|
491
|
-
color: '$on_surface_medium',
|
|
492
|
-
flexShrink: 0,
|
|
493
|
-
}}
|
|
494
|
-
>
|
|
495
|
-
{formatTime(message.time)}
|
|
496
|
-
</Text>
|
|
497
|
-
) : null}
|
|
523
|
+
<MessageType
|
|
524
|
+
hasCurrentUserSent={message.sender === localPeerId}
|
|
525
|
+
receiver={message.recipientPeer}
|
|
526
|
+
roles={message.recipientRoles}
|
|
527
|
+
/>
|
|
498
528
|
</Flex>
|
|
499
|
-
{!(selectedPeer || selectedRole) && (
|
|
500
|
-
<MessageType receiver={message.recipientPeer} roles={message.recipientRoles} />
|
|
501
|
-
)}
|
|
502
529
|
|
|
530
|
+
{!isOverlay ? (
|
|
531
|
+
<Text
|
|
532
|
+
as="span"
|
|
533
|
+
variant="caption"
|
|
534
|
+
css={{
|
|
535
|
+
color: '$on_surface_medium',
|
|
536
|
+
flexShrink: 0,
|
|
537
|
+
position: 'absolute',
|
|
538
|
+
right: 0,
|
|
539
|
+
zIndex: 1,
|
|
540
|
+
mr: '$4',
|
|
541
|
+
p: '$2',
|
|
542
|
+
}}
|
|
543
|
+
>
|
|
544
|
+
{formatTime(message.time)}
|
|
545
|
+
</Text>
|
|
546
|
+
) : null}
|
|
503
547
|
<ChatActions
|
|
504
548
|
onPin={onPin}
|
|
505
549
|
showPinAction={showPinAction}
|
|
506
550
|
message={message}
|
|
507
551
|
sentByLocalPeer={message.sender === localPeerId}
|
|
508
|
-
|
|
509
|
-
|
|
552
|
+
onReply={() => {
|
|
553
|
+
if (message.recipientRoles?.length) {
|
|
554
|
+
setRoleSelector(message.recipientRoles[0]);
|
|
555
|
+
setPeerSelector({});
|
|
556
|
+
} else {
|
|
557
|
+
setRoleSelector('');
|
|
558
|
+
setPeerSelector({ id: message.sender, name: message.senderName });
|
|
559
|
+
}
|
|
560
|
+
}}
|
|
561
|
+
showReply={showReply}
|
|
510
562
|
isMobile={isMobile}
|
|
511
563
|
openSheet={openSheet}
|
|
512
564
|
setOpenSheet={setOpenSheet}
|
|
@@ -622,27 +674,16 @@ const VirtualizedChatMessages = React.forwardRef(({ messages, unreadCount = 0, s
|
|
|
622
674
|
});
|
|
623
675
|
|
|
624
676
|
export const ChatBody = React.forwardRef(({ scrollToBottom }, listRef) => {
|
|
625
|
-
|
|
626
|
-
const selectedRole = useSubscribeChatSelector(CHAT_SELECTOR.ROLE);
|
|
627
|
-
let storeMessageSelector;
|
|
628
|
-
if (selectedRole) {
|
|
629
|
-
storeMessageSelector = selectMessagesByRole(selectedRole);
|
|
630
|
-
} else if (selectedPeer) {
|
|
631
|
-
storeMessageSelector = selectMessagesByPeerID(selectedPeer);
|
|
632
|
-
} else {
|
|
633
|
-
storeMessageSelector = selectHMSMessages;
|
|
634
|
-
}
|
|
635
|
-
let messages = useHMSStore(storeMessageSelector) || [];
|
|
677
|
+
let messages = useHMSStore(selectHMSMessages);
|
|
636
678
|
const blacklistedMessageIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST)) || [];
|
|
637
679
|
const getFilteredMessages = () => {
|
|
638
680
|
const blacklistedMessageIDSet = new Set(blacklistedMessageIDs);
|
|
639
|
-
|
|
640
681
|
return messages?.filter(message => message.type === 'chat' && !blacklistedMessageIDSet.has(message.id)) || [];
|
|
641
682
|
};
|
|
642
683
|
|
|
643
684
|
const isMobile = useMedia(cssConfig.media.md);
|
|
644
685
|
const { elements } = useRoomLayoutConferencingScreen();
|
|
645
|
-
const unreadCount =
|
|
686
|
+
const unreadCount = useHMSStore(selectUnreadHMSMessagesCount);
|
|
646
687
|
|
|
647
688
|
if (messages.length === 0 && !(isMobile && elements?.chat?.is_overlay)) {
|
|
648
689
|
return (
|
|
@@ -2,7 +2,7 @@ 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 {
|
|
5
|
+
import { HMSException, selectLocalPeer, 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';
|
|
@@ -14,9 +14,10 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
|
|
|
14
14
|
// @ts-ignore
|
|
15
15
|
import { useChatDraftMessage } from '../AppData/useChatState';
|
|
16
16
|
// @ts-ignore
|
|
17
|
-
import { useSubscribeChatSelector } from '../AppData/useUISettings';
|
|
17
|
+
import { useSetSubscribedChatSelector, useSubscribeChatSelector } from '../AppData/useUISettings';
|
|
18
18
|
// @ts-ignore
|
|
19
19
|
import { useEmojiPickerStyles } from './useEmojiPickerStyles';
|
|
20
|
+
import { useDefaultChatSelection } from '../../common/hooks';
|
|
20
21
|
import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
|
|
21
22
|
|
|
22
23
|
const TextArea = styled('textarea', {
|
|
@@ -81,11 +82,17 @@ export const ChatFooter = ({ onSend, children }: { onSend: () => void; children:
|
|
|
81
82
|
const localPeer = useHMSStore(selectLocalPeer);
|
|
82
83
|
const isOverlayChat = elements?.chat?.is_overlay;
|
|
83
84
|
const canDisableChat = !!elements?.chat?.real_time_controls?.can_disable_chat;
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
85
|
+
const selectedPeer = useSubscribeChatSelector(CHAT_SELECTOR.PEER);
|
|
86
|
+
const [selectedRole, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
|
87
|
+
const defaultSelection = useDefaultChatSelection();
|
|
88
|
+
const selection = selectedPeer.name || selectedRole || defaultSelection;
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!selectedPeer.id && !selectedRole && !['Everyone', ''].includes(defaultSelection)) {
|
|
91
|
+
setRoleSelector(defaultSelection);
|
|
92
|
+
} else {
|
|
93
|
+
inputRef.current?.focus();
|
|
94
|
+
}
|
|
95
|
+
}, [defaultSelection, selectedPeer, selectedRole, setRoleSelector]);
|
|
89
96
|
const sendMessage = useCallback(async () => {
|
|
90
97
|
const message = inputRef?.current?.value;
|
|
91
98
|
if (!message || !message.trim().length) {
|
|
@@ -94,8 +101,8 @@ export const ChatFooter = ({ onSend, children }: { onSend: () => void; children:
|
|
|
94
101
|
try {
|
|
95
102
|
if (selectedRole) {
|
|
96
103
|
await hmsActions.sendGroupMessage(message, [selectedRole]);
|
|
97
|
-
} else if (selectedPeer) {
|
|
98
|
-
await hmsActions.sendDirectMessage(message, selectedPeer);
|
|
104
|
+
} else if (selectedPeer.id) {
|
|
105
|
+
await hmsActions.sendDirectMessage(message, selectedPeer.id);
|
|
99
106
|
} else {
|
|
100
107
|
await hmsActions.sendBroadcastMessage(message);
|
|
101
108
|
}
|
|
@@ -104,8 +111,10 @@ export const ChatFooter = ({ onSend, children }: { onSend: () => void; children:
|
|
|
104
111
|
onSend();
|
|
105
112
|
}, 0);
|
|
106
113
|
} catch (error) {
|
|
107
|
-
const err = error as
|
|
108
|
-
ToastManager.addToast({
|
|
114
|
+
const err = error as HMSException;
|
|
115
|
+
ToastManager.addToast({
|
|
116
|
+
title: err.message.startsWith('Invalid peer') ? `${selectedPeer.name} is not in this room` : err.message,
|
|
117
|
+
});
|
|
109
118
|
}
|
|
110
119
|
}, [selectedRole, selectedPeer, hmsActions, onSend]);
|
|
111
120
|
|
|
@@ -172,7 +181,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: () => void; children:
|
|
|
172
181
|
</Flex>
|
|
173
182
|
) : null}
|
|
174
183
|
</Flex>
|
|
175
|
-
{
|
|
184
|
+
{selection && (
|
|
176
185
|
<Flex align="center" css={{ gap: '$4', w: '100%' }}>
|
|
177
186
|
<Flex
|
|
178
187
|
align="center"
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
import { CheckIcon, PeopleIcon } from '@100mslive/react-icons';
|
|
12
12
|
import { Box, CSS, Dropdown, Flex, HorizontalDivider, Text, Tooltip } from '../../..';
|
|
13
13
|
import { config as cssConfig } from '../../../Theme';
|
|
14
|
-
// @ts-ignore
|
|
15
14
|
import { ParticipantSearch } from '../Footer/ParticipantList';
|
|
16
15
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
|
17
16
|
// @ts-ignore
|
|
@@ -90,7 +89,7 @@ const SelectorHeader = React.memo(
|
|
|
90
89
|
|
|
91
90
|
const Everyone = React.memo(({ active }: { active: boolean }) => {
|
|
92
91
|
const unreadCount: number = useHMSStore(selectUnreadHMSMessagesCount);
|
|
93
|
-
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.
|
|
92
|
+
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER);
|
|
94
93
|
const [, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
|
95
94
|
return (
|
|
96
95
|
<SelectorItem
|
|
@@ -99,7 +98,7 @@ const Everyone = React.memo(({ active }: { active: boolean }) => {
|
|
|
99
98
|
active={active}
|
|
100
99
|
unreadCount={unreadCount}
|
|
101
100
|
onClick={() => {
|
|
102
|
-
setPeerSelector(
|
|
101
|
+
setPeerSelector({});
|
|
103
102
|
setRoleSelector('');
|
|
104
103
|
}}
|
|
105
104
|
/>
|
|
@@ -108,7 +107,7 @@ const Everyone = React.memo(({ active }: { active: boolean }) => {
|
|
|
108
107
|
|
|
109
108
|
const RoleItem = React.memo(({ role, active }: { role: string; active: boolean }) => {
|
|
110
109
|
const unreadCount: number = useHMSStore(selectMessagesUnreadCountByRole(role));
|
|
111
|
-
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.
|
|
110
|
+
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER);
|
|
112
111
|
const [, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
|
113
112
|
return (
|
|
114
113
|
<SelectorItem
|
|
@@ -116,7 +115,7 @@ const RoleItem = React.memo(({ role, active }: { role: string; active: boolean }
|
|
|
116
115
|
active={active}
|
|
117
116
|
unreadCount={unreadCount}
|
|
118
117
|
onClick={() => {
|
|
119
|
-
setPeerSelector(
|
|
118
|
+
setPeerSelector({});
|
|
120
119
|
setRoleSelector(role);
|
|
121
120
|
}}
|
|
122
121
|
/>
|
|
@@ -125,7 +124,7 @@ const RoleItem = React.memo(({ role, active }: { role: string; active: boolean }
|
|
|
125
124
|
|
|
126
125
|
const PeerItem = ({ peerId, name, active }: { name: string; peerId: string; active: boolean }) => {
|
|
127
126
|
const unreadCount: number = useHMSStore(selectMessagesUnreadCountByPeerID(peerId));
|
|
128
|
-
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.
|
|
127
|
+
const [, setPeerSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.PEER);
|
|
129
128
|
const [, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
|
|
130
129
|
|
|
131
130
|
return (
|
|
@@ -134,7 +133,7 @@ const PeerItem = ({ peerId, name, active }: { name: string; peerId: string; acti
|
|
|
134
133
|
active={active}
|
|
135
134
|
unreadCount={unreadCount}
|
|
136
135
|
onClick={() => {
|
|
137
|
-
setPeerSelector(peerId);
|
|
136
|
+
setPeerSelector({ id: peerId, name });
|
|
138
137
|
setRoleSelector('');
|
|
139
138
|
}}
|
|
140
139
|
/>
|
|
@@ -146,14 +145,15 @@ const VirtualizedSelectItemList = ({
|
|
|
146
145
|
selectedRole,
|
|
147
146
|
selectedPeerId,
|
|
148
147
|
searchValue,
|
|
148
|
+
isPublicChatEnabled,
|
|
149
149
|
}: {
|
|
150
150
|
peers: HMSPeer[];
|
|
151
151
|
selectedRole: string;
|
|
152
152
|
selectedPeerId: string;
|
|
153
153
|
searchValue: string;
|
|
154
|
+
isPublicChatEnabled: boolean;
|
|
154
155
|
}) => {
|
|
155
156
|
const roles = useFilteredRoles();
|
|
156
|
-
const isMobile = useMedia(cssConfig.media.md);
|
|
157
157
|
const filteredPeers = useMemo(
|
|
158
158
|
() =>
|
|
159
159
|
peers.filter(
|
|
@@ -164,15 +164,22 @@ const VirtualizedSelectItemList = ({
|
|
|
164
164
|
);
|
|
165
165
|
|
|
166
166
|
const listItems = useMemo(() => {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
167
|
+
let selectItems: React.ReactNode[] = [];
|
|
168
|
+
if (isPublicChatEnabled && !searchValue) {
|
|
169
|
+
selectItems = [<Everyone active={!selectedRole && !selectedPeerId} />];
|
|
170
|
+
}
|
|
171
|
+
if (roles.length > 0 && !searchValue) {
|
|
172
|
+
selectItems.push(<SelectorHeader isHorizontalDivider={isPublicChatEnabled}>Roles</SelectorHeader>);
|
|
171
173
|
roles.forEach(userRole =>
|
|
172
174
|
selectItems.push(<RoleItem key={userRole} active={selectedRole === userRole} role={userRole} />),
|
|
173
175
|
);
|
|
176
|
+
}
|
|
174
177
|
|
|
175
|
-
filteredPeers.length > 0
|
|
178
|
+
if (filteredPeers.length > 0) {
|
|
179
|
+
selectItems.push(
|
|
180
|
+
<SelectorHeader isHorizontalDivider={isPublicChatEnabled || roles.length > 0}>Participants</SelectorHeader>,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
176
183
|
filteredPeers.forEach(peer =>
|
|
177
184
|
selectItems.push(
|
|
178
185
|
<PeerItem key={peer.id} name={peer.name} peerId={peer.id} active={peer.id === selectedPeerId} />,
|
|
@@ -180,23 +187,14 @@ const VirtualizedSelectItemList = ({
|
|
|
180
187
|
);
|
|
181
188
|
|
|
182
189
|
return selectItems;
|
|
183
|
-
}, [searchValue, selectedRole, selectedPeerId, roles, filteredPeers]);
|
|
190
|
+
}, [isPublicChatEnabled, searchValue, selectedRole, selectedPeerId, roles, filteredPeers]);
|
|
184
191
|
|
|
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
192
|
return (
|
|
195
|
-
|
|
193
|
+
<Dropdown.Group css={{ overflowY: 'auto', maxHeight: '$64', bg: '$surface_default' }}>
|
|
196
194
|
{listItems.map((item, index) => (
|
|
197
195
|
<Box key={index}>{item}</Box>
|
|
198
196
|
))}
|
|
199
|
-
|
|
197
|
+
</Dropdown.Group>
|
|
200
198
|
);
|
|
201
199
|
};
|
|
202
200
|
|
|
@@ -206,6 +204,7 @@ export const ChatSelector = ({ role, peerId }: { role: string; peerId: string })
|
|
|
206
204
|
const [search, setSearch] = useState('');
|
|
207
205
|
|
|
208
206
|
const isPrivateChatEnabled = !!elements?.chat?.private_chat_enabled;
|
|
207
|
+
const isPublicChatEnabled = !!elements?.chat?.public_chat_enabled;
|
|
209
208
|
|
|
210
209
|
return (
|
|
211
210
|
<>
|
|
@@ -218,6 +217,7 @@ export const ChatSelector = ({ role, peerId }: { role: string; peerId: string })
|
|
|
218
217
|
selectedRole={role}
|
|
219
218
|
selectedPeerId={peerId}
|
|
220
219
|
peers={isPrivateChatEnabled ? peers : []}
|
|
220
|
+
isPublicChatEnabled={isPublicChatEnabled}
|
|
221
221
|
searchValue={search}
|
|
222
222
|
/>
|
|
223
223
|
</>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { useMedia } from 'react-use';
|
|
3
|
-
import {
|
|
4
|
-
import { ChevronDownIcon, ChevronUpIcon, CrossIcon, PeopleIcon, PersonIcon } from '@100mslive/react-icons';
|
|
3
|
+
import { ChevronDownIcon, ChevronUpIcon, CrossIcon, GroupIcon, PersonIcon } from '@100mslive/react-icons';
|
|
5
4
|
import { Dropdown } from '../../../Dropdown';
|
|
6
5
|
import { Box, Flex } from '../../../Layout';
|
|
7
6
|
import { Sheet } from '../../../Sheet';
|
|
@@ -11,7 +10,7 @@ import { ChatSelector } from './ChatSelector';
|
|
|
11
10
|
import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
|
|
12
11
|
// @ts-ignore
|
|
13
12
|
import { useSubscribeChatSelector } from '../AppData/useUISettings';
|
|
14
|
-
import { useFilteredRoles } from '../../common/hooks';
|
|
13
|
+
import { useDefaultChatSelection, useFilteredRoles } from '../../common/hooks';
|
|
15
14
|
import { CHAT_SELECTOR } from '../../common/constants';
|
|
16
15
|
|
|
17
16
|
export const ChatSelectorContainer = () => {
|
|
@@ -21,10 +20,10 @@ export const ChatSelectorContainer = () => {
|
|
|
21
20
|
const isPrivateChatEnabled = !!elements?.chat?.private_chat_enabled;
|
|
22
21
|
const isPublicChatEnabled = !!elements?.chat?.public_chat_enabled;
|
|
23
22
|
const roles = useFilteredRoles();
|
|
24
|
-
const selectedPeer = useSubscribeChatSelector(CHAT_SELECTOR.
|
|
23
|
+
const selectedPeer = useSubscribeChatSelector(CHAT_SELECTOR.PEER);
|
|
25
24
|
const selectedRole = useSubscribeChatSelector(CHAT_SELECTOR.ROLE);
|
|
26
|
-
const
|
|
27
|
-
const selection =
|
|
25
|
+
const defaultSelection = useDefaultChatSelection();
|
|
26
|
+
const selection = selectedPeer.name || selectedRole || defaultSelection;
|
|
28
27
|
|
|
29
28
|
if (!(isPrivateChatEnabled || isPublicChatEnabled || roles.length > 0) && !isPrivateChatEnabled && !selection) {
|
|
30
29
|
return null;
|
|
@@ -47,18 +46,18 @@ export const ChatSelectorContainer = () => {
|
|
|
47
46
|
}}
|
|
48
47
|
>
|
|
49
48
|
<Text
|
|
50
|
-
variant="
|
|
49
|
+
variant="caption"
|
|
51
50
|
css={{
|
|
52
51
|
c: '$on_surface_high',
|
|
53
52
|
pr: '$2',
|
|
54
53
|
display: 'flex',
|
|
55
54
|
alignItems: 'center',
|
|
56
55
|
gap: '$1',
|
|
57
|
-
textTransform: 'capitalize',
|
|
56
|
+
textTransform: selection !== selectedPeer.name ? 'capitalize' : undefined,
|
|
58
57
|
}}
|
|
59
58
|
>
|
|
60
59
|
{selection === CHAT_SELECTOR.EVERYONE ? (
|
|
61
|
-
<
|
|
60
|
+
<GroupIcon width={16} height={16} />
|
|
62
61
|
) : (
|
|
63
62
|
<PersonIcon width={16} height={16} />
|
|
64
63
|
)}
|
|
@@ -73,7 +72,7 @@ export const ChatSelectorContainer = () => {
|
|
|
73
72
|
asChild
|
|
74
73
|
data-testid="participant_list_filter"
|
|
75
74
|
css={{
|
|
76
|
-
|
|
75
|
+
background: '$primary_default',
|
|
77
76
|
r: '$0',
|
|
78
77
|
p: '$1 $2',
|
|
79
78
|
ml: '$6',
|
|
@@ -82,22 +81,22 @@ export const ChatSelectorContainer = () => {
|
|
|
82
81
|
>
|
|
83
82
|
<Flex align="center" css={{ c: '$on_surface_medium' }} gap="1">
|
|
84
83
|
<Text
|
|
85
|
-
variant="
|
|
84
|
+
variant="caption"
|
|
86
85
|
css={{
|
|
87
86
|
c: '$on_surface_high',
|
|
88
87
|
pr: '$2',
|
|
89
88
|
display: 'flex',
|
|
90
89
|
alignItems: 'center',
|
|
91
90
|
gap: '$1',
|
|
92
|
-
textTransform: 'capitalize',
|
|
91
|
+
textTransform: selection !== selectedPeer.name ? 'capitalize' : undefined,
|
|
93
92
|
}}
|
|
94
93
|
>
|
|
95
94
|
{selection === CHAT_SELECTOR.EVERYONE ? (
|
|
96
|
-
<
|
|
95
|
+
<GroupIcon width={16} height={16} />
|
|
97
96
|
) : (
|
|
98
97
|
<PersonIcon width={16} height={16} />
|
|
99
98
|
)}
|
|
100
|
-
{selection}
|
|
99
|
+
{selection || 'Search'}
|
|
101
100
|
</Text>
|
|
102
101
|
{selection && (
|
|
103
102
|
<ChevronDownIcon
|
|
@@ -119,7 +118,7 @@ export const ChatSelectorContainer = () => {
|
|
|
119
118
|
align="start"
|
|
120
119
|
sideOffset={8}
|
|
121
120
|
>
|
|
122
|
-
<ChatSelector role={selectedRole} peerId={selectedPeer} />
|
|
121
|
+
<ChatSelector role={selectedRole} peerId={selectedPeer.id} />
|
|
123
122
|
</Dropdown.Content>
|
|
124
123
|
</Dropdown.Root>
|
|
125
124
|
)}
|
|
@@ -148,7 +147,7 @@ export const ChatSelectorContainer = () => {
|
|
|
148
147
|
setOpen(false);
|
|
149
148
|
}}
|
|
150
149
|
>
|
|
151
|
-
<ChatSelector role={selectedRole} peerId={selectedPeer} />
|
|
150
|
+
<ChatSelector role={selectedRole} peerId={selectedPeer.id} />
|
|
152
151
|
</Box>
|
|
153
152
|
</Sheet.Content>
|
|
154
153
|
</Sheet.Root>
|