@ethora/chat-component-rn 26.5.7 → 26.5.11

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 (417) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +95 -10
  3. package/index.js +24 -0
  4. package/lib/commonjs/assets/icons.js +5 -1
  5. package/lib/commonjs/assets/icons.js.map +1 -1
  6. package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js +11 -5
  7. package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js.map +1 -1
  8. package/lib/commonjs/components/MainComponents/ChatHeader.js +31 -16
  9. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  10. package/lib/commonjs/components/MainComponents/ChatRoom.js +78 -38
  11. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  12. package/lib/commonjs/components/MainComponents/ChatWrapper.js +74 -27
  13. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  14. package/lib/commonjs/components/MainComponents/MediaMessage.js +16 -11
  15. package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
  16. package/lib/commonjs/components/MainComponents/MessageContainer.js +2 -2
  17. package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
  18. package/lib/commonjs/components/MainComponents/MessageList.js +165 -28
  19. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  20. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +17 -8
  21. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  22. package/lib/commonjs/components/MainComponents/SystemMessage.js +34 -22
  23. package/lib/commonjs/components/MainComponents/SystemMessage.js.map +1 -1
  24. package/lib/commonjs/components/MessageBubble/InteractionsOverlay.js +119 -0
  25. package/lib/commonjs/components/MessageBubble/InteractionsOverlay.js.map +1 -0
  26. package/lib/commonjs/components/MessageBubble/Message.js +122 -41
  27. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  28. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +132 -44
  29. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  30. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +155 -52
  31. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  32. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -5
  33. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  34. package/lib/commonjs/components/Modals/FilePreviewModal/DocumentViewer.js +104 -0
  35. package/lib/commonjs/components/Modals/FilePreviewModal/DocumentViewer.js.map +1 -0
  36. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +144 -24
  37. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  38. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +29 -1
  39. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  40. package/lib/commonjs/components/Modals/Modal/Modal.js +5 -1
  41. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  42. package/lib/commonjs/components/Modals/ModalHeaderComponent.js +10 -0
  43. package/lib/commonjs/components/Modals/ModalHeaderComponent.js.map +1 -1
  44. package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +77 -47
  45. package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
  46. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +3 -3
  47. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  48. package/lib/commonjs/components/Modals/styledModalComponents.js +17 -13
  49. package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
  50. package/lib/commonjs/components/styled/MediaFilePreview.js +47 -28
  51. package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
  52. package/lib/commonjs/components/styled/MessageImage.js +49 -9
  53. package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
  54. package/lib/commonjs/components/styled/NewMessageLabel.js +8 -6
  55. package/lib/commonjs/components/styled/NewMessageLabel.js.map +1 -1
  56. package/lib/commonjs/components/styled/SendInput.js +49 -27
  57. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  58. package/lib/commonjs/components/styled/StyledComponents.js +6 -3
  59. package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
  60. package/lib/commonjs/components/styled/StyledInputComponents/MediaComponents.js +14 -4
  61. package/lib/commonjs/components/styled/StyledInputComponents/MediaComponents.js.map +1 -1
  62. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +7 -2
  63. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  64. package/lib/commonjs/components/styled/UnsupportedType.js +5 -1
  65. package/lib/commonjs/components/styled/UnsupportedType.js.map +1 -1
  66. package/lib/commonjs/components/styled/VideoMessage.js +81 -16
  67. package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
  68. package/lib/commonjs/context/MessageNotificationContext.js +7 -7
  69. package/lib/commonjs/context/MessageNotificationContext.js.map +1 -1
  70. package/lib/commonjs/context/xmppProvider.js +244 -32
  71. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  72. package/lib/commonjs/helpers/chatAutoEnterer.js +2 -7
  73. package/lib/commonjs/helpers/chatAutoEnterer.js.map +1 -1
  74. package/lib/commonjs/helpers/historyPreloadScheduler.js +4 -1
  75. package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
  76. package/lib/commonjs/helpers/insertMessageWithDelimiter.js +15 -5
  77. package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
  78. package/lib/commonjs/helpers/keyboardLayout.js +18 -0
  79. package/lib/commonjs/helpers/keyboardLayout.js.map +1 -0
  80. package/lib/commonjs/helpers/mediaDimensions.js +51 -0
  81. package/lib/commonjs/helpers/mediaDimensions.js.map +1 -0
  82. package/lib/commonjs/helpers/mimeToExtension.js +56 -0
  83. package/lib/commonjs/helpers/mimeToExtension.js.map +1 -1
  84. package/lib/commonjs/helpers/normalizeRoomJid.js +20 -0
  85. package/lib/commonjs/helpers/normalizeRoomJid.js.map +1 -0
  86. package/lib/commonjs/hooks/useChatRoomFocus.js +87 -0
  87. package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -0
  88. package/lib/commonjs/hooks/useHeapSender.js +1 -1
  89. package/lib/commonjs/hooks/useHeapSender.js.map +1 -1
  90. package/lib/commonjs/hooks/useLogout.js +36 -11
  91. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  92. package/lib/commonjs/hooks/usePushNotifications.js +6 -2
  93. package/lib/commonjs/hooks/usePushNotifications.js.map +1 -1
  94. package/lib/commonjs/hooks/useRoomState.js +2 -0
  95. package/lib/commonjs/hooks/useRoomState.js.map +1 -1
  96. package/lib/commonjs/hooks/useSendMessage.js +201 -10
  97. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  98. package/lib/commonjs/hooks/useUnreadMessagesCounter.js +12 -14
  99. package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
  100. package/lib/commonjs/main.js +7 -0
  101. package/lib/commonjs/main.js.map +1 -1
  102. package/lib/commonjs/networking/api-requests/auth.api.js +67 -0
  103. package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
  104. package/lib/commonjs/networking/api-requests/rooms.api.js +29 -4
  105. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  106. package/lib/commonjs/networking/apiClient.js +2 -1
  107. package/lib/commonjs/networking/apiClient.js.map +1 -1
  108. package/lib/commonjs/networking/outboundQueue.js +92 -0
  109. package/lib/commonjs/networking/outboundQueue.js.map +1 -0
  110. package/lib/commonjs/networking/xmpp/createTimeoutPromise.xmpp.js +4 -1
  111. package/lib/commonjs/networking/xmpp/createTimeoutPromise.xmpp.js.map +1 -1
  112. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +7 -8
  113. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  114. package/lib/commonjs/networking/xmpp/getRoomsPaged.xmpp.js +26 -3
  115. package/lib/commonjs/networking/xmpp/getRoomsPaged.xmpp.js.map +1 -1
  116. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +26 -8
  117. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  118. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +2 -1
  119. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  120. package/lib/commonjs/networking/xmppClient.js +294 -35
  121. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  122. package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js +22 -6
  123. package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js.map +1 -1
  124. package/lib/commonjs/roomStore/roomsSlice.js +157 -23
  125. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  126. package/lib/commonjs/utils/installPromiseRejectionTracker.js +83 -0
  127. package/lib/commonjs/utils/installPromiseRejectionTracker.js.map +1 -0
  128. package/lib/commonjs/utils/resendMessage.js +1 -1
  129. package/lib/commonjs/utils/resendMessage.js.map +1 -1
  130. package/lib/module/assets/icons.js +5 -1
  131. package/lib/module/assets/icons.js.map +1 -1
  132. package/lib/module/components/ContextMenu/ContextMenuComponents.js +11 -5
  133. package/lib/module/components/ContextMenu/ContextMenuComponents.js.map +1 -1
  134. package/lib/module/components/MainComponents/ChatHeader.js +31 -16
  135. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  136. package/lib/module/components/MainComponents/ChatRoom.js +80 -40
  137. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  138. package/lib/module/components/MainComponents/ChatWrapper.js +74 -27
  139. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  140. package/lib/module/components/MainComponents/MediaMessage.js +17 -12
  141. package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
  142. package/lib/module/components/MainComponents/MessageContainer.js +2 -2
  143. package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
  144. package/lib/module/components/MainComponents/MessageList.js +166 -29
  145. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  146. package/lib/module/components/MainComponents/ReduxWrapper.js +18 -8
  147. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  148. package/lib/module/components/MainComponents/SystemMessage.js +33 -21
  149. package/lib/module/components/MainComponents/SystemMessage.js.map +1 -1
  150. package/lib/module/components/MessageBubble/InteractionsOverlay.js +112 -0
  151. package/lib/module/components/MessageBubble/InteractionsOverlay.js.map +1 -0
  152. package/lib/module/components/MessageBubble/Message.js +123 -42
  153. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  154. package/lib/module/components/MessageBubble/MessageInteractions.js +134 -46
  155. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  156. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +155 -52
  157. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  158. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -5
  159. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  160. package/lib/module/components/Modals/FilePreviewModal/DocumentViewer.js +99 -0
  161. package/lib/module/components/Modals/FilePreviewModal/DocumentViewer.js.map +1 -0
  162. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +148 -26
  163. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  164. package/lib/module/components/Modals/FilePreviewModal/PdfView.js +31 -3
  165. package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  166. package/lib/module/components/Modals/Modal/Modal.js +5 -1
  167. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  168. package/lib/module/components/Modals/ModalHeaderComponent.js +10 -0
  169. package/lib/module/components/Modals/ModalHeaderComponent.js.map +1 -1
  170. package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +79 -49
  171. package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
  172. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +3 -3
  173. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  174. package/lib/module/components/Modals/styledModalComponents.js +17 -13
  175. package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
  176. package/lib/module/components/styled/MediaFilePreview.js +47 -28
  177. package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
  178. package/lib/module/components/styled/MessageImage.js +51 -11
  179. package/lib/module/components/styled/MessageImage.js.map +1 -1
  180. package/lib/module/components/styled/NewMessageLabel.js +8 -6
  181. package/lib/module/components/styled/NewMessageLabel.js.map +1 -1
  182. package/lib/module/components/styled/SendInput.js +50 -28
  183. package/lib/module/components/styled/SendInput.js.map +1 -1
  184. package/lib/module/components/styled/StyledComponents.js +6 -3
  185. package/lib/module/components/styled/StyledComponents.js.map +1 -1
  186. package/lib/module/components/styled/StyledInputComponents/MediaComponents.js +14 -4
  187. package/lib/module/components/styled/StyledInputComponents/MediaComponents.js.map +1 -1
  188. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +7 -2
  189. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  190. package/lib/module/components/styled/UnsupportedType.js +5 -1
  191. package/lib/module/components/styled/UnsupportedType.js.map +1 -1
  192. package/lib/module/components/styled/VideoMessage.js +82 -17
  193. package/lib/module/components/styled/VideoMessage.js.map +1 -1
  194. package/lib/module/context/MessageNotificationContext.js +7 -7
  195. package/lib/module/context/MessageNotificationContext.js.map +1 -1
  196. package/lib/module/context/xmppProvider.js +246 -34
  197. package/lib/module/context/xmppProvider.js.map +1 -1
  198. package/lib/module/helpers/chatAutoEnterer.js +2 -7
  199. package/lib/module/helpers/chatAutoEnterer.js.map +1 -1
  200. package/lib/module/helpers/historyPreloadScheduler.js +4 -1
  201. package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
  202. package/lib/module/helpers/insertMessageWithDelimiter.js +15 -5
  203. package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
  204. package/lib/module/helpers/keyboardLayout.js +12 -0
  205. package/lib/module/helpers/keyboardLayout.js.map +1 -0
  206. package/lib/module/helpers/mediaDimensions.js +46 -0
  207. package/lib/module/helpers/mediaDimensions.js.map +1 -0
  208. package/lib/module/helpers/mimeToExtension.js +55 -0
  209. package/lib/module/helpers/mimeToExtension.js.map +1 -1
  210. package/lib/module/helpers/normalizeRoomJid.js +15 -0
  211. package/lib/module/helpers/normalizeRoomJid.js.map +1 -0
  212. package/lib/module/hooks/useChatRoomFocus.js +82 -0
  213. package/lib/module/hooks/useChatRoomFocus.js.map +1 -0
  214. package/lib/module/hooks/useHeapSender.js +1 -1
  215. package/lib/module/hooks/useHeapSender.js.map +1 -1
  216. package/lib/module/hooks/useLogout.js +36 -11
  217. package/lib/module/hooks/useLogout.js.map +1 -1
  218. package/lib/module/hooks/usePushNotifications.js +6 -2
  219. package/lib/module/hooks/usePushNotifications.js.map +1 -1
  220. package/lib/module/hooks/useRoomState.js +2 -0
  221. package/lib/module/hooks/useRoomState.js.map +1 -1
  222. package/lib/module/hooks/useSendMessage.js +203 -12
  223. package/lib/module/hooks/useSendMessage.js.map +1 -1
  224. package/lib/module/hooks/useUnreadMessagesCounter.js +12 -14
  225. package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
  226. package/lib/module/main.js +1 -0
  227. package/lib/module/main.js.map +1 -1
  228. package/lib/module/networking/api-requests/auth.api.js +67 -1
  229. package/lib/module/networking/api-requests/auth.api.js.map +1 -1
  230. package/lib/module/networking/api-requests/rooms.api.js +29 -4
  231. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  232. package/lib/module/networking/apiClient.js +2 -1
  233. package/lib/module/networking/apiClient.js.map +1 -1
  234. package/lib/module/networking/outboundQueue.js +84 -0
  235. package/lib/module/networking/outboundQueue.js.map +1 -0
  236. package/lib/module/networking/xmpp/createTimeoutPromise.xmpp.js +4 -1
  237. package/lib/module/networking/xmpp/createTimeoutPromise.xmpp.js.map +1 -1
  238. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +7 -8
  239. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  240. package/lib/module/networking/xmpp/getRoomsPaged.xmpp.js +26 -3
  241. package/lib/module/networking/xmpp/getRoomsPaged.xmpp.js.map +1 -1
  242. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +26 -8
  243. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  244. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +2 -1
  245. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  246. package/lib/module/networking/xmppClient.js +294 -35
  247. package/lib/module/networking/xmppClient.js.map +1 -1
  248. package/lib/module/roomStore/Middleware/unreadMidlleware.js +22 -6
  249. package/lib/module/roomStore/Middleware/unreadMidlleware.js.map +1 -1
  250. package/lib/module/roomStore/roomsSlice.js +154 -22
  251. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  252. package/lib/module/utils/installPromiseRejectionTracker.js +78 -0
  253. package/lib/module/utils/installPromiseRejectionTracker.js.map +1 -0
  254. package/lib/module/utils/resendMessage.js +1 -1
  255. package/lib/module/utils/resendMessage.js.map +1 -1
  256. package/lib/typescript/assets/icons.d.ts +8 -4
  257. package/lib/typescript/assets/icons.d.ts.map +1 -1
  258. package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts.map +1 -1
  259. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  260. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  261. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  262. package/lib/typescript/components/MainComponents/MediaMessage.d.ts +1 -0
  263. package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
  264. package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
  265. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  266. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts +1 -0
  267. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  268. package/lib/typescript/components/MainComponents/SystemMessage.d.ts +0 -7
  269. package/lib/typescript/components/MainComponents/SystemMessage.d.ts.map +1 -1
  270. package/lib/typescript/components/MessageBubble/InteractionsOverlay.d.ts +13 -0
  271. package/lib/typescript/components/MessageBubble/InteractionsOverlay.d.ts.map +1 -0
  272. package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
  273. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts +4 -2
  274. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  275. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  276. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  277. package/lib/typescript/components/Modals/FilePreviewModal/DocumentViewer.d.ts +29 -0
  278. package/lib/typescript/components/Modals/FilePreviewModal/DocumentViewer.d.ts.map +1 -0
  279. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts +0 -1
  280. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  281. package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
  282. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  283. package/lib/typescript/components/Modals/ModalHeaderComponent.d.ts.map +1 -1
  284. package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
  285. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  286. package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
  287. package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
  288. package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
  289. package/lib/typescript/components/styled/NewMessageLabel.d.ts +1 -5
  290. package/lib/typescript/components/styled/NewMessageLabel.d.ts.map +1 -1
  291. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  292. package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
  293. package/lib/typescript/components/styled/StyledInputComponents/MediaComponents.d.ts +9 -1
  294. package/lib/typescript/components/styled/StyledInputComponents/MediaComponents.d.ts.map +1 -1
  295. package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
  296. package/lib/typescript/components/styled/UnsupportedType.d.ts +1 -0
  297. package/lib/typescript/components/styled/UnsupportedType.d.ts.map +1 -1
  298. package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
  299. package/lib/typescript/context/xmppProvider.d.ts +1 -0
  300. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  301. package/lib/typescript/helpers/chatAutoEnterer.d.ts.map +1 -1
  302. package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
  303. package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
  304. package/lib/typescript/helpers/keyboardLayout.d.ts +9 -0
  305. package/lib/typescript/helpers/keyboardLayout.d.ts.map +1 -0
  306. package/lib/typescript/helpers/mediaDimensions.d.ts +9 -0
  307. package/lib/typescript/helpers/mediaDimensions.d.ts.map +1 -0
  308. package/lib/typescript/helpers/mimeToExtension.d.ts +8 -0
  309. package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -1
  310. package/lib/typescript/helpers/normalizeRoomJid.d.ts +2 -0
  311. package/lib/typescript/helpers/normalizeRoomJid.d.ts.map +1 -0
  312. package/lib/typescript/hooks/useChatRoomFocus.d.ts +42 -0
  313. package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -0
  314. package/lib/typescript/hooks/useHeapSender.d.ts.map +1 -1
  315. package/lib/typescript/hooks/useLogout.d.ts +23 -1
  316. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  317. package/lib/typescript/hooks/usePushNotifications.d.ts.map +1 -1
  318. package/lib/typescript/hooks/useRoomState.d.ts +1 -0
  319. package/lib/typescript/hooks/useRoomState.d.ts.map +1 -1
  320. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  321. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
  322. package/lib/typescript/main.d.ts +1 -0
  323. package/lib/typescript/main.d.ts.map +1 -1
  324. package/lib/typescript/networking/api-requests/auth.api.d.ts +3 -0
  325. package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
  326. package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
  327. package/lib/typescript/networking/apiClient.d.ts.map +1 -1
  328. package/lib/typescript/networking/outboundQueue.d.ts +57 -0
  329. package/lib/typescript/networking/outboundQueue.d.ts.map +1 -0
  330. package/lib/typescript/networking/xmpp/createTimeoutPromise.xmpp.d.ts.map +1 -1
  331. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +1 -1
  332. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
  333. package/lib/typescript/networking/xmpp/getRoomsPaged.xmpp.d.ts +1 -1
  334. package/lib/typescript/networking/xmpp/getRoomsPaged.xmpp.d.ts.map +1 -1
  335. package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
  336. package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
  337. package/lib/typescript/networking/xmppClient.d.ts +33 -4
  338. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  339. package/lib/typescript/roomStore/Middleware/unreadMidlleware.d.ts.map +1 -1
  340. package/lib/typescript/roomStore/roomsSlice.d.ts +8 -1
  341. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  342. package/lib/typescript/types/models/media.model.d.ts +1 -0
  343. package/lib/typescript/types/models/media.model.d.ts.map +1 -1
  344. package/lib/typescript/types/models/xmpp.model.d.ts +1 -1
  345. package/lib/typescript/types/models/xmpp.model.d.ts.map +1 -1
  346. package/lib/typescript/types/types.d.ts +20 -0
  347. package/lib/typescript/types/types.d.ts.map +1 -1
  348. package/lib/typescript/utils/installPromiseRejectionTracker.d.ts +20 -0
  349. package/lib/typescript/utils/installPromiseRejectionTracker.d.ts.map +1 -0
  350. package/lib/typescript/utils/resendMessage.d.ts.map +1 -1
  351. package/package.json +23 -4
  352. package/src/assets/icons.tsx +23 -14
  353. package/src/components/ContextMenu/ContextMenuComponents.tsx +10 -5
  354. package/src/components/MainComponents/ChatHeader.tsx +46 -15
  355. package/src/components/MainComponents/ChatRoom.tsx +95 -66
  356. package/src/components/MainComponents/ChatWrapper.tsx +127 -42
  357. package/src/components/MainComponents/MediaMessage.tsx +14 -8
  358. package/src/components/MainComponents/MessageContainer.tsx +4 -2
  359. package/src/components/MainComponents/MessageList.tsx +175 -28
  360. package/src/components/MainComponents/ReduxWrapper.tsx +19 -9
  361. package/src/components/MainComponents/SystemMessage.tsx +38 -26
  362. package/src/components/MessageBubble/InteractionsOverlay.tsx +121 -0
  363. package/src/components/MessageBubble/Message.tsx +133 -63
  364. package/src/components/MessageBubble/MessageInteractions.tsx +146 -58
  365. package/src/components/Modals/AttachSheet/AttachSheet.tsx +146 -39
  366. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +25 -3
  367. package/src/components/Modals/FilePreviewModal/DocumentViewer.tsx +93 -0
  368. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +161 -26
  369. package/src/components/Modals/FilePreviewModal/PdfView.tsx +32 -4
  370. package/src/components/Modals/Modal/Modal.tsx +4 -1
  371. package/src/components/Modals/ModalHeaderComponent.tsx +8 -1
  372. package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +70 -58
  373. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -15
  374. package/src/components/Modals/styledModalComponents.tsx +17 -13
  375. package/src/components/styled/MediaFilePreview.tsx +46 -26
  376. package/src/components/styled/MessageImage.tsx +58 -13
  377. package/src/components/styled/NewMessageLabel.tsx +8 -5
  378. package/src/components/styled/SendInput.tsx +64 -29
  379. package/src/components/styled/StyledComponents.ts +6 -3
  380. package/src/components/styled/StyledInputComponents/MediaComponents.tsx +15 -5
  381. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +7 -2
  382. package/src/components/styled/UnsupportedType.tsx +7 -1
  383. package/src/components/styled/VideoMessage.tsx +76 -12
  384. package/src/context/MessageNotificationContext.tsx +8 -8
  385. package/src/context/xmppProvider.tsx +247 -30
  386. package/src/helpers/chatAutoEnterer.ts +2 -8
  387. package/src/helpers/historyPreloadScheduler.ts +4 -1
  388. package/src/helpers/insertMessageWithDelimiter.ts +22 -15
  389. package/src/helpers/keyboardLayout.ts +18 -0
  390. package/src/helpers/mediaDimensions.ts +47 -0
  391. package/src/helpers/mimeToExtension.ts +64 -0
  392. package/src/helpers/normalizeRoomJid.ts +6 -0
  393. package/src/hooks/useChatRoomFocus.ts +95 -0
  394. package/src/hooks/useHeapSender.tsx +2 -1
  395. package/src/hooks/useLogout.tsx +36 -13
  396. package/src/hooks/usePushNotifications.ts +21 -8
  397. package/src/hooks/useRoomState.tsx +4 -0
  398. package/src/hooks/useSendMessage.tsx +258 -13
  399. package/src/hooks/useUnreadMessagesCounter.ts +13 -16
  400. package/src/main.ts +1 -0
  401. package/src/networking/api-requests/auth.api.ts +55 -1
  402. package/src/networking/api-requests/rooms.api.ts +31 -7
  403. package/src/networking/apiClient.ts +2 -1
  404. package/src/networking/outboundQueue.ts +98 -0
  405. package/src/networking/xmpp/createTimeoutPromise.xmpp.ts +5 -1
  406. package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +11 -13
  407. package/src/networking/xmpp/getRoomsPaged.xmpp.ts +27 -3
  408. package/src/networking/xmpp/presenceInRoom.xmpp.ts +24 -9
  409. package/src/networking/xmpp/sendTextMessage.xmpp.ts +2 -1
  410. package/src/networking/xmppClient.ts +317 -43
  411. package/src/roomStore/Middleware/unreadMidlleware.tsx +23 -5
  412. package/src/roomStore/roomsSlice.ts +177 -27
  413. package/src/types/models/media.model.ts +3 -0
  414. package/src/types/models/xmpp.model.ts +2 -1
  415. package/src/types/types.ts +31 -0
  416. package/src/utils/installPromiseRejectionTracker.ts +91 -0
  417. package/src/utils/resendMessage.ts +2 -1
