agora-appbuilder-core 4.1.11 → 4.1.12
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 +1 -1
- package/template/android/app/build.gradle +7 -0
- package/template/bridge/rtm/web/Types.ts +183 -0
- package/template/bridge/rtm/web/index-legacy.ts +540 -0
- package/template/bridge/rtm/web/index.ts +423 -491
- package/template/defaultConfig.js +1 -1
- package/template/ios/Podfile +63 -0
- package/template/ios/podspec-patches/boost.podspec +23 -0
- package/template/package.json +4 -4
- package/template/src/components/RTMConfigure-legacy.tsx +848 -0
- package/template/src/components/RTMConfigure.tsx +672 -436
- package/template/src/rtm/RTMEngine.ts +130 -33
- package/template/src/rtm-events-api/Events.ts +106 -30
- package/template/src/utils/useEndCall.ts +1 -1
|
@@ -0,0 +1,848 @@
|
|
|
1
|
+
/*
|
|
2
|
+
********************************************
|
|
3
|
+
Copyright © 2021 Agora Lab, Inc., all rights reserved.
|
|
4
|
+
AppBuilder and all associated components, source code, APIs, services, and documentation
|
|
5
|
+
(the “Materials”) are owned by Agora Lab, Inc. and its licensors. The Materials may not be
|
|
6
|
+
accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
|
|
7
|
+
Use without a license or in violation of any license terms and conditions (including use for
|
|
8
|
+
any purpose competitive to Agora Lab, Inc.’s business) is strictly prohibited. For more
|
|
9
|
+
information visit https://appbuilder.agora.io.
|
|
10
|
+
*********************************************
|
|
11
|
+
*/
|
|
12
|
+
// @ts-nocheck
|
|
13
|
+
import React, {useState, useContext, useEffect, useRef} from 'react';
|
|
14
|
+
import RtmEngine, {RtmChannelAttribute} from 'agora-react-native-rtm';
|
|
15
|
+
import {
|
|
16
|
+
ContentInterface,
|
|
17
|
+
DispatchContext,
|
|
18
|
+
PropsContext,
|
|
19
|
+
useLocalUid,
|
|
20
|
+
} from '../../agora-rn-uikit';
|
|
21
|
+
import ChatContext from './ChatContext';
|
|
22
|
+
import {Platform} from 'react-native';
|
|
23
|
+
import {backOff} from 'exponential-backoff';
|
|
24
|
+
import {useString} from '../utils/useString';
|
|
25
|
+
import {isAndroid, isIOS, isWeb, isWebInternal} from '../utils/common';
|
|
26
|
+
import {useContent, useIsAttendee, useUserName} from 'customization-api';
|
|
27
|
+
import {
|
|
28
|
+
safeJsonParse,
|
|
29
|
+
timeNow,
|
|
30
|
+
hasJsonStructure,
|
|
31
|
+
getMessageTime,
|
|
32
|
+
get32BitUid,
|
|
33
|
+
} from '../rtm/utils';
|
|
34
|
+
import {EventUtils, EventsQueue, EventNames} from '../rtm-events';
|
|
35
|
+
import events, {PersistanceLevel} from '../rtm-events-api';
|
|
36
|
+
import RTMEngine from '../rtm/RTMEngine';
|
|
37
|
+
import {filterObject} from '../utils';
|
|
38
|
+
import SDKEvents from '../utils/SdkEvents';
|
|
39
|
+
import isSDK from '../utils/isSDK';
|
|
40
|
+
import {useAsyncEffect} from '../utils/useAsyncEffect';
|
|
41
|
+
import {
|
|
42
|
+
WaitingRoomStatus,
|
|
43
|
+
useRoomInfo,
|
|
44
|
+
} from '../components/room-info/useRoomInfo';
|
|
45
|
+
import LocalEventEmitter, {
|
|
46
|
+
LocalEventsEnum,
|
|
47
|
+
} from '../rtm-events-api/LocalEvents';
|
|
48
|
+
import {PSTNUserLabel} from '../language/default-labels/videoCallScreenLabels';
|
|
49
|
+
import {controlMessageEnum} from '../components/ChatContext';
|
|
50
|
+
import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
51
|
+
import {RECORDING_BOT_UID} from '../utils/constants';
|
|
52
|
+
|
|
53
|
+
export enum UserType {
|
|
54
|
+
ScreenShare = 'screenshare',
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const RtmConfigure = (props: any) => {
|
|
58
|
+
const rtmInitTimstamp = new Date().getTime();
|
|
59
|
+
const localUid = useLocalUid();
|
|
60
|
+
const {callActive} = props;
|
|
61
|
+
const {rtcProps} = useContext(PropsContext);
|
|
62
|
+
const {dispatch} = useContext(DispatchContext);
|
|
63
|
+
const {defaultContent, activeUids} = useContent();
|
|
64
|
+
const defaultContentRef = useRef({defaultContent: defaultContent});
|
|
65
|
+
const activeUidsRef = useRef({activeUids: activeUids});
|
|
66
|
+
|
|
67
|
+
const {
|
|
68
|
+
waitingRoomStatus,
|
|
69
|
+
data: {isHost},
|
|
70
|
+
} = useRoomInfo();
|
|
71
|
+
const waitingRoomStatusRef = useRef({waitingRoomStatus: waitingRoomStatus});
|
|
72
|
+
|
|
73
|
+
const isHostRef = useRef({isHost: isHost});
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
isHostRef.current.isHost = isHost;
|
|
77
|
+
}, [isHost]);
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
waitingRoomStatusRef.current.waitingRoomStatus = waitingRoomStatus;
|
|
81
|
+
}, [waitingRoomStatus]);
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* inside event callback state won't have latest value.
|
|
85
|
+
* so creating ref to access the state
|
|
86
|
+
*/
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
activeUidsRef.current.activeUids = activeUids;
|
|
89
|
+
}, [activeUids]);
|
|
90
|
+
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
defaultContentRef.current.defaultContent = defaultContent;
|
|
93
|
+
}, [defaultContent]);
|
|
94
|
+
|
|
95
|
+
const [hasUserJoinedRTM, setHasUserJoinedRTM] = useState<boolean>(false);
|
|
96
|
+
const [isInitialQueueCompleted, setIsInitialQueueCompleted] = useState(false);
|
|
97
|
+
const [onlineUsersCount, setTotalOnlineUsers] = useState<number>(0);
|
|
98
|
+
|
|
99
|
+
let engine = useRef<RtmEngine>(null!);
|
|
100
|
+
const timerValueRef: any = useRef(5);
|
|
101
|
+
|
|
102
|
+
React.useEffect(() => {
|
|
103
|
+
setTotalOnlineUsers(
|
|
104
|
+
Object.keys(
|
|
105
|
+
filterObject(
|
|
106
|
+
defaultContent,
|
|
107
|
+
([k, v]) =>
|
|
108
|
+
v?.type === 'rtc' &&
|
|
109
|
+
!v.offline &&
|
|
110
|
+
activeUids.indexOf(v?.uid) !== -1,
|
|
111
|
+
),
|
|
112
|
+
).length,
|
|
113
|
+
);
|
|
114
|
+
}, [defaultContent]);
|
|
115
|
+
|
|
116
|
+
React.useEffect(() => {
|
|
117
|
+
if (!$config.ENABLE_CONVERSATIONAL_AI) {
|
|
118
|
+
const handBrowserClose = ev => {
|
|
119
|
+
ev.preventDefault();
|
|
120
|
+
return (ev.returnValue = 'Are you sure you want to exit?');
|
|
121
|
+
};
|
|
122
|
+
const logoutRtm = () => {
|
|
123
|
+
engine.current.leaveChannel(rtcProps.channel);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
if (!isWebInternal()) return;
|
|
127
|
+
window.addEventListener(
|
|
128
|
+
'beforeunload',
|
|
129
|
+
isWeb() && !isSDK() ? handBrowserClose : () => {},
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
window.addEventListener('pagehide', logoutRtm);
|
|
133
|
+
// cleanup this component
|
|
134
|
+
return () => {
|
|
135
|
+
window.removeEventListener(
|
|
136
|
+
'beforeunload',
|
|
137
|
+
isWeb() && !isSDK() ? handBrowserClose : () => {},
|
|
138
|
+
);
|
|
139
|
+
window.removeEventListener('pagehide', logoutRtm);
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}, []);
|
|
143
|
+
|
|
144
|
+
const doLoginAndSetupRTM = async () => {
|
|
145
|
+
try {
|
|
146
|
+
logger.log(LogSource.AgoraSDK, 'API', 'RTM login starts');
|
|
147
|
+
await engine.current.login({
|
|
148
|
+
uid: localUid.toString(),
|
|
149
|
+
token: rtcProps.rtm,
|
|
150
|
+
});
|
|
151
|
+
logger.log(LogSource.AgoraSDK, 'API', 'RTM login done');
|
|
152
|
+
RTMEngine.getInstance().setLocalUID(localUid.toString());
|
|
153
|
+
logger.log(LogSource.AgoraSDK, 'API', 'RTM local Uid set');
|
|
154
|
+
timerValueRef.current = 5;
|
|
155
|
+
await setAttribute();
|
|
156
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM setting attribute done');
|
|
157
|
+
} catch (error) {
|
|
158
|
+
logger.error(LogSource.AgoraSDK, 'Log', 'RTM login failed..Trying again');
|
|
159
|
+
setTimeout(async () => {
|
|
160
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
161
|
+
doLoginAndSetupRTM();
|
|
162
|
+
}, timerValueRef.current * 1000);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const setAttribute = async () => {
|
|
167
|
+
const rtmAttributes = [
|
|
168
|
+
{key: 'screenUid', value: String(rtcProps.screenShareUid)},
|
|
169
|
+
{key: 'isHost', value: String(isHostRef.current.isHost)},
|
|
170
|
+
];
|
|
171
|
+
try {
|
|
172
|
+
await engine.current.setLocalUserAttributes(rtmAttributes);
|
|
173
|
+
logger.log(
|
|
174
|
+
LogSource.AgoraSDK,
|
|
175
|
+
'API',
|
|
176
|
+
'RTM setting local user attributes',
|
|
177
|
+
{
|
|
178
|
+
attr: rtmAttributes,
|
|
179
|
+
},
|
|
180
|
+
);
|
|
181
|
+
timerValueRef.current = 5;
|
|
182
|
+
await joinChannel();
|
|
183
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM join channel done', {
|
|
184
|
+
data: rtmAttributes,
|
|
185
|
+
});
|
|
186
|
+
setHasUserJoinedRTM(true);
|
|
187
|
+
await runQueuedEvents();
|
|
188
|
+
setIsInitialQueueCompleted(true);
|
|
189
|
+
logger.log(
|
|
190
|
+
LogSource.AgoraSDK,
|
|
191
|
+
'Log',
|
|
192
|
+
'RTM queued events finished running',
|
|
193
|
+
{
|
|
194
|
+
attr: rtmAttributes,
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
logger.error(
|
|
199
|
+
LogSource.AgoraSDK,
|
|
200
|
+
'Log',
|
|
201
|
+
'RTM setAttribute failed..Trying again',
|
|
202
|
+
);
|
|
203
|
+
setTimeout(async () => {
|
|
204
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
205
|
+
setAttribute();
|
|
206
|
+
}, timerValueRef.current * 1000);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const joinChannel = async () => {
|
|
211
|
+
try {
|
|
212
|
+
if (RTMEngine.getInstance().channelUid !== rtcProps.channel) {
|
|
213
|
+
await engine.current.joinChannel(rtcProps.channel);
|
|
214
|
+
logger.log(LogSource.AgoraSDK, 'API', 'RTM joinChannel', {
|
|
215
|
+
data: rtcProps.channel,
|
|
216
|
+
});
|
|
217
|
+
RTMEngine.getInstance().setChannelId(rtcProps.channel);
|
|
218
|
+
logger.log(
|
|
219
|
+
LogSource.AgoraSDK,
|
|
220
|
+
'API',
|
|
221
|
+
'RTM setChannelId',
|
|
222
|
+
rtcProps.channel,
|
|
223
|
+
);
|
|
224
|
+
logger.debug(
|
|
225
|
+
LogSource.SDK,
|
|
226
|
+
'Event',
|
|
227
|
+
'Emitting rtm joined',
|
|
228
|
+
rtcProps.channel,
|
|
229
|
+
);
|
|
230
|
+
SDKEvents.emit('_rtm-joined', rtcProps.channel);
|
|
231
|
+
} else {
|
|
232
|
+
logger.debug(
|
|
233
|
+
LogSource.AgoraSDK,
|
|
234
|
+
'Log',
|
|
235
|
+
'RTM already joined channel skipping',
|
|
236
|
+
rtcProps.channel,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
timerValueRef.current = 5;
|
|
240
|
+
await getMembers();
|
|
241
|
+
await readAllChannelAttributes();
|
|
242
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM getMembers done');
|
|
243
|
+
} catch (error) {
|
|
244
|
+
logger.error(
|
|
245
|
+
LogSource.AgoraSDK,
|
|
246
|
+
'Log',
|
|
247
|
+
'RTM joinChannel failed..Trying again',
|
|
248
|
+
);
|
|
249
|
+
setTimeout(async () => {
|
|
250
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
251
|
+
joinChannel();
|
|
252
|
+
}, timerValueRef.current * 1000);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const updateRenderListState = (
|
|
257
|
+
uid: number,
|
|
258
|
+
data: Partial<ContentInterface>,
|
|
259
|
+
) => {
|
|
260
|
+
dispatch({type: 'UpdateRenderList', value: [uid, data]});
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const getMembers = async () => {
|
|
264
|
+
try {
|
|
265
|
+
logger.log(
|
|
266
|
+
LogSource.AgoraSDK,
|
|
267
|
+
'API',
|
|
268
|
+
'RTM getChannelMembersByID(getMembers) start',
|
|
269
|
+
);
|
|
270
|
+
await engine.current
|
|
271
|
+
.getChannelMembersBychannelId(rtcProps.channel)
|
|
272
|
+
.then(async data => {
|
|
273
|
+
logger.log(
|
|
274
|
+
LogSource.AgoraSDK,
|
|
275
|
+
'API',
|
|
276
|
+
'RTM getChannelMembersByID data received',
|
|
277
|
+
data,
|
|
278
|
+
);
|
|
279
|
+
await Promise.all(
|
|
280
|
+
data.members.map(async (member: any) => {
|
|
281
|
+
const backoffAttributes = backOff(
|
|
282
|
+
async () => {
|
|
283
|
+
logger.log(
|
|
284
|
+
LogSource.AgoraSDK,
|
|
285
|
+
'API',
|
|
286
|
+
`RTM fetching getUserAttributesByUid for member ${member.uid}`,
|
|
287
|
+
);
|
|
288
|
+
const attr = await engine.current.getUserAttributesByUid(
|
|
289
|
+
member.uid,
|
|
290
|
+
);
|
|
291
|
+
if (!attr || !attr.attributes) {
|
|
292
|
+
logger.log(
|
|
293
|
+
LogSource.AgoraSDK,
|
|
294
|
+
'API',
|
|
295
|
+
'RTM attributes for member not found',
|
|
296
|
+
);
|
|
297
|
+
throw attr;
|
|
298
|
+
}
|
|
299
|
+
logger.log(
|
|
300
|
+
LogSource.AgoraSDK,
|
|
301
|
+
'API',
|
|
302
|
+
`RTM getUserAttributesByUid for member ${member.uid} received`,
|
|
303
|
+
{
|
|
304
|
+
attr,
|
|
305
|
+
},
|
|
306
|
+
);
|
|
307
|
+
for (const key in attr.attributes) {
|
|
308
|
+
if (
|
|
309
|
+
attr.attributes.hasOwnProperty(key) &&
|
|
310
|
+
attr.attributes[key]
|
|
311
|
+
) {
|
|
312
|
+
return attr;
|
|
313
|
+
} else {
|
|
314
|
+
throw attr;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
retry: (e, idx) => {
|
|
320
|
+
logger.debug(
|
|
321
|
+
LogSource.AgoraSDK,
|
|
322
|
+
'Log',
|
|
323
|
+
`[retrying] Attempt ${idx}. Fetching ${member.uid}'s name`,
|
|
324
|
+
e,
|
|
325
|
+
);
|
|
326
|
+
return true;
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
);
|
|
330
|
+
try {
|
|
331
|
+
const attr = await backoffAttributes;
|
|
332
|
+
console.log('[user attributes]:', {attr});
|
|
333
|
+
//RTC layer uid type is number. so doing the parseInt to convert to number
|
|
334
|
+
//todo hari check android uid comparsion
|
|
335
|
+
const uid = parseInt(member.uid);
|
|
336
|
+
const screenUid = parseInt(attr?.attributes?.screenUid);
|
|
337
|
+
//start - updating user data in rtc
|
|
338
|
+
const userData = {
|
|
339
|
+
screenUid: screenUid,
|
|
340
|
+
//below thing for livestreaming
|
|
341
|
+
type: uid === parseInt(RECORDING_BOT_UID) ? 'bot' : 'rtc',
|
|
342
|
+
uid,
|
|
343
|
+
offline: false,
|
|
344
|
+
isHost: attr?.attributes?.isHost,
|
|
345
|
+
lastMessageTimeStamp: 0,
|
|
346
|
+
};
|
|
347
|
+
updateRenderListState(uid, userData);
|
|
348
|
+
//end- updating user data in rtc
|
|
349
|
+
|
|
350
|
+
//start - updating screenshare data in rtc
|
|
351
|
+
const screenShareUser = {
|
|
352
|
+
type: UserType.ScreenShare,
|
|
353
|
+
parentUid: uid,
|
|
354
|
+
};
|
|
355
|
+
updateRenderListState(screenUid, screenShareUser);
|
|
356
|
+
//end - updating screenshare data in rtc
|
|
357
|
+
// setting screenshare data
|
|
358
|
+
// name of the screenUid, isActive: false, (when the user starts screensharing it becomes true)
|
|
359
|
+
// isActive to identify all active screenshare users in the call
|
|
360
|
+
for (const [key, value] of Object.entries(attr?.attributes)) {
|
|
361
|
+
if (hasJsonStructure(value as string)) {
|
|
362
|
+
const data = {
|
|
363
|
+
evt: key,
|
|
364
|
+
value: value,
|
|
365
|
+
};
|
|
366
|
+
// TODOSUP: Add the data to queue, dont add same mulitple events, use set so as to not repeat events
|
|
367
|
+
EventsQueue.enqueue({
|
|
368
|
+
data: data,
|
|
369
|
+
uid: member.uid,
|
|
370
|
+
ts: timeNow(),
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
} catch (e) {
|
|
375
|
+
logger.error(
|
|
376
|
+
LogSource.AgoraSDK,
|
|
377
|
+
'Log',
|
|
378
|
+
`Could not retrieve name of ${member.uid}`,
|
|
379
|
+
e,
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
}),
|
|
383
|
+
);
|
|
384
|
+
logger.debug(
|
|
385
|
+
LogSource.AgoraSDK,
|
|
386
|
+
'Log',
|
|
387
|
+
'RTM fetched all data and user attr...RTM init done',
|
|
388
|
+
);
|
|
389
|
+
});
|
|
390
|
+
timerValueRef.current = 5;
|
|
391
|
+
} catch (error) {
|
|
392
|
+
setTimeout(async () => {
|
|
393
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
394
|
+
await getMembers();
|
|
395
|
+
}, timerValueRef.current * 1000);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
const readAllChannelAttributes = async () => {
|
|
400
|
+
try {
|
|
401
|
+
await engine.current
|
|
402
|
+
.getChannelAttributes(rtcProps.channel)
|
|
403
|
+
.then(async data => {
|
|
404
|
+
for (const item of data) {
|
|
405
|
+
const {key, value, lastUpdateTs, lastUpdateUserId} = item;
|
|
406
|
+
if (hasJsonStructure(value as string)) {
|
|
407
|
+
const evtData = {
|
|
408
|
+
evt: key,
|
|
409
|
+
value,
|
|
410
|
+
};
|
|
411
|
+
// TODOSUP: Add the data to queue, dont add same mulitple events, use set so as to not repeat events
|
|
412
|
+
EventsQueue.enqueue({
|
|
413
|
+
data: evtData,
|
|
414
|
+
uid: lastUpdateUserId,
|
|
415
|
+
ts: lastUpdateTs,
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
logger.log(
|
|
420
|
+
LogSource.AgoraSDK,
|
|
421
|
+
'API',
|
|
422
|
+
'RTM getChannelAttributes data received',
|
|
423
|
+
data,
|
|
424
|
+
);
|
|
425
|
+
});
|
|
426
|
+
timerValueRef.current = 5;
|
|
427
|
+
} catch (error) {
|
|
428
|
+
setTimeout(async () => {
|
|
429
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
430
|
+
await readAllChannelAttributes();
|
|
431
|
+
}, timerValueRef.current * 1000);
|
|
432
|
+
}
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const init = async () => {
|
|
436
|
+
//on sdk due to multiple re-render we are getting rtm error code 8
|
|
437
|
+
//you are joining the same channel too frequently, exceeding the allowed rate of joining the same channel multiple times within a short period
|
|
438
|
+
//so checking rtm connection state before proceed
|
|
439
|
+
if (engine?.current?.client?.connectionState === 'CONNECTED') {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM creating engine...');
|
|
443
|
+
engine.current = RTMEngine.getInstance().engine;
|
|
444
|
+
RTMEngine.getInstance();
|
|
445
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM engine creation done');
|
|
446
|
+
|
|
447
|
+
engine.current.on('connectionStateChanged', (evt: any) => {
|
|
448
|
+
//console.log(evt);
|
|
449
|
+
});
|
|
450
|
+
engine.current.on('error', (evt: any) => {
|
|
451
|
+
// console.log(evt);
|
|
452
|
+
});
|
|
453
|
+
engine.current.on('channelMemberJoined', (data: any) => {
|
|
454
|
+
logger.log(LogSource.AgoraSDK, 'Event', 'channelMemberJoined', data);
|
|
455
|
+
const backoffAttributes = backOff(
|
|
456
|
+
async () => {
|
|
457
|
+
logger.log(
|
|
458
|
+
LogSource.AgoraSDK,
|
|
459
|
+
'API',
|
|
460
|
+
`RTM fetching getUserAttributesByUid for member ${data.uid}`,
|
|
461
|
+
);
|
|
462
|
+
const attr = await engine.current.getUserAttributesByUid(data.uid);
|
|
463
|
+
if (!attr || !attr.attributes) {
|
|
464
|
+
logger.log(
|
|
465
|
+
LogSource.AgoraSDK,
|
|
466
|
+
'API',
|
|
467
|
+
'RTM attributes for member not found',
|
|
468
|
+
);
|
|
469
|
+
throw attr;
|
|
470
|
+
}
|
|
471
|
+
logger.log(
|
|
472
|
+
LogSource.AgoraSDK,
|
|
473
|
+
'API',
|
|
474
|
+
`RTM getUserAttributesByUid for member ${data.uid} received`,
|
|
475
|
+
{
|
|
476
|
+
attr,
|
|
477
|
+
},
|
|
478
|
+
);
|
|
479
|
+
for (const key in attr.attributes) {
|
|
480
|
+
if (attr.attributes.hasOwnProperty(key) && attr.attributes[key]) {
|
|
481
|
+
return attr;
|
|
482
|
+
} else {
|
|
483
|
+
throw attr;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
{
|
|
488
|
+
retry: (e, idx) => {
|
|
489
|
+
logger.debug(
|
|
490
|
+
LogSource.AgoraSDK,
|
|
491
|
+
'Log',
|
|
492
|
+
`[retrying] Attempt ${idx}. Fetching ${data.uid}'s name`,
|
|
493
|
+
e,
|
|
494
|
+
);
|
|
495
|
+
return true;
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
);
|
|
499
|
+
async function getname() {
|
|
500
|
+
try {
|
|
501
|
+
const attr = await backoffAttributes;
|
|
502
|
+
console.log('[user attributes]:', {attr});
|
|
503
|
+
const uid = parseInt(data.uid);
|
|
504
|
+
const screenUid = parseInt(attr?.attributes?.screenUid);
|
|
505
|
+
|
|
506
|
+
//start - updating user data in rtc
|
|
507
|
+
const userData = {
|
|
508
|
+
screenUid: screenUid,
|
|
509
|
+
//below thing for livestreaming
|
|
510
|
+
type: uid === parseInt(RECORDING_BOT_UID) ? 'bot' : 'rtc',
|
|
511
|
+
uid,
|
|
512
|
+
offline: false,
|
|
513
|
+
lastMessageTimeStamp: 0,
|
|
514
|
+
isHost: attr?.attributes?.isHost,
|
|
515
|
+
};
|
|
516
|
+
updateRenderListState(uid, userData);
|
|
517
|
+
//end- updating user data in rtc
|
|
518
|
+
|
|
519
|
+
//start - updating screenshare data in rtc
|
|
520
|
+
const screenShareUser = {
|
|
521
|
+
type: UserType.ScreenShare,
|
|
522
|
+
parentUid: uid,
|
|
523
|
+
};
|
|
524
|
+
updateRenderListState(screenUid, screenShareUser);
|
|
525
|
+
//end - updating screenshare data in rtc
|
|
526
|
+
} catch (e) {
|
|
527
|
+
logger.error(
|
|
528
|
+
LogSource.AgoraSDK,
|
|
529
|
+
'Event',
|
|
530
|
+
`Failed to retrive name of ${data.uid}`,
|
|
531
|
+
e,
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
getname();
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
engine.current.on('channelMemberLeft', (data: any) => {
|
|
539
|
+
logger.debug(LogSource.AgoraSDK, 'Event', 'channelMemberLeft', data);
|
|
540
|
+
// Chat of left user becomes undefined. So don't cleanup
|
|
541
|
+
const uid = data?.uid ? parseInt(data?.uid) : undefined;
|
|
542
|
+
if (!uid) return;
|
|
543
|
+
SDKEvents.emit('_rtm-left', uid);
|
|
544
|
+
// updating the rtc data
|
|
545
|
+
updateRenderListState(uid, {
|
|
546
|
+
offline: true,
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
engine.current.addListener(
|
|
551
|
+
'ChannelAttributesUpdated',
|
|
552
|
+
(attributeList: RtmChannelAttribute[]) => {
|
|
553
|
+
try {
|
|
554
|
+
attributeList.map((attribute: RtmChannelAttribute) => {
|
|
555
|
+
const {key, value, lastUpdateTs, lastUpdateUserId} = attribute;
|
|
556
|
+
const timestamp = getMessageTime(lastUpdateTs);
|
|
557
|
+
const sender = Platform.OS
|
|
558
|
+
? get32BitUid(lastUpdateUserId)
|
|
559
|
+
: parseInt(lastUpdateUserId);
|
|
560
|
+
eventDispatcher(
|
|
561
|
+
{
|
|
562
|
+
evt: key,
|
|
563
|
+
value,
|
|
564
|
+
},
|
|
565
|
+
sender,
|
|
566
|
+
timestamp,
|
|
567
|
+
);
|
|
568
|
+
});
|
|
569
|
+
} catch (error) {
|
|
570
|
+
logger.error(
|
|
571
|
+
LogSource.Events,
|
|
572
|
+
'CUSTOM_EVENTS',
|
|
573
|
+
'error while dispatching through eventDispatcher',
|
|
574
|
+
error,
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
);
|
|
579
|
+
|
|
580
|
+
engine.current.on('messageReceived', (evt: any) => {
|
|
581
|
+
logger.debug(LogSource.Events, 'CUSTOM_EVENTS', 'messageReceived', evt);
|
|
582
|
+
const {peerId, ts, text} = evt;
|
|
583
|
+
const [err, msg] = safeJsonParse(text);
|
|
584
|
+
if (err) {
|
|
585
|
+
logger.error(
|
|
586
|
+
LogSource.Events,
|
|
587
|
+
'CUSTOM_EVENTS',
|
|
588
|
+
'JSON payload incorrect, Error while parsing the payload',
|
|
589
|
+
err,
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const timestamp = getMessageTime(ts);
|
|
594
|
+
|
|
595
|
+
const sender = isAndroid() ? get32BitUid(peerId) : parseInt(peerId);
|
|
596
|
+
|
|
597
|
+
try {
|
|
598
|
+
eventDispatcher(msg, sender, timestamp);
|
|
599
|
+
} catch (error) {
|
|
600
|
+
logger.error(
|
|
601
|
+
LogSource.Events,
|
|
602
|
+
'CUSTOM_EVENTS',
|
|
603
|
+
'error while dispatching through eventDispatcher',
|
|
604
|
+
err,
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
engine.current.on('channelMessageReceived', evt => {
|
|
610
|
+
logger.debug(
|
|
611
|
+
LogSource.Events,
|
|
612
|
+
'CUSTOM_EVENTS',
|
|
613
|
+
'channelMessageReceived',
|
|
614
|
+
evt,
|
|
615
|
+
);
|
|
616
|
+
|
|
617
|
+
const {uid, channelId, text, ts} = evt;
|
|
618
|
+
//whiteboard upload
|
|
619
|
+
if (uid == 1010101) {
|
|
620
|
+
const [err, res] = safeJsonParse(text);
|
|
621
|
+
if (err) {
|
|
622
|
+
logger.error(
|
|
623
|
+
LogSource.Events,
|
|
624
|
+
'CUSTOM_EVENTS',
|
|
625
|
+
'JSON payload incorrect, Error while parsing the payload',
|
|
626
|
+
err,
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
if (res?.data?.data?.images) {
|
|
631
|
+
LocalEventEmitter.emit(
|
|
632
|
+
LocalEventsEnum.WHITEBOARD_FILE_UPLOAD,
|
|
633
|
+
res?.data?.data?.images,
|
|
634
|
+
);
|
|
635
|
+
}
|
|
636
|
+
} else {
|
|
637
|
+
const [err, msg] = safeJsonParse(text);
|
|
638
|
+
if (err) {
|
|
639
|
+
logger.error(
|
|
640
|
+
LogSource.Events,
|
|
641
|
+
'CUSTOM_EVENTS',
|
|
642
|
+
'JSON payload incorrect, Error while parsing the payload',
|
|
643
|
+
err,
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
const timestamp = getMessageTime(ts);
|
|
648
|
+
|
|
649
|
+
const sender = Platform.OS ? get32BitUid(uid) : parseInt(uid);
|
|
650
|
+
|
|
651
|
+
if (channelId === rtcProps.channel) {
|
|
652
|
+
try {
|
|
653
|
+
eventDispatcher(msg, sender, timestamp);
|
|
654
|
+
} catch (error) {
|
|
655
|
+
logger.error(
|
|
656
|
+
LogSource.Events,
|
|
657
|
+
'CUSTOM_EVENTS',
|
|
658
|
+
'error while dispatching through eventDispatcher',
|
|
659
|
+
error,
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
await doLoginAndSetupRTM();
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
const runQueuedEvents = async () => {
|
|
670
|
+
try {
|
|
671
|
+
while (!EventsQueue.isEmpty()) {
|
|
672
|
+
const currEvt = EventsQueue.dequeue();
|
|
673
|
+
await eventDispatcher(currEvt.data, currEvt.uid, currEvt.ts);
|
|
674
|
+
}
|
|
675
|
+
} catch (error) {
|
|
676
|
+
logger.error(
|
|
677
|
+
LogSource.Events,
|
|
678
|
+
'CUSTOM_EVENTS',
|
|
679
|
+
'error while running queue events',
|
|
680
|
+
error,
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
const eventDispatcher = async (
|
|
686
|
+
data: {
|
|
687
|
+
evt: string;
|
|
688
|
+
value: string;
|
|
689
|
+
},
|
|
690
|
+
sender: string,
|
|
691
|
+
ts: number,
|
|
692
|
+
) => {
|
|
693
|
+
console.debug(
|
|
694
|
+
LogSource.Events,
|
|
695
|
+
'CUSTOM_EVENTS',
|
|
696
|
+
'inside eventDispatcher ',
|
|
697
|
+
data,
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
let evt = '',
|
|
701
|
+
value = {};
|
|
702
|
+
|
|
703
|
+
if (data.feat === 'WAITING_ROOM') {
|
|
704
|
+
if (data.etyp === 'REQUEST') {
|
|
705
|
+
const outputData = {
|
|
706
|
+
evt: `${data.feat}_${data.etyp}`,
|
|
707
|
+
payload: JSON.stringify({
|
|
708
|
+
attendee_uid: data.data.data.attendee_uid,
|
|
709
|
+
attendee_screenshare_uid: data.data.data.attendee_screenshare_uid,
|
|
710
|
+
}),
|
|
711
|
+
persistLevel: 1,
|
|
712
|
+
source: 'core',
|
|
713
|
+
};
|
|
714
|
+
const formattedData = JSON.stringify(outputData);
|
|
715
|
+
evt = data.feat + '_' + data.etyp; //rename if client side RTM meessage is to be sent for approval
|
|
716
|
+
value = formattedData;
|
|
717
|
+
}
|
|
718
|
+
if (data.etyp === 'RESPONSE') {
|
|
719
|
+
const outputData = {
|
|
720
|
+
evt: `${data.feat}_${data.etyp}`,
|
|
721
|
+
payload: JSON.stringify({
|
|
722
|
+
approved: data.data.data.approved,
|
|
723
|
+
channelName: data.data.data.channel_name,
|
|
724
|
+
mainUser: data.data.data.mainUser,
|
|
725
|
+
screenShare: data.data.data.screenShare,
|
|
726
|
+
whiteboard: data.data.data.whiteboard,
|
|
727
|
+
chat: data.data.data?.chat,
|
|
728
|
+
}),
|
|
729
|
+
persistLevel: 1,
|
|
730
|
+
source: 'core',
|
|
731
|
+
};
|
|
732
|
+
const formattedData = JSON.stringify(outputData);
|
|
733
|
+
evt = data.feat + '_' + data.etyp;
|
|
734
|
+
value = formattedData;
|
|
735
|
+
}
|
|
736
|
+
} else {
|
|
737
|
+
if (
|
|
738
|
+
$config.ENABLE_WAITING_ROOM &&
|
|
739
|
+
!isHostRef.current?.isHost &&
|
|
740
|
+
waitingRoomStatusRef.current?.waitingRoomStatus !==
|
|
741
|
+
WaitingRoomStatus.APPROVED
|
|
742
|
+
) {
|
|
743
|
+
if (
|
|
744
|
+
data.evt === controlMessageEnum.muteAudio ||
|
|
745
|
+
data.evt === controlMessageEnum.muteVideo
|
|
746
|
+
) {
|
|
747
|
+
return;
|
|
748
|
+
} else {
|
|
749
|
+
evt = data.evt;
|
|
750
|
+
value = data.value;
|
|
751
|
+
}
|
|
752
|
+
} else {
|
|
753
|
+
evt = data.evt;
|
|
754
|
+
value = data.value;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
try {
|
|
759
|
+
const {payload, persistLevel, source} = JSON.parse(value);
|
|
760
|
+
// Step 1: Set local attributes
|
|
761
|
+
if (persistLevel === PersistanceLevel.Session) {
|
|
762
|
+
const rtmAttribute = {key: evt, value: value};
|
|
763
|
+
await engine.current.addOrUpdateLocalUserAttributes([rtmAttribute]);
|
|
764
|
+
}
|
|
765
|
+
// Step 2: Emit the event
|
|
766
|
+
console.debug(LogSource.Events, 'CUSTOM_EVENTS', 'emiting event..: ');
|
|
767
|
+
EventUtils.emitEvent(evt, source, {payload, persistLevel, sender, ts});
|
|
768
|
+
// Because async gets evaluated in a different order when in an sdk
|
|
769
|
+
if (evt === 'name') {
|
|
770
|
+
setTimeout(() => {
|
|
771
|
+
EventUtils.emitEvent(evt, source, {
|
|
772
|
+
payload,
|
|
773
|
+
persistLevel,
|
|
774
|
+
sender,
|
|
775
|
+
ts,
|
|
776
|
+
});
|
|
777
|
+
}, 200);
|
|
778
|
+
}
|
|
779
|
+
} catch (error) {
|
|
780
|
+
console.error(
|
|
781
|
+
LogSource.Events,
|
|
782
|
+
'CUSTOM_EVENTS',
|
|
783
|
+
'error while emiting event:',
|
|
784
|
+
error,
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
const end = async () => {
|
|
790
|
+
if (!callActive) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
await RTMEngine.getInstance().destroy();
|
|
794
|
+
logger.log(LogSource.AgoraSDK, 'API', 'RTM destroy done');
|
|
795
|
+
if (isIOS() || isAndroid()) {
|
|
796
|
+
EventUtils.clear();
|
|
797
|
+
}
|
|
798
|
+
setHasUserJoinedRTM(false);
|
|
799
|
+
logger.debug(LogSource.AgoraSDK, 'Log', 'RTM cleanup done');
|
|
800
|
+
};
|
|
801
|
+
|
|
802
|
+
useAsyncEffect(async () => {
|
|
803
|
+
//waiting room attendee -> rtm login will happen on page load
|
|
804
|
+
if ($config.ENABLE_WAITING_ROOM) {
|
|
805
|
+
//attendee
|
|
806
|
+
//for waiting room attendee rtm login will happen on mount
|
|
807
|
+
if (!isHost && !callActive) {
|
|
808
|
+
await init();
|
|
809
|
+
}
|
|
810
|
+
//host
|
|
811
|
+
if (
|
|
812
|
+
isHost &&
|
|
813
|
+
($config.AUTO_CONNECT_RTM || (!$config.AUTO_CONNECT_RTM && callActive))
|
|
814
|
+
) {
|
|
815
|
+
await init();
|
|
816
|
+
}
|
|
817
|
+
} else {
|
|
818
|
+
//non waiting room case
|
|
819
|
+
//host and attendee
|
|
820
|
+
if (
|
|
821
|
+
$config.AUTO_CONNECT_RTM ||
|
|
822
|
+
(!$config.AUTO_CONNECT_RTM && callActive)
|
|
823
|
+
) {
|
|
824
|
+
await init();
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return async () => {
|
|
828
|
+
await end();
|
|
829
|
+
};
|
|
830
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
831
|
+
}, [rtcProps.channel, rtcProps.appId, callActive]);
|
|
832
|
+
|
|
833
|
+
return (
|
|
834
|
+
<ChatContext.Provider
|
|
835
|
+
value={{
|
|
836
|
+
isInitialQueueCompleted,
|
|
837
|
+
rtmInitTimstamp,
|
|
838
|
+
hasUserJoinedRTM,
|
|
839
|
+
engine: engine.current,
|
|
840
|
+
localUid: localUid,
|
|
841
|
+
onlineUsersCount,
|
|
842
|
+
}}>
|
|
843
|
+
{props.children}
|
|
844
|
+
</ChatContext.Provider>
|
|
845
|
+
);
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
export default RtmConfigure;
|