agora-appbuilder-core 2.0.1 → 2.0.3-rc2
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/Readme.md +2 -1
- package/package.json +1 -1
- package/template/_package-lock.json +8853 -8806
- package/template/agora-rn-uikit/.git/index +0 -0
- package/template/agora-rn-uikit/.git/logs/HEAD +2 -2
- package/template/agora-rn-uikit/.git/logs/refs/heads/ab-dev-auto +1 -1
- package/template/agora-rn-uikit/.git/logs/refs/heads/master +1 -1
- package/template/agora-rn-uikit/.git/logs/refs/remotes/origin/HEAD +1 -1
- package/template/agora-rn-uikit/.git/objects/pack/pack-2a0122bf5a3199f941e5a52535f43881623f752c.idx +0 -0
- package/template/agora-rn-uikit/.git/objects/pack/{pack-f379286d0537eb68377220b4929979324b8d5d1c.pack → pack-2a0122bf5a3199f941e5a52535f43881623f752c.pack} +0 -0
- package/template/agora-rn-uikit/.git/packed-refs +4 -2
- package/template/agora-rn-uikit/.git/refs/heads/ab-dev-auto +1 -1
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +21 -0
- package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +22 -14
- package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +17 -13
- package/template/agora-rn-uikit/src/Controls/types.ts +4 -0
- package/template/agora-rn-uikit/src/Rtc/Create.tsx +117 -19
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +24 -13
- package/template/{src/utils/isSafariBrowser.tsx → agora-rn-uikit/src/Utils/isSafariBrowser.ts} +3 -0
- package/template/{src → agora-rn-uikit/src}/hooks/useImageDelay.tsx +5 -2
- package/template/agora-rn-uikit/src/index.ts +2 -0
- package/template/bridge/rtc/webNg/RtcEngine.ts +73 -70
- package/template/bridge/rtc/webNg/Types.ts +59 -5
- package/template/bridge/rtm/web/Types.ts +13 -0
- package/template/bridge/rtm/web/index.ts +78 -1
- package/template/global.d.ts +2 -0
- package/template/package-lock.json +8853 -8806
- package/template/package.json +3 -4
- package/template/react-native-toast-message/src/components/base/styles.js +4 -2
- package/template/src/assets/icons.ts +41 -28
- package/template/src/components/Chat.tsx +70 -184
- package/template/src/components/ChatContext.ts +13 -2
- package/template/src/components/Controls.native.tsx +37 -76
- package/template/src/components/Controls.tsx +50 -158
- package/template/src/components/DeviceConfigure.native.tsx +5 -1
- package/template/src/components/DeviceConfigure.tsx +38 -20
- package/template/src/components/Navbar.tsx +185 -226
- package/template/src/components/ParticipantsView.tsx +176 -184
- package/template/src/components/Precall.native.tsx +83 -69
- package/template/src/components/Precall.tsx +174 -191
- package/template/src/components/RTMConfigure.tsx +264 -78
- package/template/src/components/SettingsView.tsx +9 -19
- package/template/src/components/livestream/LiveStreamContext.tsx +411 -0
- package/template/src/components/livestream/Types.ts +69 -0
- package/template/src/components/livestream/index.ts +9 -0
- package/template/src/components/livestream/views/LiveStreamControls.tsx +27 -0
- package/template/src/components/participants/AllAudienceParticipants.tsx +53 -0
- package/template/src/components/participants/AllHostParticipants.tsx +65 -0
- package/template/src/components/participants/MeParticipant.tsx +37 -0
- package/template/src/components/participants/ParticipantName.tsx +47 -0
- package/template/src/components/participants/ParticipantSectionTitle.tsx +29 -0
- package/template/src/components/participants/RemoteParticipants.tsx +69 -0
- package/template/src/components/participants/ScreenshareParticipants.tsx +28 -0
- package/template/src/components/participants/context/ParticipantContext.tsx +97 -0
- package/template/src/components/styles.ts +13 -0
- package/template/src/pages/Create.tsx +25 -14
- package/template/src/pages/VideoCall.tsx +197 -159
- package/template/src/subComponents/ChatBubble.tsx +4 -1
- package/template/src/subComponents/ChatContainer.tsx +44 -20
- package/template/src/subComponents/ChatInput.tsx +4 -12
- package/template/src/subComponents/Checkbox.native.tsx +6 -5
- package/template/src/subComponents/Checkbox.tsx +1 -0
- package/template/src/subComponents/Recording.tsx +23 -9
- package/template/src/subComponents/RemoteVideoMute.tsx +2 -3
- package/template/src/subComponents/SelectDevice.tsx +70 -35
- package/template/src/subComponents/chat/ChatParticipants.tsx +121 -0
- package/template/src/subComponents/livestream/ApprovedLiveStreamControlsView.tsx +23 -0
- package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +70 -0
- package/template/src/subComponents/livestream/controls/LocalRaiseHand.tsx +57 -0
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +24 -0
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +38 -0
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +37 -0
- package/template/src/subComponents/livestream/index.ts +18 -0
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +80 -0
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +24 -0
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +200 -0
- package/template/src/subComponents/screenshare/ScreenshareContext.tsx +21 -0
- package/template/src/utils/index.tsx +48 -0
- package/template/agora-rn-uikit/.git/objects/pack/pack-f379286d0537eb68377220b4929979324b8d5d1c.idx +0 -0
|
@@ -10,8 +10,11 @@
|
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
import React, {useState, useContext, useEffect, useRef} from 'react';
|
|
13
|
-
import RtmEngine
|
|
14
|
-
|
|
13
|
+
import RtmEngine, {
|
|
14
|
+
RtmChannelAttribute,
|
|
15
|
+
RtmAttribute,
|
|
16
|
+
} from 'agora-react-native-rtm';
|
|
17
|
+
import {ClientRole, PropsContext} from '../../agora-rn-uikit';
|
|
15
18
|
import ChatContext, {controlMessageEnum} from './ChatContext';
|
|
16
19
|
import {RtcContext} from '../../agora-rn-uikit';
|
|
17
20
|
import {
|
|
@@ -19,10 +22,12 @@ import {
|
|
|
19
22
|
messageChannelType,
|
|
20
23
|
messageSourceType,
|
|
21
24
|
messageActionType,
|
|
25
|
+
attrRequestTypes,
|
|
22
26
|
} from './ChatContext';
|
|
23
27
|
import {Platform} from 'react-native';
|
|
24
28
|
import {backOff} from 'exponential-backoff';
|
|
25
29
|
import events from './RTMEvents';
|
|
30
|
+
import {filterObject} from '../utils';
|
|
26
31
|
|
|
27
32
|
export enum UserType {
|
|
28
33
|
Normal,
|
|
@@ -52,6 +57,23 @@ const parsePayload = (data: string) => {
|
|
|
52
57
|
return JSON.parse(data);
|
|
53
58
|
};
|
|
54
59
|
|
|
60
|
+
function hasJsonStructure(str: string) {
|
|
61
|
+
if (typeof str !== 'string') return false;
|
|
62
|
+
try {
|
|
63
|
+
const result = JSON.parse(str);
|
|
64
|
+
const type = Object.prototype.toString.call(result);
|
|
65
|
+
return type === '[object Object]' || type === '[object Array]';
|
|
66
|
+
} catch (err) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function safeJsonParse(str: string) {
|
|
71
|
+
try {
|
|
72
|
+
return [null, JSON.parse(str)];
|
|
73
|
+
} catch (err) {
|
|
74
|
+
return [err];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
55
77
|
const timeNow = () => new Date().getTime();
|
|
56
78
|
|
|
57
79
|
const RtmConfigure = (props: any) => {
|
|
@@ -62,10 +84,36 @@ const RtmConfigure = (props: any) => {
|
|
|
62
84
|
const [privateMessageStore, setPrivateMessageStore] = useState({});
|
|
63
85
|
const [login, setLogin] = useState<boolean>(false);
|
|
64
86
|
const [userList, setUserList] = useState<{[key: string]: any}>({});
|
|
87
|
+
const [onlineUsersCount, setTotalOnlineUsers] = useState<number>(0);
|
|
88
|
+
|
|
65
89
|
let engine = useRef<RtmEngine>(null!);
|
|
66
90
|
let localUid = useRef<string>('');
|
|
67
91
|
const timerValueRef: any = useRef(5);
|
|
68
92
|
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
const handBrowserClose = () => {
|
|
95
|
+
engine.current.leaveChannel(rtcProps.channel);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if (Platform.OS !== 'web') return;
|
|
99
|
+
window.addEventListener('beforeunload', handBrowserClose);
|
|
100
|
+
// cleanup this component
|
|
101
|
+
return () => {
|
|
102
|
+
window.removeEventListener('beforeunload', handBrowserClose);
|
|
103
|
+
};
|
|
104
|
+
}, []);
|
|
105
|
+
|
|
106
|
+
React.useEffect(() => {
|
|
107
|
+
setTotalOnlineUsers(
|
|
108
|
+
Object.keys(
|
|
109
|
+
filterObject(
|
|
110
|
+
userList,
|
|
111
|
+
([k, v]) => v?.type === UserType.Normal && !v.offline,
|
|
112
|
+
),
|
|
113
|
+
).length,
|
|
114
|
+
);
|
|
115
|
+
}, [userList]);
|
|
116
|
+
|
|
69
117
|
const addMessageToStore = (uid: string, msg: {body: string; ts: string}) => {
|
|
70
118
|
setMessageStore((m: messageStoreInterface[]) => {
|
|
71
119
|
return [...m, {ts: msg.ts, uid: uid, msg: msg.body}];
|
|
@@ -96,118 +144,136 @@ const RtmConfigure = (props: any) => {
|
|
|
96
144
|
return {...newState};
|
|
97
145
|
});
|
|
98
146
|
};
|
|
99
|
-
|
|
147
|
+
|
|
100
148
|
const doLoginAndSetupRTM = async () => {
|
|
101
149
|
try {
|
|
102
150
|
await engine.current.login({
|
|
103
151
|
uid: localUid.current,
|
|
104
152
|
token: rtcProps.rtm,
|
|
105
153
|
});
|
|
106
|
-
timerValueRef.current = 5
|
|
107
|
-
setAttribute();
|
|
154
|
+
timerValueRef.current = 5;
|
|
155
|
+
setAttribute();
|
|
108
156
|
} catch (error) {
|
|
109
|
-
setTimeout(
|
|
157
|
+
setTimeout(async () => {
|
|
110
158
|
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
111
159
|
doLoginAndSetupRTM();
|
|
112
|
-
}, timerValueRef.current * 1000
|
|
160
|
+
}, timerValueRef.current * 1000);
|
|
113
161
|
}
|
|
114
|
-
}
|
|
162
|
+
};
|
|
115
163
|
|
|
116
|
-
const setAttribute = async () => {
|
|
164
|
+
const setAttribute = async () => {
|
|
117
165
|
try {
|
|
118
166
|
await engine.current.setLocalUserAttributes([
|
|
119
167
|
{key: 'name', value: name || 'User'},
|
|
120
168
|
{key: 'screenUid', value: String(rtcProps.screenShareUid)},
|
|
169
|
+
{key: 'role', value: String(rtcProps?.role)},
|
|
170
|
+
{key: 'requests', value: attrRequestTypes.none}, // stores Uid who have raised a request
|
|
121
171
|
]);
|
|
122
|
-
timerValueRef.current = 5
|
|
123
|
-
joinChannel()
|
|
172
|
+
timerValueRef.current = 5;
|
|
173
|
+
joinChannel();
|
|
124
174
|
} catch (error) {
|
|
125
|
-
setTimeout(
|
|
175
|
+
setTimeout(async () => {
|
|
126
176
|
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
127
177
|
setAttribute();
|
|
128
|
-
}, timerValueRef.current * 1000
|
|
178
|
+
}, timerValueRef.current * 1000);
|
|
129
179
|
}
|
|
130
|
-
}
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const addOrUpdateLocalUserAttributes = async (attributes: RtmAttribute[]) => {
|
|
183
|
+
try {
|
|
184
|
+
await engine.current.addOrUpdateLocalUserAttributes(attributes);
|
|
185
|
+
} catch (error) {
|
|
186
|
+
console.log('error while local user addOrUpdateAttributes: ', error);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
131
189
|
|
|
132
190
|
const joinChannel = async () => {
|
|
133
191
|
try {
|
|
134
|
-
await engine.current.joinChannel(rtcProps.channel);
|
|
135
|
-
timerValueRef.current = 5
|
|
136
|
-
getMembers()
|
|
192
|
+
await engine.current.joinChannel(rtcProps.channel);
|
|
193
|
+
timerValueRef.current = 5;
|
|
194
|
+
getMembers();
|
|
137
195
|
} catch (error) {
|
|
138
|
-
setTimeout(
|
|
196
|
+
setTimeout(async () => {
|
|
139
197
|
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
140
198
|
joinChannel();
|
|
141
|
-
}, timerValueRef.current * 1000
|
|
142
|
-
}
|
|
143
|
-
}
|
|
199
|
+
}, timerValueRef.current * 1000);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
144
202
|
|
|
145
203
|
const getMembers = async () => {
|
|
146
204
|
try {
|
|
147
205
|
await engine.current
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
);
|
|
156
|
-
if (attr?.attributes?.name && attr?.attributes?.screenUid) {
|
|
157
|
-
return attr;
|
|
158
|
-
} else {
|
|
159
|
-
throw attr;
|
|
160
|
-
}
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
retry: (e, idx) => {
|
|
164
|
-
console.log(
|
|
165
|
-
`[retrying] Attempt ${idx}. Fetching ${member.uid}'s name`,
|
|
166
|
-
e,
|
|
206
|
+
.getChannelMembersBychannelId(rtcProps.channel)
|
|
207
|
+
.then((data) => {
|
|
208
|
+
data.members.map(async (member: any) => {
|
|
209
|
+
const backoffAttributes = backOff(
|
|
210
|
+
async () => {
|
|
211
|
+
const attr = await engine.current.getUserAttributesByUid(
|
|
212
|
+
member.uid,
|
|
167
213
|
);
|
|
168
|
-
|
|
214
|
+
if (
|
|
215
|
+
attr?.attributes?.name &&
|
|
216
|
+
attr?.attributes?.screenUid &&
|
|
217
|
+
attr?.attributes?.role &&
|
|
218
|
+
attr?.attributes?.requests
|
|
219
|
+
) {
|
|
220
|
+
return attr;
|
|
221
|
+
} else {
|
|
222
|
+
throw attr;
|
|
223
|
+
}
|
|
169
224
|
},
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
...prevState,
|
|
178
|
-
[member.uid]: {
|
|
179
|
-
name: attr?.attributes?.name || 'User',
|
|
180
|
-
type: UserType.Normal,
|
|
181
|
-
screenUid: parseInt(attr?.attributes?.screenUid),
|
|
182
|
-
},
|
|
183
|
-
[parseInt(attr?.attributes?.screenUid)]: {
|
|
184
|
-
name: `${attr?.attributes?.name || 'User'}'s screenshare`,
|
|
185
|
-
type: UserType.ScreenShare,
|
|
225
|
+
{
|
|
226
|
+
retry: (e, idx) => {
|
|
227
|
+
console.log(
|
|
228
|
+
`[retrying] Attempt ${idx}. Fetching ${member.uid}'s name`,
|
|
229
|
+
e,
|
|
230
|
+
);
|
|
231
|
+
return true;
|
|
186
232
|
},
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
233
|
+
},
|
|
234
|
+
);
|
|
235
|
+
try {
|
|
236
|
+
const attr = await backoffAttributes;
|
|
237
|
+
console.log('[user attributes]:', {attr});
|
|
238
|
+
setUserList((prevState) => {
|
|
239
|
+
return {
|
|
240
|
+
...prevState,
|
|
241
|
+
[member.uid]: {
|
|
242
|
+
name: attr?.attributes?.name || 'User',
|
|
243
|
+
type: UserType.Normal,
|
|
244
|
+
role: parseInt(attr?.attributes?.role),
|
|
245
|
+
screenUid: parseInt(attr?.attributes?.screenUid),
|
|
246
|
+
offline: false,
|
|
247
|
+
requests: attr?.attributes?.requests,
|
|
248
|
+
},
|
|
249
|
+
[parseInt(attr?.attributes?.screenUid)]: {
|
|
250
|
+
name: `${attr?.attributes?.name || 'User'}'s screenshare`,
|
|
251
|
+
type: UserType.ScreenShare,
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
});
|
|
255
|
+
} catch (e) {
|
|
256
|
+
console.error(`Could not retrieve name of ${member.uid}`, e);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
setLogin(true);
|
|
260
|
+
console.log('RTM init done');
|
|
192
261
|
});
|
|
193
|
-
|
|
194
|
-
console.log('RTM init done');
|
|
195
|
-
});
|
|
196
|
-
timerValueRef.current = 5
|
|
262
|
+
timerValueRef.current = 5;
|
|
197
263
|
} catch (error) {
|
|
198
|
-
setTimeout(
|
|
264
|
+
setTimeout(async () => {
|
|
199
265
|
timerValueRef.current = timerValueRef.current + timerValueRef.current;
|
|
200
266
|
getMembers();
|
|
201
|
-
}, timerValueRef.current * 1000
|
|
202
|
-
}
|
|
203
|
-
}
|
|
267
|
+
}, timerValueRef.current * 1000);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
204
270
|
const init = async () => {
|
|
205
271
|
engine.current = new RtmEngine();
|
|
206
272
|
rtcProps.uid
|
|
207
273
|
? (localUid.current = rtcProps.uid + '')
|
|
208
274
|
: (localUid.current = '' + timeNow());
|
|
209
275
|
engine.current.on('connectionStateChanged', (evt: any) => {
|
|
210
|
-
|
|
276
|
+
//console.log(evt);
|
|
211
277
|
});
|
|
212
278
|
engine.current.on('error', (evt: any) => {
|
|
213
279
|
// console.log(evt);
|
|
@@ -216,7 +282,12 @@ const RtmConfigure = (props: any) => {
|
|
|
216
282
|
const backoffAttributes = backOff(
|
|
217
283
|
async () => {
|
|
218
284
|
const attr = await engine.current.getUserAttributesByUid(data.uid);
|
|
219
|
-
if (
|
|
285
|
+
if (
|
|
286
|
+
attr?.attributes?.name &&
|
|
287
|
+
attr?.attributes?.screenUid &&
|
|
288
|
+
attr?.attributes?.role &&
|
|
289
|
+
attr?.attributes?.requests
|
|
290
|
+
) {
|
|
220
291
|
return attr;
|
|
221
292
|
} else {
|
|
222
293
|
throw attr;
|
|
@@ -242,7 +313,10 @@ const RtmConfigure = (props: any) => {
|
|
|
242
313
|
[data.uid]: {
|
|
243
314
|
name: attr?.attributes?.name || 'User',
|
|
244
315
|
type: UserType.Normal,
|
|
316
|
+
role: parseInt(attr?.attributes?.role),
|
|
245
317
|
screenUid: parseInt(attr?.attributes?.screenUid),
|
|
318
|
+
offline: false,
|
|
319
|
+
requests: attr?.attributes?.requests,
|
|
246
320
|
},
|
|
247
321
|
[parseInt(attr?.attributes?.screenUid)]: {
|
|
248
322
|
name: `${attr?.attributes?.name || 'User'}'s screenshare`,
|
|
@@ -256,10 +330,24 @@ const RtmConfigure = (props: any) => {
|
|
|
256
330
|
}
|
|
257
331
|
getname();
|
|
258
332
|
});
|
|
333
|
+
|
|
259
334
|
engine.current.on('channelMemberLeft', (data: any) => {
|
|
260
335
|
console.log('user left', data);
|
|
261
336
|
// Chat of left user becomes undefined. So don't cleanup
|
|
337
|
+
const {uid} = data;
|
|
338
|
+
if (!uid) return;
|
|
339
|
+
setUserList((prevState) => {
|
|
340
|
+
return {
|
|
341
|
+
...prevState,
|
|
342
|
+
[uid]: {
|
|
343
|
+
...prevState[uid],
|
|
344
|
+
requests: attrRequestTypes.none,
|
|
345
|
+
offline: true,
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
});
|
|
262
349
|
});
|
|
350
|
+
|
|
263
351
|
engine.current.on('messageReceived', (evt: any) => {
|
|
264
352
|
const {peerId, ts, text} = evt;
|
|
265
353
|
const textObj = parsePayload(text);
|
|
@@ -296,7 +384,8 @@ const RtmConfigure = (props: any) => {
|
|
|
296
384
|
});
|
|
297
385
|
break;
|
|
298
386
|
default:
|
|
299
|
-
|
|
387
|
+
break;
|
|
388
|
+
// throw new Error('Unsupported message type');
|
|
300
389
|
}
|
|
301
390
|
} catch (e) {
|
|
302
391
|
events.emit(messageChannelType.Private, null, {
|
|
@@ -334,18 +423,26 @@ const RtmConfigure = (props: any) => {
|
|
|
334
423
|
const {uid, channelId, text, ts} = evt;
|
|
335
424
|
const textObj = parsePayload(text);
|
|
336
425
|
const {type, msg} = textObj;
|
|
337
|
-
|
|
338
426
|
let arr = new Int32Array(1);
|
|
339
427
|
arr[0] = parseInt(uid);
|
|
340
428
|
|
|
341
429
|
const userUID = Platform.OS ? arr[0] : uid;
|
|
342
|
-
console.log('userId', userUID);
|
|
343
430
|
const timestamp = ts === 0 ? timeNow() : ts;
|
|
344
431
|
|
|
345
432
|
if (channelId === rtcProps.channel) {
|
|
346
433
|
if (type === messageActionType.Control) {
|
|
434
|
+
let actionMsg = '';
|
|
435
|
+
if (hasJsonStructure(msg)) {
|
|
436
|
+
const [err, result] = safeJsonParse(msg);
|
|
437
|
+
if (!err) {
|
|
438
|
+
const {action} = result;
|
|
439
|
+
actionMsg = action;
|
|
440
|
+
}
|
|
441
|
+
} else {
|
|
442
|
+
actionMsg = msg;
|
|
443
|
+
}
|
|
347
444
|
try {
|
|
348
|
-
switch (
|
|
445
|
+
switch (actionMsg) {
|
|
349
446
|
case controlMessageEnum.muteVideo:
|
|
350
447
|
RtcEngine.muteLocalVideoStream(true);
|
|
351
448
|
dispatch({
|
|
@@ -366,8 +463,28 @@ const RtmConfigure = (props: any) => {
|
|
|
366
463
|
case controlMessageEnum.cloudRecordingUnactive:
|
|
367
464
|
setRecordingActive(false);
|
|
368
465
|
break;
|
|
466
|
+
case controlMessageEnum.clientRoleChanged:
|
|
467
|
+
const {payload} = JSON.parse(msg);
|
|
468
|
+
if (payload && payload?.role) {
|
|
469
|
+
if (
|
|
470
|
+
payload.role.trim() !== '' &&
|
|
471
|
+
payload.role in ClientRole
|
|
472
|
+
) {
|
|
473
|
+
setUserList((prevState) => {
|
|
474
|
+
return {
|
|
475
|
+
...prevState,
|
|
476
|
+
[uid]: {
|
|
477
|
+
...prevState[uid],
|
|
478
|
+
role: parseInt(payload.role),
|
|
479
|
+
},
|
|
480
|
+
};
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
break;
|
|
369
485
|
default:
|
|
370
|
-
|
|
486
|
+
break;
|
|
487
|
+
// throw new Error('Unsupported message type');
|
|
371
488
|
}
|
|
372
489
|
} catch (e) {
|
|
373
490
|
events.emit(messageChannelType.Public, null, {
|
|
@@ -395,9 +512,20 @@ const RtmConfigure = (props: any) => {
|
|
|
395
512
|
});
|
|
396
513
|
});
|
|
397
514
|
|
|
515
|
+
engine.current.addListener(
|
|
516
|
+
'ChannelAttributesUpdated',
|
|
517
|
+
(attributes: RtmChannelAttribute[]) => {
|
|
518
|
+
/**
|
|
519
|
+
* a) The following piece of code is commented for future reference.
|
|
520
|
+
* b) To be used in future implementations of channel attributes
|
|
521
|
+
* c) Kindly note the agora-react-native-rtm does not return the attributes with
|
|
522
|
+
* additional lastUpdateUserId and lastUpdateTs as mentioned in RtmChannelAttribute type
|
|
523
|
+
*/
|
|
524
|
+
},
|
|
525
|
+
);
|
|
526
|
+
|
|
398
527
|
await engine.current.createClient(rtcProps.appId);
|
|
399
528
|
doLoginAndSetupRTM();
|
|
400
|
-
|
|
401
529
|
};
|
|
402
530
|
|
|
403
531
|
const sendMessage = async (msg: string) => {
|
|
@@ -416,6 +544,7 @@ const RtmConfigure = (props: any) => {
|
|
|
416
544
|
ts: timeNow(),
|
|
417
545
|
});
|
|
418
546
|
};
|
|
547
|
+
|
|
419
548
|
const sendMessageToUid = async (msg: string, uid: number) => {
|
|
420
549
|
if (msg.trim() === '') return;
|
|
421
550
|
let adjustedUID = uid;
|
|
@@ -479,6 +608,24 @@ const RtmConfigure = (props: any) => {
|
|
|
479
608
|
: {};
|
|
480
609
|
};
|
|
481
610
|
|
|
611
|
+
const updateChannelAttributes = async (attributes: RtmChannelAttribute[]) => {
|
|
612
|
+
/**
|
|
613
|
+
* a) The following piece of code is commented for future reference.
|
|
614
|
+
* b) To be used in future implementations of channel attributes
|
|
615
|
+
* c) attributes should be an array of key value [{key:"keyTobeUsed", value; 'valueToBeUsed}]
|
|
616
|
+
* following the type RtmChannelAttribute
|
|
617
|
+
*/
|
|
618
|
+
// try {
|
|
619
|
+
// await (engine.current as RtmEngine).addOrUpdateChannelAttributes(
|
|
620
|
+
// rtcProps.channel,
|
|
621
|
+
// [...attributes],
|
|
622
|
+
// {enableNotificationToChannelMembers: true},
|
|
623
|
+
// );
|
|
624
|
+
// } catch (error) {
|
|
625
|
+
// console.log('AttributesUpdated error', error);
|
|
626
|
+
// }
|
|
627
|
+
};
|
|
628
|
+
|
|
482
629
|
useEffect(() => {
|
|
483
630
|
callActive ? init() : (console.log('waiting to init RTM'), setLogin(true));
|
|
484
631
|
return () => {
|
|
@@ -487,6 +634,42 @@ const RtmConfigure = (props: any) => {
|
|
|
487
634
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
488
635
|
}, [rtcProps.channel, rtcProps.appId, callActive]);
|
|
489
636
|
|
|
637
|
+
const broadcastUserAttributes = async (
|
|
638
|
+
attributes: RtmAttribute[],
|
|
639
|
+
ctrlMsg: controlMessageEnum,
|
|
640
|
+
) => {
|
|
641
|
+
// 1. Update my attributes in attribute-list
|
|
642
|
+
await addOrUpdateLocalUserAttributes(attributes);
|
|
643
|
+
|
|
644
|
+
let formattedAttributes: any = {};
|
|
645
|
+
// Transform the array into object of key value pair
|
|
646
|
+
attributes.map((attribute) => {
|
|
647
|
+
let key = Object.values(attribute)[0];
|
|
648
|
+
let value = Object.values(attribute)[1];
|
|
649
|
+
formattedAttributes[key] = value;
|
|
650
|
+
});
|
|
651
|
+
// 2. Update my attributes in user-list
|
|
652
|
+
setUserList((prevState) => {
|
|
653
|
+
return {
|
|
654
|
+
...prevState,
|
|
655
|
+
[localUid.current]: {
|
|
656
|
+
...prevState[localUid.current],
|
|
657
|
+
...formattedAttributes,
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* 3. Broadcast my updated attributes to everyone
|
|
664
|
+
* send payload and control message as string
|
|
665
|
+
*/
|
|
666
|
+
const msgAsString = JSON.stringify({
|
|
667
|
+
action: ctrlMsg,
|
|
668
|
+
payload: {...formattedAttributes},
|
|
669
|
+
});
|
|
670
|
+
sendControlMessage(msgAsString);
|
|
671
|
+
};
|
|
672
|
+
|
|
490
673
|
return (
|
|
491
674
|
<ChatContext.Provider
|
|
492
675
|
value={{
|
|
@@ -496,9 +679,12 @@ const RtmConfigure = (props: any) => {
|
|
|
496
679
|
sendControlMessageToUid,
|
|
497
680
|
sendMessage,
|
|
498
681
|
sendMessageToUid,
|
|
682
|
+
broadcastUserAttributes,
|
|
683
|
+
addOrUpdateLocalUserAttributes,
|
|
499
684
|
engine: engine.current,
|
|
500
685
|
localUid: localUid.current,
|
|
501
686
|
userList: userList,
|
|
687
|
+
onlineUsersCount,
|
|
502
688
|
events,
|
|
503
689
|
}}>
|
|
504
690
|
{login ? props.children : <></>}
|
|
@@ -9,19 +9,10 @@
|
|
|
9
9
|
information visit https://appbuilder.agora.io.
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
|
-
import React
|
|
13
|
-
import {
|
|
14
|
-
View,
|
|
15
|
-
Text,
|
|
16
|
-
StyleSheet,
|
|
17
|
-
Platform,
|
|
18
|
-
TouchableOpacity,
|
|
19
|
-
Image,
|
|
20
|
-
} from 'react-native';
|
|
12
|
+
import React from 'react';
|
|
13
|
+
import {View, Text, StyleSheet, Platform} from 'react-native';
|
|
21
14
|
import SelectDevice from '../subComponents/SelectDevice';
|
|
22
15
|
import HostControlView from './HostControlView';
|
|
23
|
-
import ColorContext from './ColorContext';
|
|
24
|
-
import {SidePanelType} from '../subComponents/SidePanelEnum';
|
|
25
16
|
|
|
26
17
|
const SettingsView = (props: any) => {
|
|
27
18
|
const {isHost} = props;
|
|
@@ -31,9 +22,11 @@ const SettingsView = (props: any) => {
|
|
|
31
22
|
Platform.OS === 'web' ? style.settingsView : style.settingsViewNative
|
|
32
23
|
}>
|
|
33
24
|
<View style={style.main}>
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
<
|
|
25
|
+
<View>
|
|
26
|
+
<Text style={style.heading}>Select Input Device</Text>
|
|
27
|
+
<View style={style.popupPickerHolder}>
|
|
28
|
+
<SelectDevice />
|
|
29
|
+
</View>
|
|
37
30
|
</View>
|
|
38
31
|
{isHost ? <HostControlView /> : <></>}
|
|
39
32
|
</View>
|
|
@@ -49,21 +42,18 @@ const style = StyleSheet.create({
|
|
|
49
42
|
paddingVertical: 5,
|
|
50
43
|
flexGrow: 1,
|
|
51
44
|
shadowColor: $config.PRIMARY_FONT_COLOR + '80',
|
|
52
|
-
shadowOpacity: .5,
|
|
53
|
-
shadowOffset: {width
|
|
45
|
+
shadowOpacity: 0.5,
|
|
46
|
+
shadowOffset: {width: -2, height: 0},
|
|
54
47
|
shadowRadius: 3,
|
|
55
48
|
paddingHorizontal: 20,
|
|
56
49
|
},
|
|
57
50
|
popupPickerHolder: {
|
|
58
|
-
// height: '40%',
|
|
59
51
|
justifyContent: 'space-around',
|
|
60
|
-
// paddingHorizontal: '8%',
|
|
61
52
|
},
|
|
62
53
|
heading: {
|
|
63
54
|
fontSize: 20,
|
|
64
55
|
fontWeight: '700',
|
|
65
56
|
color: $config.PRIMARY_FONT_COLOR,
|
|
66
|
-
// marginBottom: 20,
|
|
67
57
|
alignSelf: 'center',
|
|
68
58
|
},
|
|
69
59
|
settingsView: {
|