@ethora/chat-component-rn 26.4.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 (273) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +148 -0
  3. package/empty-shim.js +15 -0
  4. package/index.js +13 -0
  5. package/metro.js +72 -0
  6. package/package.json +99 -0
  7. package/src/api.config.ts +34 -0
  8. package/src/assets/BG.png +0 -0
  9. package/src/assets/BG.tsx +56 -0
  10. package/src/assets/File.svg +4 -0
  11. package/src/assets/ForzaCare.png +0 -0
  12. package/src/assets/ForzaCare.tsx +27 -0
  13. package/src/assets/icons.tsx +685 -0
  14. package/src/assets/images.tsx +41 -0
  15. package/src/assets/test.xml +243 -0
  16. package/src/components/AuthForms/Login.tsx +295 -0
  17. package/src/components/AuthForms/LoginAnonym.tsx +68 -0
  18. package/src/components/AuthForms/Register.tsx +8 -0
  19. package/src/components/ContextMenu/ContextMenuComponents.tsx +87 -0
  20. package/src/components/DropdownMenu/DropdownMenu.tsx +244 -0
  21. package/src/components/ExampleComponents/CustomMessage.tsx +92 -0
  22. package/src/components/ExampleComponents/CustomTypingIndicatorExamples.tsx +239 -0
  23. package/src/components/Header/HeaderRoomList.tsx +104 -0
  24. package/src/components/InputComponents/AudioInput.tsx +24 -0
  25. package/src/components/InputComponents/AudioRecorder.tsx +100 -0
  26. package/src/components/InputComponents/MediaInput.tsx +114 -0
  27. package/src/components/InputComponents/RecordingIndicator.tsx +77 -0
  28. package/src/components/InputComponents/Search.tsx +135 -0
  29. package/src/components/InputComponents/TextInput.tsx +66 -0
  30. package/src/components/MainComponents/ChatHeader.tsx +163 -0
  31. package/src/components/MainComponents/ChatRoom.tsx +392 -0
  32. package/src/components/MainComponents/ChatWrapper.tsx +318 -0
  33. package/src/components/MainComponents/ChooseChatMessage.tsx +44 -0
  34. package/src/components/MainComponents/ConnectionBanner.tsx +33 -0
  35. package/src/components/MainComponents/EditWrapper.tsx +72 -0
  36. package/src/components/MainComponents/LoginWrapper.tsx +134 -0
  37. package/src/components/MainComponents/MediaMessage.tsx +55 -0
  38. package/src/components/MainComponents/MessageContainer.tsx +122 -0
  39. package/src/components/MainComponents/MessageList.tsx +429 -0
  40. package/src/components/MainComponents/NoMessagesPlaceholder.tsx +49 -0
  41. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +143 -0
  42. package/src/components/MainComponents/RNStyled.tsx +34 -0
  43. package/src/components/MainComponents/ReduxWrapper.tsx +40 -0
  44. package/src/components/MainComponents/RoomList.tsx +246 -0
  45. package/src/components/MainComponents/Select.tsx +165 -0
  46. package/src/components/MainComponents/Switch.tsx +73 -0
  47. package/src/components/MainComponents/SystemMessage.tsx +42 -0
  48. package/src/components/Menu/HeaderRoomListMenu.tsx +169 -0
  49. package/src/components/MenuRoom/MenuRoom.tsx +46 -0
  50. package/src/components/MessageBubble/Avatar.tsx +84 -0
  51. package/src/components/MessageBubble/BottomReplyContainer.tsx +117 -0
  52. package/src/components/MessageBubble/CustomDivider.tsx +10 -0
  53. package/src/components/MessageBubble/DeletedMessage.tsx +36 -0
  54. package/src/components/MessageBubble/Message.tsx +400 -0
  55. package/src/components/MessageBubble/MessageInteractions.tsx +247 -0
  56. package/src/components/MessageBubble/MessageReaction.tsx +149 -0
  57. package/src/components/MessageBubble/MessageReply.tsx +50 -0
  58. package/src/components/MessageBubble/MessageTranslations.tsx +30 -0
  59. package/src/components/Modals/AddMembersModal/AddMembersModal.tsx +142 -0
  60. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +471 -0
  61. package/src/components/Modals/ChatProfileModal/DeleteChatModal.tsx +91 -0
  62. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +298 -0
  63. package/src/components/Modals/Modal/Modal.tsx +52 -0
  64. package/src/components/Modals/ModalHeaderComponent.tsx +41 -0
  65. package/src/components/Modals/ModalSelectMedia/ModalSelectMedia.tsx +285 -0
  66. package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +103 -0
  67. package/src/components/Modals/NewChatModal/ModalContent.tsx +151 -0
  68. package/src/components/Modals/NewChatModal/NewChatModal.tsx +391 -0
  69. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +136 -0
  70. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +134 -0
  71. package/src/components/Modals/SettingsModals/BlockedUsers/BlockedUsersModal.tsx +63 -0
  72. package/src/components/Modals/SettingsModals/DocumentShares/DocumentSharesModal.tsx +115 -0
  73. package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +121 -0
  74. package/src/components/Modals/SettingsModals/ManageDataModal/StyledComponents.ts +0 -0
  75. package/src/components/Modals/SettingsModals/ProfileShares/ProfileShares.tsx +65 -0
  76. package/src/components/Modals/SettingsModals/Referrals/Referrals.tsx +90 -0
  77. package/src/components/Modals/SettingsModals/SharedStyledComponents.ts +74 -0
  78. package/src/components/Modals/SettingsModals/Visibility/RadioInput.tsx +59 -0
  79. package/src/components/Modals/SettingsModals/Visibility/StyledComponents.ts +32 -0
  80. package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +146 -0
  81. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +163 -0
  82. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +410 -0
  83. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +85 -0
  84. package/src/components/Modals/styledModalComponents.tsx +181 -0
  85. package/src/components/OperationalModal/OperationalModal.tsx +78 -0
  86. package/src/components/RoomComponents/ChatRoomItem.tsx +219 -0
  87. package/src/components/RoomComponents/LastMessageItem.tsx +47 -0
  88. package/src/components/RoomComponents/styled/LastAudioMessage.tsx +62 -0
  89. package/src/components/RoomComponents/styled/LastMessageEmoji.tsx +26 -0
  90. package/src/components/RoomComponents/styled/LastMessageFile.tsx +54 -0
  91. package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +54 -0
  92. package/src/components/RoomComponents/styled/LastMessageVideo.tsx +70 -0
  93. package/src/components/RoomComponents/styled/LastTextMessage.tsx +65 -0
  94. package/src/components/RoomComponents/styled/StyledRoomComponents.ts +53 -0
  95. package/src/components/SortDropDown/index.tsx +76 -0
  96. package/src/components/Thread/ThreadHeader.tsx +41 -0
  97. package/src/components/Thread/ThreadWrapper.tsx +270 -0
  98. package/src/components/Toast/Toast.tsx +128 -0
  99. package/src/components/Toast/index.ts +13 -0
  100. package/src/components/UsersList/StyledComponents.ts +30 -0
  101. package/src/components/UsersList/UsersList.tsx +112 -0
  102. package/src/components/styled/ActionButton.tsx +40 -0
  103. package/src/components/styled/AudioMessage.tsx +82 -0
  104. package/src/components/styled/Button.tsx +107 -0
  105. package/src/components/styled/ChatWrapperBox.tsx +9 -0
  106. package/src/components/styled/DateLabel.tsx +77 -0
  107. package/src/components/styled/Loader.tsx +65 -0
  108. package/src/components/styled/MediaFilePreview.tsx +42 -0
  109. package/src/components/styled/MediaModal.tsx +54 -0
  110. package/src/components/styled/MessageImage.tsx +54 -0
  111. package/src/components/styled/NewMessageLabel.tsx +50 -0
  112. package/src/components/styled/RoomListComponents/index.tsx +164 -0
  113. package/src/components/styled/SendInput.tsx +297 -0
  114. package/src/components/styled/StyledComponents.ts +320 -0
  115. package/src/components/styled/StyledInput.tsx +101 -0
  116. package/src/components/styled/StyledInputComponents/AudioComponents.tsx +1 -0
  117. package/src/components/styled/StyledInputComponents/Composing.tsx +97 -0
  118. package/src/components/styled/StyledInputComponents/CustomTypingIndicator.tsx +261 -0
  119. package/src/components/styled/StyledInputComponents/MediaComponents.tsx +90 -0
  120. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +131 -0
  121. package/src/components/styled/StyledInputComponents/VideoComponents.tsx +49 -0
  122. package/src/components/styled/TreadLabel.tsx +50 -0
  123. package/src/components/styled/UnsupportedType.tsx +95 -0
  124. package/src/components/styled/VideoMessage.tsx +68 -0
  125. package/src/context/MessageNotificationContext.tsx +335 -0
  126. package/src/context/PushNotificationProvider.tsx +78 -0
  127. package/src/context/ToastContext.tsx +63 -0
  128. package/src/context/toastProvider.tsx +0 -0
  129. package/src/context/xmppProvider.tsx +364 -0
  130. package/src/helpers/block_scroll.ts +95 -0
  131. package/src/helpers/chatAutoEnterer.ts +46 -0
  132. package/src/helpers/checkUniqueUsers.tsx +31 -0
  133. package/src/helpers/constants/CHAT_TYPES.ts +6 -0
  134. package/src/helpers/constants/LANGUAGE_OPTIONS.ts +14 -0
  135. package/src/helpers/constants/LOCAL_STORAGE.ts +3 -0
  136. package/src/helpers/constants/MESSAGE_INTERACTIONS.ts +29 -0
  137. package/src/helpers/constants/MODAL_TYPES.ts +57 -0
  138. package/src/helpers/constants/PLATFORM_CONSTANTS.ts +3 -0
  139. package/src/helpers/createMainMessageForThread.ts +23 -0
  140. package/src/helpers/createMessageFromXml.ts +118 -0
  141. package/src/helpers/createRoomFromApi.tsx +27 -0
  142. package/src/helpers/createUserNameFromSetUser.ts +15 -0
  143. package/src/helpers/dateComparison.ts +12 -0
  144. package/src/helpers/debounce.ts +10 -0
  145. package/src/helpers/ensureScopedChatCache.ts +61 -0
  146. package/src/helpers/extractUniqueMembersFromRooms.ts +45 -0
  147. package/src/helpers/formatNumberWithCommas.ts +3 -0
  148. package/src/helpers/getBooleanFromString.ts +7 -0
  149. package/src/helpers/getDataFromXml.ts +80 -0
  150. package/src/helpers/getNumberFromString.ts +5 -0
  151. package/src/helpers/getRoomsWithRetry.ts +45 -0
  152. package/src/helpers/getTintedColor.ts +28 -0
  153. package/src/helpers/getUnnamedUsers.ts +39 -0
  154. package/src/helpers/handleCopyClick.ts +3 -0
  155. package/src/helpers/handleXmppError.ts +14 -0
  156. package/src/helpers/hashcolor.ts +34 -0
  157. package/src/helpers/historyPreloadScheduler.ts +264 -0
  158. package/src/helpers/initRoomsPresence.ts +32 -0
  159. package/src/helpers/initXmppRooms.tsx +71 -0
  160. package/src/helpers/insertMessageWithDelimiter.ts +96 -0
  161. package/src/helpers/isChatIdPresentInArray.ts +54 -0
  162. package/src/helpers/localStorageUser.ts +9 -0
  163. package/src/helpers/markdownParser.tsx +295 -0
  164. package/src/helpers/nanoToMs.ts +3 -0
  165. package/src/helpers/parseMessageBody.tsx +516 -0
  166. package/src/helpers/parseUrls.tsx +42 -0
  167. package/src/helpers/resolveInitBeforeLoadUser.ts +240 -0
  168. package/src/helpers/storeConsole.ts +26 -0
  169. package/src/helpers/transformTranslatations.ts +16 -0
  170. package/src/helpers/updateMessagesTillLast.tsx +104 -0
  171. package/src/helpers/updatedChatLastTimestamps.ts +29 -0
  172. package/src/helpers/validator.ts +20 -0
  173. package/src/helpers/walletUsername.ts +12 -0
  174. package/src/hooks/hooks.ts +6 -0
  175. package/src/hooks/useChatSettingState.tsx +38 -0
  176. package/src/hooks/useChatWrapperInit.ts +266 -0
  177. package/src/hooks/useComposing.tsx +59 -0
  178. package/src/hooks/useCustomTypingIndicator.tsx +193 -0
  179. package/src/hooks/useEventHandlers.tsx +81 -0
  180. package/src/hooks/useGetNewArchRoom.tsx +57 -0
  181. package/src/hooks/useHeapSender.tsx +88 -0
  182. package/src/hooks/useLocalStorage.tsx +53 -0
  183. package/src/hooks/useLogout.tsx +31 -0
  184. package/src/hooks/useMessageHeapState.tsx +11 -0
  185. package/src/hooks/useMessageLoaderQueue.tsx +90 -0
  186. package/src/hooks/useMessageQueue.ts +146 -0
  187. package/src/hooks/usePendingNotification.ts +49 -0
  188. package/src/hooks/usePrevious.tsx +15 -0
  189. package/src/hooks/usePushNotifications.ts +106 -0
  190. package/src/hooks/useQRCodeChatHandler.ts +58 -0
  191. package/src/hooks/useRoomInitialization.tsx +160 -0
  192. package/src/hooks/useRoomState.tsx +47 -0
  193. package/src/hooks/useRoomUrl.tsx +41 -0
  194. package/src/hooks/useSendMessage.tsx +306 -0
  195. package/src/hooks/useUnreadMessagesCounter.ts +55 -0
  196. package/src/hooks/useXmppInitialization.ts +148 -0
  197. package/src/main.ts +45 -0
  198. package/src/networking/api-requests/auth.api.ts +140 -0
  199. package/src/networking/api-requests/push.api.ts +55 -0
  200. package/src/networking/api-requests/roomMembers.api.ts +20 -0
  201. package/src/networking/api-requests/rooms.api.ts +142 -0
  202. package/src/networking/api-requests/user.api.ts +65 -0
  203. package/src/networking/apiClient.ts +149 -0
  204. package/src/networking/helpers/refreshChecker.ts +13 -0
  205. package/src/networking/stanzaHandlers.ts +418 -0
  206. package/src/networking/xmpp/actionSetTimestampToPrivateStore.xmpp.ts +37 -0
  207. package/src/networking/xmpp/allRoomPresences.xmpp.ts +10 -0
  208. package/src/networking/xmpp/createPrivateRoom.xmpp.ts +26 -0
  209. package/src/networking/xmpp/createRoom.xmpp.ts +35 -0
  210. package/src/networking/xmpp/createRoomPresence.xmpp.ts +74 -0
  211. package/src/networking/xmpp/createTimeoutPromise.xmpp.ts +15 -0
  212. package/src/networking/xmpp/deleteMessage.xmpp.ts +19 -0
  213. package/src/networking/xmpp/editMessage.xmpp.ts +46 -0
  214. package/src/networking/xmpp/getChatsPrivateStoreRequest.xmpp.ts +57 -0
  215. package/src/networking/xmpp/getHistory.xmpp.ts +140 -0
  216. package/src/networking/xmpp/getLastMessageArchive.xmpp.ts +24 -0
  217. package/src/networking/xmpp/getRoomInfo.xmpp.ts +15 -0
  218. package/src/networking/xmpp/getRoomMembers.xmpp.ts +13 -0
  219. package/src/networking/xmpp/getRooms.xmpp.ts +43 -0
  220. package/src/networking/xmpp/getRoomsPaged.xmpp.ts +59 -0
  221. package/src/networking/xmpp/handlePong.xmpp.ts +7 -0
  222. package/src/networking/xmpp/handleStanzas.xmpp.ts +55 -0
  223. package/src/networking/xmpp/inviteRoomRequest.xmpp.ts +25 -0
  224. package/src/networking/xmpp/leaveTheRoom.xmpp.ts +15 -0
  225. package/src/networking/xmpp/listenerManager.ts +116 -0
  226. package/src/networking/xmpp/presenceInRoom.xmpp.ts +57 -0
  227. package/src/networking/xmpp/roomConfig.xmpp.ts +71 -0
  228. package/src/networking/xmpp/sendMediaMessage.xmpp.ts +97 -0
  229. package/src/networking/xmpp/sendMessageReaction.xmpp.ts +41 -0
  230. package/src/networking/xmpp/sendPing.xmpp.ts +21 -0
  231. package/src/networking/xmpp/sendTextMessage.xmpp.ts +99 -0
  232. package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +44 -0
  233. package/src/networking/xmpp/sendTypingRequest.xmpp.ts +26 -0
  234. package/src/networking/xmpp/setChatsPrivateStoreRequest.xmpp.ts +48 -0
  235. package/src/networking/xmpp/setMeAsOwner.xmpp.ts +52 -0
  236. package/src/networking/xmpp/setRoomImage.xmpp.ts +26 -0
  237. package/src/networking/xmpp/setVCard.xmpp.ts +19 -0
  238. package/src/networking/xmpp/subscribeToRoomMessages.xmpp.ts +75 -0
  239. package/src/networking/xmppClient.ts +603 -0
  240. package/src/roomStore/Middleware/logoutMiddleware.tsx +24 -0
  241. package/src/roomStore/Middleware/newMessageMidlleware.tsx +87 -0
  242. package/src/roomStore/Middleware/reactionsMiddleware.tsx +77 -0
  243. package/src/roomStore/Middleware/testMiddleware.tsx +20 -0
  244. package/src/roomStore/Middleware/unreadMidlleware.tsx +58 -0
  245. package/src/roomStore/chatSettingsSlice.ts +178 -0
  246. package/src/roomStore/index.ts +68 -0
  247. package/src/roomStore/persistence.ts +152 -0
  248. package/src/roomStore/roomHeapSlice.ts +37 -0
  249. package/src/roomStore/roomsSlice.ts +353 -0
  250. package/src/services/pushNotifications.ts +170 -0
  251. package/src/services/pushSubscriptionService.ts +145 -0
  252. package/src/types/messages.ts +61 -0
  253. package/src/types/models/action.model.ts +30 -0
  254. package/src/types/models/config.model.ts +16 -0
  255. package/src/types/models/customComponents.model.ts +53 -0
  256. package/src/types/models/language.model.ts +11 -0
  257. package/src/types/models/media.model.ts +5 -0
  258. package/src/types/models/message.model.ts +69 -0
  259. package/src/types/models/modal.model.ts +9 -0
  260. package/src/types/models/room.model.ts +120 -0
  261. package/src/types/models/user.model.ts +90 -0
  262. package/src/types/models/xmpp.model.ts +155 -0
  263. package/src/types/types.ts +505 -0
  264. package/src/utils/PriorityQueue.ts +47 -0
  265. package/src/utils/actionHelpers.ts +40 -0
  266. package/src/utils/actionLogger.ts +64 -0
  267. package/src/utils/clientRegistry.ts +80 -0
  268. package/src/utils/devLogger.ts +197 -0
  269. package/src/utils/messageNotificationManager.ts +108 -0
  270. package/src/utils/resendMessage.ts +87 -0
  271. package/src/utils/toastEmitter.ts +27 -0
  272. package/src/utils/xmppMemoryMonitor.ts +63 -0
  273. package/src/version.ts +1 -0
