@100mslive/roomkit-react 0.1.6-alpha.3 → 0.1.7-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. package/dist/{HLSView-HL455FYH.js → HLSView-F5BDZVT2.js} +22 -4
  2. package/dist/HLSView-F5BDZVT2.js.map +7 -0
  3. package/dist/{VirtualBackground-6EP3X7MO.js → VirtualBackground-THDRYDRA.js} +3 -3
  4. package/dist/{chunk-6JF3GAOH.js → chunk-CDYRVICT.js} +189 -174
  5. package/dist/chunk-CDYRVICT.js.map +7 -0
  6. package/dist/{chunk-UXBTLGWY.js → chunk-JSH7SKEH.js} +2 -2
  7. package/dist/{chunk-KAJJ56J4.js → chunk-U3G743OY.js} +3 -2
  8. package/dist/{chunk-KAJJ56J4.js.map → chunk-U3G743OY.js.map} +2 -2
  9. package/dist/{conference-MPZNWHV5.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-HL455FYH.js.map +0 -7
  36. package/dist/chunk-6JF3GAOH.js.map +0 -7
  37. package/dist/conference-MPZNWHV5.js.map +0 -7
  38. /package/dist/{VirtualBackground-6EP3X7MO.js.map → VirtualBackground-THDRYDRA.js.map} +0 -0
  39. /package/dist/{chunk-UXBTLGWY.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 = [