agora-appbuilder-core 4.1.9 → 4.1.11-beta.2
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/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -3
- package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +1 -2
- package/template/agora-rn-uikit/src/Reducer/index.ts +0 -2
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +11 -25
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +1 -14
- package/template/agora-rn-uikit/src/Utils/isBotUser.ts +1 -1
- package/template/android/app/build.gradle +0 -7
- package/template/bridge/rtm/web/Types.ts +0 -183
- package/template/bridge/rtm/web/index.ts +491 -423
- package/template/defaultConfig.js +3 -3
- package/template/ios/Podfile +0 -41
- package/template/package.json +5 -5
- package/template/src/assets/font-styles.css +4 -0
- package/template/src/assets/fonts/icomoon.ttf +0 -0
- package/template/src/assets/selection.json +1 -1
- package/template/src/atoms/ActionMenu.tsx +93 -13
- package/template/src/atoms/CustomIcon.tsx +1 -0
- package/template/src/atoms/DropDownMulti.tsx +80 -29
- package/template/src/atoms/Input.tsx +2 -1
- package/template/src/components/Controls.tsx +148 -143
- package/template/src/components/EventsConfigure.tsx +152 -97
- package/template/src/components/RTMConfigure.tsx +426 -644
- package/template/src/components/precall/joinCallBtn.native.tsx +7 -2
- package/template/src/components/precall/joinCallBtn.tsx +7 -2
- package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +8 -3
- package/template/src/components/precall/joinWaitingRoomBtn.tsx +22 -4
- package/template/src/components/precall/textInput.tsx +45 -22
- package/template/src/components/precall/usePreCall.tsx +7 -0
- package/template/src/components/room-info/useRoomInfo.tsx +5 -0
- package/template/src/language/default-labels/videoCallScreenLabels.ts +27 -4
- package/template/src/pages/video-call/ActionSheetContent.tsx +77 -77
- package/template/src/pages/video-call/SidePanelHeader.tsx +81 -36
- package/template/src/rtm/RTMEngine.ts +33 -130
- package/template/src/rtm-events/constants.ts +6 -0
- package/template/src/rtm-events-api/Events.ts +30 -106
- package/template/src/subComponents/caption/Caption.tsx +48 -7
- package/template/src/subComponents/caption/CaptionContainer.tsx +324 -51
- package/template/src/subComponents/caption/CaptionIcon.tsx +35 -34
- package/template/src/subComponents/caption/CaptionText.tsx +103 -2
- package/template/src/subComponents/caption/LanguageSelectorPopup.tsx +179 -69
- package/template/src/subComponents/caption/Transcript.tsx +46 -11
- package/template/src/subComponents/caption/TranscriptIcon.tsx +27 -35
- package/template/src/subComponents/caption/TranscriptText.tsx +78 -3
- package/template/src/subComponents/caption/proto/ptoto.js +38 -4
- package/template/src/subComponents/caption/proto/test.proto +34 -19
- package/template/src/subComponents/caption/useCaption.tsx +753 -10
- package/template/src/subComponents/caption/useSTTAPI.tsx +118 -205
- package/template/src/subComponents/caption/useStreamMessageUtils.native.ts +152 -33
- package/template/src/subComponents/caption/useStreamMessageUtils.ts +165 -34
- package/template/src/subComponents/caption/utils.ts +171 -3
- package/template/src/utils/SdkEvents.ts +3 -0
- package/template/src/utils/useEndCall.ts +3 -5
- package/template/src/utils/useSpeechToText.ts +31 -20
- package/template/agora-rn-uikit/src/Reducer/Spotlight.ts +0 -11
- package/template/agora-rn-uikit/src/Reducer/UserBanned.ts +0 -11
- package/template/bridge/rtm/web/index-legacy.ts +0 -540
- package/template/src/components/RTMConfigure-legacy.tsx +0 -848
|
@@ -9,32 +9,21 @@
|
|
|
9
9
|
information visit https://appbuilder.agora.io.
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
|
-
|
|
12
|
+
// @ts-nocheck
|
|
13
13
|
import React, {useState, useContext, useEffect, useRef} from 'react';
|
|
14
|
-
import {
|
|
15
|
-
type GetChannelMetadataResponse,
|
|
16
|
-
type GetOnlineUsersResponse,
|
|
17
|
-
type LinkStateEvent,
|
|
18
|
-
type MessageEvent,
|
|
19
|
-
type Metadata,
|
|
20
|
-
type PresenceEvent,
|
|
21
|
-
type SetOrUpdateUserMetadataOptions,
|
|
22
|
-
type StorageEvent,
|
|
23
|
-
type RTMClient,
|
|
24
|
-
type GetUserMetadataResponse,
|
|
25
|
-
} from 'agora-react-native-rtm';
|
|
14
|
+
import RtmEngine, {RtmChannelAttribute} from 'agora-react-native-rtm';
|
|
26
15
|
import {
|
|
27
16
|
ContentInterface,
|
|
28
17
|
DispatchContext,
|
|
29
18
|
PropsContext,
|
|
30
|
-
UidType,
|
|
31
19
|
useLocalUid,
|
|
32
20
|
} from '../../agora-rn-uikit';
|
|
33
21
|
import ChatContext from './ChatContext';
|
|
34
22
|
import {Platform} from 'react-native';
|
|
35
23
|
import {backOff} from 'exponential-backoff';
|
|
24
|
+
import {useString} from '../utils/useString';
|
|
36
25
|
import {isAndroid, isIOS, isWeb, isWebInternal} from '../utils/common';
|
|
37
|
-
import {useContent} from 'customization-api';
|
|
26
|
+
import {useContent, useIsAttendee, useUserName} from 'customization-api';
|
|
38
27
|
import {
|
|
39
28
|
safeJsonParse,
|
|
40
29
|
timeNow,
|
|
@@ -42,8 +31,8 @@ import {
|
|
|
42
31
|
getMessageTime,
|
|
43
32
|
get32BitUid,
|
|
44
33
|
} from '../rtm/utils';
|
|
45
|
-
import {EventUtils, EventsQueue} from '../rtm-events';
|
|
46
|
-
import {PersistanceLevel} from '../rtm-events-api';
|
|
34
|
+
import {EventUtils, EventsQueue, EventNames} from '../rtm-events';
|
|
35
|
+
import events, {PersistanceLevel} from '../rtm-events-api';
|
|
47
36
|
import RTMEngine from '../rtm/RTMEngine';
|
|
48
37
|
import {filterObject} from '../utils';
|
|
49
38
|
import SDKEvents from '../utils/SdkEvents';
|
|
@@ -56,79 +45,60 @@ import {
|
|
|
56
45
|
import LocalEventEmitter, {
|
|
57
46
|
LocalEventsEnum,
|
|
58
47
|
} from '../rtm-events-api/LocalEvents';
|
|
48
|
+
import {PSTNUserLabel} from '../language/default-labels/videoCallScreenLabels';
|
|
59
49
|
import {controlMessageEnum} from '../components/ChatContext';
|
|
60
50
|
import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
61
51
|
import {RECORDING_BOT_UID} from '../utils/constants';
|
|
62
|
-
import {
|
|
63
|
-
nativeChannelTypeMapping,
|
|
64
|
-
nativeLinkStateMapping,
|
|
65
|
-
nativePresenceEventTypeMapping,
|
|
66
|
-
nativeStorageEventTypeMapping,
|
|
67
|
-
} from '../../bridge/rtm/web/Types';
|
|
68
52
|
|
|
69
53
|
export enum UserType {
|
|
70
54
|
ScreenShare = 'screenshare',
|
|
71
55
|
}
|
|
72
56
|
|
|
73
|
-
const eventTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
|
74
|
-
|
|
75
57
|
const RtmConfigure = (props: any) => {
|
|
76
|
-
let engine = useRef<RTMClient>(null!);
|
|
77
58
|
const rtmInitTimstamp = new Date().getTime();
|
|
78
59
|
const localUid = useLocalUid();
|
|
79
60
|
const {callActive} = props;
|
|
80
61
|
const {rtcProps} = useContext(PropsContext);
|
|
81
62
|
const {dispatch} = useContext(DispatchContext);
|
|
82
63
|
const {defaultContent, activeUids} = useContent();
|
|
64
|
+
const defaultContentRef = useRef({defaultContent: defaultContent});
|
|
65
|
+
const activeUidsRef = useRef({activeUids: activeUids});
|
|
66
|
+
|
|
83
67
|
const {
|
|
84
68
|
waitingRoomStatus,
|
|
85
69
|
data: {isHost},
|
|
86
70
|
} = useRoomInfo();
|
|
87
|
-
const
|
|
88
|
-
const [isInitialQueueCompleted, setIsInitialQueueCompleted] = useState(false);
|
|
89
|
-
const [onlineUsersCount, setTotalOnlineUsers] = useState<number>(0);
|
|
90
|
-
const timerValueRef: any = useRef(5);
|
|
91
|
-
// Track RTM connection state (equivalent to v1.5x connectionState check)
|
|
92
|
-
const [rtmConnectionState, setRtmConnectionState] = useState<number>(0); // 0=IDLE, 2=CONNECTED
|
|
71
|
+
const waitingRoomStatusRef = useRef({waitingRoomStatus: waitingRoomStatus});
|
|
93
72
|
|
|
94
|
-
/**
|
|
95
|
-
* inside event callback state won't have latest value.
|
|
96
|
-
* so creating ref to access the state
|
|
97
|
-
*/
|
|
98
73
|
const isHostRef = useRef({isHost: isHost});
|
|
74
|
+
|
|
99
75
|
useEffect(() => {
|
|
100
76
|
isHostRef.current.isHost = isHost;
|
|
101
77
|
}, [isHost]);
|
|
102
78
|
|
|
103
|
-
const waitingRoomStatusRef = useRef({waitingRoomStatus: waitingRoomStatus});
|
|
104
79
|
useEffect(() => {
|
|
105
80
|
waitingRoomStatusRef.current.waitingRoomStatus = waitingRoomStatus;
|
|
106
81
|
}, [waitingRoomStatus]);
|
|
107
82
|
|
|
108
|
-
|
|
83
|
+
/**
|
|
84
|
+
* inside event callback state won't have latest value.
|
|
85
|
+
* so creating ref to access the state
|
|
86
|
+
*/
|
|
109
87
|
useEffect(() => {
|
|
110
88
|
activeUidsRef.current.activeUids = activeUids;
|
|
111
89
|
}, [activeUids]);
|
|
112
90
|
|
|
113
|
-
const defaultContentRef = useRef({defaultContent: defaultContent});
|
|
114
91
|
useEffect(() => {
|
|
115
92
|
defaultContentRef.current.defaultContent = defaultContent;
|
|
116
93
|
}, [defaultContent]);
|
|
117
94
|
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
for (const timeout of eventTimeouts.values()) {
|
|
125
|
-
clearTimeout(timeout);
|
|
126
|
-
}
|
|
127
|
-
eventTimeouts.clear();
|
|
128
|
-
};
|
|
129
|
-
}, []);
|
|
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);
|
|
130
101
|
|
|
131
|
-
// Set online users
|
|
132
102
|
React.useEffect(() => {
|
|
133
103
|
setTotalOnlineUsers(
|
|
134
104
|
Object.keys(
|
|
@@ -137,42 +107,31 @@ const RtmConfigure = (props: any) => {
|
|
|
137
107
|
([k, v]) =>
|
|
138
108
|
v?.type === 'rtc' &&
|
|
139
109
|
!v.offline &&
|
|
140
|
-
|
|
110
|
+
activeUids.indexOf(v?.uid) !== -1,
|
|
141
111
|
),
|
|
142
112
|
).length,
|
|
143
113
|
);
|
|
144
114
|
}, [defaultContent]);
|
|
145
115
|
|
|
146
116
|
React.useEffect(() => {
|
|
147
|
-
|
|
148
|
-
// the platform is web execute the window listeners
|
|
149
|
-
if (!$config.ENABLE_CONVERSATIONAL_AI && isWebInternal()) {
|
|
117
|
+
if (!$config.ENABLE_CONVERSATIONAL_AI) {
|
|
150
118
|
const handBrowserClose = ev => {
|
|
151
119
|
ev.preventDefault();
|
|
152
120
|
return (ev.returnValue = 'Are you sure you want to exit?');
|
|
153
121
|
};
|
|
154
122
|
const logoutRtm = () => {
|
|
155
|
-
|
|
156
|
-
if (engine.current && RTMEngine.getInstance().channelUid) {
|
|
157
|
-
// First unsubscribe from channel (like v1.5x leaveChannel)
|
|
158
|
-
engine.current.unsubscribe(RTMEngine.getInstance().channelUid);
|
|
159
|
-
// Then logout
|
|
160
|
-
engine.current.logout();
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
console.error('Error during browser close RTM cleanup:', error);
|
|
164
|
-
}
|
|
123
|
+
engine.current.leaveChannel(rtcProps.channel);
|
|
165
124
|
};
|
|
166
125
|
|
|
167
|
-
|
|
126
|
+
if (!isWebInternal()) return;
|
|
168
127
|
window.addEventListener(
|
|
169
128
|
'beforeunload',
|
|
170
129
|
isWeb() && !isSDK() ? handBrowserClose : () => {},
|
|
171
130
|
);
|
|
172
131
|
|
|
173
132
|
window.addEventListener('pagehide', logoutRtm);
|
|
133
|
+
// cleanup this component
|
|
174
134
|
return () => {
|
|
175
|
-
// Remove listeners on unmount
|
|
176
135
|
window.removeEventListener(
|
|
177
136
|
'beforeunload',
|
|
178
137
|
isWeb() && !isSDK() ? handBrowserClose : () => {},
|
|
@@ -182,303 +141,23 @@ const RtmConfigure = (props: any) => {
|
|
|
182
141
|
}
|
|
183
142
|
}, []);
|
|
184
143
|
|
|
185
|
-
const init = async (rtcUid: UidType) => {
|
|
186
|
-
//on sdk due to multiple re-render we are getting rtm error code 8
|
|
187
|
-
//you are joining the same channel too frequently, exceeding the allowed rate of joining the same channel multiple times within a short period
|
|
188
|
-
//so checking rtm connection state before proceed
|
|
189
|
-
|
|
190
|
-
// Check if already connected (equivalent to v1.5x connectionState === 'CONNECTED')
|
|
191
|
-
if (
|
|
192
|
-
rtmConnectionState === nativeLinkStateMapping.CONNECTED &&
|
|
193
|
-
RTMEngine.getInstance().isEngineReady
|
|
194
|
-
) {
|
|
195
|
-
logger.log(
|
|
196
|
-
LogSource.AgoraSDK,
|
|
197
|
-
'Log',
|
|
198
|
-
'🚫 RTM already connected, skipping initialization',
|
|
199
|
-
);
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
try {
|
|
204
|
-
if (!RTMEngine.getInstance().isEngineReady) {
|
|
205
|
-
RTMEngine.getInstance().setLocalUID(rtcUid);
|
|
206
|
-
logger.log(LogSource.AgoraSDK, 'API', 'RTM local Uid set', rtcUid);
|
|
207
|
-
}
|
|
208
|
-
engine.current = RTMEngine.getInstance().engine;
|
|
209
|
-
// Logout any opened sessions if any
|
|
210
|
-
engine.current.logout();
|
|
211
|
-
logger.log(LogSource.AgoraSDK, 'Log', 'RTM client creation done');
|
|
212
|
-
} catch (error) {
|
|
213
|
-
logger.error(
|
|
214
|
-
LogSource.AgoraSDK,
|
|
215
|
-
'Log',
|
|
216
|
-
'RTM engine initialization failed:',
|
|
217
|
-
{error},
|
|
218
|
-
);
|
|
219
|
-
throw error;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
engine.current.addEventListener(
|
|
223
|
-
'linkState',
|
|
224
|
-
async (data: LinkStateEvent) => {
|
|
225
|
-
// Update connection state for duplicate initialization prevention
|
|
226
|
-
setRtmConnectionState(data.currentState);
|
|
227
|
-
logger.log(
|
|
228
|
-
LogSource.AgoraSDK,
|
|
229
|
-
'Event',
|
|
230
|
-
`RTM linkState changed: ${data.previousState} -> ${data.currentState}`,
|
|
231
|
-
data,
|
|
232
|
-
);
|
|
233
|
-
if (data.currentState === nativeLinkStateMapping.CONNECTED) {
|
|
234
|
-
// CONNECTED state
|
|
235
|
-
logger.log(LogSource.AgoraSDK, 'Event', 'RTM connected', {
|
|
236
|
-
previousState: data.previousState,
|
|
237
|
-
currentState: data.currentState,
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
if (data.currentState === nativeLinkStateMapping.FAILED) {
|
|
241
|
-
// FAILED state
|
|
242
|
-
logger.error(LogSource.AgoraSDK, 'Event', 'RTM connection failed', {
|
|
243
|
-
error: {
|
|
244
|
-
reasonCode: data.reasonCode,
|
|
245
|
-
currentState: data.currentState,
|
|
246
|
-
},
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
engine.current.addEventListener('storage', (storage: StorageEvent) => {
|
|
253
|
-
// when remote user sets/updates metadata - 3
|
|
254
|
-
if (
|
|
255
|
-
storage.eventType === nativeStorageEventTypeMapping.SET ||
|
|
256
|
-
storage.eventType === nativeStorageEventTypeMapping.UPDATE
|
|
257
|
-
) {
|
|
258
|
-
const storageTypeStr = storage.storageType === 1 ? 'user' : 'channel';
|
|
259
|
-
const eventTypeStr = storage.eventType === 2 ? 'SET' : 'UPDATE';
|
|
260
|
-
logger.log(
|
|
261
|
-
LogSource.AgoraSDK,
|
|
262
|
-
'Event',
|
|
263
|
-
`RTM storage event of type: [${eventTypeStr} ${storageTypeStr} metadata]`,
|
|
264
|
-
storage,
|
|
265
|
-
);
|
|
266
|
-
try {
|
|
267
|
-
if (storage.data?.items && Array.isArray(storage.data.items)) {
|
|
268
|
-
storage.data.items.forEach(item => {
|
|
269
|
-
try {
|
|
270
|
-
if (!item || !item.key) {
|
|
271
|
-
logger.warn(
|
|
272
|
-
LogSource.Events,
|
|
273
|
-
'CUSTOM_EVENTS',
|
|
274
|
-
'Invalid storage item:',
|
|
275
|
-
item,
|
|
276
|
-
);
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const {key, value, authorUserId, updateTs} = item;
|
|
281
|
-
const timestamp = getMessageTime(updateTs);
|
|
282
|
-
const sender = Platform.OS
|
|
283
|
-
? get32BitUid(authorUserId)
|
|
284
|
-
: parseInt(authorUserId, 10);
|
|
285
|
-
eventDispatcher(
|
|
286
|
-
{
|
|
287
|
-
evt: key,
|
|
288
|
-
value,
|
|
289
|
-
},
|
|
290
|
-
`${sender}`,
|
|
291
|
-
timestamp,
|
|
292
|
-
);
|
|
293
|
-
} catch (error) {
|
|
294
|
-
logger.error(
|
|
295
|
-
LogSource.Events,
|
|
296
|
-
'CUSTOM_EVENTS',
|
|
297
|
-
`Failed to process storage item: ${JSON.stringify(item)}`,
|
|
298
|
-
{error},
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
} catch (error) {
|
|
304
|
-
logger.error(
|
|
305
|
-
LogSource.Events,
|
|
306
|
-
'CUSTOM_EVENTS',
|
|
307
|
-
'error while dispatching through eventDispatcher',
|
|
308
|
-
{error},
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
engine.current.addEventListener(
|
|
315
|
-
'presence',
|
|
316
|
-
async (presence: PresenceEvent) => {
|
|
317
|
-
if (`${localUid}` === presence.publisher) {
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
// remoteJoinChannel
|
|
321
|
-
if (presence.type === nativePresenceEventTypeMapping.REMOTE_JOIN) {
|
|
322
|
-
logger.log(
|
|
323
|
-
LogSource.AgoraSDK,
|
|
324
|
-
'Event',
|
|
325
|
-
'RTM presenceEvent of type [3 - remoteJoin] (channelMemberJoined)',
|
|
326
|
-
);
|
|
327
|
-
const backoffAttributes = await fetchUserAttributesWithBackoffRetry(
|
|
328
|
-
presence.publisher,
|
|
329
|
-
);
|
|
330
|
-
await processUserUidAttributes(backoffAttributes, presence.publisher);
|
|
331
|
-
}
|
|
332
|
-
// remoteLeaveChannel
|
|
333
|
-
if (presence.type === nativePresenceEventTypeMapping.REMOTE_LEAVE) {
|
|
334
|
-
logger.log(
|
|
335
|
-
LogSource.AgoraSDK,
|
|
336
|
-
'Event',
|
|
337
|
-
'RTM presenceEvent of type [4 - remoteLeave] (channelMemberLeft)',
|
|
338
|
-
presence,
|
|
339
|
-
);
|
|
340
|
-
// Chat of left user becomes undefined. So don't cleanup
|
|
341
|
-
const uid = presence?.publisher
|
|
342
|
-
? parseInt(presence.publisher, 10)
|
|
343
|
-
: undefined;
|
|
344
|
-
|
|
345
|
-
if (!uid) {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
SDKEvents.emit('_rtm-left', uid);
|
|
349
|
-
// updating the rtc data
|
|
350
|
-
updateRenderListState(uid, {
|
|
351
|
-
offline: true,
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
},
|
|
355
|
-
);
|
|
356
|
-
|
|
357
|
-
engine.current.addEventListener('message', (message: MessageEvent) => {
|
|
358
|
-
if (`${localUid}` === message.publisher) {
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
// message - 1 (channel)
|
|
362
|
-
if (message.channelType === nativeChannelTypeMapping.MESSAGE) {
|
|
363
|
-
logger.debug(
|
|
364
|
-
LogSource.Events,
|
|
365
|
-
'CUSTOM_EVENTS',
|
|
366
|
-
'messageEvent of type [1 - CHANNEL] (channelMessageReceived)',
|
|
367
|
-
message,
|
|
368
|
-
);
|
|
369
|
-
const {
|
|
370
|
-
publisher: uid,
|
|
371
|
-
channelName: channelId,
|
|
372
|
-
message: text,
|
|
373
|
-
timestamp: ts,
|
|
374
|
-
} = message;
|
|
375
|
-
//whiteboard upload
|
|
376
|
-
if (parseInt(uid, 10) === 1010101) {
|
|
377
|
-
const [err, res] = safeJsonParse(text);
|
|
378
|
-
if (err) {
|
|
379
|
-
logger.error(
|
|
380
|
-
LogSource.Events,
|
|
381
|
-
'CUSTOM_EVENTS',
|
|
382
|
-
'JSON payload incorrect, Error while parsing the payload',
|
|
383
|
-
{error: err},
|
|
384
|
-
);
|
|
385
|
-
}
|
|
386
|
-
if (res?.data?.data?.images) {
|
|
387
|
-
LocalEventEmitter.emit(
|
|
388
|
-
LocalEventsEnum.WHITEBOARD_FILE_UPLOAD,
|
|
389
|
-
res?.data?.data?.images,
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
} else {
|
|
393
|
-
const [err, msg] = safeJsonParse(text);
|
|
394
|
-
if (err) {
|
|
395
|
-
logger.error(
|
|
396
|
-
LogSource.Events,
|
|
397
|
-
'CUSTOM_EVENTS',
|
|
398
|
-
'JSON payload incorrect, Error while parsing the payload',
|
|
399
|
-
{error: err},
|
|
400
|
-
);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
const timestamp = getMessageTime(ts);
|
|
404
|
-
const sender = Platform.OS ? get32BitUid(uid) : parseInt(uid, 10);
|
|
405
|
-
|
|
406
|
-
if (channelId === rtcProps.channel) {
|
|
407
|
-
try {
|
|
408
|
-
eventDispatcher(msg, `${sender}`, timestamp);
|
|
409
|
-
} catch (error) {
|
|
410
|
-
logger.error(
|
|
411
|
-
LogSource.Events,
|
|
412
|
-
'CUSTOM_EVENTS',
|
|
413
|
-
'error while dispatching through eventDispatcher',
|
|
414
|
-
{error},
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// message - 3 (user)
|
|
422
|
-
if (message.channelType === nativeChannelTypeMapping.USER) {
|
|
423
|
-
logger.debug(
|
|
424
|
-
LogSource.Events,
|
|
425
|
-
'CUSTOM_EVENTS',
|
|
426
|
-
'messageEvent of type [3- USER] (messageReceived)',
|
|
427
|
-
message,
|
|
428
|
-
);
|
|
429
|
-
const {publisher: peerId, timestamp: ts, message: text} = message;
|
|
430
|
-
const [err, msg] = safeJsonParse(text);
|
|
431
|
-
if (err) {
|
|
432
|
-
logger.error(
|
|
433
|
-
LogSource.Events,
|
|
434
|
-
'CUSTOM_EVENTS',
|
|
435
|
-
'JSON payload incorrect, Error while parsing the payload',
|
|
436
|
-
{error: err},
|
|
437
|
-
);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
const timestamp = getMessageTime(ts);
|
|
441
|
-
|
|
442
|
-
const sender = isAndroid() ? get32BitUid(peerId) : parseInt(peerId, 10);
|
|
443
|
-
|
|
444
|
-
try {
|
|
445
|
-
eventDispatcher(msg, `${sender}`, timestamp);
|
|
446
|
-
} catch (error) {
|
|
447
|
-
logger.error(
|
|
448
|
-
LogSource.Events,
|
|
449
|
-
'CUSTOM_EVENTS',
|
|
450
|
-
'error while dispatching through eventDispatcher',
|
|
451
|
-
{error},
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
await doLoginAndSetupRTM();
|
|
458
|
-
};
|
|
459
|
-
|
|
460
144
|
const doLoginAndSetupRTM = async () => {
|
|
461
145
|
try {
|
|
462
146
|
logger.log(LogSource.AgoraSDK, 'API', 'RTM login starts');
|
|
463
147
|
await engine.current.login({
|
|
464
|
-
|
|
148
|
+
uid: localUid.toString(),
|
|
465
149
|
token: rtcProps.rtm,
|
|
466
150
|
});
|
|
467
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');
|
|
468
154
|
timerValueRef.current = 5;
|
|
469
|
-
// waiting for login to be fully connected
|
|
470
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
471
155
|
await setAttribute();
|
|
156
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM setting attribute done');
|
|
472
157
|
} catch (error) {
|
|
473
|
-
logger.error(
|
|
474
|
-
LogSource.AgoraSDK,
|
|
475
|
-
'Log',
|
|
476
|
-
'RTM login failed..Trying again',
|
|
477
|
-
{error},
|
|
478
|
-
);
|
|
158
|
+
logger.error(LogSource.AgoraSDK, 'Log', 'RTM login failed..Trying again');
|
|
479
159
|
setTimeout(async () => {
|
|
480
|
-
|
|
481
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
160
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
482
161
|
doLoginAndSetupRTM();
|
|
483
162
|
}, timerValueRef.current * 1000);
|
|
484
163
|
}
|
|
@@ -490,13 +169,7 @@ const RtmConfigure = (props: any) => {
|
|
|
490
169
|
{key: 'isHost', value: String(isHostRef.current.isHost)},
|
|
491
170
|
];
|
|
492
171
|
try {
|
|
493
|
-
|
|
494
|
-
items: rtmAttributes,
|
|
495
|
-
};
|
|
496
|
-
const options: SetOrUpdateUserMetadataOptions = {
|
|
497
|
-
userId: `${localUid}`,
|
|
498
|
-
};
|
|
499
|
-
await engine.current.storage.setUserMetadata(data, options);
|
|
172
|
+
await engine.current.setLocalUserAttributes(rtmAttributes);
|
|
500
173
|
logger.log(
|
|
501
174
|
LogSource.AgoraSDK,
|
|
502
175
|
'API',
|
|
@@ -506,15 +179,10 @@ const RtmConfigure = (props: any) => {
|
|
|
506
179
|
},
|
|
507
180
|
);
|
|
508
181
|
timerValueRef.current = 5;
|
|
509
|
-
await
|
|
510
|
-
logger.log(
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
'RTM subscribe, fetch members, reading channel atrributes all done',
|
|
514
|
-
{
|
|
515
|
-
data: rtmAttributes,
|
|
516
|
-
},
|
|
517
|
-
);
|
|
182
|
+
await joinChannel();
|
|
183
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM join channel done', {
|
|
184
|
+
data: rtmAttributes,
|
|
185
|
+
});
|
|
518
186
|
setHasUserJoinedRTM(true);
|
|
519
187
|
await runQueuedEvents();
|
|
520
188
|
setIsInitialQueueCompleted(true);
|
|
@@ -531,138 +199,184 @@ const RtmConfigure = (props: any) => {
|
|
|
531
199
|
LogSource.AgoraSDK,
|
|
532
200
|
'Log',
|
|
533
201
|
'RTM setAttribute failed..Trying again',
|
|
534
|
-
{error},
|
|
535
202
|
);
|
|
536
203
|
setTimeout(async () => {
|
|
537
|
-
|
|
538
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
204
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
539
205
|
setAttribute();
|
|
540
206
|
}, timerValueRef.current * 1000);
|
|
541
207
|
}
|
|
542
208
|
};
|
|
543
209
|
|
|
544
|
-
const
|
|
210
|
+
const joinChannel = async () => {
|
|
545
211
|
try {
|
|
546
|
-
if (RTMEngine.getInstance().channelUid
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
'Log',
|
|
550
|
-
'🚫 RTM already subscribed channel skipping',
|
|
551
|
-
rtcProps.channel,
|
|
552
|
-
);
|
|
553
|
-
} else {
|
|
554
|
-
await engine.current.subscribe(rtcProps.channel, {
|
|
555
|
-
withMessage: true,
|
|
556
|
-
withPresence: true,
|
|
557
|
-
withMetadata: true,
|
|
558
|
-
withLock: false,
|
|
559
|
-
});
|
|
560
|
-
logger.log(LogSource.AgoraSDK, 'API', 'RTM subscribeChannel', {
|
|
212
|
+
if (RTMEngine.getInstance().channelUid !== rtcProps.channel) {
|
|
213
|
+
await engine.current.joinChannel(rtcProps.channel);
|
|
214
|
+
logger.log(LogSource.AgoraSDK, 'API', 'RTM joinChannel', {
|
|
561
215
|
data: rtcProps.channel,
|
|
562
216
|
});
|
|
563
|
-
|
|
564
|
-
// Set channel ID AFTER successful subscribe (like v1.5x)
|
|
565
217
|
RTMEngine.getInstance().setChannelId(rtcProps.channel);
|
|
566
218
|
logger.log(
|
|
567
219
|
LogSource.AgoraSDK,
|
|
568
220
|
'API',
|
|
569
|
-
'RTM setChannelId
|
|
221
|
+
'RTM setChannelId',
|
|
570
222
|
rtcProps.channel,
|
|
571
223
|
);
|
|
572
|
-
|
|
573
224
|
logger.debug(
|
|
574
225
|
LogSource.SDK,
|
|
575
226
|
'Event',
|
|
576
227
|
'Emitting rtm joined',
|
|
577
228
|
rtcProps.channel,
|
|
578
229
|
);
|
|
579
|
-
// @ts-ignore
|
|
580
230
|
SDKEvents.emit('_rtm-joined', rtcProps.channel);
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
await readAllChannelAttributes();
|
|
584
|
-
logger.log(
|
|
231
|
+
} else {
|
|
232
|
+
logger.debug(
|
|
585
233
|
LogSource.AgoraSDK,
|
|
586
234
|
'Log',
|
|
587
|
-
'RTM
|
|
235
|
+
'RTM already joined channel skipping',
|
|
236
|
+
rtcProps.channel,
|
|
588
237
|
);
|
|
589
238
|
}
|
|
239
|
+
timerValueRef.current = 5;
|
|
240
|
+
await getMembers();
|
|
241
|
+
await readAllChannelAttributes();
|
|
242
|
+
logger.log(LogSource.AgoraSDK, 'Log', 'RTM getMembers done');
|
|
590
243
|
} catch (error) {
|
|
591
244
|
logger.error(
|
|
592
245
|
LogSource.AgoraSDK,
|
|
593
246
|
'Log',
|
|
594
|
-
'RTM
|
|
595
|
-
{error},
|
|
247
|
+
'RTM joinChannel failed..Trying again',
|
|
596
248
|
);
|
|
597
249
|
setTimeout(async () => {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
subscribeChannel();
|
|
250
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
251
|
+
joinChannel();
|
|
601
252
|
}, timerValueRef.current * 1000);
|
|
602
253
|
}
|
|
603
254
|
};
|
|
604
255
|
|
|
256
|
+
const updateRenderListState = (
|
|
257
|
+
uid: number,
|
|
258
|
+
data: Partial<ContentInterface>,
|
|
259
|
+
) => {
|
|
260
|
+
dispatch({type: 'UpdateRenderList', value: [uid, data]});
|
|
261
|
+
};
|
|
262
|
+
|
|
605
263
|
const getMembers = async () => {
|
|
606
264
|
try {
|
|
607
265
|
logger.log(
|
|
608
266
|
LogSource.AgoraSDK,
|
|
609
267
|
'API',
|
|
610
|
-
'RTM
|
|
268
|
+
'RTM getChannelMembersByID(getMembers) start',
|
|
611
269
|
);
|
|
612
|
-
await engine.current
|
|
613
|
-
.
|
|
614
|
-
.then(async
|
|
270
|
+
await engine.current
|
|
271
|
+
.getChannelMembersBychannelId(rtcProps.channel)
|
|
272
|
+
.then(async data => {
|
|
615
273
|
logger.log(
|
|
616
274
|
LogSource.AgoraSDK,
|
|
617
275
|
'API',
|
|
618
|
-
'RTM
|
|
276
|
+
'RTM getChannelMembersByID data received',
|
|
619
277
|
data,
|
|
620
278
|
);
|
|
621
279
|
await Promise.all(
|
|
622
|
-
data.
|
|
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
|
+
);
|
|
623
330
|
try {
|
|
624
|
-
const
|
|
625
|
-
|
|
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
|
|
626
349
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
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
|
|
631
357
|
// setting screenshare data
|
|
632
358
|
// name of the screenUid, isActive: false, (when the user starts screensharing it becomes true)
|
|
633
359
|
// isActive to identify all active screenshare users in the call
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
} catch (error) {
|
|
649
|
-
logger.error(
|
|
650
|
-
LogSource.AgoraSDK,
|
|
651
|
-
'Log',
|
|
652
|
-
`RTM Failed to process user attribute item for ${
|
|
653
|
-
member.userId
|
|
654
|
-
}: ${JSON.stringify(item)}`,
|
|
655
|
-
{error},
|
|
656
|
-
);
|
|
657
|
-
// Continue processing other items
|
|
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
|
+
});
|
|
658
372
|
}
|
|
659
|
-
}
|
|
373
|
+
}
|
|
660
374
|
} catch (e) {
|
|
661
375
|
logger.error(
|
|
662
376
|
LogSource.AgoraSDK,
|
|
663
377
|
'Log',
|
|
664
|
-
`
|
|
665
|
-
|
|
378
|
+
`Could not retrieve name of ${member.uid}`,
|
|
379
|
+
e,
|
|
666
380
|
);
|
|
667
381
|
}
|
|
668
382
|
}),
|
|
@@ -676,8 +390,7 @@ const RtmConfigure = (props: any) => {
|
|
|
676
390
|
timerValueRef.current = 5;
|
|
677
391
|
} catch (error) {
|
|
678
392
|
setTimeout(async () => {
|
|
679
|
-
|
|
680
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
393
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
681
394
|
await getMembers();
|
|
682
395
|
}, timerValueRef.current * 1000);
|
|
683
396
|
}
|
|
@@ -685,169 +398,286 @@ const RtmConfigure = (props: any) => {
|
|
|
685
398
|
|
|
686
399
|
const readAllChannelAttributes = async () => {
|
|
687
400
|
try {
|
|
688
|
-
await engine.current
|
|
689
|
-
.
|
|
690
|
-
.then(async
|
|
691
|
-
for (const item of data
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
});
|
|
705
|
-
}
|
|
706
|
-
} catch (error) {
|
|
707
|
-
logger.error(
|
|
708
|
-
LogSource.AgoraSDK,
|
|
709
|
-
'Log',
|
|
710
|
-
`RTM Failed to process channel attribute item: ${JSON.stringify(
|
|
711
|
-
item,
|
|
712
|
-
)}`,
|
|
713
|
-
{error},
|
|
714
|
-
);
|
|
715
|
-
// Continue processing other items
|
|
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
|
+
});
|
|
716
417
|
}
|
|
717
418
|
}
|
|
718
419
|
logger.log(
|
|
719
420
|
LogSource.AgoraSDK,
|
|
720
421
|
'API',
|
|
721
|
-
'RTM
|
|
422
|
+
'RTM getChannelAttributes data received',
|
|
722
423
|
data,
|
|
723
424
|
);
|
|
724
425
|
});
|
|
725
426
|
timerValueRef.current = 5;
|
|
726
427
|
} catch (error) {
|
|
727
428
|
setTimeout(async () => {
|
|
728
|
-
|
|
729
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
429
|
+
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
730
430
|
await readAllChannelAttributes();
|
|
731
431
|
}, timerValueRef.current * 1000);
|
|
732
432
|
}
|
|
733
433
|
};
|
|
734
434
|
|
|
735
|
-
const
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
const attr: GetUserMetadataResponse =
|
|
747
|
-
await engine.current.storage.getUserMetadata({
|
|
748
|
-
userId: userId,
|
|
749
|
-
});
|
|
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');
|
|
750
446
|
|
|
751
|
-
|
|
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
|
+
}
|
|
752
471
|
logger.log(
|
|
753
472
|
LogSource.AgoraSDK,
|
|
754
473
|
'API',
|
|
755
|
-
|
|
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,
|
|
756
532
|
);
|
|
757
|
-
throw attr;
|
|
758
533
|
}
|
|
534
|
+
}
|
|
535
|
+
getname();
|
|
536
|
+
});
|
|
759
537
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
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
|
+
});
|
|
766
549
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
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,
|
|
780
575
|
);
|
|
781
|
-
|
|
782
|
-
},
|
|
576
|
+
}
|
|
783
577
|
},
|
|
784
578
|
);
|
|
785
|
-
};
|
|
786
579
|
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
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
|
+
}
|
|
799
592
|
|
|
800
|
-
|
|
801
|
-
const userData = {
|
|
802
|
-
screenUid: screenUid,
|
|
803
|
-
//below thing for livestreaming
|
|
804
|
-
type: uid === parseInt(RECORDING_BOT_UID, 10) ? 'bot' : 'rtc',
|
|
805
|
-
uid,
|
|
806
|
-
offline: false,
|
|
807
|
-
isHost: isHostItem?.value || false,
|
|
808
|
-
lastMessageTimeStamp: 0,
|
|
809
|
-
};
|
|
810
|
-
updateRenderListState(uid, userData);
|
|
811
|
-
//end- updating user data in rtc
|
|
593
|
+
const timestamp = getMessageTime(ts);
|
|
812
594
|
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
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
|
+
);
|
|
820
606
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
engine.current.on('channelMessageReceived', evt => {
|
|
610
|
+
logger.debug(
|
|
611
|
+
LogSource.Events,
|
|
612
|
+
'CUSTOM_EVENTS',
|
|
613
|
+
'channelMessageReceived',
|
|
614
|
+
evt,
|
|
828
615
|
);
|
|
829
|
-
}
|
|
830
|
-
};
|
|
831
616
|
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
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();
|
|
837
667
|
};
|
|
838
668
|
|
|
839
669
|
const runQueuedEvents = async () => {
|
|
840
670
|
try {
|
|
841
671
|
while (!EventsQueue.isEmpty()) {
|
|
842
672
|
const currEvt = EventsQueue.dequeue();
|
|
843
|
-
await eventDispatcher(currEvt.data,
|
|
673
|
+
await eventDispatcher(currEvt.data, currEvt.uid, currEvt.ts);
|
|
844
674
|
}
|
|
845
675
|
} catch (error) {
|
|
846
676
|
logger.error(
|
|
847
677
|
LogSource.Events,
|
|
848
678
|
'CUSTOM_EVENTS',
|
|
849
679
|
'error while running queue events',
|
|
850
|
-
|
|
680
|
+
error,
|
|
851
681
|
);
|
|
852
682
|
}
|
|
853
683
|
};
|
|
@@ -856,13 +686,11 @@ const RtmConfigure = (props: any) => {
|
|
|
856
686
|
data: {
|
|
857
687
|
evt: string;
|
|
858
688
|
value: string;
|
|
859
|
-
feat?: string;
|
|
860
|
-
etyp?: string;
|
|
861
689
|
},
|
|
862
690
|
sender: string,
|
|
863
691
|
ts: number,
|
|
864
692
|
) => {
|
|
865
|
-
console.
|
|
693
|
+
console.debug(
|
|
866
694
|
LogSource.Events,
|
|
867
695
|
'CUSTOM_EVENTS',
|
|
868
696
|
'inside eventDispatcher ',
|
|
@@ -870,10 +698,10 @@ const RtmConfigure = (props: any) => {
|
|
|
870
698
|
);
|
|
871
699
|
|
|
872
700
|
let evt = '',
|
|
873
|
-
value =
|
|
701
|
+
value = {};
|
|
874
702
|
|
|
875
|
-
if (data
|
|
876
|
-
if (data
|
|
703
|
+
if (data.feat === 'WAITING_ROOM') {
|
|
704
|
+
if (data.etyp === 'REQUEST') {
|
|
877
705
|
const outputData = {
|
|
878
706
|
evt: `${data.feat}_${data.etyp}`,
|
|
879
707
|
payload: JSON.stringify({
|
|
@@ -887,7 +715,7 @@ const RtmConfigure = (props: any) => {
|
|
|
887
715
|
evt = data.feat + '_' + data.etyp; //rename if client side RTM meessage is to be sent for approval
|
|
888
716
|
value = formattedData;
|
|
889
717
|
}
|
|
890
|
-
if (data
|
|
718
|
+
if (data.etyp === 'RESPONSE') {
|
|
891
719
|
const outputData = {
|
|
892
720
|
evt: `${data.feat}_${data.etyp}`,
|
|
893
721
|
payload: JSON.stringify({
|
|
@@ -928,65 +756,32 @@ const RtmConfigure = (props: any) => {
|
|
|
928
756
|
}
|
|
929
757
|
|
|
930
758
|
try {
|
|
931
|
-
|
|
932
|
-
try {
|
|
933
|
-
parsedValue = typeof value === 'string' ? JSON.parse(value) : value;
|
|
934
|
-
} catch (error) {
|
|
935
|
-
logger.error(
|
|
936
|
-
LogSource.Events,
|
|
937
|
-
'CUSTOM_EVENTS',
|
|
938
|
-
'RTM Failed to parse event value in event dispatcher:',
|
|
939
|
-
{error},
|
|
940
|
-
);
|
|
941
|
-
return;
|
|
942
|
-
}
|
|
943
|
-
const {payload, persistLevel, source} = parsedValue;
|
|
759
|
+
const {payload, persistLevel, source} = JSON.parse(value);
|
|
944
760
|
// Step 1: Set local attributes
|
|
945
761
|
if (persistLevel === PersistanceLevel.Session) {
|
|
946
762
|
const rtmAttribute = {key: evt, value: value};
|
|
947
|
-
|
|
948
|
-
userId: `${localUid}`,
|
|
949
|
-
};
|
|
950
|
-
await engine.current.storage.setUserMetadata(
|
|
951
|
-
{
|
|
952
|
-
items: [rtmAttribute],
|
|
953
|
-
},
|
|
954
|
-
options,
|
|
955
|
-
);
|
|
763
|
+
await engine.current.addOrUpdateLocalUserAttributes([rtmAttribute]);
|
|
956
764
|
}
|
|
957
765
|
// Step 2: Emit the event
|
|
958
|
-
console.
|
|
766
|
+
console.debug(LogSource.Events, 'CUSTOM_EVENTS', 'emiting event..: ');
|
|
959
767
|
EventUtils.emitEvent(evt, source, {payload, persistLevel, sender, ts});
|
|
960
768
|
// Because async gets evaluated in a different order when in an sdk
|
|
961
769
|
if (evt === 'name') {
|
|
962
|
-
|
|
963
|
-
if (eventTimeouts.has(sender)) {
|
|
964
|
-
clearTimeout(eventTimeouts.get(sender)!);
|
|
965
|
-
}
|
|
966
|
-
// 2. Create new timeout with tracking
|
|
967
|
-
const timeout = setTimeout(() => {
|
|
968
|
-
// 3. Guard against unmounted component
|
|
969
|
-
if (!isRTMMounted.current) {
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
770
|
+
setTimeout(() => {
|
|
972
771
|
EventUtils.emitEvent(evt, source, {
|
|
973
772
|
payload,
|
|
974
773
|
persistLevel,
|
|
975
774
|
sender,
|
|
976
775
|
ts,
|
|
977
776
|
});
|
|
978
|
-
// 4. Clean up after execution
|
|
979
|
-
eventTimeouts.delete(sender);
|
|
980
777
|
}, 200);
|
|
981
|
-
// 5. Track the timeout for cleanup
|
|
982
|
-
eventTimeouts.set(sender, timeout);
|
|
983
778
|
}
|
|
984
779
|
} catch (error) {
|
|
985
780
|
console.error(
|
|
986
781
|
LogSource.Events,
|
|
987
782
|
'CUSTOM_EVENTS',
|
|
988
783
|
'error while emiting event:',
|
|
989
|
-
|
|
784
|
+
error,
|
|
990
785
|
);
|
|
991
786
|
}
|
|
992
787
|
};
|
|
@@ -995,58 +790,45 @@ const RtmConfigure = (props: any) => {
|
|
|
995
790
|
if (!callActive) {
|
|
996
791
|
return;
|
|
997
792
|
}
|
|
998
|
-
// Destroy and clean up RTM state
|
|
999
793
|
await RTMEngine.getInstance().destroy();
|
|
1000
|
-
// Set the engine as null
|
|
1001
|
-
engine.current = null;
|
|
1002
794
|
logger.log(LogSource.AgoraSDK, 'API', 'RTM destroy done');
|
|
1003
795
|
if (isIOS() || isAndroid()) {
|
|
1004
796
|
EventUtils.clear();
|
|
1005
797
|
}
|
|
1006
798
|
setHasUserJoinedRTM(false);
|
|
1007
|
-
setIsInitialQueueCompleted(false);
|
|
1008
799
|
logger.debug(LogSource.AgoraSDK, 'Log', 'RTM cleanup done');
|
|
1009
800
|
};
|
|
1010
801
|
|
|
1011
802
|
useAsyncEffect(async () => {
|
|
1012
803
|
//waiting room attendee -> rtm login will happen on page load
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
) {
|
|
1035
|
-
await init(localUid);
|
|
1036
|
-
}
|
|
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();
|
|
1037
825
|
}
|
|
1038
|
-
} catch (error) {
|
|
1039
|
-
logger.error(LogSource.AgoraSDK, 'Log', 'RTM init failed', {error});
|
|
1040
826
|
}
|
|
1041
827
|
return async () => {
|
|
1042
|
-
logger.log(
|
|
1043
|
-
LogSource.AgoraSDK,
|
|
1044
|
-
'Log',
|
|
1045
|
-
'RTM unmounting calling end(destroy) ',
|
|
1046
|
-
);
|
|
1047
828
|
await end();
|
|
1048
829
|
};
|
|
1049
|
-
|
|
830
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
831
|
+
}, [rtcProps.channel, rtcProps.appId, callActive]);
|
|
1050
832
|
|
|
1051
833
|
return (
|
|
1052
834
|
<ChatContext.Provider
|