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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 (