agora-appbuilder-core 2.3.0-beta.9 → 3.0.0

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 (205) 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} +16 -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 +8 -0
  53. package/template/src/app-state/useMessages.ts +52 -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 +1 -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 +23 -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/{custom-events/CustomEvents.ts → rtm-events-api/Events.ts} +67 -61
  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 +1 -1
  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 +44 -23
  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 +97 -38
  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 +25 -9
  159. package/template/src/utils/getUniqueID.ts +5 -0
  160. package/template/src/utils/isMobileOrTablet.native.ts +2 -2
  161. package/template/src/utils/isMobileOrTablet.ts +21 -8
  162. package/template/src/utils/useButtonTemplate.tsx +1 -1
  163. package/template/src/utils/useCreateMeeting.ts +21 -10
  164. package/template/src/utils/useGetMeetingPhrase.ts +11 -8
  165. package/template/src/utils/{IsAttendeeUser.ts → useIsAttendee.ts} +3 -1
  166. package/template/src/utils/{isAudioEnabled.ts → useIsAudioEnabled.ts} +4 -4
  167. package/template/src/utils/{isHostUser.ts → useIsHost.ts} +13 -16
  168. package/template/src/utils/{isPSTNUser.ts → useIsPSTN.ts} +2 -2
  169. package/template/src/utils/{isScreenShareUser.ts → useIsScreenShare.ts} +0 -0
  170. package/template/src/utils/{isVideoEnabled.ts → useIsVideoEnabled.ts} +5 -6
  171. package/template/src/utils/useJoinMeeting.ts +8 -6
  172. package/template/src/utils/useLayout.tsx +5 -5
  173. package/template/src/utils/useMutePSTN.ts +5 -3
  174. package/template/src/utils/useMuteToggleLocal.ts +3 -4
  175. package/template/src/utils/useRemoteEndCall.ts +11 -10
  176. package/template/src/utils/useRemoteMute.ts +42 -20
  177. package/template/src/utils/useSidePanel.tsx +1 -1
  178. package/template/src/utils/useString.ts +2 -2
  179. package/template/src/utils/useUserName.ts +11 -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/index.tsx +0 -4
  193. package/template/src/custom-events/types.ts +0 -51
  194. package/template/src/pages/video-call/CustomLayout.ts +0 -17
  195. package/template/src/rtm-events/types.ts +0 -7
  196. package/template/src/utils/getMeetingInvite.ts +0 -53
  197. package/template/src/utils/useGroupMessages.ts +0 -24
  198. package/template/src/utils/useNavParams.ts +0 -6
  199. package/template/src/utils/useNavigateTo.ts +0 -8
  200. package/template/src/utils/usePrivateMessages.ts +0 -33
  201. package/template/src/utils/useSendControlMessage.ts +0 -51
  202. package/template/src/utils/useSendMessage.ts +0 -40
  203. package/template/src/utils/useSetUnreadMessageCount.ts +0 -43
  204. package/template/src/utils/useUnreadMessageCount.ts +0 -50
  205. package/template/src/utils/useUserList.ts +0 -26
@@ -9,51 +9,78 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import {createHook} from 'fpe-implementation';
12
+ import {createHook} from 'customization-implementation';
13
13
  import React, {useState, useEffect, useRef} from 'react';
14
- import {useRenderContext} from 'fpe-api';
14
+ import {useRender} from 'customization-api';
15
15
  import {SidePanelType} from '../../subComponents/SidePanelEnum';
16
16
  import {useLocalUid, UidType} from '../../../agora-rn-uikit';
17
- import CustomEvents from '../../custom-events';
17
+ import events, {EventPersistLevel} from '../../rtm-events-api';
18
18
  import {EventNames} from '../../rtm-events';
19
19
  import {useChatUIControl} from '../chat-ui/useChatUIControl';
20
20
  import {useChatNotification} from '../chat-notification/useChatNotification';
21
21
  import Toast from '../../../react-native-toast-message';
22
22
  import {timeNow} from '../../rtm/utils';