@@ -71,10 +71,15 @@ export const Overlay = styled.Pressable`
71
71
  background: transparent;
72
72
  `;
73
73
 
74
+ // Horizontal hairline divider. Was `border: 1px solid …` — a border on
75
+ // ALL FOUR sides of an auto-sized View. iOS collapsed it to ~nothing, but
76
+ // Android rendered the side borders too, so the menu showed ugly little
77
+ // boxes / uneven gaps between items. A single full-width 1px line renders
78
+ // identically on both platforms.
74
79
  export const Delimeter = styled.View`
75
- border: 1px solid #0052cd0d;
80
+ height: 1px;
81
+ align-self: stretch;
82
+ background-color: #0052cd1f;
83
+ margin-top: 4px;
84
+ margin-bottom: 4px;
76
85
  `;
77
-
78
- // export const Delimeter = styled.View`
79
- // border: 1px solid var(--colors-background-bg-prymary-5, #0052cd0d);
80
- // `;
@@ -65,6 +65,14 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
65
65
  config?.headerChatMenu && config?.headerChatMenu();
66
66
  };
67
67
 
68
+ // Shared open-chat-info handler used by BOTH the outer touchable row
69
+ // and the avatar's own press (the avatar otherwise absorbs taps without
70
+ // bubbling — see the comment on ProfileImagePlaceholder below).
71
+ const openChatInfo = useCallback(
72
+ () => dispatch(setActiveModal(MODAL_TYPES.CHAT_PROFILE)),
73
+ [dispatch]
74
+ );
75
+
68
76
  return (
69
77
  <>
70
78
  <ChatContainerHeader>
@@ -85,11 +93,14 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
85
93
  onPress={handleHeaderChatMenu}
86
94
  />
87
95
  </View>
88
- ) : (
89
- // Reserve the slot so the title stays centered relative to
90
- // the right-hand actions even when the icon is hidden.
91
- <View style={styles.leftContainer} />
92
- )}
96
+ ) : null
97
+ /* Don't reserve the 15%-wide leftContainer when both the back
98
+ * button is absent AND the burger icon is hidden — the empty
99
+ * slot used to steal width from the title row, clipping the chat
100
+ * name. Customer-reported #15. The right action area still fills
101
+ * its own slot, so the title now starts at the left edge as
102
+ * intended by `disableChatHeaderBurgerMenuIcon`. */
103
+ }
93
104
  <CenterContainer
