@100mslive/roomkit-react 0.3.14-alpha.0 → 0.3.14-alpha.10
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Diagnostics/AudioTest.d.ts +2 -0
- package/dist/Diagnostics/BrowserTest.d.ts +81 -0
- package/dist/Diagnostics/ConnectivityTest.d.ts +7 -0
- package/dist/Diagnostics/Diagnostics.d.ts +2 -0
- package/dist/Diagnostics/VideoTest.d.ts +2 -0
- package/dist/Diagnostics/components.d.ts +18 -0
- package/dist/Diagnostics/hms.d.ts +9 -0
- package/dist/Diagnostics/index.d.ts +1 -0
- package/dist/{HLSView-USRUP6VG.js → HLSView-PL2BEA32.js} +2 -2
- package/dist/{HLSView-7LHIA6HH.css → HLSView-TAAU7UCF.css} +3 -3
- package/dist/{HLSView-7LHIA6HH.css.map → HLSView-TAAU7UCF.css.map} +1 -1
- package/dist/Prebuilt/App.d.ts +1 -0
- package/dist/Prebuilt/components/Notifications/PermissionErrorModal.d.ts +5 -1
- package/dist/Stats/index.d.ts +1 -0
- package/dist/{chunk-DYDYPNYY.js → chunk-EKH2S2VL.js} +13835 -2768
- package/dist/chunk-EKH2S2VL.js.map +7 -0
- package/dist/index.cjs.css +2 -2
- package/dist/index.cjs.css.map +1 -1
- package/dist/index.cjs.js +14870 -3708
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -1
- package/dist/meta.cjs.json +972 -197
- package/dist/meta.esbuild.json +984 -205
- package/package.json +7 -7
- package/src/Diagnostics/AudioTest.tsx +176 -0
- package/src/Diagnostics/BrowserTest.tsx +139 -0
- package/src/Diagnostics/ConnectivityTest.tsx +359 -0
- package/src/Diagnostics/DeviceSelector.jsx +71 -0
- package/src/Diagnostics/Diagnostics.tsx +134 -0
- package/src/Diagnostics/VideoTest.tsx +68 -0
- package/src/Diagnostics/components.tsx +96 -0
- package/src/Diagnostics/hms.ts +9 -0
- package/src/Diagnostics/index.ts +1 -0
- package/src/Prebuilt/App.tsx +3 -0
- package/src/Prebuilt/components/Chat/ChatFooter.tsx +20 -3
- package/src/Prebuilt/components/Header/common.jsx +3 -0
- package/src/Prebuilt/components/Notifications/Notifications.tsx +2 -2
- package/src/Prebuilt/components/Notifications/PermissionErrorModal.tsx +13 -11
- package/src/Prebuilt/components/StatsForNerds.jsx +1 -13
- package/src/Stats/index.tsx +1 -0
- package/src/index.ts +1 -0
- package/dist/chunk-DYDYPNYY.js.map +0 -7
- /package/dist/{HLSView-USRUP6VG.js.map → HLSView-PL2BEA32.js.map} +0 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import { Button } from '../Button';
|
3
|
+
import { Box, Flex } from '../Layout';
|
4
|
+
import { Text } from '../Text';
|
5
|
+
import { CSS } from '../Theme';
|
6
|
+
import { hmsDiagnostics } from './hms';
|
7
|
+
|
8
|
+
export const DiagnosticsSteps: Record<string, string> = {
|
9
|
+
browser: 'Browser Support',
|
10
|
+
video: 'Test Video',
|
11
|
+
audio: 'Test Audio',
|
12
|
+
connectivity: 'Connection Quality',
|
13
|
+
};
|
14
|
+
|
15
|
+
export const DiagnosticsContext = React.createContext<{
|
16
|
+
activeStep: string;
|
17
|
+
setActiveStep: React.Dispatch<React.SetStateAction<string>>;
|
18
|
+
connectivityTested: boolean;
|
19
|
+
setConnectivityTested: React.Dispatch<React.SetStateAction<boolean>>;
|
20
|
+
}>({
|
21
|
+
activeStep: 'video',
|
22
|
+
setActiveStep: () => {
|
23
|
+
return;
|
24
|
+
},
|
25
|
+
connectivityTested: false,
|
26
|
+
setConnectivityTested: () => {
|
27
|
+
return;
|
28
|
+
},
|
29
|
+
});
|
30
|
+
|
31
|
+
export const TestContainer = ({ css, children }: { css?: CSS; children: React.ReactNode }) => {
|
32
|
+
return <Box css={{ p: '$10', ...css }}>{children}</Box>;
|
33
|
+
};
|
34
|
+
|
35
|
+
export const TestFooter = ({
|
36
|
+
error,
|
37
|
+
ctaText,
|
38
|
+
children,
|
39
|
+
}: {
|
40
|
+
ctaText?: string;
|
41
|
+
error?: Error;
|
42
|
+
children?: React.ReactNode;
|
43
|
+
}) => {
|
44
|
+
const { activeStep, setActiveStep } = useContext(DiagnosticsContext);
|
45
|
+
|
46
|
+
const onNextStep = () => {
|
47
|
+
if (activeStep === 'audio') {
|
48
|
+
hmsDiagnostics.stopMicCheck();
|
49
|
+
} else if (activeStep === 'video') {
|
50
|
+
hmsDiagnostics.stopCameraCheck();
|
51
|
+
} else if (activeStep === 'connectivity') {
|
52
|
+
hmsDiagnostics.stopConnectivityCheck();
|
53
|
+
}
|
54
|
+
|
55
|
+
const keys = Object.keys(DiagnosticsSteps);
|
56
|
+
setActiveStep(step => keys[keys.indexOf(step) + 1]);
|
57
|
+
};
|
58
|
+
|
59
|
+
return (
|
60
|
+
<Flex
|
61
|
+
css={{
|
62
|
+
py: '$8',
|
63
|
+
px: '$10',
|
64
|
+
position: 'sticky',
|
65
|
+
bottom: '0',
|
66
|
+
background: '$background_dim',
|
67
|
+
justifyContent: 'space-between',
|
68
|
+
alignItems: 'center',
|
69
|
+
borderTop: '1px solid $border_default',
|
70
|
+
fontSize: '$sm',
|
71
|
+
borderBottomLeftRadius: '$1',
|
72
|
+
borderBottomRightRadius: '$1',
|
73
|
+
lineHeight: '$sm',
|
74
|
+
zIndex: 1001,
|
75
|
+
'@lg': { flexDirection: 'column', gap: '$8' },
|
76
|
+
}}
|
77
|
+
>
|
78
|
+
<Box>{error && <Text css={{ c: '$alert_error_default' }}>Error: {error.message}</Text>}</Box>
|
79
|
+
{children ? (
|
80
|
+
children
|
81
|
+
) : (
|
82
|
+
<Flex align="center" css={{ gap: '$8', '@lg': { flexDirection: 'column' } }}>
|
83
|
+
<Text css={{ c: '$on_primary_medium' }}>{ctaText}</Text>
|
84
|
+
<Flex align="center" gap="4">
|
85
|
+
<Button onClick={onNextStep} variant="standard" outlined={true}>
|
86
|
+
Skip
|
87
|
+
</Button>
|
88
|
+
<Button disabled={!!error} onClick={onNextStep}>
|
89
|
+
Yes
|
90
|
+
</Button>
|
91
|
+
</Flex>
|
92
|
+
</Flex>
|
93
|
+
)}
|
94
|
+
</Flex>
|
95
|
+
);
|
96
|
+
};
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// @ts-check
|
2
|
+
import { HMSReactiveStore } from '@100mslive/hms-video-store';
|
3
|
+
|
4
|
+
const hms = new HMSReactiveStore();
|
5
|
+
export const hmsStore = hms.getStore();
|
6
|
+
export const hmsActions = hms.getActions();
|
7
|
+
export const hmsNotifications = hms.getNotifications();
|
8
|
+
export const hmsStats = hms.getStats();
|
9
|
+
export const hmsDiagnostics = hms.getDiagnosticsSDK();
|
@@ -0,0 +1 @@
|
|
1
|
+
export { Diagnostics } from './Diagnostics';
|
package/src/Prebuilt/App.tsx
CHANGED
@@ -65,6 +65,7 @@ export type HMSPrebuiltProps = {
|
|
65
65
|
options?: HMSPrebuiltOptions;
|
66
66
|
screens?: Screens;
|
67
67
|
authToken?: string;
|
68
|
+
leaveOnUnload?: boolean;
|
68
69
|
onLeave?: () => void;
|
69
70
|
onJoin?: () => void;
|
70
71
|
/**
|
@@ -92,6 +93,7 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
|
|
92
93
|
themes,
|
93
94
|
options: { userName = '', userId = '', endpoints } = {},
|
94
95
|
screens,
|
96
|
+
leaveOnUnload = true,
|
95
97
|
onLeave,
|
96
98
|
onJoin,
|
97
99
|
},
|
@@ -188,6 +190,7 @@ export const HMSPrebuilt = React.forwardRef<HMSPrebuiltRefType, HMSPrebuiltProps
|
|
188
190
|
store={reactiveStore.current?.hmsStore}
|
189
191
|
notifications={reactiveStore.current?.hmsNotifications}
|
190
192
|
stats={reactiveStore.current?.hmsStats}
|
193
|
+
leaveOnUnload={leaveOnUnload}
|
191
194
|
>
|
192
195
|
<RoomLayoutProvider roomLayoutEndpoint={roomLayoutEndpoint} overrideLayout={overrideLayout}>
|
193
196
|
<RoomLayoutContext.Consumer>
|
@@ -22,6 +22,8 @@ import { useEmojiPickerStyles } from './useEmojiPickerStyles';
|
|
22
22
|
import { useDefaultChatSelection, useLandscapeHLSStream, useMobileHLSStream } from '../../common/hooks';
|
23
23
|
import { CHAT_SELECTOR, SESSION_STORE_KEY } from '../../common/constants';
|
24
24
|
|
25
|
+
const CHAT_MESSAGE_LIMIT = 2000;
|
26
|
+
|
25
27
|
const TextArea = styled('textarea', {
|
26
28
|
width: '100%',
|
27
29
|
bg: 'transparent',
|
@@ -90,6 +92,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
90
92
|
const selection = selectedPeer.name || selectedRole || defaultSelection;
|
91
93
|
const isLocalPeerBlacklisted = useIsPeerBlacklisted({ local: true });
|
92
94
|
const isMwebHLSStream = useMobileHLSStream();
|
95
|
+
const [messageLengthExceeded, setMessageLengthExceeded] = useState(false);
|
93
96
|
const isLandscapeHLSStream = useLandscapeHLSStream();
|
94
97
|
|
95
98
|
useEffect(() => {
|
@@ -105,7 +108,10 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
105
108
|
|
106
109
|
const resetInputHeight = useCallback(() => {
|
107
110
|
if (inputRef.current) {
|
108
|
-
inputRef.current.style.height = `${Math.max(
|
111
|
+
inputRef.current.style.height = `${Math.max(
|
112
|
+
32,
|
113
|
+
inputRef.current.value ? Math.min(inputRef.current.scrollHeight, 24 * 4) : 0,
|
114
|
+
)}px`;
|
109
115
|
}
|
110
116
|
}, []);
|
111
117
|
|
@@ -146,6 +152,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
146
152
|
if (messageElement) {
|
147
153
|
messageElement.value = draftMessage;
|
148
154
|
updateInputHeight();
|
155
|
+
setMessageLengthExceeded(draftMessage.length > CHAT_MESSAGE_LIMIT);
|
149
156
|
}
|
150
157
|
}, [draftMessage]);
|
151
158
|
|
@@ -230,6 +237,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
230
237
|
>
|
231
238
|
{children}
|
232
239
|
<TextArea
|
240
|
+
maxLength={CHAT_MESSAGE_LIMIT + 10}
|
233
241
|
css={{
|
234
242
|
c: '$on_surface_high',
|
235
243
|
'&:valid ~ .send-msg': { color: '$on_surface_high' },
|
@@ -243,7 +251,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
243
251
|
autoFocus={!(isMobile || isLandscapeHLSStream)}
|
244
252
|
onKeyPress={async event => {
|
245
253
|
if (event.key === 'Enter') {
|
246
|
-
if (!event.shiftKey) {
|
254
|
+
if (!event.shiftKey && !messageLengthExceeded) {
|
247
255
|
event.preventDefault();
|
248
256
|
await sendMessage();
|
249
257
|
}
|
@@ -251,7 +259,10 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
251
259
|
}}
|
252
260
|
autoComplete="off"
|
253
261
|
aria-autocomplete="none"
|
254
|
-
onChange={
|
262
|
+
onChange={e => {
|
263
|
+
updateInputHeight();
|
264
|
+
setMessageLengthExceeded(e.target.value.length > CHAT_MESSAGE_LIMIT);
|
265
|
+
}}
|
255
266
|
onBlur={resetInputHeight}
|
256
267
|
onPaste={e => e.stopPropagation()}
|
257
268
|
onCut={e => e.stopPropagation()}
|
@@ -269,6 +280,7 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
269
280
|
<BaseIconButton
|
270
281
|
className="send-msg"
|
271
282
|
onClick={sendMessage}
|
283
|
+
disabled={messageLengthExceeded}
|
272
284
|
css={{
|
273
285
|
ml: 'auto',
|
274
286
|
height: 'max-content',
|
@@ -295,6 +307,11 @@ export const ChatFooter = ({ onSend, children }: { onSend: (count: number) => vo
|
|
295
307
|
)}
|
296
308
|
</Flex>
|
297
309
|
)}
|
310
|
+
{messageLengthExceeded && (
|
311
|
+
<Text variant="xs" css={{ color: '$alert_error_default', fontWeight: '$semiBold', mt: '$1', ml: '$7' }}>
|
312
|
+
Message cannot exceed 2000 characters
|
313
|
+
</Text>
|
314
|
+
)}
|
298
315
|
</Box>
|
299
316
|
);
|
300
317
|
};
|
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
CrossIcon,
|
16
16
|
HeadphonesIcon,
|
17
17
|
SpeakerIcon,
|
18
|
+
TelePhoneIcon,
|
18
19
|
} from '@100mslive/react-icons';
|
19
20
|
import { HorizontalDivider } from '../../../Divider';
|
20
21
|
import { Label } from '../../../Label';
|
@@ -82,6 +83,8 @@ export const AudioActions = () => {
|
|
82
83
|
AudioIcon = <BluetoothIcon />;
|
83
84
|
} else if (currentSelection && currentSelection.label.toLowerCase().includes('wired')) {
|
84
85
|
AudioIcon = <HeadphonesIcon />;
|
86
|
+
} else if (currentSelection && currentSelection.label.toLowerCase().includes('earpiece')) {
|
87
|
+
AudioIcon = <TelePhoneIcon />;
|
85
88
|
}
|
86
89
|
return (
|
87
90
|
<AudioSelectionSheet
|
@@ -24,7 +24,7 @@ import { ChatNotifications } from './ChatNotifications';
|
|
24
24
|
import { HandRaisedNotifications } from './HandRaisedNotifications';
|
25
25
|
import { InitErrorModal } from './InitErrorModal';
|
26
26
|
import { PeerNotifications } from './PeerNotifications';
|
27
|
-
import {
|
27
|
+
import { PermissionErrorNotificationModal } from './PermissionErrorModal';
|
28
28
|
import { ReconnectNotifications } from './ReconnectNotifications';
|
29
29
|
import { TrackBulkUnmuteModal } from './TrackBulkUnmuteModal';
|
30
30
|
import { TrackNotifications } from './TrackNotifications';
|
@@ -197,7 +197,7 @@ export function Notifications() {
|
|
197
197
|
{roomState === HMSRoomState.Connected ? <PeerNotifications /> : null}
|
198
198
|
<ReconnectNotifications />
|
199
199
|
<AutoplayBlockedModal />
|
200
|
-
<
|
200
|
+
<PermissionErrorNotificationModal />
|
201
201
|
<InitErrorModal />
|
202
202
|
<ChatNotifications />
|
203
203
|
<HandRaisedNotifications />
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
2
2
|
import { useMedia } from 'react-use';
|
3
|
-
import { HMSNotificationTypes, useHMSNotifications } from '@100mslive/react-sdk';
|
3
|
+
import { HMSException, HMSNotificationTypes, useHMSNotifications } from '@100mslive/react-sdk';
|
4
4
|
import { Button, config as cssConfig, Dialog, Flex, Text } from '../../..';
|
5
5
|
// @ts-ignore: No implicit Any
|
6
6
|
import androidPermissionAlert from '../../images/android-perm-1.png';
|
@@ -9,22 +9,24 @@ import iosPermissions from '../../images/ios-perm-0.png';
|
|
9
9
|
// @ts-ignore: No implicit Any
|
10
10
|
import { isAndroid, isIOS } from '../../common/constants';
|
11
11
|
|
12
|
-
export function
|
12
|
+
export function PermissionErrorNotificationModal() {
|
13
13
|
const notification = useHMSNotifications(HMSNotificationTypes.ERROR);
|
14
|
+
return <PermissionErrorModal error={notification?.data} />;
|
15
|
+
}
|
16
|
+
|
17
|
+
export const PermissionErrorModal = ({ error }: { error?: HMSException }) => {
|
14
18
|
const [deviceType, setDeviceType] = useState('');
|
15
19
|
const [isSystemError, setIsSystemError] = useState(false);
|
16
20
|
const isMobile = useMedia(cssConfig.media.md);
|
17
|
-
|
18
21
|
useEffect(() => {
|
19
22
|
if (
|
20
|
-
!
|
21
|
-
(
|
22
|
-
(
|
23
|
+
!error ||
|
24
|
+
(error?.code !== 3001 && error?.code !== 3011) ||
|
25
|
+
(error?.code === 3001 && error?.message.includes('screen'))
|
23
26
|
) {
|
24
27
|
return;
|
25
28
|
}
|
26
|
-
|
27
|
-
const errorMessage = notification.data?.message;
|
29
|
+
const errorMessage = error?.message;
|
28
30
|
const hasAudio = errorMessage.includes('audio');
|
29
31
|
const hasVideo = errorMessage.includes('video');
|
30
32
|
const hasScreen = errorMessage.includes('screen');
|
@@ -37,8 +39,8 @@ export function PermissionErrorModal() {
|
|
37
39
|
} else if (hasScreen) {
|
38
40
|
setDeviceType('screen');
|
39
41
|
}
|
40
|
-
setIsSystemError(
|
41
|
-
}, [
|
42
|
+
setIsSystemError(error.code === 3011);
|
43
|
+
}, [error]);
|
42
44
|
|
43
45
|
return deviceType ? (
|
44
46
|
<Dialog.Root open={!!deviceType}>
|
@@ -131,4 +133,4 @@ export function PermissionErrorModal() {
|
|
131
133
|
</Dialog.Portal>
|
132
134
|
</Dialog.Root>
|
133
135
|
) : null;
|
134
|
-
}
|
136
|
+
};
|
@@ -13,6 +13,7 @@ import { Dropdown } from '../../Dropdown';
|
|
13
13
|
import { Label } from '../../Label';
|
14
14
|
import { Box, Flex } from '../../Layout';
|
15
15
|
import { Dialog } from '../../Modal';
|
16
|
+
import { formatBytes } from '../../Stats';
|
16
17
|
import { Switch } from '../../Switch';
|
17
18
|
import { Text } from '../../Text';
|
18
19
|
import { DialogDropdownTrigger } from '../primitives/DropdownTrigger';
|
@@ -245,16 +246,3 @@ const StatsRow = React.memo(({ label, value }) => (
|
|
245
246
|
</Text>
|
246
247
|
</Box>
|
247
248
|
));
|
248
|
-
|
249
|
-
const formatBytes = (bytes, unit = 'B', decimals = 2) => {
|
250
|
-
if (bytes === undefined) return '-';
|
251
|
-
if (bytes === 0) return '0 ' + unit;
|
252
|
-
|
253
|
-
const k = 1024;
|
254
|
-
const dm = decimals < 0 ? 0 : decimals;
|
255
|
-
const sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'].map(size => size + unit);
|
256
|
-
|
257
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
258
|
-
|
259
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
260
|
-
};
|
package/src/Stats/index.tsx
CHANGED
package/src/index.ts
CHANGED