@100mslive/roomkit-react 0.3.15-alpha.2 → 0.3.15-alpha.4

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.
@@ -1,20 +1,33 @@
1
- import React, { useContext, useRef, useState } from 'react';
1
+ import React, { useCallback, useRef, useState } from 'react';
2
2
  import { HMSRoomProvider, useHMSActions } from '@100mslive/react-sdk';
3
- import { CheckCircleIcon, ConnectivityIcon, GlobeIcon, MicOnIcon, VideoOnIcon } from '@100mslive/react-icons';
4
- import { DiagnosticsContext, DiagnosticsSteps } from './components';
3
+ import {
4
+ CheckCircleIcon,
5
+ ConnectivityIcon,
6
+ CrossCircleIcon,
7
+ GlobeIcon,
8
+ MicOnIcon,
9
+ VideoOnIcon,
10
+ } from '@100mslive/react-icons';
5
11
  import { Box, Flex } from '../Layout';
6
12
  import { Text } from '../Text';
7
13
  import { HMSThemeProvider } from '../Theme';
8
14
  import { AudioTest } from './AudioTest';
9
15
  import { BrowserTest } from './BrowserTest';
10
16
  import { ConnectivityTest } from './ConnectivityTest';
17
+ import {
18
+ DiagnosticsContext,
19
+ DiagnosticsStep,
20
+ DiagnosticsStepInfo,
21
+ initialSteps,
22
+ useDiagnostics,
23
+ } from './DiagnosticsContext';
11
24
  import { VideoTest } from './VideoTest';
12
25
 
