@100mslive/roomkit-react 0.2.7-alpha.0 → 0.2.7-alpha.2

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 (29) hide show
  1. package/README.md +30 -33
  2. package/dist/{HLSView-E65JZSU4.js → HLSView-DQJBCEW4.js} +2 -2
  3. package/dist/Prebuilt/common/constants.d.ts +4 -3
  4. package/dist/Prebuilt/components/AudioVideoToggle.d.ts +9 -0
  5. package/dist/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.d.ts +11 -0
  6. package/dist/Prebuilt/components/hooks/useAudioOutputTest.d.ts +8 -0
  7. package/dist/{chunk-DWLYDCFC.js → chunk-GEXL6KL2.js} +4355 -3936
  8. package/dist/chunk-GEXL6KL2.js.map +7 -0
  9. package/dist/index.cjs.js +5991 -5566
  10. package/dist/index.cjs.js.map +4 -4
  11. package/dist/index.js +1 -1
  12. package/dist/meta.cjs.json +668 -599
  13. package/dist/meta.esbuild.json +675 -606
  14. package/package.json +7 -6
  15. package/src/Prebuilt/common/constants.ts +7 -4
  16. package/src/Prebuilt/components/AppData/useUISettings.js +1 -1
  17. package/src/Prebuilt/components/AudioVideoToggle.tsx +308 -0
  18. package/src/Prebuilt/components/Chat/ChatFooter.tsx +0 -1
  19. package/src/Prebuilt/components/Footer/RoleOptions.tsx +1 -0
  20. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.tsx +159 -0
  21. package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +0 -2
  22. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +13 -2
  23. package/src/Prebuilt/components/Notifications/Notifications.tsx +1 -18
  24. package/src/Prebuilt/components/Settings/DeviceSettings.jsx +10 -17
  25. package/src/Prebuilt/components/hooks/useAudioOutputTest.tsx +20 -0
  26. package/dist/chunk-DWLYDCFC.js.map +0 -7
  27. package/src/Prebuilt/components/AudioVideoToggle.jsx +0 -171
  28. package/src/Prebuilt/components/IconButtonWithOptions/IconButtonWithOptions.jsx +0 -121
  29. /package/dist/{HLSView-E65JZSU4.js.map → HLSView-DQJBCEW4.js.map} +0 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.2.7-alpha.0",
13
+ "version": "0.2.7-alpha.2",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -82,10 +82,11 @@
82
82
  "react": ">=17.0.2 <19.0.0"
83
83
  },
84
84
  "dependencies": {
85
- "@100mslive/hls-player": "0.2.7-alpha.0",
86
- "@100mslive/hms-virtual-background": "1.12.7-alpha.0",
87
- "@100mslive/react-icons": "0.9.7-alpha.0",
88
- "@100mslive/react-sdk": "0.9.7-alpha.0",
85
+ "@100mslive/hls-player": "0.2.7-alpha.2",
86
+ "@100mslive/hms-noise-cancellation": "0.0.0-alpha.1",
87
+ "@100mslive/hms-virtual-background": "1.12.7-alpha.2",
88
+ "@100mslive/react-icons": "0.9.7-alpha.2",
89
+ "@100mslive/react-sdk": "0.9.7-alpha.2",
89
90
  "@100mslive/types-prebuilt": "0.12.7",
90
91
  "@emoji-mart/data": "^1.0.6",
91
92
  "@emoji-mart/react": "^1.0.1",
@@ -120,5 +121,5 @@
120
121
  "uuid": "^8.3.2",
121
122
  "worker-timers": "^7.0.40"
122
123
  },
123
- "gitHead": "3999106cba680bcb41ce773e10c85463da4dfeec"
124
+ "gitHead": "4098033b045e93a14929ec5f7480ca9463bbf59b"
124
125
  }
@@ -98,11 +98,12 @@ export const HLS_TIMED_METADATA_DOC_URL =
98
98
 
99
99
  export const REMOTE_STOP_SCREENSHARE_TYPE = 'REMOTE_STOP_SCREENSHARE';
100
100
 
