@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,266 @@
1
+ /** @format */
2
+
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import { IConfig } from '../types/types';
6
+ import XmppClient from '../networking/xmppClient';
7
+ import { AppDispatch, RootState } from '../roomStore';
8
+ import { useXmppClient } from '../context/xmppProvider';
9
+ import { chatAutoEnterer } from '../helpers/chatAutoEnterer';
10
+ import { initRoomsPresence } from '../helpers/initRoomsPresence';
11
+ import { updatedChatLastTimestamps } from '../helpers/updatedChatLastTimestamps';
12
+ import { updateMessagesTillLast } from '../helpers/updateMessagesTillLast';
13
+ import { refresh } from '../networking/apiClient';
14
+ import { setLangSource, setConfig } from '../roomStore/chatSettingsSlice';
15
+ import { setIsLoading } from '../roomStore/roomsSlice';
16
+ import { useRoomState } from './useRoomState';
17
+ import { useChatSettingState } from './useChatSettingState';
18
+ import { isChatIdPresentInArray } from '../helpers/isChatIdPresentInArray';
19
+ import useGetNewArchRoom from './useGetNewArchRoom';
20
+ import { getRoomsWithRetry } from '../helpers/getRoomsWithRetry';
21
+
22
+ interface useChatWrapperInitProps {
23
+ roomJID: string | null | undefined;
24
+ wasAutoSelected: boolean;
25
+ config: IConfig;
26
+ }
27
+
28
+ interface useChatWrapperInitResult {
29
+ inited: boolean;
30
+ isRetrying: boolean | 'norooms';
31
+ showModal: boolean;
32
+ setInited: React.Dispatch<React.SetStateAction<boolean>>;
33
+ setShowModal: React.Dispatch<React.SetStateAction<boolean>>;
34
+ client: XmppClient | null;
35
+ setClient: React.Dispatch<React.SetStateAction<XmppClient | null>>;
36
+ isConnectionLost: boolean;
37
+ }
38
+
39
+ const useChatWrapperInit = ({
40
+ roomJID,
41
+ wasAutoSelected,
42
+ config,
43
+ }: useChatWrapperInitProps): useChatWrapperInitResult => {
44
+ const dispatch = useDispatch<AppDispatch>();
45
+ const [inited, setInited] = useState<boolean>(false);
46
+ const [showModal, setShowModal] = useState<boolean>(false);
47
+ const [isConnectionLost, setConnectionLost] = useState<boolean>(false);
48
+ const [isRetrying, setIsRetrying] = useState<boolean | 'norooms'>(false);
49
+ const hasSyncedHistoryRef = useRef<boolean>(false);
50
+
51
+ const { client, initializeClient, setClient } = useXmppClient();
52
+ const syncRooms = useGetNewArchRoom();
53
+
54
+ const { rooms } = useSelector((state: RootState) => state.rooms);
55
+ const { roomsList } = useRoomState();
56
+ const { user } = useChatSettingState();
57
+
58
+ useEffect(() => {
59
+ return () => {
60
+ if (client && user.xmppPassword === '') {
61
+ console.log('closing client');
62
+ client.close();
63
+ setClient(null);
64
+ }
65
+ };
66
+ }, [user.xmppPassword]);
67
+
68
+ const getRoomsWithRertyRequest = async () => {
69
+ setIsRetrying(true);
70
+ const retryRooms = await getRoomsWithRetry(
71
+ client,
72
+ config,
73
+ syncRooms,
74
+ roomJID
75
+ );
76
+ if (!retryRooms) {
77
+ setIsRetrying('norooms');
78
+ return;
79
+ }
80
+ setIsRetrying(false);
81
+ };
82
+
83
+ const loadRooms = async (
84
+ client: XmppClient,
85
+ disableLoad: boolean = false
86
+ ) => {
87
+ !disableLoad &&
88
+ dispatch(
89
+ setIsLoading({ loading: true, loadingText: 'Loading rooms...' })
90
+ );
91
+ const rooms = await syncRooms(client, config);
92
+ dispatch(setIsLoading({ loading: false, loadingText: undefined }));
93
+ return rooms;
94
+ };
95
+
96
+ useEffect(() => {
97
+ let retryTimeout: NodeJS.Timeout;
98
+
99
+ const initXmmpClient = async () => {
100
+ if (config?.translates?.enabled && !config?.translates?.translations) {
101
+ dispatch(setLangSource(config?.translates?.translations));
102
+ }
103
+
104
+ dispatch(setConfig(config));
105
+ try {
106
+ if (!user.xmppUsername) {
107
+ setShowModal(true);
108
+ console.error('Error, no user');
109
+ } else {
110
+ chatAutoEnterer({ roomJID, wasAutoSelected, config, dispatch });
111
+
112
+ if (!client) {
113
+ try {
114
+ setInited(false);
115
+ setShowModal(false);
116
+
117
+ console.log(' No client, initializing one');
118
+ const newClient = await initializeClient(
119
+ user.xmppUsername || user?.defaultWallet?.walletAddress,
120
+ user?.xmppPassword,
121
+ config?.xmppSettings,
122
+ roomsList
123
+ ).then((client) => {
124
+ console.log(' Client initialized', client?.status);
125
+ return client;
126
+ });
127
+
128
+ if (roomsList && Object.keys(roomsList).length > 0) {
129
+ console.log(
130
+ ' Using existing roomsList',
131
+ Object.keys(roomsList).length
132
+ );
133
+ setInited(true);
134
+ await initRoomsPresence(newClient, roomsList);
135
+ } else {
136
+ if (config?.newArch) {
137
+ console.log(' Loading rooms with newArch');
138
+ const loadedRooms = await loadRooms(newClient);
139
+ console.log(' Loaded rooms', loadedRooms?.length || 0);
140
+ if (config?.enableRoomsRetry?.enabled) {
141
+ const isSelectedRoomPresent = isChatIdPresentInArray(
142
+ roomJID,
143
+ loadedRooms
144
+ );
145
+ console.log(
146
+ ' Selected room present?',
147
+ isSelectedRoomPresent,
148
+ roomJID
149
+ );
150
+ if (!isSelectedRoomPresent) {
151
+ await getRoomsWithRertyRequest();
152
+ }
153
+ }
154
+ setInited(true);
155
+ } else {
156
+ console.log(' Using old arch, getting rooms stanza');
157
+ await newClient.getRoomsStanza();
158
+ }
159
+ }
160
+ await newClient
161
+ .getChatsPrivateStoreRequestStanza()
162
+ .then(
163
+ async (
164
+ roomTimestampObject: [jid: string, timestamp: string]
165
+ ) => {
166
+ console.log(
167
+ 'Got chats private store',
168
+ roomTimestampObject?.length || 0
169
+ );
170
+ updatedChatLastTimestamps(roomTimestampObject, dispatch);
171
+ if (!hasSyncedHistoryRef.current) {
172
+ console.log('Updating messages till last');
173
+ await updateMessagesTillLast(rooms, newClient);
174
+ hasSyncedHistoryRef.current = true;
175
+ }
176
+ setClient(newClient);
177
+ setConnectionLost(false);
178
+ console.log('Initialization complete');
179
+ }
180
+ );
181
+
182
+ {
183
+ config?.refreshTokens?.enabled && refresh();
184
+ }
185
+ } catch (error) {
186
+ console.error(' Error during initialization', error);
187
+ setConnectionLost(true);
188
+ retryTimeout = setTimeout(initXmmpClient, 5000);
189
+ }
190
+ } else {
191
+ if (config?.newArch) {
192
+ if (config?.enableRoomsRetry?.enabled) {
193
+ const isSelectedRoomPresent = isChatIdPresentInArray(
194
+ roomJID,
195
+ roomsList
196
+ );
197
+ console.log(
198
+ 'Selected room present in existing client?',
199
+ isSelectedRoomPresent
200
+ );
201
+ if (!isSelectedRoomPresent) {
202
+ await getRoomsWithRertyRequest();
203
+ }
204
+ }
205
+ }
206
+ setInited(true);
207
+ console.log(' Getting chats private store for existing client');
208
+ await client
209
+ .getChatsPrivateStoreRequestStanza()
210
+ .then(
211
+ async (
212
+ roomTimestampObject: [jid: string, timestamp: string]
213
+ ) => {
214
+ console.log(
215
+ 'Got chats private store for existing client',
216
+ roomTimestampObject?.length || 0
217
+ );
218
+ updatedChatLastTimestamps(roomTimestampObject, dispatch);
219
+ if (!hasSyncedHistoryRef.current) {
220
+ console.log(
221
+ 'Updating messages till last for existing client'
222
+ );
223
+ await updateMessagesTillLast(rooms, client);
224
+ hasSyncedHistoryRef.current = true;
225
+ }
226
+ setClient(client);
227
+ setConnectionLost(false);
228
+ console.log(' Initialization complete for existing client');
229
+ }
230
+ );
231
+ {
232
+ config?.refreshTokens?.enabled && refresh();
233
+ }
234
+ }
235
+ }
236
+ dispatch(setIsLoading({ loading: false }));
237
+ } catch (error) {
238
+ console.error(' Fatal error', error);
239
+ setShowModal(false);
240
+ setConnectionLost(true);
241
+ setInited(false);
242
+ dispatch(setIsLoading({ loading: false }));
243
+ retryTimeout = setTimeout(initXmmpClient, 5000);
244
+ }
245
+ };
246
+
247
+ initXmmpClient();
248
+
249
+ return () => {
250
+ clearTimeout(retryTimeout);
251
+ };
252
+ }, [user.xmppPassword, user.xmppUsername]);
253
+
254
+ return {
255
+ client,
256
+ inited,
257
+ isRetrying,
258
+ showModal,
259
+ isConnectionLost,
260
+ setClient,
261
+ setInited,
262
+ setShowModal,
263
+ };
264
+ };
265
+
266
+ export default useChatWrapperInit;
@@ -0,0 +1,59 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ import { useXmppClient } from '../context/xmppProvider';
3
+ import { useSelector } from 'react-redux';
4
+ import { RootState } from '../roomStore';
5
+ import { useChatSettingState } from './useChatSettingState';
6
+ import { IConfig } from '../types/types';
7
+
8
+ const useComposing = (config?: IConfig) => {
9
+ const { client } = useXmppClient();
10
+ const { activeRoomJID } = useSelector((state: RootState) => state.rooms);
11
+ const { user } = useChatSettingState();
12
+
13
+ const sendStartComposing = useCallback(() => {
14
+ console.log('🟣 [useComposing] start', {
15
+ hasClient: !!client,
16
+ room: activeRoomJID,
17
+ disabled: !!config?.disableTypingIndicator,
18
+ });
19
+ if (config?.disableTypingIndicator) {
20
+ return;
21
+ }
22
+ if (client) {
23
+ client.sendTypingRequestStanza(
24
+ activeRoomJID || '',
25
+ `${user.firstName} ${user.lastName}`,
26
+ true
27
+ );
28
+ }
29
+ }, [activeRoomJID, client, config?.disableTypingIndicator, user.firstName, user.lastName]);
30
+
31
+ const sendEndComposing = useCallback(() => {
32
+ console.log('🟣 [useComposing] end', {
33
+ hasClient: !!client,
34
+ room: activeRoomJID,
35
+ });
36
+ if (config?.disableTypingIndicator) {
37
+ return;
38
+ }
39
+ if (client) {
40
+ client.sendTypingRequestStanza(
41
+ activeRoomJID || '',
42
+ `${user.firstName} ${user.lastName}`,
43
+ false
44
+ );
45
+ }
46
+ }, [activeRoomJID, client, config?.disableTypingIndicator, user.firstName, user.lastName]);
47
+
48
+ useEffect(() => {
49
+ const timerId = setTimeout(() => {
50
+ sendEndComposing();
51
+ }, 100);
52
+
53
+ return () => clearTimeout(timerId);
54
+ }, [sendEndComposing]);
55
+
56
+ return { sendStartComposing, sendEndComposing };
57
+ };
58
+
59
+ export default useComposing;
@@ -0,0 +1,193 @@
1
+ import { useCallback, useMemo } from 'react';
2
+ import { useSelector } from 'react-redux';
3
+ import { useChatSettingState } from './useChatSettingState';
4
+ import {
5
+ generateDefaultText,
6
+ generateProcessingText,
7
+ } from '../components/styled/StyledInputComponents/CustomTypingIndicator';
8
+ import { RootState } from '../roomStore';
9
+
10
+ /**
11
+ * Hook for managing custom typing indicator functionality
12
+ * Provides utilities for text generation and typing state management
13
+ */
14
+ export const useCustomTypingIndicator = (roomJID: string) => {
15
+ const { config } = useChatSettingState();
16
+ const { rooms } = useSelector((state: RootState) => ({
17
+ rooms: state.rooms.rooms,
18
+ }));
19
+
20
+ const room = rooms[roomJID];
21
+ const isComposing = room?.composing || false;
22
+ const composingList = room?.composingList || [];
23
+
24
+ // Generate text based on configuration
25
+ const getTypingText = useCallback(
26
+ (customText?: string | ((usersTyping: string[]) => string)) => {
27
+ if (typeof customText === 'function') {
28
+ return customText(composingList);
29
+ } else if (typeof customText === 'string') {
30
+ return customText;
31
+ } else {
32
+ return generateDefaultText(composingList);
33
+ }
34
+ },
35
+ [composingList]
36
+ );
37
+
38
+ // Generate processing text (for AI/processing states)
39
+ const getProcessingText = useCallback(() => {
40
+ return generateProcessingText(composingList);
41
+ }, [composingList]);
42
+
43
+ // Check if custom typing indicator is enabled
44
+ const isCustomTypingEnabled = useMemo(() => {
45
+ return config?.customTypingIndicator?.enabled || false;
46
+ }, [config?.customTypingIndicator?.enabled]);
47
+
48
+ // Get typing indicator configuration
49
+ const typingConfig = useMemo(() => {
50
+ return config?.customTypingIndicator || null;
51
+ }, [config?.customTypingIndicator]);
52
+
53
+ // Check if indicator should be visible
54
+ const shouldShowIndicator = useMemo(() => {
55
+ return isComposing && composingList.length > 0;
56
+ }, [isComposing, composingList.length]);
57
+
58
+ // Get position-specific styles
59
+ const getPositionStyles = useCallback(
60
+ (position: string) => {
61
+ const baseStyles = typingConfig?.styles || {};
62
+
63
+ switch (position) {
64
+ case 'top':
65
+ return {
66
+ ...baseStyles,
67
+ position: 'absolute',
68
+ top: '8px',
69
+ left: '16px',
70
+ right: '16px',
71
+ background: 'rgba(255, 255, 255, 0.95)',
72
+ padding: '8px 12px',
73
+ borderRadius: '8px',
74
+ boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
75
+ backdropFilter: 'blur(10px)',
76
+ };
77
+ case 'overlay':
78
+ return {
79
+ ...baseStyles,
80
+ position: 'fixed',
81
+ top: '50%',
82
+ left: '50%',
83
+ transform: 'translate(-50%, -50%)',
84
+ background: 'rgba(0, 0, 0, 0.8)',
85
+ color: 'white',
86
+ padding: '16px 24px',
87
+ borderRadius: '12px',
88
+ backdropFilter: 'blur(10px)',
89
+ };
90
+ case 'floating':
91
+ return {
92
+ ...baseStyles,
93
+ position: 'fixed',
94
+ bottom: '80px',
95
+ right: '20px',
96
+ background: 'rgba(255, 255, 255, 0.95)',
97
+ padding: '12px 16px',
98
+ borderRadius: '20px',
99
+ boxShadow: '0 4px 16px rgba(0, 0, 0, 0.15)',
100
+ backdropFilter: 'blur(10px)',
101
+ };
102
+ case 'bottom':
103
+ default:
104
+ return {
105
+ ...baseStyles,
106
+ position: 'static',
107
+ padding: '8px 0',
108
+ };
109
+ }
110
+ },
111
+ [typingConfig?.styles]
112
+ );
113
+
114
+ return {
115
+ isComposing,
116
+ composingList,
117
+ isCustomTypingEnabled,
118
+ typingConfig,
119
+ shouldShowIndicator,
120
+ getTypingText,
121
+ getProcessingText,
122
+ getPositionStyles,
123
+ };
124
+ };
125
+
126
+ /**
127
+ * Utility functions for creating common typing indicator configurations
128
+ */
129
+ export const createTypingIndicatorConfigs = {
130
+ // Default typing indicator
131
+ default: {
132
+ enabled: true,
133
+ position: 'bottom' as const,
134
+ },
135
+
136
+ // Processing state indicator
137
+ processing: {
138
+ enabled: true,
139
+ position: 'overlay' as const,
140
+ text: (usersTyping: string[]) => generateProcessingText(usersTyping),
141
+ styles: {
142
+ background: 'rgba(0, 0, 0, 0.8)',
143
+ color: 'white',
144
+ fontSize: '16px',
145
+ fontWeight: '500',
146
+ },
147
+ },
148
+
149
+ // Floating indicator
150
+ floating: {
151
+ enabled: true,
152
+ position: 'floating' as const,
153
+ styles: {
154
+ background: 'rgba(255, 255, 255, 0.95)',
155
+ color: '#333',
156
+ fontSize: '14px',
157
+ fontWeight: '500',
158
+ boxShadow: '0 4px 16px rgba(0, 0, 0, 0.15)',
159
+ },
160
+ },
161
+
162
+ // Top positioned indicator
163
+ top: {
164
+ enabled: true,
165
+ position: 'top' as const,
166
+ styles: {
167
+ background: 'rgba(255, 255, 255, 0.95)',
168
+ color: '#555',
169
+ fontSize: '14px',
170
+ fontWeight: '500',
171
+ boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
172
+ },
173
+ },
174
+
175
+ // Custom text examples
176
+ customTexts: {
177
+ aiProcessing: (usersTyping: string[]) => {
178
+ const states = ['thinking', 'processing', 'generating answer'];
179
+ const randomState = states[Math.floor(Math.random() * states.length)];
180
+ return `${usersTyping[0]} is ${randomState}`;
181
+ },
182
+
183
+ simple: (usersTyping: string[]) => {
184
+ return `${usersTyping.length} user${usersTyping.length > 1 ? 's' : ''} typing...`;
185
+ },
186
+
187
+ minimal: (usersTyping: string[]) => {
188
+ return '...';
189
+ },
190
+ },
191
+ };
192
+
193
+ export default useCustomTypingIndicator;
@@ -0,0 +1,81 @@
1
+ import { useCallback } from 'react';
2
+ import { IConfig } from '../types/types';
3
+
4
+ interface MessageSentEvent {
5
+ message: string;
6
+ roomJID: string;
7
+ user: any;
8
+ messageType: 'text' | 'media';
9
+ metadata?: any;
10
+ }
11
+
12
+ interface MessageFailedEvent {
13
+ message: string;
14
+ roomJID: string;
15
+ error: Error;
16
+ messageType: 'text' | 'media';
17
+ }
18
+
19
+ interface MessageEditedEvent {
20
+ messageId: string;
21
+ newMessage: string;
22
+ roomJID: string;
23
+ user: any;
24
+ }
25
+
26
+ export interface EventHandlersHook {
27
+ handleMessageSent: (event: MessageSentEvent) => Promise<void>;
28
+ handleMessageFailed: (event: MessageFailedEvent) => void;
29
+ handleMessageEdited: (event: MessageEditedEvent) => void;
30
+ }
31
+
32
+ export const useEventHandlers = (config?: IConfig): EventHandlersHook => {
33
+ const handleMessageSent = useCallback(
34
+ async (event: MessageSentEvent) => {
35
+ try {
36
+ if (config?.eventHandlers?.onMessageSent) {
37
+ await config.eventHandlers.onMessageSent(event);
38
+ }
39
+ } catch (error) {
40
+ console.error('Error in message sent handler:', error);
41
+ throw error;
42
+ }
43
+ },
44
+ [config]
45
+ );
46
+
47
+ const handleMessageFailed = useCallback(
48
+ (event: MessageFailedEvent) => {
49
+ try {
50
+ if (config?.eventHandlers?.onMessageFailed) {
51
+ config.eventHandlers.onMessageFailed(event);
52
+ }
53
+ console.error('Message failed details:', {
54
+ message: event.message,
55
+ roomJID: event.roomJID,
56
+ messageType: event.messageType,
57
+ error: event.error?.message,
58
+ timestamp: new Date().toISOString(),
59
+ });
60
+ } catch (handlerError) {
61
+ console.error('Error in message failed handler:', handlerError);
62
+ }
63
+ },
64
+ [config]
65
+ );
66
+
67
+ const handleMessageEdited = useCallback(
68
+ (event: MessageEditedEvent) => {
69
+ try {
70
+ if (config?.eventHandlers?.onMessageEdited) {
71
+ config.eventHandlers.onMessageEdited(event);
72
+ }
73
+ } catch (error) {
74
+ console.error('Error in message edited handler:', error);
75
+ }
76
+ },
77
+ [config]
78
+ );
79
+
80
+ return { handleMessageSent, handleMessageFailed, handleMessageEdited };
81
+ };
@@ -0,0 +1,57 @@
1
+ import { useCallback } from 'react';
2
+ import { useAppDispatch } from './hooks';
3
+ import { useXmppClient } from '../context/xmppProvider';
4
+ import { createRoomFromApi } from '../helpers/createRoomFromApi';
5
+ import { getRooms } from '../networking/api-requests/rooms.api';
6
+ import {
7
+ addRoomViaApi,
8
+ setIsLoading,
9
+ updateUsersSet,
10
+ } from '../roomStore/roomsSlice';
11
+ import { ApiRoom } from '../types/types';
12
+ import { pushSubscriptionService } from '../services/pushSubscriptionService';
13
+
14
+ const useGetNewArchRoom = () => {
15
+ const { client } = useXmppClient();
16
+ const dispatch = useAppDispatch();
17
+
18
+ const syncRooms = useCallback(
19
+ async (client: any, config: any): Promise<ApiRoom[]> => {
20
+ const rooms = await getRooms();
21
+ const roomJIDs: string[] = [];
22
+
23
+ rooms?.items?.forEach((room) => {
24
+ const createdRoom = createRoomFromApi(room, config?.xmppSettings?.conference);
25
+ if (createdRoom) {
26
+ dispatch(
27
+ addRoomViaApi({
28
+ room: createdRoom,
29
+ xmpp: client,
30
+ })
31
+ );
32
+ if (createdRoom.jid) {
33
+ roomJIDs.push(createdRoom.jid);
34
+ }
35
+ }
36
+ });
37
+ dispatch(setIsLoading({ loading: false, loadingText: undefined }));
38
+ dispatch(updateUsersSet({ rooms: rooms.items || [] }));
39
+
40
+ if (client?.client && roomJIDs.length > 0) {
41
+ const userNick = client.client.jid?.getLocal();
42
+ await pushSubscriptionService
43
+ .subscribeToRooms(client.client, roomJIDs, userNick)
44
+ .catch((error) => {
45
+ console.error('Failed to subscribe to loaded rooms for push:', error);
46
+ });
47
+ }
48
+
49
+ return rooms?.items || [];
50
+ },
51
+ [dispatch]
52
+ );
53
+
54
+ return syncRooms;
55
+ };
56
+
57
+ export default useGetNewArchRoom;