94
105
  rightSpace={config?.disableRoomConfig}
95
106
  leftSpace={!!config?.headerChatMenu}
@@ -102,17 +113,37 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
102
113
  />
103
114
  )}
104
115
  <ChatContainerHeaderBoxInfo
105
- onPress={() => dispatch(setActiveModal(MODAL_TYPES.CHAT_PROFILE))}
106
- disabled={config?.disableProfilesInteractions}
116
+ onPress={openChatInfo}
117
+ // Gates the entry to the CHAT-INFO modal (room name, members,
118
+ // settings) via the dedicated `disableChatInfo.disableChatHeaderMenu`
119
+ // flag. Previously wired to `disableProfilesInteractions`, which
120
+ // is for USER-profile popups (the in-bubble avatar tap, see
121
+ // Message.tsx) — wrong semantic gate, and it meant a consumer
122
+ // who wanted to hide user profiles also lost their entry to
123
+ // the chat info screen.
124
+ disabled={config?.disableChatInfo?.disableChatHeaderMenu}
107
125
  >
108
- <View>
109
- <ProfileImagePlaceholder
110
- name={currentRoom?.title || currentRoom?.name}
111
- size={40}
112
- icon={currentRoom?.icon}
113
- active={!config?.disableProfilesInteractions || true}
114
- />
115
- </View>
126
+ {/* No wrapping <View> here: ProfileImagePlaceholder renders
127
+ * its avatar as a TouchableOpacity (AvatarCircle) that
128
+ * INTERCEPTS taps even when its own onPress is undefined —
129
+ * so without forwarding a press handler, tapping the chat
130
+ * avatar did nothing (clicks on the name worked because
131
+ * those bubble up to the outer TouchableOpacity). Pass
132
+ * `click` so the avatar fires the same openChatInfo
133
+ * dispatch; the surrounding text + the gap between avatar
134
+ * and text continue to be handled by the outer
135
+ * ChatContainerHeaderBoxInfo. */}
136
+ <ProfileImagePlaceholder
137
+ name={currentRoom?.title || currentRoom?.name}
138
+ size={40}
139
+ icon={currentRoom?.icon}
140
+ active={!config?.disableChatInfo?.disableChatHeaderMenu}
141
+ click={
142
+ config?.disableChatInfo?.disableChatHeaderMenu
143
+ ? undefined
144
+ : { isClick: true, onPress: openChatInfo }
145
+ }
146
+ />
116
147
  <ChatContainerHeaderInfo>
