agora-appbuilder-core 4.1.7 → 4.1.8-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/package.json +2 -2
- package/template/_package-lock.json +30671 -5376
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -1
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +18 -9
- package/template/bridge/rtc/webNg/RtcEngine.ts +2 -2
- package/template/defaultConfig.js +4 -3
- package/template/esbuild.rsdk.go +1 -2
- package/template/global.d.ts +1 -0
- package/template/package.json +1 -2
- package/template/src/AppWrapper.tsx +30 -35
- package/template/src/auth/AuthProvider.tsx +28 -35
- package/template/src/auth/IDPAuth.tsx +1 -14
- package/template/src/components/Controls.tsx +47 -15
- package/template/src/components/common/GenericModal.tsx +143 -0
- package/template/src/components/common/GenericPopup.tsx +151 -0
- package/template/src/components/common/data-table.tsx +412 -0
- package/template/src/components/controls/useControlPermissionMatrix.tsx +9 -7
- package/template/src/components/precall/usePreCall.tsx +1 -2
- package/template/src/components/recordings/RecordingItemRow.tsx +289 -0
- package/template/src/components/recordings/RecordingsDateTable.tsx +99 -25
- package/template/src/components/recordings/TextTrackItemRow.tsx +120 -0
- package/template/src/components/room-info/useRoomInfo.tsx +1 -0
- package/template/src/components/text-tracks/TextTracksTable.tsx +306 -0
- package/template/src/components/text-tracks/ViewTextTracksModal.tsx +44 -0
- package/template/src/components/text-tracks/useFetchSTTTranscript.tsx +262 -0
- package/template/src/components/useUserPreference.tsx +0 -11
- package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -0
- package/template/src/logger/AppBuilderLogger.tsx +1 -0
- package/template/src/pages/Create.tsx +2 -2
- package/template/src/pages/VideoCall.tsx +1 -6
- package/template/src/subComponents/LogoutButton.tsx +1 -11
- package/template/src/subComponents/recording/useRecording.tsx +19 -4
- package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +83 -78
- package/template/src/utils/common.tsx +79 -1
- package/template/src/utils/useCreateRoom.ts +94 -112
- package/template/src/utils/useEndCall.ts +16 -3
- package/template/src/utils/useGetMeetingPhrase.ts +67 -76
- package/template/src/utils/useJoinRoom.ts +5 -4
- package/template/src/utils/useMutePSTN.ts +47 -45
- package/template/webpack.rsdk.config.js +1 -2
- package/template/src/components/GraphQLProvider.tsx +0 -122
|
@@ -237,9 +237,9 @@ const Create = () => {
|
|
|
237
237
|
});
|
|
238
238
|
showShareScreen();
|
|
239
239
|
} catch (error) {
|
|
240
|
-
const errorCode = error?.
|
|
240
|
+
const errorCode = error?.code;
|
|
241
241
|
if (AuthErrorCodes.indexOf(errorCode) !== -1 && isSDK()) {
|
|
242
|
-
SDKEvents.emit('unauthorized', error
|
|
242
|
+
SDKEvents.emit('unauthorized', error);
|
|
243
243
|
}
|
|
244
244
|
setLoading(false);
|
|
245
245
|
logger.error(
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
*/
|
|
12
12
|
// @ts-nocheck
|
|
13
13
|
import React, {useState, useContext, useEffect, useRef} from 'react';
|
|
14
|
-
import {useApolloClient} from '@apollo/client';
|
|
15
14
|
import {View, StyleSheet, Text} from 'react-native';
|
|
16
15
|
import {
|
|
17
16
|
RtcConfigure,
|
|
@@ -133,8 +132,6 @@ const VideoCall: React.FC = () => {
|
|
|
133
132
|
const joiningLoaderLabel = useString(videoRoomStartingCallText)();
|
|
134
133
|
const bannedUserText = useString(userBannedText)();
|
|
135
134
|
|
|
136
|
-
const client = useApolloClient();
|
|
137
|
-
|
|
138
135
|
const {setGlobalErrorMessage} = useContext(ErrorContext);
|
|
139
136
|
const {awake, release} = useWakeLock();
|
|
140
137
|
const {isRecordingBot} = useIsRecordingBot();
|
|
@@ -372,7 +369,7 @@ const VideoCall: React.FC = () => {
|
|
|
372
369
|
encryption: $config.ENCRYPTION_ENABLED
|
|
373
370
|
? {
|
|
374
371
|
key: data.encryptionSecret,
|
|
375
|
-
mode:
|
|
372
|
+
mode: data.encryptionMode,
|
|
376
373
|
screenKey: data.encryptionSecret,
|
|
377
374
|
salt: data.encryptionSecretSalt,
|
|
378
375
|
}
|
|
@@ -424,8 +421,6 @@ const VideoCall: React.FC = () => {
|
|
|
424
421
|
} else {
|
|
425
422
|
history.push('/');
|
|
426
423
|
}
|
|
427
|
-
// client.resetStore();//https://github.com/apollographql/apollo-client/issues/2919#issuecomment-406311579
|
|
428
|
-
client.cache.reset();
|
|
429
424
|
}, 0);
|
|
430
425
|
},
|
|
431
426
|
UserJoined: (uid: UidType) => {
|
|
@@ -13,14 +13,8 @@ import React, {useContext} from 'react';
|
|
|
13
13
|
import {TouchableOpacity, Text, StyleSheet} from 'react-native';
|
|
14
14
|
import StorageContext, {initStoreValue} from '../components/StorageContext';
|
|
15
15
|
import {useHistory} from '../components/Router';
|
|
16
|
-
import {gql, useMutation} from '@apollo/client';
|
|
17
16
|
import {useString} from '../utils/useString';
|
|
18
17
|
|
|
19
|
-
const LOGOUT = gql`
|
|
20
|
-
mutation logoutSession($token: String!) {
|
|
21
|
-
logoutSession(token: $token)
|
|
22
|
-
}
|
|
23
|
-
`;
|
|
24
18
|
/**
|
|
25
19
|
* Sends a logout request to the backend and logs out the user from the frontend.
|
|
26
20
|
*/
|
|
@@ -28,7 +22,6 @@ const LogoutButton = () => {
|
|
|
28
22
|
const {store, setStore} = useContext(StorageContext);
|
|
29
23
|
const {token} = store;
|
|
30
24
|
const history = useHistory();
|
|
31
|
-
const [logoutQuery] = useMutation(LOGOUT);
|
|
32
25
|
//commented for v1 release
|
|
33
26
|
// const oauthLoginLabel = useString('oauthLoginLabel')();
|
|
34
27
|
// const logoutButton = useString('logoutButton')();
|
|
@@ -41,16 +34,13 @@ const LogoutButton = () => {
|
|
|
41
34
|
* User stored some data in localstorage we don't want to remove their on logout.
|
|
42
35
|
* so setting prevstate with store default value
|
|
43
36
|
*/
|
|
44
|
-
setStore(
|
|
37
|
+
setStore(prevState => {
|
|
45
38
|
return {
|
|
46
39
|
...prevState,
|
|
47
40
|
...initStoreValue,
|
|
48
41
|
};
|
|
49
42
|
});
|
|
50
43
|
}
|
|
51
|
-
logoutQuery({variables: {token}}).catch((e) => {
|
|
52
|
-
console.log(e);
|
|
53
|
-
});
|
|
54
44
|
};
|
|
55
45
|
|
|
56
46
|
const login = () => {
|
|
@@ -67,16 +67,31 @@ const getFrontendUrl = (url: string) => {
|
|
|
67
67
|
return url;
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
export type APIStatus = 'idle' | 'pending' | 'resolved' | 'rejected';
|
|
71
|
+
|
|
72
|
+
export interface FetchRecordingData {
|
|
73
|
+
pagination: {
|
|
74
|
+
limit: number;
|
|
75
|
+
total: number;
|
|
76
|
+
page: number;
|
|
77
|
+
};
|
|
78
|
+
recordings: {
|
|
79
|
+
id: string;
|
|
80
|
+
download_url: string[];
|
|
81
|
+
title: string;
|
|
82
|
+
product_name: string;
|
|
83
|
+
status: 'COMPLETED' | 'STARTED' | 'INPROGRESS' | 'STOPPING';
|
|
84
|
+
created_at: string;
|
|
85
|
+
ended_at: string;
|
|
86
|
+
}[];
|
|
73
87
|
}
|
|
88
|
+
|
|
74
89
|
export interface RecordingContextInterface {
|
|
75
90
|
startRecording: () => void;
|
|
76
91
|
stopRecording: () => void;
|
|
77
92
|
isRecordingActive: boolean;
|
|
78
93
|
inProgress: boolean;
|
|
79
|
-
fetchRecordings?: (page: number) => Promise<
|
|
94
|
+
fetchRecordings?: (page: number) => Promise<FetchRecordingData>;
|
|
80
95
|
deleteRecording?: (id: number) => Promise<boolean>;
|
|
81
96
|
}
|
|
82
97
|
|
|
@@ -1,26 +1,15 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, {useContext} from 'react';
|
|
2
2
|
import {useParams} from '../../components/Router';
|
|
3
3
|
|
|
4
|
-
import {gql, useMutation} from '@apollo/client';
|
|
5
4
|
import {UidType} from '../../../agora-rn-uikit';
|
|
6
5
|
import {logger, LogSource} from '../../logger/AppBuilderLogger';
|
|
7
6
|
import getUniqueID from '../../utils/getUniqueID';
|
|
7
|
+
import StorageContext from '../../components/StorageContext';
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
mutation setPresenter($uid: Int!, $passphrase: String!) {
|
|
11
|
-
setPresenter(uid: $uid, passphrase: $passphrase)
|
|
12
|
-
}
|
|
13
|
-
`;
|
|
14
|
-
|
|
15
|
-
const SET_NORMAL = gql`
|
|
16
|
-
mutation setNormal($passphrase: String!) {
|
|
17
|
-
setNormal(passphrase: $passphrase)
|
|
18
|
-
}
|
|
19
|
-
`;
|
|
9
|
+
const RECORDING_LAYOUT_URL = `${$config.BACKEND_ENDPOINT}/v1/recording/layout/update`;
|
|
20
10
|
|
|
21
11
|
function useRecordingLayoutQuery() {
|
|
22
|
-
const
|
|
23
|
-
const [setNormalQuery] = useMutation(SET_NORMAL);
|
|
12
|
+
const {store} = useContext(StorageContext);
|
|
24
13
|
const {phrase} = useParams<any>();
|
|
25
14
|
/**
|
|
26
15
|
* @param screenShareUid
|
|
@@ -30,104 +19,120 @@ function useRecordingLayoutQuery() {
|
|
|
30
19
|
* and we want that as the main view
|
|
31
20
|
* https://docs.agora.io/en/cloud-recording/cloud_recording_layout?platform=RESTful
|
|
32
21
|
*/
|
|
33
|
-
const executePresenterQuery = (screenShareUid: UidType) => {
|
|
22
|
+
const executePresenterQuery = async (screenShareUid: UidType) => {
|
|
34
23
|
const requestId = getUniqueID();
|
|
35
24
|
const startReqTs = Date.now();
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
const payload = JSON.stringify({
|
|
28
|
+
uid: screenShareUid?.toString(),
|
|
39
29
|
passphrase: phrase,
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
preset: 'presenter',
|
|
31
|
+
});
|
|
32
|
+
const res = await fetch(`${RECORDING_LAYOUT_URL}`, {
|
|
33
|
+
method: 'POST',
|
|
42
34
|
headers: {
|
|
35
|
+
'Content-Type': 'application/json',
|
|
36
|
+
authorization: store.token ? `Bearer ${store.token}` : '',
|
|
43
37
|
'X-Request-Id': requestId,
|
|
44
38
|
'X-Session-Id': logger.getSessionId(),
|
|
45
39
|
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'RECORDING',
|
|
54
|
-
'setPresenterQuery success',
|
|
55
|
-
{
|
|
56
|
-
responseData: res,
|
|
57
|
-
startReqTs,
|
|
58
|
-
endReqTs,
|
|
59
|
-
latency: endReqTs - startReqTs,
|
|
60
|
-
requestId,
|
|
61
|
-
},
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
})
|
|
65
|
-
.catch(error => {
|
|
40
|
+
body: payload,
|
|
41
|
+
});
|
|
42
|
+
const response = await res.json();
|
|
43
|
+
|
|
44
|
+
if (response?.error) {
|
|
45
|
+
throw response?.error;
|
|
46
|
+
} else {
|
|
66
47
|
const endReqTs = Date.now();
|
|
67
|
-
logger.
|
|
48
|
+
logger.log(
|
|
68
49
|
LogSource.Internals,
|
|
69
50
|
'RECORDING',
|
|
70
|
-
'setPresenterQuery
|
|
71
|
-
JSON.stringify(error || {}),
|
|
51
|
+
'setPresenterQuery success',
|
|
72
52
|
{
|
|
53
|
+
responseData: res,
|
|
73
54
|
startReqTs,
|
|
74
55
|
endReqTs,
|
|
75
56
|
latency: endReqTs - startReqTs,
|
|
76
57
|
requestId,
|
|
77
58
|
},
|
|
78
59
|
);
|
|
79
|
-
}
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
const endReqTs = Date.now();
|
|
63
|
+
logger.error(
|
|
64
|
+
LogSource.Internals,
|
|
65
|
+
'RECORDING',
|
|
66
|
+
'setPresenterQuery failure',
|
|
67
|
+
JSON.stringify(error || {}),
|
|
68
|
+
{
|
|
69
|
+
startReqTs,
|
|
70
|
+
endReqTs,
|
|
71
|
+
latency: endReqTs - startReqTs,
|
|
72
|
+
requestId,
|
|
73
|
+
},
|
|
74
|
+
);
|
|
75
|
+
}
|
|
80
76
|
};
|
|
81
77
|
|
|
82
|
-
const executeNormalQuery = () => {
|
|
78
|
+
const executeNormalQuery = async () => {
|
|
83
79
|
const requestId = getUniqueID();
|
|
84
80
|
const startReqTs = Date.now();
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
81
|
+
|
|
82
|
+
const payload = JSON.stringify({
|
|
83
|
+
passphrase: phrase,
|
|
84
|
+
preset: 'normal',
|
|
85
|
+
});
|
|
86
|
+
try {
|
|
87
|
+
const res = await fetch(`${RECORDING_LAYOUT_URL}`, {
|
|
88
|
+
method: 'POST',
|
|
88
89
|
headers: {
|
|
90
|
+
'Content-Type': 'application/json',
|
|
91
|
+
authorization: store.token ? `Bearer ${store.token}` : '',
|
|
89
92
|
'X-Request-Id': requestId,
|
|
90
93
|
'X-Session-Id': logger.getSessionId(),
|
|
91
94
|
},
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
'RECORDING',
|
|
100
|
-
'executeNormalQuery success',
|
|
101
|
-
{
|
|
102
|
-
responseData: res,
|
|
103
|
-
startReqTs,
|
|
104
|
-
endReqTs,
|
|
105
|
-
latency: endReqTs - startReqTs,
|
|
106
|
-
requestId,
|
|
107
|
-
},
|
|
108
|
-
);
|
|
109
|
-
// Once the backend sucessfuly stops recording,
|
|
110
|
-
// send a control message to everbody in the channel indicating that cloud recording is now inactive.
|
|
111
|
-
// sendControlMessage(controlMessageEnum.cloudRecordingUnactive);
|
|
112
|
-
// set the local recording state to false to update the UI
|
|
113
|
-
// setScreenshareActive(false);
|
|
114
|
-
}
|
|
115
|
-
})
|
|
116
|
-
.catch(error => {
|
|
95
|
+
body: payload,
|
|
96
|
+
});
|
|
97
|
+
const response = await res.json();
|
|
98
|
+
|
|
99
|
+
if (response?.error) {
|
|
100
|
+
throw response?.error;
|
|
101
|
+
} else {
|
|
117
102
|
const endReqTs = Date.now();
|
|
118
|
-
logger.
|
|
103
|
+
logger.log(
|
|
119
104
|
LogSource.Internals,
|
|
120
105
|
'RECORDING',
|
|
121
|
-
'executeNormalQuery
|
|
122
|
-
JSON.stringify(error || {}),
|
|
106
|
+
'executeNormalQuery success',
|
|
123
107
|
{
|
|
108
|
+
responseData: res,
|
|
124
109
|
startReqTs,
|
|
125
110
|
endReqTs,
|
|
126
111
|
latency: endReqTs - startReqTs,
|
|
127
112
|
requestId,
|
|
128
113
|
},
|
|
129
114
|
);
|
|
130
|
-
|
|
115
|
+
// Once the backend sucessfuly stops recording,
|
|
116
|
+
// send a control message to everbody in the channel indicating that cloud recording is now inactive.
|
|
117
|
+
// sendControlMessage(controlMessageEnum.cloudRecordingUnactive);
|
|
118
|
+
// set the local recording state to false to update the UI
|
|
119
|
+
// setScreenshareActive(false);
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
const endReqTs = Date.now();
|
|
123
|
+
logger.error(
|
|
124
|
+
LogSource.Internals,
|
|
125
|
+
'RECORDING',
|
|
126
|
+
'executeNormalQuery failure',
|
|
127
|
+
JSON.stringify(error || {}),
|
|
128
|
+
{
|
|
129
|
+
startReqTs,
|
|
130
|
+
endReqTs,
|
|
131
|
+
latency: endReqTs - startReqTs,
|
|
132
|
+
requestId,
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
}
|
|
131
136
|
};
|
|
132
137
|
|
|
133
138
|
return {
|
|
@@ -254,7 +254,7 @@ const debounceFn = (fn: Function, ms = 300) => {
|
|
|
254
254
|
};
|
|
255
255
|
|
|
256
256
|
const capitalizeFirstLetter = (word: string): string => {
|
|
257
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
257
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
258
258
|
};
|
|
259
259
|
|
|
260
260
|
const CustomToolbarSort = (a, b) =>
|
|
@@ -382,6 +382,82 @@ function MergeMoreButtonFields(sourceArray, updateObject) {
|
|
|
382
382
|
return result;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
+
function getFormattedDateTime(ipDate: string) {
|
|
386
|
+
try {
|
|
387
|
+
let rdate = new Date(ipDate);
|
|
388
|
+
let ryear = rdate.getFullYear();
|
|
389
|
+
if (ryear === 1) {
|
|
390
|
+
throw Error(`Invalid end date, ${ipDate}`);
|
|
391
|
+
}
|
|
392
|
+
let rmonth = rdate.getMonth() + 1;
|
|
393
|
+
let rdt = rdate.getDate();
|
|
394
|
+
let hour = rdate.getHours();
|
|
395
|
+
let minute = rdate.getMinutes();
|
|
396
|
+
let ampm = hour >= 12 ? 'pm' : 'am';
|
|
397
|
+
hour = hour % 12;
|
|
398
|
+
hour = hour ? hour : 12; // the hour '0' should be '12'
|
|
399
|
+
minute = minute < 10 ? minute : minute;
|
|
400
|
+
|
|
401
|
+
const formattedHHMM = `${String(hour)}:${String(minute).padStart(
|
|
402
|
+
2,
|
|
403
|
+
'0',
|
|
404
|
+
)} ${ampm}`;
|
|
405
|
+
|
|
406
|
+
let today = new Date();
|
|
407
|
+
today.setHours(0);
|
|
408
|
+
today.setMinutes(0);
|
|
409
|
+
today.setSeconds(0);
|
|
410
|
+
today.setMilliseconds(0);
|
|
411
|
+
|
|
412
|
+
let compDate = new Date(ryear, rmonth - 1, rdt); // month - 1 because January == 0
|
|
413
|
+
let diff = today.getTime() - compDate.getTime(); // get the difference between today(at 00:00:00) and the date
|
|
414
|
+
|
|
415
|
+
if (compDate.getTime() == today.getTime()) {
|
|
416
|
+
return ['Today', `${formattedHHMM}`];
|
|
417
|
+
} else if (diff <= 24 * 60 * 60 * 1000) {
|
|
418
|
+
return ['Yesterday', `${formattedHHMM}`];
|
|
419
|
+
} else {
|
|
420
|
+
let fulldate = rdate.toDateString();
|
|
421
|
+
fulldate = fulldate.substring(fulldate.indexOf(' ') + 1);
|
|
422
|
+
return [fulldate, `${formattedHHMM}`];
|
|
423
|
+
}
|
|
424
|
+
} catch (error) {
|
|
425
|
+
console.error('error while converting recorded time: ', error);
|
|
426
|
+
return ipDate;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
const getFileName = (url: string) => {
|
|
431
|
+
return url.split('#')[0].split('?')[0].split('/').pop();
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
const downloadS3Link = (url: string): Promise<void> => {
|
|
435
|
+
return new Promise((resolve, reject) => {
|
|
436
|
+
if (typeof url !== 'string' || !url.trim()) {
|
|
437
|
+
return reject(new Error('Invalid URL provided for download'));
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
const fileName = getFileName(url);
|
|
442
|
+
const a = document.createElement('a');
|
|
443
|
+
|
|
444
|
+
a.href = url;
|
|
445
|
+
a.download = fileName;
|
|
446
|
+
a.target = '_blank';
|
|
447
|
+
a.rel = 'noopener noreferrer';
|
|
448
|
+
|
|
449
|
+
// Append to body to make `click()` work in all browsers
|
|
450
|
+
document.body.appendChild(a);
|
|
451
|
+
a.click();
|
|
452
|
+
// Clean up
|
|
453
|
+
document.body.removeChild(a);
|
|
454
|
+
resolve();
|
|
455
|
+
} catch (err) {
|
|
456
|
+
reject(err instanceof Error ? err : new Error('Download failed'));
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
};
|
|
460
|
+
|
|
385
461
|
export {
|
|
386
462
|
updateToolbarDefaultConfig,
|
|
387
463
|
useIsDesktop,
|
|
@@ -415,4 +491,6 @@ export {
|
|
|
415
491
|
CustomToolbarMerge,
|
|
416
492
|
MergeMoreButtonFields,
|
|
417
493
|
AuthErrorCodes,
|
|
494
|
+
downloadS3Link,
|
|
495
|
+
getFormattedDateTime,
|
|
418
496
|
};
|
|
@@ -1,31 +1,13 @@
|
|
|
1
|
-
import {gql, useMutation} from '@apollo/client';
|
|
2
1
|
import {RoomInfoContextInterface} from '../components/room-info/useRoomInfo';
|
|
3
2
|
import {useSetRoomInfo} from '../components/room-info/useSetRoomInfo';
|
|
4
3
|
import SDKEvents from '../utils/SdkEvents';
|
|
5
|
-
import isSDK from './isSDK';
|
|
6
4
|
import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
7
5
|
import getUniqueID from './getUniqueID';
|
|
6
|
+
import {useContext} from 'react';
|
|
7
|
+
import StorageContext from '../components/StorageContext';
|
|
8
|
+
|
|
9
|
+
const CREATE_ROOM_URL = `${$config.BACKEND_ENDPOINT}/v1/channel`;
|
|
8
10
|
|
|
9
|
-
const CREATE_CHANNEL = gql`
|
|
10
|
-
mutation CreateChannel($title: String!, $enablePSTN: Boolean) {
|
|
11
|
-
createChannel(title: $title, enablePSTN: $enablePSTN) {
|
|
12
|
-
passphrase {
|
|
13
|
-
host
|
|
14
|
-
view
|
|
15
|
-
}
|
|
16
|
-
channel
|
|
17
|
-
title
|
|
18
|
-
pstn {
|
|
19
|
-
number
|
|
20
|
-
dtmf
|
|
21
|
-
error {
|
|
22
|
-
code
|
|
23
|
-
message
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
`;
|
|
29
11
|
/**
|
|
30
12
|
* Returns an asynchronous function to create a meeting with the given options.
|
|
31
13
|
*/
|
|
@@ -34,8 +16,8 @@ export type createRoomFun = (
|
|
|
34
16
|
enablePSTN?: boolean,
|
|
35
17
|
) => Promise<void>;
|
|
36
18
|
export default function useCreateRoom(): createRoomFun {
|
|
37
|
-
const [createChannel, {error}] = useMutation(CREATE_CHANNEL);
|
|
38
19
|
const {setRoomInfo} = useSetRoomInfo();
|
|
20
|
+
const {store} = useContext(StorageContext);
|
|
39
21
|
return async (
|
|
40
22
|
roomTitle: string,
|
|
41
23
|
enablePSTN?: boolean,
|
|
@@ -56,25 +38,99 @@ export default function useCreateRoom(): createRoomFun {
|
|
|
56
38
|
requestId,
|
|
57
39
|
},
|
|
58
40
|
);
|
|
59
|
-
|
|
60
|
-
|
|
41
|
+
try {
|
|
42
|
+
const payload = JSON.stringify({
|
|
43
|
+
title: roomTitle,
|
|
44
|
+
enable_pstn: enablePSTN,
|
|
45
|
+
});
|
|
46
|
+
const response = await fetch(`${CREATE_ROOM_URL}`, {
|
|
47
|
+
method: 'POST',
|
|
61
48
|
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
authorization: store.token ? `Bearer ${store.token}` : '',
|
|
62
51
|
'X-Request-Id': requestId,
|
|
63
52
|
'X-Session-Id': logger.getSessionId(),
|
|
64
53
|
},
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
54
|
+
body: payload,
|
|
55
|
+
});
|
|
56
|
+
const res = await response.json();
|
|
57
|
+
if (res?.error) {
|
|
58
|
+
throw res.error;
|
|
59
|
+
} else if (res?.channel) {
|
|
60
|
+
const endReqTs = Date.now();
|
|
61
|
+
const latency = endReqTs - startReqTs;
|
|
62
|
+
logger.log(
|
|
63
|
+
LogSource.NetworkRest,
|
|
64
|
+
'createChannel',
|
|
65
|
+
'API createChannel. Channel created successfully',
|
|
66
|
+
{
|
|
67
|
+
responseData: res,
|
|
68
|
+
startReqTs,
|
|
69
|
+
endReqTs,
|
|
70
|
+
latency: latency,
|
|
71
|
+
requestId,
|
|
72
|
+
},
|
|
73
|
+
);
|
|
74
|
+
let roomInfo: Partial<RoomInfoContextInterface['data']> = {
|
|
75
|
+
roomId: {
|
|
76
|
+
attendee: '',
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
if (res?.viewer_pass_phrase) {
|
|
80
|
+
roomInfo.roomId.attendee = res.viewer_pass_phrase;
|
|
81
|
+
}
|
|
82
|
+
if (res?.host_pass_phrase) {
|
|
83
|
+
roomInfo.roomId.host = res.host_pass_phrase;
|
|
84
|
+
}
|
|
85
|
+
if (enablePSTN === true && res?.pstn) {
|
|
86
|
+
if (res.pstn?.error?.code || res.pstn?.error?.message) {
|
|
87
|
+
roomInfo.pstn = {
|
|
88
|
+
number: '',
|
|
89
|
+
pin: '',
|
|
90
|
+
error: {
|
|
91
|
+
code: res.pstn?.error?.code,
|
|
92
|
+
message: res.pstn?.error?.message,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
} else {
|
|
96
|
+
roomInfo.pstn = {
|
|
97
|
+
number: res.pstn?.number,
|
|
98
|
+
pin: res.pstn?.dtmf,
|
|
99
|
+
error: null,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
logger.log(LogSource.Internals, 'CREATE_MEETING', 'Room created', {
|
|
104
|
+
isHost: true,
|
|
105
|
+
isSeparateHostLink: isSeparateHostLink ? true : false,
|
|
106
|
+
meetingTitle: roomTitle,
|
|
107
|
+
roomId: roomInfo?.roomId,
|
|
108
|
+
pstn: roomInfo?.pstn,
|
|
109
|
+
});
|
|
110
|
+
setRoomInfo(prev => {
|
|
111
|
+
return {
|
|
112
|
+
...prev,
|
|
113
|
+
data: {
|
|
114
|
+
isHost: true,
|
|
115
|
+
isSeparateHostLink: isSeparateHostLink ? true : false,
|
|
116
|
+
meetingTitle: roomTitle,
|
|
117
|
+
roomId: roomInfo?.roomId,
|
|
118
|
+
pstn: roomInfo?.pstn,
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
SDKEvents.emit(
|
|
123
|
+
'create',
|
|
124
|
+
roomInfo.roomId.host,
|
|
125
|
+
roomInfo.roomId.attendee,
|
|
126
|
+
roomInfo?.pstn,
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
throw new Error(`An error occurred in parsing the channel data.`);
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const endReqTs = Date.now();
|
|
133
|
+
const latency = endReqTs - startReqTs;
|
|
78
134
|
logger.error(
|
|
79
135
|
LogSource.NetworkRest,
|
|
80
136
|
'createChannel',
|
|
@@ -89,79 +145,5 @@ export default function useCreateRoom(): createRoomFun {
|
|
|
89
145
|
);
|
|
90
146
|
throw error;
|
|
91
147
|
}
|
|
92
|
-
|
|
93
|
-
if (res && res?.data && res?.data?.createChannel) {
|
|
94
|
-
logger.log(
|
|
95
|
-
LogSource.NetworkRest,
|
|
96
|
-
'createChannel',
|
|
97
|
-
'API createChannel. Channel created successfully',
|
|
98
|
-
{
|
|
99
|
-
responseData: res.data.createChannel,
|
|
100
|
-
startReqTs,
|
|
101
|
-
endReqTs,
|
|
102
|
-
latency: latency,
|
|
103
|
-
requestId,
|
|
104
|
-
},
|
|
105
|
-
);
|
|
106
|
-
let roomInfo: Partial<RoomInfoContextInterface['data']> = {
|
|
107
|
-
roomId: {
|
|
108
|
-
attendee: '',
|
|
109
|
-
},
|
|
110
|
-
};
|
|
111
|
-
if (res?.data?.createChannel?.passphrase?.view) {
|
|
112
|
-
roomInfo.roomId.attendee = res.data.createChannel.passphrase.view;
|
|
113
|
-
}
|
|
114
|
-
if (res?.data?.createChannel?.passphrase?.host) {
|
|
115
|
-
roomInfo.roomId.host = res.data.createChannel.passphrase.host;
|
|
116
|
-
}
|
|
117
|
-
if (enablePSTN === true && res?.data?.createChannel?.pstn) {
|
|
118
|
-
if (
|
|
119
|
-
res.data.createChannel.pstn?.error?.code ||
|
|
120
|
-
res.data.createChannel.pstn?.error?.message
|
|
121
|
-
) {
|
|
122
|
-
roomInfo.pstn = {
|
|
123
|
-
number: '',
|
|
124
|
-
pin: '',
|
|
125
|
-
error: {
|
|
126
|
-
code: res.data.createChannel.pstn?.error?.code,
|
|
127
|
-
message: res.data.createChannel.pstn?.error?.message,
|
|
128
|
-
},
|
|
129
|
-
};
|
|
130
|
-
} else {
|
|
131
|
-
roomInfo.pstn = {
|
|
132
|
-
number: res.data.createChannel.pstn?.number,
|
|
133
|
-
pin: res.data.createChannel.pstn?.dtmf,
|
|
134
|
-
error: null,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
logger.log(LogSource.Internals, 'CREATE_MEETING', 'Room created', {
|
|
139
|
-
isHost: true,
|
|
140
|
-
isSeparateHostLink: isSeparateHostLink ? true : false,
|
|
141
|
-
meetingTitle: roomTitle,
|
|
142
|
-
roomId: roomInfo?.roomId,
|
|
143
|
-
pstn: roomInfo?.pstn,
|
|
144
|
-
});
|
|
145
|
-
setRoomInfo(prev => {
|
|
146
|
-
return {
|
|
147
|
-
...prev,
|
|
148
|
-
data: {
|
|
149
|
-
isHost: true,
|
|
150
|
-
isSeparateHostLink: isSeparateHostLink ? true : false,
|
|
151
|
-
meetingTitle: roomTitle,
|
|
152
|
-
roomId: roomInfo?.roomId,
|
|
153
|
-
pstn: roomInfo?.pstn,
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
});
|
|
157
|
-
SDKEvents.emit(
|
|
158
|
-
'create',
|
|
159
|
-
roomInfo.roomId.host,
|
|
160
|
-
roomInfo.roomId.attendee,
|
|
161
|
-
roomInfo?.pstn,
|
|
162
|
-
);
|
|
163
|
-
} else {
|
|
164
|
-
throw new Error(`An error occurred in parsing the channel data.`);
|
|
165
|
-
}
|
|
166
148
|
};
|
|
167
149
|
}
|