@100mslive/roomkit-react 0.3.16-alpha.0 → 0.3.16-alpha.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. package/dist/{HLSView-KOCGTP23.css → HLSView-D62ZFGUE.css} +3 -3
  2. package/dist/{HLSView-KOCGTP23.css.map → HLSView-D62ZFGUE.css.map} +1 -1
  3. package/dist/{HLSView-P7GF2RAU.js → HLSView-QYHOAJX7.js} +2 -2
  4. package/dist/Prebuilt/components/Chat/ChatBody.d.ts +887 -0
  5. package/dist/Prebuilt/components/Chat/ChatFooter.d.ts +1 -1
  6. package/dist/Prebuilt/components/Chat/utils.d.ts +2 -0
  7. package/dist/Prebuilt/components/PIP/PIPChat.d.ts +2 -0
  8. package/dist/Prebuilt/components/PIP/PIPChatOption.d.ts +5 -0
  9. package/dist/Prebuilt/components/PIP/PIPProvider.d.ts +6 -0
  10. package/dist/Prebuilt/components/PIP/PIPWindow.d.ts +7 -0
  11. package/dist/Prebuilt/components/PIP/context.d.ts +8 -0
  12. package/dist/Prebuilt/components/PIP/usePIPChat.d.ts +5 -0
  13. package/dist/Prebuilt/components/PIP/usePIPWindow.d.ts +2 -0
  14. package/dist/{chunk-DDB4BLHX.js → chunk-NYBDQX5B.js} +10131 -9675
  15. package/dist/chunk-NYBDQX5B.js.map +7 -0
  16. package/dist/index.cjs.css +2 -2
  17. package/dist/index.cjs.css.map +1 -1
  18. package/dist/index.cjs.js +4021 -3510
  19. package/dist/index.cjs.js.map +4 -4
  20. package/dist/index.css +2 -2
  21. package/dist/index.css.map +1 -1
  22. package/dist/index.js +1 -1
  23. package/dist/meta.cjs.json +2292 -1910
  24. package/dist/meta.esbuild.json +2326 -1944
  25. package/package.json +8 -7
  26. package/src/Prebuilt/App.tsx +21 -18
  27. package/src/Prebuilt/components/AudioVideoToggle.tsx +16 -9
  28. package/src/Prebuilt/components/Chat/ChatBody.tsx +4 -12
  29. package/src/Prebuilt/components/Chat/ChatFooter.tsx +2 -3
  30. package/src/Prebuilt/components/Chat/utils.ts +11 -0
  31. package/src/Prebuilt/components/ConferenceScreen.tsx +13 -1
  32. package/src/Prebuilt/components/Footer/ParticipantList.tsx +1 -4
  33. package/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx +24 -6
  34. package/src/Prebuilt/components/Notifications/HandRaisedNotifications.tsx +33 -0
  35. package/src/Prebuilt/components/Notifications/Notifications.tsx +3 -1
  36. package/src/Prebuilt/components/PIP/PIPChat.tsx +273 -0
  37. package/src/Prebuilt/components/PIP/PIPChatOption.tsx +18 -0
  38. package/src/Prebuilt/components/PIP/PIPProvider.tsx +56 -0
  39. package/src/Prebuilt/components/PIP/PIPWindow.tsx +13 -0
  40. package/src/Prebuilt/components/PIP/context.ts +10 -0
  41. package/src/Prebuilt/components/PIP/usePIPChat.tsx +105 -0
  42. package/src/Prebuilt/components/PIP/usePIPWindow.tsx +12 -0
  43. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +3 -1
  44. package/src/Prebuilt/components/Toast/ToastConfig.jsx +2 -2
  45. package/dist/chunk-DDB4BLHX.js.map +0 -7
  46. /package/dist/{HLSView-P7GF2RAU.js.map → HLSView-QYHOAJX7.js.map} +0 -0
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "prebuilt",
11
11
  "roomkit"
12
12
  ],
13
- "version": "0.3.16-alpha.0",
13
+ "version": "0.3.16-alpha.10",
14
14
  "author": "100ms",
15
15
  "license": "MIT",
16
16
  "repository": {
@@ -75,12 +75,12 @@
75
75
  "react": ">=17.0.2 <19.0.0"
76
76
  },