117
148
  <ChatContainerHeaderLabel numberOfLines={1} ellipsizeMode="tail">
118
149
  {currentRoom?.title || currentRoom?.name}
@@ -6,9 +6,11 @@ import { useDispatch } from 'react-redux';
6
6
  import MessageList from './MessageList';
7
7
  import SendInput from '../styled/SendInput';
8
8
  import {
9
+ clearVisibleRoom,
9
10
  deleteRoomMessage,
10
11
  setEditAction,
11
12
  setLastViewedTimestamp,
13
+ setVisibleRoom,
12
14
  } from '../../roomStore/roomsSlice';
13
15
  import Loader from '../styled/Loader';
14
16
  import { useXmppClient } from '../../context/xmppProvider';
@@ -36,6 +38,12 @@ import {
36
38
  } from 'react-native';
37
39
  import { KeyboardAvoidingView } from 'react-native-keyboard-controller';
38
40
  import useComposing from '../../hooks/useComposing';
41
+ import { store } from '../../roomStore';
42
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
43
+ import {
44
+ getInputDockPaddingBottom,
45
+ getKeyboardVerticalOffset,
46
+ } from '../../helpers/keyboardLayout';
39
47
 
40
48
  interface ChatRoomProps {
41
49
  CustomMessageComponent?: any;
@@ -59,6 +67,7 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
59
67
  }) => {
60
68
  const { client } = useXmppClient();
61
69
  const dispatch = useDispatch();
70
+ const insets = useSafeAreaInsets();
62
71
 
63
72
  const [isLoadingMore, setIsLoadingMore] = useState<boolean>(false);
64
73
 
@@ -99,15 +108,9 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
99
108
  if (!activeRoomJID) {
100
109
  return;
101
110
  }
102
- dispatch(
103
- setLastViewedTimestamp({
104
- chatJID: activeRoomJID,
105
- timestamp: 0,
106
- }),
107
- );
108
111
  sendMs(message, activeRoomJID);
109
112
  },
