@100mslive/roomkit-react 0.1.6 → 0.1.7-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 (39) hide show
  1. package/dist/{HLSView-4NSE37G7.js → HLSView-F5BDZVT2.js} +22 -4
  2. package/dist/HLSView-F5BDZVT2.js.map +7 -0
  3. package/dist/{VirtualBackground-A5UM363O.js → VirtualBackground-THDRYDRA.js} +3 -3
  4. package/dist/{chunk-Q6U22HIE.js → chunk-CDYRVICT.js} +189 -174
  5. package/dist/chunk-CDYRVICT.js.map +7 -0
  6. package/dist/{chunk-BUWIMYLW.js → chunk-JSH7SKEH.js} +2 -2
  7. package/dist/{chunk-NMOZ33TX.js → chunk-U3G743OY.js} +3 -2
  8. package/dist/{chunk-NMOZ33TX.js.map → chunk-U3G743OY.js.map} +2 -2
  9. package/dist/{conference-S7R3O4OC.js → conference-6IVZHILI.js} +89 -75
  10. package/dist/conference-6IVZHILI.js.map +7 -0
  11. package/dist/index.cjs.js +332 -281
  12. package/dist/index.cjs.js.map +4 -4
  13. package/dist/index.js +2 -2
  14. package/dist/meta.cjs.json +78 -63
  15. package/dist/meta.esbuild.json +111 -97
  16. package/package.json +6 -6
  17. package/src/Prebuilt/common/hooks.js +1 -2
  18. package/src/Prebuilt/common/utils.js +0 -2
  19. package/src/Prebuilt/components/Chat/ChatFooter.tsx +1 -0
  20. package/src/Prebuilt/components/Footer/Footer.tsx +4 -1
  21. package/src/Prebuilt/components/Footer/ParticipantList.jsx +7 -8
  22. package/src/Prebuilt/components/Header/ParticipantFilter.jsx +9 -12
  23. package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +4 -2
  24. package/src/Prebuilt/components/Notifications/Notifications.jsx +14 -1
  25. package/src/Prebuilt/components/Notifications/PeerNotifications.jsx +4 -15
  26. package/src/Prebuilt/components/Preview/PreviewJoin.tsx +8 -3
  27. package/src/Prebuilt/components/RaiseHand.jsx +10 -6
  28. package/src/Prebuilt/components/RoleChangeRequestModal.tsx +3 -2
  29. package/src/Prebuilt/components/SidePaneTabs.tsx +21 -2
  30. package/src/Prebuilt/components/VideoTile.jsx +6 -3
  31. package/src/Prebuilt/components/hooks/useMetadata.jsx +14 -4
  32. package/src/Prebuilt/layouts/HLSView.jsx +19 -1
  33. package/src/Tooltip/Tooltip.tsx +1 -1
  34. package/src/fixtures/peers.ts +5 -3
  35. package/dist/HLSView-4NSE37G7.js.map +0 -7
  36. package/dist/chunk-Q6U22HIE.js.map +0 -7
  37. package/dist/conference-S7R3O4OC.js.map +0 -7
  38. /package/dist/{VirtualBackground-A5UM363O.js.map → VirtualBackground-THDRYDRA.js.map} +0 -0
  39. /package/dist/{chunk-BUWIMYLW.js.map → chunk-JSH7SKEH.js.map} +0 -0
@@ -6,6 +6,7 @@ import {
6
6
  HLSLiveStreamingScreen_Elements,
7
7
  } from '@100mslive/types-prebuilt';
8
8
  import { Chat_ChatState } from '@100mslive/types-prebuilt/elements/chat';
9
+ import { useAVToggle } from '@100mslive/react-sdk';
9
10
  import { config as cssConfig, Footer as AppFooter } from '../../..';
10
11
  // @ts-ignore: No implicit Any
11
12
  import { AudioVideoToggle } from '../AudioVideoToggle';
