@fraku/video 0.0.1
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/README.md +2 -0
- package/package.json +75 -0
- package/src/App.tsx +7 -0
- package/src/components/ZoomVideoPlugin/ZoomVideoPlugin.stories.tsx +50 -0
- package/src/components/ZoomVideoPlugin/ZoomVideoPlugin.tsx +253 -0
- package/src/components/ZoomVideoPlugin/components/ButtonsDock/ButtonsDock.tsx +353 -0
- package/src/components/ZoomVideoPlugin/components/ButtonsDock/DockButton.tsx +90 -0
- package/src/components/ZoomVideoPlugin/components/ButtonsDock/MenuItemTemplate.tsx +35 -0
- package/src/components/ZoomVideoPlugin/components/ButtonsDock/index.ts +1 -0
- package/src/components/ZoomVideoPlugin/components/MobileIconButton/MobileIconButton.tsx +30 -0
- package/src/components/ZoomVideoPlugin/components/MobileIconButton/index.ts +1 -0
- package/src/components/ZoomVideoPlugin/components/Overlay/Overlay.tsx +74 -0
- package/src/components/ZoomVideoPlugin/components/Overlay/index.ts +1 -0
- package/src/components/ZoomVideoPlugin/components/ParticipantsList.tsx +52 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/SettingsContent.tsx +19 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/SettingsMenu.tsx +30 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/SettingsOverlay.tsx +52 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/Tabs/AudioSettings.tsx +191 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/Tabs/BackgroundSettings.tsx +47 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/Tabs/DropdownItemTemplate.tsx +20 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/Tabs/DropdownValueTemplate.tsx +12 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/Tabs/VideoSettings.tsx +30 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/context.ts +20 -0
- package/src/components/ZoomVideoPlugin/components/SettingsOverlay/index.ts +1 -0
- package/src/components/ZoomVideoPlugin/components/Video.tsx +35 -0
- package/src/components/ZoomVideoPlugin/constants.ts +4 -0
- package/src/components/ZoomVideoPlugin/context.ts +86 -0
- package/src/components/ZoomVideoPlugin/hooks/useClientMessages.ts +142 -0
- package/src/components/ZoomVideoPlugin/hooks/useDeviceSize.ts +24 -0
- package/src/components/ZoomVideoPlugin/hooks/useStartVideoOptions.ts +14 -0
- package/src/components/ZoomVideoPlugin/hooks/useZoomVideoPlayer.tsx +142 -0
- package/src/components/ZoomVideoPlugin/index.ts +2 -0
- package/src/components/ZoomVideoPlugin/lib/platforms.ts +17 -0
- package/src/components/ZoomVideoPlugin/pages/AfterSession.tsx +14 -0
- package/src/components/ZoomVideoPlugin/pages/MainSession.tsx +53 -0
- package/src/components/ZoomVideoPlugin/pages/PanelistsSession.tsx +97 -0
- package/src/components/ZoomVideoPlugin/pages/PreSessionConfiguration.tsx +154 -0
- package/src/components/ZoomVideoPlugin/types.global.d.ts +15 -0
- package/src/components/ZoomVideoPlugin/types.ts +23 -0
- package/src/global.d.ts +46 -0
- package/src/index.css +4 -0
- package/src/index.ts +4 -0
- package/src/main.tsx +10 -0
- package/src/vite-env.d.ts +12 -0
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fraku/video",
|
|
3
|
+
"private": false,
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./dist/index.css": "./dist/index.css",
|
|
16
|
+
"./src": "./src/index.ts"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"src"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"dev": "vite",
|
|
24
|
+
"build": "tsc && vite build",
|
|
25
|
+
"build:css": "tailwindcss -c ./tailwind.config.js -i ./src/index.css -o ./dist/index.css --minify",
|
|
26
|
+
"watch:css": "tailwindcss -c ./tailwind.config.js -i ./src/index.css -o ./dist/index.css --watch",
|
|
27
|
+
"lint": "tsc --noEmit && eslint . --ext ts,tsx --report-unused-disable-directives",
|
|
28
|
+
"preview": "vite preview",
|
|
29
|
+
"prepublishOnly": "npm run build",
|
|
30
|
+
"storybook": "storybook dev -p 6006 --no-open",
|
|
31
|
+
"test": "react-app-rewired test"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"react": "^18.2.0",
|
|
35
|
+
"react-dom": "^18.2.0"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@zoom/videosdk": "^2.2.12",
|
|
39
|
+
"classnames": "^2.5.1",
|
|
40
|
+
"primeicons": "^7.0.0",
|
|
41
|
+
"primereact": "^10.9.6",
|
|
42
|
+
"react-use": "^17.6.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@storybook/react-vite": "^9.1.13",
|
|
46
|
+
"@types/node": "^24.8.1",
|
|
47
|
+
"@types/react": "^18.2.43",
|
|
48
|
+
"@types/react-dom": "^18.2.17",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
|
50
|
+
"@typescript-eslint/parser": "^6.14.0",
|
|
51
|
+
"@vitejs/plugin-react": "^4.2.1",
|
|
52
|
+
"autoprefixer": "^10.4.21",
|
|
53
|
+
"eslint": "^8.55.0",
|
|
54
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
55
|
+
"eslint-plugin-react-refresh": "^0.4.5",
|
|
56
|
+
"eslint-plugin-storybook": "^9.1.13",
|
|
57
|
+
"postcss": "^8.5.6",
|
|
58
|
+
"react": "^18.2.0",
|
|
59
|
+
"react-dom": "^18.2.0",
|
|
60
|
+
"storybook": "^9.1.13",
|
|
61
|
+
"tailwindcss": "^3.4.17",
|
|
62
|
+
"typescript": "^5.2.2",
|
|
63
|
+
"vite": "^5.0.8",
|
|
64
|
+
"vite-plugin-dts": "^3.6.4"
|
|
65
|
+
},
|
|
66
|
+
"keywords": [
|
|
67
|
+
"react",
|
|
68
|
+
"typescript",
|
|
69
|
+
"component",
|
|
70
|
+
"library"
|
|
71
|
+
],
|
|
72
|
+
"author": "",
|
|
73
|
+
"license": "MIT",
|
|
74
|
+
"description": "A React TypeScript component library"
|
|
75
|
+
}
|
package/src/App.tsx
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import ZoomVideoPlugin from './ZoomVideoPlugin'
|
|
3
|
+
import type { Credentials } from './types'
|
|
4
|
+
|
|
5
|
+
// Load credentials from environment variables
|
|
6
|
+
const credentials: Credentials = {
|
|
7
|
+
sessionName: import.meta.env.VITE_ZOOM_SESSION_NAME || '',
|
|
8
|
+
signature: import.meta.env.VITE_ZOOM_SIGNATURE || '',
|
|
9
|
+
userName: import.meta.env.VITE_ZOOM_USER_NAME || 'Storybook User',
|
|
10
|
+
sessionPasscode: import.meta.env.VITE_ZOOM_SESSION_PASSCODE || ''
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const meta = {
|
|
14
|
+
title: 'Components/ZoomVideoPlugin',
|
|
15
|
+
component: ZoomVideoPlugin,
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: 'fullscreen'
|
|
18
|
+
},
|
|
19
|
+
tags: ['autodocs'],
|
|
20
|
+
argTypes: {
|
|
21
|
+
credentials: {
|
|
22
|
+
description: 'Zoom Video SDK credentials for the session',
|
|
23
|
+
control: 'object'
|
|
24
|
+
},
|
|
25
|
+
closeParentContainer: {
|
|
26
|
+
description: 'Callback function to close the parent container',
|
|
27
|
+
action: 'closeParentContainer'
|
|
28
|
+
},
|
|
29
|
+
setIsCloseButtonVisible: {
|
|
30
|
+
description: 'Setter for close button visibility',
|
|
31
|
+
action: 'setIsCloseButtonVisible'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
} satisfies Meta<typeof ZoomVideoPlugin>
|
|
35
|
+
|
|
36
|
+
export default meta
|
|
37
|
+
type Story = StoryObj<typeof meta>
|
|
38
|
+
|
|
39
|
+
export const Default: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
credentials,
|
|
42
|
+
closeParentContainer: () => {
|
|
43
|
+
console.log('Close parent container called')
|
|
44
|
+
},
|
|
45
|
+
setIsCloseButtonVisible: (value: boolean | ((prev: boolean) => boolean)) => {
|
|
46
|
+
console.log('Set close button visible:', value)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
Default.storyName = 'ZoomVideoPlugin'
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import ZoomVideo, { ActiveSpeaker, ConnectionState, MediaDevice, type Participant, type Stream } from '@zoom/videosdk'
|
|
3
|
+
import { useEffectOnce } from 'react-use'
|
|
4
|
+
import PreSessionConfiguration from './pages/PreSessionConfiguration'
|
|
5
|
+
import PanelistsSession from './pages/PanelistsSession'
|
|
6
|
+
import MainSession from './pages/MainSession'
|
|
7
|
+
import AfterSession from './pages/AfterSession'
|
|
8
|
+
import { useClientMessages } from './hooks/useClientMessages'
|
|
9
|
+
import { zmClient, ZoomVideoContext, ZoomVideoContextType } from './context'
|
|
10
|
+
import { SessionStep, type ZoomVideoPluginProps } from './types'
|
|
11
|
+
import { useContainerSize } from './hooks/useDeviceSize'
|
|
12
|
+
|
|
13
|
+
const fetchDevices = async () => {
|
|
14
|
+
try {
|
|
15
|
+
const devices: MediaDeviceInfo[] = await ZoomVideo.getDevices()
|
|
16
|
+
|
|
17
|
+
const micList = devices.filter((d) => d.kind === 'audioinput')
|
|
18
|
+
const speakerList = devices.filter((d) => d.kind === 'audiooutput')
|
|
19
|
+
const cameraList = devices.filter((d) => d.kind === 'videoinput')
|
|
20
|
+
|
|
21
|
+
return { micList, speakerList, cameraList }
|
|
22
|
+
} catch (e) {
|
|
23
|
+
return { micList: [], speakerList: [], cameraList: [] }
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const ZoomVideoPlugin = ({ credentials, closeParentContainer, setIsCloseButtonVisible }: ZoomVideoPluginProps) => {
|
|
28
|
+
const { ref, breakpoint } = useContainerSize()
|
|
29
|
+
const [isBlurred, setIsBlurred] = useState(false)
|
|
30
|
+
const [mediaStream, setMediaStream] = useState<typeof Stream | null>(null)
|
|
31
|
+
const [sessionStep, setSessionStep] = useState<SessionStep | null>(null)
|
|
32
|
+
const [participants, setParticipants] = useState<Participant[]>([])
|
|
33
|
+
const [activeVideoId, setActiveVideoId] = useState<number | null>(null)
|
|
34
|
+
const [activeSpeakers, setActiveSpeakers] = useState<ActiveSpeaker[]>([])
|
|
35
|
+
const [connectionState, setConnectionState] = useState<ConnectionState | null>(null)
|
|
36
|
+
|
|
37
|
+
const [localAudio, setLocalAudio] = useState(() => ZoomVideo.createLocalAudioTrack())
|
|
38
|
+
const [localVideo, setLocalVideo] = useState(() => ZoomVideo.createLocalVideoTrack())
|
|
39
|
+
const [activeMicrophone, setActiveMicrophone] = useState<string | undefined>()
|
|
40
|
+
const [activeAudioOutput, setActiveAudioOutput] = useState<string | undefined>()
|
|
41
|
+
const [activeCamera, setActiveCamera] = useState<string | undefined>()
|
|
42
|
+
const [micList, setMicList] = useState<MediaDevice[]>([])
|
|
43
|
+
const [audioOutputList, setAudioOutputList] = useState<MediaDevice[]>([])
|
|
44
|
+
const [cameraList, setCameraList] = useState<MediaDevice[]>([])
|
|
45
|
+
const [isCamOn, setIsCamOn] = useState(true)
|
|
46
|
+
const [isMicOn, setIsMicOn] = useState(true)
|
|
47
|
+
|
|
48
|
+
const initSession = useCallback(async () => {
|
|
49
|
+
if (connectionState === ConnectionState.Closed) return
|
|
50
|
+
try {
|
|
51
|
+
await zmClient.init('en-US', 'Global', {
|
|
52
|
+
webEndpoint: window?.webEndpoint ?? 'zoom.us',
|
|
53
|
+
stayAwake: true,
|
|
54
|
+
patchJsMedia: true,
|
|
55
|
+
leaveOnPageUnload: false,
|
|
56
|
+
enforceMultipleVideos: true // Enforces multiple videos if true (up to 3 videos of others and 1 video of self) on platform without SharedArrayBuffer.
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
if (zmClient.getSessionInfo()) {
|
|
60
|
+
setSessionStep(SessionStep.LocalSettingsConfiguration)
|
|
61
|
+
setIsCloseButtonVisible(true)
|
|
62
|
+
}
|
|
63
|
+
} catch (e) {
|
|
64
|
+
console.log('error init: ', e)
|
|
65
|
+
}
|
|
66
|
+
}, [connectionState, setIsCloseButtonVisible])
|
|
67
|
+
|
|
68
|
+
const joinSession = useCallback(async () => {
|
|
69
|
+
if (connectionState === ConnectionState.Closed) return
|
|
70
|
+
try {
|
|
71
|
+
const { sessionName, signature, userName, sessionPasscode } = credentials ?? {}
|
|
72
|
+
if (!sessionName || !signature || !userName || !sessionPasscode) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
await zmClient.join(sessionName, signature, userName, sessionPasscode)
|
|
77
|
+
const stream = zmClient.getMediaStream()
|
|
78
|
+
setMediaStream(stream)
|
|
79
|
+
setSessionStep(SessionStep.OnlyPanelistsSession)
|
|
80
|
+
setIsCloseButtonVisible(false)
|
|
81
|
+
} catch (e: any) {
|
|
82
|
+
console.log('error join: ', e)
|
|
83
|
+
}
|
|
84
|
+
}, [connectionState, credentials, setIsCloseButtonVisible])
|
|
85
|
+
|
|
86
|
+
const startMainSession = useCallback(() => {
|
|
87
|
+
setSessionStep(SessionStep.MainSession)
|
|
88
|
+
setIsCloseButtonVisible(false)
|
|
89
|
+
}, [setIsCloseButtonVisible])
|
|
90
|
+
|
|
91
|
+
const stopSession = useCallback(async () => {
|
|
92
|
+
console.log('Stopping session...')
|
|
93
|
+
|
|
94
|
+
if (zmClient.getSessionInfo()?.isInMeeting) {
|
|
95
|
+
try {
|
|
96
|
+
await zmClient?.leave()
|
|
97
|
+
ZoomVideo.destroyClient()
|
|
98
|
+
} catch (e) {
|
|
99
|
+
console.warn('Leave session failed', e)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
await localAudio?.stop().catch(console.warn)
|
|
103
|
+
await localVideo?.stop().catch(console.warn)
|
|
104
|
+
|
|
105
|
+
setMediaStream(null)
|
|
106
|
+
|
|
107
|
+
setSessionStep(SessionStep.AfterSession)
|
|
108
|
+
setIsCloseButtonVisible(true)
|
|
109
|
+
}, [localAudio, localVideo, setIsCloseButtonVisible])
|
|
110
|
+
|
|
111
|
+
const switchActiveMicrophone = useCallback(
|
|
112
|
+
async (deviceId: string) => {
|
|
113
|
+
if (sessionStep === SessionStep.LocalSettingsConfiguration) {
|
|
114
|
+
if (!localAudio) return
|
|
115
|
+
if (!isMicOn) return
|
|
116
|
+
await localAudio.stop().catch(console.warn)
|
|
117
|
+
setLocalAudio(ZoomVideo.createLocalAudioTrack(deviceId))
|
|
118
|
+
await localAudio.start().catch(console.warn)
|
|
119
|
+
setActiveMicrophone(deviceId)
|
|
120
|
+
} else {
|
|
121
|
+
if (!mediaStream) return
|
|
122
|
+
await mediaStream.switchMicrophone(deviceId)
|
|
123
|
+
setActiveMicrophone(deviceId)
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
[isMicOn, localAudio, mediaStream, sessionStep]
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
const switchActiveAudioOutput = useCallback(
|
|
130
|
+
async (deviceId: string) => {
|
|
131
|
+
setActiveAudioOutput(deviceId)
|
|
132
|
+
if (!mediaStream) return
|
|
133
|
+
await mediaStream.switchSpeaker(deviceId).catch(console.warn)
|
|
134
|
+
},
|
|
135
|
+
[mediaStream]
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
const doRestart = useCallback(async () => {
|
|
139
|
+
setConnectionState(null)
|
|
140
|
+
setMediaStream(null)
|
|
141
|
+
setParticipants([])
|
|
142
|
+
setActiveVideoId(null)
|
|
143
|
+
await initSession()
|
|
144
|
+
}, [initSession])
|
|
145
|
+
|
|
146
|
+
useClientMessages({
|
|
147
|
+
zmClient,
|
|
148
|
+
mediaStream,
|
|
149
|
+
setActiveMicrophone,
|
|
150
|
+
setActiveAudioOutput,
|
|
151
|
+
setActiveCamera,
|
|
152
|
+
setMicList,
|
|
153
|
+
setAudioOutputList,
|
|
154
|
+
setCameraList,
|
|
155
|
+
setConnectionState,
|
|
156
|
+
setIsCamOn,
|
|
157
|
+
setIsMicOn,
|
|
158
|
+
setParticipants,
|
|
159
|
+
setActiveVideoId,
|
|
160
|
+
setActiveSpeakers,
|
|
161
|
+
setHandRaises: () => {}
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
useEffect(() => {
|
|
165
|
+
if (!credentials?.signature) return
|
|
166
|
+
initSession()
|
|
167
|
+
}, [initSession, credentials?.signature])
|
|
168
|
+
|
|
169
|
+
useEffectOnce(() => {
|
|
170
|
+
fetchDevices().then(({ micList, speakerList, cameraList }) => {
|
|
171
|
+
setMicList(micList)
|
|
172
|
+
setAudioOutputList(speakerList)
|
|
173
|
+
setCameraList(cameraList)
|
|
174
|
+
setActiveMicrophone(micList[0]?.deviceId)
|
|
175
|
+
setActiveAudioOutput(speakerList[0]?.deviceId)
|
|
176
|
+
setActiveCamera(cameraList[0]?.deviceId)
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
const ctxValue = useMemo<ZoomVideoContextType>(() => {
|
|
181
|
+
return {
|
|
182
|
+
activeCamera,
|
|
183
|
+
activeMicrophone,
|
|
184
|
+
activeAudioOutput,
|
|
185
|
+
activeSpeakers,
|
|
186
|
+
activeVideoId,
|
|
187
|
+
audioOutputList,
|
|
188
|
+
breakpoint,
|
|
189
|
+
cameraList,
|
|
190
|
+
closeParentContainer,
|
|
191
|
+
connectionState,
|
|
192
|
+
isBlurred,
|
|
193
|
+
isCamOn,
|
|
194
|
+
isMicOn,
|
|
195
|
+
localAudio,
|
|
196
|
+
localVideo,
|
|
197
|
+
mediaStream,
|
|
198
|
+
micList,
|
|
199
|
+
participants,
|
|
200
|
+
setActiveCamera,
|
|
201
|
+
setCameraList,
|
|
202
|
+
setIsBlurred,
|
|
203
|
+
setIsCamOn,
|
|
204
|
+
setIsMicOn,
|
|
205
|
+
setLocalAudio,
|
|
206
|
+
setLocalVideo,
|
|
207
|
+
setMediaStream,
|
|
208
|
+
setMicList,
|
|
209
|
+
setParticipants,
|
|
210
|
+
switchActiveAudioOutput,
|
|
211
|
+
switchActiveMicrophone,
|
|
212
|
+
stopSession,
|
|
213
|
+
zmClient
|
|
214
|
+
}
|
|
215
|
+
}, [
|
|
216
|
+
activeCamera,
|
|
217
|
+
activeMicrophone,
|
|
218
|
+
activeAudioOutput,
|
|
219
|
+
activeSpeakers,
|
|
220
|
+
activeVideoId,
|
|
221
|
+
audioOutputList,
|
|
222
|
+
breakpoint,
|
|
223
|
+
cameraList,
|
|
224
|
+
closeParentContainer,
|
|
225
|
+
connectionState,
|
|
226
|
+
isBlurred,
|
|
227
|
+
isCamOn,
|
|
228
|
+
isMicOn,
|
|
229
|
+
localAudio,
|
|
230
|
+
localVideo,
|
|
231
|
+
mediaStream,
|
|
232
|
+
micList,
|
|
233
|
+
participants,
|
|
234
|
+
stopSession,
|
|
235
|
+
switchActiveAudioOutput,
|
|
236
|
+
switchActiveMicrophone
|
|
237
|
+
])
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<ZoomVideoContext.Provider value={ctxValue}>
|
|
241
|
+
<div ref={ref} className="w-full h-full @container">
|
|
242
|
+
{sessionStep === SessionStep.LocalSettingsConfiguration && (
|
|
243
|
+
<PreSessionConfiguration joinSession={joinSession} />
|
|
244
|
+
)}
|
|
245
|
+
{sessionStep === SessionStep.OnlyPanelistsSession && <PanelistsSession initMainSession={startMainSession} />}
|
|
246
|
+
{sessionStep === SessionStep.MainSession && <MainSession />}
|
|
247
|
+
{sessionStep === SessionStep.AfterSession && <AfterSession restartSession={doRestart} />}
|
|
248
|
+
</div>
|
|
249
|
+
</ZoomVideoContext.Provider>
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export default ZoomVideoPlugin
|