77
77
  "dependencies": {
78
- "@100mslive/hls-player": "0.3.16-alpha.0",
78
+ "@100mslive/hls-player": "0.3.16-alpha.10",
79
79
  "@100mslive/hms-noise-cancellation": "0.0.1",
80
- "@100mslive/hms-virtual-background": "1.13.16-alpha.0",
81
- "@100mslive/hms-whiteboard": "0.0.6-alpha.0",
82
- "@100mslive/react-icons": "0.10.16-alpha.0",
83
- "@100mslive/react-sdk": "0.10.16-alpha.0",
80
+ "@100mslive/hms-virtual-background": "1.13.16-alpha.10",
81
+ "@100mslive/hms-whiteboard": "0.0.6-alpha.10",
82
+ "@100mslive/react-icons": "0.10.16-alpha.10",
83
+ "@100mslive/react-sdk": "0.10.16-alpha.10",
84
84
  "@100mslive/types-prebuilt": "0.12.9",
85
85
  "@emoji-mart/data": "^1.0.6",
86
86
  "@emoji-mart/react": "^1.0.1",
@@ -104,6 +104,7 @@
104
104
  "eventemitter2": "^6.4.9",
105
105
  "lodash.merge": "^4.6.2",
106
106
  "qrcode.react": "^3.1.0",
107
+ "react-dom": "^18.2.0",
107
108
  "react-draggable": "^4.4.5",
108
109
  "react-intersection-observer": "^9.4.3",
109
110
  "react-swipeable": "^7.0.1",
@@ -116,5 +117,5 @@
116
117
  "uuid": "^8.3.2",
117
118
  "worker-timers": "^7.0.40"
118
119
  },
119
- "gitHead": "0ba6be8700e395887440d6ab1cadaacb6a769e98"
120
+ "gitHead": "770babc8f2199bd6c5b112472a97b3a93a10f6c4"
120
121
  }
@@ -23,6 +23,7 @@ import { KeyboardHandler } from './components/Input/KeyboardInputManager';
23
23
  import { LeaveScreen } from './components/LeaveScreen';
24
24
  import { MwebLandscapePrompt } from './components/MwebLandscapePrompt';
25
25
  import { Notifications } from './components/Notifications';
26
+ import { PIPProvider } from './components/PIP/PIPProvider';
26
27
  import { PreviewScreen } from './components/Preview/PreviewScreen';
27
28
  // @ts-ignore: No implicit Any
28
29
  import { ToastContainer } from './components/Toast/ToastContainer';
@@ -218,24 +219,26 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
218
219
  },
219
220
  }}
220
221
  >
221
- <Init />
222
- <DialogContainerProvider dialogContainerSelector={containerSelector}>
223
- <Box
224
- className={DEFAULT_PORTAL_CONTAINER.slice(1)} // Skips the '.' in the selector
225
- css={{
226
- bg: '$background_dim',
227
- size: '100%',
228
- lineHeight: '1.5',
229
- '-webkit-text-size-adjust': '100%',
230
- position: 'relative',
231
- }}
232
- >
233
- <AppRoutes
234
- authTokenByRoomCodeEndpoint={tokenByRoomCodeEndpoint}
235
- defaultAuthToken={authToken}
236
- />
237
- </Box>
238
- </DialogContainerProvider>
222
+ <PIPProvider>
223
+ <Init />
224
+ <DialogContainerProvider dialogContainerSelector={containerSelector}>
225
+ <Box
226
+ className={DEFAULT_PORTAL_CONTAINER.slice(1)} // Skips the '.' in the selector
227
+ css={{
228
+ bg: '$background_dim',
229
+ size: '100%',
230
+ lineHeight: '1.5',
231
+ '-webkit-text-size-adjust': '100%',
232
+ position: 'relative',
233
+ }}
234
+ >
235
+ <AppRoutes
236
+ authTokenByRoomCodeEndpoint={tokenByRoomCodeEndpoint}
237
+ defaultAuthToken={authToken}
238
+ />
239
+ </Box>
240
+ </DialogContainerProvider>
241
+ </PIPProvider>
239
242
  </HMSThemeProvider>
240
243
  );
241
244
  }}
@@ -44,7 +44,7 @@ import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/
44
44
  // @ts-ignore: No implicit Any
45
45
  import { useIsNoiseCancellationEnabled, useSetNoiseCancellation } from './AppData/useUISettings';
46
46
  import { useAudioOutputTest } from './hooks/useAudioOutputTest';
