@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
@@ -2,22 +2,22 @@
2
2
  import React, { useCallback, useMemo, useState } from 'react';
3
3
  import { selectLocalPeer, selectLocalPeerRoleName, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
4
4
  import { CheckCircleIcon, ChevronLeftIcon, ChevronRightIcon, CrossCircleIcon } from '@100mslive/react-icons';
5
- import { Box, Button, Flex, IconButton, Input, styled, Text } from '../../../../';
5
+ import { Box, Button, Flex, IconButton, Text } from '../../../../';
6
6
  import { checkCorrectAnswer } from '../../../common/utils';
7
7
  import { MultipleChoiceOptions } from '../common/MultipleChoiceOptions';
8
8
  import { SingleChoiceOptions } from '../common/SingleChoiceOptions';
9
9
  import { QUESTION_TYPE } from '../../../common/constants';
10
10
 
11
- const TextArea = styled('textarea', {
12
- backgroundColor: '$surface_brighter',
13
- border: '1px solid $border_bright',
14
- borderRadius: '$1',
15
- mb: '$md',
16
- color: '$on_surface_high',
17
- resize: 'none',
18
- p: '$2',
19
- w: '100%',
20
- });
11
+ // const TextArea = styled('textarea', {
12
+ // backgroundColor: '$surface_brighter',
13
+ // border: '1px solid $border_bright',
14
+ // borderRadius: '$1',
15
+ // mb: '$md',
16
+ // color: '$on_surface_high',
17
+ // resize: 'none',
18
+ // p: '$2',
19
+ // w: '100%',
20
+ // });
21
21
 
22
22
  export const QuestionCard = ({
23
23
  pollID,
@@ -67,23 +67,21 @@ export const QuestionCard = ({
67
67
  setCurrentIndex(curr => Math.max(1, curr - 1));
68
68
  };
69
69
 
70
- const [textAnswer, setTextAnswer] = useState('');
70
+ // const [textAnswer, setTextAnswer] = useState('');
71
71
  const [singleOptionAnswer, setSingleOptionAnswer] = useState();
72
72
  const [multipleOptionAnswer, setMultipleOptionAnswer] = useState(new Set());
73
73
 
74
- const stringAnswerExpected = [QUESTION_TYPE.LONG_ANSWER, QUESTION_TYPE.SHORT_ANSWER].includes(type);
74
+ // const stringAnswerExpected = [QUESTION_TYPE.LONG_ANSWER, QUESTION_TYPE.SHORT_ANSWER].includes(type);
75
75
 
76
76
  const respondedToQuiz = isQuiz && localPeerResponse && !localPeerResponse.skipped;
77
77
 
78
78
  const isValidVote = useMemo(() => {
79
- if (stringAnswerExpected) {
80
- return textAnswer.length > 0;
81
- } else if (type === QUESTION_TYPE.SINGLE_CHOICE) {
79
+ if (type === QUESTION_TYPE.SINGLE_CHOICE) {
82
80
  return singleOptionAnswer !== undefined;
83
81
  } else if (type === QUESTION_TYPE.MULTIPLE_CHOICE) {
84
82
  return multipleOptionAnswer.size > 0;
85
83
  }
86
- }, [textAnswer, singleOptionAnswer, multipleOptionAnswer, type, stringAnswerExpected]);
84
+ }, [singleOptionAnswer, multipleOptionAnswer, type]);
87
85
 
88
86
  const handleVote = useCallback(async () => {
89
87
  if (!isValidVote) {
@@ -92,12 +90,11 @@ export const QuestionCard = ({
92
90
  await actions.interactivityCenter.addResponsesToPoll(pollID, [
93
91
  {
94
92
  questionIndex: index,
95
- text: textAnswer,
96
93
  option: singleOptionAnswer,
97
94
  options: Array.from(multipleOptionAnswer),
98
95
  },
99
96
  ]);
100
- }, [actions, index, pollID, isValidVote, textAnswer, singleOptionAnswer, multipleOptionAnswer]);
97
+ }, [actions, index, pollID, isValidVote, singleOptionAnswer, multipleOptionAnswer]);
101
98
 
102
99
  const handleSkip = useCallback(async () => {
103
100
  await actions.interactivityCenter.addResponsesToPoll(pollID, [
@@ -181,7 +178,7 @@ export const QuestionCard = ({
181
178
  <Text css={{ color: '$on_surface_high' }}>{text}</Text>
182
179
  </Box>
183
180
 
184
- {type === QUESTION_TYPE.SHORT_ANSWER ? (
181
+ {/* {type === QUESTION_TYPE.SHORT_ANSWER ? (
185
182
  <Input
186
183
  disabled={!canRespond}
187
184
  placeholder="Enter your answer"
@@ -194,15 +191,15 @@ export const QuestionCard = ({
194
191
  cursor: localPeerResponse ? 'not-allowed' : 'text',
195
192
  }}
196
193
  />
197
- ) : null}
194
+ ) : null} */}
198
195
 
199
- {type === QUESTION_TYPE.LONG_ANSWER ? (
196
+ {/* {type === QUESTION_TYPE.LONG_ANSWER ? (
200
197
  <TextArea
201
198
  disabled={!canRespond}
202
199
  placeholder="Enter your answer"
203
200
  onChange={e => setTextAnswer(e.target.value)}
204
201
  />
205
- ) : null}
202
+ ) : null} */}
206
203
 
207
204
  {type === QUESTION_TYPE.SINGLE_CHOICE ? (
208
205
  <SingleChoiceOptions
@@ -51,7 +51,7 @@ export const MultipleChoiceOptions = ({
51
51
  </Checkbox.Root>
52
52
  ) : null}
53
53
 
54
- {isStopped && correctOptionIndexes.includes(option.index) ? (
54
+ {isStopped && correctOptionIndexes?.includes(option.index) ? (
55
55
  <Flex css={{ color: '$on_surface_high' }}>
56
56
  <CheckCircleIcon />
57
57
  </Flex>
@@ -107,16 +107,37 @@ export const SidePaneTabs = React.memo<{
107
107
  <>
108
108
  {hideTabs ? (
109
109
  <>
110
- <Text variant="sm" css={{ fontWeight: '$semiBold', p: '$4', c: '$on_surface_high', pr: '$12' }}>
111
- {showChat ? (
112
- chat_title
113
- ) : (
114
- <span>
115
- Participants <ParticipantCount count={peerCount} />
116
- </span>
117
- )}
118
- </Text>
119
-
110
+ <Flex justify="between" css={{ w: '100%' }}>
111
+ <Text variant="sm" css={{ fontWeight: '$semiBold', p: '$4', c: '$on_surface_high', pr: '$12' }}>
112
+ {showChat ? (
113
+ chat_title
114
+ ) : (
115
+ <span>
116
+ Participants&nbsp;
117
+ <ParticipantCount count={peerCount} />
118
+ </span>
119
+ )}
120
+ </Text>
121
+ <Flex>
122
+ {showChatSettings ? <ChatSettings /> : null}
123
+ {isOverlayChat && isChatOpen ? null : (
124
+ <IconButton
125
+ css={{ my: '$1', color: '$on_surface_medium', '&:hover': { color: '$on_surface_high' } }}
126
+ onClick={e => {
127
+ e.stopPropagation();
128
+ if (activeTab === SIDE_PANE_OPTIONS.CHAT) {
129
+ toggleChat();
130
+ } else {
131
+ toggleParticipants();
132
+ }
133
+ }}
134
+ data-testid="close_chat"
135
+ >
136
+ <CrossIcon />
137
+ </IconButton>
138
+ )}
139
+ </Flex>
140
+ </Flex>
120
141
  {showChat ? <Chat /> : <ParticipantList offStageRoles={off_stage_roles} onActive={setActiveRole} />}
121
142
  </>
122
143
  ) : (
@@ -148,7 +169,8 @@ export const SidePaneTabs = React.memo<{
148
169
  color: activeTab !== SIDE_PANE_OPTIONS.PARTICIPANTS ? '$on_surface_low' : '$on_surface_high',
149
170
  }}
150
171
  >
151
- Participants &nbsp; <ParticipantCount count={peerCount} />
172
+ Participants&nbsp;
173
+ <ParticipantCount count={peerCount} />
152
174
  </Tabs.Trigger>
153
175
  </Tabs.List>
154
176
  {showChatSettings ? <ChatSettings /> : null}
@@ -1,5 +1,5 @@
1
1
  import { useCallback } from 'react';
2
- import { selectSessionStore, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
2
+ import { selectLocalPeer, selectSessionStore, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
3
3
  // @ts-ignore
4
4
  import { ToastManager } from '../Toast/ToastManager';
5
5
  import { SESSION_STORE_KEY } from '../../common/constants';
@@ -21,3 +21,9 @@ export const useChatBlacklist = (
21
21
 
22
22
  return { blacklistItem, blacklistedIDs };
23
23
  };
24
+
25
+ export const useIsPeerBlacklisted = ({ local = false, peerCustomerUserId = '' }) => {
26
+ const localPeer = useHMSStore(selectLocalPeer);
27
+ const blacklistedPeerIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST)) || [];
28
+ return blacklistedPeerIDs?.includes(local ? localPeer?.customerUserId : peerCustomerUserId);
29
+ };
@@ -1,5 +1,11 @@
1
1
  import { useCallback } from 'react';
2
- import { HMSMessage, selectPeerNameByID, useHMSActions, useHMSVanillaStore } from '@100mslive/react-sdk';
2
+ import {
3
+ HMSMessage,
4
+ selectPeerNameByID,
5
+ selectSessionStore,
6
+ useHMSActions,
7
+ useHMSVanillaStore,
8
+ } from '@100mslive/react-sdk';
3
9
  // @ts-ignore
4
10
  import { ToastManager } from '../Toast/ToastManager';
5
11
  // @ts-ignore
@@ -8,7 +14,6 @@ import { SESSION_STORE_KEY } from '../../common/constants';
8
14
  type PinnedMessage = {
9
15
  text: string;
10
16
  id: string;
11
- authorId: string;
12
17
  pinnedBy: string;
13
18
  };
14
19
 
@@ -20,9 +25,9 @@ export const useSetPinnedMessages = () => {
20
25
  const vanillaStore = useHMSVanillaStore();
21
26
 
22
27
  const setPinnedMessages = useCallback(
23
- async (pinnedMessages: PinnedMessage[] = [], message: HMSMessage, pinnedBy: string) => {
28
+ async (message: HMSMessage, pinnedBy: string) => {
24
29
  const peerName = vanillaStore.getState(selectPeerNameByID(message?.sender)) || message?.senderName;
25
- const newPinnedMessage = { text: '', id: message.id, pinnedBy, authorId: message?.senderUserId || '' };
30
+ const newPinnedMessage = { text: '', id: message.id, pinnedBy };
26
31
 
27
32
  if (message && peerName) {
28
33
  newPinnedMessage['text'] = `${peerName}: ${message.message}`;
@@ -30,7 +35,8 @@ export const useSetPinnedMessages = () => {
30
35
  newPinnedMessage['text'] = message.message;
31
36
  }
32
37
 
33
- if (newPinnedMessage && !pinnedMessages.find(pinnedMessage => pinnedMessage.id === newPinnedMessage.id)) {
38
+ const pinnedMessages = vanillaStore.getState(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGES)) || [];
39
+ if (!pinnedMessages?.find((pinnedMessage: PinnedMessage) => pinnedMessage.id === newPinnedMessage.id)) {
34
40
  await hmsActions.sessionStore
35
41
  .set(SESSION_STORE_KEY.PINNED_MESSAGES, [...pinnedMessages, newPinnedMessage].slice(-3)) // Limiting to maximum of 3 messages - FIFO
36
42
  .catch(err => ToastManager.addToast({ title: err.description }));
@@ -40,30 +46,32 @@ export const useSetPinnedMessages = () => {
40
46
  );
41
47
 
42
48
  const removePinnedMessage = useCallback(
43
- async (pinnedMessages: PinnedMessage[] = [], indexToRemove: number) => {
49
+ async (indexToRemove: number) => {
50
+ const pinnedMessages = vanillaStore.getState(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGES)) || [];
44
51
  if (pinnedMessages[indexToRemove]) {
45
52
  await hmsActions.sessionStore
46
53
  .set(
47
54
  SESSION_STORE_KEY.PINNED_MESSAGES,
48
- pinnedMessages.filter((_, index: number) => index !== indexToRemove),
55
+ pinnedMessages.filter((_: PinnedMessage, index: number) => index !== indexToRemove),
49
56
  )
50
57
  .catch(err => ToastManager.addToast({ title: err.description }));
51
58
  }
52
59
  },
53
- [hmsActions],
60
+ [hmsActions, vanillaStore],
54
61
  );
55
62
 
56
63
  const unpinBlacklistedMessages = useCallback(
57
- async (pinnedMessages: PinnedMessage[] = [], blacklistedMessageIDSet: Set<string>) => {
64
+ async (blacklistedMessageIDSet: Set<string>) => {
65
+ const pinnedMessages = vanillaStore.getState(selectSessionStore(SESSION_STORE_KEY.PINNED_MESSAGES)) || [];
58
66
  const filteredPinnedMessages = pinnedMessages?.filter(
59
- pinnedMessage => !blacklistedMessageIDSet?.has(pinnedMessage.id),
67
+ (pinnedMessage: PinnedMessage) => !blacklistedMessageIDSet?.has(pinnedMessage.id),
60
68
  );
61
69
 
62
70
  await hmsActions.sessionStore
63
71
  .set(SESSION_STORE_KEY.PINNED_MESSAGES, filteredPinnedMessages)
64
72
  .catch(err => ToastManager.addToast({ title: err.description }));
65
73
  },
66
- [hmsActions],
74
+ [hmsActions, vanillaStore],
67
75
  );
68
76
 
69
77
  return { setPinnedMessages, removePinnedMessage, unpinBlacklistedMessages };
@@ -0,0 +1,20 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { selectLocalPeerID } from '@100mslive/hms-video-store';
3
+ import { HMSNotificationTypes, useHMSNotifications, useHMSStore } from '@100mslive/react-sdk';
4
+
5
+ export const useUnreadPollQuizPresent = () => {
6
+ const localPeerID = useHMSStore(selectLocalPeerID);
7
+ const notification = useHMSNotifications();
8
+ const [unreadPollQuiz, setUnreadPollQuiz] = useState(false);
9
+
10
+ useEffect(() => {
11
+ if (!notification) {
12
+ return;
13
+ }
14
+ if (notification.type !== HMSNotificationTypes.POLL_STARTED) {
15
+ return;
16
+ }
17
+ setUnreadPollQuiz(notification.data.startedBy !== localPeerID);
18
+ }, [localPeerID, notification]);
19
+ return { unreadPollQuiz, setUnreadPollQuiz };
20
+ };
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { Layout } from '@100mslive/types-prebuilt';
3
- import merge from 'lodash.merge';
3
+ import { isArray, mergeWith } from 'lodash';
4
4
  // @ts-ignore: fix types
5
5
  import { useAuthToken } from '../../components/AppData/useUISettings';
6
6
  import { useFetchRoomLayout, useFetchRoomLayoutResponse } from './hooks/useFetchRoomLayout';
@@ -18,6 +18,14 @@ export const RoomLayoutContext = React.createContext<
18
18
  | undefined
19
19
  >(undefined);
20
20
 
21
+ function customizer(objValue: any, srcValue: any) {
22
+ if (isArray(objValue) && isArray(srcValue)) {
23
+ return srcValue;
24
+ }
25
+ // default mergeWith behaviour is followed
26
+ return undefined;
27
+ }
28
+
21
29
  export const RoomLayoutProvider: React.FC<React.PropsWithChildren<RoomLayoutProviderProps>> = ({
22
30
  children,
23
31
  roomLayoutEndpoint,
@@ -25,7 +33,8 @@ export const RoomLayoutProvider: React.FC<React.PropsWithChildren<RoomLayoutProv
25
33
  }) => {
26
34
  const authToken: string = useAuthToken();
27
35
  const { layout, updateRoomLayoutForRole } = useFetchRoomLayout({ authToken, endpoint: roomLayoutEndpoint });
28
- const mergedLayout = authToken && layout ? merge(layout, overrideLayout) : layout;
36
+ const mergedLayout = authToken && layout ? mergeWith(layout, overrideLayout, customizer) : layout;
37
+
29
38
  return (
30
39
  <RoomLayoutContext.Provider value={{ layout: mergedLayout, updateRoomLayoutForRole }}>
31
40
  {children}