@tellescope/video-chat 0.0.15 → 0.0.19
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/lib/cjs/controls.d.ts +18 -0
- package/lib/cjs/controls.d.ts.map +1 -0
- package/lib/cjs/controls.js +57 -0
- package/lib/cjs/controls.js.map +1 -0
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +1 -0
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/index.native.d.ts +1 -0
- package/lib/cjs/index.native.d.ts.map +1 -1
- package/lib/cjs/index.native.js +1 -0
- package/lib/cjs/index.native.js.map +1 -1
- package/lib/cjs/native/RNVideoRenderView.d.ts +1 -1
- package/lib/cjs/native/RNVideoRenderView.d.ts.map +1 -1
- package/lib/cjs/native/RNVideoRenderView.js.map +1 -1
- package/lib/cjs/video.d.ts +12 -2
- package/lib/cjs/video.d.ts.map +1 -1
- package/lib/cjs/video.js +37 -5
- package/lib/cjs/video.js.map +1 -1
- package/lib/cjs/video.native.d.ts +7 -1
- package/lib/cjs/video.native.d.ts.map +1 -1
- package/lib/cjs/video.native.js +61 -13
- package/lib/cjs/video.native.js.map +1 -1
- package/lib/esm/controls.d.ts +18 -0
- package/lib/esm/controls.d.ts.map +1 -0
- package/lib/esm/controls.js +46 -0
- package/lib/esm/controls.js.map +1 -0
- package/lib/esm/index.d.ts +1 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +1 -0
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/index.native.d.ts +1 -0
- package/lib/esm/index.native.d.ts.map +1 -1
- package/lib/esm/index.native.js +1 -0
- package/lib/esm/index.native.js.map +1 -1
- package/lib/esm/native/RNVideoRenderView.d.ts +1 -1
- package/lib/esm/native/RNVideoRenderView.d.ts.map +1 -1
- package/lib/esm/native/RNVideoRenderView.js.map +1 -1
- package/lib/esm/shared.d.ts +1 -0
- package/lib/esm/shared.d.ts.map +1 -0
- package/lib/esm/shared.js +2 -0
- package/lib/esm/shared.js.map +1 -0
- package/lib/esm/video.d.ts +12 -2
- package/lib/esm/video.d.ts.map +1 -1
- package/lib/esm/video.js +39 -5
- package/lib/esm/video.js.map +1 -1
- package/lib/esm/video.native.d.ts +7 -1
- package/lib/esm/video.native.d.ts.map +1 -1
- package/lib/esm/video.native.js +58 -12
- package/lib/esm/video.native.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/controls.tsx +86 -0
- package/src/index.native.ts +2 -1
- package/src/index.ts +2 -1
- package/src/native/RNVideoRenderView.tsx +1 -1
- package/src/video.native.tsx +65 -7
- package/src/video.tsx +43 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellescope/video-chat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
"@fontsource/roboto": "^4.5.1",
|
|
34
34
|
"@mui/icons-material": "^5.0.1",
|
|
35
35
|
"@mui/material": "^5.0.2",
|
|
36
|
-
"@tellescope/constants": "^0.0.
|
|
37
|
-
"@tellescope/react-components": "^0.0.
|
|
38
|
-
"@tellescope/sdk": "^0.0.
|
|
39
|
-
"@tellescope/types-client": "^0.0.
|
|
40
|
-
"@tellescope/types-models": "^0.0.
|
|
41
|
-
"@tellescope/types-utilities": "^0.0.
|
|
42
|
-
"@tellescope/utilities": "^0.0.
|
|
36
|
+
"@tellescope/constants": "^0.0.19",
|
|
37
|
+
"@tellescope/react-components": "^0.0.19",
|
|
38
|
+
"@tellescope/sdk": "^0.0.19",
|
|
39
|
+
"@tellescope/types-client": "^0.0.19",
|
|
40
|
+
"@tellescope/types-models": "^0.0.19",
|
|
41
|
+
"@tellescope/types-utilities": "^0.0.19",
|
|
42
|
+
"@tellescope/utilities": "^0.0.19",
|
|
43
43
|
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
|
44
44
|
"@typescript-eslint/parser": "^4.33.0",
|
|
45
45
|
"amazon-chime-sdk-component-library-react": "^2.12.0",
|
|
46
|
-
"amazon-chime-sdk-js": "^2.
|
|
46
|
+
"amazon-chime-sdk-js": "^2.24.0",
|
|
47
47
|
"eslint": "^7.32.0",
|
|
48
48
|
"eslint-plugin-react": "^7.26.1",
|
|
49
49
|
"nodemon": "^2.0.13",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"react": "^17.0.2",
|
|
55
55
|
"react-dom": "^17.0.2"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "ddee8ca945d3daf7355a9eada1305666e56d7434",
|
|
58
58
|
"publishConfig": {
|
|
59
59
|
"access": "public"
|
|
60
60
|
}
|
package/src/controls.tsx
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// components that work with web or native
|
|
2
|
+
import React from "react"
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
VideoIcon,
|
|
6
|
+
VideoOffIcon,
|
|
7
|
+
MicrophoneIcon,
|
|
8
|
+
MicrophoneOffIcon,
|
|
9
|
+
CallEndIcon,
|
|
10
|
+
|
|
11
|
+
Paper,
|
|
12
|
+
|
|
13
|
+
Styled,
|
|
14
|
+
} from "@tellescope/react-components/lib/esm/mui"
|
|
15
|
+
import { LabeledIconButton } from "@tellescope/react-components/lib/esm/controls"
|
|
16
|
+
import { Flex } from "@tellescope/react-components/lib/esm/layout"
|
|
17
|
+
import {
|
|
18
|
+
CurrentCallContext,
|
|
19
|
+
useStartVideoCall,
|
|
20
|
+
} from "./video"
|
|
21
|
+
|
|
22
|
+
const DEFAULT_BUTTON_SIZE = 30
|
|
23
|
+
interface ButtonProps {
|
|
24
|
+
size?: number,
|
|
25
|
+
}
|
|
26
|
+
export const VideoToggle = ({ size=DEFAULT_BUTTON_SIZE } : ButtonProps) => {
|
|
27
|
+
const { toggleVideo, videoIsEnabled } = React.useContext(CurrentCallContext)
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<LabeledIconButton size={size} Icon={videoIsEnabled ? VideoIcon : VideoOffIcon} onClick={toggleVideo}
|
|
31
|
+
label={videoIsEnabled ? "Turn Camera Off" : "Turn Camera On"}
|
|
32
|
+
/>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const MicrophoneToggle = ({ size=DEFAULT_BUTTON_SIZE }: ButtonProps) => {
|
|
37
|
+
const { microphoneIsEnabled, toggleMicrophone } = React.useContext(CurrentCallContext)
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<LabeledIconButton size={size} Icon={microphoneIsEnabled ? MicrophoneIcon : MicrophoneOffIcon} onClick={toggleMicrophone}
|
|
41
|
+
label={microphoneIsEnabled ? "Turn Microphone Off" : "Turn Microphone On"}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ends meeting if host, otherwise leaves meeting
|
|
47
|
+
export const EndMeeting = ({ size=DEFAULT_BUTTON_SIZE }: ButtonProps) => {
|
|
48
|
+
const { endMeeting } = useStartVideoCall()
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<LabeledIconButton size={size} Icon={CallEndIcon} onClick={endMeeting} label="End Meeting"/>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface LeaveMeetingProps {
|
|
56
|
+
onLeave?: () => void,
|
|
57
|
+
}
|
|
58
|
+
export const LeaveMeeting = ({ onLeave, size=DEFAULT_BUTTON_SIZE } : LeaveMeetingProps & ButtonProps) => (
|
|
59
|
+
<LabeledIconButton size={size} Icon={CallEndIcon} onClick={onLeave} label="Leave Meeting"/>
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
interface ControlbarProps {
|
|
63
|
+
spacing?: number,
|
|
64
|
+
size?: number,
|
|
65
|
+
|
|
66
|
+
}
|
|
67
|
+
export const ControlBar = ({ onLeave, style, spacing=15, size } : ControlbarProps & LeaveMeetingProps & Styled) => {
|
|
68
|
+
const { isHost } = React.useContext(CurrentCallContext)
|
|
69
|
+
const itemStyle = { marginLeft: spacing, marginRight: spacing }
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Flex flex={1} alignItems="center" justifyContent="center" style={style}>
|
|
73
|
+
<Paper elevation={5} style={{ display: 'flex', flexDirection: 'row', padding: spacing }}>
|
|
74
|
+
<Flex style={itemStyle}>
|
|
75
|
+
<VideoToggle size={size}/>
|
|
76
|
+
</Flex>
|
|
77
|
+
<Flex style={itemStyle}>
|
|
78
|
+
<MicrophoneToggle size={size}/>
|
|
79
|
+
</Flex>
|
|
80
|
+
<Flex style={itemStyle}>
|
|
81
|
+
{isHost ? <EndMeeting size={size}/> : <LeaveMeeting size={size} onLeave={onLeave}/>}
|
|
82
|
+
</Flex>
|
|
83
|
+
</Paper>
|
|
84
|
+
</Flex>
|
|
85
|
+
)
|
|
86
|
+
}
|
package/src/index.native.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export * from "./video"
|
|
1
|
+
export * from "./video"
|
|
2
|
+
export * from "./controls"
|
package/src/index.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export * from "./video";
|
|
1
|
+
export * from "./video";
|
|
2
|
+
export * from "./controls"
|
|
@@ -8,7 +8,7 @@ import React from 'react';
|
|
|
8
8
|
import { requireNativeComponent, findNodeHandle, ViewStyle } from 'react-native';
|
|
9
9
|
import { NativeFunction } from './bridge';
|
|
10
10
|
|
|
11
|
-
export class RNVideoView extends React.Component<{ tileId:
|
|
11
|
+
export class RNVideoView extends React.Component<{ tileId: number, style?: ViewStyle }> {
|
|
12
12
|
componentDidMount() {
|
|
13
13
|
// we need to delay the bind video
|
|
14
14
|
// Because "componentDidMount" will be called "immediately after the initial rendering occurs"
|
package/src/video.native.tsx
CHANGED
|
@@ -17,14 +17,24 @@ import {
|
|
|
17
17
|
} from '@tellescope/types-utilities'
|
|
18
18
|
import { useSession } from "@tellescope/react-components/lib/esm/authentication"
|
|
19
19
|
import { Flex } from "@tellescope/react-components/lib/esm/layout"
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
Button,
|
|
22
|
+
Typography,
|
|
23
|
+
convert_CSS_to_RNStyles,
|
|
24
|
+
|
|
25
|
+
VideoIcon,
|
|
26
|
+
VideoOffIcon,
|
|
27
|
+
MicrophoneIcon,
|
|
28
|
+
MicrophoneOffIcon,
|
|
29
|
+
} from "@tellescope/react-components/lib/esm/mui.native"
|
|
21
30
|
|
|
22
31
|
import {
|
|
23
32
|
CurrentCallContext,
|
|
24
33
|
JoinVideoCallReturnType,
|
|
25
34
|
StartVideoCallReturnType,
|
|
26
35
|
VideoProps,
|
|
27
|
-
AttendeeDisplayInfo
|
|
36
|
+
AttendeeDisplayInfo,
|
|
37
|
+
VideoViewProps,
|
|
28
38
|
} from "./video.js"
|
|
29
39
|
|
|
30
40
|
import {
|
|
@@ -34,26 +44,38 @@ import {
|
|
|
34
44
|
} from "./native/bridge"
|
|
35
45
|
import { RNVideoView } from "./native/RNVideoRenderView"
|
|
36
46
|
|
|
47
|
+
export { CurrentCallContext }
|
|
48
|
+
|
|
37
49
|
interface TileState {
|
|
38
50
|
isLocal: boolean,
|
|
39
51
|
isScreenShare: boolean,
|
|
40
52
|
tileId: number,
|
|
41
53
|
}
|
|
42
54
|
|
|
43
|
-
export const WithVideo = ({ children } : VideoProps
|
|
55
|
+
export const WithVideo = ({ children } : VideoProps) => {
|
|
44
56
|
const [meeting, setMeeting] = useState(undefined as MeetingInfo | undefined)
|
|
57
|
+
const [isHost, setIsHost] = useState(false)
|
|
45
58
|
|
|
46
59
|
const [inMeeting, setInMeeting] = useState(false)
|
|
47
60
|
const [isLoading, setIsLoading] = useState(false)
|
|
61
|
+
const [muted, setMuted] = useState(false)
|
|
48
62
|
const [videoIsEnabled, setVideoIsEnabled] = useState(false)
|
|
49
63
|
const [videoTiles, setVideoTiles] = useState([] as number[])
|
|
64
|
+
const [localTileId, setLocalTileId] = useState(null as number | null)
|
|
50
65
|
const [screenShareTile, setScreenShareTile] = useState(null as number | null)
|
|
51
66
|
const [attendees, setAttendees] = useState ([] as AttendeeDisplayInfo[])
|
|
52
67
|
|
|
53
68
|
const toggleVideo = async () => {
|
|
54
|
-
|
|
69
|
+
NativeFunction.setCameraOn(!videoIsEnabled)
|
|
70
|
+
if (videoIsEnabled) {
|
|
71
|
+
setLocalTileId(null)
|
|
72
|
+
}
|
|
55
73
|
setVideoIsEnabled(v => !v)
|
|
56
74
|
}
|
|
75
|
+
const toggleMic = async () => {
|
|
76
|
+
NativeFunction.setMute(!muted)
|
|
77
|
+
setMuted(m => !m)
|
|
78
|
+
}
|
|
57
79
|
const emitter = getSDKEventEmitter()
|
|
58
80
|
|
|
59
81
|
useEffect(() => {
|
|
@@ -98,6 +120,9 @@ export const WithVideo = ({ children } : VideoProps ) => {
|
|
|
98
120
|
setScreenShareTile(tileState.tileId)
|
|
99
121
|
return
|
|
100
122
|
}
|
|
123
|
+
if (tileState.isLocal) {
|
|
124
|
+
setLocalTileId(tileState.tileId)
|
|
125
|
+
}
|
|
101
126
|
setVideoTiles(v => [...v, tileState.tileId])
|
|
102
127
|
setVideoIsEnabled(v => tileState.isLocal ? true : v)
|
|
103
128
|
});
|
|
@@ -126,22 +151,45 @@ export const WithVideo = ({ children } : VideoProps ) => {
|
|
|
126
151
|
|
|
127
152
|
return (
|
|
128
153
|
<CurrentCallContext.Provider value={{
|
|
154
|
+
isHost, setIsHost,
|
|
129
155
|
attendees,
|
|
156
|
+
localTileId,
|
|
130
157
|
videoTiles,
|
|
131
158
|
meeting,
|
|
132
159
|
shareScreenId: screenShareTile,
|
|
133
160
|
setMeeting,
|
|
134
161
|
videoIsEnabled,
|
|
135
|
-
toggleVideo
|
|
162
|
+
toggleVideo,
|
|
163
|
+
microphoneIsEnabled: !muted,
|
|
164
|
+
toggleMicrophone: toggleMic,
|
|
136
165
|
}}>
|
|
137
166
|
{children}
|
|
138
167
|
</CurrentCallContext.Provider>
|
|
139
168
|
)
|
|
140
169
|
}
|
|
141
170
|
|
|
171
|
+
|
|
172
|
+
export const useRemoteViews = (props={} as { style: React.CSSProperties }) => {
|
|
173
|
+
const { localTileId, videoTiles } = React.useContext(CurrentCallContext)
|
|
174
|
+
const nonLocal = videoTiles.filter(v => v !== localTileId)
|
|
175
|
+
|
|
176
|
+
return nonLocal.map(tileId =>
|
|
177
|
+
<RNVideoView key={tileId} style={convert_CSS_to_RNStyles(props.style) ?? styles.video} tileId={tileId} />
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export const SelfView = ({ style } : VideoViewProps) => {
|
|
182
|
+
const { localTileId } = React.useContext(CurrentCallContext)
|
|
183
|
+
if (localTileId === null) return null // localTileId may be zero, don't return null on simple falsey check
|
|
184
|
+
|
|
185
|
+
return (
|
|
186
|
+
<RNVideoView style={convert_CSS_to_RNStyles(style) ?? styles.video} tileId={localTileId}/>
|
|
187
|
+
)
|
|
188
|
+
}
|
|
189
|
+
|
|
142
190
|
export const useStartVideoCall = (): StartVideoCallReturnType => {
|
|
143
191
|
const session = useSession()
|
|
144
|
-
const { meeting, setMeeting, videoIsEnabled, toggleVideo } = React.useContext(CurrentCallContext)
|
|
192
|
+
const { meeting, setMeeting, setIsHost, videoIsEnabled, toggleVideo } = React.useContext(CurrentCallContext)
|
|
145
193
|
|
|
146
194
|
const [starting, setStarting] = useState(false)
|
|
147
195
|
const [ending, setEnding] = useState(false)
|
|
@@ -157,6 +205,7 @@ export const useStartVideoCall = (): StartVideoCallReturnType => {
|
|
|
157
205
|
NativeFunction.startMeeting(meeting.Meeting, host.Attendee)
|
|
158
206
|
|
|
159
207
|
setMeeting(meeting.Meeting)
|
|
208
|
+
setIsHost(true)
|
|
160
209
|
} catch(err) {
|
|
161
210
|
console.error(err)
|
|
162
211
|
}
|
|
@@ -182,7 +231,16 @@ export const useStartVideoCall = (): StartVideoCallReturnType => {
|
|
|
182
231
|
setMeeting(undefined)
|
|
183
232
|
}
|
|
184
233
|
|
|
185
|
-
return {
|
|
234
|
+
return {
|
|
235
|
+
meeting,
|
|
236
|
+
videoIsEnabled,
|
|
237
|
+
starting,
|
|
238
|
+
ending,
|
|
239
|
+
toggleVideo,
|
|
240
|
+
createAndStartMeeting,
|
|
241
|
+
addAttendees,
|
|
242
|
+
endMeeting,
|
|
243
|
+
}
|
|
186
244
|
}
|
|
187
245
|
|
|
188
246
|
export const useJoinVideoCall = (): JoinVideoCallReturnType => {
|
package/src/video.tsx
CHANGED
|
@@ -12,14 +12,6 @@ import {
|
|
|
12
12
|
MeetingInfo,
|
|
13
13
|
} from '@tellescope/types-models'
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
user_display_name,
|
|
17
|
-
} from "@tellescope/utilities"
|
|
18
|
-
|
|
19
|
-
import {
|
|
20
|
-
Session,
|
|
21
|
-
EnduserSession,
|
|
22
|
-
} from "@tellescope/sdk"
|
|
23
15
|
|
|
24
16
|
import { ThemeProvider } from 'styled-components';
|
|
25
17
|
import {
|
|
@@ -31,12 +23,15 @@ import {
|
|
|
31
23
|
// VideoGrid,
|
|
32
24
|
// VideoTile,
|
|
33
25
|
// PreviewVideo,
|
|
34
|
-
|
|
26
|
+
RemoteVideo,
|
|
35
27
|
useAttendeeAudioStatus,
|
|
28
|
+
LocalVideo,
|
|
36
29
|
useLocalVideo,
|
|
37
30
|
useMeetingManager,
|
|
38
31
|
useRosterState,
|
|
39
|
-
useRemoteVideoTileState
|
|
32
|
+
useRemoteVideoTileState,
|
|
33
|
+
VideoTile,
|
|
34
|
+
useToggleLocalMute,
|
|
40
35
|
// useRemoteVideoTileState,
|
|
41
36
|
// useContentShareControls, // screen sharing
|
|
42
37
|
} from 'amazon-chime-sdk-component-library-react';
|
|
@@ -47,8 +42,11 @@ export type AttendeeDisplayInfo = { attendeeId: string, externalUserId: string
|
|
|
47
42
|
export const CurrentCallContext = React.createContext({} as {
|
|
48
43
|
meeting: MeetingInfo | undefined, setMeeting: (m: MeetingInfo | undefined) => void,
|
|
49
44
|
videoIsEnabled: boolean, toggleVideo: () => Promise<void>,
|
|
45
|
+
microphoneIsEnabled: boolean, toggleMicrophone: () => Promise<void>,
|
|
50
46
|
attendees: AttendeeDisplayInfo[], shareScreenId: number | null,
|
|
51
|
-
|
|
47
|
+
localTileId: number | null,
|
|
48
|
+
isHost: boolean, setIsHost: (b: boolean) => void;
|
|
49
|
+
videoTiles: (number)[],
|
|
52
50
|
})
|
|
53
51
|
export interface VideoProps {
|
|
54
52
|
children?: React.ReactNode,
|
|
@@ -56,10 +54,12 @@ export interface VideoProps {
|
|
|
56
54
|
}
|
|
57
55
|
const WithContext = ({ children } : { children: React.ReactNode }) => {
|
|
58
56
|
const [meeting, setMeeting] = useState(undefined as MeetingInfo | undefined)
|
|
59
|
-
const
|
|
57
|
+
const [isHost, setIsHost] = useState(false)
|
|
58
|
+
const { toggleVideo, isVideoEnabled: videoIsEnabled, tileId: localTileId } = useLocalVideo();
|
|
60
59
|
const { roster } = useRosterState()
|
|
61
60
|
const { tileId } = useContentShareState()
|
|
62
61
|
const { tiles } = useRemoteVideoTileState()
|
|
62
|
+
const { muted, toggleMute } = useToggleLocalMute()
|
|
63
63
|
|
|
64
64
|
const attendees = [] as AttendeeDisplayInfo[]
|
|
65
65
|
for (const attendeeId in roster) {
|
|
@@ -68,7 +68,19 @@ const WithContext = ({ children } : { children: React.ReactNode }) => {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
return (
|
|
71
|
-
<CurrentCallContext.Provider value={{
|
|
71
|
+
<CurrentCallContext.Provider value={{
|
|
72
|
+
isHost, setIsHost,
|
|
73
|
+
attendees,
|
|
74
|
+
localTileId,
|
|
75
|
+
videoTiles: tiles,
|
|
76
|
+
shareScreenId: tileId,
|
|
77
|
+
meeting,
|
|
78
|
+
setMeeting,
|
|
79
|
+
videoIsEnabled,
|
|
80
|
+
toggleVideo,
|
|
81
|
+
microphoneIsEnabled: !muted,
|
|
82
|
+
toggleMicrophone: async () => toggleMute(),
|
|
83
|
+
}}>
|
|
72
84
|
{children}
|
|
73
85
|
</CurrentCallContext.Provider>
|
|
74
86
|
)
|
|
@@ -86,9 +98,9 @@ export const WithVideo = ({ children, theme=darkTheme }: VideoProps) => (
|
|
|
86
98
|
export const useStartVideoCall = () => {
|
|
87
99
|
const [starting, setStarting] = useState(false)
|
|
88
100
|
const [ending, setEnding] = useState(false)
|
|
89
|
-
const { meeting, setMeeting, toggleVideo, videoIsEnabled } = React.useContext(CurrentCallContext)
|
|
101
|
+
const { meeting, setMeeting, toggleVideo, videoIsEnabled, setIsHost } = React.useContext(CurrentCallContext)
|
|
90
102
|
|
|
91
|
-
const session = useSession()
|
|
103
|
+
const session = useSession() // meetings can only be started by users, not endusers (for now)
|
|
92
104
|
const meetingManager = useMeetingManager();
|
|
93
105
|
|
|
94
106
|
const createAndStartMeeting = async (initialAttendees?: UserIdentity[]) => {
|
|
@@ -105,6 +117,7 @@ export const useStartVideoCall = () => {
|
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
setMeeting(meeting.Meeting)
|
|
120
|
+
setIsHost(true)
|
|
108
121
|
} catch(err) {
|
|
109
122
|
console.error(err)
|
|
110
123
|
}
|
|
@@ -148,4 +161,19 @@ export const useJoinVideoCall = () => {
|
|
|
148
161
|
}
|
|
149
162
|
export type JoinVideoCallReturnType = ReturnType<typeof useJoinVideoCall>
|
|
150
163
|
|
|
164
|
+
export interface VideoViewProps {
|
|
165
|
+
style?: CSSProperties,
|
|
166
|
+
}
|
|
167
|
+
export const SelfView = ({ style }: VideoViewProps) => <div style={style}><LocalVideo/></div>
|
|
168
|
+
|
|
169
|
+
export const useRemoteViews = (props={} as VideoViewProps) => {
|
|
170
|
+
const { localTileId, videoTiles } = React.useContext(CurrentCallContext)
|
|
171
|
+
const nonLocal = videoTiles.filter(v => v !== localTileId)
|
|
172
|
+
|
|
173
|
+
return nonLocal.map(tileId =>
|
|
174
|
+
<RemoteVideo key={tileId} style={props.style} tileId={tileId} />
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
|
|
151
179
|
export { VideoTileGrid }
|