@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.
- package/dist/{HLSView-4NSE37G7.js → HLSView-F5BDZVT2.js} +22 -4
- package/dist/HLSView-F5BDZVT2.js.map +7 -0
- package/dist/{VirtualBackground-A5UM363O.js → VirtualBackground-THDRYDRA.js} +3 -3
- package/dist/{chunk-Q6U22HIE.js → chunk-CDYRVICT.js} +189 -174
- package/dist/chunk-CDYRVICT.js.map +7 -0
- package/dist/{chunk-BUWIMYLW.js → chunk-JSH7SKEH.js} +2 -2
- package/dist/{chunk-NMOZ33TX.js → chunk-U3G743OY.js} +3 -2
- package/dist/{chunk-NMOZ33TX.js.map → chunk-U3G743OY.js.map} +2 -2
- package/dist/{conference-S7R3O4OC.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-4NSE37G7.js.map +0 -7
- package/dist/chunk-Q6U22HIE.js.map +0 -7
- package/dist/conference-S7R3O4OC.js.map +0 -7
- /package/dist/{VirtualBackground-A5UM363O.js.map → VirtualBackground-THDRYDRA.js.map} +0 -0
- /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
|
-
{
|
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 = [
|