@100mslive/roomkit-react 0.1.18-alpha.1 → 0.1.19-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.
Files changed (44) hide show
  1. package/dist/{HLSView-MR7RYQZB.js → HLSView-GG4WVUQY.js} +2 -2
  2. package/dist/Prebuilt/common/constants.d.ts +2 -6
  3. package/dist/Prebuilt/components/Chat/Chat.d.ts +2 -0
  4. package/dist/Prebuilt/components/Chat/ChatActions.d.ts +12 -0
  5. package/dist/Prebuilt/components/Chat/ChatBody.d.ts +8 -0
  6. package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +2 -2
  7. package/dist/Prebuilt/components/Chat/ChatStates.d.ts +1 -1
  8. package/dist/Prebuilt/components/Chat/MwebChatOption.d.ts +1 -1
  9. package/dist/Prebuilt/components/Chat/PinnedMessage.d.ts +1 -3
  10. package/dist/Prebuilt/components/hooks/useChatBlacklist.d.ts +4 -0
  11. package/dist/Prebuilt/components/hooks/useSetPinnedMessages.d.ts +3 -10
  12. package/dist/Prebuilt/components/hooks/useUnreadPollQuizPresent.d.ts +5 -0
  13. package/dist/{chunk-WFHOR7AP.js → chunk-GXJIUWTP.js} +10083 -4574
  14. package/dist/chunk-GXJIUWTP.js.map +7 -0
  15. package/dist/index.cjs.js +12716 -7192
  16. package/dist/index.cjs.js.map +4 -4
  17. package/dist/index.js +1 -1
  18. package/dist/meta.cjs.json +367 -240
  19. package/dist/meta.esbuild.json +377 -250
  20. package/package.json +6 -6
  21. package/src/Prebuilt/common/constants.ts +4 -4
  22. package/src/Prebuilt/components/Chat/Chat.tsx +108 -0
  23. package/src/Prebuilt/components/Chat/ChatActions.tsx +297 -0
  24. package/src/Prebuilt/components/Chat/ChatBody.tsx +444 -0
  25. package/src/Prebuilt/components/Chat/ChatFooter.tsx +9 -3
  26. package/src/Prebuilt/components/Chat/ChatStates.tsx +5 -0
  27. package/src/Prebuilt/components/Chat/MwebChatOption.tsx +1 -1
  28. package/src/Prebuilt/components/Chat/PinnedMessage.tsx +4 -2
  29. package/src/Prebuilt/components/Footer/PollsToggle.tsx +12 -3
  30. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +5 -1
  31. package/src/Prebuilt/components/Polls/CreateQuestions/QuestionForm.jsx +3 -3
  32. package/src/Prebuilt/components/Polls/Voting/Leaderboard.tsx +9 -1
  33. package/src/Prebuilt/components/Polls/Voting/LeaderboardEntry.tsx +6 -6
  34. package/src/Prebuilt/components/Polls/Voting/QuestionCard.jsx +20 -23
  35. package/src/Prebuilt/components/Polls/common/MultipleChoiceOptions.jsx +1 -1
  36. package/src/Prebuilt/components/SidePaneTabs.tsx +33 -11
  37. package/src/Prebuilt/components/hooks/useChatBlacklist.ts +7 -1
  38. package/src/Prebuilt/components/hooks/useSetPinnedMessages.ts +19 -11
  39. package/src/Prebuilt/components/hooks/useUnreadPollQuizPresent.tsx +20 -0
  40. package/src/Prebuilt/provider/roomLayoutProvider/index.tsx +11 -2
  41. package/dist/chunk-WFHOR7AP.js.map +0 -7
  42. package/src/Prebuilt/components/Chat/Chat.jsx +0 -124
  43. package/src/Prebuilt/components/Chat/ChatBody.jsx +0 -726
  44. /package/dist/{HLSView-MR7RYQZB.js.map → HLSView-GG4WVUQY.js.map} +0 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.1.18-alpha.1",
13
+ "version": "0.1.19-alpha.0",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "files": [
@@ -76,10 +76,10 @@
76
76
  "react": ">=17.0.2 <19.0.0"
77
77
  },