101
- export const isChrome = parsedUserAgent.getBrowser()?.name?.toLowerCase() === 'chrome';
102
- export const isFirefox = parsedUserAgent.getBrowser()?.name?.toLowerCase() === 'firefox';
103
- export const isSafari = parsedUserAgent.getBrowser()?.name?.toLowerCase() === 'safari';
101
+ // mweb could have browser name as "Mobile Chrome" or "Mobile Firefox"
102
+ export const isChrome = parsedUserAgent.getBrowser()?.name?.toLowerCase().includes('chrome');
103
+ export const isFirefox = parsedUserAgent.getBrowser()?.name?.toLowerCase().includes('firefox');
104
+ export const isSafari = parsedUserAgent.getBrowser()?.name?.toLowerCase().includes('safari');
104
105
  export const isIOS = parsedUserAgent.getOS()?.name?.toLowerCase() === 'ios';
105
- export const isMacOS = parsedUserAgent.getOS()?.name?.toLowerCase() === 'mac os';
106
+ export const isMacOS = parsedUserAgent.getOS()?.name?.toLowerCase() === 'macos';
106
107
  export const isAndroid = parsedUserAgent.getOS()?.name?.toLowerCase() === 'android';
107
108
  export const isIPadOS = false;
108
109
  // typeof navigator !== "undefined" &&
