@tellescope/video-chat 1.3.25 → 1.3.27
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/index.d.ts +1 -2
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +1 -5
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/index.native.d.ts +1 -2
- package/lib/cjs/index.native.d.ts.map +1 -1
- package/lib/cjs/index.native.js +2 -5
- package/lib/cjs/index.native.js.map +1 -1
- package/lib/cjs/video.d.ts +17 -1
- package/lib/cjs/video.d.ts.map +1 -1
- package/lib/cjs/video.js +106 -1
- package/lib/cjs/video.js.map +1 -1
- package/lib/cjs/video.native.d.ts +6 -2
- package/lib/cjs/video.native.d.ts.map +1 -1
- package/lib/cjs/video.native.js +86 -9
- package/lib/cjs/video.native.js.map +1 -1
- package/lib/cjs/video_shared.d.ts +18 -2
- package/lib/cjs/video_shared.d.ts.map +1 -1
- package/lib/cjs/video_shared.js +114 -4
- package/lib/cjs/video_shared.js.map +1 -1
- package/lib/esm/controls.d.ts +0 -1
- package/lib/esm/controls.d.ts.map +1 -1
- package/lib/esm/hooks.d.ts +1 -13
- package/lib/esm/hooks.d.ts.map +1 -1
- package/lib/esm/hooks.js +1 -137
- package/lib/esm/hooks.js.map +1 -1
- package/lib/esm/index.d.ts +1 -2
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +1 -2
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/index.native.d.ts +1 -2
- package/lib/esm/index.native.d.ts.map +1 -1
- package/lib/esm/index.native.js +1 -2
- package/lib/esm/index.native.js.map +1 -1
- package/lib/esm/video.d.ts +17 -1
- package/lib/esm/video.d.ts.map +1 -1
- package/lib/esm/video.js +102 -1
- package/lib/esm/video.js.map +1 -1
- package/lib/esm/video.native.d.ts +6 -2
- package/lib/esm/video.native.d.ts.map +1 -1
- package/lib/esm/video.native.js +85 -10
- package/lib/esm/video.native.js.map +1 -1
- package/lib/esm/video_shared.d.ts +18 -2
- package/lib/esm/video_shared.d.ts.map +1 -1
- package/lib/esm/video_shared.js +89 -1
- package/lib/esm/video_shared.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/index.native.ts +1 -5
- package/src/index.ts +1 -5
- package/src/video.native.tsx +103 -4
- package/src/video.tsx +108 -4
- package/src/video_shared.tsx +140 -2
- package/src/hooks.ts +0 -98
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tellescope/video-chat",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.27",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/cjs/index.js",
|
|
6
6
|
"module": "./lib/esm/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@mui/icons-material": "^5.0.1",
|
|
36
36
|
"@mui/material": "^5.0.2",
|
|
37
37
|
"@tellescope/constants": "^1.3.24",
|
|
38
|
-
"@tellescope/react-components": "^1.3.
|
|
38
|
+
"@tellescope/react-components": "^1.3.27",
|
|
39
39
|
"@tellescope/sdk": "^1.3.25",
|
|
40
40
|
"@tellescope/types-client": "^1.3.24",
|
|
41
41
|
"@tellescope/types-models": "^1.3.24",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
56
56
|
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
57
57
|
},
|
|
58
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "84949695c66af0d03234a569d5cfc900515c7a7b",
|
|
59
59
|
"publishConfig": {
|
|
60
60
|
"access": "public"
|
|
61
61
|
}
|
package/src/index.native.ts
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
export * from "./video"
|
|
2
|
-
export * from "./hooks"
|
|
3
2
|
export * from "./controls"
|
|
4
|
-
export
|
|
5
|
-
CurrentCallContext,
|
|
6
|
-
useCurrentCallContext,
|
|
7
|
-
} from "./video_shared"
|
|
3
|
+
export * from "./video_shared"
|
|
8
4
|
export {
|
|
9
5
|
RNVideoRenderView,
|
|
10
6
|
} from "./native/RNVideoRenderView"
|
package/src/index.ts
CHANGED
package/src/video.native.tsx
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
useResolvedSession,
|
|
20
20
|
useSession,
|
|
21
21
|
Flex,
|
|
22
|
+
useCalendarEvents,
|
|
22
23
|
} from "@tellescope/react-components"
|
|
23
24
|
import {
|
|
24
25
|
Button,
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
VideoProps,
|
|
33
34
|
AttendeeDisplayInfo,
|
|
34
35
|
VideoViewProps,
|
|
36
|
+
VideoCallNativeProps,
|
|
35
37
|
} from "./video_shared"
|
|
36
38
|
import {
|
|
37
39
|
CurrentCallContext,
|
|
@@ -39,7 +41,10 @@ import {
|
|
|
39
41
|
getSDKEventEmitter,
|
|
40
42
|
MobileSDKEvent,
|
|
41
43
|
NativeFunction,
|
|
44
|
+
ControlBar,
|
|
42
45
|
} from "./index.native"
|
|
46
|
+
import { borderColor, borderRadius } from "@mui/system"
|
|
47
|
+
// import RNSwitchAudioOutput from 'react-native-switch-audio-output';
|
|
43
48
|
|
|
44
49
|
interface TileState {
|
|
45
50
|
isLocal: boolean,
|
|
@@ -236,20 +241,52 @@ export const useStartVideoCall = (): StartVideoCallReturnType => {
|
|
|
236
241
|
}
|
|
237
242
|
}
|
|
238
243
|
|
|
244
|
+
export const useStartAndJoinMeetingForCalendarEvent = (calendarEventId: string) => {
|
|
245
|
+
const session = useSession()
|
|
246
|
+
const [, { updateLocalElement: updateLocalEvent }] = useCalendarEvents()
|
|
247
|
+
|
|
248
|
+
const { setMeeting, setIsHost } = useContext(CurrentCallContext)
|
|
249
|
+
if (!(!!setMeeting && setIsHost)) {
|
|
250
|
+
throw new Error("Missing CurrentCallContext")
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const startAndJoinMeeting = useCallback(async () => {
|
|
254
|
+
const { meeting, host, id } = await session.api.meetings.start_meeting_for_event({ calendarEventId })
|
|
255
|
+
|
|
256
|
+
updateLocalEvent(calendarEventId, { meetingId: id } )
|
|
257
|
+
|
|
258
|
+
NativeFunction.startMeeting(meeting.Meeting, host.info)
|
|
259
|
+
|
|
260
|
+
setMeeting(meeting.Meeting)
|
|
261
|
+
setIsHost(true)
|
|
262
|
+
}, [session, setMeeting, setIsHost, updateLocalEvent])
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
startAndJoinMeeting,
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
239
269
|
export const useJoinVideoCall = (): JoinVideoCallReturnType => {
|
|
240
270
|
const session = useResolvedSession()
|
|
241
|
-
const { meeting, setMeeting, videoIsEnabled, toggleVideo } = React.useContext(CurrentCallContext)
|
|
271
|
+
const { meeting, setIsHost, setMeeting, videoIsEnabled, toggleVideo } = React.useContext(CurrentCallContext)
|
|
242
272
|
|
|
243
|
-
const joinMeeting = async (meetingInfo: string | { Meeting: MeetingInfo }, attendeeInfo
|
|
273
|
+
const joinMeeting = async (meetingInfo: string | { Meeting: MeetingInfo }, attendeeInfo?: { Attendee: AttendeeInfo }) => {
|
|
244
274
|
if (typeof meetingInfo == 'string') {
|
|
245
275
|
const meetings = await session.api.meetings.my_meetings()
|
|
246
276
|
const meeting = meetings.find(m => m.id === meetingInfo)
|
|
247
277
|
meetingInfo = meeting?.meetingInfo as { Meeting: MeetingInfo }
|
|
248
278
|
attendeeInfo = { Attendee: meeting?.attendees.find?.(a => a.id === session.userInfo.id)?.info as AttendeeInfo}
|
|
279
|
+
|
|
280
|
+
if (attendeeInfo.Attendee.ExternalUserId === meeting?.creator) {
|
|
281
|
+
setIsHost(true)
|
|
282
|
+
}
|
|
249
283
|
}
|
|
284
|
+
|
|
250
285
|
if (!meetingInfo || typeof meetingInfo === 'string' || !attendeeInfo) return
|
|
251
286
|
|
|
252
|
-
NativeFunction.startMeeting(meetingInfo.Meeting ?? meetingInfo, attendeeInfo)
|
|
287
|
+
NativeFunction.startMeeting(meetingInfo.Meeting ?? meetingInfo, attendeeInfo.Attendee ?? attendeeInfo)
|
|
288
|
+
|
|
289
|
+
setMeeting(meetingInfo.Meeting)
|
|
253
290
|
}
|
|
254
291
|
|
|
255
292
|
const leaveMeeting = () => setMeeting(undefined)
|
|
@@ -371,5 +408,67 @@ const styles = StyleSheet.create({
|
|
|
371
408
|
});
|
|
372
409
|
|
|
373
410
|
export const LocalPreview = () => {
|
|
374
|
-
|
|
411
|
+
// console.error("LocalPreview unimplemented for Native")
|
|
412
|
+
return null
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const get_video_styles = (count: number): React.CSSProperties => {
|
|
416
|
+
return ({
|
|
417
|
+
borderWidth: '1px',
|
|
418
|
+
borderColor: '#888888',
|
|
419
|
+
borderRadius: 5,
|
|
420
|
+
padding: 5,
|
|
421
|
+
width: count === 1 ? '100%' : '50%',
|
|
422
|
+
maxHeight: (
|
|
423
|
+
count <= 4
|
|
424
|
+
? '50%'
|
|
425
|
+
: count <= 8
|
|
426
|
+
? '25%'
|
|
427
|
+
: '20%'
|
|
428
|
+
),
|
|
429
|
+
backgroundColor: '#bbbbbb'
|
|
430
|
+
})
|
|
431
|
+
}
|
|
432
|
+
export const VideoCallNative: React.JSXElementConstructor<VideoCallNativeProps> = ({
|
|
433
|
+
...props
|
|
434
|
+
}) => {
|
|
435
|
+
const remoteViews = useRemoteViews()
|
|
436
|
+
// RNSwitchAudioOutput.selectAudioOutput(RNSwitchAudioOutput.AUDIO_SPEAKER)
|
|
437
|
+
const selfView = (
|
|
438
|
+
<SelfView
|
|
439
|
+
// style={{
|
|
440
|
+
// position: 'absolute',
|
|
441
|
+
// zIndex: '100',
|
|
442
|
+
// borderRadius: 100,
|
|
443
|
+
// width: 130,
|
|
444
|
+
// height: 130,
|
|
445
|
+
// bottom: 120,
|
|
446
|
+
// right: 25
|
|
447
|
+
// }}
|
|
448
|
+
/>
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
const style = get_video_styles(remoteViews.length + 1)
|
|
452
|
+
|
|
453
|
+
return (
|
|
454
|
+
<Flex column flex={1} style={{ }}>
|
|
455
|
+
<Flex flex={1} style={{ marginBottom: 75 }}>
|
|
456
|
+
|
|
457
|
+
{remoteViews.map((view, i) => (
|
|
458
|
+
<Flex key={i} alignItems="center" justifyContent="center" style={style}>
|
|
459
|
+
{view}
|
|
460
|
+
</Flex>
|
|
461
|
+
))}
|
|
462
|
+
|
|
463
|
+
<Flex alignItems="center" justifyContent="center" style={style}>
|
|
464
|
+
{selfView}
|
|
465
|
+
</Flex>
|
|
466
|
+
|
|
467
|
+
</Flex>
|
|
468
|
+
|
|
469
|
+
<ControlBar {...props}
|
|
470
|
+
style={{ position: 'absolute', bottom: 20, width: '100%' }}
|
|
471
|
+
/>
|
|
472
|
+
</Flex>
|
|
473
|
+
)
|
|
375
474
|
}
|
package/src/video.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback,
|
|
1
|
+
import React, { useCallback, useContext, useState, useEffect } from "react"
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
useResolvedSession,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from "@tellescope/types-utilities"
|
|
12
12
|
import {
|
|
13
13
|
AttendeeInfo,
|
|
14
|
+
Meeting,
|
|
14
15
|
MeetingInfo,
|
|
15
16
|
} from '@tellescope/types-models'
|
|
16
17
|
|
|
@@ -39,7 +40,8 @@ import {
|
|
|
39
40
|
// useContentShareControls, // screen sharing
|
|
40
41
|
} from 'amazon-chime-sdk-component-library-react';
|
|
41
42
|
import {
|
|
42
|
-
CurrentCallContext,
|
|
43
|
+
CurrentCallContext,
|
|
44
|
+
VideoCallNativeProps,
|
|
43
45
|
} from "./index"
|
|
44
46
|
import {
|
|
45
47
|
AttendeeDisplayInfo,
|
|
@@ -51,6 +53,103 @@ import {
|
|
|
51
53
|
} from "./video_shared"
|
|
52
54
|
import { ConsoleLogger, DefaultDeviceController, Logger, LogLevel } from "amazon-chime-sdk-js";
|
|
53
55
|
|
|
56
|
+
import { useCalendarEvents } from "@tellescope/react-components"
|
|
57
|
+
import { useCurrentCallContext } from "./index"
|
|
58
|
+
import { CalendarEvent } from "@tellescope/types-client";
|
|
59
|
+
|
|
60
|
+
export const useMeetingForCalendarEvent = (event: CalendarEvent) => {
|
|
61
|
+
const { meeting } = useCurrentCallContext()
|
|
62
|
+
const { startAndJoinMeeting } = useStartAndJoinMeetingForCalendarEvent(event.id)
|
|
63
|
+
const { joinMeeting } = useJoinMeeting()
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
startAndJoinMeeting,
|
|
67
|
+
joinMeeting,
|
|
68
|
+
meeting,
|
|
69
|
+
meetingStatus: (
|
|
70
|
+
!event.enableVideoCall
|
|
71
|
+
? 'disabled'
|
|
72
|
+
: !(event.meetingId)
|
|
73
|
+
? 'waiting-room'
|
|
74
|
+
: !!meeting
|
|
75
|
+
? 'joined'
|
|
76
|
+
: 'loading'
|
|
77
|
+
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const useStartAndJoinMeetingForCalendarEvent = (calendarEventId: string) => {
|
|
83
|
+
const session = useSession()
|
|
84
|
+
const [, { updateLocalElement: updateLocalEvent }] = useCalendarEvents()
|
|
85
|
+
|
|
86
|
+
const meetingManager = useMeetingManager();
|
|
87
|
+
|
|
88
|
+
const { setMeeting, setIsHost } = useContext(CurrentCallContext)
|
|
89
|
+
if (!(!!setMeeting && setIsHost)) {
|
|
90
|
+
throw new Error("Missing CurrentCallContext")
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const startAndJoinMeeting = useCallback(async () => {
|
|
94
|
+
const { meeting, host, id } = await session.api.meetings.start_meeting_for_event({ calendarEventId })
|
|
95
|
+
|
|
96
|
+
updateLocalEvent(calendarEventId, { meetingId: id } )
|
|
97
|
+
|
|
98
|
+
setMeeting(meeting as any)
|
|
99
|
+
|
|
100
|
+
await meetingManager.join({ meetingInfo: meeting, attendeeInfo: host.info }); // Use the join API to create a meeting session
|
|
101
|
+
await meetingManager.start(); // At this point you can let users setup their devices, or start the session immediately
|
|
102
|
+
|
|
103
|
+
setMeeting(meeting.Meeting)
|
|
104
|
+
setIsHost(true)
|
|
105
|
+
}, [session, calendarEventId, updateLocalEvent, meetingManager, setMeeting, setIsHost])
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
startAndJoinMeeting,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export const useJoinMeeting = () => {
|
|
113
|
+
const session = useResolvedSession()
|
|
114
|
+
const meetingManager = useMeetingManager();
|
|
115
|
+
|
|
116
|
+
const { setMeeting, setIsHost } = useContext(CurrentCallContext)
|
|
117
|
+
if (!(!!setMeeting && setIsHost)) {
|
|
118
|
+
throw new Error("Missing CurrentCallContext")
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const joinMeeting = useCallback(async (meeting: Meeting) => {
|
|
122
|
+
setMeeting(meeting.meetingInfo.Meeting)
|
|
123
|
+
setIsHost(meeting.creator === session.userInfo.id)
|
|
124
|
+
|
|
125
|
+
let attendeeInfo = meeting.attendees.find(a => a.id === session.userInfo.id)?.info
|
|
126
|
+
if (!attendeeInfo) {
|
|
127
|
+
const calendarEventId = meeting.calendarEventId
|
|
128
|
+
if (calendarEventId) {
|
|
129
|
+
const result = await session.api.meetings.join_meeting_for_event({ calendarEventId })
|
|
130
|
+
|
|
131
|
+
attendeeInfo = result.attendee.info
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (!attendeeInfo) {
|
|
135
|
+
console.error("Could not find attendee info for joining meeting and failed to join")
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
await meetingManager.join({
|
|
141
|
+
meetingInfo: meeting.meetingInfo,
|
|
142
|
+
attendeeInfo,
|
|
143
|
+
}); // Use the join API to create a meeting session
|
|
144
|
+
await meetingManager.start(); // At this point you can let users setup their devices, or start the session immediately
|
|
145
|
+
|
|
146
|
+
}, [setMeeting, meetingManager, setMeeting, setIsHost])
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
joinMeeting,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
54
153
|
const WithContext = ({ children } : { children: React.ReactNode }) => {
|
|
55
154
|
const [meeting, setMeeting] = useState(undefined as MeetingInfo | undefined)
|
|
56
155
|
const [isHost, setIsHost] = useState(false)
|
|
@@ -150,7 +249,7 @@ export const useJoinVideoCall = (props?: JoinVideoCallProps): JoinVideoCallRetur
|
|
|
150
249
|
const status = useMeetingStatus()
|
|
151
250
|
|
|
152
251
|
// meetingInfo may be meetingId as string
|
|
153
|
-
const joinMeeting = async (meetingInfo: string | { Meeting: MeetingInfo }, attendeeInfo
|
|
252
|
+
const joinMeeting = async (meetingInfo: string | { Meeting: MeetingInfo }, attendeeInfo?: { Attendee: AttendeeInfo }) => {
|
|
154
253
|
if (typeof meetingInfo == 'string') {
|
|
155
254
|
const meetings = await session.api.meetings.my_meetings()
|
|
156
255
|
const meeting = meetings.find(m => m.id === meetingInfo)
|
|
@@ -264,4 +363,9 @@ export const LocalPreview = ({ style=defaultPreviewStyle }: Styled) => {
|
|
|
264
363
|
|
|
265
364
|
return <video id={PREVIEW_ELEMENT_ID} style={style}/>
|
|
266
365
|
}
|
|
267
|
-
export { VideoTileGrid }
|
|
366
|
+
export { VideoTileGrid }
|
|
367
|
+
|
|
368
|
+
// unimplemented for web
|
|
369
|
+
export const VideoCallNative: React.JSXElementConstructor<VideoCallNativeProps> = () => (
|
|
370
|
+
null
|
|
371
|
+
)
|
package/src/video_shared.tsx
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
|
-
import React, { CSSProperties } from "react"
|
|
1
|
+
import React, { CSSProperties, useCallback, useEffect, useState } from "react"
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
AttendeeInfo,
|
|
5
5
|
MeetingInfo,
|
|
6
6
|
} from '@tellescope/types-models'
|
|
7
|
+
import {
|
|
8
|
+
CalendarEvent,
|
|
9
|
+
Enduser,
|
|
10
|
+
User,
|
|
11
|
+
} from '@tellescope/types-client'
|
|
7
12
|
|
|
8
13
|
import {
|
|
14
|
+
APIError,
|
|
9
15
|
UserIdentity,
|
|
10
16
|
} from '@tellescope/types-utilities'
|
|
11
17
|
|
|
18
|
+
import {
|
|
19
|
+
UserAndEnduserSelectorProps,
|
|
20
|
+
useMeetings,
|
|
21
|
+
UserAndEnduserSelector,
|
|
22
|
+
useCalendarEvents,
|
|
23
|
+
Flex,
|
|
24
|
+
Typography,
|
|
25
|
+
LoadingButton,
|
|
26
|
+
useSession,
|
|
27
|
+
useResolvedSession,
|
|
28
|
+
Button,
|
|
29
|
+
} from "@tellescope/react-components"
|
|
30
|
+
import { LocalPreview, useJoinVideoCall, useStartAndJoinMeetingForCalendarEvent } from "./video"
|
|
31
|
+
|
|
12
32
|
export type AttendeeDisplayInfo = { attendeeId: string, externalUserId: string }
|
|
13
33
|
export interface CallContext {
|
|
14
34
|
meeting: MeetingInfo | undefined, setMeeting: (m: MeetingInfo | undefined) => void,
|
|
@@ -43,7 +63,7 @@ export interface JoinVideoCallReturnType {
|
|
|
43
63
|
videoIsEnabled: CallContext['videoIsEnabled'],
|
|
44
64
|
toggleVideo: CallContext['toggleVideo'],
|
|
45
65
|
leaveMeeting: () => void,
|
|
46
|
-
joinMeeting: (meetingInfo: { Meeting: MeetingInfo } | string, attendeeInfo
|
|
66
|
+
joinMeeting: (meetingInfo: { Meeting: MeetingInfo } | string, attendeeInfo?: { Attendee: AttendeeInfo }) => Promise<void>,
|
|
47
67
|
}
|
|
48
68
|
|
|
49
69
|
export interface StartVideoCallReturnType {
|
|
@@ -55,4 +75,122 @@ export interface StartVideoCallReturnType {
|
|
|
55
75
|
createAndStartMeeting: (initialAttendees?: UserIdentity[]) => Promise<string>,
|
|
56
76
|
addAttendees: (attendees: UserIdentity[]) => Promise<void>,
|
|
57
77
|
endMeeting: () => Promise<void>,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface CreateCalendarEventForAttendeesProps extends Omit<UserAndEnduserSelectorProps, 'onSelect'> {
|
|
81
|
+
onSuccess?: (c: CalendarEvent) => void,
|
|
82
|
+
onError?: (e: APIError) => void,
|
|
83
|
+
eventProps?: Pick<CalendarEvent, 'startTimeInMS' | 'durationInMinutes' | 'title'>
|
|
84
|
+
}
|
|
85
|
+
export const CreateCalendarEventForAttendees = ({
|
|
86
|
+
onSuccess,
|
|
87
|
+
onError,
|
|
88
|
+
eventProps,
|
|
89
|
+
...props
|
|
90
|
+
} : CreateCalendarEventForAttendeesProps) => {
|
|
91
|
+
const [, { createElement: createEvent }] = useCalendarEvents({ dontFetch: true })
|
|
92
|
+
const [eventTitle, /*setEventTitle*/] = useState(eventProps?.title ?? 'Video Call')
|
|
93
|
+
const session = useResolvedSession()
|
|
94
|
+
|
|
95
|
+
const handleCreateRoom = useCallback(({ users, endusers }: { users: User[], endusers: Enduser[] }) => {
|
|
96
|
+
const userIds = users.map(u => u.id)
|
|
97
|
+
const enduserIds = endusers.map(e => e.id)
|
|
98
|
+
|
|
99
|
+
createEvent({
|
|
100
|
+
title: eventTitle,
|
|
101
|
+
attendees: ([
|
|
102
|
+
...userIds.map(id => ({ type: 'user', id } as UserIdentity)),
|
|
103
|
+
...enduserIds.map(id => ({ type: 'enduser', id } as UserIdentity)),
|
|
104
|
+
]),
|
|
105
|
+
startTimeInMS: eventProps?.startTimeInMS ?? Date.now(),
|
|
106
|
+
durationInMinutes: eventProps?.durationInMinutes || 30,
|
|
107
|
+
enableVideoCall: true,
|
|
108
|
+
})
|
|
109
|
+
.then(r => {
|
|
110
|
+
onSuccess?.(r)
|
|
111
|
+
})
|
|
112
|
+
.catch(onError)
|
|
113
|
+
}, [session, onSuccess, onError])
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<UserAndEnduserSelector {...props} onSelect={handleCreateRoom} />
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type WaitingRoomProps = {
|
|
121
|
+
calendarEvent: CalendarEvent,
|
|
122
|
+
onGoBack?: () => void,
|
|
123
|
+
}
|
|
124
|
+
export const WaitingRoom = ({ calendarEvent, onGoBack } : WaitingRoomProps) => {
|
|
125
|
+
const session = useSession()
|
|
126
|
+
const [, { findById: findEvent }] = useCalendarEvents()
|
|
127
|
+
const [, { findById: findMeeting }] = useMeetings()
|
|
128
|
+
const { startAndJoinMeeting } = useStartAndJoinMeetingForCalendarEvent(calendarEvent.id)
|
|
129
|
+
const { joinMeeting } = useJoinVideoCall()
|
|
130
|
+
|
|
131
|
+
const tsMeeting = findMeeting(calendarEvent?.meetingId ?? '')
|
|
132
|
+
|
|
133
|
+
// poll to check for started meeting
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
const t = setInterval(() => {
|
|
136
|
+
const event = findEvent(calendarEvent.id, { reload: true })
|
|
137
|
+
findMeeting(event?.meetingId ?? '', { reload: true }) // reloads tsMeeting
|
|
138
|
+
}, 2500)
|
|
139
|
+
|
|
140
|
+
return () => { clearInterval(t) }
|
|
141
|
+
}, [calendarEvent, findMeeting, findEvent])
|
|
142
|
+
|
|
143
|
+
const meetingIsStarted = tsMeeting?.status === 'live'
|
|
144
|
+
const isHost = session.userInfo.id === calendarEvent?.creator
|
|
145
|
+
|
|
146
|
+
return (
|
|
147
|
+
<Flex flex={1} column alignItems="center" justifyContent="center">
|
|
148
|
+
<Typography style={{ fontSize: 20, fontWeight: 'bold' }}>
|
|
149
|
+
{calendarEvent.title}
|
|
150
|
+
</Typography>
|
|
151
|
+
|
|
152
|
+
<Typography style={{ marginBottom: 15 }}>
|
|
153
|
+
Waiting Room
|
|
154
|
+
</Typography>
|
|
155
|
+
|
|
156
|
+
<LocalPreview />
|
|
157
|
+
|
|
158
|
+
<LoadingButton variant="contained"
|
|
159
|
+
disabled={
|
|
160
|
+
(!meetingIsStarted && !isHost)
|
|
161
|
+
|| (meetingIsStarted && !tsMeeting)
|
|
162
|
+
}
|
|
163
|
+
onClick={
|
|
164
|
+
meetingIsStarted
|
|
165
|
+
? () => joinMeeting(tsMeeting.id)
|
|
166
|
+
: startAndJoinMeeting
|
|
167
|
+
}
|
|
168
|
+
submitText={
|
|
169
|
+
meetingIsStarted ? "Join Meeting" : "Start Meeting"
|
|
170
|
+
}
|
|
171
|
+
submittingText={
|
|
172
|
+
meetingIsStarted ? "Joining" : "Starting"
|
|
173
|
+
}
|
|
174
|
+
style={{
|
|
175
|
+
marginTop: 15,
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
|
|
179
|
+
{onGoBack &&
|
|
180
|
+
<Button onClick={onGoBack} style={{ width: '100%' }}>
|
|
181
|
+
Back
|
|
182
|
+
</Button>
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
{!meetingIsStarted && !isHost &&
|
|
186
|
+
<Typography style={{ marginTop: 5 }}>
|
|
187
|
+
Waiting for the host to start the meeting
|
|
188
|
+
</Typography>
|
|
189
|
+
}
|
|
190
|
+
</Flex>
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export interface VideoCallNativeProps {
|
|
195
|
+
onLeave?: () => void,
|
|
58
196
|
}
|
package/src/hooks.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { useCallback, useContext } from "react"
|
|
2
|
-
import { useCalendarEvents, useResolvedSession, useSession } from "@tellescope/react-components"
|
|
3
|
-
import { useMeetingManager } from "amazon-chime-sdk-component-library-react"
|
|
4
|
-
import { CurrentCallContext, useCurrentCallContext } from "./index"
|
|
5
|
-
import { CalendarEvent, Meeting } from "@tellescope/types-client"
|
|
6
|
-
|
|
7
|
-
export const useStartAndJoinMeetingForCalendarEvent = (calendarEventId: string) => {
|
|
8
|
-
const session = useSession()
|
|
9
|
-
const [, { updateLocalElement: updateLocalEvent }] = useCalendarEvents()
|
|
10
|
-
|
|
11
|
-
const meetingManager = useMeetingManager();
|
|
12
|
-
|
|
13
|
-
const { setMeeting, setIsHost } = useContext(CurrentCallContext)
|
|
14
|
-
if (!(!!setMeeting && setIsHost)) {
|
|
15
|
-
throw new Error("Missing CurrentCallContext")
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const startAndJoinMeeting = useCallback(async () => {
|
|
19
|
-
const { meeting, host, id } = await session.api.meetings.start_meeting_for_event({ calendarEventId })
|
|
20
|
-
|
|
21
|
-
updateLocalEvent(calendarEventId, { meetingId: id } )
|
|
22
|
-
|
|
23
|
-
setMeeting(meeting as any)
|
|
24
|
-
|
|
25
|
-
await meetingManager.join({ meetingInfo: meeting, attendeeInfo: host.info }); // Use the join API to create a meeting session
|
|
26
|
-
await meetingManager.start(); // At this point you can let users setup their devices, or start the session immediately
|
|
27
|
-
|
|
28
|
-
setMeeting(meeting.Meeting)
|
|
29
|
-
setIsHost(true)
|
|
30
|
-
}, [session, calendarEventId, updateLocalEvent, meetingManager, setMeeting, setIsHost])
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
startAndJoinMeeting,
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export const useJoinMeeting = () => {
|
|
38
|
-
const session = useResolvedSession()
|
|
39
|
-
const meetingManager = useMeetingManager();
|
|
40
|
-
|
|
41
|
-
const { setMeeting, setIsHost } = useContext(CurrentCallContext)
|
|
42
|
-
if (!(!!setMeeting && setIsHost)) {
|
|
43
|
-
throw new Error("Missing CurrentCallContext")
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const joinMeeting = useCallback(async (meeting: Meeting) => {
|
|
47
|
-
setMeeting(meeting.meetingInfo.Meeting)
|
|
48
|
-
setIsHost(meeting.creator === session.userInfo.id)
|
|
49
|
-
|
|
50
|
-
let attendeeInfo = meeting.attendees.find(a => a.id === session.userInfo.id)?.info
|
|
51
|
-
if (!attendeeInfo) {
|
|
52
|
-
const calendarEventId = meeting.calendarEventId
|
|
53
|
-
if (calendarEventId) {
|
|
54
|
-
const result = await session.api.meetings.join_meeting_for_event({ calendarEventId })
|
|
55
|
-
|
|
56
|
-
attendeeInfo = result.attendee.info
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!attendeeInfo) {
|
|
60
|
-
console.error("Could not find attendee info for joining meeting and failed to join")
|
|
61
|
-
return
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
await meetingManager.join({
|
|
66
|
-
meetingInfo: meeting.meetingInfo,
|
|
67
|
-
attendeeInfo,
|
|
68
|
-
}); // Use the join API to create a meeting session
|
|
69
|
-
await meetingManager.start(); // At this point you can let users setup their devices, or start the session immediately
|
|
70
|
-
|
|
71
|
-
}, [setMeeting, meetingManager, setMeeting, setIsHost])
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
joinMeeting,
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export const useMeetingForCalendarEvent = (event: CalendarEvent) => {
|
|
79
|
-
const { meeting } = useCurrentCallContext()
|
|
80
|
-
const { startAndJoinMeeting } = useStartAndJoinMeetingForCalendarEvent(event.id)
|
|
81
|
-
const { joinMeeting } = useJoinMeeting()
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
startAndJoinMeeting,
|
|
85
|
-
joinMeeting,
|
|
86
|
-
meeting,
|
|
87
|
-
meetingStatus: (
|
|
88
|
-
!event.enableVideoCall
|
|
89
|
-
? 'disabled'
|
|
90
|
-
: !(event.meetingId)
|
|
91
|
-
? 'waiting-room'
|
|
92
|
-
: !!meeting
|
|
93
|
-
? 'joined'
|
|
94
|
-
: 'loading'
|
|
95
|
-
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
}
|