@100mslive/roomkit-react 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/{HLSView-4NSE37G7.js → HLSView-3S74KF3A.js} +23 -4
- package/dist/HLSView-3S74KF3A.js.map +7 -0
- package/dist/Prebuilt/components/RoleChangeRequest/RequestPrompt.d.ts +9 -0
- package/dist/VideoTile/StyledVideoTile.d.ts +445 -3
- package/dist/{VirtualBackground-A5UM363O.js → VirtualBackground-3TI5NA4V.js} +3 -3
- package/dist/{chunk-BUWIMYLW.js → chunk-36X4ZCLC.js} +2 -2
- package/dist/{chunk-NMOZ33TX.js → chunk-5DQ3WTED.js} +3 -2
- package/dist/{chunk-NMOZ33TX.js.map → chunk-5DQ3WTED.js.map} +2 -2
- package/dist/{chunk-Q6U22HIE.js → chunk-Z7P5WITU.js} +223 -200
- package/dist/chunk-Z7P5WITU.js.map +7 -0
- package/dist/{conference-S7R3O4OC.js → conference-JNABIZBG.js} +534 -504
- package/dist/conference-JNABIZBG.js.map +7 -0
- package/dist/index.cjs.js +1011 -924
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.js +2 -2
- package/dist/meta.cjs.json +241 -167
- package/dist/meta.esbuild.json +276 -203
- package/package.json +6 -6
- package/src/Input/Input.tsx +1 -1
- package/src/Prebuilt/common/hooks.js +1 -2
- package/src/Prebuilt/common/utils.js +7 -2
- package/src/Prebuilt/components/Chat/ChatBody.jsx +125 -106
- 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 +8 -9
- package/src/Prebuilt/components/Header/ParticipantFilter.jsx +9 -12
- package/src/Prebuilt/components/Leave/DesktopLeaveRoom.tsx +36 -44
- package/src/Prebuilt/components/Leave/MwebLeaveRoom.tsx +23 -35
- 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 +12 -5
- package/src/Prebuilt/components/RaiseHand.jsx +3 -6
- package/src/Prebuilt/components/RoleChangeRequest/RequestPrompt.tsx +66 -0
- package/src/Prebuilt/components/RoleChangeRequest/RoleChangeRequestModal.tsx +89 -0
- package/src/Prebuilt/components/SidePaneTabs.tsx +21 -2
- package/src/Prebuilt/components/VideoTile.jsx +24 -15
- package/src/Prebuilt/components/conference.jsx +1 -1
- package/src/Prebuilt/components/hooks/useMetadata.jsx +15 -4
- package/src/Prebuilt/layouts/HLSView.jsx +20 -1
- package/src/Prebuilt/layouts/SidePane.tsx +0 -1
- package/src/Tooltip/Tooltip.tsx +1 -1
- package/src/VideoTile/StyledVideoTile.tsx +10 -14
- 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/src/Prebuilt/components/RoleChangeRequestModal.tsx +0 -120
- /package/dist/Prebuilt/components/{RoleChangeRequestModal.d.ts → RoleChangeRequest/RoleChangeRequestModal.d.ts} +0 -0
- /package/dist/{VirtualBackground-A5UM363O.js.map → VirtualBackground-3TI5NA4V.js.map} +0 -0
- /package/dist/{chunk-BUWIMYLW.js.map → chunk-36X4ZCLC.js.map} +0 -0
@@ -30,6 +30,7 @@ export const MwebLeaveRoom = ({
|
|
30
30
|
const permissions = useHMSStore(selectPermissions);
|
31
31
|
const { isStreamingOn } = useRecordingStreaming();
|
32
32
|
const showStream = screenType !== 'hls_live_streaming' && isStreamingOn;
|
33
|
+
const showLeaveOptions = (permissions?.hlsStreaming && isStreamingOn) || permissions?.endRoom;
|
33
34
|
|
34
35
|
useDropdownList({ open, name: 'LeaveRoom' });
|
35
36
|
|
@@ -39,7 +40,7 @@ export const MwebLeaveRoom = ({
|
|
39
40
|
|
40
41
|
return (
|
41
42
|
<Fragment>
|
42
|
-
{
|
43
|
+
{showLeaveOptions ? (
|
43
44
|
<Sheet.Root open={open} onOpenChange={setOpen}>
|
44
45
|
<Sheet.Trigger asChild>
|
45
46
|
<LeaveIconButton
|
@@ -70,36 +71,24 @@ export const MwebLeaveRoom = ({
|
|
70
71
|
css={{ pt: 0, mt: '$10', color: '$on_surface_low', '&:hover': { color: '$on_surface_high' } }}
|
71
72
|
/>
|
72
73
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
/>
|
88
|
-
) : null}
|
74
|
+
<LeaveCard
|
75
|
+
title={showStream ? 'End Stream' : 'End Session'}
|
76
|
+
subtitle={`The will end the ${
|
77
|
+
showStream ? 'stream' : 'session'
|
78
|
+
} for everyone. You can't undo this action.`}
|
79
|
+
bg="$alert_error_dim"
|
80
|
+
titleColor="$alert_error_brighter"
|
81
|
+
css={{ color: '$alert_error_bright', '&:hover': { color: '$alert_error_brighter' } }}
|
82
|
+
icon={<StopIcon height={24} width={24} />}
|
83
|
+
onClick={() => {
|
84
|
+
setOpen(false);
|
85
|
+
setShowEndStreamAlert(true);
|
86
|
+
}}
|
87
|
+
/>
|
89
88
|
</Sheet.Content>
|
90
89
|
</Sheet.Root>
|
91
90
|
) : (
|
92
|
-
<LeaveIconButton
|
93
|
-
key="LeaveRoom"
|
94
|
-
data-testid="leave_room_btn"
|
95
|
-
onClick={() => {
|
96
|
-
if (screenType === 'hls_live_streaming') {
|
97
|
-
setShowLeaveRoomAlert(true);
|
98
|
-
} else {
|
99
|
-
leaveRoom({ endstream: false });
|
100
|
-
}
|
101
|
-
}}
|
102
|
-
>
|
91
|
+
<LeaveIconButton key="LeaveRoom" data-testid="leave_room_btn" onClick={() => setShowLeaveRoomAlert(true)}>
|
103
92
|
<Tooltip title="Leave Room">
|
104
93
|
<Box>
|
105
94
|
<ExitIcon style={{ transform: 'rotate(180deg)' }} />
|
@@ -116,13 +105,12 @@ export const MwebLeaveRoom = ({
|
|
116
105
|
/>
|
117
106
|
</Sheet.Content>
|
118
107
|
</Sheet.Root>
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
) : null}
|
108
|
+
|
109
|
+
<Sheet.Root open={showLeaveRoomAlert} onOpenChange={setShowLeaveRoomAlert}>
|
110
|
+
<Sheet.Content css={{ bg: '$surface_dim', p: '$10', pb: '$12' }}>
|
111
|
+
<LeaveSessionContent setShowLeaveRoomAlert={setShowLeaveRoomAlert} leaveRoom={leaveRoom} />
|
112
|
+
</Sheet.Content>
|
113
|
+
</Sheet.Root>
|
126
114
|
</Fragment>
|
127
115
|
);
|
128
116
|
};
|
@@ -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: `${Math.max(aspectRatio, 1) * 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': {
|
@@ -225,6 +230,7 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
|
|
225
230
|
trackId={localPeer.videoTrack}
|
226
231
|
data-testid="preview_tile"
|
227
232
|
/>
|
233
|
+
|
228
234
|
{!isVideoOn ? (
|
229
235
|
<StyledVideoTile.AvatarContainer>
|
230
236
|
<Avatar name={name} data-testid="preview_avatar_tile" />
|
@@ -234,8 +240,9 @@ export const PreviewTile = ({ name, error }: { name: string; error?: boolean })
|
|
234
240
|
) : !error ? (
|
235
241
|
<FullPageProgress />
|
236
242
|
) : null}
|
243
|
+
|
237
244
|
{showMuteIcon ? (
|
238
|
-
<StyledVideoTile.AudioIndicator
|
245
|
+
<StyledVideoTile.AudioIndicator>
|
239
246
|
<MicOffIcon />
|
240
247
|
</StyledVideoTile.AudioIndicator>
|
241
248
|
) : (
|
@@ -250,7 +257,7 @@ export const PreviewControls = ({ hideSettings }: { hideSettings: boolean }) =>
|
|
250
257
|
|
251
258
|
return (
|
252
259
|
<Flex
|
253
|
-
justify=
|
260
|
+
justify={hideSettings && isMobile ? 'center' : 'between'}
|
254
261
|
css={{
|
255
262
|
width: '100%',
|
256
263
|
mt: '$8',
|
@@ -1,18 +1,15 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import { selectLocalPeer, selectPeerMetadata, useHMSStore } from '@100mslive/react-sdk';
|
3
2
|
import { HandIcon } from '@100mslive/react-icons';
|
4
3
|
import { Tooltip } from '../../Tooltip';
|
5
4
|
import IconButton from '../IconButton';
|
5
|
+
// @ts-ignore: No implicit Any
|
6
6
|
import { useMyMetadata } from './hooks/useMetadata';
|
7
7
|
|
8
8
|
export const RaiseHand = () => {
|
9
|
-
const { toggleHandRaise } = useMyMetadata();
|
10
|
-
const localPeer = useHMSStore(selectLocalPeer);
|
11
|
-
const isHandRaised = useHMSStore(selectPeerMetadata(localPeer.id))?.isHandRaised || false;
|
12
|
-
|
9
|
+
const { isHandRaised, toggleHandRaise } = useMyMetadata();
|
13
10
|
return (
|
14
11
|
<Tooltip title={isHandRaised ? 'Lower hand' : 'Raise hand'}>
|
15
|
-
<IconButton active={!isHandRaised} onClick={toggleHandRaise}>
|
12
|
+
<IconButton active={!isHandRaised} onClick={async () => await toggleHandRaise()}>
|
16
13
|
<HandIcon />
|
17
14
|
</IconButton>
|
18
15
|
</Tooltip>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { useMedia } from 'react-use';
|
3
|
+
import { Box, Button, config as cssConfig, Dialog, Flex, Text } from '../../..';
|
4
|
+
import { Sheet } from '../../../Sheet';
|
5
|
+
|
6
|
+
export const RequestPrompt = ({
|
7
|
+
open = true,
|
8
|
+
onOpenChange,
|
9
|
+
title,
|
10
|
+
body,
|
11
|
+
actionText = 'Accept',
|
12
|
+
onAction,
|
13
|
+
}: {
|
14
|
+
open?: boolean;
|
15
|
+
onOpenChange: (value: boolean) => void;
|
16
|
+
title: string;
|
17
|
+
body: React.ReactNode;
|
18
|
+
actionText?: string;
|
19
|
+
onAction: () => void;
|
20
|
+
}) => {
|
21
|
+
const isMobile = useMedia(cssConfig.media.md);
|
22
|
+
|
23
|
+
if (isMobile) {
|
24
|
+
return (
|
25
|
+
<Sheet.Root open={open} onOpenChange={onOpenChange}>
|
26
|
+
<Sheet.Content css={{ py: '$8' }}>
|
27
|
+
<Text css={{ fontWeight: '$semiBold', c: '$on_surface_high', '@md': { px: '$8' } }}>{title}</Text>
|
28
|
+
{body}
|
29
|
+
<RequestActions actionText={actionText} onAction={onAction} />
|
30
|
+
</Sheet.Content>
|
31
|
+
</Sheet.Root>
|
32
|
+
);
|
33
|
+
}
|
34
|
+
|
35
|
+
return (
|
36
|
+
<Dialog.Root open={open} onOpenChange={onOpenChange}>
|
37
|
+
<Dialog.Portal>
|
38
|
+
<Dialog.Overlay />
|
39
|
+
<Dialog.Content css={{ p: '$10' }}>
|
40
|
+
<Dialog.Title css={{ p: 0, display: 'flex', flexDirection: 'row', gap: '$md', justifyContent: 'center' }}>
|
41
|
+
<Text variant="h6">{title}</Text>
|
42
|
+
</Dialog.Title>
|
43
|
+
<Box css={{ mt: '$4', mb: '$10' }}>{body}</Box>
|
44
|
+
<RequestActions actionText={actionText} onAction={onAction} />
|
45
|
+
</Dialog.Content>
|
46
|
+
</Dialog.Portal>
|
47
|
+
</Dialog.Root>
|
48
|
+
);
|
49
|
+
};
|
50
|
+
|
51
|
+
const RequestActions = ({ onAction, actionText }: { actionText?: string; onAction: () => void }) => (
|
52
|
+
<Flex justify="center" align="center" css={{ width: '100%', gap: '$md', '@md': { mt: '$8', px: '$8' } }}>
|
53
|
+
<Box css={{ width: '50%' }}>
|
54
|
+
<Dialog.Close css={{ width: '100%' }}>
|
55
|
+
<Button variant="standard" outlined css={{ width: '100%' }}>
|
56
|
+
Decline
|
57
|
+
</Button>
|
58
|
+
</Dialog.Close>
|
59
|
+
</Box>
|
60
|
+
<Box css={{ width: '50%' }}>
|
61
|
+
<Button variant="primary" css={{ width: '100%' }} onClick={onAction}>
|
62
|
+
{actionText}
|
63
|
+
</Button>
|
64
|
+
</Box>
|
65
|
+
</Flex>
|
66
|
+
);
|
@@ -0,0 +1,89 @@
|
|
1
|
+
import React, { useEffect } from 'react';
|
2
|
+
import {
|
3
|
+
selectLocalPeerName,
|
4
|
+
selectLocalPeerRoleName,
|
5
|
+
selectRoleChangeRequest,
|
6
|
+
useCustomEvent,
|
7
|
+
useHMSActions,
|
8
|
+
useHMSStore,
|
9
|
+
} from '@100mslive/react-sdk';
|
10
|
+
import { Flex, Text } from '../../..';
|
11
|
+
// @ts-ignore: No implicit Any
|
12
|
+
import { PreviewControls, PreviewTile } from '../Preview/PreviewJoin';
|
13
|
+
import { RequestPrompt } from './RequestPrompt';
|
14
|
+
// @ts-ignore: No implicit Any
|
15
|
+
import { useMyMetadata } from '../hooks/useMetadata';
|
16
|
+
// @ts-ignore: No implicit Any
|
17
|
+
import { ROLE_CHANGE_DECLINED } from '../../common/constants';
|
18
|
+
|
19
|
+
export const RoleChangeRequestModal = () => {
|
20
|
+
const hmsActions = useHMSActions();
|
21
|
+
const { updateMetaData } = useMyMetadata();
|
22
|
+
const currentRole = useHMSStore(selectLocalPeerRoleName);
|
23
|
+
const roleChangeRequest = useHMSStore(selectRoleChangeRequest);
|
24
|
+
const name = useHMSStore(selectLocalPeerName);
|
25
|
+
const { sendEvent } = useCustomEvent({ type: ROLE_CHANGE_DECLINED });
|
26
|
+
|
27
|
+
useEffect(() => {
|
28
|
+
if (!roleChangeRequest?.role) {
|
29
|
+
return;
|
30
|
+
}
|
31
|
+
(async () => {
|
32
|
+
await hmsActions.preview({ asRole: roleChangeRequest.role.name });
|
33
|
+
})();
|
34
|
+
}, [hmsActions, roleChangeRequest, currentRole, updateMetaData]);
|
35
|
+
|
36
|
+
if (!roleChangeRequest?.role) {
|
37
|
+
return null;
|
38
|
+
}
|
39
|
+
|
40
|
+
const body = (
|
41
|
+
<>
|
42
|
+
<Text
|
43
|
+
variant="xs"
|
44
|
+
css={{
|
45
|
+
c: '$on_surface_medium',
|
46
|
+
textAlign: 'center',
|
47
|
+
'@md': { textAlign: 'left', borderBottom: '1px solid $border_bright', pb: '$4', px: '$8' },
|
48
|
+
}}
|
49
|
+
>
|
50
|
+
Setup your audio and video before joining
|
51
|
+
</Text>
|
52
|
+
<Flex
|
53
|
+
align="center"
|
54
|
+
justify="center"
|
55
|
+
css={{
|
56
|
+
'@sm': { width: '100%' },
|
57
|
+
flexDirection: 'column',
|
58
|
+
mt: '$6',
|
59
|
+
'@md': { px: '$8' },
|
60
|
+
}}
|
61
|
+
>
|
62
|
+
<PreviewTile name={name || ''} />
|
63
|
+
|
64
|
+
<PreviewControls hideSettings={true} />
|
65
|
+
</Flex>
|
66
|
+
</>
|
67
|
+
);
|
68
|
+
|
69
|
+
return (
|
70
|
+
<RequestPrompt
|
71
|
+
title="You're invited to join the stage"
|
72
|
+
onOpenChange={async value => {
|
73
|
+
if (!value) {
|
74
|
+
hmsActions.rejectChangeRole(roleChangeRequest);
|
75
|
+
sendEvent({ ...roleChangeRequest, peerName: name }, { peerId: roleChangeRequest.requestedBy?.id });
|
76
|
+
await hmsActions.cancelMidCallPreview();
|
77
|
+
await hmsActions.lowerLocalPeerHand();
|
78
|
+
}
|
79
|
+
}}
|
80
|
+
body={body}
|
81
|
+
onAction={async () => {
|
82
|
+
await hmsActions.acceptChangeRole(roleChangeRequest);
|
83
|
+
await updateMetaData({ prevRole: currentRole });
|
84
|
+
await hmsActions.lowerLocalPeerHand();
|
85
|
+
}}
|
86
|
+
actionText="Accept"
|
87
|
+
/>
|
88
|
+
);
|
89
|
+
};
|
@@ -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,11 +20,12 @@ 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';
|
25
27
|
import { useSetAppDataByKey, useUISettings } from './AppData/useUISettings';
|
28
|
+
import { getAttributeBoxSize } from '../common/utils';
|
26
29
|
import { APP_DATA, SESSION_STORE_KEY, UI_SETTINGS } from '../common/constants';
|
27
30
|
|
28
31
|
const Tile = ({
|
@@ -43,6 +46,7 @@ const Tile = ({
|
|
43
46
|
}) => {
|
44
47
|
const trackSelector = trackId ? selectVideoTrackByID(trackId) : selectVideoTrackByPeerID(peerId);
|
45
48
|
const track = useHMSStore(trackSelector);
|
49
|
+
const isMobile = useMedia(cssConfig.media.md);
|
46
50
|
const peerName = useHMSStore(selectPeerNameByID(peerId));
|
47
51
|
const audioTrack = useHMSStore(selectAudioTrackByPeerID(peerId));
|
48
52
|
const localPeerID = useHMSStore(selectLocalPeerID);
|
@@ -69,21 +73,28 @@ const Tile = ({
|
|
69
73
|
const onHoverHandler = useCallback(event => {
|
70
74
|
setIsMouseHovered(event.type === 'mouseenter');
|
71
75
|
}, []);
|
72
|
-
|
76
|
+
|
77
|
+
const ref = useRef(null);
|
78
|
+
const calculatedHeight = ref.current?.clientHeight || '';
|
79
|
+
const calculatedWidth = ref.current?.clientWidth || '';
|
80
|
+
|
81
|
+
const isTileBigEnoughToShowStats = calculatedHeight >= 180 && calculatedWidth >= 180;
|
82
|
+
|
73
83
|
const avatarSize = useMemo(() => {
|
74
|
-
if (!
|
84
|
+
if (!calculatedWidth || !calculatedHeight) {
|
75
85
|
return undefined;
|
76
86
|
}
|
77
|
-
if (
|
87
|
+
if (calculatedWidth <= 150 || calculatedHeight <= 150) {
|
78
88
|
return 'small';
|
79
|
-
} else if (
|
89
|
+
} else if (calculatedWidth <= 300 || calculatedHeight <= 300) {
|
80
90
|
return 'medium';
|
81
91
|
}
|
82
92
|
return 'large';
|
83
|
-
}, [
|
93
|
+
}, [calculatedWidth, calculatedHeight]);
|
84
94
|
|
85
95
|
return (
|
86
96
|
<StyledVideoTile.Root
|
97
|
+
ref={ref}
|
87
98
|
css={{
|
88
99
|
width,
|
89
100
|
height,
|
@@ -130,7 +141,7 @@ const Tile = ({
|
|
130
141
|
isAudioMuted ? (
|
131
142
|
<StyledVideoTile.AudioIndicator
|
132
143
|
data-testid="participant_audio_mute_icon"
|
133
|
-
size={
|
144
|
+
size={getAttributeBoxSize(calculatedWidth, calculatedHeight)}
|
134
145
|
>
|
135
146
|
<MicOffIcon />
|
136
147
|
</StyledVideoTile.AudioIndicator>
|
@@ -138,7 +149,7 @@ const Tile = ({
|
|
138
149
|
<AudioLevel trackId={audioTrack?.id} />
|
139
150
|
)
|
140
151
|
) : null}
|
141
|
-
{isMouseHovered || isDragabble ? (
|
152
|
+
{isMouseHovered || (isDragabble && isMobile) ? (
|
142
153
|
<TileMenu
|
143
154
|
peerID={peerId}
|
144
155
|
audioTrackID={audioTrack?.id}
|
@@ -147,7 +158,7 @@ const Tile = ({
|
|
147
158
|
enableSpotlightingPeer={enableSpotlightingPeer}
|
148
159
|
/>
|
149
160
|
) : null}
|
150
|
-
{!hideMetadataOnTile && <PeerMetadata peerId={peerId} />}
|
161
|
+
{!hideMetadataOnTile && <PeerMetadata peerId={peerId} height={calculatedHeight} width={calculatedWidth} />}
|
151
162
|
|
152
163
|
<TileConnection
|
153
164
|
hideLabel={hideParticipantNameOnTile}
|
@@ -164,8 +175,6 @@ const Tile = ({
|
|
164
175
|
);
|
165
176
|
};
|
166
177
|
|
167
|
-
const metaStyles = { top: '$4', left: '$4', width: '$14', height: '$14' };
|
168
|
-
|
169
178
|
const heightAnimation = value =>
|
170
179
|
keyframes({
|
171
180
|
'50%': {
|
@@ -215,20 +224,20 @@ export const AudioLevel = ({ trackId }) => {
|
|
215
224
|
);
|
216
225
|
};
|
217
226
|
|
218
|
-
const PeerMetadata = ({ peerId }) => {
|
227
|
+
const PeerMetadata = ({ peerId, height, width }) => {
|
219
228
|
const metaData = useHMSStore(selectPeerMetadata(peerId));
|
220
|
-
const isHandRaised = metaData?.isHandRaised || false;
|
221
229
|
const isBRB = metaData?.isBRBOn || false;
|
230
|
+
const isHandRaised = useHMSStore(selectHasPeerHandRaised(peerId));
|
222
231
|
|
223
232
|
return (
|
224
233
|
<Fragment>
|
225
234
|
{isHandRaised ? (
|
226
|
-
<StyledVideoTile.AttributeBox
|
235
|
+
<StyledVideoTile.AttributeBox size={getAttributeBoxSize(width, height)} data-testid="raiseHand_icon_onTile">
|
227
236
|
<HandIcon width={24} height={24} />
|
228
237
|
</StyledVideoTile.AttributeBox>
|
229
238
|
) : null}
|
230
239
|
{isBRB ? (
|
231
|
-
<StyledVideoTile.AttributeBox
|
240
|
+
<StyledVideoTile.AttributeBox size={getAttributeBoxSize(width, height)} data-testid="brb_icon_onTile">
|
232
241
|
<BrbTileIcon width={22} height={22} />
|
233
242
|
</StyledVideoTile.AttributeBox>
|
234
243
|
) : null}
|
@@ -13,12 +13,12 @@ import { Footer } from './Footer/Footer';
|
|
13
13
|
import { HLSFailureModal } from './Notifications/HLSFailureModal';
|
14
14
|
import { ActivatedPIP } from './PIP/PIPComponent';
|
15
15
|
import { PictureInPicture } from './PIP/PIPManager';
|
16
|
+
import { RoleChangeRequestModal } from './RoleChangeRequest/RoleChangeRequestModal';
|
16
17
|
import { Box, Flex } from '../../Layout';
|
17
18
|
import { useHMSPrebuiltContext } from '../AppContext';
|
18
19
|
import { VideoStreamingSection } from '../layouts/VideoStreamingSection';
|
19
20
|
import FullPageProgress from './FullPageProgress';
|
20
21
|
import { Header } from './Header';
|
21
|
-
import { RoleChangeRequestModal } from './RoleChangeRequestModal';
|
22
22
|
import {
|
23
23
|
useRoomLayoutConferencingScreen,
|
24
24
|
useRoomLayoutPreviewScreen,
|