@@ -0,0 +1,149 @@
1
+ import axios from 'axios';
2
+ import { store } from '../roomStore';
3
+
4
+ import { logout, refreshTokens } from '../roomStore/chatSettingsSlice';
5
+ import { appToken as defaultAppToken } from '../../api.config';
6
+ import { installAxiosCapture } from '../utils/devLogger';
7
+
8
+ const DEFAULT_BASE_URL = 'https://api.chat.ethora.com/v1';
9
+
10
+ let currentBaseURL = DEFAULT_BASE_URL;
11
+ let currentAppToken: string = defaultAppToken;
12
+
13
+ const http = axios.create({
14
+ baseURL: currentBaseURL,
15
+ });
16
+
17
+ // Dev-logger hook: capture every request + response on the shared
18
+ // `http` instance.
19
+ installAxiosCapture(http);
20
+
21
+ export function setBaseURL(baseUrl?: string, appToken?: string) {
22
+ if (baseUrl && baseUrl !== currentBaseURL) {
23
+ currentBaseURL = baseUrl;
24
+ http.defaults.baseURL = baseUrl;
25
+ }
26
+ if (appToken && appToken !== currentAppToken) {
27
+ currentAppToken = appToken;
28
+ }
29
+ }
30
+
31
+ export function getCurrentAppToken() {
32
+ return currentAppToken;
33
+ }
34
+
35
+ export function getCurrentBaseURL() {
36
+ return currentBaseURL;
37
+ }
38
+
39
+ export function refresh(): Promise<{
40
+ data: { refreshToken: string; token: string };
41
+ }> {
42
+ return new Promise((resolve, reject) => {
43
+ const user = store.getState().chatSettingStore.user;
44
+ try {
45
+ http
46
+ .post(
47
+ '/users/login/refresh',
48
+ {},
49
+ { headers: { Authorization: user.refreshToken } }
50
+ )
51
+ .then((response) => {
52
+ store.dispatch(
53
+ refreshTokens({
54
+ token: response.data.token,
55
+ refreshToken: response.data.refreshToken,
56
+ })
57
+ );
58
+ })
59
+ .catch((error) => {
60
+ reject(error);
61
+ });
62
+ } catch (error) {
63
+ console.log('errr');
64
+ store.dispatch(logout());
65
+ }
66
+ });
67
+ }
68
+
69
+ let isRefreshing = false;
70
+ let failedQueue: any[] = [];
71
+
72
+ const addRequestToQueue = (config: any) => {
73
+ return new Promise((resolve, reject) => {
74
+ failedQueue.push({ resolve, reject, config });
75
+ });
76
+ };
77
+
78
+ const processQueue = (newAccessToken: string) => {
79
+ for (const request of failedQueue) {
80
+ if (newAccessToken) {
81
+ request.config.headers.Authorization = newAccessToken;
82
+ }
83
+
84
+ request.resolve(http(request.config));
85
+ }
86
+
87
+ failedQueue = [];
88
+ };
89
+
90
+ http.interceptors.response.use(
91
+ (response) => response,
92
+ async (error) => {
93
+ // BUGFIX: the original condition was `if (!enabled)` — inverted, so
94
+ // turning `refreshTokens.enabled: true` actually DISABLED the refresh
95
+ // path on 401. Use the correct sense.
96
+ if (store.getState().chatSettingStore?.config?.refreshTokens?.enabled) {
97
+ if (
98
+ store.getState().chatSettingStore?.config?.refreshTokens
99
+ ?.refreshFunction
100
+ ) {
101
+ const { refreshToken, accessToken } = store
102
+ .getState()
103
+ .chatSettingStore?.config?.refreshTokens?.refreshFunction();
104
+ store.dispatch(
105
+ refreshTokens({
106
+ token: accessToken,
107
+ refreshToken: refreshToken,
108
+ })
109
+ );
110
+ return;
111
+ } else {
112
+ const originalRequest = error.config;
113
+
114
+ if (!error.response || error.response.status !== 401) {
115
+ throw error;
116
+ }
117
+ if (
118
+ originalRequest.url === '/users/login/refresh' ||
119
+ originalRequest.url === '/users/login'
120
+ ) {
121
+ return Promise.reject(error);
122
+ }
123
+
124
+ originalRequest._retry = true;
125
+
126
+ if (isRefreshing) {
127
+ const retryOriginalRequest = addRequestToQueue(originalRequest);
128
+
129
+ return retryOriginalRequest;
130
+ } else {
131
+ isRefreshing = true;
132
+ try {
133
+ const tokens = await refresh();
134
+ console.log('tokens', tokens);
135
+ isRefreshing = false;
136
+ originalRequest.headers.Authorization = tokens.data.token;
137
+ processQueue(tokens.data.token);
138
+ return http(originalRequest);
139
+ } catch (refreshErr) {
140
+ isRefreshing = false;
141
+ return refreshErr;
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ );
148
+
149
+ export default http;
@@ -0,0 +1,13 @@
1
+ export const refreshHelper = (
2
+ isEnabled: boolean,
3
+ refreshFunc: any,
4
+ logoutClb: any
5
+ ) => {
6
+ if (isEnabled) {
7
+ try {
8
+ refreshFunc();
9
+ } catch (error) {
10
+ logoutClb();
11
+ }
12
+ }
13
+ };
@@ -0,0 +1,418 @@
1
+ import { Element } from 'ltx';
2
+ import { store } from '../roomStore';
3
+ import {
4
+ addRoom,
5
+ addRoomMessage,
6
+ deleteRoomMessage,
7
+ editRoomMessage,
8
+ setComposing,
9
+ setCurrentRoom,
10
+ setRoomRole,
11
+ updateRoom,
12
+ } from '../roomStore/roomsSlice';
13
+ import { IRoom } from '../types/types';
14
+ import { createMessageFromXml } from '../helpers/createMessageFromXml';
15
+ import { getDataFromXml } from '../helpers/getDataFromXml';
16
+ import { setDeleteModal } from '../roomStore/chatSettingsSlice';
17
+ import { messageNotificationManager } from '../utils/messageNotificationManager';
18
+
19
+ // TO DO: we are thinking to refactor this code in the following way:
20
+ // each stanza will be parsed for 'type'
21
+ // then it will be handled based on the type
22
+ // XMPP parsing will be done universally as a pre-processing step
23
+ // then handlers for different types will work with a Javascript object
24
+ // types: standard, coin transfer, is composing, attachment (media), token (nft) or smart contract
25
+ // types can be added into our chat protocol (XMPP stanza add field type="") to make it easier to parse here
26
+
27
+ //core default
28
+ const onRealtimeMessage = async (stanza: Element) => {
29
+ if (
30
+ !stanza?.getChild('result') &&
31
+ !stanza.getChild('composing') &&
32
+ !stanza.getChild('paused') &&
33
+ !stanza.getChild('subject') &&
34
+ !stanza.is('iq') &&
35
+ stanza.attrs.id !== 'deleteMessageStanza'
36
+ ) {
37
+ const body = stanza?.getChild('body');
38
+ const archived = stanza?.getChild('archived');
39
+ const data = stanza?.getChild('data');
40
+ const id = archived?.attrs.id;
41
+
42
+ const deleted = stanza
43
+ .getChild('result')
44
+ ?.getChild('forwarded')
45
+ ?.getChild('message')
46
+ ?.getChild('deleted');
47
+
48
+ if (!data) {
49
+ console.log(stanza.toString());
50
+ console.log('Missing data elements in real-time message.');
51
+ return;
52
+ }
53
+
54
+ if (!data.attrs.senderJID) {
55
+ console.log(stanza.toString());
56
+ console.log(data.attrs.senderJID);
57
+
58
+ console.log('Missing sender information in real-time message.');
59
+ return;
60
+ }
61
+
62
+ // Use the same parser as MAM so the message carries `xmppId` (the
63
+ // outer stanza id = our original send id). insertMessageWithDelimiter
64
+ // dedupes by xmppId, which is how the optimistic pending bubble flips
65
+ // to delivered in-place instead of rendering twice.
66
+ const parsed = await getDataFromXml(stanza);
67
+ const { data: pData, id: pId, body: pBody, ...pRest } = parsed || ({} as any);
68
+ const message = await createMessageFromXml({
69
+ data: pData || data.attrs,
70
+ id: pId || id,
71
+ body: pBody,
72
+ ...pRest,
73
+ isDeleted: !!deleted || !!(pRest as any)?.deleted,
74
+ });
75
+
76
+ const roomJID = stanza.attrs.from.split('/')[0];
77
+ store.dispatch(
78
+ addRoomMessage({
79
+ roomJID,
80
+ message,
81
+ })
82
+ );
83
+
84
+ // Trigger in-app notification (manager dedupes + drops own messages
85
+ // for empty bodies). Self-messages are filtered by sender check.
86
+ try {
87
+ const state = store.getState();
88
+ const currentUserWallet = (state.chatSettingStore.user?.walletAddress || '').toLowerCase();
89
+ const senderJID = String(data.attrs.senderJID || '').toLowerCase();
90
+ if (currentUserWallet && senderJID.includes(currentUserWallet)) {
91
+ return message; // own message, skip toast
92
+ }
93
+ const room = state.rooms.rooms[roomJID];
94
+ const roomName = room?.title || room?.name || '';
95
+ const senderName = [
96
+ data.attrs.senderFirstName,
97
+ data.attrs.senderLastName,
98
+ ]
99
+ .filter(Boolean)
100
+ .join(' ')
101
+ .trim() || 'New message';
102
+ messageNotificationManager.showNotification(
103
+ message,
104
+ roomName,
105
+ senderName,
106
+ roomJID
107
+ );
108
+ } catch (err) {
109
+ console.warn('notification dispatch failed', err);
110
+ }
111
+ return message;
112
+ }
113
+ };
114
+
115
+ const onDeleteMessage = async (stanza: Element) => {
116
+ if (stanza.attrs.id === 'deleteMessageStanza') {
117
+ const deleted = stanza.getChild('delete');
118
+ const stanzaId = stanza.getChild('stanza-id');
119
+
120
+ if (!deleted) {
121
+ return;
122
+ }
123
+
124
+ store.dispatch(
125
+ deleteRoomMessage({
126
+ roomJID: stanzaId.attrs.by,
127
+ messageId: deleted.attrs.id,
128
+ })
129
+ );
130
+ store.dispatch(setDeleteModal({ isDeleteModal: false }));
131
+ }
132
+ };
133
+
134
+ const onEditMessage = async (stanza: Element) => {
135
+ if (stanza?.attrs?.id?.includes('edit-message')) {
136
+ const stanzaId = stanza.getChild('stanza-id');
137
+ const replace = stanza.getChild('replace');
138
+
139
+ if (!stanzaId && !replace) {
140
+ return;
141
+ }
142
+
143
+ store.dispatch(
144
+ editRoomMessage({
145
+ roomJID: stanzaId.attrs.by,
146
+ messageId: replace.attrs.id,
147
+ text: replace.attrs.text,
148
+ })
149
+ );
150
+ }
151
+ };
152
+
153
+ const onMessageHistory = async (stanza: any) => {
154
+ if (
155
+ stanza.is('message') &&
156
+ stanza.children[0].attrs.xmlns === 'urn:xmpp:mam:2'
157
+ ) {
158
+ // console.log("stanza -->", stanza.toString());
159
+ const body = stanza
160
+ .getChild('result')
161
+ ?.getChild('forwarded')
162
+ ?.getChild('message')
163
+ ?.getChild('body');
164
+ const data = stanza
165
+ .getChild('result')
166
+ ?.getChild('forwarded')
167
+ ?.getChild('message')
168
+ ?.getChild('data');
169
+ const deleted = stanza
170
+ .getChild('result')
171
+ ?.getChild('forwarded')
172
+ ?.getChild('message')
173
+ ?.getChild('deleted');
174
+
175
+ const delay = stanza
176
+ .getChild('result')
177
+ ?.getChild('forwarded')
178
+ ?.getChild('delay');
179
+ const id = stanza.getChild('result')?.attrs.id;
180
+ if (!delay) {
181
+ if (stanza.getChild('subject')) {
182
+ console.log('Subject.');
183
+ return;
184
+ }
185
+ if (!data || !body || !id) {
186
+ console.log('Missing required elements in message history.');
187
+ return;
188
+ }
189
+ }
190
+ // console.log(stanza.attrs.from);
191
+
192
+ if (
193
+ !data?.attrs ||
194
+ !data.attrs.senderFirstName ||
195
+ !data.attrs.senderLastName ||
196
+ !data.attrs.senderJID
197
+ ) {
198
+ // console.log(
199
+ // "Missing sender information in message history.",
200
+ // stanza.toString()
201
+ // );
202
+ return;
203
+ }
204
+ const message = await createMessageFromXml(
205
+ data.attrs,
206
+ body,
207
+ id,
208
+ stanza.attrs.from,
209
+ !!deleted
210
+ );
211
+ store.dispatch(
212
+ addRoomMessage({
213
+ roomJID: stanza.attrs.from,
214
+ message,
215
+ })
216
+ );
217
+ }
218
+ };
219
+
220
+ const handleComposing = async (stanza: Element, currentUser: string) => {
221
+ if (stanza.getChild('paused') || stanza.getChild('composing')) {
222
+ const composingUser = stanza.attrs?.from?.split('/')?.[1];
223
+
224
+ // Normalize both sides the same way before comparing — previously
225
+ // we lower-cased the currentUser but only stripped underscores from
226
+ // the composingUser, so wallet-style IDs with underscores
227
+ // ("foo_bar") never matched their own MUC nick ("foo_bar") and the
228
+ // user saw a typing indicator for their own keystrokes.
229
+ const norm = (s?: string) =>
230
+ (s || '').toLowerCase().replace(/_/g, '');
231
+
232
+ // Secondary self-check via the <data senderJID="..."> attribute —
233
+ // covers the case where the MUC resource part differs from the
234
+ // raw xmppUsername (custom nick formats, JID-mode resources, etc.).
235
+ const senderJID = stanza.getChild('data')?.attrs?.senderJID || '';
236
+ const senderLocal = senderJID.split('@')[0] || '';
237
+ const state = store.getState();
238
+ const selfUser = state.chatSettingStore?.user;
239
+ const selfXmppUsername = selfUser?.xmppUsername || '';
240
+ const selfWallet = selfUser?.walletAddress || '';
241
+ const isSelf =
242
+ (composingUser && norm(currentUser) === norm(composingUser)) ||
243
+ (senderLocal && norm(senderLocal) === norm(selfXmppUsername)) ||
244
+ (senderLocal && norm(senderLocal).includes(norm(selfWallet)));
245
+
246
+ if (composingUser && !isSelf) {
247
+ const chatJID = stanza.attrs?.from.split('/')[0];
248
+
249
+ let composingList = [];
250
+
251
+ stanza?.getChild('composing')
252
+ ? composingList.push(
253
+ stanza.getChild('data')?.attrs?.fullName?.split(' ')?.[0] || 'User'
254
+ )
255
+ : composingList.pop();
256
+
257
+ store.dispatch(
258
+ setComposing({
259
+ chatJID: chatJID,
260
+ composing: !!stanza?.getChild('composing'),
261
+ composingList,
262
+ })
263
+ );
264
+ }
265
+ }
266
+ };
267
+
268
+ const onPresenceInRoom = (stanza: Element | any) => {
269
+ if (stanza.attrs.id === 'presenceInRoom' && !stanza.getChild('error')) {
270
+ const roomJID: string = stanza.attrs.from.split('/')[0];
271
+ const role: string = stanza?.children[1]?.children[0]?.attrs.role;
272
+ store.dispatch(setRoomRole({ chatJID: roomJID, role: role }));
273
+ }
274
+ };
275
+
276
+ const onChatInvite = async (stanza: Element, client: any) => {
277
+ if (stanza.is('message') && stanza.attrs.type !== 'groupchat') {
278
+ // check if it is invite
279
+ const chatId = stanza.attrs.from;
280
+ const xEls = stanza.getChildren('x');
281
+
282
+ for (const el of xEls) {
283
+ const child = el.getChild('invite');
284
+
285
+ if (child) {
286
+ const chat = store.getState().rooms.rooms[chatId];
287
+ if (chat) {
288
+ return;
289
+ }
290
+
291
+ await client.presenceInRoomStanza(chatId);
292
+ await client.getRoomsStanza();
293
+ }
294
+ }
295
+ }
296
+ };
297
+
298
+ const onGetMembers = (stanza: Element) => {
299
+ const jid = store.getState().rooms.activeRoomJID;
300
+ // Defensive: many iq stanzas don't have an id (server pings,
301
+ // disco#info responses, etc.).
302
+ if (String(stanza.attrs?.id || '') !== 'roomMemberInfo') {return;}
303
+ // The original implementation used the browser-only DOMParser, which
304
+ // throws `ReferenceError: Property 'DOMParser' doesn't exist` in
305
+ // React Native. Walk the ltx element tree directly instead — the
306
+ // shape is the same: nested <query><activity .../></query> children.
307
+ try {
308
+ const queries = (stanza as any).getChildren?.('query') || [];
309
+ const activities: any[] = [];
310
+ for (const q of queries) {
311
+ const acts = q?.getChildren?.('activity') || [];
312
+ for (const a of acts) {activities.push(a);}
313
+ }
314
+ const roomMembers = activities.map((a: any) => ({
315
+ name: a?.attrs?.name,
316
+ role: a?.attrs?.role,
317
+ ban_status: a?.attrs?.ban_status,
318
+ last_active: Number(a?.attrs?.last_active),
319
+ jid: a?.attrs?.jid,
320
+ }));
321
+ if (jid) {
322
+ store.dispatch(updateRoom({ jid, updates: { roomMembers } as any }));
323
+ }
324
+ } catch (err) {
325
+ console.warn('onGetMembers parse failed', err);
326
+ }
327
+ };
328
+
329
+ const onGetRoomInfo = (stanza: Element) => {
330
+ if (stanza.attrs.id === 'roomInfo' && !stanza.getChild('error')) {
331
+ }
332
+ };
333
+
334
+ const onGetLastMessageArchive = (stanza: Element, _xmpp: any) => {
335
+ if (stanza.attrs.id === 'GetLastArchive') {
336
+ }
337
+ };
338
+
339
+ const onNewRoomCreated = (stanza: Element, xmpp: any) => {
340
+ store.dispatch(setCurrentRoom({ roomJID: stanza.attrs.from }));
341
+ xmpp.getRoomsStanza();
342
+ };
343
+
344
+ const onGetChatRooms = (stanza: Element, xmpp: any) => {
345
+ if (
346
+ stanza.attrs.id === 'getUserRooms' &&
347
+ Array.isArray(stanza.getChild('query')?.children)
348
+ ) {
349
+ stanza.getChild('query')?.children.forEach(async (result: any) => {
350
+ const currentChatRooms = store.getState().rooms.rooms;
351
+
352
+ const isRoomAlreadyAdded = Object.values(currentChatRooms).some(
353
+ (element) => element.jid === result?.attrs?.jid
354
+ );
355
+
356
+ if (!isRoomAlreadyAdded) {
357
+ try {
358
+ const roomData: IRoom = {
359
+ jid: result?.attrs?.jid || '',
360
+ name: result?.attrs?.name || '',
361
+ id: '',
362
+ title: result?.attrs?.name || '',
363
+ usersCnt: Number(result?.attrs?.users_cnt || 0),
364
+ messages: [],
365
+ isLoading: false,
366
+ roomBg:
367
+ result?.attrs?.room_background !== 'none'
368
+ ? result?.attrs?.room_background
369
+ : null,
370
+ icon:
371
+ result?.attrs?.room_thumbnail !== 'none'
372
+ ? result?.attrs?.room_thumbnail
373
+ : null,
374
+ unreadMessages: 0,
375
+ lastViewedTimestamp: 0,
376
+ };
377
+
378
+ store.dispatch(addRoom({ roomData: { ...roomData } }));
379
+
380
+ if (!store.getState().rooms.activeRoomJID) {
381
+ store.dispatch(setCurrentRoom({ roomJID: roomData.jid }));
382
+ }
383
+
384
+ if (roomData.jid) {
385
+ xmpp.presenceInRoomStanza(roomData.jid);
386
+ }
387
+ } catch (error) {}
388
+ }
389
+ });
390
+ }
391
+ };
392
+
393
+ // No-op stubs for handlers that handleStanzas.xmpp.ts imports but the
394
+ // RN side hasn't ported yet. Without these the bundle compiles but
395
+ // require() returns undefined at runtime → "X is not a function".
396
+ const onMessageError = (_stanza: Element, _xmpp?: any) => {};
397
+ const onReactionMessage = (_stanza: Element) => {};
398
+ const onReactionHistory = (_stanza: Element) => {};
399
+ const onRoomKicked = (_stanza: Element) => {};
400
+
401
+ export {
402
+ onRealtimeMessage,
403
+ onMessageHistory,
404
+ onPresenceInRoom,
405
+ onGetLastMessageArchive,
406
+ handleComposing,
407
+ onGetChatRooms,
408
+ onNewRoomCreated,
409
+ onGetMembers,
410
+ onGetRoomInfo,
411
+ onDeleteMessage,
412
+ onEditMessage,
413
+ onChatInvite,
414
+ onMessageError,
415
+ onReactionMessage,
416
+ onReactionHistory,
417
+ onRoomKicked,
418
+ };
@@ -0,0 +1,37 @@
1
+ import { getChatsPrivateStoreRequest } from './getChatsPrivateStoreRequest.xmpp';
2
+ import { setChatsPrivateStoreRequest } from './setChatsPrivateStoreRequest.xmpp';
3
+
4
+ const populateChats = (chats: string[], timestamp: string): string => {
5
+ const populatedData = chats.reduce(
6
+ (acc, chat) => {
7
+ acc[chat] = timestamp;
8
+ return acc;
9
+ },
10
+ {} as Record<string, string>
11
+ );
12
+
13
+ return JSON.stringify(populatedData);
14
+ };
15
+
16
+ export async function actionSetTimestampToPrivateStore(
17
+ client: any,
18
+ chatId: string,
19
+ timestamp: number,
20
+ chats?: string[]
21
+ ) {
22
+ let storeObj: any = await getChatsPrivateStoreRequest(client);
23
+
24
+ if (storeObj && typeof storeObj === 'object') {
25
+ storeObj[chatId] = timestamp;
26
+
27
+ const str = JSON.stringify(storeObj);
28
+ await setChatsPrivateStoreRequest(client, str);
29
+ return true;
30
+ } else {
31
+ await setChatsPrivateStoreRequest(
32
+ client,
33
+ populateChats(chats, timestamp.toString())
34
+ );
35
+ return true;
36
+ }
37
+ }
@@ -0,0 +1,10 @@
1
+ import { Client, xml } from '@xmpp/client';
2
+ import { store } from '../../roomStore';
3
+ import { presenceInRoom } from './presenceInRoom.xmpp';
4
+
5
+ export async function allRoomPresences(client: Client) {
6
+ const rooms = store.getState().rooms.rooms;
7
+ await Promise.all(
8
+ Object.keys(rooms).map((roomJid) => presenceInRoom(client, roomJid))
9
+ );
10
+ }
@@ -0,0 +1,26 @@
1
+ import { Client } from '@xmpp/client';
2
+ import { createRoomPresence } from './createRoomPresence.xmpp';
3
+ import { setMeAsOwner } from './setMeAsOwner.xmpp';
4
+ import { roomConfig } from './roomConfig.xmpp';
5
+ import { CONFERENCE_DOMAIN } from '../../helpers/constants/PLATFORM_CONSTANTS';
6
+
7
+ export async function createPrivateRoom(
8
+ title: string,
9
+ description: string,
10
+ to: string,
11
+ client: Client
12
+ ) {
13
+ console.log(title, description, to);
14
+
15
+ const roomHash = to;
16
+ const roomId = `${roomHash}${CONFERENCE_DOMAIN}`;
17
+
18
+ try {
19
+ await createRoomPresence(roomId, client);
20
+ await setMeAsOwner(roomId, client);
21
+ await roomConfig(roomId, title, description, client);
22
+ } catch (error) {
23
+ console.log(error);
24
+ }
25
+ return roomId;
26
+ }
@@ -0,0 +1,35 @@
1
+ import { sha256 } from 'js-sha256';
2
+
3
+ import { Client } from '@xmpp/client';
4
+ import { createRoomPresence } from './createRoomPresence.xmpp';
5
+ import { setMeAsOwner } from './setMeAsOwner.xmpp';
6
+ import { roomConfig } from './roomConfig.xmpp';
7
+ import { CONFERENCE_DOMAIN } from '../../helpers/constants/PLATFORM_CONSTANTS';
8
+ import { pushSubscriptionService } from '../../services/pushSubscriptionService';
9
+
10
+ export async function createRoom(
11
+ title: string,
12
+ description: string,
13
+ client: Client
14
+ ) {
15
+ const randomNumber = Math.round(Math.random() * 100_000);
16
+ const chatNameWithSalt = title + Date.now() + randomNumber;
17
+ const roomHash = sha256(chatNameWithSalt);
18
+ const roomId = `${roomHash}${CONFERENCE_DOMAIN}`;
19
+
20
+ try {
21
+ await createRoomPresence(roomId, client);
22
+ await setMeAsOwner(roomId, client);
23
+ await roomConfig(roomId, title, description, client);
24
+
25
+ const userNick = client.jid?.getLocal();
26
+ await pushSubscriptionService
27
+ .subscribeToRoom(client, roomId, userNick)
28
+ .catch((error) => {
29
+ console.error('Failed to subscribe to new room for push:', error);
30
+ });
31
+ } catch (error) {
32
+ console.log(error);
33
+ }
34
+ return roomId;
35
+ }