13
- const DiagnosticsStepIcon: Record<string, React.ReactNode> = {
14
- video: <VideoOnIcon width="2rem" height="2rem" />,
15
- audio: <MicOnIcon width="2rem" height="2rem" />,
16
- browser: <GlobeIcon width="2rem" height="2rem" />,
17
- connectivity: <ConnectivityIcon width="2rem" height="2rem" />,
26
+ const DiagnosticsStepIcon: Record<DiagnosticsStep, React.ReactNode> = {
27
+ [DiagnosticsStep.VIDEO]: <VideoOnIcon width="2rem" height="2rem" />,
28
+ [DiagnosticsStep.AUDIO]: <MicOnIcon width="2rem" height="2rem" />,
29
+ [DiagnosticsStep.BROWSER]: <GlobeIcon width="2rem" height="2rem" />,
30
+ [DiagnosticsStep.CONNECTIVITY]: <ConnectivityIcon width="2rem" height="2rem" />,
18
31
  };
19
32
 
20
33
  const Container = ({ children }: { children: React.ReactNode }) => (
@@ -27,11 +40,15 @@ const Container = ({ children }: { children: React.ReactNode }) => (
27
40
  lineHeight: '1.5',
28
41
  '-webkit-text-size-adjust': '100%',
29
42
  position: 'relative',
30
- h: `calc(100% - 108px)`,
43
+ h: '100%',
31
44
  '@lg': {
32
45
  p: '$12',
33
46
  },
34
47
  overflowY: 'auto',
48
+ boxSizing: 'border-box',
49
+ '& *': {
50
+ boxSizing: 'border-box',
51
+ },
35
52
  '::-webkit-scrollbar-track': {
36
53
  WebkitBoxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)',
37
54
  boxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)',
@@ -53,34 +70,34 @@ const Container = ({ children }: { children: React.ReactNode }) => (
53
70
  );
54
71
 
55
72
  const DiagnosticsStepTest = () => {
56
- const { activeStep } = useContext(DiagnosticsContext);
73
+ const { activeStepIndex } = useDiagnostics();
57
74
 
58
75
  let TestComponent = () => <></>;
59
76
 
60
- if (activeStep === 'audio') {
77
+ if (activeStepIndex === DiagnosticsStep.AUDIO) {
61
78
  TestComponent = AudioTest;
62
- } else if (activeStep === 'video') {
79
+ } else if (activeStepIndex === DiagnosticsStep.VIDEO) {
63
80
  TestComponent = VideoTest;
64
- } else if (activeStep === 'browser') {
81
+ } else if (activeStepIndex === DiagnosticsStep.BROWSER) {
65
82
  TestComponent = BrowserTest;
66
- } else if (activeStep === 'connectivity') {
83
+ } else if (activeStepIndex === DiagnosticsStep.CONNECTIVITY) {
67
84
  TestComponent = ConnectivityTest;
68
85
  }
69
86
 
70
- return <TestComponent key={activeStep} />;
87
+ return <TestComponent key={activeStepIndex} />;
71
88
  };
72
89
 
73
90
  const DiagnosticsStepHeader = () => {
74
- const { activeStep } = useContext(DiagnosticsContext);
91
+ const { activeStepIndex, activeStep } = useDiagnostics();
75
92
  return (
76
93
  <Flex css={{ py: '$8', px: '$10', alignItems: 'center', borderBottom: '1px solid $border_default' }}>
77
- <Text css={{ c: '$primary_bright', mt: '$xs' }}>{DiagnosticsStepIcon[activeStep]}</Text>
78
- <Text css={{ fontSize: '$h6', ml: '$9' }}>{DiagnosticsSteps[activeStep]}</Text>
94
+ <Text css={{ c: '$primary_bright', mt: '$xs' }}>{DiagnosticsStepIcon[activeStepIndex]}</Text>
95
+ <Text css={{ fontSize: '$h6', ml: '$9' }}>{activeStep.name}</Text>
79
96
  </Flex>
80
97
  );
81
98
  };
82
99
 
83
- const DiagnosticsStep = () => {
100
+ const DiagnosticsStepContainer = () => {
84
101
  return (
85
102
  <Box css={{ border: '1px solid $border_default', r: '$1', w: '75%', maxWidth: '65rem', '@lg': { w: '100%' } }}>
86
103
  <DiagnosticsStepHeader />
@@ -90,53 +107,62 @@ const DiagnosticsStep = () => {
90
107
  };
91
108
 
92
109
  const DiagnosticsStepsList = () => {
93
- const { activeStep, connectivityTested } = useContext(DiagnosticsContext);
110
+ const { activeStepIndex, activeStep, steps } = useDiagnostics();
94
111
 
95
112
  return (
96
113
  <Box css={{ w: '25%', '@lg': { display: 'none' } }}>
97
- {Object.keys(DiagnosticsSteps).map(key => {
98
- const keys = Object.keys(DiagnosticsSteps);
99
- const activeStepIndex = keys.indexOf(activeStep);
100
- const keyIndex = keys.indexOf(key);
101
- const isStepCompleted = activeStepIndex > keyIndex || (activeStep === 'connectivity' && connectivityTested);
102
-
103
- let color = '$on_primary_low';
104
- if (activeStep === key) {
105
- color = '$on_primary_high';
106
- }
107
- if (isStepCompleted) {
108
- color = '$primary_bright';
109
- }
110
-
111
- return (
112
- <Flex key={key} css={{ mb: '$10', c: color, gap: '$4', alignItems: 'center' }}>
113
- {isStepCompleted ? (
114
- <CheckCircleIcon width="1rem" height="1rem" />
115
- ) : (
116
- <Text css={{ c: color, fontSize: '1.75rem' }}>&bull;</Text>
117
- )}
118
- <Text css={{ c: color }}>{DiagnosticsSteps[key]}</Text>
119
- </Flex>
120
- );
121
- })}
114
+ {Object.keys(DiagnosticsStep)
115
+ .filter(key => !isNaN(Number(key)))
116
+ .map(key => {
117
+ const keyIndex = Number(key);
118
+ const step = steps[keyIndex as DiagnosticsStep];
119
+ const isStepCompleted = activeStepIndex > keyIndex || activeStep.isCompleted;
120
+
121
+ let color = '$on_primary_low';
122
+ let icon = <Text css={{ c: color, fontSize: '1.75rem' }}>&bull;</Text>;
123
+
124
+ if (activeStepIndex === keyIndex) {
125
+ color = '$on_primary_high';
126
+ icon = <Text css={{ c: color, fontSize: '1.75rem' }}>&bull;</Text>;
127
+ }
128
+ if (isStepCompleted) {
129
+ color = '$primary_bright';
130
+ icon = <CheckCircleIcon width="1rem" height="1rem" />;
131
+ }
132
+ if (step.hasFailed) {
133
+ color = '$alert_error_default';
134
+ icon = <CrossCircleIcon width="1rem" height="1rem" />;
135
+ }
136
+
137
+ return (
138
+ <Flex key={key} css={{ mb: '$10', c: color, gap: '$4', alignItems: 'center' }}>
139
+ {icon}
140
+ <Text css={{ c: color }}>{step.name}</Text>
141
+ </Flex>
142
+ );
143
+ })}
122
144
  </Box>
123
145
  );
124
146
  };
125
147
 
126
148
  const DiagnosticsProvider = () => {
127
149
  const actions = useHMSActions();
128
- const [activeStep, setActiveStep] = useState(Object.keys(DiagnosticsSteps)[0]);
129
- const [connectivityTested, setConnectivityTested] = useState(false);
150
+ const [activeStep, setActiveStep] = useState(0);
151
+ const [steps, setSteps] = useState(initialSteps);
130
152
  const diagnosticsRef = useRef(actions.initDiagnostics());
131
153
 
154
+ const updateStep = useCallback((step: DiagnosticsStep, value: Omit<DiagnosticsStepInfo, 'name'>) => {
155
+ setSteps(prevSteps => ({ ...prevSteps, [step]: { ...prevSteps[step], ...value } }));
156
+ }, []);
157
+
132
158
  return (
133
159
  <DiagnosticsContext.Provider
134
160
  value={{
135
161
  hmsDiagnostics: diagnosticsRef.current,
136
- activeStep,
162
+ activeStepIndex: activeStep,
137
163
  setActiveStep,
138
- connectivityTested,
139
- setConnectivityTested,
164
+ steps,
165
+ updateStep,
140
166
  }}
141
167
  >
142
168
  <Container>
@@ -146,7 +172,7 @@ const DiagnosticsProvider = () => {
146
172
  </Text>
147
173
  <Flex css={{ direction: 'column', mt: '$12', justifyItems: 'center' }}>
148
174
  <DiagnosticsStepsList />
149
- <DiagnosticsStep />
175
+ <DiagnosticsStepContainer />
150
176
  </Flex>
151
177
  </Container>
152
178
  </DiagnosticsContext.Provider>
@@ -0,0 +1,46 @@
1
+ import React, { useContext } from 'react';
2
+ import { HMSDiagnosticsInterface } from '@100mslive/react-sdk';
3
+
4
+ export enum DiagnosticsStep {
5
+ BROWSER,
6
+ VIDEO,
7
+ AUDIO,
8
+ CONNECTIVITY,
9
+ }
10
+
11
+ export const initialSteps = {
12
+ [DiagnosticsStep.BROWSER]: { name: 'Browser Support' },
13
+ [DiagnosticsStep.VIDEO]: { name: 'Test Video' },
14
+ [DiagnosticsStep.AUDIO]: { name: 'Test Audio' },
15
+ [DiagnosticsStep.CONNECTIVITY]: { name: 'Connection Quality' },
16
+ };
17
+
18
+ export interface DiagnosticsStepInfo {
19
+ name: string;
20
+ hasFailed?: boolean;
21
+ isCompleted?: boolean;
22
+ }
23
+
24
+ export const DiagnosticsContext = React.createContext<{
25
+ hmsDiagnostics?: HMSDiagnosticsInterface;
26
+ activeStepIndex: DiagnosticsStep;
27
+ setActiveStep: React.Dispatch<React.SetStateAction<DiagnosticsStep>>;
28
+ steps: Record<DiagnosticsStep, DiagnosticsStepInfo>;
29
+ updateStep: (step: DiagnosticsStep, value: Omit<DiagnosticsStepInfo, 'name'>) => void;
30
+ }>({
31
+ activeStepIndex: 0,
32
+ setActiveStep: () => {
33
+ return;
34
+ },
35
+ steps: initialSteps,
36
+ updateStep: () => {
37
+ return;
38
+ },
39
+ });
40
+
41
+ export const useDiagnostics = () => {
42
+ const context = useContext(DiagnosticsContext);
43
+ const activeStep = context.steps[context.activeStepIndex];
44
+
45
+ return { ...context, activeStep };
46
+ };
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect, useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import {
3
3
  HMSException,
4
4
  selectDevices,
@@ -8,16 +8,17 @@ import {
8
8
  } from '@100mslive/react-sdk';
9
9
  import { VideoOnIcon } from '@100mslive/react-icons';
10
10
  import { PermissionErrorModal } from '../Prebuilt/components/Notifications/PermissionErrorModal';
11
- import { DiagnosticsContext, TestContainer, TestFooter } from './components';
11
+ import { TestContainer, TestFooter } from './components';
12
12
  import { Flex } from '../Layout';
13
13
  import { Text } from '../Text';
14
14
  import { Video } from '../Video';
15
15
  import { StyledVideoTile } from '../VideoTile';
16
16
  // @ts-ignore: No implicit any
17
17
  import { DeviceSelector } from './DeviceSelector';
18
+ import { DiagnosticsStep, useDiagnostics } from './DiagnosticsContext';
18
19
 
19
20
  export const VideoTest = () => {
20
- const { hmsDiagnostics } = useContext(DiagnosticsContext);
21
+ const { hmsDiagnostics, updateStep } = useDiagnostics();
21
22
  const allDevices = useHMSStore(selectDevices);
22
23
  const { videoInput } = allDevices;
23
24
  const trackID = useHMSStore(selectLocalVideoTrackID);
@@ -25,8 +26,11 @@ export const VideoTest = () => {
25
26
  const [error, setError] = useState<HMSException | undefined>();
26
27
 
27
28
  useEffect(() => {
28
- hmsDiagnostics?.startCameraCheck().catch(err => setError(err));
29
- }, [hmsDiagnostics]);
29
+ hmsDiagnostics?.startCameraCheck().catch(err => {
30
+ updateStep(DiagnosticsStep.VIDEO, { hasFailed: true });
31
+ setError(err);
32
+ });
33
+ }, [hmsDiagnostics, updateStep]);
30
34
 
31
35
  return (
32
36
  <>
@@ -1,33 +1,9 @@
1
- import React, { useContext } from 'react';
2
- import { HMSDiagnosticsInterface } from '@100mslive/react-sdk';
1
+ import React from 'react';
3
2
  import { Button } from '../Button';
4
3
  import { Box, Flex } from '../Layout';
5
4
  import { Text } from '../Text';
6
5
  import { CSS } from '../Theme';
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
- hmsDiagnostics?: HMSDiagnosticsInterface;
17
- activeStep: string;
18
- setActiveStep: React.Dispatch<React.SetStateAction<string>>;
19
- connectivityTested: boolean;
20
- setConnectivityTested: React.Dispatch<React.SetStateAction<boolean>>;
21
- }>({
22
- activeStep: 'video',
23
- setActiveStep: () => {
24
- return;
25
- },
26
- connectivityTested: false,
27
- setConnectivityTested: () => {
28
- return;
29
- },
30
- });
6
+ import { DiagnosticsStep, useDiagnostics } from './DiagnosticsContext';
31
7
 
32
8
  export const TestContainer = ({ css, children }: { css?: CSS; children: React.ReactNode }) => {
33
9
  return <Box css={{ p: '$10', ...css }}>{children}</Box>;
@@ -42,19 +18,18 @@ export const TestFooter = ({
42
18
  error?: Error;
43
19
  children?: React.ReactNode;
44
20
  }) => {
45
- const { hmsDiagnostics, activeStep, setActiveStep } = useContext(DiagnosticsContext);
21
+ const { hmsDiagnostics, activeStepIndex: activeStep, setActiveStep } = useDiagnostics();
46
22
 
47
23
  const onNextStep = () => {
48
- if (activeStep === 'audio') {
24
+ if (activeStep === DiagnosticsStep.AUDIO) {
49
25
  hmsDiagnostics?.stopMicCheck();
50
- } else if (activeStep === 'video') {
26
+ } else if (activeStep === DiagnosticsStep.VIDEO) {
51
27
  hmsDiagnostics?.stopCameraCheck();
52
- } else if (activeStep === 'connectivity') {
28
+ } else if (activeStep === DiagnosticsStep.CONNECTIVITY) {
53
29
  hmsDiagnostics?.stopConnectivityCheck();
54
30
  }
55
31
 
56
- const keys = Object.keys(DiagnosticsSteps);
57
- setActiveStep(step => keys[keys.indexOf(step) + 1]);
32
+ setActiveStep(step => step + 1);
58
33
  };
59
34
 
60
35
  return (