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.
Files changed (58) hide show
  1. package/package.json +2 -2
  2. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -3
  3. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +1 -2
  4. package/template/agora-rn-uikit/src/Reducer/index.ts +0 -2
  5. package/template/agora-rn-uikit/src/Rtc/Join.tsx +11 -25
  6. package/template/agora-rn-uikit/src/RtcConfigure.tsx +1 -14
  7. package/template/agora-rn-uikit/src/Utils/isBotUser.ts +1 -1
  8. package/template/android/app/build.gradle +0 -7
  9. package/template/bridge/rtm/web/Types.ts +0 -183
  10. package/template/bridge/rtm/web/index.ts +491 -423
  11. package/template/defaultConfig.js +3 -3
  12. package/template/ios/Podfile +0 -41
  13. package/template/package.json +5 -5
  14. package/template/src/assets/font-styles.css +4 -0
  15. package/template/src/assets/fonts/icomoon.ttf +0 -0
  16. package/template/src/assets/selection.json +1 -1
  17. package/template/src/atoms/ActionMenu.tsx +93 -13
  18. package/template/src/atoms/CustomIcon.tsx +1 -0
  19. package/template/src/atoms/DropDownMulti.tsx +80 -29
  20. package/template/src/atoms/Input.tsx +2 -1
  21. package/template/src/components/Controls.tsx +148 -143
  22. package/template/src/components/EventsConfigure.tsx +152 -97
  23. package/template/src/components/RTMConfigure.tsx +426 -644
  24. package/template/src/components/precall/joinCallBtn.native.tsx +7 -2
  25. package/template/src/components/precall/joinCallBtn.tsx +7 -2
  26. package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +8 -3
  27. package/template/src/components/precall/joinWaitingRoomBtn.tsx +22 -4
  28. package/template/src/components/precall/textInput.tsx +45 -22
  29. package/template/src/components/precall/usePreCall.tsx +7 -0
  30. package/template/src/components/room-info/useRoomInfo.tsx +5 -0
  31. package/template/src/language/default-labels/videoCallScreenLabels.ts +27 -4
  32. package/template/src/pages/video-call/ActionSheetContent.tsx +77 -77
  33. package/template/src/pages/video-call/SidePanelHeader.tsx +81 -36
  34. package/template/src/rtm/RTMEngine.ts +33 -130
  35. package/template/src/rtm-events/constants.ts +6 -0
  36. package/template/src/rtm-events-api/Events.ts +30 -106
  37. package/template/src/subComponents/caption/Caption.tsx +48 -7
  38. package/template/src/subComponents/caption/CaptionContainer.tsx +324 -51
  39. package/template/src/subComponents/caption/CaptionIcon.tsx +35 -34
  40. package/template/src/subComponents/caption/CaptionText.tsx +103 -2
  41. package/template/src/subComponents/caption/LanguageSelectorPopup.tsx +179 -69
  42. package/template/src/subComponents/caption/Transcript.tsx +46 -11
  43. package/template/src/subComponents/caption/TranscriptIcon.tsx +27 -35
  44. package/template/src/subComponents/caption/TranscriptText.tsx +78 -3
  45. package/template/src/subComponents/caption/proto/ptoto.js +38 -4
  46. package/template/src/subComponents/caption/proto/test.proto +34 -19
  47. package/template/src/subComponents/caption/useCaption.tsx +753 -10
  48. package/template/src/subComponents/caption/useSTTAPI.tsx +118 -205
  49. package/template/src/subComponents/caption/useStreamMessageUtils.native.ts +152 -33
  50. package/template/src/subComponents/caption/useStreamMessageUtils.ts +165 -34
  51. package/template/src/subComponents/caption/utils.ts +171 -3
  52. package/template/src/utils/SdkEvents.ts +3 -0
  53. package/template/src/utils/useEndCall.ts +3 -5
  54. package/template/src/utils/useSpeechToText.ts +31 -20
  55. package/template/agora-rn-uikit/src/Reducer/Spotlight.ts +0 -11
  56. package/template/agora-rn-uikit/src/Reducer/UserBanned.ts +0 -11
  57. package/template/bridge/rtm/web/index-legacy.ts +0 -540
  58. 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 [hasUserJoinedRTM, setHasUserJoinedRTM] = useState<boolean>(false);
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
- const activeUidsRef = useRef({activeUids: activeUids});
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
- // Eventdispatcher timeout refs clean
119
- const isRTMMounted = useRef(true);
120
- useEffect(() => {
121
- return () => {
122
- isRTMMounted.current = false;
123
- // Clear all pending timeouts on unmount
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
- activeUidsRef.current.activeUids.indexOf(v?.uid) !== -1,
110
+ activeUids.indexOf(v?.uid) !== -1,
141
111
  ),
142
112
  ).length,
143
113
  );
