agora-appbuilder-core 2.3.0-beta.1 → 2.3.0-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 +1 -1
- package/template/fpe-api/fpeEvents.ts +1 -1
- package/template/src/components/ParticipantsView.tsx +64 -66
- package/template/src/components/RTMConfigure.tsx +21 -31
- package/template/src/components/chat-messages/useChatMessages.tsx +20 -14
- package/template/src/components/participants/AllHostParticipants.tsx +28 -23
- package/template/src/components/useShareLink.tsx +22 -5
- package/template/src/custom-events/CustomEvents.ts +53 -29
- package/template/src/rtm/utils.ts +16 -0
- package/template/src/rtm-events/EventUtils.ts +1 -2
- package/template/src/subComponents/ChatContainer.tsx +5 -5
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +4 -2
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +19 -19
package/package.json
CHANGED
|
@@ -53,63 +53,43 @@ const ParticipantView = () => {
|
|
|
53
53
|
<View style={style.lineUnderHeading}>
|
|
54
54
|
<Text style={style.mainHeading}>{participantsLabel}</Text>
|
|
55
55
|
</View>
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
</View>
|
|
57
|
+
<ScrollView style={[style.bodyContainer, style.padding10]}>
|
|
58
|
+
{$config.EVENT_MODE ? (
|
|
59
|
+
<>
|
|
60
|
+
{
|
|
61
|
+
/*Live streaming is true
|
|
61
62
|
Host and New host view */
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
<View style={style.participantsection}>
|
|
79
|
-
<ParticipantSectionTitle
|
|
80
|
-
title={hostLabel}
|
|
81
|
-
count={hostUids.length}
|
|
82
|
-
/>
|
|
83
|
-
<View style={style.participantContainer}>
|
|
84
|
-
<AllHostParticipants
|
|
85
|
-
p_style={style}
|
|
86
|
-
isHost={isHost}
|
|
87
|
-
/>
|
|
88
|
-
</View>
|
|
89
|
-
</View>
|
|
90
|
-
</>
|
|
91
|
-
) : (
|
|
92
|
-
/** New Host ( earlier was 'audience' and now is host )
|
|
93
|
-
* a) Can view all hosts without remote controls
|
|
94
|
-
*/
|
|
63
|
+
rtcProps?.role == ClientRole.Broadcaster &&
|
|
64
|
+
(isHost ? (
|
|
65
|
+
/**
|
|
66
|
+
* Original Host
|
|
67
|
+
* a) Can view streaming requests
|
|
68
|
+
* b) Can view all hosts with remote controls
|
|
69
|
+
*/
|
|
70
|
+
<>
|
|
71
|
+
{/* a) Live streaming view */}
|
|
72
|
+
<View style={style.participantsection}>
|
|
73
|
+
<CurrentLiveStreamRequestsView
|
|
74
|
+
p_style={style}
|
|
75
|
+
userList={liveStreamData}
|
|
76
|
+
/>
|
|
77
|
+
</View>
|
|
78
|
+
{/* b) Host view with remote controls*/}
|
|
95
79
|
<View style={style.participantsection}>
|
|
96
80
|
<ParticipantSectionTitle
|
|
97
81
|
title={hostLabel}
|
|
98
82
|
count={hostUids.length}
|
|
99
83
|
/>
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
isHost={isHost}
|
|
104
|
-
/>
|
|
84
|
+
<View style={style.participantContainer}>
|
|
85
|
+
<AllHostParticipants p_style={style} isHost={isHost} />
|
|
86
|
+
</View>
|
|
105
87
|
</View>
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
*/
|
|
112
|
-
rtcProps?.role == ClientRole.Audience && (
|
|
88
|
+
</>
|
|
89
|
+
) : (
|
|
90
|
+
/** New Host ( earlier was 'audience' and now is host )
|
|
91
|
+
* a) Can view all hosts without remote controls
|
|
92
|
+
*/
|
|
113
93
|
<View style={style.participantsection}>
|
|
114
94
|
<ParticipantSectionTitle
|
|
115
95
|
title={hostLabel}
|
|
@@ -121,32 +101,50 @@ const ParticipantView = () => {
|
|
|
121
101
|
isHost={isHost}
|
|
122
102
|
/>
|
|
123
103
|
</View>
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
104
|
+
))
|
|
105
|
+
}
|
|
106
|
+
{
|
|
107
|
+
/**
|
|
108
|
+
* Audience views all hosts without remote controls
|
|
109
|
+
*/
|
|
110
|
+
rtcProps?.role == ClientRole.Audience && (
|
|
128
111
|
<View style={style.participantsection}>
|
|
129
112
|
<ParticipantSectionTitle
|
|
130
|
-
title={
|
|
131
|
-
count={
|
|
113
|
+
title={hostLabel}
|
|
114
|
+
count={hostUids.length}
|
|
132
115
|
/>
|
|
133
116
|
<AllAudienceParticipants
|
|
134
|
-
uids={
|
|
117
|
+
uids={hostUids}
|
|
135
118
|
p_style={style}
|
|
136
119
|
isHost={isHost}
|
|
137
120
|
/>
|
|
138
121
|
</View>
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
<View style={style.
|
|
144
|
-
<
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
{
|
|
125
|
+
/* Everyone can see audience */
|
|
126
|
+
<View style={style.participantsection}>
|
|
127
|
+
<ParticipantSectionTitle
|
|
128
|
+
title={audienceLabel}
|
|
129
|
+
count={audienceUids.length}
|
|
130
|
+
/>
|
|
131
|
+
<AllAudienceParticipants
|
|
132
|
+
uids={audienceUids}
|
|
133
|
+
p_style={style}
|
|
134
|
+
isHost={isHost}
|
|
135
|
+
/>
|
|
145
136
|
</View>
|
|
137
|
+
}
|
|
138
|
+
</>
|
|
139
|
+
) : (
|
|
140
|
+
<View style={style.participantsection}>
|
|
141
|
+
<View style={style.participantContainer}>
|
|
142
|
+
<AllHostParticipants p_style={style} isHost={isHost} />
|
|
146
143
|
</View>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
</
|
|
144
|
+
</View>
|
|
145
|
+
)}
|
|
146
|
+
</ScrollView>
|
|
147
|
+
|
|
150
148
|
<View
|
|
151
149
|
style={{
|
|
152
150
|
width: '100%',
|
|
@@ -22,9 +22,15 @@ import {useString} from '../utils/useString';
|
|
|
22
22
|
import {isAndroid, isWeb} from '../utils/common';
|
|
23
23
|
import StorageContext from './StorageContext';
|
|
24
24
|
import {useRenderContext} from 'fpe-api';
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
safeJsonParse,
|
|
27
|
+
timeNow,
|
|
28
|
+
hasJsonStructure,
|
|
29
|
+
getMessageTime,
|
|
30
|
+
get32BitUid,
|
|
31
|
+
adjustUID,
|
|
32
|
+
} from '../rtm/utils';
|
|
26
33
|
import {EventUtils, EventsQueue, eventMessageType} from '../rtm-events';
|
|
27
|
-
|
|
28
34
|
import RTMEngine from '../rtm/RTMEngine';
|
|
29
35
|
import {filterObject} from '../utils';
|
|
30
36
|
|
|
@@ -32,18 +38,6 @@ export enum UserType {
|
|
|
32
38
|
ScreenShare = 'screenshare',
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
const adjustUID = (uid: number | string) => {
|
|
36
|
-
let number: number | string;
|
|
37
|
-
if (typeof uid === 'string') number = uid;
|
|
38
|
-
else {
|
|
39
|
-
number = uid;
|
|
40
|
-
if (number < 0) {
|
|
41
|
-
number = 0xffffffff + number + 1;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return number;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
41
|
const stringifyPayload = (
|
|
48
42
|
source: messageSourceType,
|
|
49
43
|
type: messageActionType,
|
|
@@ -370,12 +364,9 @@ const RtmConfigure = (props: any) => {
|
|
|
370
364
|
const textObj = parsePayload(text);
|
|
371
365
|
const {type, msg} = textObj;
|
|
372
366
|
|
|
373
|
-
|
|
374
|
-
arr[0] = parseInt(peerId);
|
|
367
|
+
const timestamp = getMessageTime(ts);
|
|
375
368
|
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
const sender = isAndroid ? arr[0] : peerId;
|
|
369
|
+
const sender = isAndroid ? get32BitUid(peerId) : peerId;
|
|
379
370
|
|
|
380
371
|
if (type === messageActionType.Control) {
|
|
381
372
|
switch (msg) {
|
|
@@ -417,11 +408,10 @@ const RtmConfigure = (props: any) => {
|
|
|
417
408
|
const textObj = parsePayload(text);
|
|
418
409
|
const [err, result] = safeJsonParse(text);
|
|
419
410
|
const {type, msg} = textObj;
|
|
420
|
-
let arr = new Int32Array(1);
|
|
421
|
-
arr[0] = parseInt(uid);
|
|
422
411
|
|
|
423
|
-
const
|
|
424
|
-
|
|
412
|
+
const timestamp = getMessageTime(ts);
|
|
413
|
+
|
|
414
|
+
const sender = Platform.OS ? get32BitUid(uid) : uid;
|
|
425
415
|
|
|
426
416
|
if (channelId === rtcProps.channel) {
|
|
427
417
|
if (
|
|
@@ -534,10 +524,9 @@ const RtmConfigure = (props: any) => {
|
|
|
534
524
|
|
|
535
525
|
const sendMessageToUid = async (msg: string, uid: UidType) => {
|
|
536
526
|
if (msg.trim() === '') return;
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
}
|
|
527
|
+
|
|
528
|
+
const adjustedUID = adjustUID(uid);
|
|
529
|
+
|
|
541
530
|
const text = stringifyPayload(
|
|
542
531
|
messageSourceType.Core,
|
|
543
532
|
messageActionType.Normal,
|
|
@@ -563,16 +552,17 @@ const RtmConfigure = (props: any) => {
|
|
|
563
552
|
};
|
|
564
553
|
|
|
565
554
|
const sendControlMessageToUid = async (msg: string, uid: UidType) => {
|
|
566
|
-
if (
|
|
567
|
-
|
|
568
|
-
|
|
555
|
+
if (msg.trim() === '') return;
|
|
556
|
+
|
|
557
|
+
const adjustedUID = adjustUID(uid);
|
|
558
|
+
|
|
569
559
|
const text = stringifyPayload(
|
|
570
560
|
messageSourceType.Core,
|
|
571
561
|
messageActionType.Control,
|
|
572
562
|
msg,
|
|
573
563
|
);
|
|
574
564
|
await (engine.current as RtmEngine).sendMessageToPeer({
|
|
575
|
-
peerId:
|
|
565
|
+
peerId: adjustedUID.toString(),
|
|
576
566
|
offline: false,
|
|
577
567
|
text,
|
|
578
568
|
});
|
|
@@ -13,16 +13,14 @@ import {createHook} from 'fpe-implementation';
|
|
|
13
13
|
import React, {useState, useEffect, useRef} from 'react';
|
|
14
14
|
import {useRenderContext} from 'fpe-api';
|
|
15
15
|
import {SidePanelType} from '../../subComponents/SidePanelEnum';
|
|
16
|
-
import {useLocalUid} from '../../../agora-rn-uikit';
|
|
16
|
+
import {useLocalUid, UidType} from '../../../agora-rn-uikit';
|
|
17
17
|
import CustomEvents from '../../custom-events';
|
|
18
18
|
import {EventNames} from '../../rtm-events';
|
|
19
19
|
import {useChatUIControl} from '../chat-ui/useChatUIControl';
|
|
20
20
|
import {useChatNotification} from '../chat-notification/useChatNotification';
|
|
21
|
-
import {useString} from '../../utils/useString';
|
|
22
21
|
import Toast from '../../../react-native-toast-message';
|
|
23
22
|
import {timeNow} from '../../rtm/utils';
|
|
24
23
|
import {useSidePanel} from '../../utils/useSidePanel';
|
|
25
|
-
import {UidType} from '../../../agora-rn-uikit';
|
|
26
24
|
|
|
27
25
|
interface ChatMessagesProviderProps {
|
|
28
26
|
children: React.ReactNode;
|
|
@@ -32,13 +30,13 @@ interface messageInterface {
|
|
|
32
30
|
msg: string;
|
|
33
31
|
}
|
|
34
32
|
interface messageStoreInterface extends messageInterface {
|
|
35
|
-
uid:
|
|
33
|
+
uid: UidType;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
interface ChatMessagesInterface {
|
|
39
37
|
messageStore: messageStoreInterface | any;
|
|
40
38
|
privateMessageStore: any;
|
|
41
|
-
sendChatMessage: (msg: string, toUid?:
|
|
39
|
+
sendChatMessage: (msg: string, toUid?: UidType) => void;
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
const ChatMessagesContext = React.createContext<ChatMessagesInterface>({
|
|
@@ -94,7 +92,7 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
|
|
|
94
92
|
};
|
|
95
93
|
CustomEvents.on(EventNames.PUBLIC_CHAT_MESSAGE, (data) => {
|
|
96
94
|
showMessageNotification(data.payload.value, data.sender);
|
|
97
|
-
addMessageToStore(data.sender, {
|
|
95
|
+
addMessageToStore(parseInt(data.sender), {
|
|
98
96
|
msg: data.payload.value,
|
|
99
97
|
ts: data.ts,
|
|
100
98
|
});
|
|
@@ -111,34 +109,41 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
|
|
|
111
109
|
CustomEvents.on(EventNames.PRIVATE_CHAT_MESSAGE, (data) => {
|
|
112
110
|
showMessageNotification(data.payload.value, data.sender);
|
|
113
111
|
addMessageToPrivateStore(
|
|
114
|
-
data.sender,
|
|
112
|
+
parseInt(data.sender),
|
|
115
113
|
{
|
|
116
114
|
msg: data.payload.value,
|
|
117
115
|
ts: data.ts,
|
|
118
116
|
},
|
|
119
117
|
false,
|
|
120
118
|
);
|
|
121
|
-
|
|
119
|
+
/**
|
|
120
|
+
* if user's private window is active.
|
|
121
|
+
* then we will not increment the unread count
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
if (!(individualActiveRef.current === parseInt(data.sender))) {
|
|
122
125
|
setUnreadIndividualMessageCount((prevState) => {
|
|
123
126
|
const prevCount =
|
|
124
|
-
prevState && prevState[data.sender]
|
|
127
|
+
prevState && prevState[parseInt(data.sender)]
|
|
128
|
+
? prevState[parseInt(data.sender)]
|
|
129
|
+
: 0;
|
|
125
130
|
return {
|
|
126
131
|
...prevState,
|
|
127
|
-
[data.sender]: prevCount + 1,
|
|
132
|
+
[parseInt(data.sender)]: prevCount + 1,
|
|
128
133
|
};
|
|
129
134
|
});
|
|
130
135
|
}
|
|
131
136
|
});
|
|
132
137
|
}, []);
|
|
133
138
|
|
|
134
|
-
const addMessageToStore = (uid:
|
|
139
|
+
const addMessageToStore = (uid: UidType, body: messageInterface) => {
|
|
135
140
|
setMessageStore((m: messageStoreInterface[]) => {
|
|
136
141
|
return [...m, {ts: body.ts, uid, msg: body.msg}];
|
|
137
142
|
});
|
|
138
143
|
};
|
|
139
144
|
|
|
140
145
|
const addMessageToPrivateStore = (
|
|
141
|
-
uid:
|
|
146
|
+
uid: UidType,
|
|
142
147
|
body: messageInterface,
|
|
143
148
|
local: boolean,
|
|
144
149
|
) => {
|
|
@@ -158,6 +163,7 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
|
|
|
158
163
|
};
|
|
159
164
|
|
|
160
165
|
const sendChatMessage = (msg: string, toUid?: UidType) => {
|
|
166
|
+
if (typeof msg == 'string' && msg.trim() === '') return;
|
|
161
167
|
if (toUid) {
|
|
162
168
|
CustomEvents.send(
|
|
163
169
|
EventNames.PRIVATE_CHAT_MESSAGE,
|
|
@@ -167,7 +173,7 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
|
|
|
167
173
|
toUid,
|
|
168
174
|
);
|
|
169
175
|
addMessageToPrivateStore(
|
|
170
|
-
toUid
|
|
176
|
+
toUid,
|
|
171
177
|
{
|
|
172
178
|
msg: msg,
|
|
173
179
|
ts: timeNow(),
|
|
@@ -178,7 +184,7 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
|
|
|
178
184
|
CustomEvents.send(EventNames.PUBLIC_CHAT_MESSAGE, {
|
|
179
185
|
value: msg,
|
|
180
186
|
});
|
|
181
|
-
addMessageToStore(localUid
|
|
187
|
+
addMessageToStore(localUid, {
|
|
182
188
|
msg: msg,
|
|
183
189
|
ts: timeNow(),
|
|
184
190
|
});
|
|
@@ -19,30 +19,35 @@ export default function AllHostParticipants(props: any) {
|
|
|
19
19
|
|
|
20
20
|
return (
|
|
21
21
|
<>
|
|
22
|
-
{
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
) : renderList[uid]?.type === 'screenshare' ? (
|
|
30
|
-
<ScreenshareParticipants
|
|
31
|
-
name={getParticipantName(uid)}
|
|
32
|
-
p_styles={p_style}
|
|
33
|
-
key={uid}
|
|
34
|
-
/>
|
|
35
|
-
) : (
|
|
36
|
-
<RemoteParticipants
|
|
37
|
-
name={getParticipantName(uid)}
|
|
38
|
-
p_styles={p_style}
|
|
39
|
-
user={renderList[uid]}
|
|
40
|
-
showControls={renderList[uid]?.type === 'rtc'}
|
|
41
|
-
isHost={isHost}
|
|
42
|
-
key={uid}
|
|
43
|
-
/>
|
|
44
|
-
),
|
|
22
|
+
{/* User should see his name first */}
|
|
23
|
+
{renderPosition.filter((uid) => uid === localUid).length > 0 && (
|
|
24
|
+
<MeParticipant
|
|
25
|
+
name={getParticipantName(localUid)}
|
|
26
|
+
p_style={p_style}
|
|
27
|
+
key={localUid}
|
|
28
|
+
/>
|
|
45
29
|
)}
|
|
30
|
+
{/* Others Users in the call */}
|
|
31
|
+
{renderPosition
|
|
32
|
+
.filter((uid) => uid !== localUid)
|
|
33
|
+
.map((uid) =>
|
|
34
|
+
renderList[uid]?.type === 'screenshare' ? (
|
|
35
|
+
<ScreenshareParticipants
|
|
36
|
+
name={getParticipantName(uid)}
|
|
37
|
+
p_styles={p_style}
|
|
38
|
+
key={uid}
|
|
39
|
+
/>
|
|
40
|
+
) : (
|
|
41
|
+
<RemoteParticipants
|
|
42
|
+
name={getParticipantName(uid)}
|
|
43
|
+
p_styles={p_style}
|
|
44
|
+
user={renderList[uid]}
|
|
45
|
+
showControls={renderList[uid]?.type === 'rtc'}
|
|
46
|
+
isHost={isHost}
|
|
47
|
+
key={uid}
|
|
48
|
+
/>
|
|
49
|
+
),
|
|
50
|
+
)}
|
|
46
51
|
</>
|
|
47
52
|
);
|
|
48
53
|
}
|
|
@@ -45,8 +45,12 @@ interface ShareLinkProvideProps {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
const ShareLinkProvider = (props: ShareLinkProvideProps) => {
|
|
48
|
-
const {
|
|
49
|
-
|
|
48
|
+
const {
|
|
49
|
+
meetingTitle,
|
|
50
|
+
meetingPassphrase,
|
|
51
|
+
isSeparateHostLink,
|
|
52
|
+
isJoinDataFetched,
|
|
53
|
+
} = useMeetingInfo();
|
|
50
54
|
|
|
51
55
|
//commmented for v1 release
|
|
52
56
|
// const copiedToClipboardText = useString(
|
|
@@ -61,7 +65,7 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
|
|
|
61
65
|
const meetingIdText = 'Meeting ID';
|
|
62
66
|
const PSTNNumberText = 'PSTN Number';
|
|
63
67
|
const PSTNPinText = 'PSTN Pin';
|
|
64
|
-
const meetingInviteText = ({meetingName, id, url, pstn}) => {
|
|
68
|
+
const meetingInviteText = ({meetingName, id, url, pstn, isCallActive}) => {
|
|
65
69
|
let inviteContent = '';
|
|
66
70
|
if (url) {
|
|
67
71
|
// if host data is present generate links for both host and attendee
|
|
@@ -70,7 +74,13 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
|
|
|
70
74
|
}
|
|
71
75
|
// if host data is not present then generate link for attendee alone
|
|
72
76
|
else {
|
|
73
|
-
|
|
77
|
+
if (isCallActive) {
|
|
78
|
+
//copy this label on videocall screen
|
|
79
|
+
inviteContent += `Meeting - ${meetingName}\nURL for Attendee: ${url?.attendee}`;
|
|
80
|
+
} else {
|
|
81
|
+
//copy this label on share link screen
|
|
82
|
+
inviteContent += `Meeting - ${meetingName}\nMeeting URL: ${url?.attendee}`;
|
|
83
|
+
}
|
|
74
84
|
}
|
|
75
85
|
} else {
|
|
76
86
|
// if host data is present generate meeting ID for both host and attendee
|
|
@@ -79,7 +89,13 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
|
|
|
79
89
|
}
|
|
80
90
|
// if host data is not present then generate meeting ID for attendee alone
|
|
81
91
|
else {
|
|
82
|
-
|
|
92
|
+
if (isCallActive) {
|
|
93
|
+
//copy this label on videocall screen
|
|
94
|
+
inviteContent += `Meeting - ${meetingName}\nAttendee Meeting ID: ${id?.attendee}`;
|
|
95
|
+
} else {
|
|
96
|
+
//copy this label on share link screen
|
|
97
|
+
inviteContent += `Meeting - ${meetingName}\nMeeting ID: ${id?.attendee}`;
|
|
98
|
+
}
|
|
83
99
|
}
|
|
84
100
|
}
|
|
85
101
|
// Adding pstn data into meeting data if present
|
|
@@ -114,6 +130,7 @@ const ShareLinkProvider = (props: ShareLinkProvideProps) => {
|
|
|
114
130
|
pin: meetingPassphrase.pstn.pin,
|
|
115
131
|
}
|
|
116
132
|
: undefined,
|
|
133
|
+
isCallActive: isJoinDataFetched,
|
|
117
134
|
});
|
|
118
135
|
return stringToCopy;
|
|
119
136
|
};
|
|
@@ -16,10 +16,11 @@ import RTMEngine from '../rtm/RTMEngine';
|
|
|
16
16
|
import {ToOptions, EventPayload} from './types';
|
|
17
17
|
import {EventUtils, eventMessageType} from '../rtm-events';
|
|
18
18
|
import {TEventCallback, EventSourceEnum} from './types';
|
|
19
|
+
import {adjustUID} from '../rtm/utils';
|
|
19
20
|
|
|
20
21
|
class CustomEvents {
|
|
21
|
-
engine!: RtmEngine;
|
|
22
|
-
source: EventSourceEnum = EventSourceEnum.core;
|
|
22
|
+
private engine!: RtmEngine;
|
|
23
|
+
private source: EventSourceEnum = EventSourceEnum.core;
|
|
23
24
|
|
|
24
25
|
constructor(source?: EventSourceEnum) {
|
|
25
26
|
this.engine = RTMEngine.getInstance().engine;
|
|
@@ -63,6 +64,7 @@ class CustomEvents {
|
|
|
63
64
|
}
|
|
64
65
|
return true;
|
|
65
66
|
};
|
|
67
|
+
|
|
66
68
|
private _validateListener = (listener: TEventCallback): boolean => {
|
|
67
69
|
if (typeof listener !== 'function') {
|
|
68
70
|
throw Error(
|
|
@@ -73,10 +75,13 @@ class CustomEvents {
|
|
|
73
75
|
};
|
|
74
76
|
|
|
75
77
|
/**
|
|
76
|
-
*
|
|
78
|
+
* Sets the local attribute of user if persist level is 2 or 3.
|
|
79
|
+
* If param 'to' is not provided, message is sent in the channel.
|
|
80
|
+
* If param 'to' is provided message is sent to that individual.
|
|
81
|
+
* If param 'to' is an array of uids is provided then message is sent to all the individual uids in loop.
|
|
77
82
|
*
|
|
78
83
|
* @param {any} rtmPayload payload to be sent across
|
|
79
|
-
* @param {ToOptions} to
|
|
84
|
+
* @param {ToOptions} to uid or uids[] of user
|
|
80
85
|
* @api private
|
|
81
86
|
*/
|
|
82
87
|
private _send = async (rtmPayload: any, to?: ToOptions) => {
|
|
@@ -87,7 +92,7 @@ class CustomEvents {
|
|
|
87
92
|
// Case 1: send to channel
|
|
88
93
|
if (
|
|
89
94
|
typeof to === 'undefined' ||
|
|
90
|
-
(typeof to === 'number' &&
|
|
95
|
+
(typeof to === 'number' && to <= 0) ||
|
|
91
96
|
(Array.isArray(to) && to?.length === 0)
|
|
92
97
|
) {
|
|
93
98
|
console.log('CUSTOM_EVENT_API: case 1 executed');
|
|
@@ -100,12 +105,12 @@ class CustomEvents {
|
|
|
100
105
|
}
|
|
101
106
|
}
|
|
102
107
|
// Case 2: send to indivdual
|
|
103
|
-
if (typeof to === 'number' &&
|
|
108
|
+
if (typeof to === 'number' && to > 0) {
|
|
104
109
|
console.log('CUSTOM_EVENT_API: case 2 executed', to);
|
|
105
|
-
|
|
110
|
+
const adjustedUID = adjustUID(to);
|
|
106
111
|
try {
|
|
107
112
|
await this.engine.sendMessageToPeer({
|
|
108
|
-
peerId: `${
|
|
113
|
+
peerId: `${adjustedUID}`,
|
|
109
114
|
offline: false,
|
|
110
115
|
text,
|
|
111
116
|
});
|
|
@@ -120,9 +125,9 @@ class CustomEvents {
|
|
|
120
125
|
|
|
121
126
|
try {
|
|
122
127
|
for (const uid of to) {
|
|
123
|
-
|
|
128
|
+
const adjustedUID = adjustUID(uid);
|
|
124
129
|
await this.engine.sendMessageToPeer({
|
|
125
|
-
peerId: `${
|
|
130
|
+
peerId: `${adjustedUID}`,
|
|
126
131
|
offline: false,
|
|
127
132
|
text,
|
|
128
133
|
});
|
|
@@ -134,15 +139,35 @@ class CustomEvents {
|
|
|
134
139
|
}
|
|
135
140
|
};
|
|
136
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Listens for a specified event.
|
|
144
|
+
* Adds a listener function to the specified event.
|
|
145
|
+
* When the specified event happens, the Events API triggers the callback that you pass.
|
|
146
|
+
* The listener will not be added if it is a duplicate.
|
|
147
|
+
*
|
|
148
|
+
* @param {String} evt Name of the event to attach the listener to.
|
|
149
|
+
* @param {Function} listener Method to be called when the event is emitted.
|
|
150
|
+
* @api public
|
|
151
|
+
*/
|
|
137
152
|
on = (evt: string, listener: TEventCallback) => {
|
|
138
153
|
if (!this._validateEvt(evt) || !this._validateListener(listener)) return;
|
|
139
154
|
EventUtils.addListener(evt, listener, this.source);
|
|
140
155
|
};
|
|
141
156
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Removes a listener function from the specified event if evt and listener function both are provided.
|
|
159
|
+
* Removes all listeners from a specified event if listener function is not provided.
|
|
160
|
+
* If you do not specify an event then all listeners will be removed.
|
|
161
|
+
* That means every event will be emptied.
|
|
162
|
+
*
|
|
163
|
+
* @param {String} evt Name of the event to remove the listener from.
|
|
164
|
+
* @param {Function} listenerToRemove Method to remove from the event.
|
|
165
|
+
* @api public
|
|
166
|
+
*/
|
|
167
|
+
off = (evt?: string, listenerToRemove?: TEventCallback) => {
|
|
168
|
+
if (listenerToRemove) {
|
|
169
|
+
if (this._validateListener(listenerToRemove) && this._validateEvt(evt)) {
|
|
170
|
+
EventUtils.removeListener(evt, listenerToRemove, this.source);
|
|
146
171
|
}
|
|
147
172
|
} else if (evt) {
|
|
148
173
|
if (this._validateEvt(evt)) {
|
|
@@ -153,6 +178,20 @@ class CustomEvents {
|
|
|
153
178
|
}
|
|
154
179
|
};
|
|
155
180
|
|
|
181
|
+
/**
|
|
182
|
+
* This method sends p2p or channel message depending upon the 'to' value.
|
|
183
|
+
* - If 'to' is provided this method sends p2p message.
|
|
184
|
+
* - If 'to' is empty this method sends channel message.
|
|
185
|
+
*
|
|
186
|
+
*
|
|
187
|
+
* @param {String} evt Name of the event to remove the listener from.
|
|
188
|
+
* @param {EventPayload} payload contains action, level, value metrics.
|
|
189
|
+
* - action: {string}
|
|
190
|
+
* - level: 1 | 2 | 3
|
|
191
|
+
* - value: {string}. NOTICE: value bytelength has MAX_SIZE 32kb limit.
|
|
192
|
+
* @param {ToOptions} to uid or uid array. The default mode is to send a message in channel.
|
|
193
|
+
* @api public
|
|
194
|
+
* */
|
|
156
195
|
send = async (evt: string, payload: EventPayload, to?: ToOptions) => {
|
|
157
196
|
if (!this._validateEvt(evt)) return;
|
|
158
197
|
const {action = '', value = '', level = 1} = payload;
|
|
@@ -177,21 +216,6 @@ class CustomEvents {
|
|
|
177
216
|
console.log('CUSTOM_EVENT_API: sendPersist sending failed. ', error);
|
|
178
217
|
}
|
|
179
218
|
};
|
|
180
|
-
|
|
181
|
-
printEvents = () => {
|
|
182
|
-
console.log(
|
|
183
|
-
'CUSTOM_EVENT_API: EVENTS source',
|
|
184
|
-
EventUtils.getEvents(EventSourceEnum.core),
|
|
185
|
-
);
|
|
186
|
-
console.log(
|
|
187
|
-
'CUSTOM_EVENT_API: EVENTS fpe',
|
|
188
|
-
EventUtils.getEvents(EventSourceEnum.fpe),
|
|
189
|
-
);
|
|
190
|
-
};
|
|
191
|
-
// once = (name: string, listener: any) => {
|
|
192
|
-
// console.log('CUSTOM_EVENT_API: Event lifecycle: ONCE');
|
|
193
|
-
// const response = EventUtils.addOnceListener(name, listener);
|
|
194
|
-
// };
|
|
195
219
|
}
|
|
196
220
|
|
|
197
221
|
export default CustomEvents;
|
|
@@ -26,3 +26,19 @@ export const adjustUID = (uid: number): number => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export const timeNow = () => new Date().getTime();
|
|
29
|
+
|
|
30
|
+
export const getMessageTime = (ts?: number): number => {
|
|
31
|
+
if (!ts) return timeNow();
|
|
32
|
+
try {
|
|
33
|
+
const timestamp = new Date(ts).getHours();
|
|
34
|
+
return isNaN(timestamp) ? timeNow() : timestamp;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
return timeNow();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const get32BitUid = (peerId: string) => {
|
|
41
|
+
let arr = new Int32Array(1);
|
|
42
|
+
arr[0] = parseInt(peerId);
|
|
43
|
+
return arr[0];
|
|
44
|
+
};
|
|
@@ -120,10 +120,9 @@ const EventUtils = (function () {
|
|
|
120
120
|
/**
|
|
121
121
|
* Adds a listener function to the specified event.
|
|
122
122
|
* The listener will not be added if it is a duplicate.
|
|
123
|
-
* If the listener returns true then it will be removed after it is called.
|
|
124
123
|
*
|
|
125
124
|
* @param {String} evt Name of the event to attach the listener to.
|
|
126
|
-
* @param {Function} listener Method to be called when the event is emitted.
|
|
125
|
+
* @param {Function} listener Method to be called when the event is emitted.
|
|
127
126
|
* @param {EventSourceEnum} source Name of the bucket to search events from
|
|
128
127
|
* @return {Object} Current instance of EventUtils
|
|
129
128
|
*/
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
information visit https://appbuilder.agora.io.
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
|
-
import React, {
|
|
12
|
+
import React, {useRef} from 'react';
|
|
13
13
|
import {
|
|
14
14
|
View,
|
|
15
15
|
ScrollView,
|
|
@@ -21,12 +21,12 @@ import {
|
|
|
21
21
|
} from 'react-native';
|
|
22
22
|
import {RFValue} from 'react-native-responsive-fontsize';
|
|
23
23
|
import ChatBubble from './ChatBubble';
|
|
24
|
-
import
|
|
25
|
-
import {
|
|
24
|
+
import {ChatBubbleProps} from '../components/ChatContext';
|
|
25
|
+
import {useLocalUid} from '../../agora-rn-uikit';
|
|
26
26
|
import {ImageIcon} from '../../agora-rn-uikit';
|
|
27
27
|
import TextWithTooltip from './TextWithTooltip';
|
|
28
28
|
import {useFpe} from 'fpe-api';
|
|
29
|
-
import {
|
|
29
|
+
import {isWeb} from '../utils/common';
|
|
30
30
|
import {useString} from '../utils/useString';
|
|
31
31
|
import {useChatUIControl} from '../components/chat-ui/useChatUIControl';
|
|
32
32
|
import useUserList from '../utils/useUserList';
|
|
@@ -50,7 +50,7 @@ const ChatContainer = (props: any) => {
|
|
|
50
50
|
selectedChatUserId: selectedUserID,
|
|
51
51
|
setPrivateActive,
|
|
52
52
|
} = useChatUIControl();
|
|
53
|
-
const
|
|
53
|
+
const localUid = useLocalUid();
|
|
54
54
|
//commented for v1 release
|
|
55
55
|
//const remoteUserDefaultLabel = useString('remoteUserDefaultLabel')();
|
|
56
56
|
const remoteUserDefaultLabel = 'User';
|
|
@@ -34,13 +34,15 @@ export interface ScreenshareButtonProps {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const ScreenshareButton = (props: ScreenshareButtonProps) => {
|
|
37
|
-
const {isScreenshareActive, startUserScreenshare} =
|
|
37
|
+
const {isScreenshareActive, startUserScreenshare, stopUserScreenShare} =
|
|
38
|
+
useScreenshare();
|
|
38
39
|
//commented for v1 release
|
|
39
40
|
//const screenShareButton = useString('screenShareButton')();
|
|
40
41
|
const screenShareButton = 'Share';
|
|
41
42
|
const defaultTemplateValue = useButtonTemplate().buttonTemplateName;
|
|
42
43
|
const {buttonTemplateName = defaultTemplateValue} = props;
|
|
43
|
-
const onPress = () =>
|
|
44
|
+
const onPress = () =>
|
|
45
|
+
isScreenshareActive ? stopUserScreenShare() : startUserScreenshare();
|
|
44
46
|
let btnTemplateProps: BtnTemplateInterface = {
|
|
45
47
|
name: isScreenshareActive ? 'screenshareOffIcon' : 'screenshareIcon',
|
|
46
48
|
onPress,
|
|
@@ -40,9 +40,6 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
|
|
|
40
40
|
const setPinnedLayout = useSetPinnedLayout();
|
|
41
41
|
const changeLayout = useChangeDefaultLayout();
|
|
42
42
|
|
|
43
|
-
const prevRenderPosition = usePrevious<{renderPosition: UidType[]}>({
|
|
44
|
-
renderPosition,
|
|
45
|
-
});
|
|
46
43
|
const {channel, appId, screenShareUid, screenShareToken, encryption} =
|
|
47
44
|
useContext(PropsContext).rtcProps;
|
|
48
45
|
|
|
@@ -60,9 +57,8 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
|
|
|
60
57
|
value: [screenShareUid],
|
|
61
58
|
});
|
|
62
59
|
setPinnedLayout();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
else {
|
|
60
|
+
} else {
|
|
61
|
+
//screenshare is stopped set the layout Grid View
|
|
66
62
|
changeLayout();
|
|
67
63
|
}
|
|
68
64
|
};
|
|
@@ -113,15 +109,17 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
|
|
|
113
109
|
};
|
|
114
110
|
|
|
115
111
|
const stopUserScreenShare = () => {
|
|
116
|
-
if (isScreenshareActive)
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
if (!isScreenshareActive) return;
|
|
113
|
+
userScreenshare(false);
|
|
114
|
+
};
|
|
115
|
+
const startUserScreenshare = () => {
|
|
116
|
+
if (isScreenshareActive) return;
|
|
117
|
+
userScreenshare(true);
|
|
119
118
|
};
|
|
120
119
|
|
|
121
|
-
const
|
|
122
|
-
const isScreenActive = isScreenshareActive;
|
|
120
|
+
const userScreenshare = async (isActive: boolean) => {
|
|
123
121
|
if (isRecordingActive) {
|
|
124
|
-
executeRecordingQuery(
|
|
122
|
+
executeRecordingQuery(isActive);
|
|
125
123
|
}
|
|
126
124
|
try {
|
|
127
125
|
// @ts-ignore
|
|
@@ -134,17 +132,19 @@ export const ScreenshareConfigure = (props: {children: React.ReactNode}) => {
|
|
|
134
132
|
rtc.RtcEngine as unknown as IAgoraRTC,
|
|
135
133
|
encryption as unknown as any,
|
|
136
134
|
);
|
|
137
|
-
|
|
135
|
+
isActive && setScreenshareActive(true);
|
|
138
136
|
} catch (e) {
|
|
139
137
|
console.error("can't start the screen share", e);
|
|
140
138
|
executeNormalQuery();
|
|
141
139
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
140
|
+
if (isActive) {
|
|
141
|
+
CustomEvents.send(EventNames.SCREENSHARE_ATTRIBUTE, {
|
|
142
|
+
value: `${true}`,
|
|
143
|
+
level: EventLevel.LEVEL2,
|
|
144
|
+
});
|
|
145
|
+
//if local user started the screenshare then change layout to pinned
|
|
146
|
+
triggerChangeLayout(true, screenShareUid);
|
|
147
|
+
}
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
return (
|