@100mslive/roomkit-react 0.1.14 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- 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>
|