23
23
  import {useSidePanel} from '../../utils/useSidePanel';
24
+ import getUniqueID from '../../utils/getUniqueID';
25
+
26
+ enum ChatMessageActionEnum {
27
+ Create = 'Create_Chat_Message',
28
+ Update = 'Update_Chat_Message',
29
+ Delete = 'Delete_Chat_Message',
30
+ }
24
31
 
25
32
  interface ChatMessagesProviderProps {
26
33
  children: React.ReactNode;
27
34
  }
28
- interface messageInterface {
29
- ts: number;
35
+ export interface messageInterface {
36
+ createdTimestamp: number;
37
+ updatedTimestamp?: number;
30
38
  msg: string;
39
+ msgId: string;
40
+ isDeleted: boolean;
31
41
  }
32
- interface messageStoreInterface extends messageInterface {
42
+ export interface messageStoreInterface extends messageInterface {
33
43
  uid: UidType;
34
44
  }
35
45
 
36
46
  interface ChatMessagesInterface {
37
- messageStore: messageStoreInterface | any;
38
- privateMessageStore: any;
47
+ messageStore: messageStoreInterface[];
48
+ privateMessageStore: {[key: string]: messageStoreInterface[]};
39
49
  sendChatMessage: (msg: string, toUid?: UidType) => void;
50
+ editChatMessage: (msgId: string, msg: string, toUid?: UidType) => void;
51
+ deleteChatMessage: (msgId: string, toUid?: UidType) => void;
40
52
  }
41
53
 
42
54
  const ChatMessagesContext = React.createContext<ChatMessagesInterface>({
43
55
  messageStore: [],
44
56
  privateMessageStore: {},
45
57
  sendChatMessage: () => {},
58
+ editChatMessage: () => {},
59
+ deleteChatMessage: () => {},
46
60
  });
47
61
 
48
62
  const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
49
- const {renderList} = useRenderContext();
63
+ const {renderList} = useRender();
50
64
  const localUid = useLocalUid();
51
65
  const {setSidePanel} = useSidePanel();
52
- const {groupActive, selectedChatUserId, setGroupActive} = useChatUIControl();
53
- const {setUnreadGroupMessageCount, setUnreadIndividualMessageCount} =
54
- useChatNotification();
66
+ const {
67
+ groupActive,
68
+ selectedChatUserId,
69
+ setGroupActive,
70
+ setPrivateActive,
71
+ setSelectedChatUserId,
72
+ } = useChatUIControl();
73
+ const {
74
+ setUnreadGroupMessageCount,
75
+ setUnreadIndividualMessageCount,
76
+ unreadPrivateMessageCount,
77
+ unreadIndividualMessageCount,
78
+ setUnreadPrivateMessageCount,
79
+ } = useChatNotification();
55
80
  const [messageStore, setMessageStore] = useState<messageStoreInterface[]>([]);
56
- const [privateMessageStore, setPrivateMessageStore] = useState({});
81
+ const [privateMessageStore, setPrivateMessageStore] = useState<{
82
+ [key: string]: messageStoreInterface[];
83
+ }>({});
57
84
 
58
85
  const renderListRef = useRef({renderList: renderList});
59
86
  const groupActiveRef = useRef<boolean>();
@@ -75,70 +102,210 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
75
102
  }, [selectedChatUserId]);
76
103
 
