@100mslive/roomkit-react 0.1.6 → 0.1.7
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-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,
|