144
114
  }, [defaultContent]);
145
115
 
146
116
  React.useEffect(() => {
147
- // If its not a convo ai project and
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
- try {
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
- // Set up window listeners
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
- // @ts-ignore
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
- // Cap the timer to prevent excessive delays (max 30 seconds)
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
- const data: Metadata = {
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 subscribeChannel();
510
- logger.log(
511
- LogSource.AgoraSDK,
512
- 'Log',
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
- // Cap the timer to prevent excessive delays (max 30 seconds)
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 subscribeChannel = async () => {
210
+ const joinChannel = async () => {
545
211
  try {
546
- if (RTMEngine.getInstance().channelUid === rtcProps.channel) {
547
- logger.debug(
548
- LogSource.AgoraSDK,
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 as subscribe is successful',
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
- timerValueRef.current = 5;
582
- await getMembers();
583
- await readAllChannelAttributes();
584
- logger.log(
231
+ } else {
232
+ logger.debug(
585
233
  LogSource.AgoraSDK,
586
234
  'Log',
587
- 'RTM readAllChannelAttributes and getMembers done',
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 subscribeChannel failed..Trying again',
595
- {error},
247
+ 'RTM joinChannel failed..Trying again',
596
248
  );
597
249
  setTimeout(async () => {
598
- // Cap the timer to prevent excessive delays (max 30 seconds)
599
- timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
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 presence.getOnlineUsers(getMembers) start',
268
+ 'RTM getChannelMembersByID(getMembers) start',
611
269
  );
612
- await engine.current.presence
613
- .getOnlineUsers(rtcProps.channel, 1)
614
- .then(async (data: GetOnlineUsersResponse) => {
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 presence.getOnlineUsers data received',
276
+ 'RTM getChannelMembersByID data received',
619
277
  data,
620
278
  );
621
279
  await Promise.all(
622
- data.occupants?.map(async member => {
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 backoffAttributes =
625
- await fetchUserAttributesWithBackoffRetry(member.userId);
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
- await processUserUidAttributes(
628
- backoffAttributes,
629
- member.userId,
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
- backoffAttributes?.items?.forEach(item => {
635
- try {
636
- if (hasJsonStructure(item.value as string)) {
637
- const data = {
638
- evt: item.key, // Use item.key instead of key
639
- value: item.value, // Use item.value instead of value
640
- };
641
- // TODOSUP: Add the data to queue, dont add same mulitple events, use set so as to not repeat events
642
- EventsQueue.enqueue({
643
- data: data,
644
- uid: member.userId,
645
- ts: timeNow(),
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
- `RTM Could not retrieve name of ${member.userId}`,
665
- {error: e},
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
- // Cap the timer to prevent excessive delays (max 30 seconds)
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.storage
689
- .getChannelMetadata(rtcProps.channel, 1)
690
- .then(async (data: GetChannelMetadataResponse) => {
691
- for (const item of data.items) {
692
- try {
693
- const {key, value, authorUserId, updateTs} = item;
694
- if (hasJsonStructure(value as string)) {
695
- const evtData = {
696
- evt: key,
697
- value,
698
- };
699
- // TODOSUP: Add the data to queue, dont add same mulitple events, use set so as to not repeat events
700
- EventsQueue.enqueue({
701
- data: evtData,
702
- uid: authorUserId,
703
- ts: updateTs,
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 storage.getChannelMetadata data received',
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
- // Cap the timer to prevent excessive delays (max 30 seconds)
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 fetchUserAttributesWithBackoffRetry = async (
736
- userId: string,
737
- ): Promise<GetUserMetadataResponse> => {
738
- return backOff(
739
- async () => {
740
- logger.log(
741
- LogSource.AgoraSDK,
742
- 'API',
743
- `RTM fetching getUserMetadata for member ${userId}`,
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
- if (!attr || !attr.items) {
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
- 'RTM attributes for member not found',
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
- logger.log(
761
- LogSource.AgoraSDK,
762
- 'API',
763
- `RTM getUserMetadata for member ${userId} received`,
764
- {attr},
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
- if (attr.items && attr.items.length > 0) {
768
- return attr;
769
- } else {
770
- throw attr;
771
- }
772
- },
773
- {
774
- retry: (e, idx) => {
775
- logger.debug(
776
- LogSource.AgoraSDK,
777
- 'Log',
778
- `RTM [retrying] Attempt ${idx}. Fetching ${userId}'s attributes`,
779
- e,
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
- return true;
782
- },
576
+ }
783
577
  },
784
578
  );
785
- };
786
579
 
787
- const processUserUidAttributes = async (
788
- attr: GetUserMetadataResponse,
789
- userId: string,
790
- ) => {
791
- try {
792
- console.log('[user attributes]:', {attr});
793
- const uid = parseInt(userId, 10);
794
- const screenUidItem = attr?.items?.find(item => item.key === 'screenUid');
795
- const isHostItem = attr?.items?.find(item => item.key === 'isHost');
796
- const screenUid = screenUidItem?.value
797
- ? parseInt(screenUidItem.value, 10)
798
- : undefined;
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
- //start - updating user data in rtc
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
- //start - updating screenshare data in rtc
814
- if (screenUid) {
815
- const screenShareUser = {
816
- type: UserType.ScreenShare,
817
- parentUid: uid,
818
- };
819
- updateRenderListState(screenUid, screenShareUser);
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
- //end - updating screenshare data in rtc
822
- } catch (e) {
823
- logger.error(
824
- LogSource.AgoraSDK,
825
- 'Event',
826
- `RTM Failed to process user data for ${userId}`,
827
- {error: e},
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
- const updateRenderListState = (
833
- uid: number,
834
- data: Partial<ContentInterface>,
835
- ) => {
836
- dispatch({type: 'UpdateRenderList', value: [uid, data]});
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, `${currEvt.uid}`, currEvt.ts);
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
- {error},
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.log(
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?.feat === 'WAITING_ROOM') {
876
- if (data?.etyp === 'REQUEST') {
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?.etyp === 'RESPONSE') {
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
- let parsedValue;
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
- const options: SetOrUpdateUserMetadataOptions = {
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.log(LogSource.Events, 'CUSTOM_EVENTS', 'emiting event..: ');
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
- // 1. Cancel existing timeout for this sender
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
- {error},
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
- try {
1014
- if ($config.ENABLE_WAITING_ROOM) {
1015
- //attendee
1016
- //for waiting room attendee rtm login will happen on mount
1017
- if (!isHost && !callActive) {
1018
- await init(localUid);
1019
- }
1020
- //host
1021
- if (
1022
- isHost &&
1023
- ($config.AUTO_CONNECT_RTM ||
1024
- (!$config.AUTO_CONNECT_RTM && callActive))
1025
- ) {
1026
- await init(localUid);
1027
- }
1028
- } else {
1029
- //non waiting room case
1030
- //host and attendee
1031
- if (
1032
- $config.AUTO_CONNECT_RTM ||
1033
- (!$config.AUTO_CONNECT_RTM && callActive)
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
- }, [rtcProps.channel, rtcProps.appId, callActive, localUid]);
830
+ // eslint-disable-next-line react-hooks/exhaustive-deps
831
+ }, [rtcProps.channel, rtcProps.appId, callActive]);
1050
832
 
1051
833
  return (
1052
834
  <ChatContext.Provider