77
104
  React.useEffect(() => {
78
- const showMessageNotification = (msg: string, uid: string) => {
105
+ const showMessageNotification = (
106
+ msg: string,
107
+ uid: string,
108
+ isPrivateMessage: boolean = false,
109
+ ) => {
110
+ const uidAsNumber = parseInt(uid);
79
111
  Toast.show({
80
112
  type: 'success',
81
113
  text1: msg.length > 30 ? msg.slice(0, 30) + '...' : msg,
82
- text2: renderListRef.current.renderList[parseInt(uid)]?.name
83
- ? fromText(renderListRef.current.renderList[parseInt(uid)]?.name)
114
+ text2: renderListRef.current.renderList[uidAsNumber]?.name
115
+ ? fromText(renderListRef.current.renderList[uidAsNumber]?.name)
84
116
  : '',
85
117
  visibilityTime: 1000,
86
118
  onPress: () => {
119
+ if (isPrivateMessage) {
120
+ setUnreadPrivateMessageCount(
121
+ unreadPrivateMessageCount -
122
+ (unreadIndividualMessageCount[uidAsNumber] || 0),
123
+ );
124
+ setUnreadIndividualMessageCount((prevState) => {
125
+ return {
126
+ ...prevState,
127
+ [uidAsNumber]: 0,
128
+ };
129
+ });
130
+ setGroupActive(false);
131
+ setSelectedChatUserId(uidAsNumber);
132
+ setPrivateActive(true);
133
+ } else {
134
+ setUnreadGroupMessageCount(0);
135
+ setPrivateActive(false);
136
+ setSelectedChatUserId(0);
137
+ setGroupActive(true);
138
+ }
87
139
  setSidePanel(SidePanelType.Chat);
88
- setUnreadGroupMessageCount(0);
89
- setGroupActive(true);
90
140
  },
91
141
  });
92
142
  };
93
- CustomEvents.on(EventNames.PUBLIC_CHAT_MESSAGE, (data) => {
94
- showMessageNotification(data.payload.value, data.sender);
95
- addMessageToStore(parseInt(data.sender), {
96
- msg: data.payload.value,
97
- ts: data.ts,
98
- });
99
- /**
100
- * if chat group window is not active.
101
- * then we will increment the unread count
102
- */
103
- if (!groupActiveRef.current) {
104
- setUnreadGroupMessageCount((prevState) => {
105
- return prevState + 1;
106
- });
143
+ events.on(EventNames.PUBLIC_CHAT_MESSAGE, (data) => {
144
+ const payload = JSON.parse(data.payload);
145
+ const messageAction = payload.action;
146
+ const messageData = payload.value;
147
+ switch (messageAction) {
148
+ case ChatMessageActionEnum.Create:
149
+ showMessageNotification(messageData.msg, `${data.sender}`);
150
+ addMessageToStore(data.sender, {
151
+ msg: messageData.msg,
152
+ createdTimestamp: messageData.createdTimestamp,
153
+ isDeleted: messageData.isDeleted,
154
+ msgId: messageData.msgId,
155
+ });
156
+ /**
157
+ * if chat group window is not active.
158
+ * then we will increment the unread count
159
+ */
160
+ if (!groupActiveRef.current) {
161
+ setUnreadGroupMessageCount((prevState) => {
162
+ return prevState + 1;
163
+ });
164
+ }
165
+ break;
166
+ case ChatMessageActionEnum.Update:
167
+ setMessageStore((prevState) => {
168
+ const newState = prevState.map((item) => {
169
+ if (
170
+ item.msgId === messageData.msgId &&
171
+ item.uid === data.sender
172
+ ) {
173
+ return {
174
+ ...item,
175
+ msg: messageData.msg,
176
+ updatedTimestamp: messageData.updatedTimestamp,
177
+ };
178
+ } else {
179
+ return item;
180
+ }
181
+ });
182
+ return newState;
183
+ });
184
+ break;
185
+ case ChatMessageActionEnum.Delete:
186
+ setMessageStore((prevState) => {
187
+ const newState = prevState.map((item) => {
188
+ if (
189
+ item.msgId === messageData.msgId &&
190
+ item.uid === data.sender
191
+ ) {
192
+ return {
193
+ ...item,
194
+ isDeleted: true,
195
+ updatedTimestamp: messageData.updatedTimestamp,
196
+ };
197
+ } else {
198
+ return item;
199
+ }
200
+ });
201
+ return newState;
202
+ });
203
+ break;
204
+ default:
205
+ break;
107
206
  }
108
207
  });
109
- CustomEvents.on(EventNames.PRIVATE_CHAT_MESSAGE, (data) => {
110
- showMessageNotification(data.payload.value, data.sender);
111
- addMessageToPrivateStore(
112
- parseInt(data.sender),
113
- {
114
- msg: data.payload.value,
115
- ts: data.ts,
116
- },
117
- false,
118
- );
119
- /**
120
- * if user's private window is active.
121
- * then we will not increment the unread count
122
- */
123
-
124
- if (!(individualActiveRef.current === parseInt(data.sender))) {
125
- setUnreadIndividualMessageCount((prevState) => {
126
- const prevCount =
127
- prevState && prevState[parseInt(data.sender)]
128
- ? prevState[parseInt(data.sender)]
129
- : 0;
130
- return {
131
- ...prevState,
132
- [parseInt(data.sender)]: prevCount + 1,
133
- };
134
- });
208
+ events.on(EventNames.PRIVATE_CHAT_MESSAGE, (data) => {
209
+ const payload = JSON.parse(data.payload);
210
+ const messageAction = payload.action;
211
+ const messageData = payload.value;
212
+ switch (messageAction) {
213
+ case ChatMessageActionEnum.Create:
214
+ showMessageNotification(messageData.msg, `${data.sender}`, true);
215
+ addMessageToPrivateStore(
216
+ data.sender,
217
+ {
218
+ msg: messageData.msg,
219
+ createdTimestamp: messageData.createdTimestamp,
220
+ msgId: messageData.msgId,
221
+ isDeleted: messageData.isDeleted,
222
+ },
223
+ false,
224
+ );
225
+ /**
226
+ * if user's private window is active.
227
+ * then we will not increment the unread count
228
+ */
229
+
230
+ if (!(individualActiveRef.current === data.sender)) {
231
+ setUnreadIndividualMessageCount((prevState) => {
232
+ const prevCount =
233
+ prevState && prevState[data.sender]
234
+ ? prevState[data.sender]
235
+ : 0;
236
+ return {
237
+ ...prevState,
238
+ [data.sender]: prevCount + 1,
239
+ };
240
+ });
241
+ }
242
+ break;
243
+ case ChatMessageActionEnum.Update:
244
+ setPrivateMessageStore((prevState) => {
245
+ const privateChatOfUid = prevState[data.sender];
246
+ const updatedData = privateChatOfUid.map((item) => {
247
+ if (
248
+ item.msgId === messageData.msgId &&
249
+ item.uid === data.sender
250
+ ) {
251
+ return {
252
+ ...item,
253
+ msg: messageData.msg,
254
+ updatedTimestamp: messageData.updatedTimestamp,
255
+ };
256
+ } else {
257
+ return item;
258
+ }
259
+ });
260
+ const newState = {
261
+ ...prevState,
262
+ [data.sender]: updatedData,
263
+ };
264
+ return newState;
265
+ });
266
+ break;
267
+ case ChatMessageActionEnum.Delete:
268
+ setPrivateMessageStore((prevState) => {
269
+ const privateChatOfUid = prevState[data.sender];
270
+ const updatedData = privateChatOfUid.map((item) => {
271
+ if (
272
+ item.msgId === messageData.msgId &&
273
+ item.uid === data.sender
274
+ ) {
275
+ return {
276
+ ...item,
277
+ isDeleted: true,
278
+ updatedTimestamp: messageData.updatedTimestamp,
279
+ };
280
+ } else {
281
+ return item;
282
+ }
283
+ });
284
+ const newState = {
285
+ ...prevState,
286
+ [data.sender]: updatedData,
287
+ };
288
+ return newState;
289
+ });
290
+ break;
291
+ default:
292
+ break;
135
293
  }
136
294
  });
137
295
  }, []);
138
296
 
139
297
  const addMessageToStore = (uid: UidType, body: messageInterface) => {
140
298
  setMessageStore((m: messageStoreInterface[]) => {
141
- return [...m, {ts: body.ts, uid, msg: body.msg}];
299
+ return [
300
+ ...m,
301
+ {
302
+ createdTimestamp: body.createdTimestamp,
303
+ uid,
304
+ msg: body.msg,
305
+ msgId: body.msgId,
306
+ isDeleted: body.isDeleted,
307
+ },
308
+ ];
142
309
  });
143
310
  };
144
311
 
@@ -147,16 +314,30 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
147
314
  body: messageInterface,
148
315
  local: boolean,
149
316
  ) => {
150
- setPrivateMessageStore((state: any) => {
317
+ setPrivateMessageStore((state) => {
151
318
  let newState = {...state};
152
319
  newState[uid] !== undefined
153
320
  ? (newState[uid] = [
154
321
  ...newState[uid],
155
- {ts: body.ts, uid: local ? localUid : uid, msg: body.msg},
322
+ {
323
+ createdTimestamp: body.createdTimestamp,
324
+ uid: local ? localUid : uid,
325
+ msg: body.msg,
326
+ msgId: body.msgId,
327
+ isDeleted: body.isDeleted,
328
+ },
156
329
  ])
157
330
  : (newState = {
158
331
  ...newState,
159
- [uid]: [{ts: body.ts, uid: local ? localUid : uid, msg: body.msg}],
332
+ [uid]: [
333
+ {
334
+ createdTimestamp: body.createdTimestamp,
335
+ uid: local ? localUid : uid,
336
+ msg: body.msg,
337
+ msgId: body.msgId,
338
+ isDeleted: body.isDeleted,
339
+ },
340
+ ],
160
341
  });
161
342
  return {...newState};
162
343
  });
@@ -165,29 +346,163 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
165
346
  const sendChatMessage = (msg: string, toUid?: UidType) => {
166
347
  if (typeof msg == 'string' && msg.trim() === '') return;
167
348
  if (toUid) {
168
- CustomEvents.send(
349
+ const messageData = {
350
+ msg,
351
+ createdTimestamp: timeNow(),
352
+ msgId: getUniqueID(),
353
+ isDeleted: false,
354
+ };
355
+ events.send(
169
356
  EventNames.PRIVATE_CHAT_MESSAGE,
170
- {
171
- value: msg,
172
- },
357
+ JSON.stringify({
358
+ value: messageData,
359
+ action: ChatMessageActionEnum.Create,
360
+ }),
361
+ EventPersistLevel.LEVEL1,
173
362
  toUid,
174
363
  );
175
- addMessageToPrivateStore(
176
- toUid,
177
- {
178
- msg: msg,
179
- ts: timeNow(),
180
- },
181
- true,
364
+ addMessageToPrivateStore(toUid, messageData, true);
365
+ } else {
366
+ const messageData = {
367
+ msg,
368
+ msgId: getUniqueID(),
369
+ isDeleted: false,
370
+ createdTimestamp: timeNow(),
371
+ };
372
+ events.send(
373
+ EventNames.PUBLIC_CHAT_MESSAGE,
374
+ JSON.stringify({
375
+ value: messageData,
376
+ action: ChatMessageActionEnum.Create,
377
+ }),
378
+ EventPersistLevel.LEVEL1,
379
+ );
380
+ addMessageToStore(localUid, messageData);
381
+ }
382
+ };
383
+
384
+ const editChatMessage = (msgId: string, msg: string, toUid?: UidType) => {
385
+ if (typeof msg == 'string' && msg.trim() === '') return;
386
+ if (toUid) {
387
+ const checkData = privateMessageStore[toUid].filter(
388
+ (item) => item.msgId === msgId && item.uid === localUid,
182
389
  );
390
+ if (checkData && checkData.length) {
391
+ const editMsgData = {msg, updatedTimestamp: timeNow()};
392
+ events.send(
393
+ EventNames.PRIVATE_CHAT_MESSAGE,
394
+ JSON.stringify({
395
+ value: {msgId, ...editMsgData},
396
+ action: ChatMessageActionEnum.Update,
397
+ }),
398
+ EventPersistLevel.LEVEL1,
399
+ toUid,
400
+ );
401
+ setPrivateMessageStore((prevState) => {
402
+ const privateChatOfUid = prevState[toUid];
403
+ const updatedData = privateChatOfUid.map((item) => {
404
+ if (item.msgId === msgId) {
405
+ return {...item, ...editMsgData};
406
+ } else {
407
+ return item;
408
+ }
409
+ });
410
+ const newState = {...prevState, [toUid]: updatedData};
411
+ return newState;
412
+ });
413
+ } else {
414
+ console.log("You don't have permission to edit");
415
+ }
183
416
  } else {
184
- CustomEvents.send(EventNames.PUBLIC_CHAT_MESSAGE, {
185
- value: msg,
186
- });
187
- addMessageToStore(localUid, {
188
- msg: msg,
189
- ts: timeNow(),
190
- });
417
+ //check if user has permission to edit
418
+ const checkData = messageStore.filter(
419
+ (item) => item.msgId === msgId && item.uid === localUid,
420
+ );
421
+ if (checkData && checkData.length) {
422
+ const editMsgData = {msg, updatedTimestamp: timeNow()};
423
+ events.send(
424
+ EventNames.PUBLIC_CHAT_MESSAGE,
425
+ JSON.stringify({
426
+ value: {msgId, ...editMsgData},
427
+ action: ChatMessageActionEnum.Update,
428
+ }),
429
+ EventPersistLevel.LEVEL1,
430
+ );
431
+ setMessageStore((prevState) => {
432
+ const newState = prevState.map((item) => {
433
+ if (item.msgId === msgId) {
434
+ return {...item, ...editMsgData};
435
+ } else {
436
+ return item;
437
+ }
438
+ });
439
+ return newState;
440
+ });
441
+ } else {
442
+ console.log("You don't have permission to edit");
443
+ }
444
+ }
445
+ };
446
+
447
+ const deleteChatMessage = (msgId: string, toUid?: UidType) => {
448
+ if (toUid) {
449
+ const checkData = privateMessageStore[toUid].filter(
450
+ (item) => item.msgId === msgId && item.uid === localUid,
451
+ );
452
+ if (checkData && checkData.length) {
453
+ const deleteMsgData = {updatedTimestamp: timeNow()};
454
+ events.send(
455
+ EventNames.PRIVATE_CHAT_MESSAGE,
456
+ JSON.stringify({
457
+ value: {msgId, ...deleteMsgData},
458
+ action: ChatMessageActionEnum.Delete,
459
+ }),
460
+ EventPersistLevel.LEVEL1,
461
+ toUid,
462
+ );
463
+ setPrivateMessageStore((prevState) => {
464
+ const privateChatOfUid = prevState[toUid];
465
+ const updatedData = privateChatOfUid.map((item) => {
466
+ if (item.msgId === msgId) {
467
+ return {...item, isDeleted: true, ...deleteMsgData};
468
+ } else {
469
+ return item;
470
+ }
471
+ });
472
+ const newState = {...prevState, [toUid]: updatedData};
473
+ return newState;
474
+ });
475
+ } else {
476
+ console.log("You don't have permission to delete");
477
+ }
478
+ } else {
479
+ //check if user has permission to delete
480
+ const checkData = messageStore.filter(
481
+ (item) => item.msgId === msgId && item.uid === localUid,
482
+ );
483
+ if (checkData && checkData.length) {
484
+ const deleteMsgData = {updatedTimestamp: timeNow()};
485
+ events.send(
486
+ EventNames.PUBLIC_CHAT_MESSAGE,
487
+ JSON.stringify({
488
+ value: {msgId, ...deleteMsgData},
489
+ action: ChatMessageActionEnum.Delete,
490
+ }),
491
+ EventPersistLevel.LEVEL1,
492
+ );
493
+ setMessageStore((prevState) => {
494
+ const newState = prevState.map((item) => {
495
+ if (item.msgId === msgId) {
496
+ return {...item, isDeleted: true, ...deleteMsgData};
497
+ } else {
498
+ return item;
499
+ }
500
+ });
501
+ return newState;
502
+ });
503
+ } else {
504
+ console.log("You don't have permission to delete");
505
+ }
191
506
  }
192
507
  };
193
508
 
@@ -197,6 +512,8 @@ const ChatMessagesProvider = (props: ChatMessagesProviderProps) => {
197
512
  messageStore,
198
513
  privateMessageStore,
199
514
  sendChatMessage,
515
+ editChatMessage,
516
+ deleteChatMessage,
200
517
  }}>
201
518
  {props.children}
202
519
  </ChatMessagesContext.Provider>
@@ -9,10 +9,10 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import {createHook} from 'fpe-implementation';
12
+ import {createHook} from 'customization-implementation';
13
13
  import React, {SetStateAction, useState, useEffect} from 'react';
14
14
 
15
- interface individualUnreadMessageCount {
15
+ export interface individualUnreadMessageCount {
16
16
  [key: number]: number;
17
17
  }
18
18
 
@@ -9,7 +9,7 @@
9
9
  information visit https://appbuilder.agora.io.
10
10
  *********************************************
11
11
  */
12
- import {createHook} from 'fpe-implementation';
12
+ import {createHook} from 'customization-implementation';
13
13
  import React, {SetStateAction, useState} from 'react';
14
14
  import {UidType} from '../../../agora-rn-uikit';
15
15
 
@@ -13,12 +13,13 @@
13
13
  import React from 'react';
14
14
  import {View, StyleSheet} from 'react-native';
15
15
  import Logo from '../../subComponents/Logo';
16
- import {hasBrandLogo} from '../../utils/common';
16
+ import {useHasBrandLogo} from '../../utils/common';
17
17
 
18
18
  const CommonLogo: React.FC = () => {
19
+ const hasBrandLogo = useHasBrandLogo();
19
20
  return (
20
21
  <View style={style.nav}>
21
- {hasBrandLogo && <Logo />}
22
+ {hasBrandLogo() && <Logo />}
22
23
  {/* <OpenInNativeButton /> */}
23
24
  </View>
24
25
  );
@@ -1,12 +1,12 @@
1
1
  import {UidType} from '../../../agora-rn-uikit';
2
2
  import React, {createContext, useState, useContext} from 'react';
3
- import {createHook} from 'fpe-implementation';
3
+ import {createHook} from 'customization-implementation';
4
4
  import LiveStreamContext, {
5
5
  raiseHandListInterface,
6
6
  } from '../../components/livestream';
7
7
  import {ClientRole, useLocalUid} from '../../../agora-rn-uikit';
8
8
  import {filterObject} from '../../utils';
9
- import useUserList from '../../utils/useUserList';
9
+ import {useRender} from 'customization-api';
10
10
 
11
11
  export interface LiveStreamDataObjectInterface {
12
12
  [key: number]: {
@@ -30,7 +30,7 @@ interface ScreenShareProviderProps {
30
30
  children: React.ReactNode;
31
31
  }
32
32
  const LiveStreamDataProvider = (props: ScreenShareProviderProps) => {
33
- const {renderList} = useUserList();
33
+ const {renderList} = useRender();
34
34
  const {raiseHandList} = useContext(LiveStreamContext);
35
35
  const [hostUids, setHostUids] = useState<UidType[]>([]);
36
36
  const [audienceUids, setAudienceUids] = useState<UidType[]>([]);
@@ -6,12 +6,13 @@ import React, {
6
6
  useContext,
7
7
  useState,
8
8
  } from 'react';
9
- import {createHook} from 'fpe-implementation';
9
+ import {createHook} from 'customization-implementation';
10
10
 
11
11
  export interface ScreenShareObjectInterface {
12
12
  [key: string | number]: {
13
13
  name: string;
14
14
  isActive: boolean;
15
+ ts: number;
15
16
  };
16
17
  }
17
18
  export interface ScreenShareContextInterface {
@@ -33,6 +34,7 @@ const ScreenShareProvider = (props: ScreenShareProviderProps) => {
33
34
  [rtcProps?.screenShareUid]: {
34
35
  name: '',
35
36
  isActive: false,
37
+ ts: 0,
36
38
  },
37
39
  });
38
40