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.
Files changed (206) hide show
  1. package/Readme.md +11 -6
  2. package/package.json +1 -1
  3. package/template/Gulpfile.js +121 -83
  4. package/template/_gitignore +2 -2
  5. package/template/_package-lock.json +12959 -13248
  6. package/template/agora-rn-uikit/src/AgoraUIKit.tsx +2 -2
  7. package/template/agora-rn-uikit/src/Contexts/PropsContext.tsx +2 -0
  8. package/template/agora-rn-uikit/src/Contexts/RtcContext.tsx +3 -3
  9. package/template/agora-rn-uikit/src/Controls/BtnTemplate.tsx +4 -5
  10. package/template/agora-rn-uikit/src/Controls/ImageIcon.tsx +3 -1
  11. package/template/agora-rn-uikit/src/Controls/LocalControls.tsx +2 -2
  12. package/template/agora-rn-uikit/src/Reducer/LocalMuteAudio.ts +1 -1
  13. package/template/agora-rn-uikit/src/Reducer/LocalMuteVideo.ts +1 -1
  14. package/template/agora-rn-uikit/src/Reducer/RemoteAudioStateChanged.ts +1 -1
  15. package/template/agora-rn-uikit/src/Reducer/RemoteVideoStateChanged.ts +1 -1
  16. package/template/agora-rn-uikit/src/Reducer/UpdateDualStreamMode.ts +4 -4
  17. package/template/agora-rn-uikit/src/Reducer/UserJoined.ts +7 -5
  18. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteAudio.ts +1 -1
  19. package/template/agora-rn-uikit/src/Reducer/UserMuteRemoteVideo.ts +1 -1
  20. package/template/agora-rn-uikit/src/Reducer/UserOffline.ts +2 -2
  21. package/template/agora-rn-uikit/src/Rtc/Create.tsx +88 -43
  22. package/template/agora-rn-uikit/src/Rtc/Join.tsx +13 -4
  23. package/template/agora-rn-uikit/src/RtcConfigure.tsx +36 -19
  24. package/template/agora-rn-uikit/src/Utils/permission.ts +17 -6
  25. package/template/babel.config.js +9 -9
  26. package/template/bridge/rtc/webNg/RtcEngine.ts +51 -26
  27. package/template/customization-api/action-library.ts +22 -0
  28. package/template/{fpe-api/context.ts → customization-api/app-state.ts} +21 -14
  29. package/template/customization-api/customEvents.ts +9 -0
  30. package/template/{fpe-api/install.ts → customization-api/customize.ts} +27 -26
  31. package/template/{fpe-api → customization-api}/index.ts +11 -6
  32. package/template/{fpe-api/components.ts → customization-api/sub-components.ts} +22 -3
  33. package/template/{fpe-api → customization-api}/typeDefinition.ts +13 -14
  34. package/template/customization-api/utils.ts +30 -0
  35. package/template/{fpe-implementation → customization-implementation}/createHook.ts +0 -0
  36. package/template/{fpe-implementation/dummyFpe.ts → customization-implementation/dummyConfig.ts} +4 -4
  37. package/template/customization-implementation/index.ts +4 -0
  38. package/template/{fpe-api/useFpe.tsx → customization-implementation/useCustomization.tsx} +12 -12
  39. package/template/{fpe.config.js → customization.config.js} +11 -11
  40. package/template/electron/main/index.js +42 -35
  41. package/template/esbuild.rsdk.go +8 -17
  42. package/template/global.d.ts +4 -3
  43. package/template/index.rsdk.tsx +13 -5
  44. package/template/index.wsdk.tsx +21 -5
  45. package/template/package.json +3 -0
  46. package/template/react-native-toast-message/src/index.js +3 -7
  47. package/template/react-native-toast-message/src/{index.wsdk.js → index.sdk.tsx} +1 -1
  48. package/template/react-native-toast-message/src/styles.sdk.ts +17 -0
  49. package/template/src/App.tsx +8 -4
  50. package/template/src/AppWrapper.tsx +8 -6
  51. package/template/src/SDKAppWrapper.tsx +28 -21
  52. package/template/src/app-state/useLocalUserInfo.ts +11 -0
  53. package/template/src/app-state/useMessages.ts +55 -0
  54. package/template/src/atoms/PrimaryButton.tsx +2 -2
  55. package/template/src/atoms/SecondaryButton.tsx +12 -4
  56. package/template/src/atoms/TextInput.tsx +2 -2
  57. package/template/src/components/Chat.tsx +22 -11
  58. package/template/src/components/ChatContext.ts +10 -27
  59. package/template/src/components/Controls.native.tsx +13 -7
  60. package/template/src/components/Controls.tsx +15 -24
  61. package/template/src/components/DeviceConfigure.tsx +4 -3
  62. package/template/src/components/EventsConfigure.tsx +54 -0
  63. package/template/src/components/GridVideo.tsx +5 -6
  64. package/template/src/components/HostControlView.tsx +13 -19
  65. package/template/src/components/Navbar.tsx +54 -41
  66. package/template/src/components/NetworkQualityContext.tsx +4 -3
  67. package/template/src/components/ParticipantsView.tsx +7 -7
  68. package/template/src/components/PinnedVideo.tsx +3 -4
  69. package/template/src/components/Precall.native.tsx +3 -3
  70. package/template/src/components/Precall.tsx +14 -10
  71. package/template/src/components/RTMConfigure.tsx +61 -219
  72. package/template/src/components/SettingsView.tsx +6 -3
  73. package/template/src/components/Share.tsx +24 -18
  74. package/template/src/components/chat-messages/useChatMessages.tsx +397 -80
  75. package/template/src/components/chat-notification/useChatNotification.tsx +2 -2
  76. package/template/src/components/chat-ui/useChatUIControl.tsx +4 -1
  77. package/template/src/components/common/Logo.tsx +3 -2
  78. package/template/src/components/contexts/LiveStreamDataContext.tsx +3 -3
  79. package/template/src/components/contexts/ScreenShareContext.tsx +3 -1
  80. package/template/src/components/contexts/VideoMeetingDataContext.tsx +85 -0
  81. package/template/src/components/contexts/WhiteboardContext.tsx +8 -8
  82. package/template/src/components/livestream/LiveStreamContext.tsx +88 -74
  83. package/template/src/components/meeting-info/useMeetingInfo.tsx +26 -19
  84. package/template/src/components/meeting-info/useSetMeetingInfo.tsx +1 -1
  85. package/template/src/components/participants/AllAudienceParticipants.tsx +2 -2
  86. package/template/src/components/participants/AllHostParticipants.tsx +4 -4
  87. package/template/src/components/participants/MeParticipant.tsx +5 -3
  88. package/template/src/components/participants/ParticipantName.tsx +2 -2
  89. package/template/src/components/participants/RemoteParticipants.tsx +9 -7
  90. package/template/src/components/precall/LocalMute.native.tsx +14 -10
  91. package/template/src/components/precall/LocalMute.tsx +7 -5
  92. package/template/src/components/precall/VideoPreview.native.tsx +6 -6
  93. package/template/src/components/precall/VideoPreview.tsx +3 -3
  94. package/template/src/components/precall/joinCallBtn.tsx +3 -3
  95. package/template/src/components/precall/meetingTitle.tsx +3 -1
  96. package/template/src/components/precall/selectDevice.tsx +2 -2
  97. package/template/src/components/precall/usePreCall.tsx +1 -1
  98. package/template/src/components/styles.ts +3 -3
  99. package/template/src/components/useShareLink.tsx +69 -29
  100. package/template/src/components/useUserPreference.tsx +16 -15
  101. package/template/src/components/useWakeLock.tsx +3 -3
  102. package/template/src/language/i18nTypes.ts +1 -1
  103. package/template/src/language/index.ts +2 -2
  104. package/template/src/language/useLanguage.tsx +2 -3
  105. package/template/src/pages/Authenticate.tsx +3 -2
  106. package/template/src/pages/Create.tsx +18 -20
  107. package/template/src/pages/Join.tsx +6 -7
  108. package/template/src/pages/VideoCall.tsx +74 -66
  109. package/template/src/pages/create/useCreate.tsx +1 -1
  110. package/template/src/pages/video-call/CustomUserContextHolder.tsx +14 -6
  111. package/template/src/pages/video-call/DefaultLayouts.ts +8 -8
  112. package/template/src/pages/video-call/{NameWithMicStatus.tsx → NameWithMicIcon.tsx} +8 -1
  113. package/template/src/pages/video-call/RenderComponent.tsx +7 -10
  114. package/template/src/pages/video-call/VideoCallScreen.tsx +31 -22
  115. package/template/src/pages/video-call/VideoComponent.tsx +13 -15
  116. package/template/src/pages/video-call/VideoRenderer.tsx +6 -6
  117. package/template/src/pages/video-call/useLayoutsData.ts +23 -0
  118. package/template/src/rtm/RTMEngine.ts +13 -0
  119. package/template/src/rtm-events/EventUtils.ts +20 -20
  120. package/template/src/rtm-events/EventsQueue.ts +9 -3
  121. package/template/src/rtm-events/constants.ts +5 -0
  122. package/template/src/rtm-events/index.tsx +1 -3
  123. package/template/src/rtm-events-api/Events.ts +255 -0
  124. package/template/src/rtm-events-api/index.tsx +6 -0
  125. package/template/src/rtm-events-api/types.ts +22 -0
  126. package/template/src/subComponents/ChatBubble.tsx +24 -8
  127. package/template/src/subComponents/ChatContainer.tsx +24 -15
  128. package/template/src/subComponents/ChatInput.tsx +56 -42
  129. package/template/src/subComponents/LanguageSelector.tsx +2 -2
  130. package/template/src/subComponents/LayoutIconDropdown.native.tsx +5 -5
  131. package/template/src/subComponents/LayoutIconDropdown.tsx +7 -7
  132. package/template/src/subComponents/LocalAudioMute.tsx +3 -4
  133. package/template/src/subComponents/LocalEndCall.tsx +3 -6
  134. package/template/src/subComponents/LocalSwitchCamera.tsx +3 -4
  135. package/template/src/subComponents/LocalVideoMute.tsx +3 -3
  136. package/template/src/subComponents/NetworkQualityPill.tsx +8 -9
  137. package/template/src/subComponents/OpenInNativeButton.tsx +2 -3
  138. package/template/src/subComponents/RemoteAudioMute.tsx +5 -11
  139. package/template/src/subComponents/RemoteEndCall.tsx +3 -10
  140. package/template/src/subComponents/RemoteVideoMute.tsx +3 -10
  141. package/template/src/subComponents/SelectDevice.tsx +4 -3
  142. package/template/src/subComponents/SelectOAuth.tsx +3 -2
  143. package/template/src/subComponents/SidePanelButtons.ts +6 -5
  144. package/template/src/subComponents/TextWithTooltip.tsx +6 -2
  145. package/template/src/subComponents/{toastConfig.tsx → ToastConfig.tsx} +2 -2
  146. package/template/src/subComponents/chat/ChatParticipants.tsx +6 -5
  147. package/template/src/subComponents/livestream/CurrentLiveStreamRequestsView.tsx +2 -2
  148. package/template/src/subComponents/livestream/controls/RemoteLiveStreamApprovedRequestRecall.tsx +4 -3
  149. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestApprove.tsx +2 -2
  150. package/template/src/subComponents/livestream/controls/RemoteLiveStreamRequestReject.tsx +2 -4
  151. package/template/src/subComponents/livestream/index.ts +2 -2
  152. package/template/src/subComponents/recording/useRecording.tsx +47 -24
  153. package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +11 -5
  154. package/template/src/subComponents/screenshare/ScreenshareConfigure.native.tsx +46 -34
  155. package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +98 -39
  156. package/template/src/subComponents/screenshare/useScreenshare.tsx +1 -1
  157. package/template/src/utils/SdkEvents.ts +9 -46
  158. package/template/src/utils/common.tsx +41 -9
  159. package/template/src/utils/getUniqueID.ts +5 -0
  160. package/template/src/utils/isMobileOrTablet.native.ts +6 -2
  161. package/template/src/utils/isMobileOrTablet.ts +25 -8
  162. package/template/src/utils/useButtonTemplate.tsx +1 -1
  163. package/template/src/utils/useCreateMeeting.ts +24 -10
  164. package/template/src/utils/useGetMeetingPhrase.ts +11 -8
  165. package/template/src/utils/{IsAttendeeUser.ts → useIsAttendee.ts} +12 -16
  166. package/template/src/utils/{isAudioEnabled.ts → useIsAudioEnabled.ts} +8 -4
  167. package/template/src/utils/{isHostUser.ts → useIsHost.ts} +17 -16
  168. package/template/src/utils/{isPSTNUser.ts → useIsPSTN.ts} +4 -3
  169. package/template/src/utils/{isScreenShareUser.ts → useIsScreenShare.ts} +1 -1
  170. package/template/src/utils/{isVideoEnabled.ts → useIsVideoEnabled.ts} +9 -6
  171. package/template/src/utils/useJoinMeeting.ts +11 -7
  172. package/template/src/utils/useLayout.tsx +8 -6
  173. package/template/src/utils/useMutePSTN.ts +5 -3
  174. package/template/src/utils/useMuteToggleLocal.ts +6 -4
  175. package/template/src/utils/useRemoteEndCall.ts +14 -10
  176. package/template/src/utils/useRemoteMute.ts +45 -20
  177. package/template/src/utils/useSidePanel.tsx +4 -1
  178. package/template/src/utils/useString.ts +2 -2
  179. package/template/src/utils/useUserName.ts +14 -0
  180. package/template/tsconfig_fpeApi.json +8 -9
  181. package/template/tsconfig_rsdk_index.json +8 -9
  182. package/template/tsconfig_wsdk_index.json +8 -9
  183. package/template/webpack.commons.js +9 -9
  184. package/template/webpack.rsdk.config.js +4 -2
  185. package/template/webpack.ts.config.js +6 -6
  186. package/template/webpack.wsdk.config.js +2 -1
  187. package/template/fpe-api/fpeEvents.ts +0 -9
  188. package/template/fpe-api/utils.ts +0 -61
  189. package/template/fpe-implementation/index.ts +0 -1
  190. package/template/fpe-todo.txt +0 -14
  191. package/template/src/components/RTMEvents.tsx +0 -84
  192. package/template/src/custom-events/CustomEvents.ts +0 -238
  193. package/template/src/custom-events/index.tsx +0 -4
  194. package/template/src/custom-events/types.ts +0 -51
  195. package/template/src/pages/video-call/CustomLayout.ts +0 -17
  196. package/template/src/rtm-events/types.ts +0 -7
  197. package/template/src/utils/getMeetingInvite.ts +0 -53
  198. package/template/src/utils/useGroupMessages.ts +0 -24
  199. package/template/src/utils/useNavParams.ts +0 -6
  200. package/template/src/utils/useNavigateTo.ts +0 -8
  201. package/template/src/utils/usePrivateMessages.ts +0 -33
  202. package/template/src/utils/useSendControlMessage.ts +0 -51
  203. package/template/src/utils/useSendMessage.ts +0 -40
  204. package/template/src/utils/useSetUnreadMessageCount.ts +0 -43
  205. package/template/src/utils/useUnreadMessageCount.ts +0 -50
  206. 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 {EventSourceEnum} from '../custom-events/types';
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<EventSourceEnum, TEventList> | Record<string, never>;
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: EventSourceEnum,
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 {EventSourceEnum} source Name of the bucket to search events from
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: EventSourceEnum,
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: EventSourceEnum): TEvents | {} {
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 {EventSourceEnum} source Name of the bucket to search events from
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: EventSourceEnum): object {
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 {EventSourceEnum} source Name of the bucket to search events from
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: EventSourceEnum,
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 {EventSourceEnum} source Name of the bucket to search events from
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: EventSourceEnum): object {
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: EventSourceEnum): object {
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, args.payload.source, listener.listener);
235
+ this.removeListener(evt, source, listener.listener);
239
236
  }
