agora-appbuilder-core 4.1.10-beta.1 → 4.1.11

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 (132) hide show
  1. package/package.json +2 -2
  2. package/template/agora-rn-uikit/src/Utils/isBotUser.ts +1 -1
  3. package/template/android/app/build.gradle +0 -7
  4. package/template/bridge/rtc/webNg/RtcEngine.ts +2 -2
  5. package/template/bridge/rtm/web/Types.ts +0 -183
  6. package/template/bridge/rtm/web/index.ts +488 -450
  7. package/template/customization-api/typeDefinition.ts +0 -1
  8. package/template/defaultConfig.js +3 -4
  9. package/template/global.d.ts +0 -1
  10. package/template/ios/Podfile +0 -41
  11. package/template/package.json +5 -5
  12. package/template/src/AppRoutes.tsx +3 -3
  13. package/template/src/ai-agent/components/ControlButtons.tsx +1 -1
  14. package/template/src/assets/font-styles.css +1 -33
  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 -8
  19. package/template/src/atoms/DropDownMulti.tsx +80 -29
  20. package/template/src/atoms/Dropdown.tsx +0 -5
  21. package/template/src/atoms/Input.tsx +2 -1
  22. package/template/src/atoms/TertiaryButton.tsx +1 -1
  23. package/template/src/atoms/UserAvatar.tsx +1 -1
  24. package/template/src/components/ChatContext.ts +3 -5
  25. package/template/src/components/Controls.tsx +167 -208
  26. package/template/src/components/DeviceConfigure.tsx +1 -1
  27. package/template/src/components/EventsConfigure.tsx +168 -118
  28. package/template/src/components/Navbar.tsx +11 -14
  29. package/template/src/components/RTMConfigure.tsx +819 -32
  30. package/template/src/components/beauty-effect/useBeautyEffects.tsx +13 -50
  31. package/template/src/components/chat/chatConfigure.tsx +1 -7
  32. package/template/src/components/chat-messages/useChatMessages.tsx +11 -43
  33. package/template/src/components/controls/useControlPermissionMatrix.tsx +4 -32
  34. package/template/src/components/participants/AllHostParticipants.tsx +2 -10
  35. package/template/src/components/participants/Participant.tsx +1 -7
  36. package/template/src/components/participants/UserActionMenuOptions.tsx +2 -12
  37. package/template/src/components/precall/joinCallBtn.native.tsx +7 -2
  38. package/template/src/components/precall/joinCallBtn.tsx +7 -2
  39. package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +16 -15
  40. package/template/src/components/precall/joinWaitingRoomBtn.tsx +31 -17
  41. package/template/src/components/precall/textInput.tsx +45 -22
  42. package/template/src/components/precall/usePreCall.tsx +7 -0
  43. package/template/src/components/recordings/RecordingsDateTable.tsx +2 -3
  44. package/template/src/components/room-info/useRoomInfo.tsx +5 -0
  45. package/template/src/components/useUserPreference.tsx +12 -39
  46. package/template/src/components/virtual-background/useVB.tsx +0 -18
  47. package/template/src/components/whiteboard/WhiteboardConfigure.tsx +0 -27
  48. package/template/src/language/default-labels/videoCallScreenLabels.ts +27 -11
  49. package/template/src/logger/AppBuilderLogger.tsx +3 -11
  50. package/template/src/pages/VideoCall.tsx +518 -171
  51. package/template/src/pages/video-call/ActionSheetContent.tsx +77 -77
  52. package/template/src/pages/video-call/SidePanelHeader.tsx +81 -53
  53. package/template/src/pages/video-call/VideoCallScreen.tsx +0 -18
  54. package/template/src/pages/video-call/VideoCallScreenWrapper.tsx +1 -0
  55. package/template/src/rtm/RTMEngine.ts +37 -262
  56. package/template/src/rtm/utils.ts +1 -68
  57. package/template/src/rtm-events/constants.ts +7 -40
  58. package/template/src/rtm-events-api/Events.ts +39 -158
  59. package/template/src/subComponents/ChatBubble.tsx +3 -3
  60. package/template/src/subComponents/ChatContainer.tsx +9 -19
  61. package/template/src/subComponents/LocalAudioMute.tsx +2 -2
  62. package/template/src/subComponents/LocalVideoMute.tsx +2 -2
  63. package/template/src/subComponents/SidePanelEnum.tsx +0 -1
  64. package/template/src/subComponents/caption/Caption.tsx +48 -7
  65. package/template/src/subComponents/caption/CaptionContainer.tsx +324 -51
  66. package/template/src/subComponents/caption/CaptionIcon.tsx +35 -34
  67. package/template/src/subComponents/caption/CaptionText.tsx +103 -2
  68. package/template/src/subComponents/caption/LanguageSelectorPopup.tsx +179 -69
  69. package/template/src/subComponents/caption/Transcript.tsx +46 -11
  70. package/template/src/subComponents/caption/TranscriptIcon.tsx +27 -35
  71. package/template/src/subComponents/caption/TranscriptText.tsx +78 -3
  72. package/template/src/subComponents/caption/proto/ptoto.js +38 -4
  73. package/template/src/subComponents/caption/proto/test.proto +34 -19
  74. package/template/src/subComponents/caption/useCaption.tsx +754 -11
  75. package/template/src/subComponents/caption/useSTTAPI.tsx +118 -205
  76. package/template/src/subComponents/caption/useStreamMessageUtils.native.ts +152 -33
  77. package/template/src/subComponents/caption/useStreamMessageUtils.ts +165 -34
  78. package/template/src/subComponents/caption/utils.ts +171 -3
  79. package/template/src/subComponents/chat/ChatSendButton.tsx +0 -1
  80. package/template/src/subComponents/screenshare/ScreenshareButton.tsx +0 -16
  81. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +1 -1
  82. package/template/src/subComponents/waiting-rooms/WaitingRoomControls.tsx +4 -7
  83. package/template/src/utils/SdkEvents.ts +3 -0
  84. package/template/src/utils/useEndCall.ts +4 -4
  85. package/template/src/utils/useMuteToggleLocal.ts +10 -14
  86. package/template/src/utils/useSpeechToText.ts +31 -20
  87. package/template/bridge/rtm/web/index-legacy.ts +0 -540
  88. package/template/src/components/RTMConfigure-legacy.tsx +0 -848
  89. package/template/src/components/UserGlobalPreferenceProvider.tsx +0 -227
  90. package/template/src/components/breakout-room/BreakoutRoomPanel.tsx +0 -58
  91. package/template/src/components/breakout-room/context/BreakoutRoomContext.tsx +0 -2508
  92. package/template/src/components/breakout-room/events/BreakoutRoomEventsConfigure.tsx +0 -272
  93. package/template/src/components/breakout-room/events/constants.ts +0 -17
  94. package/template/src/components/breakout-room/hoc/BreakoutRoomNameRenderer.tsx +0 -68
  95. package/template/src/components/breakout-room/hooks/useBreakoutRoomExit.ts +0 -49
  96. package/template/src/components/breakout-room/state/reducer.ts +0 -522
  97. package/template/src/components/breakout-room/state/types.ts +0 -54
  98. package/template/src/components/breakout-room/ui/BreakoutMeetingTitle.tsx +0 -60
  99. package/template/src/components/breakout-room/ui/BreakoutRoomActionMenu.tsx +0 -136
  100. package/template/src/components/breakout-room/ui/BreakoutRoomAnnouncementModal.tsx +0 -135
  101. package/template/src/components/breakout-room/ui/BreakoutRoomGroupSettings.tsx +0 -588
  102. package/template/src/components/breakout-room/ui/BreakoutRoomMainRoomUsers.tsx +0 -142
  103. package/template/src/components/breakout-room/ui/BreakoutRoomMemberActionMenu.tsx +0 -122
  104. package/template/src/components/breakout-room/ui/BreakoutRoomParticipants.tsx +0 -124
  105. package/template/src/components/breakout-room/ui/BreakoutRoomRaiseHand.tsx +0 -65
  106. package/template/src/components/breakout-room/ui/BreakoutRoomRenameModal.tsx +0 -227
  107. package/template/src/components/breakout-room/ui/BreakoutRoomSettings.tsx +0 -140
  108. package/template/src/components/breakout-room/ui/BreakoutRoomTransition.tsx +0 -52
  109. package/template/src/components/breakout-room/ui/BreakoutRoomView.tsx +0 -193
  110. package/template/src/components/breakout-room/ui/ExitBreakoutRoomIconButton.tsx +0 -79
  111. package/template/src/components/breakout-room/ui/ParticipantManualAssignmentModal.tsx +0 -638
  112. package/template/src/components/breakout-room/ui/SelectParticipantAssignmentStrategy.tsx +0 -57
  113. package/template/src/components/common/Dividers.tsx +0 -53
  114. package/template/src/components/controls/toolbar-items/ExitBreakoutRoomToolbarItem.tsx +0 -13
  115. package/template/src/components/raise-hand/RaiseHandButton.tsx +0 -50
  116. package/template/src/components/raise-hand/RaiseHandProvider.tsx +0 -308
  117. package/template/src/components/raise-hand/index.ts +0 -14
  118. package/template/src/components/room-info/useCurrentRoomInfo.tsx +0 -42
  119. package/template/src/components/room-info/useSetBreakoutRoomInfo.tsx +0 -64
  120. package/template/src/pages/video-call/BreakoutVideoCall.tsx +0 -213
  121. package/template/src/pages/video-call/VideoCallContent.tsx +0 -211
  122. package/template/src/pages/video-call/VideoCallStateWrapper.tsx +0 -495
  123. package/template/src/rtm/RTMConfigureBreakoutRoomProvider.tsx +0 -882
  124. package/template/src/rtm/RTMConfigureMainRoomProvider.tsx +0 -757
  125. package/template/src/rtm/RTMCoreProvider.tsx +0 -419
  126. package/template/src/rtm/RTMGlobalStateProvider.tsx +0 -706
  127. package/template/src/rtm/RTMStatusBanner.tsx +0 -99
  128. package/template/src/rtm/constants.ts +0 -12
  129. package/template/src/rtm/hooks/useMainRoomUserDisplayName.ts +0 -45
  130. package/template/src/rtm/rtm-presence-utils.ts +0 -344
  131. package/template/src/subComponents/chat/ChatAnnouncementView.tsx +0 -65
  132. package/template/src/utils/useDebouncedCallback.tsx +0 -20
