@100mslive/roomkit-react 0.3.15-alpha.1 → 0.3.15-alpha.3

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,35 +1,68 @@
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 }) => (
21
34
  <Box
22
35
  css={{
23
36
  px: '120px',
24
- py: '120px',
37
+ pt: '120px',
38
+ pb: '24px',
25
39
  bg: '$background_dim',
26
40
  lineHeight: '1.5',
27
41
  '-webkit-text-size-adjust': '100%',
28
42
  position: 'relative',
29
- minHeight: '100vh',
43
+ h: '100%',
30
44
  '@lg': {
31
45
  p: '$12',
32
46
  },
47
+ overflowY: 'auto',
48
+ boxSizing: 'border-box',
49
+ '& *': {
50
+ boxSizing: 'border-box',
51
+ },
52
+ '::-webkit-scrollbar-track': {
53
+ WebkitBoxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)',
54
+ boxShadow: 'inset 0 0 6px rgba(0, 0, 0, 0.3)',
55
+ backgroundColor: 'transparent',
56
+ },
57
+ '::-webkit-scrollbar': {
58
+ width: '6px',
59
+ height: '6px',
60
+ backgroundColor: 'transparent',
61
+ },
62
+ '::-webkit-scrollbar-thumb': {
63
+ backgroundColor: '#657080',
64
+ borderRadius: '5px',
65
+ },
33
66
  }}
34
67
  >
35
68
  {children}
@@ -37,92 +70,99 @@ const Container = ({ children }: { children: React.ReactNode }) => (
37
70
  );
38
71
 
39
72
  const DiagnosticsStepTest = () => {
40
- const { activeStep } = useContext(DiagnosticsContext);
73
+ const { activeStepIndex } = useDiagnostics();
41
74
 
42
75
  let TestComponent = () => <></>;
43
76
 
44
- if (activeStep === 'audio') {
77
+ if (activeStepIndex === DiagnosticsStep.AUDIO) {
45
78
  TestComponent = AudioTest;
46
- } else if (activeStep === 'video') {
79
+ } else if (activeStepIndex === DiagnosticsStep.VIDEO) {
47
80
  TestComponent = VideoTest;
48
- } else if (activeStep === 'browser') {
81
+ } else if (activeStepIndex === DiagnosticsStep.BROWSER) {
49
82
  TestComponent = BrowserTest;
50
- } else if (activeStep === 'connectivity') {
83
+ } else if (activeStepIndex === DiagnosticsStep.CONNECTIVITY) {
51
84
  TestComponent = ConnectivityTest;
52
85
  }
53
86
 
54
- return <TestComponent key={activeStep} />;
87
+ return <TestComponent key={activeStepIndex} />;
55
88
  };
56
89
 
57
90
  const DiagnosticsStepHeader = () => {
58
- const { activeStep } = useContext(DiagnosticsContext);
91
+ const { activeStepIndex, activeStep } = useDiagnostics();
59
92
  return (
60
93
  <Flex css={{ py: '$8', px: '$10', alignItems: 'center', borderBottom: '1px solid $border_default' }}>
61
- <Text css={{ c: '$primary_bright', mt: '$xs' }}>{DiagnosticsStepIcon[activeStep]}</Text>
62
- <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>
63
96
  </Flex>
64
97
  );
65
98
  };
66
99
 
67
- const DiagnosticsStep = () => {
100
+ const DiagnosticsStepContainer = () => {
68
101
  return (
69
102
  <Box css={{ border: '1px solid $border_default', r: '$1', w: '75%', maxWidth: '65rem', '@lg': { w: '100%' } }}>
70
103
  <DiagnosticsStepHeader />
71
- <Box css={{ maxHeight: '55vh', overflowY: 'auto' }}>
72
- <DiagnosticsStepTest />
73
- </Box>
104
+ <DiagnosticsStepTest />
74
105
  </Box>
75
106
  );
76
107
  };
77
108
 
78
109
  const DiagnosticsStepsList = () => {
79
- const { activeStep, connectivityTested } = useContext(DiagnosticsContext);
110
+ const { activeStepIndex, activeStep, steps } = useDiagnostics();
80
111
 
81
112
  return (
82
113
  <Box css={{ w: '25%', '@lg': { display: 'none' } }}>
83
- {Object.keys(DiagnosticsSteps).map(key => {
84
- const keys = Object.keys(DiagnosticsSteps);
85
- const activeStepIndex = keys.indexOf(activeStep);
86
- const keyIndex = keys.indexOf(key);
87
- const isStepCompleted = activeStepIndex > keyIndex || (activeStep === 'connectivity' && connectivityTested);
88
-
89
- let color = '$on_primary_low';
90
- if (activeStep === key) {
91
- color = '$on_primary_high';
92
- }
93
- if (isStepCompleted) {
94
- color = '$primary_bright';
95
- }
96
-
97
- return (
98
- <Flex key={key} css={{ mb: '$10', c: color, gap: '$4', alignItems: 'center' }}>
99
- {isStepCompleted ? (
100
- <CheckCircleIcon width="1rem" height="1rem" />
101
- ) : (
102
- <Text css={{ c: color, fontSize: '1.75rem' }}>&bull;</Text>
103
- )}
104
- <Text css={{ c: color }}>{DiagnosticsSteps[key]}</Text>
105
- </Flex>
106
- );
107
- })}
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
+ })}
108
144
  </Box>
109
145
  );
110
146
  };
111
147
 
112
148
  const DiagnosticsProvider = () => {
113
149
  const actions = useHMSActions();
114
- const [activeStep, setActiveStep] = useState(Object.keys(DiagnosticsSteps)[0]);
115
- const [connectivityTested, setConnectivityTested] = useState(false);
150
+ const [activeStep, setActiveStep] = useState(0);
151
+ const [steps, setSteps] = useState(initialSteps);
116
152
  const diagnosticsRef = useRef(actions.initDiagnostics());
117
153
 
154
+ const updateStep = useCallback((step: DiagnosticsStep, value: Omit<DiagnosticsStepInfo, 'name'>) => {
155
+ setSteps(prevSteps => ({ ...prevSteps, [step]: { ...prevSteps[step], ...value } }));
156
+ }, []);
157
+
118
158
  return (
119
159
  <DiagnosticsContext.Provider
120
160
  value={{
121
161
  hmsDiagnostics: diagnosticsRef.current,
122
- activeStep,
162
+ activeStepIndex: activeStep,
123
163
  setActiveStep,
124
- connectivityTested,
125
- setConnectivityTested,
164
+ steps,
165
+ updateStep,
126
166
  }}
127
167
  >
128
168
  <Container>
@@ -132,7 +172,7 @@ const DiagnosticsProvider = () => {
132
172
  </Text>
133
173
  <Flex css={{ direction: 'column', mt: '$12', justifyItems: 'center' }}>
134
174
  <DiagnosticsStepsList />
135
- <DiagnosticsStep />
175
+ <DiagnosticsStepContainer />
136
176
  </Flex>
137
177
  </Container>
138
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 (
@@ -62,8 +37,6 @@ export const TestFooter = ({
62
37
  css={{
63
38
  py: '$8',
64
39
  px: '$10',
65
- position: 'sticky',
66
- bottom: '0',
67
40
  background: '$background_dim',
68
41
  justifyContent: 'space-between',
69
42
  alignItems: 'center',