@@ -41,6 +42,8 @@ export const Footer = ({
41
42
  const isOverlayChat = !!elements?.chat?.is_overlay;
42
43
  const openByDefault = elements?.chat?.initial_state === Chat_ChatState.CHAT_STATE_OPEN;
43
44
 
45
+ const { toggleAudio, toggleVideo } = useAVToggle();
46
+ const noAVPermissions = !(toggleAudio || toggleVideo);
44
47
  const isChatOpen = useIsSidepaneTypeOpen(SIDE_PANE_OPTIONS.CHAT);
45
48
  const toggleChat = useSidepaneToggle(SIDE_PANE_OPTIONS.CHAT);
46
49
 
@@ -91,7 +94,7 @@ export const Footer = ({
91
94
  >
92
95
  {isMobile ? (
93
96
  <>
94
- {screenType === 'hls_live_streaming' ? <RaiseHand /> : null}
97
+ {noAVPermissions ? <RaiseHand /> : null}
95
98
  {elements?.chat && <ChatToggle />}
96
99
  <MoreSettings elements={elements} screenType={screenType} />
97
100
  </>
@@ -1,11 +1,12 @@
1
1
  import React, { Fragment, useCallback, useEffect, useState } from 'react';
2
2
  import { useDebounce, useMedia } from 'react-use';
3
3
  import {
4
+ selectHandRaisedPeers,
5
+ selectHasPeerHandRaised,
4
6
  selectIsPeerAudioEnabled,
5
7
  selectLocalPeerID,
6
8
  selectPeerCount,
7
9
  selectPeerMetadata,
8
- selectPeersByCondition,
9
10
  selectPermissions,
10
11
  useHMSActions,
11
12
  useHMSStore,
@@ -27,7 +28,7 @@ import { RoleAccordion } from './RoleAccordion';
27
28
  import { useRoomLayoutConferencingScreen } from '../../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
28
29
  import { useIsSidepaneTypeOpen, useSidepaneToggle } from '../AppData/useSidepane';
29
30
  import { useParticipants } from '../../common/hooks';
30
- import { isInternalRole } from '../../common/utils';
31
+ import { getFormattedCount } from '../../common/utils';
31
32
  import { SIDE_PANE_OPTIONS } from '../../common/constants';
32
33
 
33
34
  export const ParticipantList = () => {
@@ -35,7 +36,7 @@ export const ParticipantList = () => {
35
36
  const { participants, isConnected, peerCount } = useParticipants(filter);
36
37
  const peersOrderedByRoles = {};
37
38
 
38
- const handRaisedPeers = useHMSStore(selectPeersByCondition(peer => JSON.parse(peer.metadata || '{}')?.isHandRaised));
39
+ const handRaisedPeers = useHMSStore(selectHandRaisedPeers);
39
40
 
40
41
  participants.forEach(participant => {
41
42
  if (peersOrderedByRoles[participant.roleName] === undefined) {
@@ -107,7 +108,7 @@ export const ParticipantCount = () => {
107
108
  >
108
109
  <PeopleIcon />
109
110
  <Text variant="sm" css={{ mx: '$4', c: 'inherit' }}>
110
- {peerCount}
111
+ {getFormattedCount(peerCount)}
111
112
  </Text>
112
113
  </IconButton>
113
114
  );
@@ -176,7 +177,7 @@ export const Participant = ({ peer, isConnected }) => {
176
177
  * shows settings to change for a participant like changing their role
177
178
  */
178
179
  const ParticipantActions = React.memo(({ peerId, role, isLocal }) => {
179
- const isHandRaised = useHMSStore(selectPeerMetadata(peerId))?.isHandRaised;
180
+ const isHandRaised = useHMSStore(selectHasPeerHandRaised(peerId));
180
181
  const canChangeRole = useHMSStore(selectPermissions)?.changeRole;
181
182
  const shouldShowMoreActions = canChangeRole;
182
183
  const isAudioMuted = !useHMSStore(selectIsPeerAudioEnabled(peerId));
@@ -209,9 +210,7 @@ const ParticipantActions = React.memo(({ peerId, role, isLocal }) => {
209
210
  </Flex>
210
211
  ) : null}
211
212
 
212
- {shouldShowMoreActions && !isInternalRole(role) && !isLocal ? (
213
- <ParticipantMoreActions peerId={peerId} role={role} />
214
- ) : null}
213
+ {shouldShowMoreActions && !isLocal ? <ParticipantMoreActions peerId={peerId} role={role} /> : null}
215
214
  </Flex>
216
215
  );
217
216
  });
@@ -1,7 +1,6 @@
1
1
  import React, { useCallback, useState } from 'react';
2
2
  import { CheckIcon, ChevronDownIcon, ChevronUpIcon, HandRaiseIcon, PeopleIcon } from '@100mslive/react-icons';
3
3
  import { Box, Dropdown, Flex, Text, textEllipsis } from '../../../';
4
- import { isInternalRole } from '../../common/utils';
5
4
 
6
5
  export const ParticipantFilter = ({ selection, onSelection, isConnected, roles }) => {
7
6
  const [open, setOpen] = useState(false);
@@ -53,17 +52,15 @@ export const ParticipantFilter = ({ selection, onSelection, isConnected, roles }
53
52
  value={{ metadata: { isHandRaised: true }, role: '' }}
54
53
  />
55
54
  <Dropdown.ItemSeparator />
56
- {roles
57
- .filter(role => !isInternalRole(role))
58
- .map(role => (
59
- <Item
60
- key={role}
61
- selected={selectionValue === role}
62
- title={role}
63
- value={{ metadata: { isHandRaised: false }, role }}
64
- onSelection={onItemClick}
65
- />
66
- ))}
55
+ {roles.map(role => (
56
+ <Item
57
+ key={role}
58
+ selected={selectionValue === role}
59
+ title={role}
60
+ value={{ metadata: { isHandRaised: false }, role }}
61
+ onSelection={onItemClick}
62
+ />
63
+ ))}
67
64
  </Dropdown.Content>
68
65
  </Dropdown.Root>
69
66
  );
@@ -5,6 +5,7 @@ import {
5
5
  selectIsConnectedToRoom,
6
6
  selectPeerCount,
7
7
  selectPermissions,
8
+ useAVToggle,
8
9
  useHMSActions,
9
10
  useHMSStore,
10
11
  useRecordingStreaming,
@@ -84,6 +85,8 @@ export const MwebOptions = ({
84
85
  const peerCount = useHMSStore(selectPeerCount);
85
86
  const emojiCardRef = useRef(null);
86
87
  const { isBRBOn, toggleBRB, isHandRaised, toggleHandRaise } = useMyMetadata();
88
+ const { toggleAudio, toggleVideo } = useAVToggle();
89
+ const noAVPermissions = !(toggleAudio || toggleVideo);
87
90
  // const isVideoOn = useHMSStore(selectIsLocalVideoEnabled);
88
91
 
89
92
  useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' });
@@ -158,7 +161,7 @@ export const MwebOptions = ({
158
161
  </ActionTile.Root>
159
162
  )}
160
163
 
161
- {screenType !== 'hls_live_streaming' ? (
164
+ {!noAVPermissions ? (
162
165
  <ActionTile.Root
163
166
  active={isHandRaised}
164
167
  onClick={() => {
@@ -279,7 +282,6 @@ export const MwebOptions = ({
279
282
 
280
283
  {showEmojiCard && (
281
284
  <Box
282
- onClick={() => setShowEmojiCard(false)}
283
285
  ref={emojiCardRef}
284
286
  css={{
285
287
  maxWidth: '100%',
@@ -4,10 +4,12 @@ import { useNavigate, useParams } from 'react-router-dom';
4
4
  import {
5
5
  HMSNotificationTypes,
6
6
  HMSRoomState,
7
+ selectHasPeerHandRaised,
7
8
  selectRoomState,
8
9
  useCustomEvent,
9
10
  useHMSNotifications,
10
11
  useHMSStore,
12
+ useHMSVanillaStore,
11
13
  } from '@100mslive/react-sdk';
12
14
  import { Button } from '../../../';
13
15
  import { useUpdateRoomLayout } from '../../provider/roomLayoutProvider';
@@ -34,6 +36,7 @@ export function Notifications() {
34
36
  const updateRoomLayoutForRole = useUpdateRoomLayout();
35
37
  const isNotificationDisabled = useIsNotificationDisabled();
36
38
  const { redirectToLeave } = useRedirectToLeave();
39
+ const vanillaStore = useHMSVanillaStore();
37
40
 
38
41
  const handleRoleChangeDenied = useCallback(request => {
39
42
  ToastManager.addToast({
@@ -49,6 +52,16 @@ export function Notifications() {
49
52
  return;
50
53
  }
51
54
  switch (notification.type) {
55
+ case HMSNotificationTypes.HAND_RAISE_CHANGED: {
56
+ if (roomState !== HMSRoomState.Connected || notification.data.isLocal) {
57
+ return;
58
+ }
59
+ const hasPeerHandRaised = vanillaStore.getState(selectHasPeerHandRaised(notification.data.id));
60
+ if (hasPeerHandRaised) {
61
+ ToastBatcher.showToast({ notification, type: 'RAISE_HAND' });
62
+ }
63
+ break;
64
+ }
52
65
  case HMSNotificationTypes.METADATA_UPDATED:
53
66
  if (roomState !== HMSRoomState.Connected) {
54
67
  return;
@@ -154,7 +167,7 @@ export function Notifications() {
154
167
  <TrackUnmuteModal />
155
168
  <TrackBulkUnmuteModal />
156
169
  <TrackNotifications />
157
- <PeerNotifications />
170
+ {roomState === HMSRoomState.Connected ? <PeerNotifications /> : null}
158
171
  <ReconnectNotifications />
159
172
  <AutoplayBlockedModal />
160
173
  <PermissionErrorModal />
@@ -1,14 +1,7 @@
1
1
  import { useEffect } from 'react';
2
- import {
3
- HMSNotificationTypes,
4
- HMSRoomState,
5
- selectRoomState,
6
- useHMSNotifications,
7
- useHMSStore,
8
- } from '@100mslive/react-sdk';
2
+ import { HMSNotificationTypes, useHMSNotifications } from '@100mslive/react-sdk';
9
3
  import { ToastBatcher } from '../Toast/ToastBatcher';
10
4
  import { useSubscribedNotifications } from '../AppData/useUISettings';
11
- import { isInternalRole } from '../../common/utils';
12
5
  import { SUBSCRIBED_NOTIFICATIONS } from '../../common/constants';
13
6
 
14
7
  const notificationTypes = [
@@ -21,19 +14,15 @@ export const PeerNotifications = () => {
21
14
  const notification = useHMSNotifications(notificationTypes);
22
15
  const isPeerJoinSubscribed = useSubscribedNotifications(SUBSCRIBED_NOTIFICATIONS.PEER_JOINED);
23
16
  const isPeerLeftSubscribed = useSubscribedNotifications(SUBSCRIBED_NOTIFICATIONS.PEER_LEFT);
24
- const roomState = useHMSStore(selectRoomState);
25
17
  useEffect(() => {
26
- if (roomState !== HMSRoomState.Connected) {
27
- return;
28
- }
29
- if (!notification || (notification?.data?.roleName && isInternalRole(notification.data.roleName))) {
18
+ if (!notification?.data) {
30
19
  return;
31
20
  }
32
21
 
33
22
  console.debug(`[${notification.type}]`, notification);
34
23
  switch (notification.type) {
35
24
  case HMSNotificationTypes.PEER_LIST:
36
- if (!isPeerJoinSubscribed || notification.data?.length === 0) {
25
+ if (!isPeerJoinSubscribed || notification.data.length === 0) {
37
26
  return;
38
27
  }
39
28
  break;
@@ -52,7 +41,7 @@ export const PeerNotifications = () => {
52
41
  }
53
42
 
54
43
  ToastBatcher.showToast({ notification });
55
- }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed, roomState]);
44
+ }, [notification, isPeerJoinSubscribed, isPeerLeftSubscribed]);
56
45
 
57
46
  return null;
58
47
  };
@@ -105,7 +105,11 @@ const PreviewJoin = ({
105
105
  const roomLayout = useRoomLayout();
106
106
 
107
107
  const { preview_header: previewHeader = {} } = roomLayout?.screens?.preview?.default?.elements || {};
108
-
108
+ const localPeer = useHMSStore(selectLocalPeer);
109
+ const videoTrack = useHMSStore(selectVideoTrackByID(localPeer?.videoTrack));
110
+ const isMobile = useMedia(cssConfig.media.md);
111
+ const aspectRatio =
112
+ videoTrack?.width && videoTrack?.height ? videoTrack.width / videoTrack.height : isMobile ? 9 / 16 : 16 / 9;
109
113
  useEffect(() => {
110
114
  if (authToken) {
111
115
  if (skipPreview) {
@@ -166,7 +170,7 @@ const PreviewJoin = ({
166
170
  <PreviewTile name={name} error={previewError} />
167
171
  </Flex>
168
172
  ) : null}
169
- <Box css={{ w: '100%', maxWidth: '640px' }}>
173
+ <Box css={{ w: '100%', maxWidth: `${aspectRatio * 360}px` }}>
170
174
  <PreviewControls hideSettings={!toggleVideo && !toggleAudio} />
171
175
  <PreviewForm
172
176
  name={name}
@@ -202,12 +206,13 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
202
206
  const isMobile = useMedia(cssConfig.media.md);
203
207
  const aspectRatio =
204
208
  videoTrack?.width && videoTrack?.height ? videoTrack.width / videoTrack.height : isMobile ? 9 / 16 : 16 / 9;
209
+
205
210
  return (
206
211
  <StyledVideoTile.Container
207
212
  css={{
208
213
  bg: '$surface_default',
209
214
  aspectRatio,
210
- height: 'min(640px, 40vh)',
215
+ height: 'min(360px, 70vh)',
211
216
  maxWidth: '640px',
212
217
  overflow: 'clip',
213
218
  '@md': {
@@ -1,18 +1,22 @@
1
1
  import React from 'react';
2
- import { selectLocalPeer, selectPeerMetadata, useHMSStore } from '@100mslive/react-sdk';
2
+ import { selectHasPeerHandRaised, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
3
3
  import { HandIcon } from '@100mslive/react-icons';
4
4
  import { Tooltip } from '../../Tooltip';
5
5
  import IconButton from '../IconButton';
6
- import { useMyMetadata } from './hooks/useMetadata';
7
6
 
8
7
  export const RaiseHand = () => {
9
- const { toggleHandRaise } = useMyMetadata();
10
- const localPeer = useHMSStore(selectLocalPeer);
11
- const isHandRaised = useHMSStore(selectPeerMetadata(localPeer.id))?.isHandRaised || false;
8
+ const localPeerId = useHMSStore(selectLocalPeerID);
9
+ const isHandRaised = useHMSStore(selectHasPeerHandRaised(localPeerId));
10
+ const actions = useHMSActions();
12
11
 
13
12
  return (
14
13
  <Tooltip title={isHandRaised ? 'Lower hand' : 'Raise hand'}>
15
- <IconButton active={!isHandRaised} onClick={toggleHandRaise}>
14
+ <IconButton
15
+ active={!isHandRaised}
16
+ onClick={() => {
17
+ isHandRaised ? actions.lowerLocalPeerHand() : actions.raiseLocalPeerHand();
18
+ }}
19
+ >
16
20
  <HandIcon />
17
21
  </IconButton>
18
22
  </Tooltip>
@@ -64,13 +64,14 @@ export const RoleChangeRequestModal = () => {
64
64
  await hmsActions.rejectChangeRole(roleChangeRequest);
65
65
  sendEvent({ ...roleChangeRequest, peerName: name }, { peerId: roleChangeRequest.requestedBy?.id });
66
66
  await hmsActions.cancelMidCallPreview();
67
- await updateMetaData({ isHandRaised: false });
67
+ await hmsActions.lowerLocalPeerHand();
68
68
  }
69
69
  }}
70
70
  body={body}
71
71
  onAction={async () => {
72
72
  await hmsActions.acceptChangeRole(roleChangeRequest);
73
- await updateMetaData({ isHandRaised: false, prevRole: currentRole });
73
+ await updateMetaData({ prevRole: currentRole });
74
+ await hmsActions.lowerLocalPeerHand();
74
75
  }}
75
76
  actionText="Accept"
76
77
  />
@@ -8,11 +8,14 @@ import { Chat } from './Chat/Chat';
8
8
  // @ts-ignore: No implicit Any
9
9
  import { ParticipantList } from './Footer/ParticipantList';
10
10
  import { config as cssConfig, Flex, IconButton, Tabs, Text } from '../..';
11
+ import { Tooltip } from '../../Tooltip';
11
12
  // @ts-ignore: No implicit Any
12
13
  import { useRoomLayoutConferencingScreen } from '../provider/roomLayoutProvider/hooks/useRoomLayoutScreen';
13
14
  // @ts-ignore: No implicit Any
14
15
  import { useIsSidepaneTypeOpen, useSidepaneReset, useSidepaneToggle } from './AppData/useSidepane';
15
16
  // @ts-ignore: No implicit Any
17
+ import { getFormattedCount } from '../common/utils';
18
+ // @ts-ignore: No implicit Any
16
19
  import { SIDE_PANE_OPTIONS } from '../common/constants';
17
20
 
18
21
  const tabTriggerCSS = {
@@ -24,6 +27,16 @@ const tabTriggerCSS = {
24
27
  justifyContent: 'center',
25
28
  };
26
29
 
30
+ const ParticipantCount = ({ count }: { count: number }) => {
31
+ return count < 1000 ? (
32
+ <span>({count})</span>
33
+ ) : (
34
+ <Tooltip title={count}>
35
+ <span>({getFormattedCount(count)})</span>
36
+ </Tooltip>
37
+ );
38
+ };
39
+
27
40
  export const SidePaneTabs = React.memo<{
28
41
  active: 'Participants | Chat';
29
42
  screenType: keyof ConferencingScreen;
@@ -73,7 +86,13 @@ export const SidePaneTabs = React.memo<{
73
86
  {hideTabs ? (
74
87
  <>
75
88
  <Text variant="sm" css={{ fontWeight: '$semiBold', p: '$4', c: '$on_surface_high', pr: '$12' }}>
76
- {showChat ? 'Chat' : `Participants (${peerCount})`}
89
+ {showChat ? (
90
+ 'Chat'
91
+ ) : (
92
+ <span>
93
+ Participants <ParticipantCount count={peerCount} />
94
+ </span>
95
+ )}
77
96
  </Text>
78
97
 
79
98
  {showChat ? <Chat screenType={screenType} /> : <ParticipantList />}
@@ -106,7 +125,7 @@ export const SidePaneTabs = React.memo<{
106
125
  color: activeTab !== SIDE_PANE_OPTIONS.PARTICIPANTS ? '$on_surface_low' : '$on_surface_high',
107
126
  }}
108
127
  >
109
- Participants ({peerCount})
128
+ Participants <ParticipantCount count={peerCount} />
110
129
  </Tabs.Trigger>
111
130
  </Tabs.List>
112
131
  <Tabs.Content value={SIDE_PANE_OPTIONS.PARTICIPANTS} css={{ p: 0 }}>
@@ -1,6 +1,8 @@
1
1
  import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { useMedia } from 'react-use';
2
3
  import {
3
4
  selectAudioTrackByPeerID,
5
+ selectHasPeerHandRaised,
4
6
  selectIsPeerAudioEnabled,
5
7
  selectLocalPeerID,
6
8
  selectPeerMetadata,
@@ -18,7 +20,7 @@ import TileMenu, { isSameTile } from './TileMenu/TileMenu';
18
20
  import { Avatar } from '../../Avatar';
19
21
  import { Box, Flex } from '../../Layout';
20
22
  import { VideoTileStats } from '../../Stats';
21
- import { keyframes } from '../../Theme';
23
+ import { config as cssConfig, keyframes } from '../../Theme';
22
24
  import { Video } from '../../Video';
23
25
  import { StyledVideoTile } from '../../VideoTile';
24
26
  import { getVideoTileLabel } from './peerTileUtils';
@@ -43,6 +45,7 @@ const Tile = ({
43
45
  }) => {
44
46
  const trackSelector = trackId ? selectVideoTrackByID(trackId) : selectVideoTrackByPeerID(peerId);
45
47
  const track = useHMSStore(trackSelector);
48
+ const isMobile = useMedia(cssConfig.media.md);
46
49
  const peerName = useHMSStore(selectPeerNameByID(peerId));
47
50
  const audioTrack = useHMSStore(selectAudioTrackByPeerID(peerId));
48
51
  const localPeerID = useHMSStore(selectLocalPeerID);
@@ -138,7 +141,7 @@ const Tile = ({
138
141
  <AudioLevel trackId={audioTrack?.id} />
139
142
  )
140
143
  ) : null}
141
- {isMouseHovered || isDragabble ? (
144
+ {isMouseHovered || (isDragabble && isMobile) ? (
142
145
  <TileMenu
143
146
  peerID={peerId}
144
147
  audioTrackID={audioTrack?.id}
@@ -217,8 +220,8 @@ export const AudioLevel = ({ trackId }) => {
217
220
 
218
221
  const PeerMetadata = ({ peerId }) => {
219
222
  const metaData = useHMSStore(selectPeerMetadata(peerId));
220
- const isHandRaised = metaData?.isHandRaised || false;
221
223
  const isBRB = metaData?.isBRBOn || false;
224
+ const isHandRaised = useHMSStore(selectHasPeerHandRaised(peerId));
222
225
 
223
226
  return (
224
227
  <Fragment>
@@ -1,5 +1,6 @@
1
1
  import { useCallback } from 'react';
2
2
  import {
3
+ selectHasPeerHandRaised,
3
4
  selectLocalPeerID,
4
5
  selectPeerMetadata,
5
6
  useHMSActions,
@@ -12,6 +13,7 @@ export const useMyMetadata = () => {
12
13
  const localPeerId = useHMSStore(selectLocalPeerID);
13
14
  const vanillaStore = useHMSVanillaStore();
14
15
  const metaData = useHMSStore(selectPeerMetadata(localPeerId));
16
+ const isHandRaised = useHMSStore(selectHasPeerHandRaised(localPeerId));
15
17
 
16
18
  const update = async updatedFields => {
17
19
  try {
@@ -25,11 +27,19 @@ export const useMyMetadata = () => {
25
27
  };
26
28
 
27
29
  const toggleHandRaise = useCallback(async () => {
28
- await update({ isHandRaised: !metaData?.isHandRaised, isBRBOn: false });
29
- }, [metaData?.isHandRaised]); //eslint-disable-line
30
+ if (isHandRaised) {
31
+ await hmsActions.lowerLocalPeerHand();
32
+ } else {
33
+ await hmsActions.raiseLocalPeerHand();
34
+ }
35
+ }, [isHandRaised]); //eslint-disable-line
30
36
 
31
37
  const toggleBRB = useCallback(async () => {
32
- await update({ isBRBOn: !metaData?.isBRBOn, isHandRaised: false });
38
+ const newValue = !metaData?.isBRBOn;
39
+ await update({ isBRBOn: !metaData?.isBRBOn });
40
+ if (newValue) {
41
+ await hmsActions.lowerLocalPeerHand();
42
+ }
33
43
  }, [metaData?.isBRBOn]); //eslint-disable-line
34
44
 
35
45
  const setPrevRole = async role => {
@@ -39,7 +49,7 @@ export const useMyMetadata = () => {
39
49
  };
40
50
 
41
51
  return {
42
- isHandRaised: !!metaData?.isHandRaised,
52
+ isHandRaised,
43
53
  isBRBOn: !!metaData?.isBRBOn,
44
54
  metaData,
45
55
  updateMetaData: update,
@@ -3,7 +3,7 @@ import { useFullscreen, useMedia, useToggle } from 'react-use';
3
3
  import { HLSPlaybackState, HMSHLSPlayer, HMSHLSPlayerEvents } from '@100mslive/hls-player';
4
4
  import screenfull from 'screenfull';
5
5
  import { selectAppData, selectHLSState, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
6
- import { ColoredHandIcon, ExpandIcon, RadioIcon, ShrinkIcon } from '@100mslive/react-icons';
6
+ import { ColoredHandIcon, ExpandIcon, PlayIcon, RadioIcon, ShrinkIcon } from '@100mslive/react-icons';
7
7
  import { HlsStatsOverlay } from '../components/HlsStatsOverlay';
8
8
  import { HMSVideoPlayer } from '../components/HMSVideo';
9
9
  import { FullScreenButton } from '../components/HMSVideo/FullscreenButton';
@@ -265,6 +265,24 @@ const HLSView = () => {
265
265
  onMouseMove={onHoverHandler}
266
266
  onMouseLeave={onHoverHandler}
267
267
  >
268
+ {isMobile && isPaused && (
269
+ <Box
270
+ css={{
271
+ position: 'absolute',
272
+ top: '40%',
273
+ left: '50%',
274
+ transform: 'translateY(-40%) translateX(-50%)',
275
+ padding: '$4 $14',
276
+ display: 'inline-flex',
277
+ r: '$0',
278
+ bg: '$primary_default',
279
+ }}
280
+ >
281
+ <IconButton onClick={async () => await hlsPlayer?.play()} data-testid="play_btn">
282
+ <PlayIcon width="60px" height="60px" />
283
+ </IconButton>
284
+ </Box>
285
+ )}
268
286
  <Flex
269
287
  ref={controlsRef}
270
288
  direction="column"
@@ -8,7 +8,7 @@ const TooltipBox = styled(BaseTooltip.Content, {
8
8
  borderRadius: '$2',
9
9
  padding: '$2 $4',
10
10
  fontSize: '$xs',
11
-
11
+ zIndex: 11,
12
12
  color: '$on_surface_high',
13
13
  backgroundColor: '$surface_bright',
14
14
  '@media (prefers-reduced-motion: no-preference)': {
@@ -1,17 +1,19 @@
1
1
  import { HMSPeerWithMuteStatus } from '@100mslive/hms-video-store';
2
2
 
3
3
  let counter = 1;
4
- export const makeFakeParticipant = (name: string, role = 'Student') => {
4
+ export const makeFakeParticipant = (name: string, role = 'Student'): HMSPeerWithMuteStatus => {
5
5
  return {
6
6
  peer: {
7
7
  id: String(counter++),
8
8
  name,
9
- role: role,
9
+ roleName: role,
10
10
  auxiliaryTracks: [],
11
11
  isLocal: counter === 1,
12
+ groups: [],
13
+ isHandRaised: false,
12
14
  },
13
15
  isAudioEnabled: false,
14
- } as HMSPeerWithMuteStatus;
16
+ };
15
17
  };
16
18
 
17
19
  export const fakeParticipants = [