@100mslive/roomkit-react 0.1.18 → 0.1.19-alpha.1

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/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.1.18",
13
+ "version": "0.1.19-alpha.1",
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",
80
- "@100mslive/hms-virtual-background": "1.11.27",
81
- "@100mslive/react-icons": "0.8.27",
82
- "@100mslive/react-sdk": "0.8.27",
79
+ "@100mslive/hls-player": "0.1.28-alpha.1",
80
+ "@100mslive/hms-virtual-background": "1.11.28-alpha.1",
81
+ "@100mslive/react-icons": "0.8.28-alpha.1",
82
+ "@100mslive/react-sdk": "0.8.28-alpha.1",
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": "bebaa35da830548dc943d08a9d3cfe2f472e23b1"
118
+ "gitHead": "5f85c1840b3852eee50dbd94689eac2aa7a1f327"
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';
@@ -20,7 +20,7 @@ import { Tooltip } from '../../../Tooltip';
20
20
  import { ToastManager } from '../Toast/ToastManager';
21
21
  import { MwebChatOption } from './MwebChatOption';
22
22
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
23
- import { useChatBlacklist } from '../hooks/useChatBlacklist';
23
+ import { useChatBlacklist, useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
24
24
  import { useSetPinnedMessages } from '../hooks/useSetPinnedMessages';
25
25
  import { SESSION_STORE_KEY } from '../../common/constants';
26
26
 
@@ -68,6 +68,8 @@ export const ChatActions = ({
68
68
  SESSION_STORE_KEY.CHAT_MESSAGE_BLACKLIST,
69
69
  );
70
70
 
71
+ const isSenderBlocked = useIsPeerBlacklisted({ peerCustomerUserId: message.senderUserId });
72
+
71
73
  const updatePinnedMessages = useCallback(
72
74
  (messageID = '') => {
73
75
  const blacklistedMessageIDSet = new Set([...(blacklistedMessageIDs || []), messageID]);
@@ -140,7 +142,7 @@ export const ChatActions = ({
140
142
  }
141
143
  },
142
144
  color: '$alert_error_default',
143
- show: !!can_block_user && !sentByLocalPeer,
145
+ show: !!can_block_user && !sentByLocalPeer && !isSenderBlocked,
144
146
  },
145
147
  remove: {
146
148
  text: 'Remove Partipant',
@@ -14,7 +14,7 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
14
14
  import { useChatDraftMessage } from '../AppData/useChatState';
15
15
  // @ts-ignore
16
16
  import { useSetSubscribedChatSelector, useSubscribeChatSelector } from '../AppData/useUISettings';
17
- import { useIsLocalPeerBlacklisted } from '../hooks/useChatBlacklist';
17
+ import { useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
18
18
  // @ts-ignore
19
19
  import { useEmojiPickerStyles } from './useEmojiPickerStyles';
20
20
  import { useDefaultChatSelection } from '../../common/hooks';
@@ -86,7 +86,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
86
86
  const [selectedRole, setRoleSelector] = useSetSubscribedChatSelector(CHAT_SELECTOR.ROLE);
87
87
  const defaultSelection = useDefaultChatSelection();
88
88
  const selection = selectedPeer.name || selectedRole || defaultSelection;
89
- const isLocalPeerBlacklisted = useIsLocalPeerBlacklisted();
89
+ const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true });
90
90
 
91
91
  useEffect(() => {
92
92
  if (!selectedPeer.id && !selectedRole && !['Everyone', ''].includes(defaultSelection)) {
@@ -4,7 +4,7 @@ import { Button } from '../../../Button';
4
4
  import { Box, Flex } from '../../../Layout';
5
5
  import { Text } from '../../../Text';
6
6
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
7
- import { useIsLocalPeerBlacklisted } from '../hooks/useChatBlacklist';
7
+ import { useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
8
8
  import { SESSION_STORE_KEY } from '../../common/constants';
9
9
 
10
10
  export const ChatPaused = () => {
@@ -55,7 +55,7 @@ export const ChatPaused = () => {
55
55
  };
56
56
 
57
57
  export const ChatBlocked = () => {
58
- const isLocalPeerBlacklisted = useIsLocalPeerBlacklisted();
58
+ const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true });
59
59
  if (!isLocalPeerBlacklisted) {
60
60
  return null;
61
61
  }
@@ -262,9 +262,9 @@ export const isValidQuestion = ({ text, type, options, weight, isQuiz = false })
262
262
  return false;
263
263
  }
264
264
 
265
- if (![QUESTION_TYPE.SINGLE_CHOICE, QUESTION_TYPE.MULTIPLE_CHOICE].includes(type)) {
266
- return true;
267
- }
265
+ // if (![QUESTION_TYPE.SINGLE_CHOICE, QUESTION_TYPE.MULTIPLE_CHOICE].includes(type)) {
266
+ // return true;
267
+ // }
268
268
 
269
269
  const everyOptionHasText = options.length > 0 && options.every(option => option && isValidTextInput(option.text, 1));
270
270
  const hasCorrectAnswer = options.some(option => option.isCorrectAnswer);
@@ -78,7 +78,15 @@ export const Leaderboard = ({ pollID }: { pollID: string }) => {
78
78
  <Text variant="xs" css={{ color: '$on_surface_medium' }}>
79
79
  Based on score and time taken to cast the correct answer
80
80
  </Text>
81
- <Box css={{ mt: '$8', gap: '$4', overflowY: 'auto', flex: '1 1 0', mr: '-$6', pr: '$6' }}>
81
+ <Box
82
+ css={{
83
+ mt: '$8',
84
+ overflowY: 'auto',
85
+ flex: '1 1 0',
86
+ mr: '-$6',
87
+ pr: '$6',
88
+ }}
89
+ >
82
90
  {pollLeaderboard?.entries &&
83
91
  pollLeaderboard.entries.map(question => (
84
92
  <LeaderboardEntry
@@ -21,7 +21,7 @@ export const LeaderboardEntry = ({
21
21
  maxPossibleScore: number;
22
22
  }) => {
23
23
  return (
24
- <Flex align="center" justify="between">
24
+ <Flex align="center" justify="between" css={{ my: '$4' }}>
25
25
  <Flex align="center" css={{ gap: '$6' }}>
26
26
  <Flex
27
27
  align="center"
@@ -44,17 +44,17 @@ export const LeaderboardEntry = ({
44
44
  {userName}
45
45
  </Text>
46
46
 
47
- <Text variant="sm">
48
- {score}/{maxPossibleScore} points
47
+ <Text variant="sm" css={{ mt: '$2' }}>
48
+ {score} / {maxPossibleScore} points
49
49
  </Text>
50
50
  </Box>
51
51
  </Flex>
52
- <Flex align="center" css={{ gap: '$6', color: '$on_surface_medium' }}>
53
- {position === 1 ? <TrophyFilledIcon /> : null}
52
+ <Flex align="center" css={{ gap: '$4', color: '$on_surface_medium' }}>
53
+ {position === 1 ? <TrophyFilledIcon height={18} width={18} /> : null}
54
54
  <CheckCircleIcon height={16} width={16} />
55
55
  {questionCount ? (
56
56
  <Text variant="xs">
57
- {correctResponses}/{questionCount}
57
+ {correctResponses} / {questionCount}
58
58
  </Text>
59
59
  ) : null}
60
60
  </Flex>
@@ -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
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import { HMSVirtualBackgroundTypes } from '@100mslive/hms-virtual-background';
3
- import { VirtualBackground, VirtualBackgroundMedia } from '@100mslive/types-prebuilt/elements/virtual_background';
3
+ import { VirtualBackgroundMedia } from '@100mslive/types-prebuilt/elements/virtual_background';
4
4
  import {
5
5
  HMSRoomState,
6
6
  selectIsLargeRoom,
@@ -28,7 +28,7 @@ import { defaultMedia, vbPlugin } from './constants';
28
28
  const iconDims = { height: '40px', width: '40px' };
29
29
  const MAX_RETRIES = 2;
30
30
 
31
- export const VBPicker = ({ background_media = [] }: VirtualBackground = {}) => {
31
+ export const VBPicker = ({ backgroundMedia = [] }: { backgroundMedia: VirtualBackgroundMedia[] }) => {
32
32
  const toggleVB = useSidepaneToggle(SIDE_PANE_OPTIONS.VB);
33
33
  const hmsActions = useHMSActions();
34
34
  const role = useHMSStore(selectLocalPeerRole);
@@ -46,7 +46,9 @@ export const VBPicker = ({ background_media = [] }: VirtualBackground = {}) => {
46
46
  const roomState = useHMSStore(selectRoomState);
47
47
  const isLargeRoom = useHMSStore(selectIsLargeRoom);
48
48
  const addedPluginToVideoTrack = useRef(false);
49
- const mediaList = [...background_media.map((media: VirtualBackgroundMedia) => media?.url), ...defaultMedia];
49
+ const mediaList = backgroundMedia.length
50
+ ? backgroundMedia.map((media: VirtualBackgroundMedia) => media?.url)
51
+ : defaultMedia;
50
52
 
51
53
  const inPreview = roomState === HMSRoomState.Preview;
52
54
  // Hidden in preview as the effect will be visible in the preview tile. Needed inside the room because the peer might not be on-screen
@@ -22,8 +22,8 @@ export const useChatBlacklist = (
22
22
  return { blacklistItem, blacklistedIDs };
23
23
  };
24
24
 
25
- export const useIsLocalPeerBlacklisted = () => {
25
+ export const useIsPeerBlacklisted = ({ local = false, peerCustomerUserId = '' }) => {
26
26
  const localPeer = useHMSStore(selectLocalPeer);
27
27
  const blacklistedPeerIDs = useHMSStore(selectSessionStore(SESSION_STORE_KEY.CHAT_PEER_BLACKLIST)) || [];
28
- return blacklistedPeerIDs?.includes(localPeer?.customerUserId);
28
+ return blacklistedPeerIDs?.includes(local ? localPeer?.customerUserId : peerCustomerUserId);
29
29
  };
@@ -12,7 +12,10 @@ import { Box, Flex } from '../../Layout';
12
12
  import { config as cssConfig } from '../../Theme';
13
13
  // @ts-ignore: No implicit Any
14
14
  import { useSidepaneReset } from '../components/AppData/useSidepane';
15
- import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
15
+ import {
16
+ useRoomLayoutConferencingScreen,
17
+ useRoomLayoutPreviewScreen,
18
+ } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
16
19
  import { translateAcross } from '../../utils';
17
20
  import { APP_DATA, SIDE_PANE_OPTIONS } from '../common/constants';
18
21
 
@@ -28,6 +31,7 @@ const SidePane = ({
28
31
  const activeScreensharePeerId = useHMSStore(selectAppData(APP_DATA.activeScreensharePeerId));
29
32
  const trackId = useHMSStore(selectVideoTrackByPeerID(activeScreensharePeerId))?.id;
30
33
  const { elements } = useRoomLayoutConferencingScreen();
34
+ const { elements: preview_elements } = useRoomLayoutPreviewScreen();
31
35
  const resetSidePane = useSidepaneReset();
32
36
  let ViewComponent;
33
37
  if (sidepane === SIDE_PANE_OPTIONS.POLLS) {
@@ -37,7 +41,7 @@ const SidePane = ({
37
41
  ViewComponent = <SidePaneTabs hideControls={hideControls} active={sidepane} />;
38
42
  }
39
43
  if (sidepane === SIDE_PANE_OPTIONS.VB) {
40
- ViewComponent = <VBPicker {...elements.virtual_background} />;
44
+ ViewComponent = <VBPicker backgroundMedia={preview_elements?.virtual_background?.background_media || []} />;
41
45
  }
42
46
 
43
47
  useEffect(() => {
@@ -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,17 @@ export const RoomLayoutContext = React.createContext<
18
18
  | undefined
19
19
  >(undefined);
20
20
 
21
+ // The default merge in lodash merges the values of current layout and the changes.
22
+ // This behaviour makes changes in array based values inconsistent since a union happens.
23
+ // The customizer uses the new value provided if one of the values is an array
24
+ function customizer(objValue: any, srcValue: any) {
25
+ if (isArray(objValue) || isArray(srcValue)) {
26
+ return srcValue;
27
+ }
28
+ // default merge behaviour is followed
29
+ return undefined;
30
+ }
31
+
21
32
  export const RoomLayoutProvider: React.FC<React.PropsWithChildren<RoomLayoutProviderProps>> = ({
22
33
  children,
23
34
  roomLayoutEndpoint,
@@ -25,7 +36,7 @@ export const RoomLayoutProvider: React.FC<React.PropsWithChildren<RoomLayoutProv
25
36
  }) => {
26
37
  const authToken: string = useAuthToken();
27
38
  const { layout, updateRoomLayoutForRole } = useFetchRoomLayout({ authToken, endpoint: roomLayoutEndpoint });
28
- const mergedLayout = authToken && layout ? merge(layout, overrideLayout) : layout;
39
+ const mergedLayout = authToken && layout ? mergeWith(layout, overrideLayout, customizer) : layout;
29
40
  return (
30
41
  <RoomLayoutContext.Provider value={{ layout: mergedLayout, updateRoomLayoutForRole }}>
31
42
  {children}