agora-appbuilder-core 2.3.0-beta.9 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +11 -6
- package/package.json +1 -1
- package/template/Gulpfile.js +121 -83
- package/template/_gitignore +2 -2
- package/template/_package-lock.json +12959 -13248
- package/template/agora-rn-uikit/src/AgoraUIKit.tsx +2 -2
- package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +2 -0
- package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +3 -3
- 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/Controls/LocalControls.tsx +2 -2
- package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +4 -4
- package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +7 -5
- package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +1 -1
- package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +2 -2
- package/template/agora-rn-uikit/src/Rtc/Create.tsx +88 -43
- package/template/agora-rn-uikit/src/Rtc/Join.tsx +13 -4
- package/template/agora-rn-uikit/src/RtcConfigure.tsx +36 -19
- package/template/agora-rn-uikit/src/Utils/permission.ts +17 -6
- package/template/babel.config.js +9 -9
- package/template/bridge/rtc/webNg/RtcEngine.ts +51 -26
- package/template/customization-api/action-library.ts +22 -0
- package/template/{fpe-api/context.ts → customization-api/app-state.ts} +21 -14
- package/template/customization-api/customEvents.ts +9 -0
- package/template/{fpe-api/install.ts → customization-api/customize.ts} +27 -26
- package/template/{fpe-api → customization-api}/index.ts +11 -6
- package/template/{fpe-api/components.ts → customization-api/sub-components.ts} +22 -3
- package/template/{fpe-api → customization-api}/typeDefinition.ts +13 -14
- package/template/customization-api/utils.ts +30 -0
- package/template/{fpe-implementation → customization-implementation}/createHook.ts +0 -0
- package/template/{fpe-implementation/dummyFpe.ts → customization-implementation/dummyConfig.ts} +4 -4
- package/template/customization-implementation/index.ts +4 -0
- package/template/{fpe-api/useFpe.tsx → customization-implementation/useCustomization.tsx} +12 -12
- package/template/{fpe.config.js → customization.config.js} +11 -11
- package/template/electron/main/index.js +42 -35
- package/template/esbuild.rsdk.go +8 -17
- package/template/global.d.ts +4 -3
- package/template/index.rsdk.tsx +13 -5
- package/template/index.wsdk.tsx +21 -5
- package/template/package.json +3 -0
- 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/App.tsx +8 -4
- package/template/src/AppWrapper.tsx +8 -6
- package/template/src/SDKAppWrapper.tsx +28 -21
- package/template/src/app-state/useLocalUserInfo.ts +11 -0
- package/template/src/app-state/useMessages.ts +55 -0
- package/template/src/atoms/PrimaryButton.tsx +2 -2
- package/template/src/atoms/SecondaryButton.tsx +12 -4
- package/template/src/atoms/TextInput.tsx +2 -2
- package/template/src/components/Chat.tsx +22 -11
- package/template/src/components/ChatContext.ts +10 -27
- package/template/src/components/Controls.native.tsx +13 -7
- package/template/src/components/Controls.tsx +15 -24
- package/template/src/components/DeviceConfigure.tsx +4 -3
- package/template/src/components/EventsConfigure.tsx +54 -0
- package/template/src/components/GridVideo.tsx +5 -6
- package/template/src/components/HostControlView.tsx +13 -19
- package/template/src/components/Navbar.tsx +54 -41
- package/template/src/components/NetworkQualityContext.tsx +4 -3
- package/template/src/components/ParticipantsView.tsx +7 -7
- package/template/src/components/PinnedVideo.tsx +3 -4
- package/template/src/components/Precall.native.tsx +3 -3
- package/template/src/components/Precall.tsx +14 -10
- package/template/src/components/RTMConfigure.tsx +61 -219
- package/template/src/components/SettingsView.tsx +6 -3
- package/template/src/components/Share.tsx +24 -18
- package/template/src/components/chat-messages/useChatMessages.tsx +397 -80
- package/template/src/components/chat-notification/useChatNotification.tsx +2 -2
- package/template/src/components/chat-ui/useChatUIControl.tsx +4 -1
- package/template/src/components/common/Logo.tsx +3 -2
- package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
- package/template/src/components/contexts/ScreenShareContext.tsx +3 -1
- package/template/src/components/contexts/VideoMeetingDataContext.tsx +85 -0
- package/template/src/components/contexts/WhiteboardContext.tsx +8 -8
- package/template/src/components/livestream/LiveStreamContext.tsx +88 -74
- package/template/src/components/meeting-info/useMeetingInfo.tsx +26 -19
- package/template/src/components/meeting-info/useSetMeetingInfo.tsx +1 -1
- package/template/src/components/participants/AllAudienceParticipants.tsx +2 -2
- package/template/src/components/participants/AllHostParticipants.tsx +4 -4
- package/template/src/components/participants/MeParticipant.tsx +5 -3
- package/template/src/components/participants/ParticipantName.tsx +2 -2
- package/template/src/components/participants/RemoteParticipants.tsx +9 -7
- package/template/src/components/precall/LocalMute.native.tsx +14 -10
- package/template/src/components/precall/LocalMute.tsx +7 -5
- package/template/src/components/precall/VideoPreview.native.tsx +6 -6
- package/template/src/components/precall/VideoPreview.tsx +3 -3
- package/template/src/components/precall/joinCallBtn.tsx +3 -3
- package/template/src/components/precall/meetingTitle.tsx +3 -1
- package/template/src/components/precall/selectDevice.tsx +2 -2
- package/template/src/components/precall/usePreCall.tsx +1 -1
- package/template/src/components/styles.ts +3 -3
- package/template/src/components/useShareLink.tsx +69 -29
- package/template/src/components/useUserPreference.tsx +16 -15
- package/template/src/components/useWakeLock.tsx +3 -3
- package/template/src/language/i18nTypes.ts +1 -1
- package/template/src/language/index.ts +2 -2
- package/template/src/language/useLanguage.tsx +2 -3
- package/template/src/pages/Authenticate.tsx +3 -2
- package/template/src/pages/Create.tsx +18 -20
- package/template/src/pages/Join.tsx +6 -7
- package/template/src/pages/VideoCall.tsx +74 -66
- package/template/src/pages/create/useCreate.tsx +1 -1
- package/template/src/pages/video-call/CustomUserContextHolder.tsx +14 -6
- package/template/src/pages/video-call/DefaultLayouts.ts +8 -8
- package/template/src/pages/video-call/{NameWithMicStatus.tsx → NameWithMicIcon.tsx} +8 -1
- package/template/src/pages/video-call/RenderComponent.tsx +7 -10
- package/template/src/pages/video-call/VideoCallScreen.tsx +31 -22
- package/template/src/pages/video-call/VideoComponent.tsx +13 -15
- package/template/src/pages/video-call/VideoRenderer.tsx +6 -6
- package/template/src/pages/video-call/useLayoutsData.ts +23 -0
- package/template/src/rtm/RTMEngine.ts +13 -0
- package/template/src/rtm-events/EventUtils.ts +20 -20
- package/template/src/rtm-events/EventsQueue.ts +9 -3
- package/template/src/rtm-events/constants.ts +5 -0
- package/template/src/rtm-events/index.tsx +1 -3
- package/template/src/rtm-events-api/Events.ts +255 -0
- package/template/src/rtm-events-api/index.tsx +6 -0
- package/template/src/rtm-events-api/types.ts +22 -0
- package/template/src/subComponents/ChatBubble.tsx +24 -8
- package/template/src/subComponents/ChatContainer.tsx +24 -15
- package/template/src/subComponents/ChatInput.tsx +56 -42
- package/template/src/subComponents/LanguageSelector.tsx +2 -2
- package/template/src/subComponents/LayoutIconDropdown.native.tsx +5 -5
- package/template/src/subComponents/LayoutIconDropdown.tsx +7 -7
- package/template/src/subComponents/LocalAudioMute.tsx +3 -4
- package/template/src/subComponents/LocalEndCall.tsx +3 -6
- package/template/src/subComponents/LocalSwitchCamera.tsx +3 -4
- package/template/src/subComponents/LocalVideoMute.tsx +3 -3
- package/template/src/subComponents/NetworkQualityPill.tsx +8 -9
- package/template/src/subComponents/OpenInNativeButton.tsx +2 -3
- package/template/src/subComponents/RemoteAudioMute.tsx +5 -11
- package/template/src/subComponents/RemoteEndCall.tsx +3 -10
- package/template/src/subComponents/RemoteVideoMute.tsx +3 -10
- package/template/src/subComponents/SelectDevice.tsx +4 -3
- package/template/src/subComponents/SelectOAuth.tsx +3 -2
- package/template/src/subComponents/SidePanelButtons.ts +6 -5
- package/template/src/subComponents/TextWithTooltip.tsx +6 -2
- package/template/src/subComponents/{toastConfig.tsx → ToastConfig.tsx} +2 -2
- package/template/src/subComponents/chat/ChatParticipants.tsx +6 -5
- package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +2 -2
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +4 -3
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +2 -2
- package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +2 -4
- package/template/src/subComponents/livestream/index.ts +2 -2
- package/template/src/subComponents/recording/useRecording.tsx +47 -24
- package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +11 -5
- package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +46 -34
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +98 -39
- package/template/src/subComponents/screenshare/useScreenshare.tsx +1 -1
- package/template/src/utils/SdkEvents.ts +9 -46
- package/template/src/utils/common.tsx +41 -9
- package/template/src/utils/getUniqueID.ts +5 -0
- package/template/src/utils/isMobileOrTablet.native.ts +6 -2
- package/template/src/utils/isMobileOrTablet.ts +25 -8
- package/template/src/utils/useButtonTemplate.tsx +1 -1
- package/template/src/utils/useCreateMeeting.ts +24 -10
- package/template/src/utils/useGetMeetingPhrase.ts +11 -8
- package/template/src/utils/{IsAttendeeUser.ts → useIsAttendee.ts} +12 -16
- package/template/src/utils/{isAudioEnabled.ts → useIsAudioEnabled.ts} +8 -4
- package/template/src/utils/{isHostUser.ts → useIsHost.ts} +17 -16
- package/template/src/utils/{isPSTNUser.ts → useIsPSTN.ts} +4 -3
- package/template/src/utils/{isScreenShareUser.ts → useIsScreenShare.ts} +1 -1
- package/template/src/utils/{isVideoEnabled.ts → useIsVideoEnabled.ts} +9 -6
- package/template/src/utils/useJoinMeeting.ts +11 -7
- package/template/src/utils/useLayout.tsx +8 -6
- package/template/src/utils/useMutePSTN.ts +5 -3
- package/template/src/utils/useMuteToggleLocal.ts +6 -4
- package/template/src/utils/useRemoteEndCall.ts +14 -10
- package/template/src/utils/useRemoteMute.ts +45 -20
- package/template/src/utils/useSidePanel.tsx +4 -1
- package/template/src/utils/useString.ts +2 -2
- package/template/src/utils/useUserName.ts +14 -0
- package/template/tsconfig_fpeApi.json +8 -9
- package/template/tsconfig_rsdk_index.json +8 -9
- package/template/tsconfig_wsdk_index.json +8 -9
- package/template/webpack.commons.js +9 -9
- package/template/webpack.rsdk.config.js +4 -2
- package/template/webpack.ts.config.js +6 -6
- package/template/webpack.wsdk.config.js +2 -1
- package/template/fpe-api/fpeEvents.ts +0 -9
- package/template/fpe-api/utils.ts +0 -61
- package/template/fpe-implementation/index.ts +0 -1
- package/template/fpe-todo.txt +0 -14
- package/template/src/components/RTMEvents.tsx +0 -84
- package/template/src/custom-events/CustomEvents.ts +0 -238
- package/template/src/custom-events/index.tsx +0 -4
- package/template/src/custom-events/types.ts +0 -51
- package/template/src/pages/video-call/CustomLayout.ts +0 -17
- package/template/src/rtm-events/types.ts +0 -7
- package/template/src/utils/getMeetingInvite.ts +0 -53
- package/template/src/utils/useGroupMessages.ts +0 -24
- package/template/src/utils/useNavParams.ts +0 -6
- package/template/src/utils/useNavigateTo.ts +0 -8
- package/template/src/utils/usePrivateMessages.ts +0 -33
- package/template/src/utils/useSendControlMessage.ts +0 -51
- package/template/src/utils/useSendMessage.ts +0 -40
- package/template/src/utils/useSetUnreadMessageCount.ts +0 -43
- package/template/src/utils/useUnreadMessageCount.ts +0 -50
- package/template/src/utils/useUserList.ts +0 -26
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
information visit https://appbuilder.agora.io.
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
12
|
+
import {EventSource} from '../rtm-events-api/types';
|
|
13
13
|
type TListener = <T>(t: T) => void;
|
|
14
14
|
type TListenerMetaData = {once: boolean; listener: TListener};
|
|
15
15
|
type TEventList = Map<string, TListenerMetaData[]>;
|
|
16
|
-
type TEvents = Record<
|
|
16
|
+
type TEvents = Record<EventSource, TEventList> | Record<string, never>;
|
|
17
17
|
|
|
18
18
|
const EventUtils = (function () {
|
|
19
19
|
'use strict';
|
|
@@ -52,7 +52,7 @@ const EventUtils = (function () {
|
|
|
52
52
|
*/
|
|
53
53
|
const _getListeners = function (
|
|
54
54
|
evt: string,
|
|
55
|
-
source:
|
|
55
|
+
source: EventSource,
|
|
56
56
|
): TListenerMetaData[] | [] {
|
|
57
57
|
let response: TListenerMetaData[] | [];
|
|
58
58
|
if (_events.hasOwnProperty(source)) {
|
|
@@ -75,14 +75,14 @@ const EventUtils = (function () {
|
|
|
75
75
|
* This is mainly for internal use but others may find it useful.
|
|
76
76
|
*
|
|
77
77
|
* @param {String} evt Name of the event to return the listeners from.
|
|
78
|
-
* @param {
|
|
78
|
+
* @param {EventSource} source Name of the bucket to search events from
|
|
79
79
|
* @return {Object} All listener functions for an event in an object.
|
|
80
80
|
* @api private
|
|
81
81
|
* @example : {evt-name: [{once: false, listener: f}, {once: false, listener: f}...so on and so forth]
|
|
82
82
|
*/
|
|
83
83
|
const _getListenersAsObject = function (
|
|
84
84
|
evt: string,
|
|
85
|
-
source:
|
|
85
|
+
source: EventSource,
|
|
86
86
|
): object {
|
|
87
87
|
const listeners = _getListeners(evt, source);
|
|
88
88
|
let response: any;
|
|
@@ -114,7 +114,7 @@ const EventUtils = (function () {
|
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
return {
|
|
117
|
-
getEvents(source:
|
|
117
|
+
getEvents(source: EventSource): TEvents | {} {
|
|
118
118
|
return _events[source] || (_events[source] = new Map());
|
|
119
119
|
},
|
|
120
120
|
/**
|
|
@@ -123,10 +123,10 @@ const EventUtils = (function () {
|
|
|
123
123
|
*
|
|
124
124
|
* @param {String} evt Name of the event to attach the listener to.
|
|
125
125
|
* @param {Function} listener Method to be called when the event is emitted.
|
|
126
|
-
* @param {
|
|
126
|
+
* @param {EventSource} source Name of the bucket to search events from
|
|
127
127
|
* @return {Object} Current instance of EventUtils
|
|
128
128
|
*/
|
|
129
|
-
addListener(evt: string, listener: any, source:
|
|
129
|
+
addListener(evt: string, listener: any, source: EventSource): object {
|
|
130
130
|
if (!_isValidListener(listener)) {
|
|
131
131
|
throw new Error('Listener must be a function');
|
|
132
132
|
}
|
|
@@ -156,13 +156,13 @@ const EventUtils = (function () {
|
|
|
156
156
|
*
|
|
157
157
|
* @param {String} evt Name of the event to remove the listener from.
|
|
158
158
|
* @param {Function} listenerToRemove Method to remove from the event.
|
|
159
|
-
* @param {
|
|
159
|
+
* @param {EventSource} source Name of the bucket to search events from
|
|
160
160
|
* @return {Object} Current instance of EventUtils for chaining.
|
|
161
161
|
*/
|
|
162
162
|
removeListener(
|
|
163
163
|
evt: string,
|
|
164
164
|
listenerToRemove: TListener,
|
|
165
|
-
source:
|
|
165
|
+
source: EventSource,
|
|
166
166
|
): Object {
|
|
167
167
|
let listeners = _getListenersAsObject(evt, source);
|
|
168
168
|
for (let key in listeners) {
|
|
@@ -182,10 +182,10 @@ const EventUtils = (function () {
|
|
|
182
182
|
* That means every event will be emptied.
|
|
183
183
|
*
|
|
184
184
|
* @param {String} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed.
|
|
185
|
-
* @param {
|
|
185
|
+
* @param {EventSource} source Name of the bucket to search events from
|
|
186
186
|
* @return {Object} Current instance of EventUtils
|
|
187
187
|
*/
|
|
188
|
-
removeAllListeners(evt: string, source:
|
|
188
|
+
removeAllListeners(evt: string, source: EventSource): object {
|
|
189
189
|
let type = typeof evt;
|
|
190
190
|
let events = this.getEvents(source);
|
|
191
191
|
if (type === 'string') {
|
|
@@ -203,7 +203,7 @@ const EventUtils = (function () {
|
|
|
203
203
|
* @param {source} source source Name of the bucket to search events from
|
|
204
204
|
* @return {Object} Current instance of EventUtils
|
|
205
205
|
*/
|
|
206
|
-
removeAll(source:
|
|
206
|
+
removeAll(source: EventSource): object {
|
|
207
207
|
_events[source] = new Map();
|
|
208
208
|
return this;
|
|
209
209
|
},
|
|
@@ -219,11 +219,8 @@ const EventUtils = (function () {
|
|
|
219
219
|
* @param {Array} [args] Optional array of arguments to be passed to each listener.
|
|
220
220
|
* @return {Object} Current instance of EventUtils
|
|
221
221
|
*/
|
|
222
|
-
emitEvent(evt: string, args: any): object {
|
|
223
|
-
let listenersMap = _getListenersAsObject(
|
|
224
|
-
evt,
|
|
225
|
-
args.payload.source || EventSourceEnum.core,
|
|
226
|
-
);
|
|
222
|
+
emitEvent(evt: string, source: EventSource, args: any): object {
|
|
223
|
+
let listenersMap = _getListenersAsObject(evt, source);
|
|
227
224
|
let listeners: TListenerMetaData[];
|
|
228
225
|
let listener: TListenerMetaData;
|
|
229
226
|
for (let key in listenersMap) {
|
|
@@ -235,16 +232,19 @@ const EventUtils = (function () {
|
|
|
235
232
|
listener = listeners[i];
|
|
236
233
|
|
|
237
234
|
if (listener.once === true) {
|
|
238
|
-
this.removeListener(evt,
|
|
235
|
+
this.removeListener(evt, source, listener.listener);
|
|
239
236
|
}
|
|
240
237
|
|
|
241
|
-
const newargs = [].slice.call(arguments,
|
|
238
|
+
const newargs = [].slice.call(arguments, 2);
|
|
242
239
|
listener.listener.apply(this, newargs || []);
|
|
243
240
|
}
|
|
244
241
|
}
|
|
245
242
|
}
|
|
246
243
|
return this;
|
|
247
244
|
},
|
|
245
|
+
clear() {
|
|
246
|
+
_events = {};
|
|
247
|
+
},
|
|
248
248
|
// 1. To add multiple listeners
|
|
249
249
|
// addListeners(evt: string, listeners: any) {
|
|
250
250
|
// if (Array.isArray(listeners)) {
|
|
@@ -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
|
})();
|
|
@@ -28,6 +28,9 @@ const PUBLIC_CHAT_MESSAGE = 'PUBLIC_CHAT_MESSAGE';
|
|
|
28
28
|
const PRIVATE_CHAT_MESSAGE = 'PRIVATE_CHAT_MESSAGE';
|
|
29
29
|
// 4. NAME ATTRIBUTE
|
|
30
30
|
const NAME_ATTRIBUTE = 'name';
|
|
31
|
+
// 5. VIDEO MEETING ROLE
|
|
32
|
+
const VIDEO_MEETING_HOST = 'VIDEO_MEETING_HOST';
|
|
33
|
+
const VIDEO_MEETING_ATTENDEE = 'VIDEO_MEETING_ATTENDEE';
|
|
31
34
|
const EventNames = {
|
|
32
35
|
RECORDING_ATTRIBUTE,
|
|
33
36
|
RAISED_ATTRIBUTE,
|
|
@@ -36,6 +39,8 @@ const EventNames = {
|
|
|
36
39
|
PRIVATE_CHAT_MESSAGE,
|
|
37
40
|
SCREENSHARE_ATTRIBUTE,
|
|
38
41
|
NAME_ATTRIBUTE,
|
|
42
|
+
VIDEO_MEETING_HOST,
|
|
43
|
+
VIDEO_MEETING_ATTENDEE,
|
|
39
44
|
};
|
|
40
45
|
/** ***** EVENT NAMES ENDS ***** */
|
|
41
46
|
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/*
|
|
2
|
+
********************************************
|
|
3
|
+
Copyright © 2022 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
|
+
|
|
13
|
+
('use strict');
|
|
14
|
+
import RtmEngine from 'agora-react-native-rtm';
|
|
15
|
+
import RTMEngine from '../rtm/RTMEngine';
|
|
16
|
+
import {EventUtils} from '../rtm-events';
|
|
17
|
+
import {
|
|
18
|
+
ReceiverUid,
|
|
19
|
+
EventCallback,
|
|
20
|
+
EventSource,
|
|
21
|
+
EventPersistLevel,
|
|
22
|
+
} from './types';
|
|
23
|
+
import {adjustUID} from '../rtm/utils';
|
|
24
|
+
|
|
25
|
+
class Events {
|
|
26
|
+
private source: EventSource = EventSource.core;
|
|
27
|
+
|
|
28
|
+
constructor(source?: EventSource) {
|
|
29
|
+
if (source) {
|
|
30
|
+
this.source = source;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Persists the data in the local attributes of the user
|
|
36
|
+
*
|
|
37
|
+
* @param {String} evt to be stored in rtm Attribute key
|
|
38
|
+
* @param {String} payload to be stored in rtm Attribute value
|
|
39
|
+
* @api private
|
|
40
|
+
*/
|
|
41
|
+
private _persist = async (evt: string, payload: string) => {
|
|
42
|
+
const rtmEngine: RtmEngine = RTMEngine.getInstance().engine;
|
|
43
|
+
try {
|
|
44
|
+
const rtmAttribute = {key: evt, value: payload};
|
|
45
|
+
// Step 1: Call RTM API to update local attributes
|
|
46
|
+
await rtmEngine.addOrUpdateLocalUserAttributes([rtmAttribute]);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.log(
|
|
49
|
+
'CUSTOM_EVENT_API error occured while updating the value ',
|
|
50
|
+
error,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* event type validator.
|
|
57
|
+
*
|
|
58
|
+
* @api private
|
|
59
|
+
* @returns {boolean}
|
|
60
|
+
*/
|
|
61
|
+
private _validateEvt = (evt: string): boolean => {
|
|
62
|
+
if (typeof evt !== 'string') {
|
|
63
|
+
throw Error(
|
|
64
|
+
`CUSTOM_EVENT_API Event name cannot be of type ${typeof evt}`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (evt.trim() == '') {
|
|
68
|
+
throw Error(`CUSTOM_EVENT_API Name or function cannot be empty`);
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* event listener validator
|
|
75
|
+
*
|
|
76
|
+
* @api private
|
|
77
|
+
* @returns {boolean}
|
|
78
|
+
*/
|
|
79
|
+
private _validateListener = (listener: EventCallback): boolean => {
|
|
80
|
+
if (typeof listener !== 'function') {
|
|
81
|
+
throw Error(
|
|
82
|
+
`CUSTOM_EVENT_API Function cannot be of type ${typeof listener}`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
return true;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Sets the local attribute of user if persist level is 2 or 3.
|
|
90
|
+
* If param 'toUid' is not provided, message is sent in the channel.
|
|
91
|
+
* If param 'toUid' is provided message is sent to that individual.
|
|
92
|
+
* If param 'toUid' is an array of uids is provided then message is sent to all the individual uids in loop.
|
|
93
|
+
*
|
|
94
|
+
* @param {Object} rtmPayload payload to be sent across
|
|
95
|
+
* @param {ReceiverUid} toUid uid or uids[] of user
|
|
96
|
+
* @api private
|
|
97
|
+
*/
|
|
98
|
+
private _send = async (rtmPayload: any, toUid?: ReceiverUid) => {
|
|
99
|
+
const to = typeof toUid == 'string' ? parseInt(toUid) : toUid;
|
|
100
|
+
const rtmEngine: RtmEngine = RTMEngine.getInstance().engine;
|
|
101
|
+
|
|
102
|
+
const text = JSON.stringify(rtmPayload);
|
|
103
|
+
// Case 1: send to channel
|
|
104
|
+
if (
|
|
105
|
+
typeof to === 'undefined' ||
|
|
106
|
+
(typeof to === 'number' && to <= 0) ||
|
|
107
|
+
(Array.isArray(to) && to?.length === 0)
|
|
108
|
+
) {
|
|
109
|
+
console.log('CUSTOM_EVENT_API: case 1 executed');
|
|
110
|
+
try {
|
|
111
|
+
const channelId = RTMEngine.getInstance().channelUid;
|
|
112
|
+
await rtmEngine.sendMessageByChannelId(channelId, text);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
console.log('CUSTOM_EVENT_API: send event case 1 error : ', error);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
// Case 2: send to indivdual
|
|
119
|
+
if (typeof to === 'number' && to !== 0) {
|
|
120
|
+
console.log('CUSTOM_EVENT_API: case 2 executed', to);
|
|
121
|
+
const adjustedUID = adjustUID(to);
|
|
122
|
+
try {
|
|
123
|
+
await rtmEngine.sendMessageToPeer({
|
|
124
|
+
peerId: `${adjustedUID}`,
|
|
125
|
+
offline: false,
|
|
126
|
+
text,
|
|
127
|
+
});
|
|
128
|
+
} catch (error) {
|
|
129
|
+
console.log('CUSTOM_EVENT_API: send event case 2 error : ', error);
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Case 3: send to multiple individuals
|
|
134
|
+
if (typeof to === 'object' && Array.isArray(to)) {
|
|
135
|
+
console.log('CUSTOM_EVENT_API: case 3 executed', to);
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
for (const uid of to) {
|
|
139
|
+
const adjustedUID = adjustUID(uid);
|
|
140
|
+
await rtmEngine.sendMessageToPeer({
|
|
141
|
+
peerId: `${adjustedUID}`,
|
|
142
|
+
offline: false,
|
|
143
|
+
text,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
} catch (error) {
|
|
147
|
+
console.log('CUSTOM_EVENT_API: send event case 3 error : ', error);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Listen on a new event by eventName and listener.
|
|
155
|
+
* When the specified event happens, the Events API triggers the callback that you pass.
|
|
156
|
+
* The listener will not be added/listened if it is a duplicate.
|
|
157
|
+
*
|
|
158
|
+
* @param {String} eventName Name of the event. It must be a unique string.
|
|
159
|
+
* @param {Function} listener Method to be called when the event is emitted.
|
|
160
|
+
* @returns {Function} Returns function, call it and this listener will be removed from event
|
|
161
|
+
* @api public
|
|
162
|
+
*/
|
|
163
|
+
on = (eventName: string, listener: EventCallback): Function => {
|
|
164
|
+
try {
|
|
165
|
+
if (!this._validateEvt(eventName) || !this._validateListener(listener))
|
|
166
|
+
return;
|
|
167
|
+
EventUtils.addListener(eventName, listener, this.source);
|
|
168
|
+
return () => {
|
|
169
|
+
EventUtils.removeListener(eventName, listener, this.source);
|
|
170
|
+
};
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.log('CUSTOM_EVENT_API on error: ', error);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Listen off an event by eventName and listener
|
|
178
|
+
* or listen off events by eventName, when if only eventName argument is passed.
|
|
179
|
+
* or listen off all events, when if no arguments are passed.
|
|
180
|
+
*
|
|
181
|
+
* @param {String} eventName Name of the event to remove the listener from.
|
|
182
|
+
* @param {Function} listener Listener to remove from the event.
|
|
183
|
+
* @api public
|
|
184
|
+
*/
|
|
185
|
+
off = (eventName?: string, listener?: EventCallback) => {
|
|
186
|
+
try {
|
|
187
|
+
if (listener) {
|
|
188
|
+
if (this._validateListener(listener) && this._validateEvt(eventName)) {
|
|
189
|
+
// listen off an event by eventName and listener
|
|
190
|
+
EventUtils.removeListener(eventName, listener, this.source);
|
|
191
|
+
}
|
|
192
|
+
} else if (eventName) {
|
|
193
|
+
// listen off events by name, when if only name is passed.
|
|
194
|
+
if (this._validateEvt(eventName)) {
|
|
195
|
+
EventUtils.removeAllListeners(eventName, this.source);
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
// listen off all events, that means every event will be emptied.
|
|
199
|
+
EventUtils.removeAll(this.source);
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.log('CUSTOM_EVENT_API off error: ', error);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* This method sends p2p or channel message depending upon the 'receiver' value.
|
|
208
|
+
* - If 'receiver' is provided this method sends p2p message.
|
|
209
|
+
* - If 'receiver' is empty this method sends channel message.
|
|
210
|
+
*
|
|
211
|
+
*
|
|
212
|
+
* @param {String} eventName Name of the event to send.
|
|
213
|
+
* @param {String} payload (optional) Additional data to be sent along with the event.
|
|
214
|
+
* @param {Enum} persistLevel (optional) set different levels of persistance. Default value is Level 1
|
|
215
|
+
* @param {ReceiverUid} receiver (optional) uid or uid array. Default mode sends message in channel.
|
|
216
|
+
* @api public
|
|
217
|
+
* */
|
|
218
|
+
send = async (
|
|
219
|
+
eventName: string = '',
|
|
220
|
+
payload: string = '',
|
|
221
|
+
persistLevel: EventPersistLevel = EventPersistLevel.LEVEL1,
|
|
222
|
+
receiver: ReceiverUid = -1,
|
|
223
|
+
) => {
|
|
224
|
+
if (!this._validateEvt(eventName)) return;
|
|
225
|
+
|
|
226
|
+
const persistValue = JSON.stringify({
|
|
227
|
+
payload,
|
|
228
|
+
persistLevel,
|
|
229
|
+
source: this.source,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const rtmPayload = {
|
|
233
|
+
evt: eventName,
|
|
234
|
+
value: persistValue,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
if (
|
|
238
|
+
persistLevel === EventPersistLevel.LEVEL2 ||
|
|
239
|
+
persistLevel === EventPersistLevel.LEVEL3
|
|
240
|
+
) {
|
|
241
|
+
try {
|
|
242
|
+
await this._persist(eventName, persistValue);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.log('CUSTOM_EVENT_API persist error: ', error);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
await this._send(rtmPayload, receiver);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.log('CUSTOM_EVENT_API: sending failed. ', error);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export default Events;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {UidType} from '../../agora-rn-uikit';
|
|
2
|
+
|
|
3
|
+
export type ReceiverUid = UidType | UidType[];
|
|
4
|
+
|
|
5
|
+
export type EventPayload = string | Record<string, never>;
|
|
6
|
+
|
|
7
|
+
export enum EventSource {
|
|
8
|
+
core = 'core',
|
|
9
|
+
fpe = 'fpe',
|
|
10
|
+
}
|
|
11
|
+
export enum EventPersistLevel {
|
|
12
|
+
'LEVEL1' = 1,
|
|
13
|
+
'LEVEL2',
|
|
14
|
+
'LEVEL3',
|
|
15
|
+
}
|
|
16
|
+
interface EventCallbackPayload {
|
|
17
|
+
payload: string;
|
|
18
|
+
persistLevel: EventPersistLevel;
|
|
19
|
+
sender: UidType;
|
|
20
|
+
ts: number;
|
|
21
|
+
}
|
|
22
|
+
export type EventCallback = (args: EventCallbackPayload) => void;
|
|
@@ -15,19 +15,27 @@ import Hyperlink from 'react-native-hyperlink';
|
|
|
15
15
|
import {useString} from '../utils/useString';
|
|
16
16
|
import {ChatBubbleProps} from '../components/ChatContext';
|
|
17
17
|
import ColorContext from '../components/ColorContext';
|
|
18
|
-
import {
|
|
19
|
-
import
|
|
18
|
+
import {isWebInternal} from '../utils/common';
|
|
19
|
+
import {useRender} from 'customization-api';
|
|
20
20
|
|
|
21
21
|
const ChatBubble = (props: ChatBubbleProps) => {
|
|
22
|
-
const {renderList} =
|
|
22
|
+
const {renderList} = useRender();
|
|
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
|
-
if (
|
|
38
|
+
if (isWebInternal()) {
|
|
31
39
|
window.open(url, '_blank');
|
|
32
40
|
} else {
|
|
33
41
|
Linking.openURL(url);
|
|
@@ -37,7 +45,15 @@ const ChatBubble = (props: ChatBubbleProps) => {
|
|
|
37
45
|
//const remoteUserDefaultLabel = useString('remoteUserDefaultLabel')();
|
|
38
46
|
const remoteUserDefaultLabel = 'User';
|
|
39
47
|
return props?.render ? (
|
|
40
|
-
props.render(
|
|
48
|
+
props.render(
|
|
49
|
+
isLocal,
|
|
50
|
+
message,
|
|
51
|
+
createdTimestamp,
|
|
52
|
+
uid,
|
|
53
|
+
msgId,
|
|
54
|
+
isDeleted,
|
|
55
|
+
updatedTimestamp,
|
|
56
|
+
)
|
|
41
57
|
) : (
|
|
42
58
|
<View>
|
|
43
59
|
<View style={isLocal ? style.chatSenderViewLocal : style.chatSenderView}>
|
|
@@ -25,26 +25,24 @@ import {ChatBubbleProps} from '../components/ChatContext';
|
|
|
25
25
|
import {useLocalUid} from '../../agora-rn-uikit';
|
|
26
26
|
import {ImageIcon} from '../../agora-rn-uikit';
|
|
27
27
|
import TextWithTooltip from './TextWithTooltip';
|
|
28
|
-
import {
|
|
29
|
-
import {isValidReactComponent,
|
|
28
|
+
import {useCustomization} from 'customization-implementation';
|
|
29
|
+
import {isValidReactComponent, isWebInternal} from '../utils/common';
|
|
30
30
|
import {useString} from '../utils/useString';
|
|
31
31
|
import {useChatUIControl} from '../components/chat-ui/useChatUIControl';
|
|
32
|
-
import
|
|
33
|
-
import
|
|
34
|
-
import usePrivateMessages from '../utils/usePrivateMessages';
|
|
32
|
+
import {useRender} from 'customization-api';
|
|
33
|
+
import {useChatMessages} from '../components/chat-messages/useChatMessages';
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
36
|
* Chat container is the component which renders all the chat messages
|
|
38
37
|
* It retrieves all the messages from the appropriate stores (Message store an provate message store)
|
|
39
38
|
* and maps it to a ChatBubble
|
|
40
39
|
*/
|
|
41
|
-
const ChatContainer = (props
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const privateMessageStore =
|
|
40
|
+
const ChatContainer = (props?: {
|
|
41
|
+
chatBubble?: React.ComponentType<ChatBubbleProps>;
|
|
42
|
+
}) => {
|
|
43
|
+
const {renderList} = useRender();
|
|
44
|
+
const {messageStore, privateMessageStore} = useChatMessages();
|
|
46
45
|
const {height, width} = useWindowDimensions();
|
|
47
|
-
const {selectPrivate} = props;
|
|
48
46
|
const {
|
|
49
47
|
privateActive,
|
|
50
48
|
selectedChatUserId: selectedUserID,
|
|
@@ -56,7 +54,7 @@ const ChatContainer = (props: any) => {
|
|
|
56
54
|
const remoteUserDefaultLabel = 'User';
|
|
57
55
|
const scrollViewRef = useRef<ScrollView>(null);
|
|
58
56
|
|
|
59
|
-
const {ChatBubbleComponent} =
|
|
57
|
+
const {ChatBubbleComponent} = useCustomization((data) => {
|
|
60
58
|
let components: {
|
|
61
59
|
ChatBubbleComponent: React.ComponentType<ChatBubbleProps>;
|
|
62
60
|
} = {
|
|
@@ -80,6 +78,10 @@ const ChatContainer = (props: any) => {
|
|
|
80
78
|
data?.components?.videoCall?.chat?.chatBubble;
|
|
81
79
|
}
|
|
82
80
|
}
|
|
81
|
+
} else {
|
|
82
|
+
if (props?.chatBubble && isValidReactComponent(props?.chatBubble)) {
|
|
83
|
+
components.ChatBubbleComponent = props?.chatBubble;
|
|
84
|
+
}
|
|
83
85
|
}
|
|
84
86
|
return components;
|
|
85
87
|
});
|
|
@@ -124,9 +126,12 @@ const ChatContainer = (props: any) => {
|
|
|
124
126
|
<ChatBubbleComponent
|
|
125
127
|
isLocal={localUid === message.uid}
|
|
126
128
|
message={message.msg}
|
|
127
|
-
|
|
129
|
+
createdTimestamp={message.createdTimestamp}
|
|
130
|
+
updatedTimestamp={message.updatedTimestamp}
|
|
128
131
|
uid={message.uid}
|
|
129
132
|
key={message.ts}
|
|
133
|
+
msgId={message.msgId}
|
|
134
|
+
isDeleted={message.isDeleted}
|
|
130
135
|
/>
|
|
131
136
|
</>
|
|
132
137
|
))
|
|
@@ -135,9 +140,12 @@ const ChatContainer = (props: any) => {
|
|
|
135
140
|
<ChatBubbleComponent
|
|
136
141
|
isLocal={localUid === message.uid}
|
|
137
142
|
message={message.msg}
|
|
138
|
-
|
|
143
|
+
createdTimestamp={message.createdTimestamp}
|
|
144
|
+
updatedTimestamp={message.updatedTimestamp}
|
|
139
145
|
uid={message.uid}
|
|
140
146
|
key={message.ts}
|
|
147
|
+
msgId={message.msgId}
|
|
148
|
+
isDeleted={message.isDeleted}
|
|
141
149
|
/>
|
|
142
150
|
))
|
|
143
151
|
) : (
|
|
@@ -175,7 +183,7 @@ const style = StyleSheet.create({
|
|
|
175
183
|
alignSelf: 'flex-end',
|
|
176
184
|
},
|
|
177
185
|
name: {
|
|
178
|
-
fontWeight:
|
|
186
|
+
fontWeight: isWebInternal() ? '500' : '700',
|
|
179
187
|
color: $config.PRIMARY_FONT_COLOR,
|
|
180
188
|
textAlign: 'left',
|
|
181
189
|
marginRight: 10,
|
|
@@ -196,4 +204,5 @@ const style = StyleSheet.create({
|
|
|
196
204
|
textAlign: 'center',
|
|
197
205
|
},
|
|
198
206
|
});
|
|
207
|
+
|
|
199
208
|
export default ChatContainer;
|