agora-appbuilder-core 4.1.9 → 4.1.10-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/template/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/bridge/rtc/webNg/RtcEngine.ts +2 -2
- package/template/bridge/rtm/web/index.ts +30 -0
- package/template/customization-api/typeDefinition.ts +1 -0
- package/template/defaultConfig.js +3 -2
- package/template/global.d.ts +1 -0
- package/template/src/AppRoutes.tsx +3 -3
- package/template/src/ai-agent/components/ControlButtons.tsx +1 -1
- package/template/src/assets/font-styles.css +36 -0
- package/template/src/assets/fonts/icomoon.ttf +0 -0
- package/template/src/assets/selection.json +1 -1
- package/template/src/atoms/CustomIcon.tsx +8 -0
- package/template/src/atoms/Dropdown.tsx +5 -0
- package/template/src/atoms/TertiaryButton.tsx +1 -1
- package/template/src/atoms/UserAvatar.tsx +1 -1
- package/template/src/components/ChatContext.ts +5 -3
- package/template/src/components/Controls.tsx +68 -22
- package/template/src/components/DeviceConfigure.tsx +1 -1
- package/template/src/components/EventsConfigure.tsx +22 -17
- package/template/src/components/Navbar.tsx +14 -11
- package/template/src/components/RTMConfigure.tsx +31 -1036
- package/template/src/components/UserGlobalPreferenceProvider.tsx +227 -0
- package/template/src/components/beauty-effect/useBeautyEffects.tsx +50 -13
- package/template/src/components/breakout-room/BreakoutRoomPanel.tsx +58 -0
- package/template/src/components/breakout-room/context/BreakoutRoomContext.tsx +2508 -0
- package/template/src/components/breakout-room/events/BreakoutRoomEventsConfigure.tsx +272 -0
- package/template/src/components/breakout-room/events/constants.ts +17 -0
- package/template/src/components/breakout-room/hoc/BreakoutRoomNameRenderer.tsx +68 -0
- package/template/src/components/breakout-room/hooks/useBreakoutRoomExit.ts +49 -0
- package/template/src/components/breakout-room/state/reducer.ts +522 -0
- package/template/src/components/breakout-room/state/types.ts +54 -0
- package/template/src/components/breakout-room/ui/BreakoutMeetingTitle.tsx +60 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomActionMenu.tsx +136 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomAnnouncementModal.tsx +135 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomGroupSettings.tsx +588 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomMainRoomUsers.tsx +142 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomMemberActionMenu.tsx +122 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomParticipants.tsx +124 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomRaiseHand.tsx +65 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomRenameModal.tsx +227 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomSettings.tsx +140 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomTransition.tsx +52 -0
- package/template/src/components/breakout-room/ui/BreakoutRoomView.tsx +193 -0
- package/template/src/components/breakout-room/ui/ExitBreakoutRoomIconButton.tsx +79 -0
- package/template/src/components/breakout-room/ui/ParticipantManualAssignmentModal.tsx +638 -0
- package/template/src/components/breakout-room/ui/SelectParticipantAssignmentStrategy.tsx +57 -0
- package/template/src/components/chat/chatConfigure.tsx +7 -1
- package/template/src/components/chat-messages/useChatMessages.tsx +43 -11
- package/template/src/components/common/Dividers.tsx +53 -0
- package/template/src/components/controls/toolbar-items/ExitBreakoutRoomToolbarItem.tsx +13 -0
- package/template/src/components/controls/useControlPermissionMatrix.tsx +32 -4
- package/template/src/components/participants/AllHostParticipants.tsx +10 -2
- package/template/src/components/participants/Participant.tsx +7 -1
- package/template/src/components/participants/UserActionMenuOptions.tsx +12 -2
- package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +12 -8
- package/template/src/components/precall/joinWaitingRoomBtn.tsx +14 -10
- package/template/src/components/raise-hand/RaiseHandButton.tsx +50 -0
- package/template/src/components/raise-hand/RaiseHandProvider.tsx +308 -0
- package/template/src/components/raise-hand/index.ts +14 -0
- package/template/src/components/recordings/RecordingsDateTable.tsx +3 -2
- package/template/src/components/room-info/useCurrentRoomInfo.tsx +42 -0
- package/template/src/components/room-info/useSetBreakoutRoomInfo.tsx +64 -0
- package/template/src/components/useUserPreference.tsx +39 -12
- package/template/src/components/virtual-background/useVB.tsx +18 -0
- package/template/src/components/whiteboard/WhiteboardConfigure.tsx +27 -0
- package/template/src/language/default-labels/videoCallScreenLabels.ts +7 -0
- package/template/src/logger/AppBuilderLogger.tsx +11 -3
- package/template/src/pages/VideoCall.tsx +171 -518
- package/template/src/pages/video-call/BreakoutVideoCall.tsx +213 -0
- package/template/src/pages/video-call/SidePanelHeader.tsx +17 -0
- package/template/src/pages/video-call/VideoCallContent.tsx +211 -0
- package/template/src/pages/video-call/VideoCallScreen.tsx +18 -0
- package/template/src/pages/video-call/VideoCallScreenWrapper.tsx +0 -1
- package/template/src/pages/video-call/VideoCallStateWrapper.tsx +495 -0
- package/template/src/rtm/RTMConfigureBreakoutRoomProvider.tsx +882 -0
- package/template/src/rtm/RTMConfigureMainRoomProvider.tsx +757 -0
- package/template/src/rtm/RTMCoreProvider.tsx +419 -0
- package/template/src/rtm/RTMEngine.ts +188 -60
- package/template/src/rtm/RTMGlobalStateProvider.tsx +706 -0
- package/template/src/rtm/RTMStatusBanner.tsx +99 -0
- package/template/src/rtm/constants.ts +12 -0
- package/template/src/rtm/hooks/useMainRoomUserDisplayName.ts +45 -0
- package/template/src/rtm/rtm-presence-utils.ts +344 -0
- package/template/src/rtm/utils.ts +68 -1
- package/template/src/rtm-events/constants.ts +40 -1
- package/template/src/rtm-events-api/Events.ts +62 -19
- package/template/src/subComponents/ChatBubble.tsx +3 -3
- package/template/src/subComponents/ChatContainer.tsx +19 -9
- package/template/src/subComponents/LocalAudioMute.tsx +2 -2
- package/template/src/subComponents/LocalVideoMute.tsx +2 -2
- package/template/src/subComponents/SidePanelEnum.tsx +1 -0
- package/template/src/subComponents/caption/useCaption.tsx +1 -1
- package/template/src/subComponents/chat/ChatAnnouncementView.tsx +65 -0
- package/template/src/subComponents/chat/ChatSendButton.tsx +1 -0
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +16 -0
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +1 -1
- package/template/src/subComponents/waiting-rooms/WaitingRoomControls.tsx +7 -4
- package/template/src/utils/useDebouncedCallback.tsx +20 -0
- package/template/src/utils/useEndCall.ts +0 -2
- package/template/src/utils/useMuteToggleLocal.ts +14 -10
- package/template/agora-rn-uikit/src/Reducer/Spotlight.ts +0 -11
- package/template/agora-rn-uikit/src/Reducer/UserBanned.ts +0 -11
|
@@ -2,1061 +2,56 @@
|
|
|
2
2
|
********************************************
|
|
3
3
|
Copyright © 2021 Agora Lab, Inc., all rights reserved.
|
|
4
4
|
AppBuilder and all associated components, source code, APIs, services, and documentation
|
|
5
|
-
(the
|
|
5
|
+
(the "Materials") are owned by Agora Lab, Inc. and its licensors. The Materials may not be
|
|
6
6
|
accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
|
|
7
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
|
|
8
|
+
any purpose competitive to Agora Lab, Inc.'s business) is strictly prohibited. For more
|
|
9
9
|
information visit https://appbuilder.agora.io.
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import 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';
|
|
26
|
-
import {
|
|
27
|
-
ContentInterface,
|
|
28
|
-
DispatchContext,
|
|
29
|
-
PropsContext,
|
|
30
|
-
UidType,
|
|
31
|
-
useLocalUid,
|
|
32
|
-
} from '../../agora-rn-uikit';
|
|
13
|
+
import React from 'react';
|
|
14
|
+
import {useLocalUid} from '../../agora-rn-uikit';
|
|
33
15
|
import ChatContext from './ChatContext';
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
getMessageTime,
|
|
43
|
-
get32BitUid,
|
|
44
|
-
} from '../rtm/utils';
|
|
45
|
-
import {EventUtils, EventsQueue} from '../rtm-events';
|
|
46
|
-
import {PersistanceLevel} from '../rtm-events-api';
|
|
47
|
-
import RTMEngine from '../rtm/RTMEngine';
|
|
48
|
-
import {filterObject} from '../utils';
|
|
49
|
-
import SDKEvents from '../utils/SdkEvents';
|
|
50
|
-
import isSDK from '../utils/isSDK';
|
|
51
|
-
import {useAsyncEffect} from '../utils/useAsyncEffect';
|
|
52
|
-
import {
|
|
53
|
-
WaitingRoomStatus,
|
|
54
|
-
useRoomInfo,
|
|
55
|
-
} from '../components/room-info/useRoomInfo';
|
|
56
|
-
import LocalEventEmitter, {
|
|
57
|
-
LocalEventsEnum,
|
|
58
|
-
} from '../rtm-events-api/LocalEvents';
|
|
59
|
-
import {controlMessageEnum} from '../components/ChatContext';
|
|
60
|
-
import {LogSource, logger} from '../logger/AppBuilderLogger';
|
|
61
|
-
import {RECORDING_BOT_UID} from '../utils/constants';
|
|
62
|
-
import {
|
|
63
|
-
nativeChannelTypeMapping,
|
|
64
|
-
nativeLinkStateMapping,
|
|
65
|
-
nativePresenceEventTypeMapping,
|
|
66
|
-
nativeStorageEventTypeMapping,
|
|
67
|
-
} from '../../bridge/rtm/web/Types';
|
|
68
|
-
|
|
69
|
-
export enum UserType {
|
|
70
|
-
ScreenShare = 'screenshare',
|
|
16
|
+
import {useRTMCore} from '../rtm/RTMCoreProvider';
|
|
17
|
+
import {useRTMConfigureMain} from '../rtm/RTMConfigureMainRoomProvider';
|
|
18
|
+
import {useRTMConfigureBreakout} from '../rtm/RTMConfigureBreakoutRoomProvider';
|
|
19
|
+
import {RTM_ROOMS} from '../rtm/constants';
|
|
20
|
+
|
|
21
|
+
interface Props {
|
|
22
|
+
room: RTM_ROOMS;
|
|
23
|
+
children: React.ReactNode;
|
|
71
24
|
}
|
|
72
25
|
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
const RtmConfigure = (props: any) => {
|
|
76
|
-
let engine = useRef<RTMClient>(null!);
|
|
77
|
-
const rtmInitTimstamp = new Date().getTime();
|
|
26
|
+
const RtmConfigure = (props: Props) => {
|
|
78
27
|
const localUid = useLocalUid();
|
|
79
|
-
const {
|
|
80
|
-
const {
|
|
81
|
-
const {dispatch} = useContext(DispatchContext);
|
|
82
|
-
const {defaultContent, activeUids} = useContent();
|
|
83
|
-
const {
|
|
84
|
-
waitingRoomStatus,
|
|
85
|
-
data: {isHost},
|
|
86
|
-
} = 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
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* inside event callback state won't have latest value.
|
|
96
|
-
* so creating ref to access the state
|
|
97
|
-
*/
|
|
98
|
-
const isHostRef = useRef({isHost: isHost});
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
isHostRef.current.isHost = isHost;
|
|
101
|
-
}, [isHost]);
|
|
102
|
-
|
|
103
|
-
const waitingRoomStatusRef = useRef({waitingRoomStatus: waitingRoomStatus});
|
|
104
|
-
useEffect(() => {
|
|
105
|
-
waitingRoomStatusRef.current.waitingRoomStatus = waitingRoomStatus;
|
|
106
|
-
}, [waitingRoomStatus]);
|
|
107
|
-
|
|
108
|
-
const activeUidsRef = useRef({activeUids: activeUids});
|
|
109
|
-
useEffect(() => {
|
|
110
|
-
activeUidsRef.current.activeUids = activeUids;
|
|
111
|
-
}, [activeUids]);
|
|
112
|
-
|
|
113
|
-
const defaultContentRef = useRef({defaultContent: defaultContent});
|
|
114
|
-
useEffect(() => {
|
|
115
|
-
defaultContentRef.current.defaultContent = defaultContent;
|
|
116
|
-
}, [defaultContent]);
|
|
117
|
-
|
|
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
|
-
}, []);
|
|
130
|
-
|
|
131
|
-
// Set online users
|
|
132
|
-
React.useEffect(() => {
|
|
133
|
-
setTotalOnlineUsers(
|
|
134
|
-
Object.keys(
|
|
135
|
-
filterObject(
|
|
136
|
-
defaultContent,
|
|
137
|
-
([k, v]) =>
|
|
138
|
-
v?.type === 'rtc' &&
|
|
139
|
-
!v.offline &&
|
|
140
|
-
activeUidsRef.current.activeUids.indexOf(v?.uid) !== -1,
|
|
141
|
-
),
|
|
142
|
-
).length,
|
|
143
|
-
);
|
|
144
|
-
}, [defaultContent]);
|
|
145
|
-
|
|
146
|
-
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()) {
|
|
150
|
-
const handBrowserClose = ev => {
|
|
151
|
-
ev.preventDefault();
|
|
152
|
-
return (ev.returnValue = 'Are you sure you want to exit?');
|
|
153
|
-
};
|
|
154
|
-
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
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
// Set up window listeners
|
|
168
|
-
window.addEventListener(
|
|
169
|
-
'beforeunload',
|
|
170
|
-
isWeb() && !isSDK() ? handBrowserClose : () => {},
|
|
171
|
-
);
|
|
172
|
-
|
|
173
|
-
window.addEventListener('pagehide', logoutRtm);
|
|
174
|
-
return () => {
|
|
175
|
-
// Remove listeners on unmount
|
|
176
|
-
window.removeEventListener(
|
|
177
|
-
'beforeunload',
|
|
178
|
-
isWeb() && !isSDK() ? handBrowserClose : () => {},
|
|
179
|
-
);
|
|
180
|
-
window.removeEventListener('pagehide', logoutRtm);
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
}, []);
|
|
184
|
-
|
|
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
|
-
}
|
|
28
|
+
const {room} = props;
|
|
29
|
+
const {client} = useRTMCore();
|
|
439
30
|
|
|
440
|
-
|
|
31
|
+
// Call hooks unconditionally, but only use data based on room type
|
|
32
|
+
let rtmMainData = null;
|
|
33
|
+
let rtmBreakoutData = null;
|
|
34
|
+
rtmMainData = useRTMConfigureMain();
|
|
35
|
+
rtmBreakoutData = useRTMConfigureBreakout();
|
|
441
36
|
|
|
442
|
-
|
|
37
|
+
const rtmData = room === RTM_ROOMS.MAIN ? rtmMainData : rtmBreakoutData;
|
|
443
38
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
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
|
-
const doLoginAndSetupRTM = async () => {
|
|
461
|
-
try {
|
|
462
|
-
logger.log(LogSource.AgoraSDK, 'API', 'RTM login starts');
|
|
463
|
-
await engine.current.login({
|
|
464
|
-
// @ts-ignore
|
|
465
|
-
token: rtcProps.rtm,
|
|
466
|
-
});
|
|
467
|
-
logger.log(LogSource.AgoraSDK, 'API', 'RTM login done');
|
|
468
|
-
timerValueRef.current = 5;
|
|
469
|
-
// waiting for login to be fully connected
|
|
470
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
471
|
-
await setAttribute();
|
|
472
|
-
} catch (error) {
|
|
473
|
-
logger.error(
|
|
474
|
-
LogSource.AgoraSDK,
|
|
475
|
-
'Log',
|
|
476
|
-
'RTM login failed..Trying again',
|
|
477
|
-
{error},
|
|
478
|
-
);
|
|
479
|
-
setTimeout(async () => {
|
|
480
|
-
// Cap the timer to prevent excessive delays (max 30 seconds)
|
|
481
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
482
|
-
doLoginAndSetupRTM();
|
|
483
|
-
}, timerValueRef.current * 1000);
|
|
484
|
-
}
|
|
485
|
-
};
|
|
486
|
-
|
|
487
|
-
const setAttribute = async () => {
|
|
488
|
-
const rtmAttributes = [
|
|
489
|
-
{key: 'screenUid', value: String(rtcProps.screenShareUid)},
|
|
490
|
-
{key: 'isHost', value: String(isHostRef.current.isHost)},
|
|
491
|
-
];
|
|
492
|
-
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);
|
|
500
|
-
logger.log(
|
|
501
|
-
LogSource.AgoraSDK,
|
|
502
|
-
'API',
|
|
503
|
-
'RTM setting local user attributes',
|
|
504
|
-
{
|
|
505
|
-
attr: rtmAttributes,
|
|
506
|
-
},
|
|
507
|
-
);
|
|
508
|
-
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
|
-
);
|
|
518
|
-
setHasUserJoinedRTM(true);
|
|
519
|
-
await runQueuedEvents();
|
|
520
|
-
setIsInitialQueueCompleted(true);
|
|
521
|
-
logger.log(
|
|
522
|
-
LogSource.AgoraSDK,
|
|
523
|
-
'Log',
|
|
524
|
-
'RTM queued events finished running',
|
|
525
|
-
{
|
|
526
|
-
attr: rtmAttributes,
|
|
527
|
-
},
|
|
528
|
-
);
|
|
529
|
-
} catch (error) {
|
|
530
|
-
logger.error(
|
|
531
|
-
LogSource.AgoraSDK,
|
|
532
|
-
'Log',
|
|
533
|
-
'RTM setAttribute failed..Trying again',
|
|
534
|
-
{error},
|
|
535
|
-
);
|
|
536
|
-
setTimeout(async () => {
|
|
537
|
-
// Cap the timer to prevent excessive delays (max 30 seconds)
|
|
538
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
539
|
-
setAttribute();
|
|
540
|
-
}, timerValueRef.current * 1000);
|
|
541
|
-
}
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
const subscribeChannel = async () => {
|
|
545
|
-
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', {
|
|
561
|
-
data: rtcProps.channel,
|
|
562
|
-
});
|
|
563
|
-
|
|
564
|
-
// Set channel ID AFTER successful subscribe (like v1.5x)
|
|
565
|
-
RTMEngine.getInstance().setChannelId(rtcProps.channel);
|
|
566
|
-
logger.log(
|
|
567
|
-
LogSource.AgoraSDK,
|
|
568
|
-
'API',
|
|
569
|
-
'RTM setChannelId as subscribe is successful',
|
|
570
|
-
rtcProps.channel,
|
|
571
|
-
);
|
|
572
|
-
|
|
573
|
-
logger.debug(
|
|
574
|
-
LogSource.SDK,
|
|
575
|
-
'Event',
|
|
576
|
-
'Emitting rtm joined',
|
|
577
|
-
rtcProps.channel,
|
|
578
|
-
);
|
|
579
|
-
// @ts-ignore
|
|
580
|
-
SDKEvents.emit('_rtm-joined', rtcProps.channel);
|
|
581
|
-
timerValueRef.current = 5;
|
|
582
|
-
await getMembers();
|
|
583
|
-
await readAllChannelAttributes();
|
|
584
|
-
logger.log(
|
|
585
|
-
LogSource.AgoraSDK,
|
|
586
|
-
'Log',
|
|
587
|
-
'RTM readAllChannelAttributes and getMembers done',
|
|
588
|
-
);
|
|
589
|
-
}
|
|
590
|
-
} catch (error) {
|
|
591
|
-
logger.error(
|
|
592
|
-
LogSource.AgoraSDK,
|
|
593
|
-
'Log',
|
|
594
|
-
'RTM subscribeChannel failed..Trying again',
|
|
595
|
-
{error},
|
|
596
|
-
);
|
|
597
|
-
setTimeout(async () => {
|
|
598
|
-
// Cap the timer to prevent excessive delays (max 30 seconds)
|
|
599
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
600
|
-
subscribeChannel();
|
|
601
|
-
}, timerValueRef.current * 1000);
|
|
602
|
-
}
|
|
603
|
-
};
|
|
604
|
-
|
|
605
|
-
const getMembers = async () => {
|
|
606
|
-
try {
|
|
607
|
-
logger.log(
|
|
608
|
-
LogSource.AgoraSDK,
|
|
609
|
-
'API',
|
|
610
|
-
'RTM presence.getOnlineUsers(getMembers) start',
|
|
611
|
-
);
|
|
612
|
-
await engine.current.presence
|
|
613
|
-
.getOnlineUsers(rtcProps.channel, 1)
|
|
614
|
-
.then(async (data: GetOnlineUsersResponse) => {
|
|
615
|
-
logger.log(
|
|
616
|
-
LogSource.AgoraSDK,
|
|
617
|
-
'API',
|
|
618
|
-
'RTM presence.getOnlineUsers data received',
|
|
619
|
-
data,
|
|
620
|
-
);
|
|
621
|
-
await Promise.all(
|
|
622
|
-
data.occupants?.map(async member => {
|
|
623
|
-
try {
|
|
624
|
-
const backoffAttributes =
|
|
625
|
-
await fetchUserAttributesWithBackoffRetry(member.userId);
|
|
626
|
-
|
|
627
|
-
await processUserUidAttributes(
|
|
628
|
-
backoffAttributes,
|
|
629
|
-
member.userId,
|
|
630
|
-
);
|
|
631
|
-
// setting screenshare data
|
|
632
|
-
// name of the screenUid, isActive: false, (when the user starts screensharing it becomes true)
|
|
633
|
-
// 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
|
|
658
|
-
}
|
|
659
|
-
});
|
|
660
|
-
} catch (e) {
|
|
661
|
-
logger.error(
|
|
662
|
-
LogSource.AgoraSDK,
|
|
663
|
-
'Log',
|
|
664
|
-
`RTM Could not retrieve name of ${member.userId}`,
|
|
665
|
-
{error: e},
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
}),
|
|
669
|
-
);
|
|
670
|
-
logger.debug(
|
|
671
|
-
LogSource.AgoraSDK,
|
|
672
|
-
'Log',
|
|
673
|
-
'RTM fetched all data and user attr...RTM init done',
|
|
674
|
-
);
|
|
675
|
-
});
|
|
676
|
-
timerValueRef.current = 5;
|
|
677
|
-
} catch (error) {
|
|
678
|
-
setTimeout(async () => {
|
|
679
|
-
// Cap the timer to prevent excessive delays (max 30 seconds)
|
|
680
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
681
|
-
await getMembers();
|
|
682
|
-
}, timerValueRef.current * 1000);
|
|
683
|
-
}
|
|
684
|
-
};
|
|
685
|
-
|
|
686
|
-
const readAllChannelAttributes = async () => {
|
|
687
|
-
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
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
logger.log(
|
|
719
|
-
LogSource.AgoraSDK,
|
|
720
|
-
'API',
|
|
721
|
-
'RTM storage.getChannelMetadata data received',
|
|
722
|
-
data,
|
|
723
|
-
);
|
|
724
|
-
});
|
|
725
|
-
timerValueRef.current = 5;
|
|
726
|
-
} catch (error) {
|
|
727
|
-
setTimeout(async () => {
|
|
728
|
-
// Cap the timer to prevent excessive delays (max 30 seconds)
|
|
729
|
-
timerValueRef.current = Math.min(timerValueRef.current * 2, 30);
|
|
730
|
-
await readAllChannelAttributes();
|
|
731
|
-
}, timerValueRef.current * 1000);
|
|
732
|
-
}
|
|
733
|
-
};
|
|
734
|
-
|
|
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
|
-
});
|
|
750
|
-
|
|
751
|
-
if (!attr || !attr.items) {
|
|
752
|
-
logger.log(
|
|
753
|
-
LogSource.AgoraSDK,
|
|
754
|
-
'API',
|
|
755
|
-
'RTM attributes for member not found',
|
|
756
|
-
);
|
|
757
|
-
throw attr;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
logger.log(
|
|
761
|
-
LogSource.AgoraSDK,
|
|
762
|
-
'API',
|
|
763
|
-
`RTM getUserMetadata for member ${userId} received`,
|
|
764
|
-
{attr},
|
|
765
|
-
);
|
|
766
|
-
|
|
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,
|
|
780
|
-
);
|
|
781
|
-
return true;
|
|
782
|
-
},
|
|
783
|
-
},
|
|
39
|
+
if (!rtmData) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`RTMConfigure: Invalid room prop '${room}' or missing context provider`,
|
|
784
42
|
);
|
|
785
|
-
}
|
|
786
|
-
|
|
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;
|
|
799
|
-
|
|
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
|
|
812
|
-
|
|
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);
|
|
820
|
-
}
|
|
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},
|
|
828
|
-
);
|
|
829
|
-
}
|
|
830
|
-
};
|
|
831
|
-
|
|
832
|
-
const updateRenderListState = (
|
|
833
|
-
uid: number,
|
|
834
|
-
data: Partial<ContentInterface>,
|
|
835
|
-
) => {
|
|
836
|
-
dispatch({type: 'UpdateRenderList', value: [uid, data]});
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
const runQueuedEvents = async () => {
|
|
840
|
-
try {
|
|
841
|
-
while (!EventsQueue.isEmpty()) {
|
|
842
|
-
const currEvt = EventsQueue.dequeue();
|
|
843
|
-
await eventDispatcher(currEvt.data, `${currEvt.uid}`, currEvt.ts);
|
|
844
|
-
}
|
|
845
|
-
} catch (error) {
|
|
846
|
-
logger.error(
|
|
847
|
-
LogSource.Events,
|
|
848
|
-
'CUSTOM_EVENTS',
|
|
849
|
-
'error while running queue events',
|
|
850
|
-
{error},
|
|
851
|
-
);
|
|
852
|
-
}
|
|
853
|
-
};
|
|
854
|
-
|
|
855
|
-
const eventDispatcher = async (
|
|
856
|
-
data: {
|
|
857
|
-
evt: string;
|
|
858
|
-
value: string;
|
|
859
|
-
feat?: string;
|
|
860
|
-
etyp?: string;
|
|
861
|
-
},
|
|
862
|
-
sender: string,
|
|
863
|
-
ts: number,
|
|
864
|
-
) => {
|
|
865
|
-
console.log(
|
|
866
|
-
LogSource.Events,
|
|
867
|
-
'CUSTOM_EVENTS',
|
|
868
|
-
'inside eventDispatcher ',
|
|
869
|
-
data,
|
|
870
|
-
);
|
|
871
|
-
|
|
872
|
-
let evt = '',
|
|
873
|
-
value = '';
|
|
874
|
-
|
|
875
|
-
if (data?.feat === 'WAITING_ROOM') {
|
|
876
|
-
if (data?.etyp === 'REQUEST') {
|
|
877
|
-
const outputData = {
|
|
878
|
-
evt: `${data.feat}_${data.etyp}`,
|
|
879
|
-
payload: JSON.stringify({
|
|
880
|
-
attendee_uid: data.data.data.attendee_uid,
|
|
881
|
-
attendee_screenshare_uid: data.data.data.attendee_screenshare_uid,
|
|
882
|
-
}),
|
|
883
|
-
persistLevel: 1,
|
|
884
|
-
source: 'core',
|
|
885
|
-
};
|
|
886
|
-
const formattedData = JSON.stringify(outputData);
|
|
887
|
-
evt = data.feat + '_' + data.etyp; //rename if client side RTM meessage is to be sent for approval
|
|
888
|
-
value = formattedData;
|
|
889
|
-
}
|
|
890
|
-
if (data?.etyp === 'RESPONSE') {
|
|
891
|
-
const outputData = {
|
|
892
|
-
evt: `${data.feat}_${data.etyp}`,
|
|
893
|
-
payload: JSON.stringify({
|
|
894
|
-
approved: data.data.data.approved,
|
|
895
|
-
channelName: data.data.data.channel_name,
|
|
896
|
-
mainUser: data.data.data.mainUser,
|
|
897
|
-
screenShare: data.data.data.screenShare,
|
|
898
|
-
whiteboard: data.data.data.whiteboard,
|
|
899
|
-
chat: data.data.data?.chat,
|
|
900
|
-
}),
|
|
901
|
-
persistLevel: 1,
|
|
902
|
-
source: 'core',
|
|
903
|
-
};
|
|
904
|
-
const formattedData = JSON.stringify(outputData);
|
|
905
|
-
evt = data.feat + '_' + data.etyp;
|
|
906
|
-
value = formattedData;
|
|
907
|
-
}
|
|
908
|
-
} else {
|
|
909
|
-
if (
|
|
910
|
-
$config.ENABLE_WAITING_ROOM &&
|
|
911
|
-
!isHostRef.current?.isHost &&
|
|
912
|
-
waitingRoomStatusRef.current?.waitingRoomStatus !==
|
|
913
|
-
WaitingRoomStatus.APPROVED
|
|
914
|
-
) {
|
|
915
|
-
if (
|
|
916
|
-
data.evt === controlMessageEnum.muteAudio ||
|
|
917
|
-
data.evt === controlMessageEnum.muteVideo
|
|
918
|
-
) {
|
|
919
|
-
return;
|
|
920
|
-
} else {
|
|
921
|
-
evt = data.evt;
|
|
922
|
-
value = data.value;
|
|
923
|
-
}
|
|
924
|
-
} else {
|
|
925
|
-
evt = data.evt;
|
|
926
|
-
value = data.value;
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
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;
|
|
944
|
-
// Step 1: Set local attributes
|
|
945
|
-
if (persistLevel === PersistanceLevel.Session) {
|
|
946
|
-
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
|
-
);
|
|
956
|
-
}
|
|
957
|
-
// Step 2: Emit the event
|
|
958
|
-
console.log(LogSource.Events, 'CUSTOM_EVENTS', 'emiting event..: ');
|
|
959
|
-
EventUtils.emitEvent(evt, source, {payload, persistLevel, sender, ts});
|
|
960
|
-
// Because async gets evaluated in a different order when in an sdk
|
|
961
|
-
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
|
-
}
|
|
972
|
-
EventUtils.emitEvent(evt, source, {
|
|
973
|
-
payload,
|
|
974
|
-
persistLevel,
|
|
975
|
-
sender,
|
|
976
|
-
ts,
|
|
977
|
-
});
|
|
978
|
-
// 4. Clean up after execution
|
|
979
|
-
eventTimeouts.delete(sender);
|
|
980
|
-
}, 200);
|
|
981
|
-
// 5. Track the timeout for cleanup
|
|
982
|
-
eventTimeouts.set(sender, timeout);
|
|
983
|
-
}
|
|
984
|
-
} catch (error) {
|
|
985
|
-
console.error(
|
|
986
|
-
LogSource.Events,
|
|
987
|
-
'CUSTOM_EVENTS',
|
|
988
|
-
'error while emiting event:',
|
|
989
|
-
{error},
|
|
990
|
-
);
|
|
991
|
-
}
|
|
992
|
-
};
|
|
993
|
-
|
|
994
|
-
const end = async () => {
|
|
995
|
-
if (!callActive) {
|
|
996
|
-
return;
|
|
997
|
-
}
|
|
998
|
-
// Destroy and clean up RTM state
|
|
999
|
-
await RTMEngine.getInstance().destroy();
|
|
1000
|
-
// Set the engine as null
|
|
1001
|
-
engine.current = null;
|
|
1002
|
-
logger.log(LogSource.AgoraSDK, 'API', 'RTM destroy done');
|
|
1003
|
-
if (isIOS() || isAndroid()) {
|
|
1004
|
-
EventUtils.clear();
|
|
1005
|
-
}
|
|
1006
|
-
setHasUserJoinedRTM(false);
|
|
1007
|
-
setIsInitialQueueCompleted(false);
|
|
1008
|
-
logger.debug(LogSource.AgoraSDK, 'Log', 'RTM cleanup done');
|
|
1009
|
-
};
|
|
1010
|
-
|
|
1011
|
-
useAsyncEffect(async () => {
|
|
1012
|
-
//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
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
} catch (error) {
|
|
1039
|
-
logger.error(LogSource.AgoraSDK, 'Log', 'RTM init failed', {error});
|
|
1040
|
-
}
|
|
1041
|
-
return async () => {
|
|
1042
|
-
logger.log(
|
|
1043
|
-
LogSource.AgoraSDK,
|
|
1044
|
-
'Log',
|
|
1045
|
-
'RTM unmounting calling end(destroy) ',
|
|
1046
|
-
);
|
|
1047
|
-
await end();
|
|
1048
|
-
};
|
|
1049
|
-
}, [rtcProps.channel, rtcProps.appId, callActive, localUid]);
|
|
43
|
+
}
|
|
1050
44
|
|
|
1051
45
|
return (
|
|
1052
46
|
<ChatContext.Provider
|
|
1053
47
|
value={{
|
|
1054
|
-
isInitialQueueCompleted,
|
|
1055
|
-
rtmInitTimstamp,
|
|
1056
|
-
hasUserJoinedRTM,
|
|
1057
|
-
engine:
|
|
48
|
+
isInitialQueueCompleted: rtmData.isInitialQueueCompleted,
|
|
49
|
+
rtmInitTimstamp: rtmData.rtmInitTimstamp,
|
|
50
|
+
hasUserJoinedRTM: rtmData.hasUserJoinedRTM,
|
|
51
|
+
engine: client,
|
|
1058
52
|
localUid: localUid,
|
|
1059
|
-
onlineUsersCount,
|
|
53
|
+
onlineUsersCount: rtmData.onlineUsersCount,
|
|
54
|
+
syncUserState: rtmData.syncUserState,
|
|
1060
55
|
}}>
|
|
1061
56
|
{props.children}
|
|
1062
57
|
</ChatContext.Provider>
|