110
- [activeRoomJID],
113
+ [activeRoomJID, sendMs]
111
114
  );
112
115
 
113
116
  const sendMedia = useCallback(
@@ -151,41 +154,47 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
151
154
  dispatch(setEditAction({ isEdit: false }));
152
155
  };
153
156
 
157
+ // Read the latest client through a ref so this effect's setup phase
158
+ // does NOT re-run on every `client` identity change. With `client` in
159
+ // the deps array, a reconnect or any provider re-render would re-fire
160
+ // setup → `dispatch(setVisibleRoom(...))` ~one tick after the host
161
+ // cleared visibility via the `isVisible` prop (XmppProvider) — racing
162
+ // and clobbering it, so `useUnread()` reported 0 in tab-mounted hosts.
163
+ // Customer-reported #19. The cleanup still needs the live client for
164
+ // flushLastViewedToPrivateStoreStanza, which is what the ref provides.
165
+ const clientRef = useRef(client);
166
+ useEffect(() => {
167
+ clientRef.current = client;
168
+ }, [client]);
169
+
154
170
  useEffect(() => {
155
171
  if (!activeRoomJID) {
156
172
  return;
157
173
  }
158
174
 
159
- dispatch(
160
- setLastViewedTimestamp({
161
- chatJID: activeRoomJID,
162
- timestamp: 0,
163
- }),
164
- );
175
+ dispatch(setVisibleRoom({ roomJID: activeRoomJID }));
165
176
  setIsLoadingMore(false);
166
177
  return () => {
167
- if (client) {
168
- client.actionSetTimestampToPrivateStoreStanza(
169
- activeRoomJID,
170
- new Date().getTime(),
171
- Object.keys(roomsList),
172
- );
173
- }
178
+ const timestamp = new Date().getTime();
174
179
  dispatch(
175
180
  setLastViewedTimestamp({
176
181
  chatJID: activeRoomJID,
177
- timestamp: new Date().getTime(),
178
- }),
179
- );
180
- dispatch(
181
- deleteRoomMessage({
182
- roomJID: activeRoomJID,
183
- messageId: 'delimiter-new',
182
+ timestamp,
184
183
  }),
185
184
  );
185
+ dispatch(clearVisibleRoom());
186
+ const liveClient = clientRef.current;
187
+ if (liveClient) {
188
+ liveClient
189
+ .flushLastViewedToPrivateStoreStanza(store.getState().rooms?.rooms, {
190
+ visibleRoomJID: activeRoomJID,
191
+ })
192
+ .catch(() => {});
193
+ }
194
+ dispatch(deleteRoomMessage({ roomJID: activeRoomJID, messageId: 'delimiter-new' }));
186
195
  setIsLoadingMore(false);
187
196
  };
188
- }, [activeRoomJID]);
197
+ }, [activeRoomJID, dispatch]);
189
198
 