240
237
 
241
- const newargs = [].slice.call(arguments, 1);
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.shift();
30
+ return _eventsQueue.pop();
31
31
  },
32
- printQueue() {
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
 
@@ -3,6 +3,4 @@ import EventsQueue from './EventsQueue';
3
3
 
4
4
  export * from './constants';
5
5
 
6
- import {eventMessageType} from './types';
7
-
8
- export {EventUtils, EventsQueue, eventMessageType};
6
+ export {EventUtils, EventsQueue};
@@ -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,6 @@
1
+ import Events from './Events';
2
+
3
+ export * from './types';
4
+
5
+ const events = new Events();
6
+ 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 {isWeb} from '../utils/common';
19
- import useUserList from '../utils/useUserList';
18
+ import {isWebInternal} from '../utils/common';
19
+ import {useRender} from 'customization-api';
20
20
 
21
21
  const ChatBubble = (props: ChatBubbleProps) => {
22
- const {renderList} = useUserList();
22
+ const {renderList} = useRender();
23
23
  const {primaryColor} = useContext(ColorContext);
24
- let {isLocal, message, timestamp, uid} = props;
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(timestamp)).getHours() +
34
+ new Date(parseInt(createdTimestamp)).getHours() +
27
35
  ':' +
28
- new Date(parseInt(timestamp)).getMinutes();
36
+ new Date(parseInt(createdTimestamp)).getMinutes();
29
37
  const handleUrl = (url: string) => {
30
- if (isWeb) {
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(isLocal, message, timestamp, uid)
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 {useFpe} from 'fpe-api';
29
- import {isValidReactComponent, isWeb} from '../utils/common';
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 useUserList from '../utils/useUserList';
33
- import useGroupMessages from '../utils/useGroupMessages';
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: any) => {
42
- const {renderList} = useUserList();
43
- const messageStore = useGroupMessages();
44
- const getPrivateMessage = usePrivateMessages();
45
- const privateMessageStore = getPrivateMessage();
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} = useFpe((data) => {
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
- timestamp={message.ts}
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
- timestamp={message.ts}
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: isWeb ? '500' : '700',
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;