@100mslive/roomkit-react 0.3.14-alpha.0 → 0.3.14-alpha.10
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/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