agora-appbuilder-core 2.3.0-beta.2 → 2.3.0-beta.22
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 +11 -6
- package/package.json +2 -2
- package/template/Gulpfile.js +112 -13
- package/template/_package-lock.json +13011 -13288
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +2 -0
- package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +4 -5
- package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +3 -1
- package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +3 -1
- package/template/agora-rn-uikit/src/Rtc/Create.tsx +64 -33
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +11 -2
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +23 -4
- package/template/agora-rn-uikit/src/Utils/permission.ts +17 -6
- package/template/bridge/rtc/webNg/RtcEngine.ts +51 -26
- package/template/esbuild.rsdk.go +20 -6
- package/template/fpe-api/components.ts +15 -0
- package/template/fpe-api/context.ts +2 -3
- package/template/fpe-api/install.ts +19 -9
- package/template/fpe-api/typeDefinition.ts +7 -6
- package/template/fpe-api/utils.ts +32 -25
- package/template/global.d.ts +3 -2
- package/template/index.rsdk.tsx +15 -4
- package/template/index.wsdk.tsx +13 -3
- package/template/package.json +4 -2
- package/template/react-native-toast-message/src/index.js +3 -7
- package/template/react-native-toast-message/src/{index.wsdk.js → index.sdk.tsx} +1 -1
- package/template/react-native-toast-message/src/styles.sdk.ts +17 -0
- package/template/src/SDKAppWrapper.tsx +1 -1
- package/template/src/components/Chat.tsx +23 -5
- package/template/src/components/ChatContext.ts +15 -4
- package/template/src/components/Controls.native.tsx +10 -6
- package/template/src/components/Controls.tsx +6 -4
- package/template/src/components/HostControlView.tsx +5 -3
- package/template/src/components/Navbar.tsx +15 -13
- package/template/src/components/RTMConfigure.tsx +20 -50
- package/template/src/components/chat-messages/useChatMessages.tsx +369 -70
- package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
- package/template/src/components/contexts/ScreenShareContext.tsx +2 -0
- package/template/src/components/livestream/LiveStreamContext.tsx +9 -6
- package/template/src/components/participants/MeParticipant.tsx +5 -3
- package/template/src/components/participants/RemoteParticipants.tsx +9 -7
- package/template/src/components/precall/LocalMute.native.tsx +12 -8
- package/template/src/components/precall/LocalMute.tsx +5 -3
- package/template/src/components/precall/textInput.tsx +1 -1
- package/template/src/components/useShareLink.tsx +37 -39
- package/template/src/components/useUserPreference.tsx +125 -0
- package/template/src/custom-events/CustomEvents.ts +39 -23
- package/template/src/custom-events/types.ts +3 -3
- package/template/src/language/default-labels/videoCallScreenLabels.ts +4 -2
- package/template/src/pages/Create.tsx +10 -3
- package/template/src/pages/Join.tsx +4 -1
- package/template/src/pages/VideoCall.tsx +61 -56
- package/template/src/pages/video-call/CustomUserContextHolder.tsx +13 -5
- package/template/src/pages/video-call/VideoCallScreen.tsx +18 -15
- package/template/src/rtm/RTMEngine.ts +13 -0
- package/template/src/rtm/utils.ts +1 -1
- package/template/src/rtm-events/EventUtils.ts +3 -0
- package/template/src/rtm-events/EventsQueue.ts +9 -3
- package/template/src/rtm-events/constants.ts +3 -1
- package/template/src/subComponents/ChatBubble.tsx +22 -4
- package/template/src/subComponents/ChatContainer.tsx +30 -19
- package/template/src/subComponents/ChatInput.tsx +38 -26
- package/template/src/subComponents/SelectDevice.tsx +1 -1
- package/template/src/subComponents/recording/useRecording.tsx +15 -4
- package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +11 -5
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +35 -26
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +83 -33
- package/template/src/utils/SdkEvents.ts +3 -3
- package/template/src/utils/getMeetingInvite.ts +38 -15
- package/template/src/utils/getUniqueID.ts +5 -0
- package/template/src/utils/useDeleteMessage.ts +36 -0
- package/template/src/utils/useEditMessage.ts +41 -0
- package/template/src/utils/useGetName.ts +2 -3
- package/template/src/utils/useJoinMeeting.ts +22 -14
- package/template/src/utils/useLocalShareScreenUid.ts +19 -0
- package/template/src/utils/useSendMessage.ts +4 -5
- package/template/src/utils/useSetName.ts +2 -4
- package/template/webpack.rsdk.config.js +3 -2
- package/template/webpack.wsdk.config.js +0 -1
|
@@ -52,6 +52,7 @@ import {WhiteboardProvider} from '../components/contexts/WhiteboardContext';
|
|
|
52
52
|
import {useWakeLock} from '../components/useWakeLock';
|
|
53
53
|
import StorageContext from '../components/StorageContext';
|
|
54
54
|
import SDKEvents from '../utils/SdkEvents';
|
|
55
|
+
import {UserPreferenceProvider} from '../components/useUserPreference';
|
|
55
56
|
|
|
56
57
|
enum RnEncryptionEnum {
|
|
57
58
|
/**
|
|
@@ -114,6 +115,7 @@ const VideoCall: React.FC = () => {
|
|
|
114
115
|
: false,
|
|
115
116
|
role: ClientRole.Broadcaster,
|
|
116
117
|
geoFencing: $config.GEO_FENCING,
|
|
118
|
+
audioRoom: $config.AUDIO_ROOM,
|
|
117
119
|
});
|
|
118
120
|
|
|
119
121
|
const useJoin = useJoinMeeting();
|
|
@@ -128,11 +130,11 @@ const VideoCall: React.FC = () => {
|
|
|
128
130
|
}, []);
|
|
129
131
|
|
|
130
132
|
useEffect(() => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
useJoin(phrase)
|
|
134
|
+
.then(() => {})
|
|
135
|
+
.catch((error) => {
|
|
136
|
+
setGlobalErrorMessage(error);
|
|
137
|
+
});
|
|
136
138
|
}, []);
|
|
137
139
|
|
|
138
140
|
const data = useMeetingInfo();
|
|
@@ -158,6 +160,7 @@ const VideoCall: React.FC = () => {
|
|
|
158
160
|
screenShareToken: data.screenShareToken,
|
|
159
161
|
role: data.isHost ? ClientRole.Broadcaster : ClientRole.Audience,
|
|
160
162
|
geoFencing: $config.GEO_FENCING,
|
|
163
|
+
audioRoom: $config.AUDIO_ROOM,
|
|
161
164
|
});
|
|
162
165
|
|
|
163
166
|
// 1. Store the display name from API
|
|
@@ -200,65 +203,67 @@ const VideoCall: React.FC = () => {
|
|
|
200
203
|
<DeviceConfigure>
|
|
201
204
|
<ChatUIControlProvider>
|
|
202
205
|
<ChatNotificationProvider>
|
|
203
|
-
<
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
<SidePanelProvider
|
|
207
|
+
value={{
|
|
208
|
+
sidePanel,
|
|
209
|
+
setSidePanel,
|
|
210
|
+
}}>
|
|
211
|
+
<ChatMessagesProvider>
|
|
209
212
|
<ScreenShareProvider>
|
|
210
213
|
<RtmConfigure
|
|
211
214
|
setRecordingActive={setRecordingActive}
|
|
212
215
|
callActive={callActive}>
|
|
213
|
-
<
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
activeLayoutName,
|
|
217
|
-
setActiveLayoutName,
|
|
218
|
-
}}>
|
|
219
|
-
<RecordingProvider
|
|
216
|
+
<UserPreferenceProvider>
|
|
217
|
+
<WhiteboardProvider>
|
|
218
|
+
<LayoutProvider
|
|
220
219
|
value={{
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
activeLayoutName,
|
|
221
|
+
setActiveLayoutName,
|
|
223
222
|
}}>
|
|
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
|
-
|
|
223
|
+
<RecordingProvider
|
|
224
|
+
value={{
|
|
225
|
+
setRecordingActive,
|
|
226
|
+
isRecordingActive,
|
|
227
|
+
}}>
|
|
228
|
+
<ScreenshareConfigure>
|
|
229
|
+
<LiveStreamContextProvider
|
|
230
|
+
value={{
|
|
231
|
+
setRtcProps,
|
|
232
|
+
rtcProps,
|
|
233
|
+
callActive,
|
|
234
|
+
}}>
|
|
235
|
+
<LiveStreamDataProvider>
|
|
236
|
+
<LocalUserContext
|
|
237
|
+
localUid={rtcProps?.uid || 0}>
|
|
238
|
+
<CustomUserContextHolder>
|
|
239
|
+
<NetworkQualityProvider>
|
|
240
|
+
{callActive ? (
|
|
241
|
+
<VideoCallScreen />
|
|
242
|
+
) : $config.PRECALL ? (
|
|
243
|
+
<PreCallProvider
|
|
244
|
+
value={{
|
|
245
|
+
callActive,
|
|
246
|
+
setCallActive,
|
|
247
|
+
}}>
|
|
248
|
+
<Precall />
|
|
249
|
+
</PreCallProvider>
|
|
250
|
+
) : (
|
|
251
|
+
<></>
|
|
252
|
+
)}
|
|
253
|
+
</NetworkQualityProvider>
|
|
254
|
+
</CustomUserContextHolder>
|
|
255
|
+
</LocalUserContext>
|
|
256
|
+
</LiveStreamDataProvider>
|
|
257
|
+
</LiveStreamContextProvider>
|
|
258
|
+
</ScreenshareConfigure>
|
|
259
|
+
</RecordingProvider>
|
|
260
|
+
</LayoutProvider>
|
|
261
|
+
</WhiteboardProvider>
|
|
262
|
+
</UserPreferenceProvider>
|
|
258
263
|
</RtmConfigure>
|
|
259
264
|
</ScreenShareProvider>
|
|
260
|
-
</
|
|
261
|
-
</
|
|
265
|
+
</ChatMessagesProvider>
|
|
266
|
+
</SidePanelProvider>
|
|
262
267
|
</ChatNotificationProvider>
|
|
263
268
|
</ChatUIControlProvider>
|
|
264
269
|
</DeviceConfigure>
|
|
@@ -2,11 +2,19 @@ import React from 'react';
|
|
|
2
2
|
import {useFpe} from 'fpe-api';
|
|
3
3
|
|
|
4
4
|
const CustomUserContextHolder: React.FC<{children: any}> = (props) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
const useUserContext = useFpe((config) => {
|
|
6
|
+
if (
|
|
7
|
+
config?.components?.videoCall &&
|
|
8
|
+
typeof config?.components?.videoCall === 'object' &&
|
|
9
|
+
config?.components?.videoCall?.useUserContext &&
|
|
10
|
+
typeof config?.components?.videoCall?.useUserContext === 'function'
|
|
11
|
+
) {
|
|
12
|
+
return config?.components?.videoCall?.useUserContext;
|
|
13
|
+
} else {
|
|
14
|
+
return () => {};
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
useUserContext();
|
|
10
18
|
return props.children;
|
|
11
19
|
};
|
|
12
20
|
export default CustomUserContextHolder;
|
|
@@ -95,14 +95,13 @@ const VideoCallScreen = () => {
|
|
|
95
95
|
components.BottombarComponent = data?.components?.videoCall.bottomBar;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// }
|
|
98
|
+
if (
|
|
99
|
+
data?.components?.videoCall.topBar &&
|
|
100
|
+
typeof data?.components?.videoCall.topBar !== 'object' &&
|
|
101
|
+
isValidReactComponent(data?.components?.videoCall.topBar)
|
|
102
|
+
) {
|
|
103
|
+
components.TopbarComponent = data?.components?.videoCall.topBar;
|
|
104
|
+
}
|
|
106
105
|
|
|
107
106
|
if (
|
|
108
107
|
data?.components?.videoCall.participantsPanel &&
|
|
@@ -128,13 +127,17 @@ const VideoCallScreen = () => {
|
|
|
128
127
|
});
|
|
129
128
|
|
|
130
129
|
useEffect(() => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Commenting this code as getDevices API is web only
|
|
132
|
+
* The below code fails on native app
|
|
133
|
+
*/
|
|
134
|
+
// new Promise((res) =>
|
|
135
|
+
// rtc.RtcEngine.getDevices(function (devices: MediaDeviceInfo[]) {
|
|
136
|
+
// res(devices);
|
|
137
|
+
// }),
|
|
138
|
+
// ).then((devices: MediaDeviceInfo[]) => {
|
|
139
|
+
// SDKEvents.emit('join', meetingTitle, devices, isHost);
|
|
140
|
+
// });
|
|
138
141
|
}, []);
|
|
139
142
|
|
|
140
143
|
return VideocallComponent ? (
|
|
@@ -30,6 +30,11 @@ class RTMEngine {
|
|
|
30
30
|
await this.engine.createClient($config.APP_ID);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
private async destroyClientInstance() {
|
|
34
|
+
await this.engine.logout();
|
|
35
|
+
await this.engine.destroyClient();
|
|
36
|
+
}
|
|
37
|
+
|
|
33
38
|
private constructor() {
|
|
34
39
|
if (RTMEngine._instance) {
|
|
35
40
|
return RTMEngine._instance;
|
|
@@ -53,6 +58,14 @@ class RTMEngine {
|
|
|
53
58
|
get channelUid() {
|
|
54
59
|
return this.channelId;
|
|
55
60
|
}
|
|
61
|
+
destroy() {
|
|
62
|
+
try {
|
|
63
|
+
this.destroyClientInstance();
|
|
64
|
+
RTMEngine._instance = null;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.log('Error destroying instance error: ', error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
56
69
|
}
|
|
57
70
|
|
|
58
71
|
export default RTMEngine;
|
|
@@ -30,7 +30,7 @@ export const timeNow = () => new Date().getTime();
|
|
|
30
30
|
export const getMessageTime = (ts?: number): number => {
|
|
31
31
|
if (!ts) return timeNow();
|
|
32
32
|
try {
|
|
33
|
-
const timestamp = new Date(ts).
|
|
33
|
+
const timestamp = new Date(ts).getTime();
|
|
34
34
|
return isNaN(timestamp) ? timeNow() : timestamp;
|
|
35
35
|
} catch (error) {
|
|
36
36
|
return timeNow();
|
|
@@ -27,10 +27,16 @@ const EventsQueue = (function () {
|
|
|
27
27
|
},
|
|
28
28
|
dequeue() {
|
|
29
29
|
if (_eventsQueue.length == 0) return;
|
|
30
|
-
_eventsQueue.
|
|
30
|
+
return _eventsQueue.pop();
|
|
31
31
|
},
|
|
32
|
-
|
|
33
|
-
return _eventsQueue;
|
|
32
|
+
isEmpty() {
|
|
33
|
+
return _eventsQueue.length === 0;
|
|
34
|
+
},
|
|
35
|
+
size() {
|
|
36
|
+
return _eventsQueue.length;
|
|
37
|
+
},
|
|
38
|
+
clear() {
|
|
39
|
+
_eventsQueue = [];
|
|
34
40
|
},
|
|
35
41
|
};
|
|
36
42
|
})();
|
|
@@ -26,7 +26,8 @@ const ROLE_ATTRIBUTE = 'role';
|
|
|
26
26
|
// 3. CHAT MESSAGES
|
|
27
27
|
const PUBLIC_CHAT_MESSAGE = 'PUBLIC_CHAT_MESSAGE';
|
|
28
28
|
const PRIVATE_CHAT_MESSAGE = 'PRIVATE_CHAT_MESSAGE';
|
|
29
|
-
|
|
29
|
+
// 4. NAME ATTRIBUTE
|
|
30
|
+
const NAME_ATTRIBUTE = 'name';
|
|
30
31
|
const EventNames = {
|
|
31
32
|
RECORDING_ATTRIBUTE,
|
|
32
33
|
RAISED_ATTRIBUTE,
|
|
@@ -34,6 +35,7 @@ const EventNames = {
|
|
|
34
35
|
PUBLIC_CHAT_MESSAGE,
|
|
35
36
|
PRIVATE_CHAT_MESSAGE,
|
|
36
37
|
SCREENSHARE_ATTRIBUTE,
|
|
38
|
+
NAME_ATTRIBUTE,
|
|
37
39
|
};
|
|
38
40
|
/** ***** EVENT NAMES ENDS ***** */
|
|
39
41
|
|
|
@@ -21,11 +21,19 @@ import useUserList from '../utils/useUserList';
|
|
|
21
21
|
const ChatBubble = (props: ChatBubbleProps) => {
|
|
22
22
|
const {renderList} = useUserList();
|
|
23
23
|
const {primaryColor} = useContext(ColorContext);
|
|
24
|
-
let {
|
|
24
|
+
let {
|
|
25
|
+
isLocal,
|
|
26
|
+
message,
|
|
27
|
+
createdTimestamp,
|
|
28
|
+
uid,
|
|
29
|
+
isDeleted,
|
|
30
|
+
msgId,
|
|
31
|
+
updatedTimestamp,
|
|
32
|
+
} = props;
|
|
25
33
|
let time =
|
|
26
|
-
new Date(parseInt(
|
|
34
|
+
new Date(parseInt(createdTimestamp)).getHours() +
|
|
27
35
|
':' +
|
|
28
|
-
new Date(parseInt(
|
|
36
|
+
new Date(parseInt(createdTimestamp)).getMinutes();
|
|
29
37
|
const handleUrl = (url: string) => {
|
|
30
38
|
if (isWeb) {
|
|
31
39
|
window.open(url, '_blank');
|
|
@@ -36,7 +44,17 @@ const ChatBubble = (props: ChatBubbleProps) => {
|
|
|
36
44
|
//commented for v1 release
|
|
37
45
|
//const remoteUserDefaultLabel = useString('remoteUserDefaultLabel')();
|
|
38
46
|
const remoteUserDefaultLabel = 'User';
|
|
39
|
-
return (
|
|
47
|
+
return props?.render ? (
|
|
48
|
+
props.render(
|
|
49
|
+
isLocal,
|
|
50
|
+
message,
|
|
51
|
+
createdTimestamp,
|
|
52
|
+
uid,
|
|
53
|
+
msgId,
|
|
54
|
+
isDeleted,
|
|
55
|
+
updatedTimestamp,
|
|
56
|
+
)
|
|
57
|
+
) : (
|
|
40
58
|
<View>
|
|
41
59
|
<View style={isLocal ? style.chatSenderViewLocal : style.chatSenderView}>
|
|
42
60
|
<Text style={isLocal ? style.timestampTextLocal : style.timestampText}>
|
|
@@ -26,7 +26,7 @@ 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 {isWeb} from '../utils/common';
|
|
29
|
+
import {isValidReactComponent, 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';
|
|
@@ -38,13 +38,14 @@ import usePrivateMessages from '../utils/usePrivateMessages';
|
|
|
38
38
|
* It retrieves all the messages from the appropriate stores (Message store an provate message store)
|
|
39
39
|
* and maps it to a ChatBubble
|
|
40
40
|
*/
|
|
41
|
-
const ChatContainer = (props
|
|
41
|
+
const ChatContainer = (props?: {
|
|
42
|
+
chatBubble?: React.ComponentType<ChatBubbleProps>;
|
|
43
|
+
}) => {
|
|
42
44
|
const {renderList} = useUserList();
|
|
43
45
|
const messageStore = useGroupMessages();
|
|
44
46
|
const getPrivateMessage = usePrivateMessages();
|
|
45
47
|
const privateMessageStore = getPrivateMessage();
|
|
46
48
|
const {height, width} = useWindowDimensions();
|
|
47
|
-
const {selectPrivate} = props;
|
|
48
49
|
const {
|
|
49
50
|
privateActive,
|
|
50
51
|
selectedChatUserId: selectedUserID,
|
|
@@ -66,20 +67,24 @@ const ChatContainer = (props: any) => {
|
|
|
66
67
|
data?.components?.videoCall &&
|
|
67
68
|
typeof data?.components?.videoCall === 'object'
|
|
68
69
|
) {
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
70
|
+
//commented for v1 release
|
|
71
|
+
if (
|
|
72
|
+
data?.components?.videoCall?.chat &&
|
|
73
|
+
typeof data?.components?.videoCall?.chat === 'object'
|
|
74
|
+
) {
|
|
75
|
+
if (
|
|
76
|
+
data?.components?.videoCall?.chat?.chatBubble &&
|
|
77
|
+
typeof data?.components?.videoCall?.chat?.chatBubble !== 'object' &&
|
|
78
|
+
isValidReactComponent(data?.components?.videoCall?.chat?.chatBubble)
|
|
79
|
+
) {
|
|
80
|
+
components.ChatBubbleComponent =
|
|
81
|
+
data?.components?.videoCall?.chat?.chatBubble;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
if (props?.chatBubble && isValidReactComponent(props?.chatBubble)) {
|
|
86
|
+
components.ChatBubbleComponent = props?.chatBubble;
|
|
87
|
+
}
|
|
83
88
|
}
|
|
84
89
|
return components;
|
|
85
90
|
});
|
|
@@ -124,9 +129,12 @@ const ChatContainer = (props: any) => {
|
|
|
124
129
|
<ChatBubbleComponent
|
|
125
130
|
isLocal={localUid === message.uid}
|
|
126
131
|
message={message.msg}
|
|
127
|
-
|
|
132
|
+
createdTimestamp={message.createdTimestamp}
|
|
133
|
+
updatedTimestamp={message.updatedTimestamp}
|
|
128
134
|
uid={message.uid}
|
|
129
135
|
key={message.ts}
|
|
136
|
+
msgId={message.msgId}
|
|
137
|
+
isDeleted={message.isDeleted}
|
|
130
138
|
/>
|
|
131
139
|
</>
|
|
132
140
|
))
|
|
@@ -135,9 +143,12 @@ const ChatContainer = (props: any) => {
|
|
|
135
143
|
<ChatBubbleComponent
|
|
136
144
|
isLocal={localUid === message.uid}
|
|
137
145
|
message={message.msg}
|
|
138
|
-
|
|
146
|
+
createdTimestamp={message.createdTimestamp}
|
|
147
|
+
updatedTimestamp={message.updatedTimestamp}
|
|
139
148
|
uid={message.uid}
|
|
140
149
|
key={message.ts}
|
|
150
|
+
msgId={message.msgId}
|
|
151
|
+
isDeleted={message.isDeleted}
|
|
141
152
|
/>
|
|
142
153
|
))
|
|
143
154
|
) : (
|
|
@@ -119,7 +119,10 @@ export const ChatTextInput = (props: ChatTextInputProps) => {
|
|
|
119
119
|
/**
|
|
120
120
|
* Input component for the Chat interface
|
|
121
121
|
*/
|
|
122
|
-
const ChatInput = (
|
|
122
|
+
const ChatInput = (props: {
|
|
123
|
+
chatInput?: React.ComponentType<ChatTextInputProps>;
|
|
124
|
+
chatSendButton?: React.ComponentType<ChatSendButtonProps>;
|
|
125
|
+
}) => {
|
|
123
126
|
const {primaryColor} = useContext(ColorContext);
|
|
124
127
|
const {ChatInputComponent, ChatSendButtonComponent} = useFpe((data) => {
|
|
125
128
|
let components: {
|
|
@@ -133,31 +136,40 @@ const ChatInput = () => {
|
|
|
133
136
|
data?.components?.videoCall &&
|
|
134
137
|
typeof data?.components?.videoCall === 'object'
|
|
135
138
|
) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
139
|
+
if (
|
|
140
|
+
data?.components?.videoCall?.chat &&
|
|
141
|
+
typeof data?.components?.videoCall?.chat === 'object'
|
|
142
|
+
) {
|
|
143
|
+
if (
|
|
144
|
+
data?.components?.videoCall?.chat?.chatInput &&
|
|
145
|
+
typeof data?.components?.videoCall?.chat?.chatInput !== 'object' &&
|
|
146
|
+
isValidReactComponent(data?.components?.videoCall?.chat?.chatInput)
|
|
147
|
+
) {
|
|
148
|
+
components.ChatInputComponent =
|
|
149
|
+
data?.components?.videoCall?.chat?.chatInput;
|
|
150
|
+
}
|
|
151
|
+
if (
|
|
152
|
+
data?.components?.videoCall?.chat?.chatSentButton &&
|
|
153
|
+
typeof data?.components?.videoCall?.chat?.chatSentButton !==
|
|
154
|
+
'object' &&
|
|
155
|
+
isValidReactComponent(
|
|
156
|
+
data?.components?.videoCall?.chat?.chatSentButton,
|
|
157
|
+
)
|
|
158
|
+
) {
|
|
159
|
+
components.ChatSendButtonComponent =
|
|
160
|
+
data?.components?.videoCall?.chat?.chatSentButton;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
if (props?.chatInput && isValidReactComponent(props.chatInput)) {
|
|
165
|
+
components.ChatInputComponent = props.chatInput;
|
|
166
|
+
}
|
|
167
|
+
if (
|
|
168
|
+
props?.chatSendButton &&
|
|
169
|
+
isValidReactComponent(props.chatSendButton)
|
|
170
|
+
) {
|
|
171
|
+
components.ChatSendButtonComponent = props.chatSendButton;
|
|
172
|
+
}
|
|
161
173
|
}
|
|
162
174
|
return components;
|
|
163
175
|
});
|
|
@@ -91,7 +91,7 @@ const RecordingProvider = (props: RecordingProviderProps) => {
|
|
|
91
91
|
//const recordingStartedText = useString<boolean>('recordingNotificationLabel');
|
|
92
92
|
const recordingStartedText = (active: boolean) =>
|
|
93
93
|
active ? 'Recording Started' : 'Recording Stopped';
|
|
94
|
-
const {executePresenterQuery} = useRecordingLayoutQuery();
|
|
94
|
+
const {executePresenterQuery, executeNormalQuery} = useRecordingLayoutQuery();
|
|
95
95
|
const {localUid} = useContext(ChatContext);
|
|
96
96
|
const {screenShareData} = useScreenContext();
|
|
97
97
|
|
|
@@ -156,9 +156,20 @@ const RecordingProvider = (props: RecordingProviderProps) => {
|
|
|
156
156
|
// 2. set the local recording state to true to update the UI
|
|
157
157
|
setRecordingActive(true);
|
|
158
158
|
// 3. set the presenter mode if screen share is active
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
// 3.a Get the most recent screenshare uid
|
|
160
|
+
const sorted = Object.entries(screenShareData)
|
|
161
|
+
.filter((el) => el[1]?.ts && el[1].ts > 0 && el[1]?.isActive)
|
|
162
|
+
.sort((a, b) => b[1].ts - a[1].ts);
|
|
163
|
+
|
|
164
|
+
const activeScreenshareUid = sorted.length > 0 ? sorted[0][0] : 0;
|
|
165
|
+
if (activeScreenshareUid) {
|
|
166
|
+
console.log(
|
|
167
|
+
'screenshare: Executing presenter query for screenuid',
|
|
168
|
+
activeScreenshareUid,
|
|
169
|
+
);
|
|
170
|
+
executePresenterQuery(parseInt(activeScreenshareUid));
|
|
171
|
+
} else {
|
|
172
|
+
executeNormalQuery();
|
|
162
173
|
}
|
|
163
174
|
}
|
|
164
175
|
})
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import {useParams} from '../../components/Router';
|
|
3
3
|
|
|
4
4
|
import {gql, useMutation} from '@apollo/client';
|
|
5
|
-
import {
|
|
5
|
+
import {UidType} from '../../../agora-rn-uikit';
|
|
6
6
|
|
|
7
7
|
const SET_PRESENTER = gql`
|
|
8
8
|
mutation setPresenter($uid: Int!, $passphrase: String!) {
|
|
@@ -19,10 +19,16 @@ const SET_NORMAL = gql`
|
|
|
19
19
|
function useRecordingLayoutQuery() {
|
|
20
20
|
const [setPresenterQuery] = useMutation(SET_PRESENTER);
|
|
21
21
|
const [setNormalQuery] = useMutation(SET_NORMAL);
|
|
22
|
-
const {screenShareUid} = useContext(PropsContext).rtcProps;
|
|
23
22
|
const {phrase} = useParams<any>();
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
/**
|
|
24
|
+
* @param screenShareUid
|
|
25
|
+
* Default : Grid
|
|
26
|
+
* Below query changes the layout to vertical and passed UID is maxed view
|
|
27
|
+
* This should be called only when screenshare is actively going on
|
|
28
|
+
* and we want that as the main view
|
|
29
|
+
* https://docs.agora.io/en/cloud-recording/cloud_recording_layout?platform=RESTful
|
|
30
|
+
*/
|
|
31
|
+
const executePresenterQuery = (screenShareUid: UidType) => {
|
|
26
32
|
setPresenterQuery({
|
|
27
33
|
variables: {
|
|
28
34
|
uid: screenShareUid,
|