@@ -142,3 +143,5 @@ export enum QUESTION_TYPE {
142
143
  export const ROLE_CHANGE_DECLINED = 'role_change_declined';
143
144
 
144
145
  export const DEFAULT_PORTAL_CONTAINER = '.prebuilt-container';
146
+
147
+ export const TEST_AUDIO_URL = 'https://100ms.live/test-audio.wav';
@@ -90,7 +90,7 @@ export const usePinnedTrack = () => {
90
90
 
91
91
  export const useSubscribedNotifications = notificationKey => {
92
92
  const notificationPreference = useHMSStore(selectAppDataByPath(APP_DATA.subscribedNotifications, notificationKey));
93
- return notificationPreference;
93
+ return notificationPreference || {};
94
94
  };
95
95
 
96
96
  export const useIsNotificationDisabled = () => {
@@ -0,0 +1,308 @@
1
+ import React, { Fragment, useEffect, useState } from 'react';
2
+ import { HMSKrispPlugin } from '@100mslive/hms-noise-cancellation';
3
+ import {
4
+ DeviceType,
5
+ HMSRoomState,
6
+ selectIsLocalAudioPluginPresent,
7
+ selectLocalAudioTrackID,
8
+ selectLocalVideoTrackID,
9
+ selectRoomState,
10
+ selectVideoTrackByID,
11
+ useAVToggle,
12
+ useDevices,
13
+ useHMSActions,
14
+ useHMSStore,
15
+ } from '@100mslive/react-sdk';
16
+ import {
17
+ AudioLevelIcon,
18
+ CameraFlipIcon,
19
+ CheckIcon,
20
+ MicOffIcon,
21
+ MicOnIcon,
22
+ SettingsIcon,
23
+ SpeakerIcon,
24
+ VideoOffIcon,
25
+ VideoOnIcon,
26
+ } from '@100mslive/react-icons';
27
+ import { IconButtonWithOptions } from './IconButtonWithOptions/IconButtonWithOptions';
28
+ // @ts-ignore: No implicit Any
29
+ import SettingsModal from './Settings/SettingsModal';
30
+ // @ts-ignore: No implicit Any
31
+ import { ToastManager } from './Toast/ToastManager';
32
+ import { Dropdown } from '../../Dropdown';
33
+ import { Box, Flex } from '../../Layout';
34
+ import { Switch } from '../../Switch';
35
+ import { Text } from '../../Text';
36
+ import { Tooltip } from '../../Tooltip';
37
+ import IconButton from '../IconButton';
38
+ import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
39
+ import { useAudioOutputTest } from './hooks/useAudioOutputTest';
40
+ import { isMacOS, TEST_AUDIO_URL } from '../common/constants';
41
+
42
+ // const optionsCSS = { fontWeight: '$semiBold', color: '$on_surface_high', w: '100%' };
43
+
44
+ export const Options = ({
45
+ options,
46
+ selectedDeviceId,
47
+ onClick,
48
+ }: {
49
+ options?: Array<MediaDeviceInfo | InputDeviceInfo>;
50
+ selectedDeviceId?: string;
51
+ onClick: (deviceId: string) => Promise<void>;
52
+ }) => {
53
+ return (
54
+ <>
55
+ {options?.map(option => (
56
+ <Dropdown.Item
57
+ key={option.label}
58
+ css={{
59
+ backgroundColor: selectedDeviceId === option.deviceId ? '$surface_bright' : '$surface_dim',
60
+ p: '$4 $8',
61
+ h: '$15',
62
+ fontSize: '$xs',
63
+ justifyContent: 'space-between',
64
+ }}
65
+ onClick={() => {
66
+ onClick(option.deviceId);
67
+ }}
68
+ >
69
+ {option.label}
70
+ {selectedDeviceId === option.deviceId ? <CheckIcon width={16} height={16} /> : null}
71
+ </Dropdown.Item>
72
+ ))}
73
+ </>
74
+ );
75
+ };
76
+
77
+ const OptionLabel = ({ children, icon }: { children: React.ReactNode; icon: React.ReactNode }) => {
78
+ return (
79
+ <Dropdown.Label
80
+ css={{
81
+ h: '$16',
82
+ p: '$4 $8',
83
+ color: '$on_surface_medium',
84
+ bg: 'transparent',
85
+ fontSize: '$xs',
86
+ gap: '$4',
87
+ alignItems: 'center',
88
+ }}
89
+ >
90
+ <Flex css={{ alignItems: 'center', justifyContent: 'center', '& svg': { size: '$8' } }}>{icon}</Flex> {children}
91
+ </Dropdown.Label>
92
+ );
93
+ };
94
+
95
+ const plugin = new HMSKrispPlugin();
96
+ const NoiseCancellation = () => {
97
+ const localPeerAudioTrackID = useHMSStore(selectLocalAudioTrackID);
98
+ const isPluginAdded = useHMSStore(selectIsLocalAudioPluginPresent(plugin.getName()));
99
+ const [active, setActive] = useState(isPluginAdded);
100
+ const [inProgress, setInProgress] = useState(false);
101
+ const actions = useHMSActions();
102
+
103
+ useEffect(() => {
104
+ (async () => {
105
+ setInProgress(true);
106
+ if (active && !isPluginAdded) {
107
+ await actions.addPluginToAudioTrack(plugin);
108
+ }
109
+ if (!active && isPluginAdded) {
110
+ await actions.removePluginFromAudioTrack(plugin);
111
+ }
112
+ setInProgress(false);
113
+ })();
114
+ }, [actions, active, isPluginAdded]);
115
+
116
+ if (!plugin.isSupported() || !localPeerAudioTrackID) {
117
+ return null;
118
+ }
119
+
120
+ return (
121
+ <Dropdown.Item
122
+ css={{
123
+ p: '$4 $8',
124
+ h: '$15',
125
+ fontSize: '$xs',
126
+ justifyContent: 'space-between',
127
+ }}
128
+ onClick={e => {
129
+ e.preventDefault();
130
+ setActive(value => !value);
131
+ }}
132
+ >
133
+ <Text css={{ display: 'flex', alignItems: 'center', gap: '$2', fontSize: '$xs', '& svg': { size: '$8' } }}>
134
+ <AudioLevelIcon />
135
+ Reduce Noise
136
+ </Text>
137
+ <Switch
138
+ id="noise_cancellation"
139
+ checked={active}
140
+ disabled={inProgress}
141
+ onClick={e => e.stopPropagation()}
142
+ onCheckedChange={value => {
143
+ setActive(value);
144
+ }}
145
+ />
146
+ </Dropdown.Item>
147
+ );
148
+ };
149
+
150
+ const AudioOutputLabel = ({ deviceId }: { deviceId: string }) => {
151
+ const { playing, setPlaying, audioRef } = useAudioOutputTest({ deviceId });
152
+ return (
153
+ <OptionLabel icon={<SpeakerIcon />}>
154
+ <Box css={{ flex: '1 1 0' }}>Speakers</Box>
155
+ <Text
156
+ variant="xs"
157
+ css={{ color: '$primary_bright', '&:hover': { cursor: 'pointer' } }}
158
+ onClick={async () => {
159
+ if (playing) {
160
+ return;
161
+ }
162
+ await audioRef.current?.play();
163
+ }}
164
+ >
165
+ <audio
166
+ ref={audioRef}
167
+ src={TEST_AUDIO_URL}
168
+ onEnded={() => setPlaying(false)}
169
+ onPlay={() => setPlaying(true)}
170
+ style={{ display: 'none' }}
171
+ />
172
+ {playing ? 'Playing Sound...' : 'Play Test Sound'}
173
+ </Text>
174
+ </OptionLabel>
175
+ );
176
+ };
177
+
178
+ const AudioSettings = ({ onClick }: { onClick: () => void }) => {
179
+ return (
180
+ <>
181
+ <Dropdown.Item
182
+ css={{
183
+ backgroundColor: '$surface_dim',
184
+ p: '$4 $8',
185
+ h: '$15',
186
+ alignItems: 'center',
187
+ gap: '$2',
188
+ fontSize: '$xs',
189
+ '& svg': { size: '$8' },
190
+ }}
191
+ onClick={onClick}
192
+ >
193
+ <SettingsIcon /> Audio Settings
194
+ </Dropdown.Item>
195
+ </>
196
+ );
197
+ };
198
+
199
+ export const AudioVideoToggle = ({ hideOptions = false }) => {
200
+ const { allDevices, selectedDeviceIDs, updateDevice } = useDevices();
201
+ const { videoInput, audioInput, audioOutput } = allDevices;
202
+ const { isLocalVideoEnabled, isLocalAudioEnabled, toggleAudio, toggleVideo } = useAVToggle();
203
+ const actions = useHMSActions();
204
+ const videoTrackId = useHMSStore(selectLocalVideoTrackID);
205
+ const localVideoTrack = useHMSStore(selectVideoTrackByID(videoTrackId));
206
+ const roomState = useHMSStore(selectRoomState);
207
+ const hasAudioDevices = Number(audioInput?.length) > 0;
208
+ const hasVideoDevices = Number(videoInput?.length) > 0;
209
+ const shouldShowAudioOutput = 'setSinkId' in HTMLMediaElement.prototype && Number(audioOutput?.length) > 0;
210
+ const { screenType } = useRoomLayoutConferencingScreen();
211
+ const [showSettings, setShowSettings] = useState(false);
212
+
213
+ if (!toggleAudio && !toggleVideo) {
214
+ return null;
215
+ }
216
+
217
+ return (
218
+ <Fragment>
219
+ {toggleAudio ? (
220
+ <IconButtonWithOptions
221
+ disabled={!toggleAudio}
222
+ hideOptions={hideOptions || !hasAudioDevices}
223
+ onDisabledClick={toggleAudio}
224
+ tooltipMessage={`Turn ${isLocalAudioEnabled ? 'off' : 'on'} audio (${isMacOS ? '⌘' : 'ctrl'} + d)`}
225
+ icon={
226
+ !isLocalAudioEnabled ? <MicOffIcon data-testid="audio_off_btn" /> : <MicOnIcon data-testid="audio_on_btn" />
227
+ }
228
+ active={isLocalAudioEnabled}
229
+ onClick={toggleAudio}
230
+ key="toggleAudio"
231
+ >
232
+ <Dropdown.Group>
233
+ <OptionLabel icon={<MicOnIcon />}>{!shouldShowAudioOutput ? 'Audio' : 'Microphone'}</OptionLabel>
234
+ <Options
235
+ options={audioInput}
236
+ selectedDeviceId={selectedDeviceIDs.audioInput}
237
+ onClick={deviceId => updateDevice({ deviceId, deviceType: DeviceType.audioInput })}
238
+ />
239
+ </Dropdown.Group>
240
+ <Dropdown.ItemSeparator css={{ mx: 0 }} />
241
+ {shouldShowAudioOutput && (
242
+ <>
243
+ <AudioOutputLabel deviceId={selectedDeviceIDs.audioOutput || ''} />
244
+ <Dropdown.Group>
245
+ <Options
246
+ options={audioOutput}
247
+ selectedDeviceId={selectedDeviceIDs.audioOutput}
248
+ onClick={deviceId => updateDevice({ deviceId, deviceType: DeviceType.audioOutput })}
249
+ />
250
+ </Dropdown.Group>
251
+ </>
252
+ )}
253
+ <Dropdown.ItemSeparator css={{ mx: 0 }} />
254
+ <NoiseCancellation />
255
+ <Dropdown.ItemSeparator css={{ mx: 0 }} />
256
+ <AudioSettings onClick={() => setShowSettings(true)} />
257
+ </IconButtonWithOptions>
258
+ ) : null}
259
+
260
+ {toggleVideo ? (
261
+ <IconButtonWithOptions
262
+ disabled={!toggleVideo}
263
+ hideOptions={hideOptions || !hasVideoDevices}
264
+ onDisabledClick={toggleVideo}
265
+ tooltipMessage={`Turn ${isLocalVideoEnabled ? 'off' : 'on'} video (${isMacOS ? '⌘' : 'ctrl'} + e)`}
266
+ icon={
267
+ !isLocalVideoEnabled ? (
268
+ <VideoOffIcon data-testid="video_off_btn" />
269
+ ) : (
270
+ <VideoOnIcon data-testid="video_on_btn" />
271
+ )
272
+ }
273
+ key="toggleVideo"
274
+ active={isLocalVideoEnabled}
275
+ onClick={toggleVideo}
276
+ >
277
+ <Options
278
+ options={videoInput}
279
+ selectedDeviceId={selectedDeviceIDs.videoInput}
280
+ onClick={deviceId => updateDevice({ deviceId, deviceType: DeviceType.videoInput })}
281
+ />
282
+ </IconButtonWithOptions>
283
+ ) : null}
284
+
285
+ {localVideoTrack?.facingMode && roomState === HMSRoomState.Preview ? (
286
+ <Tooltip title="Switch Camera" key="switchCamera">
287
+ <IconButton
288
+ onClick={async () => {
289
+ try {
290
+ await actions.switchCamera();
291
+ } catch (e) {
292
+ ToastManager.addToast({
293
+ title: `Error while flipping camera ${(e as Error).message || ''}`,
294
+ variant: 'error',
295
+ });
296
+ }
297
+ }}
298
+ >
299
+ <CameraFlipIcon />
300
+ </IconButton>
301
+ </Tooltip>
302
+ ) : null}
303
+ {showSettings && (
304
+ <SettingsModal open={showSettings} onOpenChange={() => setShowSettings(false)} screenType={screenType} />
305
+ )}
306
+ </Fragment>
307
+ );
308
+ };
@@ -219,7 +219,6 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
219
219
  placeholder={message_placeholder}
220
220
  ref={inputRef}
221
221
  required
222
- autoFocus={!isMobile}
223
222
  onKeyPress={async event => {
224
223
  if (event.key === 'Enter') {
225
224
  if (!event.shiftKey) {
@@ -80,6 +80,7 @@ export const RoleOptions = ({ roleName, peerList }: { roleName: string; peerList
80
80
  return (
81
81
  <Dropdown.Root open={openOptions} onOpenChange={setOpenOptions}>
82
82
  <Dropdown.Trigger
83
+ data-testid="role_group_options"
83
84
  onClick={e => e.stopPropagation()}
84
85
  className="role_actions"
85
86
  asChild
@@ -0,0 +1,159 @@
1
+ import React from 'react';
2
+ import { VerticalMenuIcon } from '@100mslive/react-icons';
3
+ import { Dropdown } from '../../../Dropdown';
4
+ import { Flex } from '../../../Layout';
5
+ import { styled } from '../../../Theme';
6
+ import { Tooltip } from '../../../Tooltip';
7
+ import IconButton from '../../IconButton';
8
+
9
+ const variants = {
10
+ disabled: {
11
+ true: {
12
+ bg: '$surface_brighter',
13
+ },
14
+ },
15
+ active: {
16
+ false: {
17
+ bg: '$secondary_dim',
18
+ },
19
+ },
20
+ };
21
+
22
+ const IconSection = styled(IconButton, {
23
+ w: 'unset',
24
+ h: '$14',
25
+ p: '$4',
26
+ r: '$1',
27
+ bg: '$transparent',
28
+ borderTopRightRadius: 0,
29
+ borderColor: '$border_bright',
30
+ borderBottomRightRadius: 0,
31
+ position: 'relative',
32
+ '&:not([disabled]):focus-visible': {
33
+ zIndex: 1,
34
+ },
35
+ '@md': {
36
+ mx: 0,
37
+ borderTopRightRadius: '$1',
38
+ borderBottomRightRadius: '$1',
39
+ },
40
+ variants: {
41
+ ...variants,
42
+ hideOptions: {
43
+ true: {
44
+ borderTopRightRadius: '$1',
45
+ borderBottomRightRadius: '$1',
46
+ },
47
+ },
48
+ },
49
+ });
50
+
51
+ const OptionsSection = styled(IconButton, {
52
+ w: 'unset',
53
+ h: '$14',
54
+ p: '$4 $2',
55
+ r: '$1',
56
+ borderTopLeftRadius: 0,
57
+ borderColor: '$border_bright',
58
+ borderBottomLeftRadius: 0,
59
+ borderLeftWidth: 0,
60
+ position: 'relative',
61
+ '&:not([disabled]):focus-visible': {
62
+ zIndex: 1,
63
+ },
64
+ '@md': {
65
+ display: 'none',
66
+ },
67
+ variants,
68
+ });
69
+
70
+ const Icon = styled(Flex, {
71
+ alignItems: 'center',
72
+ justifyContent: 'center',
73
+ color: '$on_primary_high',
74
+ variants: {
75
+ disabled: {
76
+ true: {
77
+ color: '$on_surface_low',
78
+ },
79
+ },
80
+ active: {
81
+ true: {
82
+ color: '$on_surface_high',
83
+ },
84
+ },
85
+ },
86
+ });
87
+
88
+ export const IconButtonWithOptions = ({
89
+ disabled = false,
90
+ onDisabledClick = () => {
91
+ return;
92
+ },
93
+ tooltipMessage = '',
94
+ icon,
95
+ children,
96
+ active,
97
+ hideOptions = false,
98
+ onClick = () => {
99
+ return;
100
+ },
101
+ }: {
102
+ onClick: () => void;
103
+ onDisabledClick: () => void;
104
+ icon: React.ReactNode;
105
+ children: React.ReactNode;
106
+ hideOptions?: boolean;
107
+ active: boolean;
108
+ disabled?: boolean;
109
+ tooltipMessage?: string;
110
+ }) => {
111
+ const commonProps = { disabled, active };
112
+ return (
113
+ <Flex>
114
+ <IconSection {...commonProps} onClick={onClick} hideOptions={hideOptions}>
115
+ <Tooltip disabled={!tooltipMessage} title={tooltipMessage}>
116
+ <Icon {...commonProps}>{icon}</Icon>
117
+ </Tooltip>
118
+ </IconSection>
119
+ {!hideOptions && children ? (
120
+ <Dropdown.Root>
121
+ <Dropdown.Trigger
122
+ asChild
123
+ // onClick does not work
124
+ onPointerDown={e => {
125
+ if (disabled) {
126
+ e.preventDefault();
127
+ onDisabledClick();
128
+ }
129
+ }}
130
+ >
131
+ <OptionsSection {...commonProps}>
132
+ <Tooltip title="View Options">
133
+ <Icon {...commonProps}>
134
+ <VerticalMenuIcon />
135
+ </Icon>
136
+ </Tooltip>
137
+ </OptionsSection>
138
+ </Dropdown.Trigger>
139
+ <Dropdown.Content
140
+ sideOffset={5}
141
+ alignOffset={-44}
142
+ align="start"
143
+ side="top"
144
+ css={{
145
+ w: 344,
146
+ maxWidth: '100%',
147
+ maxHeight: 'unset',
148
+ p: 0,
149
+ border: 'none',
150
+ bg: '$surface_dim',
151
+ }}
152
+ >
153
+ {children}
154
+ </Dropdown.Content>
155
+ </Dropdown.Root>
156
+ ) : null}
157
+ </Flex>
158
+ );
159
+ };
@@ -1,8 +1,6 @@
1
1
  import React, { Fragment, useState } from 'react';
2
2
  import { ConferencingScreen } from '@100mslive/types-prebuilt';
3
- // @ts-ignore: No implicit Any
4
3
  import { selectIsConnectedToRoom, selectPermissions, useHMSStore, useRecordingStreaming } from '@100mslive/react-sdk';
5
- // @ts-ignore: No implicit Any
6
4
  import { ExitIcon, StopIcon, VerticalMenuIcon } from '@100mslive/react-icons';
7
5
  import { Dropdown } from '../../../Dropdown';
8
6
  import { Box, Flex } from '../../../Layout';
@@ -11,25 +11,36 @@ import {
11
11
  // @ts-ignore: No implicit Any
12
12
  import { ToastBatcher } from '../Toast/ToastBatcher';
13
13
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
14
+ // @ts-ignore: No implicit Any
15
+ import { useSubscribedNotifications } from '../AppData/useUISettings';
14
16
 
15
17
  export const HandRaisedNotifications = () => {
16
18
  const notification = useHMSNotifications(HMSNotificationTypes.HAND_RAISE_CHANGED);
17
19
  const roomState = useHMSStore(selectRoomState);
18
20
  const vanillaStore = useHMSVanillaStore();
19
21
  const { on_stage_exp } = useRoomLayoutConferencingScreen().elements || {};
22
+ const subscribedNotifications = useSubscribedNotifications();
20
23
 
21
24
  useEffect(() => {
22
25
  if (!notification?.data) {
23
26
  return;
24
27
  }
25
- if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !on_stage_exp) {
28
+
29
+ // Don't show toast message in case of local peer.
30
+ if (
31
+ roomState !== HMSRoomState.Connected ||
32
+ notification.data.isLocal ||
33
+ !on_stage_exp ||
34
+ !subscribedNotifications.METADATA_UPDATED
35
+ ) {
26
36
  return;
27
37
  }
28
38
  const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
29
39
  if (hasPeerHandRaised) {
30
40
  ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
41
+ console.debug('Metadata updated', notification.data);
31
42
  }
32
- }, [notification, on_stage_exp, roomState, vanillaStore]);
43
+ }, [notification, on_stage_exp, roomState, subscribedNotifications.METADATA_UPDATED, vanillaStore]);
33
44
 
34
45
  return null;
35
46
  };
@@ -16,8 +16,6 @@ import { GroupIcon } from '@100mslive/react-icons';
16
16
  import { Box, Button } from '../../..';
17
17
  import { useUpdateRoomLayout } from '../../provider/roomLayoutProvider';
18
18
  // @ts-ignore: No implicit Any
19
- import { ToastBatcher } from '../Toast/ToastBatcher';
20
- // @ts-ignore: No implicit Any
21
19
  import { ToastManager } from '../Toast/ToastManager';
22
20
  import { AutoplayBlockedModal } from './AutoplayBlockedModal';
23
21
  import { ChatNotifications } from './ChatNotifications';
@@ -34,8 +32,6 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
34
32
  import { usePollViewToggle } from '../AppData/useSidepane';
35
33
  // @ts-ignore: No implicit Any
36
34
  import { useIsNotificationDisabled, useSubscribedNotifications } from '../AppData/useUISettings';
37
- // @ts-ignore: No implicit Any
38
- import { getMetadata } from '../../common/utils';
39
35
  import { ROLE_CHANGE_DECLINED } from '../../common/constants';
40
36
 
41
37
  const pollToastKey: Record<string, string> = {};
@@ -43,7 +39,7 @@ const pollToastKey: Record<string, string> = {};
43
39
  export function Notifications() {
44
40
  const localPeerID = useHMSStore(selectLocalPeerID);
45
41
  const notification = useHMSNotifications();
46
- const subscribedNotifications = useSubscribedNotifications() || {};
42
+ const subscribedNotifications = useSubscribedNotifications();
47
43
  const roomState = useHMSStore(selectRoomState);
48
44
  const updateRoomLayoutForRole = useUpdateRoomLayout();
49
45
  const isNotificationDisabled = useIsNotificationDisabled();
@@ -65,19 +61,6 @@ export function Notifications() {
65
61
  return;
66
62
  }
67
63
  switch (notification.type) {
68
- case HMSNotificationTypes.METADATA_UPDATED:
69
- if (roomState !== HMSRoomState.Connected) {
70
- return;
71
- }
72
- // Don't show toast message when metadata is updated and raiseHand is false.
73
- // Don't show toast message in case of local peer.
74
- const metadata = getMetadata(notification.data?.metadata);
75
- if (!metadata?.isHandRaised || notification.data.isLocal) return;
76
-
77
- console.debug('Metadata updated', notification.data);
78
- if (!subscribedNotifications.METADATA_UPDATED) return;
79
- ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
80
- break;
81
64
  case HMSNotificationTypes.NAME_UPDATED:
82
65
  console.log(notification.data.id + ' changed their name to ' + notification.data.name);
83
66
  break;