@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
@@ -7,6 +7,7 @@ import {
7
7
  import { BackIcon, MoreIcon, QrIcon } from '../../assets/icons';
8
8
  import Button from '../styled/Button';
9
9
  import { Text } from 'react-native';
10
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
10
11
 
11
12
  interface ModalHeaderComponentProps {
12
13
  handleCloseModal?: any;
@@ -21,8 +22,14 @@ const ModalHeaderComponent: React.FC<ModalHeaderComponentProps> = ({
21
22
  rightMenu,
22
23
  leftMenu,
23
24
  }) => {
25
+ // The library's full-screen modals are an absolute-fill overlay inside
26
+ // ModalBackground (NOT a native Modal), so the OS doesn't apply any
27
+ // status-bar inset automatically — we have to. SafeAreaProvider is
28
+ // mounted by ReduxWrapper, so this reads the live per-device inset
29
+ // (notch / Dynamic Island / nothing).
30
+ const insets = useSafeAreaInsets();
24
31
  return (
25
- <HeaderContainer>
32
+ <HeaderContainer style={{ paddingTop: insets.top + 8 }}>
26
33
  <HeaderLeft>
27
34
  {leftMenu ? (
28
35
  leftMenu
@@ -9,7 +9,7 @@ import {
9
9
  } from '../styledModalComponents';
10
10
  import { TextareaInput } from '../../styled/StyledInputComponents/StyledInputComponents';
11
11
  import Button from '../../styled/Button';
12
- import { Modal, Text, TextInput } from 'react-native';
12
+ import { Modal, Text, TextInput, View, StyleSheet } from 'react-native';
13
13
 
14
14
  interface ModalWrapperProps {
15
15
  iconTitle?: any;
@@ -53,6 +53,47 @@ export const ModalWrapper: FC<ModalWrapperProps> = ({
53
53
  // }
54
54
  // };
55
55
 
56
+ const inner = (
57
+ <>
58
+ <CloseButton onPress={handleCloseModal}>
59
+ <Text style={{ fontSize: 24 }}>&times;</Text>
60
+ </CloseButton>
61
+ {IconTitle ? <IconTitle /> : <ModalTitle>{title}</ModalTitle>}
62
+ {description && <ModalDescription>{description}</ModalDescription>}
63
+ {isTextarea && (
64
+ <GroupContainer
65
+ style={{ flexDirection: 'column', position: 'relative' }}
66
+ />
67
+ )}
68
+ {!buttonText && <GroupContainer />}
69
+ <GroupContainer>
70
+ <Button
71
+ onPress={handleCloseModal}
72
+ text={'Cancel'}
73
+ style={{ width: '100%' }}
74
+ unstyled
75
+ variant="outlined"
76
+ />
77
+ {buttonText && (
78
+ <Button
79
+ onPress={handleClick}
80
+ text={buttonText}
81
+ // White label on the filled (e.g. red Delete) button. Button
82
+ // applies an inline `color: color || 'black'` that overrides
83
+ // the filled-variant white, so pass it explicitly.
84
+ color="#FFFFFF"
85
+ style={{
86
+ width: '100%',
87
+ backgroundColor: backgroundColorButton,
88
+ }}
89
+ unstyled
90
+ variant="filled"
91
+ />
92
+ )}
93
+ </GroupContainer>
94
+ </>
95
+ );
96
+
56
97
  return (
57
98
  <Modal
58
99
  transparent
@@ -61,64 +102,35 @@ export const ModalWrapper: FC<ModalWrapperProps> = ({
61
102
  onRequestClose={handleCloseModal}
62
103
  >
63
104
  <ModalBackground>
64
- <ModalContainer
65
- style={
66
- compact
67
- ? {
68
- flex: 0,
69
- width: '85%',
70
- maxWidth: 360,
71
- height: 'auto',
72
- padding: 24,
73
- borderRadius: 16,
74
- gap: 16,
75
- }
76
- : { maxWidth: 640 }
77
- }
78
- >
79
- <CloseButton onPress={handleCloseModal}>
80
- <Text style={{ fontSize: 24 }}>&times;</Text>
81
- </CloseButton>
82
- {IconTitle ? <IconTitle /> : <ModalTitle>{title}</ModalTitle>}
83
- {description && <ModalDescription>{description}</ModalDescription>}
84
- {isTextarea && (
85
- <GroupContainer
86
- style={{ flexDirection: 'column', position: 'relative' }}
87
- >
88
- {/* <TextareaInput
89
- ref={textareaRef}
90
- onInput={handleInput}
91
- id="additionalDetails"
92
- value={textarea}
93
- onChangeText={(text) => setTextarea(text)}
94
- placeholder="Additional Details"
95
- /> */}
96
- </GroupContainer>
97
- )}
98
- {!buttonText && <GroupContainer />}
99
- <GroupContainer>
100
- <Button
101
- onPress={handleCloseModal}
102
- text={'Cancel'}
103
- style={{ width: '100%' }}
104
- unstyled
105
- variant="outlined"
106
- />
107
- {buttonText && (
108
- <Button
109
- onPress={handleClick}
110
- text={buttonText}
111
- style={{
112
- width: '100%',
113
- backgroundColor: backgroundColorButton,
114
- }}
115
- unstyled
116
- variant="filled"
117
- />
118
- )}
119
- </GroupContainer>
120
- </ModalContainer>
105
+ {compact ? (
106
+ // Dedicated small centered dialog. The base ModalContainer is
107
+ // flex:1 / width:100% / height:100% (full-screen); style-merge
108
+ // overrides proved unreliable, so confirm-style modals render in
109
+ // their own bounded View instead — never full-screen (#14).
110
+ // (Upstream also shrank this modal; this keeps that intent while
111
+ // adding the white filled-button label via `inner` below.)
112
+ <View style={styles.compactDialog}>{inner}</View>
113
+ ) : (
114
+ <ModalContainer style={{ maxWidth: 640 }}>{inner}</ModalContainer>
115
+ )}
121
116
  </ModalBackground>
122
117
  </Modal>
123
118
  );
124
119
  };
120
+
121
+ const styles = StyleSheet.create({
122
+ compactDialog: {
123
+ width: '85%',
124
+ maxWidth: 360,
125
+ alignSelf: 'center',
126
+ backgroundColor: '#fff',
127
+ borderRadius: 16,
128
+ padding: 24,
129
+ gap: 16,
130
+ shadowColor: '#000',
131
+ shadowOffset: { width: 0, height: 4 },
132
+ shadowOpacity: 0.2,
133
+ shadowRadius: 12,
134
+ elevation: 8,
135
+ },
136
+ });
@@ -285,22 +285,26 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
285
285
  </LabelData>
286
286
  </BorderedContainer>
287
287
 
288
- {selectedUser && !config?.disableProfilesInteractions && (
288
+ {selectedUser && !config?.disableMemberProfileActions && (
289
289
  <>
290
- <ActionButton
291
- StartIcon={<ChatIcon />}
292
- onPress={handlePrivateMessage}
293
- variant="filled"
294
- >
295
- <Text style={{ color: '#ffffff' }}>Message</Text>
296
- </ActionButton>
297
- <ActionButton
298
- onPress={() => {}}
299
- // onPress={() => handleCopyClick(selectedUser.id)}
300
- variant="filled"
301
- >
302
- <Text style={{ color: '#ffffff' }}>Copy User Id</Text>
303
- </ActionButton>
290
+ {!config?.hideMemberSendMessageAction && (
291
+ <ActionButton
292
+ StartIcon={<ChatIcon />}
293
+ onPress={handlePrivateMessage}
294
+ variant="filled"
295
+ >
296
+ <Text style={{ color: '#ffffff' }}>Message</Text>
297
+ </ActionButton>
298
+ )}
299
+ {!config?.hideMemberCopyIdAction && (
300
+ <ActionButton
301
+ onPress={() => {}}
302
+ // onPress={() => handleCopyClick(selectedUser.id)}
303
+ variant="filled"
304
+ >
305
+ <Text style={{ color: '#ffffff' }}>Copy User Id</Text>
306
+ </ActionButton>
307
+ )}
304
308
  </>
305
309
  )}
306
310
 
@@ -21,17 +21,12 @@ export const CloseButton = styled.TouchableOpacity`
21
21
  font-size: 20px;
22
22
  cursor: pointer;
23
23
  color: #888;
24
-
25
- &:hover {
26
- color: #555;
27
- background-color: #dddddd;
28
- }
29
24
  `;
30
25
 
31
26
  export const ModalContainer = styled.View`
32
- flex: 1;
33
- width: 100%;
34
- height: 100%;
27
+ // flex: 1;
28
+ // width: 100%;
29
+ // height: 100%;
35
30
  background: white;
36
31
  padding: 32px 64px;
37
32
  box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.2);
@@ -57,7 +52,7 @@ export const ModalDescription = styled.Text`
57
52
 
58
53
  export const GroupContainer = styled.View`
59
54
  display: flex;
60
- gap: 32px;
55
+ gap: 16px;
61
56
  width: 100%;
62
57
  padding: 0;
63
58
  `;
@@ -77,10 +72,19 @@ export const HeaderContainer = styled.View`
77
72
  position: relative;
78
73
  top: 0;
79
74
  width: 100%;
80
- padding: 2px 8px;
81
- padding-top: 62px;
82
- max-height: 24px;
83
- min-height: 24px;
75
+ /* The previous incarnation had padding-top:62px (hard-coded status-bar
76
+ * offset) clamped to min/max-height:24px — content overflowed the
77
+ * visible band and the back arrow hugged the bottom edge. The earlier
78
+ * fix dropped the clamp but kept a hard-coded 56px top inset, which on
79
+ * top of this modal's absolute-fill overlay (no system inset is auto-
80
+ * applied) made the header eat far more space than it should.
81
+ *
82
+ * Now: compact 8px vertical padding here; the dynamic top inset for
83
+ * the status bar / Dynamic Island is supplied by ModalHeaderComponent
84
+ * via useSafeAreaInsets() — accurate per-device (~59px on a 16 Pro,
85
+ * 20px on an SE). Together that's status-bar + 8px above the back
86
+ * button and 8px below — properly sized and properly centered. */
87
+ padding: 8px 16px;
84
88
  background-color: #fff;
85
89
  border-bottom-width: 1px;
86
90
  border-bottom-color: #f0f0f0;
@@ -7,13 +7,56 @@ import { FileIcon } from '../../assets/icons';
7
7
  import { RemoveButton, RemoveButtonText } from './StyledComponents';
8
8
  import { FC, useState } from 'react';
9
9
  import { MediaFile } from '../../types/types';
10
- import { Video, ResizeMode } from 'expo-av';
10
+ import { useVideoPlayer, VideoView } from 'expo-video';
11
11
 
12
12
  interface MediaFilePreviewProps {
13
13
  filePreviews: MediaFile[];
14
14
  handleRemoveImage: (index: number) => void;
15
15
  }
16
16
 
17
+ const VideoThumb: FC<{ uri: string; onPress: () => void }> = ({
18
+ uri,
19
+ onPress,
20
+ }) => {
21
+ const player = useVideoPlayer(uri, (p) => {
22
+ p.muted = true;
23
+ });
24
+ return (
25
+ <TouchableOpacity
26
+ activeOpacity={0.8}
27
+ onPress={onPress}
28
+ style={styles.videoThumb}
29
+ >
30
+ <VideoView
31
+ player={player}
32
+ style={StyleSheet.absoluteFill}
33
+ contentFit="cover"
34
+ nativeControls={false}
35
+ surfaceType="textureView"
36
+ pointerEvents="none"
37
+ />
38
+ <View style={styles.playOverlay}>
39
+ <Text style={styles.playIcon}>▶</Text>
40
+ </View>
41
+ </TouchableOpacity>
42
+ );
43
+ };
44
+
45
+ const FullscreenPreviewVideo: FC<{ uri: string }> = ({ uri }) => {
46
+ const player = useVideoPlayer(uri, (p) => {
47
+ p.play();
48
+ });
49
+ return (
50
+ <VideoView
51
+ player={player}
52
+ style={styles.fullVideo}
53
+ contentFit="contain"
54
+ nativeControls
55
+ surfaceType="textureView"
56
+ />
57
+ );
58
+ };
59
+
17
60
  export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
18
61
  filePreviews,
19
62
  handleRemoveImage,
@@ -30,22 +73,7 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
30
73
  {isImage ? (
31
74
  <MediaImage source={{ uri: file.uri }} />
32
75
  ) : isVideo ? (
33
- <TouchableOpacity
34
- activeOpacity={0.8}
35
- onPress={() => setPreviewUri(file.uri)}
36
- style={styles.videoThumb}
37
- >
38
- <Video
39
- source={{ uri: file.uri }}
40
- style={StyleSheet.absoluteFill}
41
- resizeMode={ResizeMode.COVER}
42
- shouldPlay={false}
43
- isMuted
44
- />
45
- <View style={styles.playOverlay}>
46
- <Text style={styles.playIcon}>▶</Text>
47
- </View>
48
- </TouchableOpacity>
76
+ <VideoThumb uri={file.uri} onPress={() => setPreviewUri(file.uri)} />
49
77
  ) : (
50
78
  <View style={{ width: 70, height: 70, borderRadius: 8 }}>
51
79
  <FileIcon width={70} height={70} />
@@ -66,15 +94,7 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
66
94
  >
67
95
  <Text style={styles.closeText}>✕</Text>
68
96
  </TouchableOpacity>
69
- {previewUri && (
70
- <Video
71
- source={{ uri: previewUri }}
72
- style={styles.fullVideo}
73
- resizeMode={ResizeMode.CONTAIN}
74
- useNativeControls
75
- shouldPlay
76
- />
77
- )}
97
+ {previewUri && <FullscreenPreviewVideo uri={previewUri} />}
78
98
  </SafeAreaView>
79
99
  </Modal>
80
100
  </MediaContainer>
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import { Container } from './StyledInputComponents/MediaComponents';
3
3
  import { useDispatch } from 'react-redux';
4
4
  import {
@@ -6,43 +6,88 @@ import {
6
6
  setActiveModal,
7
7
  } from '../../roomStore/chatSettingsSlice';
8
8
  import { MODAL_TYPES } from '../../helpers/constants/MODAL_TYPES';
9
- import { ActivityIndicator, Image, TouchableOpacity } from 'react-native';
9
+ import { ActivityIndicator, Image, TouchableOpacity, View } from 'react-native';
10
+ import {
11
+ defaultMediaDims,
12
+ fitMediaDimensions,
13
+ MediaDims,
14
+ } from '../../helpers/mediaDimensions';
15
+
10
16
  interface CustomMessageImageProps {
11
17
  fileURL: string;
12
18
  fileName: string;
13
19
  mimetype: string;
14
20
  }
15
21
 
22
+ const FALLBACK_IMAGE =
23
+ 'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg';
24
+
16
25
  const CustomMessageImage: React.FC<CustomMessageImageProps> = ({
17
26
  fileURL,
18
27
  fileName,
19
28
  mimetype,
20
29
  }) => {
21
- const [error, setError] = useState(false);
22
30
  const [loading, setLoading] = useState(true);
31
+ // Start with a neutral box; swap to the real aspect ratio once the
32
+ // image's natural dimensions are known so it's shown scaled, not cropped.
33
+ const [dims, setDims] = useState<MediaDims>(defaultMediaDims());
23
34
 
24
35
  const dispatch = useDispatch();
25
36
 
37
+ useEffect(() => {
38
+ if (!fileURL) {
39
+ return;
40
+ }
41
+ let active = true;
42
+ Image.getSize(
43
+ fileURL,
44
+ (w, h) => {
45
+ if (active) {
46
+ setDims(fitMediaDimensions(w, h));
47
+ }
48
+ },
49
+ () => {
50
+ /* keep the default box if the size probe fails */
51
+ }
52
+ );
53
+ return () => {
54
+ active = false;
55
+ };
56
+ }, [fileURL]);
57
+
26
58
  const handleOpen = () => {
27
59
  dispatch(setActiveFile({ fileName, fileURL, mimetype }));
28
60
  dispatch(setActiveModal(MODAL_TYPES.FILE_PREVIEW));
29
61
  };
30
62
 
31
63
  return (
32
- <Container>
33
- <TouchableOpacity onPress={handleOpen}>
34
- {loading && <ActivityIndicator size="small" color="#0052CD" />}
64
+ <Container style={{ width: dims.width }}>
65
+ <TouchableOpacity onPress={handleOpen} activeOpacity={0.9}>
66
+ {loading && (
67
+ <View
68
+ style={{
69
+ position: 'absolute',
70
+ width: dims.width,
71
+ height: dims.height,
72
+ alignItems: 'center',
73
+ justifyContent: 'center',
74
+ zIndex: 1,
75
+ }}
76
+ >
77
+ <ActivityIndicator size="small" color="#0052CD" />
78
+ </View>
79
+ )}
35
80
  <Image
36
- src={
37
- fileURL ||
38
- 'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg'
39
- }
81
+ source={{ uri: fileURL || FALLBACK_IMAGE }}
40
82
  style={{
41
- width: 250,
42
- height: 200,
83
+ width: dims.width,
84
+ height: dims.height,
85
+ borderRadius: 10,
86
+ backgroundColor: 'rgba(0, 0, 0, 0)',
43
87
  }}
44
- onError={() => setError(true)}
45
88
  onLoadEnd={() => setLoading(false)}
89
+ // The box already matches the natural aspect ratio, so 'cover'
90
+ // fills it edge-to-edge with no actual cropping or letterboxing.
46
91
  resizeMode="cover"
47
92
  />
48
93
  </TouchableOpacity>
@@ -24,23 +24,26 @@ export const StyledLabel = styled.View`
24
24
  margin: 10px 0px;
25
25
  `;
26
26
 
27
- export const StyledLabelText = styled.Text<{ color?: string }>`
28
- color: ${(props) => (props?.color ? props?.color : '#0052CD')};
27
+ export const StyledLabelText = styled.Text`
28
+ color: #ffffff;
29
29
  font-size: 12px;
30
30
  line-height: 14px;
31
- font-weight: 400;
31
+ font-weight: 500;
32
32
  `;
33
33
 
34
+ // `color` is kept for CustomNewMessageLabel API parity, but the built-in
35
+ // label always renders WHITE text — it sits on a dark (#3f3f3f) pill, where
36
+ // the previous primary/blue text was unreadable.
34
37
  interface NewMessageLabelProps {
35
38
  color?: string;
36
39
  }
37
40
 
38
- const NewMessageLabel: React.FC<NewMessageLabelProps> = ({ color }) => {
41
+ const NewMessageLabel: React.FC<NewMessageLabelProps> = () => {
39
42
  return (
40
43
  <Container>
41
44
  <Line />
42
45
  <StyledLabel>
43
- <StyledLabelText color={color}>New messages</StyledLabelText>
46
+ <StyledLabelText>New messages</StyledLabelText>
44
47
  </StyledLabel>
45
48
  <Line />
46
49
  </Container>
@@ -9,7 +9,7 @@ import {
9
9
  import { IConfig, MediaFile } from '../../types/types';
10
10
  import Button from './Button';
11
11
  import { SendIcon, AttachIcon } from '../../assets/icons';
12
- import { KeyboardAvoidingView, Platform, View, TouchableOpacity, Alert, ActionSheetIOS, Linking } from 'react-native';
12
+ import { KeyboardAvoidingView, View, TouchableOpacity, Alert, Linking } from 'react-native';
13
13
  import AttachSheet from '../Modals/AttachSheet/AttachSheet';
14
14
  import { MediaFilePreview } from './MediaFilePreview';
15
15
  import * as ImagePicker from 'expo-image-picker';
@@ -19,6 +19,21 @@ import * as ImageManipulator from 'expo-image-manipulator';
19
19
  // iOS photos default to HEIC; many web backends (incl. ours) 500 on
20
20
  // HEIC uploads because they can't decode it. Convert to JPEG before
21
21
  // upload — JPEG is universally supported. JPEGs pass through.
22
+ // Server rejects uploads over its body-size cap with HTTP 413 (Request
23
+ // Entity Too Large). Guard client-side so the user gets a clear message
24
+ // instead of a silent failed bubble. 50 MB matches the backend limit.
25
+ const MAX_MEDIA_BYTES = 50 * 1024 * 1024;
26
+
27
+ const formatBytes = (bytes: number): string => {
28
+ if (bytes >= 1024 * 1024) {
29
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
30
+ }
31
+ if (bytes >= 1024) {
32
+ return `${(bytes / 1024).toFixed(0)} KB`;
33
+ }
34
+ return `${bytes} B`;
35
+ };
36
+
22
37
  const normalizeImageAsset = async (asset: ImagePicker.ImagePickerAsset) => {
23
38
  const mime = (asset.mimeType || '').toLowerCase();
24
39
  const looksLikeHeic =
@@ -72,7 +87,6 @@ const SendInput: React.FC<SendInputProps> = ({
72
87
  const [isRecording, setIsRecording] = useState(false);
73
88
  const [isFocused, setIsFocused] = useState(false);
74
89
  const [filePreviews, setFilePreviews] = useState<MediaFile[]>([]);
75
- const [inputHeight, setInputHeight] = useState(40);
76
90
  const [showMediaMenu, setShowMediaMenu] = useState(false);
77
91
 
78
92
  // Refs shadow `message` and `filePreviews` so handleSendClick can:
@@ -90,6 +104,21 @@ const SendInput: React.FC<SendInputProps> = ({
90
104
  const sendingRef = useRef(false);
91
105
 
92
106
  const handleFileSelect = (files: MediaFile[]) => {
107
+ // Enforce the upload size cap before anything reaches the network.
108
+ // The backend rejects oversized bodies with HTTP 413; catching it
109
+ // here gives a clear message instead of a silent failed bubble.
110
+ const oversize = files.find(
111
+ (f) => typeof f.size === 'number' && f.size > MAX_MEDIA_BYTES
112
+ );
113
+ if (oversize) {
114
+ Alert.alert(
115
+ 'File too large',
116
+ `"${oversize.name}" is ${formatBytes(oversize.size!)}. The maximum allowed size is ${Math.round(
117
+ MAX_MEDIA_BYTES / (1024 * 1024)
118
+ )} MB.`
119
+ );
120
+ return;
121
+ }
93
122
  filePreviewsRef.current = files;
94
123
  setFilePreviews([...files]);
95
124
  };
@@ -127,13 +156,19 @@ const SendInput: React.FC<SendInputProps> = ({
127
156
  uri: asset.uri,
128
157
  type: asset.mimeType || 'video/mp4',
129
158
  name: asset.fileName || asset.uri.split('/').pop() || `camera_${Date.now()}.mp4`,
159
+ size: (asset as any).fileSize,
130
160
  },
131
161
  ]);
132
162
  return;
133
163
  }
134
164
  const normalized = await normalizeImageAsset(asset);
135
165
  handleFileSelect([
136
- { uri: normalized.uri, type: normalized.mime, name: normalized.name },
166
+ {
167
+ uri: normalized.uri,
168
+ type: normalized.mime,
169
+ name: normalized.name,
170
+ size: (asset as any).fileSize,
171
+ },
137
172
  ]);
138
173
  } catch (error) {
139
174
  console.error('Camera error:', error);
@@ -165,13 +200,19 @@ const SendInput: React.FC<SendInputProps> = ({
165
200
  uri: asset.uri,
166
201
  type: asset.mimeType || 'video/mp4',
167
202
  name: asset.fileName || asset.uri.split('/').pop() || `gallery_${Date.now()}.mp4`,
203
+ size: (asset as any).fileSize,
168
204
  },
169
205
  ]);
170
206
  return;
171
207
  }
172
208
  const normalized = await normalizeImageAsset(asset);
173
209
  handleFileSelect([
174
- { uri: normalized.uri, type: normalized.mime, name: normalized.name },
210
+ {
211
+ uri: normalized.uri,
212
+ type: normalized.mime,
213
+ name: normalized.name,
214
+ size: (asset as any).fileSize,
215
+ },
175
216
  ]);
176
217
  } catch (error) {
177
218
  console.error('Gallery error:', error);
@@ -192,6 +233,7 @@ const SendInput: React.FC<SendInputProps> = ({
192
233
  uri: asset.uri,
193
234
  type: asset.mimeType || 'application/octet-stream',
194
235
  name: asset.name || `file_${Date.now()}`,
236
+ size: asset.size ?? undefined,
195
237
  },
196
238
  ]);
197
239
  } catch (err) {
@@ -200,21 +242,7 @@ const SendInput: React.FC<SendInputProps> = ({
200
242
  };
201
243
 
202
244
  const handleAttachPress = () => {
203
- if (Platform.OS === 'ios') {
204
- ActionSheetIOS.showActionSheetWithOptions(
205
- {
206
- options: ['Cancel', 'Camera', 'Photo Library', 'Document'],
207
- cancelButtonIndex: 0,
208
- },
209
- (buttonIndex) => {
210
- if (buttonIndex === 1) {handleCameraSelection();}
211
- else if (buttonIndex === 2) {handleGallerySelection();}
212
- else if (buttonIndex === 3) {handleFileSelection();}
213
- }
214
- );
215
- } else {
216
- setShowMediaMenu(true);
217
- }
245
+ setShowMediaMenu(true);
218
246
  };
219
247
 
220
248
  const handleRemoveImage = (index: number) => {
@@ -336,17 +364,15 @@ const SendInput: React.FC<SendInputProps> = ({
336
364
  }}
337
365
  editable={!isLoading || !isMessageProcessing}
338
366
  multiline={true}
339
- // maxHeight={72}
340
- onContentSizeChange={(event) => {
341
- setInputHeight(
342
- Math.min(
343
- 72,
344
- Math.max(40, event.nativeEvent.contentSize.height)
345
- )
346
- );
347
- }}
367
+ // No fixed height: a multiline TextInput auto-grows to fit
368
+ // its content between min/max. Locking `height` made iOS
369
+ // top-align the text inside the taller box (it looked like
370
+ // the text had dropped). minHeight keeps the 40px tap
371
+ // target; the row's align-items:center vertically centres
372
+ // the content-sized input.
348
373
  style={{
349
- height: inputHeight,
374
+ minHeight: 40,
375
+ maxHeight: 120,
350
376
  flex: 1,
351
377
  }}
352
378
  />
@@ -371,6 +397,15 @@ const SendInput: React.FC<SendInputProps> = ({
371
397
  borderRadius: 20,
372
398
  alignItems: 'center',
373
399
  justifyContent: 'center',
400
+ // The shared Button (CustomButton) bakes in `margin: 0 10px`,
401
+ // which pushed the send button 10px further from the input
402
+ // and from the right edge than the attach button (a raw
403
+ // TouchableOpacity with no margin). Zero it so both sides of
404
+ // the input use the row's uniform gap:8 + 16px container
405
+ // padding. Longhand left/right to override the styled
406
+ // longhand (marginHorizontal loses to marginLeft/Right in RN).
407
+ marginLeft: 0,
408
+ marginRight: 0,
374
409
  backgroundColor:
375
410
  message || filePreviews.length > 0
376
411
  ? config?.colors?.primary