190
199
  // hooks useEffects
191
200
  // useRoomUrl(activeRoomJID || "", roomsList, config);
@@ -210,16 +219,34 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
210
219
  return <ChooseChatMessage />;
211
220
  }
212
221
 
222
+ const keyboardVerticalOffset = getKeyboardVerticalOffset({
223
+ platform: Platform.OS,
224
+ configuredOffset: configWithEventHandlers?.keyboardVerticalOffset ?? 0,
225
+ bottomInset: insets.bottom,
226
+ });
227
+ const inputDockPaddingBottom = getInputDockPaddingBottom({
228
+ platform: Platform.OS,
229
+ bottomInset: insets.bottom,
230
+ });
231
+
213
232
  return (
214
233
  <KeyboardAvoidingView
215
234
  style={{ flex: 1 }}
216
- // Android: rely on the manifest's `adjustResize` (default). KAV
217
- // behavior="height" on top of adjustResize double-handles the
218
- // resize and causes a visible message-list flicker every time
219
- // the keyboard opens (bug #6). `undefined` makes KAV a no-op on
220
- // Android — the system resize alone shows the input correctly.
221
- behavior={Platform.OS === 'ios' ? 'padding' : undefined}
222
- keyboardVerticalOffset={configWithEventHandlers?.keyboardVerticalOffset ?? 0}
235
+ // Bug #6 history:
236
+ // - Original code: behavior="height" on Android — caused
237
+ // flicker because Android's adjustResize already shrinks
238
+ // the window; KAV resizing on top of that double-resized
239
+ // every keyboard open.
240
+ // - 26.5.6 attempt: behavior={undefined} on Android — input
241
+ // got completely blocked because some host apps disable
242
+ // adjustResize via the activity's softInputMode.
243
+ // - 26.5.8 fix: behavior="padding" on BOTH platforms. Padding
244
+ // adds bottom-padding equal to the keyboard height without
245
+ // changing the layout's height prop — no double-resize on
246
+ // Android, no flicker, and the input is always lifted above
247
+ // the keyboard regardless of the host's softInputMode.
248
+ behavior="padding"
249
+ keyboardVerticalOffset={keyboardVerticalOffset}
223
250
  >
224
251
  <ChatContainer
225
252
  style={
@@ -342,37 +369,39 @@ const ChatRoom: React.FC<ChatRoomProps> = React.memo(
342
369
  {editAction && editAction.isEdit && (
343
370
  <EditWrapper text={editAction.text || ''} onClose={onCloseEdit} />
344
371
  )}
345
- {CustomInputComponent ? (
346
- <CustomInputComponent
347
- sendMessage={
348
- editAction && editAction.isEdit ? sendEditMessage : sendMessage
349
- }
350
- sendMedia={sendMedia}
351
- config={configWithEventHandlers}
352
- isLoading={loading}
353
- onFocus={sendStartComposing}
354
- onBlur={sendEndComposing}
355
- isMessageProcessing={isLastMessageFromUserAndProcessing(
356
- activeRoomJID,
357
- )}
358
- editMessage={editAction && editAction.text}
359
- />
360
- ) : (
361
- <SendInput
362
- editMessage={editAction && editAction.text}
363
- sendMessage={
364
- editAction && editAction.isEdit ? sendEditMessage : sendMessage
365
- }
366
- sendMedia={sendMedia}
367
- config={configWithEventHandlers}
368
- isLoading={loading}
369
- onFocus={sendStartComposing}
370
- onBlur={sendEndComposing}
371
- isMessageProcessing={isLastMessageFromUserAndProcessing(
372
- activeRoomJID,
373
- )}
374
- />
375
- )}
372
+ <View style={{ paddingBottom: inputDockPaddingBottom, backgroundColor: '#fff' }}>
373
+ {CustomInputComponent ? (
374
+ <CustomInputComponent
375
+ sendMessage={
376
+ editAction && editAction.isEdit ? sendEditMessage : sendMessage
377
+ }
378
+ sendMedia={sendMedia}
379
+ config={configWithEventHandlers}
380
+ isLoading={loading}
381
+ onFocus={sendStartComposing}
382
+ onBlur={sendEndComposing}
383
+ isMessageProcessing={isLastMessageFromUserAndProcessing(
384
+ activeRoomJID,
385
+ )}
386
+ editMessage={editAction && editAction.text}
387
+ />
388
+ ) : (
389
+ <SendInput
390
+ editMessage={editAction && editAction.text}
391
+ sendMessage={
392
+ editAction && editAction.isEdit ? sendEditMessage : sendMessage
393
+ }
394
+ sendMedia={sendMedia}
395
+ config={configWithEventHandlers}
396
+ isLoading={loading}
397
+ onFocus={sendStartComposing}
398
+ onBlur={sendEndComposing}
399
+ isMessageProcessing={isLastMessageFromUserAndProcessing(
400
+ activeRoomJID,
401
+ )}
402
+ />
403
+ )}
404
+ </View>
376
405
 
377
406
  {configWithEventHandlers?.customTypingIndicator?.enabled &&
378
407
  (configWithEventHandlers.customTypingIndicator.position ===
@@ -9,6 +9,7 @@ import {
9
9
  } from '../../roomStore/chatSettingsSlice';
10
10
  import {ChatWrapperBox} from '../styled/ChatWrapperBox';
11
11
  import {Overlay, StyledModal} from '../styled/MediaModal';
12
+ import ConnectionBanner from './ConnectionBanner';
12
13
  import {Message} from '../MessageBubble/Message';
13
14
  import {IConfig, IRoom, MessageProps, ModalType, User} from '../../types/types';
14
15
  import {useXmppClient} from '../../context/xmppProvider';
@@ -30,6 +31,8 @@ import {ModalWrapper} from '../Modals/ModalWrapper/ModalWrapper';
30
31
  import {useChatSettingState} from '../../hooks/useChatSettingState';
31
32
  import {DeviceEventEmitter, Pressable, Text, View} from 'react-native';
32
33
  import {pushLog as devPushLog} from '../../utils/devLogger';
34
+ import {normalizeRoomJid} from '../../helpers/normalizeRoomJid';
35
+ import {InteractionsOverlayProvider} from '../MessageBubble/InteractionsOverlay';
33
36
 
34
37
  interface ChatWrapperProps {
35
38
  token?: string;
@@ -126,7 +129,11 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
126
129
 
127
130
  useEffect(() => {
128
131
  if (roomJID) {
129
- dispatch(setCurrentRoom({roomJID: roomJID}));
132
+ dispatch(
133
+ setCurrentRoom({
134
+ roomJID: normalizeRoomJid(roomJID, config?.xmppSettings?.conference),
135
+ }),
136
+ );
130
137
  }
131
138
 
132
139
  const initXmmpClient = async () => {
@@ -186,45 +193,79 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
186
193
 
187
194
  if (!client && !storedClient) {
188
195
  devPushLog('rn', 'ChatWrapper: initing xmpp client (legacy path)');
189
- await initializeClient(
190
- user.xmppUsername || user.defaultWallet?.walletAddress,
191
- user.xmppPassword,
192
- config?.xmppSettings
193
- ).then(c => {
194
- c.getRoomsStanza()
195
- .then(() => {
196
- c.getChatsPrivateStoreRequestStanza();
197
- dispatch(setStoreClient(c));
198
- setClient(c);
199
- })
200
- .catch((err: unknown) => console.warn('getRoomsStanza failed', err));
201
- });
196
+ // The outer `.then(c => {...})` used to lack a `.catch()` —
197
+ // if initializeClient rejected (network / SASL), the outer
198
+ // try/catch couldn't see it because the rejection happens in
199
+ // the .then handler, not in the awaited promise itself.
200
+ // Convert to await + try/catch.
201
+ try {
202
+ const c = await initializeClient(
203
+ user.xmppUsername || user.defaultWallet?.walletAddress,
204
+ user.xmppPassword,
205
+ config?.xmppSettings
206
+ );
207
+ try {
208
+ await c.getRoomsStanza();
209
+ c.getChatsPrivateStoreRequestStanza().catch((err: unknown) =>
210
+ console.warn('getChatsPrivateStoreRequestStanza failed', err)
211
+ );
212
+ dispatch(setStoreClient(c));
213
+ setClient(c);
214
+ } catch (err) {
215
+ console.warn('getRoomsStanza failed', err);
216
+ }
217
+ } catch (err) {
218
+ devPushLog('warn', 'initializeClient failed (legacy path)', err);
219
+ }
202
220
  setInited(true);
203
- if (config?.refreshTokens?.enabled) {refresh();}
221
+ if (config?.refreshTokens?.enabled) {
222
+ // refresh() is fire-and-forget but rejects on bad
223
+ // refreshToken / network — surface via .catch instead of
224
+ // leaving the rejection unhandled (was bug #4, id:2).
225
+ refresh().catch((err) =>
226
+ console.warn('refresh failed', err)
227
+ );
228
+ }
204
229
  } else if (storedClient) {
205
230
  devPushLog('rn', 'ChatWrapper: reusing storedClient');
206
231
  setClient(storedClient);
207
232
  if (!activeRoomJID) {
208
233
  storedClient.getRoomsStanza()
209
234
  .then(() => {
210
- storedClient.getChatsPrivateStoreRequestStanza();
235
+ storedClient.getChatsPrivateStoreRequestStanza().catch(
236
+ (err: unknown) =>
237
+ console.warn('getChatsPrivateStoreRequestStanza failed', err)
238
+ );
211
239
  })
212
240
  .catch((err: unknown) => console.warn('getRoomsStanza failed', err));
213
241
  }
214
242
  setInited(true);
215
- if (config?.refreshTokens?.enabled) {refresh();}
243
+ if (config?.refreshTokens?.enabled) {
244
+ refresh().catch((err) =>
245
+ console.warn('refresh failed', err)
246
+ );
247
+ }
216
248
  } else if (client) {
217
249
  devPushLog('rn', 'ChatWrapper: reusing provider client');
218
250
  if (!activeRoomJID) {
219
251
  client.getRoomsStanza()
220
252
  .then(() => {
221
- client.getChatsPrivateStoreRequestStanza();
253
+ client.getChatsPrivateStoreRequestStanza().catch(
254
+ (err: unknown) =>
255
+ console.warn('getChatsPrivateStoreRequestStanza failed', err)
256
+ );
222
257
  })
223
258
  .catch((err: unknown) => console.warn('getRoomsStanza failed', err));
224
259
  }
225
- client.getChatsPrivateStoreRequestStanza();
260
+ client.getChatsPrivateStoreRequestStanza().catch((err: unknown) =>
261
+ console.warn('getChatsPrivateStoreRequestStanza failed', err)
262
+ );
226
263
  setInited(true);
227
- if (config?.refreshTokens?.enabled) {refresh();}
264
+ if (config?.refreshTokens?.enabled) {
265
+ refresh().catch((err) =>
266
+ console.warn('refresh failed', err)
267
+ );
268
+ }
228
269
  }
229
270
 
230
271
  dispatch(setIsLoading({loading: false}));
@@ -250,6 +291,38 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
250
291
  config?.initBeforeLoad,
251
292
  ]);
252
293
 
294
+ // Cache-first display (initBeforeLoad). The main effect above only marks
295
+ // the chat `inited` once the provider bootstrap reaches 'ready' — which
296
+ // waits on the cold XMPP connect. On re-entry that left the user staring
297
+ // at a loader while fully-cached rooms/messages sat in redux-persist
298
+ // ("pulls a new connection for 100 years"). Here we render the cached
299
+ // content the instant rehydration lands; the live client gets wired by
300
+ // the main effect when the connect completes (send/loadMore activate
301
+ // then). Mirrors web showing cached rooms immediately + refreshing in
302
+ // the background.
303
+ useEffect(() => {
304
+ if (!config?.initBeforeLoad || initMode !== 'provider') {return;}
305
+ if (isInited || showModal) {return;}
306
+ if (providerBootstrapStatus === 'failed') {return;}
307
+ const haveCachedRooms = !!rooms && Object.keys(rooms).length > 0;
308
+ const haveUser =
309
+ !!user?.xmppUsername || !!user?.defaultWallet?.walletAddress;
310
+ if (haveCachedRooms && haveUser) {
311
+ devPushLog('rn', 'ChatWrapper: cache-first — showing persisted rooms while provider connects');
312
+ setShowModal(false);
313
+ setInited(true);
314
+ }
315
+ }, [
316
+ config?.initBeforeLoad,
317
+ initMode,
318
+ isInited,
319
+ showModal,
320
+ providerBootstrapStatus,
321
+ rooms,
322
+ user?.xmppUsername,
323
+ user?.defaultWallet?.walletAddress,
324
+ ]);
325
+
253
326
  // Skip the legacy email/password LoginForm entirely when XmppProvider
254
327
  // is driving auth via initBeforeLoad — the bootstrap effect will
255
328
  // populate the user shortly. Showing LoginForm here causes a flicker
@@ -270,7 +343,13 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
270
343
 
271
344
  return (
272
345
  <>
273
- {showModal && (
346
+ {/* Connection/bootstrap error UI. For patient-facing apps the
347
+ full-screen dark overlay reads as a crash, so
348
+ `disableConnectionErrorOverlay` swaps it for a subtle inline
349
+ "Connection lost. Retrying…" banner (and reconnect + re-join now
350
+ recover automatically). */}
351
+ {showModal && config?.disableConnectionErrorOverlay && <ConnectionBanner />}
352
+ {showModal && !config?.disableConnectionErrorOverlay && (
274
353
  <Overlay>
275
354
  <View
276
355
  style={{
@@ -320,28 +399,34 @@ const ChatWrapper: FC<ChatWrapperProps> = ({
320
399
  style={{
321
400
  ...MainComponentStyles,
322
401
  }}>
323
- {showRoomList ? (
324
- <RoomList
325
- chats={Object.values(rooms)}
326
- onRoomClick={handleChangeChat}
327
- />
328
- ) : (
329
- <ChatWrapperBox
330
- style={{
331
- ...MainComponentStyles,
332
- }}>
333
- <ChatRoom
334
- CustomMessageComponent={CustomMessageComponent || Message}
335
- handleBackClick={
336
- roomJID || config?.disableRooms
337
- ? undefined
338
- : () => {
339
- dispatch(setCurrentRoom({ roomJID: '' }));
340
- }
341
- }
402
+ {/* Host the message context menu in-tree (not a RN Modal) so
403
+ opening it doesn't steal focus / dismiss the keyboard on
404
+ Android. Wraps only the chat area — the global Modal /
405
+ ModalWrapper below stay above it. */}
406
+ <InteractionsOverlayProvider>
407
+ {showRoomList ? (
408
+ <RoomList
409
+ chats={Object.values(rooms)}
410
+ onRoomClick={handleChangeChat}
342
411
  />
343
- </ChatWrapperBox>
344
- )}
412
+ ) : (
413
+ <ChatWrapperBox
414
+ style={{
415
+ ...MainComponentStyles,
416
+ }}>
417
+ <ChatRoom
418
+ CustomMessageComponent={CustomMessageComponent || Message}
419
+ handleBackClick={
420
+ roomJID || config?.disableRooms
421
+ ? undefined
422
+ : () => {
423
+ dispatch(setCurrentRoom({ roomJID: '' }));
424
+ }
425
+ }
426
+ />
427
+ </ChatWrapperBox>
428
+ )}
429
+ </InteractionsOverlayProvider>
345
430
  <Modal
346
431
  modal={activeModal}
347
432
  setOpenModal={(value?: ModalType) =>
@@ -5,13 +5,14 @@ import CustomMessageImage from '../styled/MessageImage';
5
5
  import CustomMessageVideo from '../styled/VideoMessage';
6
6
  import AudioMessage from '../styled/AudioMessage';
7
7
  import { Text } from 'react-native';
8
- import { deriveDisplayFilename } from '../../helpers/mimeToExtension';
8
+ import { deriveDisplayFilename, isLikelyAudio } from '../../helpers/mimeToExtension';
9
9
 
10
10
  interface MediaMessageProps {
11
11
  mimeType?: string;
12
12
  message?: IMessage;
13
13
  location?: string;
14
14
  messageText?: string;
15
+ isUser: boolean;
15
16
  }
16
17
 
17
18
  const MediaMessage: React.FC<MediaMessageProps> = ({
@@ -19,6 +20,7 @@ const MediaMessage: React.FC<MediaMessageProps> = ({
19
20
  location,
20
21
  messageText,
21
22
  message,
23
+ isUser,
22
24
  }) => {
23
25
  if (mimeType) {
24
26
  const displayName = deriveDisplayFilename({
@@ -48,19 +50,23 @@ const MediaMessage: React.FC<MediaMessageProps> = ({
48
50
  return <AudioMessage src={location || ''} />;
49
51
  }
50
52
  default: {
51
- // Many backends tag binary payloads (PDFs, DOCX, archives) as
52
- // application/octet-stream; sniff the filename extension for the
53
- // legitimate audio case before falling through to FileDownload.
54
- if (mimeType.includes('application/octet-stream')) {
55
- if (/\.(mp3|m4a|wav|aac|ogg|flac)$/i.test(displayName)) {
56
- return <AudioMessage src={location || ''} />;
57
- }
53
+ // Some senders (notably the web app's voice-message uploader)
54
+ // ship audio as `application/octet-stream` with no audio file
55
+ // extension. `isLikelyAudio` recognises those via the URL path,
56
+ // filename, or voice-message naming hints (voicemail-,
57
+ // voice-note-, recording-, …) so we still render the AudioMessage
58
+ // player instead of falling through to the generic FileDownload
59
+ // card (where the voicemail rendered as a broken `.bin`
60
+ // attachment). Customer-reported #9 voicemail fix.
61
+ if (isLikelyAudio(mimeType, displayName, location)) {
62
+ return <AudioMessage src={location || ''} />;
58
63
  }
59
64
  return (
60
65
  <FileDownload
61
66
  fileURL={location ? location : ''}
62
67
  fileName={displayName}
63
68
  mimetype={mimeType}
69
+ isUser={isUser}
64
70
  />
65
71
  );
66
72
  }
@@ -73,7 +73,7 @@ export const MessageContainer: FC<MessageContainerProps> = ({
73
73
  );
74
74
  }
75
75
 
76
- if (message?.id === 'delimiter-new') {
76
+ if (String(message?.id || '').startsWith('delimiter-new')) {
77
77
  return CustomNewMessageLabel ? (
78
78
  <CustomNewMessageLabel color={config?.colors?.primary} />
79
79
  ) : (
@@ -85,7 +85,9 @@ export const MessageContainer: FC<MessageContainerProps> = ({
85
85
 
86
86
  return (
87
87
  <View key={message.id}>
88
- {showDateLabel && !activeMessage && message.id !== 'delimiter-new' ? (
88
+ {showDateLabel &&
89
+ !activeMessage &&
90
+ !String(message.id || '').startsWith('delimiter-new') ? (
89
91
  CustomDaySeparator ? (
90
92
  <CustomDaySeparator
91
93
  date={messageDate}