78
78
  "dependencies": {
79
- "@100mslive/hls-player": "0.1.27-alpha.1",
80
- "@100mslive/hms-virtual-background": "1.11.27-alpha.1",
81
- "@100mslive/react-icons": "0.8.27-alpha.1",
82
- "@100mslive/react-sdk": "0.8.27-alpha.1",
79
+ "@100mslive/hls-player": "0.1.28-alpha.0",
80
+ "@100mslive/hms-virtual-background": "1.11.28-alpha.0",
81
+ "@100mslive/react-icons": "0.8.28-alpha.0",
82
+ "@100mslive/react-sdk": "0.8.28-alpha.0",
83
83
  "@100mslive/types-prebuilt": "0.12.5",
84
84
  "@emoji-mart/data": "^1.0.6",
85
85
  "@emoji-mart/react": "^1.0.1",
@@ -115,5 +115,5 @@
115
115
  "uuid": "^8.3.2",
116
116
  "worker-timers": "^7.0.40"
117
117
  },
118
- "gitHead": "ce20a10ac4c2cea6ac8a7cc4ffc0226c45aa8975"
118
+ "gitHead": "92b555102a4b5f0cc1f2913738c56a8e8cdf4b2b"
119
119
  }
@@ -121,15 +121,15 @@ export enum INTERACTION_TYPE {
121
121
  export enum QUESTION_TYPE_TITLE {
122
122
  'single-choice' = 'Single Choice',
123
123
  'multiple-choice' = 'Multiple Choice',
124
- 'short-answer' = 'Short Answer',
125
- 'long-answer' = 'Long Answer',
124
+ // 'short-answer' = 'Short Answer',
125
+ // 'long-answer' = 'Long Answer',
126
126
  }
127
127
 
128
128
  export enum QUESTION_TYPE {
129
129
  SINGLE_CHOICE = 'single-choice',
130
130
  MULTIPLE_CHOICE = 'multiple-choice',
131
- SHORT_ANSWER = 'short-answer',
132
- LONG_ANSWER = 'long-answer',
131
+ // SHORT_ANSWER = 'short-answer',
132
+ // LONG_ANSWER = 'long-answer',
133
133
  }
134
134
 
135
135
  export const ROLE_CHANGE_DECLINED = 'role_change_declined';
@@ -0,0 +1,108 @@
1
+ import React, { MutableRefObject, useCallback, useRef } from 'react';
2
+ import { useMedia } from 'react-use';
3
+ import { VariableSizeList } from 'react-window';
4
+ import { selectSessionStore, selectUnreadHMSMessagesCount } from '@100mslive/hms-video-store';
5
+ import { selectHMSMessagesCount, useHMSActions, useHMSStore, useHMSVanillaStore } from '@100mslive/react-sdk';
6
+ import { ChevronDownIcon } from '@100mslive/react-icons';
7
+ import { Button } from '../../../Button';
8
+ import { Flex } from '../../../Layout';
9
+ import { config as cssConfig } from '../../../Theme';
10
+ import { ChatBody } from './ChatBody';
11
+ import { ChatFooter } from './ChatFooter';
12
+ import { ChatBlocked, ChatPaused } from './ChatStates';
13
+ import { PinnedMessage } from './PinnedMessage';
14
+ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
15
+ import { SESSION_STORE_KEY } from '../../common/constants';
16
+
17
+ export const Chat = () => {
18
+ const { elements } = useRoomLayoutConferencingScreen();
19
+ const listRef = useRef<VariableSizeList | null>(null);
20
+ const hmsActions = useHMSActions();
21
+ const vanillaStore = useHMSVanillaStore();
22
+ const { enabled: isChatEnabled = true } = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_STATE)) || {};
23
+ const isMobile = useMedia(cssConfig.media.md);
24
+ const scrollToBottom = useCallback(
25
+ (unreadCount = 0) => {
26
+ if (listRef.current && listRef.current.scrollToItem && unreadCount > 0) {
27
+ const messagesCount = vanillaStore.getState(selectHMSMessagesCount);
28
+ listRef.current?.scrollToItem(messagesCount, 'end');
29
+ requestAnimationFrame(() => {
30
+ listRef.current?.scrollToItem(messagesCount, 'end');
31
+ });
32
+ hmsActions.setMessageRead(true);
33
+ }
34
+ },
35
+ [hmsActions, vanillaStore],
36
+ );
37
+
38
+ return (
39
+ <Flex
40
+ direction="column"
41
+ css={{
42
+ size: '100%',
43
+ gap: '$4',
44
+ }}
45
+ >
46
+ {isMobile && elements?.chat?.is_overlay ? null : <PinnedMessage />}
47
+ <ChatBody ref={listRef} scrollToBottom={scrollToBottom} />
48
+ <ChatPaused />
49
+ <ChatBlocked />
50
+ {isMobile && elements?.chat?.is_overlay ? <PinnedMessage /> : null}
51
+ {isChatEnabled ? (
52
+ <ChatFooter onSend={scrollToBottom}>
53
+ <NewMessageIndicator scrollToBottom={scrollToBottom} listRef={listRef} />
54
+ </ChatFooter>
55
+ ) : null}
56
+ </Flex>
57
+ );
58
+ };
59
+
60
+ const NewMessageIndicator = ({
61
+ scrollToBottom,
62
+ listRef,
63
+ }: {
64
+ scrollToBottom: (count: number) => void;
65
+ listRef: MutableRefObject<VariableSizeList | null>;
66
+ }) => {
67
+ const unreadCount = useHMSStore(selectUnreadHMSMessagesCount);
68
+ if (!unreadCount || !listRef.current) {
69
+ return null;
70
+ }
71
+ // @ts-ignore
72
+ const outerElement = listRef.current._outerRef;
73
+ // @ts-ignore
74
+ if (outerElement.scrollHeight === listRef.current.state.scrollOffset + outerElement.offsetHeight) {
75
+ return null;
76
+ }
77
+ return (
78
+ <Flex
79
+ justify="center"
80
+ css={{
81
+ width: '100%',
82
+ left: 0,
83
+ bottom: '$28',
84
+ position: 'absolute',
85
+ }}
86
+ >
87
+ <Button
88
+ variant="standard"
89
+ onClick={() => {
90
+ scrollToBottom(unreadCount);
91
+ }}
92
+ icon
93
+ css={{
94
+ p: '$3 $4',
95
+ pl: '$6',
96
+ '& > svg': { ml: '$4' },
97
+ borderRadius: '$round',
98
+ fontSize: '$xs',
99
+ fontWeight: '$semiBold',
100
+ c: '$on_secondary_high',
101
+ }}
102
+ >
103
+ New {unreadCount === 1 ? 'message' : 'messages'}
104
+ <ChevronDownIcon height={16} width={16} />
105
+ </Button>
106
+ </Flex>
107
+ );
108
+ };
@@ -0,0 +1,297 @@
1
+ import React, { useCallback, useState } from 'react';
2
+ import { HMSMessage, selectLocalPeerName, selectPermissions, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
3
+ import {
4
+ CopyIcon,
5
+ CrossCircleIcon,
6
+ CrossIcon,
7
+ EyeCloseIcon,
8
+ PeopleRemoveIcon,
9
+ PinIcon,
10
+ ReplyIcon,
11
+ VerticalMenuIcon,
12
+ } from '@100mslive/react-icons';
13
+ import { Dropdown } from '../../../Dropdown';
14
+ import { IconButton } from '../../../IconButton';
15
+ import { Flex } from '../../../Layout';
16
+ import { Sheet } from '../../../Sheet';
17
+ import { Text } from '../../../Text';
18
+ import { Tooltip } from '../../../Tooltip';
19
+ // @ts-ignore
20
+ import { ToastManager } from '../Toast/ToastManager';
21
+ import { MwebChatOption } from './MwebChatOption';
22
+ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
23
+ import { useChatBlacklist, useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
24
+ import { useSetPinnedMessages } from '../hooks/useSetPinnedMessages';
25
+ import { SESSION_STORE_KEY } from '../../common/constants';
26
+
27
+ const iconStyle = { height: '1.125rem', width: '1.125rem' };
28
+ const tooltipBoxCSS = {
29
+ fontSize: '$xs',
30
+ backgroundColor: '$surface_default',
31
+ p: '$1 $5',
32
+ fontWeight: '$regular',
33
+ borderRadius: '$3',
34
+ };
35
+
36
+ export const ChatActions = ({
37
+ showPinAction,
38
+ onReply,
39
+ showReply,
40
+ message,
41
+ sentByLocalPeer,
42
+ isMobile,
43
+ openSheet,
44
+ setOpenSheet,
45
+ }: {
46
+ showPinAction: boolean;
47
+ onReply: () => void;
48
+ showReply: boolean;
49
+ message: HMSMessage;
50
+ sentByLocalPeer: boolean;
51
+ isMobile: boolean;
52
+ openSheet: boolean;
53
+ setOpenSheet: (value: boolean) => void;
54
+ }) => {
55
+ const { elements } = useRoomLayoutConferencingScreen();
56
+ const { can_hide_message, can_block_user } = elements?.chat?.real_time_controls || {
57
+ can_hide_message: false,
58
+ can_block_user: false,
59
+ };
60
+ const [open, setOpen] = useState(false);
61
+ const actions = useHMSActions();
62
+ const canRemoveOthers = useHMSStore(selectPermissions)?.removeOthers;
63
+ const { blacklistItem: blacklistPeer } = useChatBlacklist(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST);
64
+ const localPeerName = useHMSStore(selectLocalPeerName);
65
+ const { setPinnedMessages, unpinBlacklistedMessages } = useSetPinnedMessages();
66
+
67
+ const { blacklistItem: blacklistMessage, blacklistedIDs: blacklistedMessageIDs } = useChatBlacklist(
68
+ SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST,
69
+ );
70
+
71
+ const isSenderBlocked = useIsPeerBlacklisted({ peerCustomerUserId: message.senderUserId });
72
+
73
+ const updatePinnedMessages = useCallback(
74
+ (messageID = '') => {
75
+ const blacklistedMessageIDSet = new Set([...(blacklistedMessageIDs || []), messageID]);
76
+ unpinBlacklistedMessages(blacklistedMessageIDSet);
77
+ },
78
+ [blacklistedMessageIDs, unpinBlacklistedMessages],
79
+ );
80
+
81
+ const copyMessageContent = useCallback(() => {
82
+ try {
83
+ navigator?.clipboard.writeText(message.message);
84
+ ToastManager.addToast({
85
+ title: 'Message copied successfully',
86
+ });
87
+ } catch (e) {
88
+ console.log(e);
89
+ ToastManager.addToast({
90
+ title: 'Could not copy message',
91
+ });
92
+ }
93
+ }, [message]);
94
+
95
+ const options: Record<
96
+ string,
97
+ {
98
+ text: string;
99
+ tooltipText?: string;
100
+ icon: React.ReactNode;
101
+ onClick: () => void | Promise<void>;
102
+ show: boolean;
103
+ color?: string;
104
+ }
105
+ > = {
106
+ reply: {
107
+ text: message.recipientRoles?.length ? 'Reply to Group' : 'Reply Privately',
108
+ tooltipText: message.recipientRoles?.length ? 'Reply to Group' : 'Reply Privately',
109
+ icon: <ReplyIcon style={iconStyle} />,
110
+ onClick: onReply,
111
+ show: showReply,
112
+ },
113
+ pin: {
114
+ text: 'Pin message',
115
+ tooltipText: 'Pin',
116
+ icon: <PinIcon style={iconStyle} />,
117
+ onClick: () => setPinnedMessages(message, localPeerName || ''),
118
+ show: showPinAction,
119
+ },
120
+ copy: {
121
+ text: 'Copy text',
122
+ tooltipText: 'Copy',
123
+ icon: <CopyIcon style={iconStyle} />,
124
+ onClick: copyMessageContent,
125
+ show: true,
126
+ },
127
+ hide: {
128
+ text: message.recipientPeer ? 'Hide for both' : 'Hide for everyone',
129
+ icon: <EyeCloseIcon style={iconStyle} />,
130
+ onClick: async () => {
131
+ blacklistMessage(message.id);
132
+ updatePinnedMessages(message.id);
133
+ },
134
+ show: !!can_hide_message,
135
+ },
136
+ block: {
137
+ text: 'Block from chat',
138
+ icon: <CrossCircleIcon style={iconStyle} />,
139
+ onClick: async () => {
140
+ if (message.senderUserId) {
141
+ blacklistPeer(message.senderUserId);
142
+ }
143
+ },
144
+ color: '$alert_error_default',
145
+ show: !!can_block_user && !sentByLocalPeer && !isSenderBlocked,
146
+ },
147
+ remove: {
148
+ text: 'Remove Partipant',
149
+ icon: <PeopleRemoveIcon style={iconStyle} />,
150
+ color: '$alert_error_default',
151
+ show: !!canRemoveOthers && !sentByLocalPeer,
152
+ onClick: async () => {
153
+ if (!message.sender) {
154
+ return;
155
+ }
156
+ try {
157
+ await actions.removePeer(message.sender, '');
158
+ } catch (error) {
159
+ ToastManager.addToast({ title: (error as Error).message, variant: 'error' });
160
+ }
161
+ },
162
+ },
163
+ };
164
+
165
+ if (isMobile) {
166
+ return (
167
+ <Sheet.Root open={openSheet} onOpenChange={setOpenSheet}>
168
+ <Sheet.Content css={{ bg: '$surface_default', pb: '$14' }} onClick={() => setOpenSheet(false)}>
169
+ <Sheet.Title
170
+ css={{
171
+ display: 'flex',
172
+ color: '$on_surface_high',
173
+ w: '100%',
174
+ justifyContent: 'space-between',
175
+ mt: '$8',
176
+ fontSize: '$md',
177
+ px: '$10',
178
+ pb: '$8',
179
+ borderBottom: '1px solid $border_bright',
180
+ alignItems: 'center',
181
+ }}
182
+ >
183
+ Message options
184
+ <Sheet.Close css={{ color: '$on_surface_high' }} onClick={() => setOpenSheet(false)}>
185
+ <CrossIcon />
186
+ </Sheet.Close>
187
+ </Sheet.Title>
188
+
189
+ {Object.keys(options).map(optionKey => {
190
+ const option = options[optionKey];
191
+ return option.show ? (
192
+ <MwebChatOption
193
+ key={optionKey}
194
+ text={option.text}
195
+ icon={option.icon}
196
+ onClick={option.onClick}
197
+ color={option?.color}
198
+ />
199
+ ) : null;
200
+ })}
201
+ </Sheet.Content>
202
+ </Sheet.Root>
203
+ );
204
+ }
205
+
206
+ return (
207
+ <Dropdown.Root open={open} onOpenChange={setOpen} css={{ '@md': { display: 'none' } }}>
208
+ <Flex
209
+ className="chat_actions"
210
+ css={{
211
+ background: '$surface_bright',
212
+ borderRadius: '$1',
213
+ p: '$2',
214
+ opacity: open ? 1 : 0,
215
+ position: 'absolute',
216
+ right: 0,
217
+ zIndex: 1,
218
+ '@md': { opacity: 1 },
219
+ }}
220
+ >
221
+ {options.reply.show ? (
222
+ <Tooltip boxCss={tooltipBoxCSS} title={options.reply.tooltipText}>
223
+ <IconButton data-testid="reply_message_btn" onClick={options.reply.onClick}>
224
+ {options.reply.icon}
225
+ </IconButton>
226
+ </Tooltip>
227
+ ) : null}
228
+ {options.pin.show ? (
229
+ <Tooltip boxCss={tooltipBoxCSS} title={options.pin.tooltipText}>
230
+ <IconButton data-testid="pin_message_btn" onClick={options.pin.onClick}>
231
+ {options.pin.icon}
232
+ </IconButton>
233
+ </Tooltip>
234
+ ) : null}
235
+
236
+ {options.copy.show ? (
237
+ <Tooltip boxCss={tooltipBoxCSS} title={options.copy.tooltipText}>
238
+ <IconButton onClick={options.copy.onClick} data-testid="copy_message_btn">
239
+ <CopyIcon style={iconStyle} />
240
+ </IconButton>
241
+ </Tooltip>
242
+ ) : null}
243
+
244
+ {options.block.show || options.hide.show || options.remove.show ? (
245
+ <Tooltip boxCss={tooltipBoxCSS} title="More actions">
246
+ <Dropdown.Trigger asChild>
247
+ <IconButton>
248
+ <VerticalMenuIcon style={iconStyle} />
249
+ </IconButton>
250
+ </Dropdown.Trigger>
251
+ </Tooltip>
252
+ ) : null}
253
+ </Flex>
254
+ <Dropdown.Portal>
255
+ <Dropdown.Content
256
+ sideOffset={5}
257
+ align="end"
258
+ css={{ width: '$48', backgroundColor: '$surface_bright', py: '$0', border: '1px solid $border_bright' }}
259
+ >
260
+ {options.hide.show ? (
261
+ <Dropdown.Item data-testid="hide_message_btn" onClick={options.hide.onClick}>
262
+ {options.hide.icon}
263
+ <Text variant="sm" css={{ ml: '$4', fontWeight: '$semiBold' }}>
264
+ {options.hide.text}
265
+ </Text>
266
+ </Dropdown.Item>
267
+ ) : null}
268
+
269
+ {options.block.show ? (
270
+ <Dropdown.Item
271
+ data-testid="block_peer_btn"
272
+ onClick={options.block.onClick}
273
+ css={{ color: options.block.color }}
274
+ >
275
+ {options.block.icon}
276
+ <Text variant="sm" css={{ ml: '$4', color: 'inherit', fontWeight: '$semiBold' }}>
277
+ {options.block.text}
278
+ </Text>
279
+ </Dropdown.Item>
280
+ ) : null}
281
+ {options.remove.show ? (
282
+ <Dropdown.Item
283
+ data-testid="remove_peer_btn"
284
+ onClick={options.remove.onClick}
285
+ css={{ color: options.remove.color }}
286
+ >
287
+ {options.remove.icon}
288
+ <Text variant="sm" css={{ ml: '$4', color: 'inherit', fontWeight: '$semiBold' }}>
289
+ {options.remove.text}
290
+ </Text>
291
+ </Dropdown.Item>
292
+ ) : null}
293
+ </Dropdown.Content>
294
+ </Dropdown.Portal>
295
+ </Dropdown.Root>
296
+ );
297
+ };