47
- import { isMacOS, TEST_AUDIO_URL } from '../common/constants';
47
+ import { isAndroid, isIOS, isMacOS, TEST_AUDIO_URL } from '../common/constants';
48
48
 
49
49
  const krispPlugin = new HMSKrispPlugin();
50
50
  // const optionsCSS = { fontWeight: '$semiBold', color: '$on_surface_high', w: '100%' };
@@ -109,6 +109,9 @@ const useNoiseCancellationWithPlugin = () => {
109
109
  if (inProgress) {
110
110
  return;
111
111
  }
112
+ if (!krispPlugin.checkSupport().isSupported) {
113
+ throw Error('Krisp plugin is not supported');
114
+ }
112
115
  setInProgress(true);
113
116
  if (enabled) {
114
117
  await actions.addPluginToAudioTrack(krispPlugin);
@@ -281,13 +284,17 @@ export const AudioVideoToggle = ({ hideOptions = false }: { hideOptions?: boolea
281
284
  useEffect(() => {
282
285
  (async () => {
283
286
  if (isNoiseCancellationEnabled && !isKrispPluginAdded && !inProgress && localPeer?.audioTrack) {
284
- await setNoiseCancellationWithPlugin(true);
285
- ToastManager.addToast({
286
- title: `Noise Reduction Enabled`,
287
- variant: 'standard',
288
- duration: 2000,
289
- icon: <AudioLevelIcon />,
290
- });
287
+ try {
288
+ await setNoiseCancellationWithPlugin(true);
289
+ ToastManager.addToast({
290
+ title: `Noise Reduction Enabled`,
291
+ variant: 'standard',
292
+ duration: 2000,
293
+ icon: <AudioLevelIcon />,
294
+ });
295
+ } catch (error) {
296
+ console.error(error);
297
+ }
291
298
  }
292
299
  })();
293
300
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -365,7 +372,7 @@ export const AudioVideoToggle = ({ hideOptions = false }: { hideOptions?: boolea
365
372
  </IconButtonWithOptions>
366
373
  ) : null}
367
374
 
368
- {localVideoTrack?.facingMode && roomState === HMSRoomState.Preview ? (
375
+ {localVideoTrack?.facingMode && roomState === HMSRoomState.Preview && (isIOS || isAndroid) ? (
369
376
  <Tooltip title="Switch Camera" key="switchCamera">
370
377
  <IconButton
371
378
  onClick={async () => {
@@ -28,18 +28,9 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
28
28
  // @ts-ignore: No implicit Any
29
29
  import { useSetSubscribedChatSelector } from '../AppData/useUISettings';
30
30
  import { usePinnedBy } from '../hooks/usePinnedBy';
31
+ import { formatTime } from './utils';
31
32
  import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
32
33
 
33
- const formatTime = (date: Date) => {
34
- if (!(date instanceof Date)) {
35
- return '';
36
- }
37
- const hours = date.getHours();
38
- const minutes = date.getMinutes();
39
- const suffix = hours > 11 ? 'PM' : 'AM';
40
- return `${hours < 10 ? '0' : ''}${hours}:${minutes < 10 ? '0' : ''}${minutes} ${suffix}`;
41
- };
42
-
43
34
  const rowHeights: Record<number, { size: number; id: string }> = {};
44
35
  let listInstance: VariableSizeList | null = null; //eslint-disable-line
45
36
  function getRowHeight(index: number) {
@@ -109,7 +100,7 @@ const MessageTypeContainer = ({ left, right }: { left?: string; right?: string }
109
100
  );
110
101
  };
111
102
 
112
- const MessageType = ({
103
+ export const MessageType = ({
113
104
  roles,
114
105
  hasCurrentUserSent,
115
106
  receiver,
@@ -172,7 +163,8 @@ const getMessageType = ({ roles, receiver }: { roles?: HMSRoleName[]; receiver?:
172
163
  }
173
164
  return receiver ? 'private' : '';
174
165
  };
175
- const SenderName = styled(Text, {
166
+
167
+ export const SenderName = styled(Text, {
176
168
  overflow: 'hidden',
177
169
  textOverflow: 'ellipsis',
178
170
  whiteSpace: 'nowrap',
@@ -20,10 +20,9 @@ import { useIsPeerBlacklisted } from '../hooks/useChatBlacklist';
20
20
  // @ts-ignore: No implicit any
21
21
  import { useEmojiPickerStyles } from './useEmojiPickerStyles';
22
22
  import { useDefaultChatSelection, useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
23
+ import { CHAT_MESSAGE_LIMIT } from './utils';
23
24
  import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
24
25
 
25
- const CHAT_MESSAGE_LIMIT = 2000;
26
-
27
26
  const TextArea = styled('textarea', {
28
27
  width: '100%',
29
28
  bg: 'transparent',
@@ -76,7 +75,7 @@ function EmojiPicker({ onSelect }: { onSelect: (emoji: any) => void }) {
76
75
  );
77
76
  }
78
77
 
79
- export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => void; children: ReactNode }) => {
78
+ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => void; children?: ReactNode }) => {
80
79
  const hmsActions = useHMSActions();
81
80
  const inputRef = useRef<HTMLTextAreaElement>(null);
82
81
  const [draftMessage, setDraftMessage] = useChatDraftMessage();
@@ -0,0 +1,11 @@
1
+ export const formatTime = (date: Date) => {
2
+ if (!(date instanceof Date)) {
3
+ return '';
4
+ }
5
+ const hours = date.getHours();
6
+ const minutes = date.getMinutes();
7
+ const suffix = hours > 11 ? 'PM' : 'AM';
8
+ return `${hours < 10 ? '0' : ''}${hours}:${minutes < 10 ? '0' : ''}${minutes} ${suffix}`;
9
+ };
10
+
11
+ export const CHAT_MESSAGE_LIMIT = 2000;
@@ -6,6 +6,7 @@ import {
6
6
  selectAppData,
7
7
  selectIsConnectedToRoom,
8
8
  selectRoomState,
9
+ useAwayNotifications,
9
10
  useHMSActions,
10
11
  useHMSStore,
11
12
  } from '@100mslive/react-sdk';
@@ -50,6 +51,7 @@ export const ConferenceScreen = () => {
50
51
  const isMobileDevice = isAndroid || isIOS || isIPadOS;
51
52
  const dropdownListRef = useRef<string[]>();
52
53
  const [isHLSStarted] = useSetAppDataByKey(APP_DATA.hlsStarted);
54
+ const { requestPermission } = useAwayNotifications();
53
55
 
54
56
  // using it in hls stream to show action button when chat is disabled
55
57
  const showChat = !!screenProps.elements?.chat;
@@ -99,10 +101,20 @@ export const ConferenceScreen = () => {
99
101
  speakerAutoSelectionBlacklist: ['Yeti Stereo Microphone'],
100
102
  },
101
103
  })
104
+ .then(() => requestPermission())
102
105
  .catch(console.error);
103
106
  autoRoomJoined.current = true;
104
107
  }
105
- }, [authTokenInAppData, endpoints?.init, hmsActions, isConnectedToRoom, isPreviewScreenEnabled, roomState, userName]);
108
+ }, [
109
+ authTokenInAppData,
110
+ endpoints?.init,
111
+ hmsActions,
112
+ isConnectedToRoom,
113
+ isPreviewScreenEnabled,
114
+ roomState,
115
+ userName,
116
+ requestPermission,
117
+ ]);
106
118
 
107
119
  useEffect(() => {
108
120
  onJoinFunc?.();
@@ -194,7 +194,6 @@ export const Participant = ({
194
194
  <ParticipantActions
195
195
  peerId={peer.id}
196
196
  peerType={peer.type}
197
- isLocal={peer.id === localPeerId}
198
197
  role={peer.roleName}
199
198
  isHandRaisedAccordion={isHandRaisedAccordion}
200
199
  />
@@ -273,12 +272,10 @@ const ParticipantActions = React.memo(
273
272
  peerId,
274
273
  peerType,
275
274
  role,
276
- isLocal,
277
275
  isHandRaisedAccordion,
278
276
  }: {
279
277
  peerId: string;
280
278
  role: string;
281
- isLocal: boolean;
282
279
  isHandRaisedAccordion?: boolean;
283
280
  peerType: HMSPeerType;
284
281
  }) => {
@@ -331,7 +328,7 @@ const ParticipantActions = React.memo(
331
328
  </Flex>
332
329
  ) : null}
333
330
 
334
- {shouldShowMoreActions && !isLocal ? <ParticipantMoreActions peerId={peerId} role={role} /> : null}
331
+ {shouldShowMoreActions ? <ParticipantMoreActions peerId={peerId} role={role} /> : null}
335
332
  </>
336
333
  )}
337
334
  </Flex>
@@ -28,8 +28,11 @@ import { Checkbox, Dropdown, Flex, Switch, Text, Tooltip } from '../../../..';
28
28
  import IconButton from '../../../IconButton';
29
29
  // @ts-ignore: No implicit any
30
30
  import { PIP } from '../../PIP';
31
+ import { PIPChat } from '../../PIP/PIPChat';
31
32
  // @ts-ignore: No implicit any
33
+ import { PIPChatOption } from '../../PIP/PIPChatOption';
32
34
  import { PictureInPicture } from '../../PIP/PIPManager';
35
+ import { PIPWindow } from '../../PIP/PIPWindow';
33
36
  // @ts-ignore: No implicit any
34
37
  import { RoleChangeModal } from '../../RoleChangeModal';
35
38
  // @ts-ignore: No implicit any
@@ -45,10 +48,14 @@ import { CaptionModal } from '../CaptionModal';
45
48
  import { FullScreenItem } from '../FullScreenItem';
46
49
  import { MuteAllModal } from '../MuteAllModal';
47
50
  // @ts-ignore: No implicit any
51
+ import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../../AppData/useSidepane';
52
+ // @ts-ignore: No implicit any
48
53
  import { useDropdownList } from '../../hooks/useDropdownList';
49
54
  import { useMyMetadata } from '../../hooks/useMetadata';
50
55
  // @ts-ignore: No implicit any
51
- import { APP_DATA, isMacOS } from '../../../common/constants';
56
+ import { usePIPChat } from '../../PIP/usePIPChat';
57
+ // @ts-ignore: No implicit any
58
+ import { APP_DATA, isMacOS, SIDE_PANE_OPTIONS } from '../../../common/constants';
52
59
 
53
60
  const MODALS = {
54
61
  CHANGE_NAME: 'changeName',
@@ -79,6 +86,10 @@ export const DesktopOptions = ({
79
86
  const isBRBEnabled = !!elements?.brb;
80
87
  const isTranscriptionAllowed = useHMSStore(selectIsTranscriptionAllowedByMode(HMSTranscriptionMode.CAPTION));
81
88
  const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
89
+ const { isSupported, pipWindow, requestPipWindow } = usePIPChat();
90
+ const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
91
+ const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
92
+ const showPipChatOption = !!elements?.chat && isSupported;
82
93
 
83
94
  useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' });
84
95
 
@@ -98,6 +109,11 @@ export const DesktopOptions = ({
98
109
 
99
110
  return (
100
111
  <Fragment>
112
+ {isSupported && pipWindow ? (
113
+ <PIPWindow pipWindow={pipWindow}>
114
+ <PIPChat />
115
+ </PIPWindow>
116
+ ) : null}
101
117
  <Dropdown.Root
102
118
  open={openModals.has(MODALS.MORE_SETTINGS)}
103
119
  onOpenChange={value => updateState(MODALS.MORE_SETTINGS, value)}
@@ -168,13 +184,15 @@ export const DesktopOptions = ({
168
184
  </Dropdown.Item>
169
185
  ) : null}
170
186
 
187
+ <PIPChatOption
188
+ showPIPChat={showPipChatOption}
189
+ openChat={async () => {
190
+ isChatOpen && toggleChat();
191
+ await requestPipWindow(350, 500);
192
+ }}
193
+ />
171
194
  <FullScreenItem />
172
- {/* {isAllowedToPublish.screen && isEmbedEnabled && (
173
- <EmbedUrl setShowOpenUrl={() => updateState(MODALS.EMBED_URL, true)} />
174
- )} */}
175
-
176
195
  <Dropdown.ItemSeparator css={{ mx: 0 }} />
177
-
178
196
  <Dropdown.Item onClick={() => updateState(MODALS.DEVICE_SETTINGS, true)} data-testid="device_settings_btn">
179
197
  <SettingsIcon />
180
198
  <Text variant="sm" css={{ ml: '$4' }}>
@@ -1,14 +1,19 @@
1
1
  import { useEffect } from 'react';
2
+ import { useDebounce } from 'react-use';
2
3
  import {
3
4
  HMSNotificationTypes,
4
5
  HMSRoomState,
6
+ selectHandRaisedPeers,
5
7
  selectHasPeerHandRaised,
8
+ selectIsLocalScreenShared,
6
9
  selectPeerByID,
7
10
  selectRoomState,
11
+ useAwayNotifications,
8
12
  useHMSNotifications,
9
13
  useHMSStore,
10
14
  useHMSVanillaStore,
11
15
  } from '@100mslive/react-sdk';
16
+ import { useRoomLayout } from '../../provider/roomLayoutProvider';
12
17
  // @ts-ignore: No implicit Any
13
18
  import { ToastBatcher } from '../Toast/ToastBatcher';
14
19
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
@@ -22,6 +27,9 @@ export const HandRaisedNotifications = () => {
22
27
  const vanillaStore = useHMSVanillaStore();
23
28
  const { on_stage_exp } = useRoomLayoutConferencingScreen().elements || {};
24
29
  const isSubscribing = !!useSubscribedNotifications(SUBSCRIBED_NOTIFICATIONS.METADATA_UPDATED);
30
+ const amIScreenSharing = useHMSStore(selectIsLocalScreenShared);
31
+ const { showNotification } = useAwayNotifications();
32
+ const logoURL = useRoomLayout()?.logo?.url;
25
33
 
26
34
  useEffect(() => {
27
35
  if (!notification?.data) {
@@ -32,6 +40,7 @@ export const HandRaisedNotifications = () => {
32
40
  if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
33
41
  return;
34
42
  }
43
+
35
44
  const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
36
45
  const peer = vanillaStore.getState(selectPeerByID(notification.data.id));
37
46
  if (hasPeerHandRaised) {
@@ -41,5 +50,29 @@ export const HandRaisedNotifications = () => {
41
50
  }
42
51
  }, [isSubscribing, notification, on_stage_exp, roomState, vanillaStore]);
43
52
 
53
+ useDebounce(
54
+ () => {
55
+ if (!notification?.data) {
56
+ return;
57
+ }
58
+
59
+ // Don't show toast message in case of local peer.
60
+ if (roomState !== HMSRoomState.Connected || notification.data.isLocal || !isSubscribing) {
61
+ return;
62
+ }
63
+
64
+ const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
65
+ const peer = vanillaStore.getState(selectPeerByID(notification.data.id));
66
+ const handRaisedPeers = vanillaStore.getState(selectHandRaisedPeers);
67
+ if (amIScreenSharing && hasPeerHandRaised) {
68
+ const title = `${peer?.name} ${
69
+ handRaisedPeers.length > 1 ? `and ${handRaisedPeers.length - 1} others` : ''
70
+ } raised hand`;
71
+ showNotification(title, { icon: logoURL });
72
+ }
73
+ },
74
+ 1000,
75
+ [isSubscribing, notification, roomState, vanillaStore, amIScreenSharing],
76
+ );
44
77
  return null;
45
78
  };
@@ -35,6 +35,7 @@ import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvid
35
35
  import { usePollViewToggle } from '../AppData/useSidepane';
36
36
  // @ts-ignore: No implicit Any
37
37
  import { useIsNotificationDisabled, useSubscribedNotifications } from '../AppData/useUISettings';
38
+ import { usePIPWindow } from '../PIP/usePIPWindow';
38
39
  import { ROLE_CHANGE_DECLINED } from '../../common/constants';
39
40
 
40
41
  const pollToastKey: Record<string, string> = {};
@@ -52,6 +53,7 @@ export function Notifications() {
52
53
  const { showNotification } = useAwayNotifications();
53
54
  const amIScreenSharing = useHMSStore(selectIsLocalScreenShared);
54
55
  const logoURL = useRoomLayout()?.logo?.url;
56
+ const { pipWindow } = usePIPWindow();
55
57
 
56
58
  const handleRoleChangeDenied = useCallback((request: HMSRoleChangeRequest & { peerName: string }) => {
57
59
  ToastManager.addToast({
@@ -172,7 +174,7 @@ export function Notifications() {
172
174
  }
173
175
  break;
174
176
  case HMSNotificationTypes.NEW_MESSAGE:
175
- if (amIScreenSharing && !notification.data?.ignored) {
177
+ if (amIScreenSharing && !notification.data?.ignored && !pipWindow) {
176
178
  showNotification(`New message from ${notification.data.senderName}`, {
177
179
  body: notification.data.message,
178
180
  icon: logoURL,