agora-appbuilder-core 4.1.9 → 4.1.11-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +1 -3
- package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +1 -2
- package/template/agora-rn-uikit/src/Reducer/index.ts +0 -2
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +11 -25
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +1 -14
- package/template/agora-rn-uikit/src/Utils/isBotUser.ts +1 -1
- package/template/android/app/build.gradle +0 -7
- package/template/bridge/rtm/web/Types.ts +0 -183
- package/template/bridge/rtm/web/index.ts +491 -423
- package/template/defaultConfig.js +3 -3
- package/template/ios/Podfile +0 -41
- package/template/package.json +5 -5
- package/template/src/assets/font-styles.css +4 -0
- package/template/src/assets/fonts/icomoon.ttf +0 -0
- package/template/src/assets/selection.json +1 -1
- package/template/src/atoms/ActionMenu.tsx +93 -13
- package/template/src/atoms/CustomIcon.tsx +1 -0
- package/template/src/atoms/DropDownMulti.tsx +80 -29
- package/template/src/atoms/Input.tsx +2 -1
- package/template/src/components/Controls.tsx +148 -143
- package/template/src/components/EventsConfigure.tsx +152 -97
- package/template/src/components/RTMConfigure.tsx +426 -644
- package/template/src/components/precall/joinCallBtn.native.tsx +7 -2
- package/template/src/components/precall/joinCallBtn.tsx +7 -2
- package/template/src/components/precall/joinWaitingRoomBtn.native.tsx +8 -3
- package/template/src/components/precall/joinWaitingRoomBtn.tsx +22 -4
- package/template/src/components/precall/textInput.tsx +45 -22
- package/template/src/components/precall/usePreCall.tsx +7 -0
- package/template/src/components/room-info/useRoomInfo.tsx +5 -0
- package/template/src/language/default-labels/videoCallScreenLabels.ts +27 -4
- package/template/src/pages/video-call/ActionSheetContent.tsx +77 -77
- package/template/src/pages/video-call/SidePanelHeader.tsx +81 -36
- package/template/src/rtm/RTMEngine.ts +33 -130
- package/template/src/rtm-events/constants.ts +6 -0
- package/template/src/rtm-events-api/Events.ts +30 -106
- package/template/src/subComponents/caption/Caption.tsx +48 -7
- package/template/src/subComponents/caption/CaptionContainer.tsx +324 -51
- package/template/src/subComponents/caption/CaptionIcon.tsx +35 -34
- package/template/src/subComponents/caption/CaptionText.tsx +103 -2
- package/template/src/subComponents/caption/LanguageSelectorPopup.tsx +179 -69
- package/template/src/subComponents/caption/Transcript.tsx +46 -11
- package/template/src/subComponents/caption/TranscriptIcon.tsx +27 -35
- package/template/src/subComponents/caption/TranscriptText.tsx +78 -3
- package/template/src/subComponents/caption/proto/ptoto.js +38 -4
- package/template/src/subComponents/caption/proto/test.proto +34 -19
- package/template/src/subComponents/caption/useCaption.tsx +753 -10
- package/template/src/subComponents/caption/useSTTAPI.tsx +118 -205
- package/template/src/subComponents/caption/useStreamMessageUtils.native.ts +152 -33
- package/template/src/subComponents/caption/useStreamMessageUtils.ts +165 -34
- package/template/src/subComponents/caption/utils.ts +171 -3
- package/template/src/utils/SdkEvents.ts +3 -0
- package/template/src/utils/useEndCall.ts +3 -5
- package/template/src/utils/useSpeechToText.ts +31 -20
- package/template/agora-rn-uikit/src/Reducer/Spotlight.ts +0 -11
- package/template/agora-rn-uikit/src/Reducer/UserBanned.ts +0 -11
- package/template/bridge/rtm/web/index-legacy.ts +0 -540
- package/template/src/components/RTMConfigure-legacy.tsx +0 -848
|
@@ -1,472 +1,540 @@
|
|
|
1
|
+
/*
|
|
2
|
+
********************************************
|
|
3
|
+
Copyright © 2021 Agora Lab, Inc., all rights reserved.
|
|
4
|
+
AppBuilder and all associated components, source code, APIs, services, and documentation
|
|
5
|
+
(the “Materials”) are owned by Agora Lab, Inc. and its licensors. The Materials may not be
|
|
6
|
+
accessed, used, modified, or distributed for any purpose without a license from Agora Lab, Inc.
|
|
7
|
+
Use without a license or in violation of any license terms and conditions (including use for
|
|
8
|
+
any purpose competitive to Agora Lab, Inc.’s business) is strictly prohibited. For more
|
|
9
|
+
information visit https://appbuilder.agora.io.
|
|
10
|
+
*********************************************
|
|
11
|
+
*/
|
|
12
|
+
// @ts-nocheck
|
|
1
13
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
linkStatusReasonCodeMapping,
|
|
29
|
-
nativeChannelTypeMapping,
|
|
30
|
-
nativeLinkStateMapping,
|
|
31
|
-
nativeMessageEventTypeMapping,
|
|
32
|
-
nativePresenceEventTypeMapping,
|
|
33
|
-
nativeStorageEventTypeMapping,
|
|
34
|
-
nativeStorageTypeMapping,
|
|
35
|
-
webChannelTypeMapping,
|
|
36
|
-
} from './Types';
|
|
37
|
-
|
|
38
|
-
type CallbackType = (args?: any) => void;
|
|
39
|
-
|
|
40
|
-
// Conversion function
|
|
41
|
-
const convertWebToNativeMetadata = (webMetadata: any): NativeMetadata => {
|
|
42
|
-
// Convert object entries to MetadataItem array
|
|
43
|
-
const items: NativeMetadataItem[] =
|
|
44
|
-
Object.entries(webMetadata.metadata).map(
|
|
45
|
-
([key, metadataItem]: [string, MetaDataDetail]) => {
|
|
46
|
-
return {
|
|
47
|
-
key: key,
|
|
48
|
-
value: metadataItem.value,
|
|
49
|
-
revision: metadataItem.revision,
|
|
50
|
-
authorUserId: metadataItem.authorUid,
|
|
51
|
-
updateTs: metadataItem.updated,
|
|
52
|
-
};
|
|
53
|
-
},
|
|
54
|
-
) || [];
|
|
55
|
-
|
|
56
|
-
// Create native Metadata object
|
|
57
|
-
const nativeMetadata: NativeMetadata = {
|
|
58
|
-
majorRevision: webMetadata?.revision || -1, // Use first item's revision as major revision
|
|
59
|
-
items: items,
|
|
60
|
-
itemCount: webMetadata?.totalCount || 0,
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
return nativeMetadata;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export class RTMWebClient {
|
|
67
|
-
private client: RTMClient;
|
|
68
|
-
private appId: string;
|
|
69
|
-
private userId: string;
|
|
70
|
-
private eventsMap = new Map<keyof NativeRTMClientEventMap, CallbackType>([
|
|
71
|
-
['linkState', () => null],
|
|
72
|
-
['storage', () => null],
|
|
73
|
-
['presence', () => null],
|
|
74
|
-
['message', () => null],
|
|
14
|
+
ChannelAttributeOptions,
|
|
15
|
+
RtmAttribute,
|
|
16
|
+
RtmChannelAttribute,
|
|
17
|
+
Subscription,
|
|
18
|
+
} from 'agora-react-native-rtm/lib/typescript/src';
|
|
19
|
+
import {RtmClientEvents} from 'agora-react-native-rtm/lib/typescript/src/RtmEngine';
|
|
20
|
+
import AgoraRTM, {VERSION} from 'agora-rtm-sdk';
|
|
21
|
+
import RtmClient from 'agora-react-native-rtm';
|
|
22
|
+
import {LogSource, logger} from '../../../src/logger/AppBuilderLogger';
|
|
23
|
+
// export {RtmAttribute}
|
|
24
|
+
//
|
|
25
|
+
interface RtmAttributePlaceholder {}
|
|
26
|
+
export {RtmAttributePlaceholder as RtmAttribute};
|
|
27
|
+
|
|
28
|
+
type callbackType = (args?: any) => void;
|
|
29
|
+
|
|
30
|
+
export default class RtmEngine {
|
|
31
|
+
public appId: string;
|
|
32
|
+
public client: RtmClient;
|
|
33
|
+
public channelMap = new Map<string, any>([]);
|
|
34
|
+
public remoteInvititations = new Map<string, any>([]);
|
|
35
|
+
public localInvititations = new Map<string, any>([]);
|
|
36
|
+
public channelEventsMap = new Map<string, any>([
|
|
37
|
+
['channelMessageReceived', () => null],
|
|
38
|
+
['channelMemberJoined', () => null],
|
|
39
|
+
['channelMemberLeft', () => null],
|
|
75
40
|
]);
|
|
41
|
+
public clientEventsMap = new Map<string, any>([
|
|
42
|
+
['connectionStateChanged', () => null],
|
|
43
|
+
['messageReceived', () => null],
|
|
44
|
+
['remoteInvitationReceived', () => null],
|
|
45
|
+
['tokenExpired', () => null],
|
|
46
|
+
]);
|
|
47
|
+
public localInvitationEventsMap = new Map<string, any>([
|
|
48
|
+
['localInvitationAccepted', () => null],
|
|
49
|
+
['localInvitationCanceled', () => null],
|
|
50
|
+
['localInvitationFailure', () => null],
|
|
51
|
+
['localInvitationReceivedByPeer', () => null],
|
|
52
|
+
['localInvitationRefused', () => null],
|
|
53
|
+
]);
|
|
54
|
+
public remoteInvitationEventsMap = new Map<string, any>([
|
|
55
|
+
['remoteInvitationAccepted', () => null],
|
|
56
|
+
['remoteInvitationCanceled', () => null],
|
|
57
|
+
['remoteInvitationFailure', () => null],
|
|
58
|
+
['remoteInvitationRefused', () => null],
|
|
59
|
+
]);
|
|
60
|
+
constructor() {
|
|
61
|
+
this.appId = '';
|
|
62
|
+
logger.debug(LogSource.AgoraSDK, 'Log', 'Using RTM Bridge');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
on(event: any, listener: any) {
|
|
66
|
+
if (
|
|
67
|
+
event === 'channelMessageReceived' ||
|
|
68
|
+
event === 'channelMemberJoined' ||
|
|
69
|
+
event === 'channelMemberLeft'
|
|
70
|
+
) {
|
|
71
|
+
this.channelEventsMap.set(event, listener);
|
|
72
|
+
} else if (
|
|
73
|
+
event === 'connectionStateChanged' ||
|
|
74
|
+
event === 'messageReceived' ||
|
|
75
|
+
event === 'remoteInvitationReceived' ||
|
|
76
|
+
event === 'tokenExpired'
|
|
77
|
+
) {
|
|
78
|
+
this.clientEventsMap.set(event, listener);
|
|
79
|
+
} else if (
|
|
80
|
+
event === 'localInvitationAccepted' ||
|
|
81
|
+
event === 'localInvitationCanceled' ||
|
|
82
|
+
event === 'localInvitationFailure' ||
|
|
83
|
+
event === 'localInvitationReceivedByPeer' ||
|
|
84
|
+
event === 'localInvitationRefused'
|
|
85
|
+
) {
|
|
86
|
+
this.localInvitationEventsMap.set(event, listener);
|
|
87
|
+
} else if (
|
|
88
|
+
event === 'remoteInvitationAccepted' ||
|
|
89
|
+
event === 'remoteInvitationCanceled' ||
|
|
90
|
+
event === 'remoteInvitationFailure' ||
|
|
91
|
+
event === 'remoteInvitationRefused'
|
|
92
|
+
) {
|
|
93
|
+
this.remoteInvitationEventsMap.set(event, listener);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
76
96
|
|
|
77
|
-
|
|
78
|
-
this.appId =
|
|
79
|
-
this.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
97
|
+
createClient(APP_ID: string) {
|
|
98
|
+
this.appId = APP_ID;
|
|
99
|
+
this.client = AgoraRTM.createInstance(this.appId);
|
|
100
|
+
|
|
101
|
+
if ($config.GEO_FENCING) {
|
|
102
|
+
try {
|
|
103
|
+
//include area is comma seperated value
|
|
104
|
+
let includeArea = $config.GEO_FENCING_INCLUDE_AREA
|
|
105
|
+
? $config.GEO_FENCING_INCLUDE_AREA
|
|
106
|
+
: AREAS.GLOBAL;
|
|
107
|
+
|
|
108
|
+
//exclude area is single value
|
|
109
|
+
let excludeArea = $config.GEO_FENCING_EXCLUDE_AREA
|
|
110
|
+
? $config.GEO_FENCING_EXCLUDE_AREA
|
|
111
|
+
: '';
|
|
112
|
+
|
|
113
|
+
includeArea = includeArea?.split(',');
|
|
114
|
+
|
|
115
|
+
//pass excludedArea if only its provided
|
|
116
|
+
if (excludeArea) {
|
|
117
|
+
AgoraRTM.setArea({
|
|
118
|
+
areaCodes: includeArea,
|
|
119
|
+
excludedArea: excludeArea,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
//otherwise we can pass area directly
|
|
123
|
+
else {
|
|
124
|
+
AgoraRTM.setArea({areaCodes: includeArea});
|
|
125
|
+
}
|
|
126
|
+
} catch (setAeraError) {
|
|
127
|
+
console.log('error on RTM setArea', setAeraError);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
window.rtmClient = this.client;
|
|
132
|
+
|
|
133
|
+
this.client.on('ConnectionStateChanged', (state, reason) => {
|
|
134
|
+
this.clientEventsMap.get('connectionStateChanged')({state, reason});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
this.client.on('MessageFromPeer', (msg, uid, msgProps) => {
|
|
138
|
+
this.clientEventsMap.get('messageReceived')({
|
|
139
|
+
text: msg.text,
|
|
140
|
+
ts: msgProps.serverReceivedTs,
|
|
141
|
+
offline: msgProps.isOfflineMessage,
|
|
142
|
+
peerId: uid,
|
|
96
143
|
});
|
|
144
|
+
});
|
|
97
145
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
(this.eventsMap.get('storage') ?? (() => {}))(nativeStorageEvent);
|
|
146
|
+
this.client.on('RemoteInvitationReceived', (remoteInvitation: any) => {
|
|
147
|
+
this.remoteInvititations.set(remoteInvitation.callerId, remoteInvitation);
|
|
148
|
+
this.clientEventsMap.get('remoteInvitationReceived')({
|
|
149
|
+
callerId: remoteInvitation.callerId,
|
|
150
|
+
content: remoteInvitation.content,
|
|
151
|
+
state: remoteInvitation.state,
|
|
152
|
+
channelId: remoteInvitation.channelId,
|
|
153
|
+
response: remoteInvitation.response,
|
|
107
154
|
});
|
|
108
155
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
(this.eventsMap.get('presence') ?? (() => {}))(nativePresenceEvent);
|
|
156
|
+
remoteInvitation.on('RemoteInvitationAccepted', () => {
|
|
157
|
+
this.remoteInvitationEventsMap.get('RemoteInvitationAccepted')({
|
|
158
|
+
callerId: remoteInvitation.callerId,
|
|
159
|
+
content: remoteInvitation.content,
|
|
160
|
+
state: remoteInvitation.state,
|
|
161
|
+
channelId: remoteInvitation.channelId,
|
|
162
|
+
response: remoteInvitation.response,
|
|
163
|
+
});
|
|
118
164
|
});
|
|
119
165
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
166
|
+
remoteInvitation.on('RemoteInvitationCanceled', (content: string) => {
|
|
167
|
+
this.remoteInvitationEventsMap.get('remoteInvitationCanceled')({
|
|
168
|
+
callerId: remoteInvitation.callerId,
|
|
169
|
+
content: content,
|
|
170
|
+
state: remoteInvitation.state,
|
|
171
|
+
channelId: remoteInvitation.channelId,
|
|
172
|
+
response: remoteInvitation.response,
|
|
173
|
+
});
|
|
128
174
|
});
|
|
129
|
-
} catch (error) {
|
|
130
|
-
const contextError = new Error(
|
|
131
|
-
`Failed to create RTMWebClient for appId: ${this.appId}, userId: ${
|
|
132
|
-
this.userId
|
|
133
|
-
}. Error: ${error.message || error}`,
|
|
134
|
-
);
|
|
135
|
-
console.error('RTMWebClient constructor error:', contextError);
|
|
136
|
-
throw contextError;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
175
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (!data) {
|
|
149
|
-
throw new Error('setUserMetadata: data parameter is required');
|
|
150
|
-
}
|
|
151
|
-
if (!data.items || !Array.isArray(data.items)) {
|
|
152
|
-
throw new Error(
|
|
153
|
-
'setUserMetadata: data.items must be a non-empty array',
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
if (data.items.length === 0) {
|
|
157
|
-
throw new Error('setUserMetadata: data.items cannot be empty');
|
|
158
|
-
}
|
|
159
|
-
// 2. Make sure key is present as this is mandatory
|
|
160
|
-
// https://docs.agora.io/en/signaling/reference/api?platform=web#storagesetuserpropsag_platform
|
|
161
|
-
const validatedItems = data.items.map((item, index) => {
|
|
162
|
-
if (!item.key || typeof item.key !== 'string') {
|
|
163
|
-
throw new Error(
|
|
164
|
-
`setUserMetadata: item at index ${index} missing required 'key' property`,
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
return {
|
|
168
|
-
key: item.key,
|
|
169
|
-
value: item.value || '', // Default to empty string if not provided
|
|
170
|
-
revision: item.revision || -1, // Default to -1 if not provided
|
|
171
|
-
};
|
|
176
|
+
remoteInvitation.on('RemoteInvitationFailure', (reason: string) => {
|
|
177
|
+
this.remoteInvitationEventsMap.get('remoteInvitationFailure')({
|
|
178
|
+
callerId: remoteInvitation.callerId,
|
|
179
|
+
content: remoteInvitation.content,
|
|
180
|
+
state: remoteInvitation.state,
|
|
181
|
+
channelId: remoteInvitation.channelId,
|
|
182
|
+
response: remoteInvitation.response,
|
|
183
|
+
code: -1, //Web sends string, RN expect number but can't find enum
|
|
172
184
|
});
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
remoteInvitation.on('RemoteInvitationRefused', () => {
|
|
188
|
+
this.remoteInvitationEventsMap.get('remoteInvitationRefused')({
|
|
189
|
+
callerId: remoteInvitation.callerId,
|
|
190
|
+
content: remoteInvitation.content,
|
|
191
|
+
state: remoteInvitation.state,
|
|
192
|
+
channelId: remoteInvitation.channelId,
|
|
193
|
+
response: remoteInvitation.response,
|
|
177
194
|
});
|
|
178
|
-
}
|
|
195
|
+
});
|
|
196
|
+
});
|
|
179
197
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
this.client.on('TokenExpired', () => {
|
|
199
|
+
this.clientEventsMap.get('tokenExpired')({}); //RN expect evt: any
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async login(loginParam: {uid: string; token?: string}): Promise<any> {
|
|
204
|
+
return this.client.login(loginParam);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async logout(): Promise<any> {
|
|
208
|
+
return await this.client.logout();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async joinChannel(channelId: string): Promise<any> {
|
|
212
|
+
this.channelMap.set(channelId, this.client.createChannel(channelId));
|
|
213
|
+
this.channelMap
|
|
214
|
+
.get(channelId)
|
|
215
|
+
.on('ChannelMessage', (msg: {text: string}, uid: string, messagePros) => {
|
|
216
|
+
let text = msg.text;
|
|
217
|
+
let ts = messagePros.serverReceivedTs;
|
|
218
|
+
this.channelEventsMap.get('channelMessageReceived')({
|
|
219
|
+
uid,
|
|
220
|
+
channelId,
|
|
221
|
+
text,
|
|
222
|
+
ts,
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
this.channelMap.get(channelId).on('MemberJoined', (uid: string) => {
|
|
226
|
+
this.channelEventsMap.get('channelMemberJoined')({uid, channelId});
|
|
227
|
+
});
|
|
228
|
+
this.channelMap.get(channelId).on('MemberLeft', (uid: string) => {
|
|
229
|
+
console.log('Member Left', this.channelEventsMap);
|
|
230
|
+
this.channelEventsMap.get('channelMemberLeft')({uid});
|
|
231
|
+
});
|
|
232
|
+
this.channelMap
|
|
233
|
+
.get(channelId)
|
|
234
|
+
.on('AttributesUpdated', (attributes: RtmChannelAttribute) => {
|
|
235
|
+
/**
|
|
236
|
+
* a) Kindly note the below event listener 'channelAttributesUpdated' expects type
|
|
237
|
+
* RtmChannelAttribute[] (array of objects [{key: 'valueOfKey', value: 'valueOfValue}])
|
|
238
|
+
* whereas the above listener 'AttributesUpdated' receives attributes in object form
|
|
239
|
+
* {[valueOfKey]: valueOfValue} of type RtmChannelAttribute
|
|
240
|
+
* b) Hence in this bridge the data should be modified to keep in sync with both the
|
|
241
|
+
* listeners for web and listener for native
|
|
242
|
+
*/
|
|
198
243
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
* isHost: {authorUid: "", revision: 13483783553, updated: 0, value : "true"},
|
|
203
|
-
* screenUid: {…}}
|
|
204
|
-
* }
|
|
205
|
-
* timestamp: 0
|
|
206
|
-
* totalCount: 2
|
|
207
|
-
* userId: "xxx"
|
|
244
|
+
* 1. Loop through object
|
|
245
|
+
* 2. Create a object {key: "", value: ""} and push into array
|
|
246
|
+
* 3. Return the Array
|
|
208
247
|
*/
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
248
|
+
const channelAttributes = Object.keys(attributes).reduce((acc, key) => {
|
|
249
|
+
const {value, lastUpdateTs, lastUpdateUserId} = attributes[key];
|
|
250
|
+
acc.push({key, value, lastUpdateTs, lastUpdateUserId});
|
|
251
|
+
return acc;
|
|
252
|
+
}, []);
|
|
253
|
+
|
|
254
|
+
this.channelEventsMap.get('ChannelAttributesUpdated')(
|
|
255
|
+
channelAttributes,
|
|
214
256
|
);
|
|
215
|
-
|
|
216
|
-
items: [...items],
|
|
217
|
-
itemCount: webResponse.totalCount,
|
|
218
|
-
userId: webResponse.userId,
|
|
219
|
-
timestamp: webResponse.timestamp,
|
|
220
|
-
};
|
|
221
|
-
return nativeResponse;
|
|
222
|
-
},
|
|
257
|
+
});
|
|
223
258
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
)
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
259
|
+
return this.channelMap.get(channelId).join();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async leaveChannel(channelId: string): Promise<any> {
|
|
263
|
+
if (this.channelMap.get(channelId)) {
|
|
264
|
+
return this.channelMap.get(channelId).leave();
|
|
265
|
+
} else {
|
|
266
|
+
Promise.reject('Wrong channel');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async sendMessageByChannelId(channel: string, message: string): Promise<any> {
|
|
271
|
+
if (this.channelMap.get(channel)) {
|
|
272
|
+
return this.channelMap.get(channel).sendMessage({text: message});
|
|
273
|
+
} else {
|
|
274
|
+
console.log(this.channelMap, channel);
|
|
275
|
+
Promise.reject('Wrong channel');
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
destroyClient() {
|
|
280
|
+
console.log('Destroy called');
|
|
281
|
+
this.channelEventsMap.forEach((callback, event) => {
|
|
282
|
+
this.client.off(event, callback);
|
|
283
|
+
});
|
|
284
|
+
this.channelEventsMap.clear();
|
|
285
|
+
this.channelMap.clear();
|
|
286
|
+
this.clientEventsMap.clear();
|
|
287
|
+
this.remoteInvitationEventsMap.clear();
|
|
288
|
+
this.localInvitationEventsMap.clear();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async getChannelMembersBychannelId(channel: string) {
|
|
292
|
+
if (this.channelMap.get(channel)) {
|
|
293
|
+
let memberArray: Array<any> = [];
|
|
294
|
+
let currentChannel = this.channelMap.get(channel);
|
|
295
|
+
await currentChannel.getMembers().then((arr: Array<number>) => {
|
|
296
|
+
arr.map((elem: number) => {
|
|
297
|
+
memberArray.push({
|
|
298
|
+
channelId: channel,
|
|
299
|
+
uid: elem,
|
|
300
|
+
});
|
|
265
301
|
});
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
addTimeStamp: options?.addTimeStamp || true,
|
|
273
|
-
},
|
|
274
|
-
);
|
|
275
|
-
},
|
|
302
|
+
});
|
|
303
|
+
return {members: memberArray};
|
|
304
|
+
} else {
|
|
305
|
+
Promise.reject('Wrong channel');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
276
308
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
) => {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const items = Object.entries(webResponse.metadata).map(
|
|
289
|
-
([key, metadataItem]) => ({
|
|
290
|
-
key: key,
|
|
291
|
-
value: metadataItem.value,
|
|
292
|
-
}),
|
|
293
|
-
);
|
|
294
|
-
const nativeResponse: NativeGetChannelMetadataResponse = {
|
|
295
|
-
items: [...items],
|
|
296
|
-
itemCount: webResponse.totalCount,
|
|
297
|
-
timestamp: webResponse.timestamp,
|
|
298
|
-
channelName: webResponse.channelName,
|
|
299
|
-
channelType: nativeChannelTypeMapping.MESSAGE,
|
|
300
|
-
};
|
|
301
|
-
return nativeResponse;
|
|
302
|
-
} catch (error) {
|
|
303
|
-
const contextError = new Error(
|
|
304
|
-
`Failed to get channel metadata for channel '${channelName}' with type ${channelType}: ${
|
|
305
|
-
error.message || error
|
|
306
|
-
}`,
|
|
307
|
-
);
|
|
308
|
-
console.error('BRIDGE getChannelMetadata error:', contextError);
|
|
309
|
-
throw contextError;
|
|
310
|
-
}
|
|
311
|
-
},
|
|
312
|
-
};
|
|
309
|
+
async queryPeersOnlineStatus(uid: Array<String>) {
|
|
310
|
+
let peerArray: Array<any> = [];
|
|
311
|
+
await this.client.queryPeersOnlineStatus(uid).then(list => {
|
|
312
|
+
Object.entries(list).forEach(value => {
|
|
313
|
+
peerArray.push({
|
|
314
|
+
online: value[1],
|
|
315
|
+
uid: value[0],
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
});
|
|
319
|
+
return {items: peerArray};
|
|
313
320
|
}
|
|
314
321
|
|
|
315
|
-
|
|
316
|
-
return
|
|
317
|
-
|
|
318
|
-
channelName: string,
|
|
319
|
-
channelType: NativeRtmChannelType,
|
|
320
|
-
) => {
|
|
321
|
-
// Validate input parameters
|
|
322
|
-
if (
|
|
323
|
-
!channelName ||
|
|
324
|
-
typeof channelName !== 'string' ||
|
|
325
|
-
channelName.trim() === ''
|
|
326
|
-
) {
|
|
327
|
-
throw new Error(
|
|
328
|
-
'getOnlineUsers: channelName must be a non-empty string',
|
|
329
|
-
);
|
|
330
|
-
}
|
|
331
|
-
if (typeof channelType !== 'number') {
|
|
332
|
-
throw new Error('getOnlineUsers: channelType must be a number');
|
|
333
|
-
}
|
|
322
|
+
async renewToken(token: string) {
|
|
323
|
+
return this.client.renewToken(token);
|
|
324
|
+
}
|
|
334
325
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
);
|
|
348
|
-
console.error('BRIDGE presence error:', contextError);
|
|
349
|
-
throw contextError;
|
|
350
|
-
}
|
|
351
|
-
},
|
|
326
|
+
async getUserAttributesByUid(uid: string) {
|
|
327
|
+
let response = {};
|
|
328
|
+
await this.client
|
|
329
|
+
.getUserAttributes(uid)
|
|
330
|
+
.then((attributes: string) => {
|
|
331
|
+
response = {attributes, uid};
|
|
332
|
+
})
|
|
333
|
+
.catch((e: any) => {
|
|
334
|
+
Promise.reject(e);
|
|
335
|
+
});
|
|
336
|
+
return response;
|
|
337
|
+
}
|
|
352
338
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
339
|
+
async getChannelAttributes(channelId: string) {
|
|
340
|
+
let response = {};
|
|
341
|
+
await this.client
|
|
342
|
+
.getChannelAttributes(channelId)
|
|
343
|
+
.then((attributes: RtmChannelAttribute) => {
|
|
344
|
+
/**
|
|
345
|
+
* Here the attributes received are in the format {[valueOfKey]: valueOfValue} of type RtmChannelAttribute
|
|
346
|
+
* We need to convert it into (array of objects [{key: 'valueOfKey', value: 'valueOfValue}])
|
|
347
|
+
/**
|
|
348
|
+
* 1. Loop through object
|
|
349
|
+
* 2. Create a object {key: "", value: ""} and push into array
|
|
350
|
+
* 3. Return the Array
|
|
351
|
+
*/
|
|
352
|
+
const channelAttributes = Object.keys(attributes).reduce((acc, key) => {
|
|
353
|
+
const {value, lastUpdateTs, lastUpdateUserId} = attributes[key];
|
|
354
|
+
acc.push({key, value, lastUpdateTs, lastUpdateUserId});
|
|
355
|
+
return acc;
|
|
356
|
+
}, []);
|
|
357
|
+
response = channelAttributes;
|
|
358
|
+
})
|
|
359
|
+
.catch((e: any) => {
|
|
360
|
+
Promise.reject(e);
|
|
361
|
+
});
|
|
362
|
+
return response;
|
|
363
|
+
}
|
|
362
364
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
},
|
|
366
|
-
};
|
|
365
|
+
async removeAllLocalUserAttributes() {
|
|
366
|
+
return this.client.clearLocalUserAttributes();
|
|
367
367
|
}
|
|
368
368
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
listener: (event: any) => void,
|
|
372
|
-
) {
|
|
373
|
-
if (this.client) {
|
|
374
|
-
// Simply replace the handler in our map - web client listeners are fixed in constructor
|
|
375
|
-
this.eventsMap.set(event, listener as CallbackType);
|
|
376
|
-
}
|
|
369
|
+
async removeLocalUserAttributesByKeys(keys: string[]) {
|
|
370
|
+
return this.client.deleteLocalUserAttributesByKeys(keys);
|
|
377
371
|
}
|
|
378
372
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
}
|
|
388
|
-
this.eventsMap.set(event, () => null); // reset to no-op
|
|
389
|
-
}
|
|
373
|
+
async replaceLocalUserAttributes(attributes: string[]) {
|
|
374
|
+
let formattedAttributes: any = {};
|
|
375
|
+
attributes.map(attribute => {
|
|
376
|
+
let key = Object.values(attribute)[0];
|
|
377
|
+
let value = Object.values(attribute)[1];
|
|
378
|
+
formattedAttributes[key] = value;
|
|
379
|
+
});
|
|
380
|
+
return this.client.setLocalUserAttributes({...formattedAttributes});
|
|
390
381
|
}
|
|
391
382
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
383
|
+
async setLocalUserAttributes(attributes: string[]) {
|
|
384
|
+
let formattedAttributes: any = {};
|
|
385
|
+
attributes.map(attribute => {
|
|
386
|
+
let key = Object.values(attribute)[0];
|
|
387
|
+
let value = Object.values(attribute)[1];
|
|
388
|
+
formattedAttributes[key] = value;
|
|
389
|
+
// console.log('!!!!formattedAttributes', formattedAttributes, key, value);
|
|
390
|
+
});
|
|
391
|
+
return this.client.setLocalUserAttributes({...formattedAttributes});
|
|
398
392
|
}
|
|
399
393
|
|
|
400
|
-
async
|
|
401
|
-
|
|
394
|
+
async addOrUpdateLocalUserAttributes(attributes: RtmAttribute[]) {
|
|
395
|
+
let formattedAttributes: any = {};
|
|
396
|
+
attributes.map(attribute => {
|
|
397
|
+
let key = Object.values(attribute)[0];
|
|
398
|
+
let value = Object.values(attribute)[1];
|
|
399
|
+
formattedAttributes[key] = value;
|
|
400
|
+
});
|
|
401
|
+
return this.client.addOrUpdateLocalUserAttributes({...formattedAttributes});
|
|
402
402
|
}
|
|
403
403
|
|
|
404
|
-
async
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
404
|
+
async addOrUpdateChannelAttributes(
|
|
405
|
+
channelId: string,
|
|
406
|
+
attributes: RtmChannelAttribute[],
|
|
407
|
+
option: ChannelAttributeOptions,
|
|
408
|
+
): Promise<void> {
|
|
409
|
+
let formattedAttributes: any = {};
|
|
410
|
+
attributes.map(attribute => {
|
|
411
|
+
let key = Object.values(attribute)[0];
|
|
412
|
+
let value = Object.values(attribute)[1];
|
|
413
|
+
formattedAttributes[key] = value;
|
|
414
|
+
});
|
|
415
|
+
return this.client.addOrUpdateChannelAttributes(
|
|
416
|
+
channelId,
|
|
417
|
+
{...formattedAttributes},
|
|
418
|
+
option,
|
|
419
|
+
);
|
|
413
420
|
}
|
|
414
421
|
|
|
415
|
-
async
|
|
416
|
-
|
|
422
|
+
async sendLocalInvitation(invitationProps: any) {
|
|
423
|
+
let invite = this.client.createLocalInvitation(invitationProps.uid);
|
|
424
|
+
this.localInvititations.set(invitationProps.uid, invite);
|
|
425
|
+
invite.content = invitationProps.content;
|
|
426
|
+
|
|
427
|
+
invite.on('LocalInvitationAccepted', (response: string) => {
|
|
428
|
+
this.localInvitationEventsMap.get('localInvitationAccepted')({
|
|
429
|
+
calleeId: invite.calleeId,
|
|
430
|
+
content: invite.content,
|
|
431
|
+
state: invite.state,
|
|
432
|
+
channelId: invite.channelId,
|
|
433
|
+
response,
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
invite.on('LocalInvitationCanceled', () => {
|
|
438
|
+
this.localInvitationEventsMap.get('localInvitationCanceled')({
|
|
439
|
+
calleeId: invite.calleeId,
|
|
440
|
+
content: invite.content,
|
|
441
|
+
state: invite.state,
|
|
442
|
+
channelId: invite.channelId,
|
|
443
|
+
response: invite.response,
|
|
444
|
+
});
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
invite.on('LocalInvitationFailure', (reason: string) => {
|
|
448
|
+
this.localInvitationEventsMap.get('localInvitationFailure')({
|
|
449
|
+
calleeId: invite.calleeId,
|
|
450
|
+
content: invite.content,
|
|
451
|
+
state: invite.state,
|
|
452
|
+
channelId: invite.channelId,
|
|
453
|
+
response: invite.response,
|
|
454
|
+
code: -1, //Web sends string, RN expect number but can't find enum
|
|
455
|
+
});
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
invite.on('LocalInvitationReceivedByPeer', () => {
|
|
459
|
+
this.localInvitationEventsMap.get('localInvitationReceivedByPeer')({
|
|
460
|
+
calleeId: invite.calleeId,
|
|
461
|
+
content: invite.content,
|
|
462
|
+
state: invite.state,
|
|
463
|
+
channelId: invite.channelId,
|
|
464
|
+
response: invite.response,
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
invite.on('LocalInvitationRefused', (response: string) => {
|
|
469
|
+
this.localInvitationEventsMap.get('localInvitationRefused')({
|
|
470
|
+
calleeId: invite.calleeId,
|
|
471
|
+
content: invite.content,
|
|
472
|
+
state: invite.state,
|
|
473
|
+
channelId: invite.channelId,
|
|
474
|
+
response: response,
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
return invite.send();
|
|
417
478
|
}
|
|
418
479
|
|
|
419
|
-
async
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
) {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
throw new Error('publish: channelName must be a non-empty string');
|
|
431
|
-
}
|
|
432
|
-
if (typeof message !== 'string') {
|
|
433
|
-
throw new Error('publish: message must be a string');
|
|
434
|
-
}
|
|
480
|
+
async sendMessageToPeer(AgoraPeerMessage: {
|
|
481
|
+
peerId: string;
|
|
482
|
+
offline: boolean;
|
|
483
|
+
text: string;
|
|
484
|
+
}) {
|
|
485
|
+
return this.client.sendMessageToPeer(
|
|
486
|
+
{text: AgoraPeerMessage.text},
|
|
487
|
+
AgoraPeerMessage.peerId,
|
|
488
|
+
);
|
|
489
|
+
//check promise result
|
|
490
|
+
}
|
|
435
491
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
492
|
+
async acceptRemoteInvitation(remoteInvitationProps: {
|
|
493
|
+
uid: string;
|
|
494
|
+
response?: string;
|
|
495
|
+
channelId: string;
|
|
496
|
+
}) {
|
|
497
|
+
let invite = this.remoteInvititations.get(remoteInvitationProps.uid);
|
|
498
|
+
// console.log(invite);
|
|
499
|
+
// console.log(this.remoteInvititations);
|
|
500
|
+
// console.log(remoteInvitationProps.uid);
|
|
501
|
+
return invite.accept();
|
|
443
502
|
}
|
|
444
503
|
|
|
445
|
-
async
|
|
446
|
-
|
|
504
|
+
async refuseRemoteInvitation(remoteInvitationProps: {
|
|
505
|
+
uid: string;
|
|
506
|
+
response?: string;
|
|
507
|
+
channelId: string;
|
|
508
|
+
}) {
|
|
509
|
+
return this.remoteInvititations.get(remoteInvitationProps.uid).refuse();
|
|
447
510
|
}
|
|
448
511
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
return this.client.removeAllListeners();
|
|
512
|
+
async cancelLocalInvitation(LocalInvitationProps: {
|
|
513
|
+
uid: string;
|
|
514
|
+
content?: string;
|
|
515
|
+
channelId?: string;
|
|
516
|
+
}) {
|
|
517
|
+
console.log(this.localInvititations.get(LocalInvitationProps.uid));
|
|
518
|
+
return this.localInvititations.get(LocalInvitationProps.uid).cancel();
|
|
457
519
|
}
|
|
458
|
-
}
|
|
459
520
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
521
|
+
getSdkVersion(callback: (version: string) => void) {
|
|
522
|
+
callback(VERSION);
|
|
523
|
+
}
|
|
463
524
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
525
|
+
addListener<EventType extends keyof RtmClientEvents>(
|
|
526
|
+
event: EventType,
|
|
527
|
+
listener: RtmClientEvents[EventType],
|
|
528
|
+
): Subscription {
|
|
529
|
+
if (event === 'ChannelAttributesUpdated') {
|
|
530
|
+
this.channelEventsMap.set(event, listener as callbackType);
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
remove: () => {
|
|
534
|
+
console.log(
|
|
535
|
+
'Use destroy method to remove all the event listeners from the RtcEngine instead.',
|
|
536
|
+
);
|
|
537
|
+
},
|
|
538
|
+
};
|
|
467
539
|
}
|
|
468
540
|
}
|
|
469
|
-
// Factory function to create RTM client
|
|
470
|
-
export function createAgoraRtmClient(config: RtmConfig): RTMWebClient {
|
|
471
|
-
return new RTMWebClient(config.appId, config.userId);
|
|
472
|
-
}
|