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

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 (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,