@@ -1,706 +0,0 @@
1
- /*
2
- ********************************************
3
- Copyright © 2021 Agora Lab, Inc., all rights reserved.
4
- AppBuilder and all associated components, source code, APIs, services, and documentation
5
- (the "Materials") are owned by Agora Lab, Inc. and its licensors. The Materials may not be
6
- accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
7
- Use without a license or in violation of any license terms and conditions (including use for
8
- any purpose competitive to Agora Lab, Inc.'s business) is strictly prohibited. For more
9
- information visit https://appbuilder.agora.io.
10
- *********************************************
11
- */
12
-
13
- import React, {useState, useEffect, useRef} from 'react';
14
- import {
15
- type PresenceEvent,
16
- type StorageEvent,
17
- type SetOrUpdateUserMetadataOptions,
18
- type MessageEvent,
19
- } from 'agora-react-native-rtm';
20
- import {timeNow, hasJsonStructure} from '../rtm/utils';
21
- import {EventsQueue} from '../rtm-events';
22
- import {PersistanceLevel} from '../rtm-events-api';
23
- import RTMEngine from '../rtm/RTMEngine';
24
- import {useRTMCore} from './RTMCoreProvider';
25
- import {RtcPropsInterface, UidType} from '../../agora-rn-uikit';
26
- import {
27
- nativePresenceEventTypeMapping,
28
- nativeStorageEventTypeMapping,
29
- } from '../../bridge/rtm/web/Types';
30
- import {RTM_ROOMS} from './constants';
31
- import {
32
- fetchOnlineMembersWithRetries,
33
- fetchUserAttributesWithRetries,
34
- mapUserAttributesToState,
35
- fetchChannelAttributesWithRetries,
36
- processUserAttributeForQueue,
37
- } from './rtm-presence-utils';
38
- import {SDKEvents} from '../utils/eventEmitter';
39
-
40
- export enum UserType {
41
- ScreenShare = 'screenshare',
42
- }
43
-
44
- // RTM-specific user data interface
45
- export interface RTMUserData {
46
- uid?: UidType;
47
- screenUid?: number; // Screen sharing UID reference (stored in RTM user metadata)
48
- parentUid?: UidType; // Only available for screenshare
49
- type: 'rtc' | 'screenshare' | 'bot';
50
- name?: string; // User's display name (stored in RTM user metadata)
51
- offline: boolean; // User online/offline status (managed through RTM presence events)
52
- lastMessageTimeStamp: number; // Timestamp of last message (RTM message tracking)
53
- isInWaitingRoom?: boolean; // Waiting room status (RTM-based feature state)
54
- isHost: string; // Host privileges (stored in RTM user metadata as 'isHost')
55
- }
56
-
57
- interface RTMGlobalStateProviderProps {
58
- children: React.ReactNode;
59
- rtmLoginInfo: {
60
- uid: UidType;
61
- channel: string;
62
- };
63
- }
64
-
65
- // Context for message and storage handler registration
66
- const RTMGlobalStateContext = React.createContext<{
67
- mainRoomRTMUsers: {[uid: number]: RTMUserData};
68
- setMainRoomRTMUsers: React.Dispatch<
69
- React.SetStateAction<{[uid: number]: RTMUserData}>
70
- >;
71
- // Custom state for developer features (main room scope, cross-room accessible)
72
- customRTMMainRoomData: {[key: string]: any};
73
- setCustomRTMMainRoomData: React.Dispatch<
74
- React.SetStateAction<{[key: string]: any}>
75
- >;
76
- registerMainChannelMessageHandler: (
77
- handler: (message: MessageEvent) => void,
78
- ) => void;
79
- unregisterMainChannelMessageHandler: () => void;
80
- registerMainChannelStorageHandler: (
81
- handler: (storage: StorageEvent) => void,
82
- ) => void;
83
- unregisterMainChannelStorageHandler: () => void;
84
- }>({
85
- mainRoomRTMUsers: {},
86
- setMainRoomRTMUsers: () => {},
87
- customRTMMainRoomData: {},
88
- setCustomRTMMainRoomData: () => {},
89
- registerMainChannelMessageHandler: () => {},
90
- unregisterMainChannelMessageHandler: () => {},
91
- registerMainChannelStorageHandler: () => {},
92
- unregisterMainChannelStorageHandler: () => {},
93
- });
94
-
95
- const RTMGlobalStateProvider: React.FC<RTMGlobalStateProviderProps> = ({
96
- children,
97
- rtmLoginInfo,
98
- }) => {
99
- const mainChannelName = rtmLoginInfo.channel;
100
- const localUid = rtmLoginInfo.uid;
101
- const {client, isLoggedIn, registerCallbacks, unregisterCallbacks} =
102
- useRTMCore();
103
- // Main room RTM users (RTM-specific data only)
104
- const [mainRoomRTMUsers, setMainRoomRTMUsers] = useState<{
105
- [uid: number]: RTMUserData;
106
- }>({});
107
-
108
- // Custom state for developer features (main room scope, cross-room accessible)
109
- const [customRTMMainRoomData, setCustomRTMMainRoomData] = useState<{
110
- [key: string]: any;
111
- }>({});
112
- useEffect(() => {
113
- console.log('mainRoomRTMUsers user-attributes changed', mainRoomRTMUsers);
114
- }, [mainRoomRTMUsers]);
115
-
116
- // Timeout Refs
117
- const isRTMMounted = useRef(true);
118
- const hasInitRef = useRef(false);
119
-
120
- const subscribeTimerRef: any = useRef(5);
121
- const subscribeTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(
122
- null,
123
- );
124
-
125
- const channelAttributesTimerRef: any = useRef(5);
126
- const channelAttributesTimeoutRef = useRef<ReturnType<
127
- typeof setTimeout
128
- > | null>(null);
129
-
130
- const membersTimerRef: any = useRef(5);
131
- const membersTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
132
-
133
- // Message handler registration for main channel
134
- const messageHandlerRef = useRef<((message: MessageEvent) => void) | null>(
135
- null,
136
- );
137
- const registerMainChannelMessageHandler = (
138
- handler: (message: MessageEvent) => void,
139
- ) => {
140
- console.log(
141
- 'rudra-core-client: RTM registering main channel message handler',
142
- );
143
- if (messageHandlerRef.current) {
144
- console.warn(
145
- 'RTMGlobalStateProvider: Overwriting an existing main channel message handler!',
146
- );
147
- }
148
- messageHandlerRef.current = handler;
149
- };
150
- const unregisterMainChannelMessageHandler = () => {
151
- console.log(
152
- 'rudra-core-client: RTM unregistering main channel message handler',
153
- );
154
- messageHandlerRef.current = null;
155
- };
156
-
157
- // Storage handler registration for main channel
158
- const storageHandlerRef = useRef<((storage: StorageEvent) => void) | null>(
159
- null,
160
- );
161
- const registerMainChannelStorageHandler = (
162
- handler: (storage: StorageEvent) => void,
163
- ) => {
164
- console.log(
165
- 'rudra-core-client: RTM registering main channel storage handler',
166
- );
167
- if (storageHandlerRef.current) {
168
- console.warn(
169
- 'RTMGlobalStateProvider: Overwriting an existing main channel storage handler!',
170
- );
171
- }
172
- storageHandlerRef.current = handler;
173
- };
174
- const unregisterMainChannelStorageHandler = () => {
175
- console.log(
176
- 'rudra-core-client: RTM unregistering main channel storage handler',
177
- );
178
- storageHandlerRef.current = null;
179
- };
180
-
181
- // Update main rtm users state
182
- const updateMainRoomUser = (uid: number, data: RTMUserData) => {
183
- setMainRoomRTMUsers(prev => ({
184
- ...prev,
185
- [uid]: {...(prev[uid] || {}), ...data},
186
- }));
187
- };
188
-
189
- // Init cycle starts
190
- const init = async () => {
191
- try {
192
- console.log('rudra-core-client: Starting RTM init for main channel');
193
- await subscribeChannel();
194
- await getMembersWithAttributes();
195
- await getChannelAttributes();
196
- console.log('rudra-core-client: RTM init completed successfully');
197
- } catch (error) {
198
- console.log('rudra-core-client: RTM init failed', error);
199
- }
200
- };
201
-
202
- const subscribeChannel = async () => {
203
- try {
204
- if (RTMEngine.getInstance().allChannelIds.includes(mainChannelName)) {
205
- console.log('rudra- main channel already subsribed');
206
- } else {
207
- console.log('rudra- subscribing...');
208
- await client.subscribe(mainChannelName, {
209
- withMessage: true,
210
- withPresence: true,
211
- withMetadata: true,
212
- withLock: false,
213
- });
214
- console.log('rudra- subscribed main channel', mainChannelName);
215
-
216
- RTMEngine.getInstance().addChannel(RTM_ROOMS.MAIN, mainChannelName);
217
- RTMEngine.getInstance().setActiveChannelName(RTM_ROOMS.MAIN);
218
- SDKEvents.emit('_rtm-joined', mainChannelName);
219
-
220
- subscribeTimerRef.current = 5;
221
- // Clear any pending retry timeout since we succeeded
222
- if (subscribeTimeoutRef.current) {
223
- clearTimeout(subscribeTimeoutRef.current);
224
- subscribeTimeoutRef.current = null;
225
- }
226
- console.log('rudra- added to rtm engine');
227
- }
228
- } catch (error) {
229
- console.log(
230
- 'rudra-core-client: RTM subscribeChannel failed..Trying again',
231
- error,
232
- );
233
- subscribeTimeoutRef.current = setTimeout(async () => {
234
- // Cap the timer to prevent excessive delays (max 30 seconds)
235
- subscribeTimerRef.current = Math.min(subscribeTimerRef.current * 2, 30);
236
- subscribeChannel();
237
- }, subscribeTimerRef.current * 1000);
238
- }
239
- };
240
-
241
- const getMembersWithAttributes = async () => {
242
- try {
243
- console.log(
244
- 'rudra-core-client: RTM presence.getOnlineUsers(getMembers) start',
245
- );
246
- const {allMembers, totalOccupancy} = await fetchOnlineMembersWithRetries(
247
- client,
248
- mainChannelName,
249
- {
250
- onPage: async ({occupants, total, pageToken}) => {
251
- console.log(
252
- 'rudra-core-client: fetching user attributes for page: ',
253
- pageToken,
254
- occupants,
255
- );
256
- await Promise.all(
257
- occupants.map(async member => {
258
- try {
259
- const userAttributes = await fetchUserAttributesWithRetries(
260
- client,
261
- member.userId,
262
- {
263
- isMounted: () => isRTMMounted.current,
264
- // called later if name arrives
265
- onNameFound: async retryAttr =>
266
- mapUserAttributesToState(
267
- retryAttr,
268
- member.userId,
269
- updateMainRoomUser,
270
- ),
271
- },
272
- );
273
- console.log(
274
- `supriya rtm backoffAttributes user-attributes for ${member.userId}`,
275
- userAttributes,
276
- );
277
- mapUserAttributesToState(
278
- userAttributes,
279
- member.userId,
280
- updateMainRoomUser,
281
- );
282
-
283
- userAttributes?.items?.forEach(item => {
284
- processUserAttributeForQueue(
285
- item,
286
- member.userId,
287
- RTM_ROOMS.MAIN,
288
- (eventKey, value, userId) => {
289
- const data = {evt: eventKey, value};
290
- console.log(
291
- 'supriya-session-test adding to queue',
292
- data,
293
- );
294
- EventsQueue.enqueue({
295
- data,
296
- uid: userId,
297
- ts: timeNow(),
298
- });
299
- },
300
- );
301
- });
302
- } catch (e) {
303
- console.log(
304
- 'rudra-core-client: RTM Could not retrieve name of',
305
- member.userId,
306
- e,
307
- );
308
- }
309
- }),
310
- );
311
- },
312
- },
313
- );
314
-
315
- membersTimerRef.current = 5;
316
- // Clear any pending retry timeout since we succeeded
317
- if (membersTimeoutRef.current) {
318
- clearTimeout(membersTimeoutRef.current);
319
- membersTimeoutRef.current = null;
320
- }
321
- console.log(
322
- 'rudra-core-client: RTM fetched all data and user attr...RTM init done',
323
- );
324
- // });
325
- } catch (error) {
326
- membersTimeoutRef.current = setTimeout(async () => {
327
- // Cap the timer to prevent excessive delays (max 30 seconds)
328
- membersTimerRef.current = Math.min(membersTimerRef.current * 2, 30);
329
- await getMembersWithAttributes();
330
- }, membersTimerRef.current * 1000);
331
- }
332
- };
333
-
334
- const getChannelAttributes = async () => {
335
- try {
336
- await fetchChannelAttributesWithRetries(
337
- client,
338
- mainChannelName,
339
- eventData => EventsQueue.enqueue(eventData),
340
- );
341
- channelAttributesTimerRef.current = 5;
342
- // Clear any pending retry timeout since we succeeded
343
- if (channelAttributesTimeoutRef.current) {
344
- clearTimeout(channelAttributesTimeoutRef.current);
345
- channelAttributesTimeoutRef.current = null;
346
- }
347
- } catch (error) {
348
- console.log(
349
- 'rudra-core-client: RTM getchannelattributes failed..Trying again',
350
- error,
351
- );
352
- channelAttributesTimeoutRef.current = setTimeout(async () => {
353
- // Cap the timer to prevent excessive delays (max 30 seconds)
354
- channelAttributesTimerRef.current = Math.min(
355
- channelAttributesTimerRef.current * 2,
356
- 30,
357
- );
358
- getChannelAttributes();
359
- }, channelAttributesTimerRef.current * 1000);
360
- }
361
- };
362
-
363
- // Listeners
364
- const handleMainChannelPresenceEvent = async (presence: PresenceEvent) => {
365
- console.log(
366
- 'rudra-core-client: RTM presence event received for different channel',
367
- presence.channelName,
368
- 'expected:',
369
- mainChannelName,
370
- );
371
- if (presence.channelName !== mainChannelName) {
372
- console.log(
373
- 'rudra-core-client: RTM presence event received for different channel',
374
- presence.channelName,
375
- 'expected:',
376
- mainChannelName,
377
- );
378
- return;
379
- }
380
-
381
- // remoteJoinChannel
382
- if (presence.type === nativePresenceEventTypeMapping.REMOTE_JOIN) {
383
- console.log(
384
- 'rudra-core-client: RTM main room user joined',
385
- presence.publisher,
386
- );
387
- try {
388
- const userAttributes = await fetchUserAttributesWithRetries(
389
- client,
390
- presence.publisher,
391
- {
392
- isMounted: () => isRTMMounted.current,
393
- // This is called later if name arrives and hence we process that attribute
394
- onNameFound: retriedAttributes =>
395
- mapUserAttributesToState(
396
- retriedAttributes,
397
- presence.publisher,
398
- updateMainRoomUser,
399
- ),
400
- },
401
- );
402
- // This is called as soon as we receive any attributes
403
- mapUserAttributesToState(
404
- userAttributes,
405
- presence.publisher,
406
- updateMainRoomUser,
407
- );
408
- } catch (error) {
409
- console.log(
410
- 'rudra-core-client: RTM Failed to process user who joined main room',
411
- presence.publisher,
412
- error,
413
- );
414
- }
415
- }
416
-
417
- // remoteLeaveChannel
418
- if (presence.type === nativePresenceEventTypeMapping.REMOTE_LEAVE) {
419
- console.log(
420
- 'rudra-core-client: RTM main room user left',
421
- presence.publisher,
422
- );
423
- const uid = presence?.publisher
424
- ? parseInt(presence.publisher, 10)
425
- : undefined;
426
-
427
- if (!uid) {
428
- return;
429
- }
430
- SDKEvents.emit('_rtm-left', uid);
431
- // Mark user as offline (matching legacy channelMemberLeft behavior)
432
- setMainRoomRTMUsers(prev => {
433
- const updated = {...prev};
434
-
435
- if (updated[uid]) {
436
- updated[uid] = {
437
- ...updated[uid],
438
- offline: true,
439
- };
440
- }
441
-
442
- // Also mark screenshare as offline if exists
443
- // const screenUid = prev[uid]?.screenUid;
444
- // if (screenUid && updated[screenUid]) {
445
- // updated[screenUid] = {
446
- // ...updated[screenUid],
447
- // offline: true,
448
- // };
449
- // }
450
-
451
- console.log(
452
- 'rudra-core-client: RTM marked user as offline in main room',
453
- uid,
454
- );
455
- return updated;
456
- });
457
- }
458
- };
459
-
460
- const handleMainChannelStorageEvent = async (storage: StorageEvent) => {
461
- console.log(
462
- 'rudra-core-client: RTM global storage event received',
463
- storage,
464
- );
465
-
466
- // Only handle SET/UPDATE events for metadata persistence
467
- if (
468
- storage.eventType === nativeStorageEventTypeMapping.SET ||
469
- storage.eventType === nativeStorageEventTypeMapping.UPDATE
470
- ) {
471
- const storageTypeStr = storage.storageType === 1 ? 'user' : 'channel';
472
- const eventTypeStr = storage.eventType === 2 ? 'SET' : 'UPDATE';
473
- console.log(
474
- `rudra-core-client: RTM processing ${eventTypeStr} ${storageTypeStr} metadata`,
475
- );
476
-
477
- // // STEP 1: Handle metadata persistence FIRST (core RTM functionality)
478
- // try {
479
- // if (storage.data?.items && Array.isArray(storage.data.items)) {
480
- // for (const item of storage.data.items) {
481
- // try {
482
- // if (!item || !item.key) {
483
- // console.log(
484
- // 'rudra-core-client: RTM invalid storage item:',
485
- // item,
486
- // );
487
- // continue;
488
- // }
489
-
490
- // const {key, value, authorUserId, updateTs} = item;
491
-
492
- // // Parse the value to check persistLevel
493
- // let parsedValue;
494
- // try {
495
- // parsedValue =
496
- // typeof value === 'string' ? JSON.parse(value) : value;
497
- // } catch (parseError) {
498
- // console.log(
499
- // 'rudra-core-client: RTM failed to parse storage event value:',
500
- // parseError,
501
- // );
502
- // continue;
503
- // }
504
-
505
- // const {persistLevel} = parsedValue;
506
-
507
- // // Handle metadata persistence for Session level events
508
- // if (persistLevel === PersistanceLevel.Session) {
509
- // console.log(
510
- // 'rudra-core-client: RTM setting user metadata for key:',
511
- // key,
512
- // );
513
-
514
- // const rtmAttribute = {key: key, value: value};
515
- // const options: SetOrUpdateUserMetadataOptions = {
516
- // userId: `${localUid}`,
517
- // };
518
-
519
- // try {
520
- // await client.storage.setUserMetadata(
521
- // {items: [rtmAttribute]},
522
- // options,
523
- // );
524
- // console.log(
525
- // 'rudra-core-client: RTM successfully set user metadata for key:',
526
- // key,
527
- // );
528
- // } catch (setMetadataError) {
529
- // console.log(
530
- // 'rudra-core-client: RTM failed to set user metadata:',
531
- // setMetadataError,
532
- // );
533
- // }
534
- // }
535
- // } catch (itemError) {
536
- // console.log(
537
- // 'rudra-core-client: RTM failed to process storage item:',
538
- // item,
539
- // itemError,
540
- // );
541
- // }
542
- // }
543
- // }
544
- // } catch (error) {
545
- // console.log(
546
- // 'rudra-core-client: RTM error processing storage event:',
547
- // error,
548
- // );
549
- // }
550
-
551
- // STEP 2: Forward to application logic AFTER metadata persistence
552
- if (storageHandlerRef.current) {
553
- try {
554
- storageHandlerRef.current(storage);
555
- console.log(
556
- 'rudra-core-client: RTM forwarded storage event to registered handler',
557
- );
558
- } catch (error) {
559
- console.log(
560
- 'rudra-core-client: RTM error forwarding storage event:',
561
- error,
562
- );
563
- }
564
- }
565
- }
566
- };
567
-
568
- const handleMainChannelMessageEvent = async (message: MessageEvent) => {
569
- console.log(
570
- 'rudra-core-client: RTM main channel message event received',
571
- message,
572
- );
573
-
574
- // Check if this is a SESSION-level event and persist it
575
- try {
576
- if (hasJsonStructure(message.message)) {
577
- const parsed = JSON.parse(message.message);
578
- const {evt, value} = parsed;
579
-
580
- if (value && hasJsonStructure(value)) {
581
- const parsedValue = JSON.parse(value);
582
- const {persistLevel, _channelId} = parsedValue;
583
-
584
- // If this is a SESSION-level event from main channel, store it on local user's attributes
585
- if (
586
- persistLevel === PersistanceLevel.Session &&
587
- _channelId === mainChannelName
588
- ) {
589
- // const roomAwareKey = `${RTM_ROOMS.MAIN}__${evt}`;
590
- const rtmAttribute = {key: evt, value: value};
591
-
592
- const options: SetOrUpdateUserMetadataOptions = {
593
- userId: `${localUid}`,
594
- };
595
- await client.storage.setUserMetadata(
596
- {items: [rtmAttribute]},
597
- options,
598
- );
599
- // console.log(
600
- // 'rudra-core-client: Stored SESSION attribute cross-room',
601
- // roomAwareKey,
602
- // );
603
- }
604
- }
605
- }
606
- } catch (error) {
607
- console.log(
608
- 'rudra-core-client: RTM error storing session attribute:',
609
- error,
610
- );
611
- }
612
-
613
- // Forward to registered message handler (RTMConfigure)
614
- if (messageHandlerRef.current) {
615
- try {
616
- messageHandlerRef.current(message);
617
- console.log(
618
- 'rudra-core-client: RTM forwarded message event to registered handler',
619
- );
620
- } catch (error) {
621
- console.log(
622
- 'rudra-core-client: RTM error forwarding message event:',
623
- error,
624
- );
625
- }
626
- } else {
627
- console.log(
628
- 'rudra-core-client: RTM no message handler registered for main channel',
629
- );
630
- }
631
- };
632
-
633
- // Main initialization effect
634
- useEffect(() => {
635
- if (!client || !isLoggedIn || !mainChannelName || hasInitRef.current) {
636
- return;
637
- }
638
- hasInitRef.current = true;
639
- console.log('RTMGlobalStateProvider: Client ready, starting init');
640
- // Register presence, storage, and message event callbacks for main channel
641
- registerCallbacks(mainChannelName, {
642
- presence: handleMainChannelPresenceEvent,
643
- storage: handleMainChannelStorageEvent,
644
- message: handleMainChannelMessageEvent,
645
- });
646
- console.log(
647
- 'rudra-core-client: RTM registered presence, storage, and message callbacks for main channel',
648
- );
649
- init();
650
- return () => {
651
- console.log('rudra-core-client: main state cleanup');
652
- hasInitRef.current = false;
653
- isRTMMounted.current = false;
654
- if (mainChannelName) {
655
- unregisterCallbacks(mainChannelName);
656
- if (RTMEngine.getInstance().hasChannel(mainChannelName)) {
657
- client?.unsubscribe(mainChannelName).catch(() => {});
658
- RTMEngine.getInstance().removeChannel(RTM_ROOMS.MAIN);
659
- }
660
- }
661
-
662
- // Clear timer-based retry timeouts
663
- if (subscribeTimeoutRef.current) {
664
- clearTimeout(subscribeTimeoutRef.current);
665
- subscribeTimeoutRef.current = null;
666
- }
667
- if (membersTimeoutRef.current) {
668
- clearTimeout(membersTimeoutRef.current);
669
- membersTimeoutRef.current = null;
670
- }
671
- if (channelAttributesTimeoutRef.current) {
672
- clearTimeout(channelAttributesTimeoutRef.current);
673
- channelAttributesTimeoutRef.current = null;
674
- }
675
- };
676
- }, [client, isLoggedIn, mainChannelName]);
677
-
678
- return (
679
- <RTMGlobalStateContext.Provider
680
- value={{
681
- mainRoomRTMUsers,
682
- setMainRoomRTMUsers,
683
- customRTMMainRoomData,
684
- setCustomRTMMainRoomData,
685
- registerMainChannelMessageHandler,
686
- unregisterMainChannelMessageHandler,
687
- registerMainChannelStorageHandler,
688
- unregisterMainChannelStorageHandler,
689
- }}>
690
- {children}
691
- </RTMGlobalStateContext.Provider>
692
- );
693
- };
694
-
695
- // Hook to use main channel message registration
696
- export const useRTMGlobalState = () => {
697
- const context = React.useContext(RTMGlobalStateContext);
698
- if (!context) {
699
- throw new Error(
700
- 'useRTMMainChannel must be used within RTMGlobalStateProvider',
701
- );
702
- }
703
- return context;
704
- };
705
-
706
- export default RTMGlobalStateProvider;