@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.
- package/dist/{HLSView-HL455FYH.js → HLSView-F5BDZVT2.js} +22 -4
- package/dist/HLSView-F5BDZVT2.js.map +7 -0
- package/dist/{VirtualBackground-6EP3X7MO.js → VirtualBackground-THDRYDRA.js} +3 -3
- package/dist/{chunk-6JF3GAOH.js → chunk-CDYRVICT.js} +189 -174
- package/dist/chunk-CDYRVICT.js.map +7 -0
- package/dist/{chunk-UXBTLGWY.js → chunk-JSH7SKEH.js} +2 -2
- package/dist/{chunk-KAJJ56J4.js → chunk-U3G743OY.js} +3 -2
- package/dist/{chunk-KAJJ56J4.js.map → chunk-U3G743OY.js.map} +2 -2
- package/dist/{conference-MPZNWHV5.js → conference-6IVZHILI.js} +89 -75
- package/dist/conference-6IVZHILI.js.map +7 -0
- package/dist/index.cjs.js +332 -281
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +2 -2
- package/dist/meta.cjs.json +78 -63
- package/dist/meta.esbuild.json +111 -97
- package/package.json +6 -6
- package/src/Prebuilt/common/hooks.js +1 -2
- package/src/Prebuilt/common/utils.js +0 -2
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +1 -0
- package/src/Prebuilt/components/Footer/Footer.tsx +4 -1
- package/src/Prebuilt/components/Footer/ParticipantList.jsx +7 -8
- package/src/Prebuilt/components/Header/ParticipantFilter.jsx +9 -12
- package/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx +4 -2
- package/src/Prebuilt/components/Notifications/Notifications.jsx +14 -1
- package/src/Prebuilt/components/Notifications/PeerNotifications.jsx +4 -15
- package/src/Prebuilt/components/Preview/PreviewJoin.tsx +8 -3
- package/src/Prebuilt/components/RaiseHand.jsx +10 -6
- package/src/Prebuilt/components/RoleChangeRequestModal.tsx +3 -2
- package/src/Prebuilt/components/SidePaneTabs.tsx +21 -2
- package/src/Prebuilt/components/VideoTile.jsx +6 -3
- package/src/Prebuilt/components/hooks/useMetadata.jsx +14 -4
- package/src/Prebuilt/layouts/HLSView.jsx +19 -1
- package/src/Tooltip/Tooltip.tsx +1 -1
- package/src/fixtures/peers.ts +5 -3
- package/dist/HLSView-HL455FYH.js.map +0 -7
- package/dist/chunk-6JF3GAOH.js.map +0 -7
- package/dist/conference-MPZNWHV5.js.map +0 -7
- /package/dist/{VirtualBackground-6EP3X7MO.js.map → VirtualBackground-THDRYDRA.js.map} +0 -0
- /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
|
-
{
|
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 {
|
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(
|
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(
|
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 && !
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
-
{
|
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 (
|
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
|
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
|
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:
|
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(
|
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 {
|
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
|
10
|
-
const
|
11
|
-
const
|
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
|
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
|
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({
|
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 ?
|
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
|
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
|
-
|
29
|
-
|
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
|
-
|
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
|
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"
|
package/src/Tooltip/Tooltip.tsx
CHANGED
package/src/fixtures/peers.ts
CHANGED
@@ -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
|
-
|
9
|
+
roleName: role,
|
10
10
|
auxiliaryTracks: [],
|
11
11
|
isLocal: counter === 1,
|
12
|
+
groups: [],
|
13
|
+
isHandRaised: false,
|
12
14
|
},
|
13
15
|
isAudioEnabled: false,
|
14
|
-
}
|
16
|
+
};
|
15
17
|
};
|
16
18
|
|
17
19
|
export const fakeParticipants = [
|