@ethora/chat-component-rn 26.8.1 → 26.8.2

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 (604) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +43 -10
  3. package/lib/commonjs/assets/icons.js +7 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/AuthForms/Login.js +4 -4
  6. package/lib/commonjs/components/AuthForms/Login.js.map +1 -1
  7. package/lib/commonjs/components/Header/HeaderRoomList.js +29 -8
  8. package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ChatHeader.js +9 -3
  10. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/ChatRoom.js +150 -14
  12. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  13. package/lib/commonjs/components/MainComponents/ChatWrapper.js +34 -13
  14. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  15. package/lib/commonjs/components/MainComponents/LoginWrapper.js +2 -1
  16. package/lib/commonjs/components/MainComponents/LoginWrapper.js.map +1 -1
  17. package/lib/commonjs/components/MainComponents/MediaMessage.js +29 -9
  18. package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
  19. package/lib/commonjs/components/MainComponents/MessageContainer.js +5 -1
  20. package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
  21. package/lib/commonjs/components/MainComponents/MessageList.js +13 -5
  22. package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
  23. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js +14 -13
  24. package/lib/commonjs/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  25. package/lib/commonjs/components/MainComponents/RoomList.js +208 -35
  26. package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
  27. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +317 -98
  28. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  29. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +322 -110
  30. package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  31. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +546 -203
  32. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  33. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +226 -0
  34. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -0
  35. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +69 -27
  36. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  37. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +2 -1
  38. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  39. package/lib/commonjs/components/Modals/Modal/Modal.js +8 -0
  40. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  41. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js +2 -1
  42. package/lib/commonjs/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  43. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +202 -106
  44. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  45. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
  46. package/lib/commonjs/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  47. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js +563 -0
  48. package/lib/commonjs/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -0
  49. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js +210 -0
  50. package/lib/commonjs/components/Modals/ProfileHeader/ProfileMenu.js.map +1 -0
  51. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +4 -2
  52. package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  53. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js +7 -21
  54. package/lib/commonjs/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  55. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +507 -244
  56. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  57. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +74 -46
  58. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  59. package/lib/commonjs/components/Modals/styledModalComponents.js +9 -2
  60. package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
  61. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +21 -7
  62. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  63. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +22 -3
  64. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  65. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +17 -3
  66. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  67. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +17 -3
  68. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  69. package/lib/commonjs/components/VideoCalls/VideoCallSession.js +6 -3
  70. package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -1
  71. package/lib/commonjs/components/styled/AudioMessage.js +2 -1
  72. package/lib/commonjs/components/styled/AudioMessage.js.map +1 -1
  73. package/lib/commonjs/components/styled/MessageImage.js +37 -9
  74. package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
  75. package/lib/commonjs/components/styled/SendInput.js +80 -11
  76. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  77. package/lib/commonjs/components/styled/StyledComponents.js +9 -3
  78. package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
  79. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +11 -4
  80. package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  81. package/lib/commonjs/components/styled/UnsupportedType.js +14 -4
  82. package/lib/commonjs/components/styled/UnsupportedType.js.map +1 -1
  83. package/lib/commonjs/components/styled/VideoMessage.js +119 -61
  84. package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
  85. package/lib/commonjs/context/xmppProvider.js +184 -59
  86. package/lib/commonjs/context/xmppProvider.js.map +1 -1
  87. package/lib/commonjs/helpers/createMessageFromXml.js +19 -1
  88. package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
  89. package/lib/commonjs/helpers/ensureScopedChatCache.js +2 -2
  90. package/lib/commonjs/helpers/ensureScopedChatCache.js.map +1 -1
  91. package/lib/commonjs/helpers/getChatBackground.js +23 -0
  92. package/lib/commonjs/helpers/getChatBackground.js.map +1 -0
  93. package/lib/commonjs/helpers/getDisplayFileName.js +79 -0
  94. package/lib/commonjs/helpers/getDisplayFileName.js.map +1 -0
  95. package/lib/commonjs/helpers/getServerReadTimestamp.js +188 -0
  96. package/lib/commonjs/helpers/getServerReadTimestamp.js.map +1 -0
  97. package/lib/commonjs/helpers/historyPreloadScheduler.js +65 -2
  98. package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
  99. package/lib/commonjs/helpers/initXmppRooms.js +14 -8
  100. package/lib/commonjs/helpers/initXmppRooms.js.map +1 -1
  101. package/lib/commonjs/helpers/insertMessageWithDelimiter.js +51 -9
  102. package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
  103. package/lib/commonjs/helpers/isOwnMessage.js +75 -0
  104. package/lib/commonjs/helpers/isOwnMessage.js.map +1 -0
  105. package/lib/commonjs/helpers/keyboardLayout.js +12 -2
  106. package/lib/commonjs/helpers/keyboardLayout.js.map +1 -1
  107. package/lib/commonjs/helpers/mediaLibraryRuntime.js +31 -0
  108. package/lib/commonjs/helpers/mediaLibraryRuntime.js.map +1 -0
  109. package/lib/commonjs/helpers/mimeToExtension.js +6 -14
  110. package/lib/commonjs/helpers/mimeToExtension.js.map +1 -1
  111. package/lib/commonjs/helpers/msgSortableMs.js +37 -0
  112. package/lib/commonjs/helpers/msgSortableMs.js.map +1 -0
  113. package/lib/commonjs/helpers/persistCrypto.js +122 -0
  114. package/lib/commonjs/helpers/persistCrypto.js.map +1 -0
  115. package/lib/commonjs/helpers/pickImageAsset.js +68 -0
  116. package/lib/commonjs/helpers/pickImageAsset.js.map +1 -0
  117. package/lib/commonjs/helpers/pushPayload.js +71 -0
  118. package/lib/commonjs/helpers/pushPayload.js.map +1 -0
  119. package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +130 -17
  120. package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
  121. package/lib/commonjs/helpers/secureFileUrl.js +101 -0
  122. package/lib/commonjs/helpers/secureFileUrl.js.map +1 -0
  123. package/lib/commonjs/helpers/secureKeyValue.js +83 -0
  124. package/lib/commonjs/helpers/secureKeyValue.js.map +1 -0
  125. package/lib/commonjs/helpers/secureStoreRuntime.js +59 -0
  126. package/lib/commonjs/helpers/secureStoreRuntime.js.map +1 -0
  127. package/lib/commonjs/helpers/secureUserStorage.js +75 -0
  128. package/lib/commonjs/helpers/secureUserStorage.js.map +1 -0
  129. package/lib/commonjs/helpers/shallowEqual.js +36 -0
  130. package/lib/commonjs/helpers/shallowEqual.js.map +1 -0
  131. package/lib/commonjs/helpers/sheetGestures.js +32 -0
  132. package/lib/commonjs/helpers/sheetGestures.js.map +1 -0
  133. package/lib/commonjs/hooks/useChatRoomFocus.js +45 -12
  134. package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -1
  135. package/lib/commonjs/hooks/useChatWrapperInit.js +30 -10
  136. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  137. package/lib/commonjs/hooks/useComposing.js +27 -0
  138. package/lib/commonjs/hooks/useComposing.js.map +1 -1
  139. package/lib/commonjs/hooks/useFileToken.js +10 -0
  140. package/lib/commonjs/hooks/useFileToken.js.map +1 -0
  141. package/lib/commonjs/hooks/useLogout.js +23 -7
  142. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  143. package/lib/commonjs/hooks/usePendingNotification.js +8 -11
  144. package/lib/commonjs/hooks/usePendingNotification.js.map +1 -1
  145. package/lib/commonjs/hooks/useSendMessage.js +50 -14
  146. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  147. package/lib/commonjs/hooks/useUnreadMessagesCounter.js +6 -1
  148. package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
  149. package/lib/commonjs/i18n/strings.js +145 -37
  150. package/lib/commonjs/i18n/strings.js.map +1 -1
  151. package/lib/commonjs/main.js +44 -0
  152. package/lib/commonjs/main.js.map +1 -1
  153. package/lib/commonjs/networking/api-requests/auth.api.js +134 -60
  154. package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
  155. package/lib/commonjs/networking/api-requests/roomMembers.api.js +1 -1
  156. package/lib/commonjs/networking/api-requests/roomMembers.api.js.map +1 -1
  157. package/lib/commonjs/networking/api-requests/rooms.api.js +9 -9
  158. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  159. package/lib/commonjs/networking/api-requests/user.api.js +68 -9
  160. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  161. package/lib/commonjs/networking/apiClient.js +62 -112
  162. package/lib/commonjs/networking/apiClient.js.map +1 -1
  163. package/lib/commonjs/networking/authRefresh.js +332 -0
  164. package/lib/commonjs/networking/authRefresh.js.map +1 -0
  165. package/lib/commonjs/networking/stanzaHandlers.js +41 -28
  166. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  167. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +46 -8
  168. package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  169. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +8 -1
  170. package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  171. package/lib/commonjs/networking/xmpp/subscribeToRoomMessages.xmpp.js +5 -1
  172. package/lib/commonjs/networking/xmpp/subscribeToRoomMessages.xmpp.js.map +1 -1
  173. package/lib/commonjs/networking/xmppClient.js +124 -8
  174. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  175. package/lib/commonjs/roomStore/chatSettingsSlice.js +26 -7
  176. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  177. package/lib/commonjs/roomStore/index.js +35 -2
  178. package/lib/commonjs/roomStore/index.js.map +1 -1
  179. package/lib/commonjs/roomStore/persistence.js +226 -23
  180. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  181. package/lib/commonjs/roomStore/roomsSlice.js +151 -38
  182. package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
  183. package/lib/commonjs/services/pushSubscriptionService.js +15 -13
  184. package/lib/commonjs/services/pushSubscriptionService.js.map +1 -1
  185. package/lib/commonjs/version.js +1 -1
  186. package/lib/module/assets/icons.js +6 -1
  187. package/lib/module/assets/icons.js.map +1 -1
  188. package/lib/module/components/AuthForms/Login.js +4 -4
  189. package/lib/module/components/AuthForms/Login.js.map +1 -1
  190. package/lib/module/components/Header/HeaderRoomList.js +29 -8
  191. package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
  192. package/lib/module/components/MainComponents/ChatHeader.js +9 -3
  193. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  194. package/lib/module/components/MainComponents/ChatRoom.js +152 -16
  195. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  196. package/lib/module/components/MainComponents/ChatWrapper.js +35 -14
  197. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  198. package/lib/module/components/MainComponents/LoginWrapper.js +2 -1
  199. package/lib/module/components/MainComponents/LoginWrapper.js.map +1 -1
  200. package/lib/module/components/MainComponents/MediaMessage.js +30 -10
  201. package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
  202. package/lib/module/components/MainComponents/MessageContainer.js +5 -1
  203. package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
  204. package/lib/module/components/MainComponents/MessageList.js +13 -5
  205. package/lib/module/components/MainComponents/MessageList.js.map +1 -1
  206. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js +14 -13
  207. package/lib/module/components/MainComponents/ProfileImagePlaceholder.js.map +1 -1
  208. package/lib/module/components/MainComponents/RoomList.js +207 -35
  209. package/lib/module/components/MainComponents/RoomList.js.map +1 -1
  210. package/lib/module/components/Menu/HeaderRoomListMenu.js +319 -101
  211. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  212. package/lib/module/components/Modals/AttachSheet/AttachSheet.js +313 -113
  213. package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
  214. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +549 -207
  215. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  216. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +223 -0
  217. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -0
  218. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +70 -28
  219. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  220. package/lib/module/components/Modals/FilePreviewModal/PdfView.js +2 -1
  221. package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  222. package/lib/module/components/Modals/Modal/Modal.js +9 -1
  223. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  224. package/lib/module/components/Modals/NewChatModal/ModalContent.js +2 -1
  225. package/lib/module/components/Modals/NewChatModal/ModalContent.js.map +1 -1
  226. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +205 -108
  227. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  228. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js +8 -0
  229. package/lib/module/components/Modals/NewChatModal/UpdNewChatModal.js.map +1 -1
  230. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js +555 -0
  231. package/lib/module/components/Modals/ProfileHeader/ProfileHeader.js.map +1 -0
  232. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js +205 -0
  233. package/lib/module/components/Modals/ProfileHeader/ProfileMenu.js.map +1 -0
  234. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +4 -2
  235. package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
  236. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js +9 -23
  237. package/lib/module/components/Modals/UserProfileModal/EditUserModal.js.map +1 -1
  238. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +509 -248
  239. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  240. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +76 -48
  241. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  242. package/lib/module/components/Modals/styledModalComponents.js +9 -2
  243. package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
  244. package/lib/module/components/RoomComponents/ChatRoomItem.js +21 -7
  245. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  246. package/lib/module/components/RoomComponents/styled/LastMessageFile.js +22 -3
  247. package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  248. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +17 -3
  249. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  250. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +17 -3
  251. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  252. package/lib/module/components/VideoCalls/VideoCallSession.js +6 -3
  253. package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -1
  254. package/lib/module/components/styled/AudioMessage.js +2 -1
  255. package/lib/module/components/styled/AudioMessage.js.map +1 -1
  256. package/lib/module/components/styled/MessageImage.js +37 -9
  257. package/lib/module/components/styled/MessageImage.js.map +1 -1
  258. package/lib/module/components/styled/SendInput.js +81 -12
  259. package/lib/module/components/styled/SendInput.js.map +1 -1
  260. package/lib/module/components/styled/StyledComponents.js +9 -3
  261. package/lib/module/components/styled/StyledComponents.js.map +1 -1
  262. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +11 -4
  263. package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
  264. package/lib/module/components/styled/UnsupportedType.js +14 -4
  265. package/lib/module/components/styled/UnsupportedType.js.map +1 -1
  266. package/lib/module/components/styled/VideoMessage.js +120 -62
  267. package/lib/module/components/styled/VideoMessage.js.map +1 -1
  268. package/lib/module/context/xmppProvider.js +184 -60
  269. package/lib/module/context/xmppProvider.js.map +1 -1
  270. package/lib/module/helpers/createMessageFromXml.js +19 -1
  271. package/lib/module/helpers/createMessageFromXml.js.map +1 -1
  272. package/lib/module/helpers/ensureScopedChatCache.js +2 -2
  273. package/lib/module/helpers/ensureScopedChatCache.js.map +1 -1
  274. package/lib/module/helpers/getChatBackground.js +18 -0
  275. package/lib/module/helpers/getChatBackground.js.map +1 -0
  276. package/lib/module/helpers/getDisplayFileName.js +73 -0
  277. package/lib/module/helpers/getDisplayFileName.js.map +1 -0
  278. package/lib/module/helpers/getServerReadTimestamp.js +181 -0
  279. package/lib/module/helpers/getServerReadTimestamp.js.map +1 -0
  280. package/lib/module/helpers/historyPreloadScheduler.js +66 -3
  281. package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
  282. package/lib/module/helpers/initXmppRooms.js +14 -8
  283. package/lib/module/helpers/initXmppRooms.js.map +1 -1
  284. package/lib/module/helpers/insertMessageWithDelimiter.js +52 -9
  285. package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
  286. package/lib/module/helpers/isOwnMessage.js +70 -0
  287. package/lib/module/helpers/isOwnMessage.js.map +1 -0
  288. package/lib/module/helpers/keyboardLayout.js +12 -2
  289. package/lib/module/helpers/keyboardLayout.js.map +1 -1
  290. package/lib/module/helpers/mediaLibraryRuntime.js +25 -0
  291. package/lib/module/helpers/mediaLibraryRuntime.js.map +1 -0
  292. package/lib/module/helpers/mimeToExtension.js +6 -13
  293. package/lib/module/helpers/mimeToExtension.js.map +1 -1
  294. package/lib/module/helpers/msgSortableMs.js +32 -0
  295. package/lib/module/helpers/msgSortableMs.js.map +1 -0
  296. package/lib/module/helpers/persistCrypto.js +115 -0
  297. package/lib/module/helpers/persistCrypto.js.map +1 -0
  298. package/lib/module/helpers/pickImageAsset.js +63 -0
  299. package/lib/module/helpers/pickImageAsset.js.map +1 -0
  300. package/lib/module/helpers/pushPayload.js +63 -0
  301. package/lib/module/helpers/pushPayload.js.map +1 -0
  302. package/lib/module/helpers/resolveInitBeforeLoadUser.js +130 -16
  303. package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
  304. package/lib/module/helpers/secureFileUrl.js +91 -0
  305. package/lib/module/helpers/secureFileUrl.js.map +1 -0
  306. package/lib/module/helpers/secureKeyValue.js +75 -0
  307. package/lib/module/helpers/secureKeyValue.js.map +1 -0
  308. package/lib/module/helpers/secureStoreRuntime.js +52 -0
  309. package/lib/module/helpers/secureStoreRuntime.js.map +1 -0
  310. package/lib/module/helpers/secureUserStorage.js +72 -0
  311. package/lib/module/helpers/secureUserStorage.js.map +1 -0
  312. package/lib/module/helpers/shallowEqual.js +31 -0
  313. package/lib/module/helpers/shallowEqual.js.map +1 -0
  314. package/lib/module/helpers/sheetGestures.js +26 -0
  315. package/lib/module/helpers/sheetGestures.js.map +1 -0
  316. package/lib/module/hooks/useChatRoomFocus.js +46 -13
  317. package/lib/module/hooks/useChatRoomFocus.js.map +1 -1
  318. package/lib/module/hooks/useChatWrapperInit.js +30 -10
  319. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  320. package/lib/module/hooks/useComposing.js +28 -1
  321. package/lib/module/hooks/useComposing.js.map +1 -1
  322. package/lib/module/hooks/useFileToken.js +5 -0
  323. package/lib/module/hooks/useFileToken.js.map +1 -0
  324. package/lib/module/hooks/useLogout.js +23 -7
  325. package/lib/module/hooks/useLogout.js.map +1 -1
  326. package/lib/module/hooks/usePendingNotification.js +8 -11
  327. package/lib/module/hooks/usePendingNotification.js.map +1 -1
  328. package/lib/module/hooks/useSendMessage.js +52 -16
  329. package/lib/module/hooks/useSendMessage.js.map +1 -1
  330. package/lib/module/hooks/useUnreadMessagesCounter.js +6 -1
  331. package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
  332. package/lib/module/i18n/strings.js +145 -37
  333. package/lib/module/i18n/strings.js.map +1 -1
  334. package/lib/module/main.js +14 -2
  335. package/lib/module/main.js.map +1 -1
  336. package/lib/module/networking/api-requests/auth.api.js +131 -59
  337. package/lib/module/networking/api-requests/auth.api.js.map +1 -1
  338. package/lib/module/networking/api-requests/roomMembers.api.js +1 -1
  339. package/lib/module/networking/api-requests/roomMembers.api.js.map +1 -1
  340. package/lib/module/networking/api-requests/rooms.api.js +9 -9
  341. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  342. package/lib/module/networking/api-requests/user.api.js +64 -7
  343. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  344. package/lib/module/networking/apiClient.js +61 -113
  345. package/lib/module/networking/apiClient.js.map +1 -1
  346. package/lib/module/networking/authRefresh.js +321 -0
  347. package/lib/module/networking/authRefresh.js.map +1 -0
  348. package/lib/module/networking/stanzaHandlers.js +41 -28
  349. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  350. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +46 -8
  351. package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
  352. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +8 -1
  353. package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
  354. package/lib/module/networking/xmpp/subscribeToRoomMessages.xmpp.js +5 -1
  355. package/lib/module/networking/xmpp/subscribeToRoomMessages.xmpp.js.map +1 -1
  356. package/lib/module/networking/xmppClient.js +124 -8
  357. package/lib/module/networking/xmppClient.js.map +1 -1
  358. package/lib/module/roomStore/chatSettingsSlice.js +26 -7
  359. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  360. package/lib/module/roomStore/index.js +37 -4
  361. package/lib/module/roomStore/index.js.map +1 -1
  362. package/lib/module/roomStore/persistence.js +223 -22
  363. package/lib/module/roomStore/persistence.js.map +1 -1
  364. package/lib/module/roomStore/roomsSlice.js +139 -34
  365. package/lib/module/roomStore/roomsSlice.js.map +1 -1
  366. package/lib/module/services/pushSubscriptionService.js +15 -13
  367. package/lib/module/services/pushSubscriptionService.js.map +1 -1
  368. package/lib/module/version.js +1 -1
  369. package/lib/typescript/assets/icons.d.ts +16 -0
  370. package/lib/typescript/assets/icons.d.ts.map +1 -1
  371. package/lib/typescript/components/AuthForms/Login.d.ts.map +1 -1
  372. package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
  373. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  374. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  375. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  376. package/lib/typescript/components/MainComponents/LoginWrapper.d.ts.map +1 -1
  377. package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
  378. package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
  379. package/lib/typescript/components/MainComponents/MessageList.d.ts +10 -1
  380. package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
  381. package/lib/typescript/components/MainComponents/ProfileImagePlaceholder.d.ts.map +1 -1
  382. package/lib/typescript/components/MainComponents/RoomList.d.ts +7 -0
  383. package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
  384. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +3 -0
  385. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  386. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts +9 -0
  387. package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
  388. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +10 -0
  389. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  390. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts +9 -0
  391. package/lib/typescript/components/Modals/ChatProfileModal/ReportChatModal.d.ts.map +1 -0
  392. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  393. package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
  394. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  395. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts +4 -2
  396. package/lib/typescript/components/Modals/NewChatModal/ModalContent.d.ts.map +1 -1
  397. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts +1 -1
  398. package/lib/typescript/components/Modals/NewChatModal/NewChatModal.d.ts.map +1 -1
  399. package/lib/typescript/components/Modals/NewChatModal/UpdNewChatModal.d.ts.map +1 -1
  400. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts +75 -0
  401. package/lib/typescript/components/Modals/ProfileHeader/ProfileHeader.d.ts.map +1 -0
  402. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts +25 -0
  403. package/lib/typescript/components/Modals/ProfileHeader/ProfileMenu.d.ts.map +1 -0
  404. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts +6 -1
  405. package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
  406. package/lib/typescript/components/Modals/UserProfileModal/EditUserModal.d.ts.map +1 -1
  407. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts +16 -0
  408. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  409. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts +1 -0
  410. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  411. package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
  412. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  413. package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts +1 -1
  414. package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts.map +1 -1
  415. package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts +1 -1
  416. package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts.map +1 -1
  417. package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts +1 -1
  418. package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts.map +1 -1
  419. package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -1
  420. package/lib/typescript/components/styled/AudioMessage.d.ts.map +1 -1
  421. package/lib/typescript/components/styled/MessageImage.d.ts +14 -0
  422. package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
  423. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  424. package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
  425. package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
  426. package/lib/typescript/components/styled/UnsupportedType.d.ts.map +1 -1
  427. package/lib/typescript/components/styled/VideoMessage.d.ts +8 -0
  428. package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
  429. package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
  430. package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
  431. package/lib/typescript/helpers/getChatBackground.d.ts +15 -0
  432. package/lib/typescript/helpers/getChatBackground.d.ts.map +1 -0
  433. package/lib/typescript/helpers/getDisplayFileName.d.ts +49 -0
  434. package/lib/typescript/helpers/getDisplayFileName.d.ts.map +1 -0
  435. package/lib/typescript/helpers/getServerReadTimestamp.d.ts +108 -0
  436. package/lib/typescript/helpers/getServerReadTimestamp.d.ts.map +1 -0
  437. package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
  438. package/lib/typescript/helpers/initXmppRooms.d.ts.map +1 -1
  439. package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts +1 -1
  440. package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
  441. package/lib/typescript/helpers/isOwnMessage.d.ts +36 -0
  442. package/lib/typescript/helpers/isOwnMessage.d.ts.map +1 -0
  443. package/lib/typescript/helpers/keyboardLayout.d.ts +5 -1
  444. package/lib/typescript/helpers/keyboardLayout.d.ts.map +1 -1
  445. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts +3 -0
  446. package/lib/typescript/helpers/mediaLibraryRuntime.d.ts.map +1 -0
  447. package/lib/typescript/helpers/mimeToExtension.d.ts +0 -15
  448. package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -1
  449. package/lib/typescript/helpers/msgSortableMs.d.ts +2 -0
  450. package/lib/typescript/helpers/msgSortableMs.d.ts.map +1 -0
  451. package/lib/typescript/helpers/persistCrypto.d.ts +13 -0
  452. package/lib/typescript/helpers/persistCrypto.d.ts.map +1 -0
  453. package/lib/typescript/helpers/pickImageAsset.d.ts +27 -0
  454. package/lib/typescript/helpers/pickImageAsset.d.ts.map +1 -0
  455. package/lib/typescript/helpers/pushPayload.d.ts +7 -0
  456. package/lib/typescript/helpers/pushPayload.d.ts.map +1 -0
  457. package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
  458. package/lib/typescript/helpers/secureFileUrl.d.ts +7 -0
  459. package/lib/typescript/helpers/secureFileUrl.d.ts.map +1 -0
  460. package/lib/typescript/helpers/secureKeyValue.d.ts +13 -0
  461. package/lib/typescript/helpers/secureKeyValue.d.ts.map +1 -0
  462. package/lib/typescript/helpers/secureStoreRuntime.d.ts +29 -0
  463. package/lib/typescript/helpers/secureStoreRuntime.d.ts.map +1 -0
  464. package/lib/typescript/helpers/secureUserStorage.d.ts +23 -0
  465. package/lib/typescript/helpers/secureUserStorage.d.ts.map +1 -0
  466. package/lib/typescript/helpers/shallowEqual.d.ts +11 -0
  467. package/lib/typescript/helpers/shallowEqual.d.ts.map +1 -0
  468. package/lib/typescript/helpers/sheetGestures.d.ts +20 -0
  469. package/lib/typescript/helpers/sheetGestures.d.ts.map +1 -0
  470. package/lib/typescript/hooks/useChatRoomFocus.d.ts +4 -1
  471. package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -1
  472. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  473. package/lib/typescript/hooks/useComposing.d.ts.map +1 -1
  474. package/lib/typescript/hooks/useFileToken.d.ts +2 -0
  475. package/lib/typescript/hooks/useFileToken.d.ts.map +1 -0
  476. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  477. package/lib/typescript/hooks/usePendingNotification.d.ts.map +1 -1
  478. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  479. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts +1 -0
  480. package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
  481. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  482. package/lib/typescript/main.d.ts +9 -2
  483. package/lib/typescript/main.d.ts.map +1 -1
  484. package/lib/typescript/networking/api-requests/auth.api.d.ts +3 -1
  485. package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
  486. package/lib/typescript/networking/api-requests/user.api.d.ts +27 -0
  487. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  488. package/lib/typescript/networking/apiClient.d.ts +12 -6
  489. package/lib/typescript/networking/apiClient.d.ts.map +1 -1
  490. package/lib/typescript/networking/authRefresh.d.ts +95 -0
  491. package/lib/typescript/networking/authRefresh.d.ts.map +1 -0
  492. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  493. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +10 -2
  494. package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
  495. package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
  496. package/lib/typescript/networking/xmpp/subscribeToRoomMessages.xmpp.d.ts.map +1 -1
  497. package/lib/typescript/networking/xmppClient.d.ts +14 -0
  498. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  499. package/lib/typescript/roomStore/chatSettingsSlice.d.ts +16 -0
  500. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  501. package/lib/typescript/roomStore/index.d.ts.map +1 -1
  502. package/lib/typescript/roomStore/persistence.d.ts +18 -1
  503. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  504. package/lib/typescript/roomStore/roomsSlice.d.ts +43 -3
  505. package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
  506. package/lib/typescript/services/pushSubscriptionService.d.ts +1 -1
  507. package/lib/typescript/services/pushSubscriptionService.d.ts.map +1 -1
  508. package/lib/typescript/types/types.d.ts +50 -5
  509. package/lib/typescript/types/types.d.ts.map +1 -1
  510. package/lib/typescript/version.d.ts +1 -1
  511. package/package.json +41 -28
  512. package/src/assets/icons.tsx +48 -9
  513. package/src/components/AuthForms/Login.tsx +3 -3
  514. package/src/components/Header/HeaderRoomList.tsx +29 -7
  515. package/src/components/MainComponents/ChatHeader.tsx +9 -3
  516. package/src/components/MainComponents/ChatRoom.tsx +161 -15
  517. package/src/components/MainComponents/ChatWrapper.tsx +36 -20
  518. package/src/components/MainComponents/LoginWrapper.tsx +1 -0
  519. package/src/components/MainComponents/MediaMessage.tsx +26 -8
  520. package/src/components/MainComponents/MessageContainer.tsx +5 -1
  521. package/src/components/MainComponents/MessageList.tsx +23 -4
  522. package/src/components/MainComponents/ProfileImagePlaceholder.tsx +21 -14
  523. package/src/components/MainComponents/RoomList.tsx +236 -39
  524. package/src/components/Menu/HeaderRoomListMenu.tsx +328 -75
  525. package/src/components/Modals/AttachSheet/AttachSheet.tsx +333 -97
  526. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +600 -282
  527. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +244 -0
  528. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +79 -38
  529. package/src/components/Modals/FilePreviewModal/PdfView.tsx +2 -1
  530. package/src/components/Modals/Modal/Modal.tsx +7 -0
  531. package/src/components/Modals/NewChatModal/ModalContent.tsx +6 -3
  532. package/src/components/Modals/NewChatModal/NewChatModal.tsx +219 -119
  533. package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +12 -1
  534. package/src/components/Modals/ProfileHeader/ProfileHeader.tsx +624 -0
  535. package/src/components/Modals/ProfileHeader/ProfileMenu.tsx +217 -0
  536. package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +14 -4
  537. package/src/components/Modals/UserProfileModal/EditUserModal.tsx +9 -25
  538. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +617 -307
  539. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +75 -58
  540. package/src/components/Modals/styledModalComponents.tsx +9 -2
  541. package/src/components/RoomComponents/ChatRoomItem.tsx +18 -3
  542. package/src/components/RoomComponents/styled/LastMessageFile.tsx +28 -4
  543. package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +18 -3
  544. package/src/components/RoomComponents/styled/LastMessageVideo.tsx +18 -3
  545. package/src/components/VideoCalls/VideoCallSession.tsx +8 -3
  546. package/src/components/styled/AudioMessage.tsx +2 -1
  547. package/src/components/styled/MessageImage.tsx +53 -7
  548. package/src/components/styled/SendInput.tsx +83 -12
  549. package/src/components/styled/StyledComponents.ts +9 -3
  550. package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +11 -4
  551. package/src/components/styled/UnsupportedType.tsx +14 -4
  552. package/src/components/styled/VideoMessage.tsx +131 -54
  553. package/src/context/xmppProvider.tsx +216 -57
  554. package/src/helpers/createMessageFromXml.ts +20 -1
  555. package/src/helpers/ensureScopedChatCache.ts +2 -2
  556. package/src/helpers/getChatBackground.ts +18 -0
  557. package/src/helpers/getDisplayFileName.ts +87 -0
  558. package/src/helpers/getServerReadTimestamp.ts +197 -0
  559. package/src/helpers/historyPreloadScheduler.ts +80 -3
  560. package/src/helpers/initXmppRooms.tsx +14 -10
  561. package/src/helpers/insertMessageWithDelimiter.ts +55 -19
  562. package/src/helpers/isOwnMessage.ts +90 -0
  563. package/src/helpers/keyboardLayout.ts +23 -2
  564. package/src/helpers/mediaLibraryRuntime.ts +25 -0
  565. package/src/helpers/mimeToExtension.ts +6 -22
  566. package/src/helpers/msgSortableMs.ts +25 -0
  567. package/src/helpers/persistCrypto.ts +127 -0
  568. package/src/helpers/pickImageAsset.ts +68 -0
  569. package/src/helpers/pushPayload.ts +62 -0
  570. package/src/helpers/resolveInitBeforeLoadUser.ts +125 -18
  571. package/src/helpers/secureFileUrl.ts +103 -0
  572. package/src/helpers/secureKeyValue.ts +80 -0
  573. package/src/helpers/secureStoreRuntime.ts +62 -0
  574. package/src/helpers/secureUserStorage.ts +80 -0
  575. package/src/helpers/shallowEqual.ts +33 -0
  576. package/src/helpers/sheetGestures.ts +25 -0
  577. package/src/hooks/useChatRoomFocus.ts +49 -9
  578. package/src/hooks/useChatWrapperInit.ts +30 -10
  579. package/src/hooks/useComposing.tsx +37 -1
  580. package/src/hooks/useFileToken.ts +7 -0
  581. package/src/hooks/useLogout.tsx +29 -9
  582. package/src/hooks/usePendingNotification.ts +5 -11
  583. package/src/hooks/useSendMessage.tsx +60 -15
  584. package/src/hooks/useUnreadMessagesCounter.ts +11 -0
  585. package/src/i18n/strings.ts +145 -37
  586. package/src/main.ts +26 -2
  587. package/src/networking/api-requests/auth.api.ts +156 -48
  588. package/src/networking/api-requests/roomMembers.api.ts +1 -1
  589. package/src/networking/api-requests/rooms.api.ts +9 -9
  590. package/src/networking/api-requests/user.api.ts +79 -7
  591. package/src/networking/apiClient.ts +68 -123
  592. package/src/networking/authRefresh.ts +451 -0
  593. package/src/networking/stanzaHandlers.ts +44 -28
  594. package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +71 -10
  595. package/src/networking/xmpp/presenceInRoom.xmpp.ts +6 -1
  596. package/src/networking/xmpp/subscribeToRoomMessages.xmpp.ts +12 -1
  597. package/src/networking/xmppClient.ts +141 -9
  598. package/src/roomStore/chatSettingsSlice.ts +34 -10
  599. package/src/roomStore/index.ts +40 -4
  600. package/src/roomStore/persistence.ts +234 -24
  601. package/src/roomStore/roomsSlice.ts +161 -29
  602. package/src/services/pushSubscriptionService.ts +18 -13
  603. package/src/types/types.ts +72 -5
  604. package/src/version.ts +1 -1
@@ -14,7 +14,7 @@ import { VideoCallOverlay } from '../components/VideoCalls/VideoCallOverlay';
14
14
  import XmppClient, {
15
15
  XmppCredentialsProvider,
16
16
  } from '../networking/xmppClient';
17
- import { refreshTokens } from '../roomStore/chatSettingsSlice';
17
+ import { refreshAuthTokensQuietly } from '../networking/authRefresh';
18
18
  import {
19
19
  IConfig,
20
20
  ProviderBootstrapStatus,
@@ -37,6 +37,7 @@ import {
37
37
  import { ensureScopedChatCache } from '../helpers/ensureScopedChatCache';
38
38
  import { getRooms as prefetchRoomsViaRest } from '../networking/api-requests/rooms.api';
39
39
  import { allRoomPresences } from '../networking/xmpp/allRoomPresences.xmpp';
40
+ import { pushSubscriptionService } from '../services/pushSubscriptionService';
40
41
  import { store } from '../roomStore';
41
42
  import { logout, setStoreClient, setConfig } from '../roomStore/chatSettingsSlice';
42
43
  import {
@@ -45,12 +46,15 @@ import {
45
46
  clearVisibleRoom,
46
47
  setLastViewedTimestamp,
47
48
  deleteRoomMessage,
48
- msgSortableMs,
49
49
  setUnreadSyncing,
50
50
  } from '../roomStore/roomsSlice';
51
+ import {
52
+ getFlushBoundaryTs,
53
+ getReadMarkerTimestamp,
54
+ } from '../helpers/getServerReadTimestamp';
51
55
  import { runHistoryPreloadScheduler } from '../helpers/historyPreloadScheduler';
52
- import { asyncLocalStorage } from '../hooks/useLocalStorage';
53
- import { localStorageConstants } from '../helpers/constants/LOCAL_STORAGE';
56
+ import { updateMessagesTillLast } from '../helpers/updateMessagesTillLast';
57
+ import { secureUserStorage } from '../helpers/secureUserStorage';
54
58
  import { clearPersistedState } from '../roomStore/persistence';
55
59
  import { pushLog as devPushLog } from '../utils/devLogger';
56
60
 
@@ -83,6 +87,16 @@ interface XmppProviderProps {
83
87
 
84
88
  const LOGOUT_EVENT = 'ethora-xmpp-logout';
85
89
 
90
+ const subscribeAllRoomsForPush = (client: any, reason: string) => {
91
+ const rooms = Object.keys(store.getState().rooms.rooms || {});
92
+ if (!client || !rooms.length) {return;}
93
+ const nick = client.jid?.getLocal();
94
+ pushSubscriptionService
95
+ .subscribeToRooms(client, rooms, nick)
96
+ .then(() => devPushLog('xmpp', `${reason}: mucsub ok for ${rooms.length} rooms`))
97
+ .catch((e) => devPushLog('warn', `${reason}: mucsub subscribe failed`, e));
98
+ };
99
+
86
100
  export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, isVisible }) => {
87
101
  const [client, setClient] = useState<XmppClient | null>(null);
88
102
  const [providerBootstrapStatus, setProviderBootstrapStatus] =
@@ -107,23 +121,25 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
107
121
  // the XmppClient at least doesn't crash on `undefined.password`.
108
122
  const credentialsProvider = useMemo<XmppCredentialsProvider>(() => {
109
123
  return async () => {
110
- // 1. Consumer-supplied REST refresh (when wired). This runs
111
- // before the SDK's own refresh chain so non-Ethora backends
112
- // can keep auth state in sync with their own token endpoint.
113
- const customRefresh = config?.refreshTokens?.refreshFunction;
114
- if (customRefresh) {
115
- try {
116
- const result = await customRefresh();
117
- if (result?.accessToken) {
118
- store.dispatch(
119
- refreshTokens({
120
- token: result.accessToken,
121
- refreshToken: result.refreshToken || '',
122
- })
123
- );
124
- }
125
- } catch (err) {
126
- devPushLog('warn', 'XMPP creds refresh: customRefresh failed', err);
124
+ // 1. Make sure the REST tokens are fresh before re-minting XMPP
125
+ // creds. This used to call `config.refreshTokens.refreshFunction`
126
+ // directly and then fall into step 2, which refreshes again —
127
+ // two rotations back to back, which the new backend scheme
128
+ // reads as a race at best and token reuse at worst. One call to
129
+ // the shared rotation point covers both the consumer-supplied
130
+ // function and the built-in endpoint.
131
+ if (config?.refreshTokens?.enabled) {
132
+ const rotated = await refreshAuthTokensQuietly({ force: true });
133
+
134
+ if (rotated?.xmppPassword) {
135
+ const rotatedUser = store.getState().chatSettingStore.user;
136
+ return {
137
+ username:
138
+ rotatedUser?.xmppUsername ||
139
+ rotatedUser?.defaultWallet?.walletAddress ||
140
+ '',
141
+ password: rotated.xmppPassword,
142
+ };
127
143
  }
128
144
  }
129
145
 
@@ -163,7 +179,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
163
179
  }, [
164
180
  config?.jwtLogin?.enabled,
165
181
  config?.jwtLogin?.token,
166
- config?.refreshTokens?.refreshFunction,
182
+ config?.refreshTokens?.enabled,
167
183
  config?.userLogin?.enabled,
168
184
  config?.customLogin?.enabled,
169
185
  config?.initBeforeLoadAuth?.myEndpoint,
@@ -227,9 +243,11 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
227
243
  created.setOnOnline(() => {
228
244
  const underlying = (created as any).client;
229
245
  if (!underlying) {return;}
230
- allRoomPresences(underlying).catch((e) =>
231
- devPushLog('warn', 'reconnect: allRoomPresences re-join failed', e)
232
- );
246
+ allRoomPresences(underlying)
247
+ .catch((e) =>
248
+ devPushLog('warn', 'reconnect: allRoomPresences re-join failed', e)
249
+ )
250
+ .finally(() => subscribeAllRoomsForPush(underlying, 'reconnect'));
233
251
  // Also refresh the private store so unread / lastViewed markers
234
252
  // are accurate after a long reconnect — the MUC re-join above only
235
253
  // restores delivery, not unread state. Idempotent on first connect.
@@ -238,6 +256,19 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
238
256
  .catch((e: unknown) =>
239
257
  devPushLog('warn', 'reconnect: privateStore refresh failed', e)
240
258
  );
259
+ // Pull whatever landed in each room's archive while the stream was
260
+ // down. MUC presence re-join above only restores delivery for
261
+ // messages sent AFTER this reconnect — anything sent during the
262
+ // offline window has no live stanza to catch, and previously only
263
+ // came back on a full app restart (fresh useChatWrapperInit mount
264
+ // re-running its own one-shot boot sync). Safe on the very first
265
+ // connect too: rooms have no `lastMessageTimestamp` yet at that
266
+ // point, so this is a no-op until the bootstrap's own history load
267
+ // populates it. Customer-reported #32.
268
+ const rooms = store.getState().rooms?.rooms || {};
269
+ updateMessagesTillLast(rooms, created).catch((e: unknown) =>
270
+ devPushLog('warn', 'reconnect: offline catch-up sync failed', e)
271
+ );
241
272
  });
242
273
 
243
274
  setClient(created);
@@ -299,6 +330,13 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
299
330
 
300
331
  if (completedBootstrapKeyRef.current === key) {
301
332
  devPushLog('rn', 'initBeforeLoad: already completed (same key) — skip');
333
+ // This run does no work, so it must not leave the budget it armed
334
+ // above running: 45 s later it would flip an already-'ready'
335
+ // provider to 'failed' and surface "Could not authenticate" over a
336
+ // healthy connection. Any dep change that leaves the key intact
337
+ // triggers this - e.g. a rotated `userLogin.user.token`.
338
+ reachedReady = true;
339
+ clearBudget();
302
340
  return;
303
341
  }
304
342
  if (inflightBootstrapKeyRef.current === key) {
@@ -322,7 +360,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
322
360
  devPushLog('rn', 'initBeforeLoad: clearStoreBeforeInit');
323
361
  store.dispatch(setLogoutState());
324
362
  store.dispatch(logout());
325
- await asyncLocalStorage(localStorageConstants.ETHORA_USER).remove().catch(() => undefined);
363
+ await secureUserStorage().remove().catch(() => undefined);
326
364
  }
327
365
 
328
366
  await ensureScopedChatCache(config);
@@ -353,6 +391,29 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
353
391
  store.dispatch(setConfig(config));
354
392
  }
355
393
 
394
+ // Rotate BEFORE the first XMPP connect. On the rotating backend
395
+ // the xmpp password is a short-lived JWT that only the newest
396
+ // rotation knows, and each rotation invalidates its predecessors
397
+ // — so a snapshot's password (a host's cached `userLogin.user`,
398
+ // a persisted session) is usually already dead at boot. Without
399
+ // this, the first SASL attempt fails `not-authorized`, all three
400
+ // bootstrap retries re-present the same dead password, and the
401
+ // user dead-ends on the Connection error modal even though one
402
+ // rotation away a perfectly good session existed. The rotation
403
+ // also lands the fileToken pre-render, so secure media never
404
+ // paints blank first. Quiet + deduped; when it can't rotate
405
+ // (no refresh material, non-rotating backend) we just connect
406
+ // with what the snapshot has, exactly as before.
407
+ // jwtLogin is skipped: /users/client just minted fresh creds.
408
+ let connectPassword = resolved.xmppPassword;
409
+ if (config?.refreshTokens?.enabled && !config?.jwtLogin?.enabled) {
410
+ const rotated = await refreshAuthTokensQuietly({ force: true });
411
+ if (cancelled) {return;}
412
+ if (rotated?.xmppPassword) {
413
+ connectPassword = rotated.xmppPassword;
414
+ }
415
+ }
416
+
356
417
  // Kick off REST /chats/my; allRoomPresences below needs the
357
418
  // room list to be in redux, otherwise it joins 0 MUCs and the
358
419
  // user receives zero realtime messages until they manually tap
@@ -362,7 +423,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
362
423
 
363
424
  const c = await initializeClient(
364
425
  resolved.xmppUsername!,
365
- resolved.xmppPassword,
426
+ connectPassword,
366
427
  config?.xmppSettings
367
428
  );
368
429
  if (cancelled) {return;}
@@ -398,6 +459,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
398
459
  } catch (e) {
399
460
  devPushLog('warn', 'initBeforeLoad: allRoomPresences failed', e);
400
461
  }
462
+ subscribeAllRoomsForPush((c as any).client, 'initBeforeLoad');
401
463
 
402
464
  store.dispatch(setStoreClient(c));
403
465
  completedBootstrapKeyRef.current = key;
@@ -542,9 +604,14 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
542
604
  // be re-marked visible on return. Lives in the effect closure (one per
543
605
  // client) — persists across the listener's many invocations.
544
606
  let visibleBeforeBackground: string | null = null;
607
+ const suspendInBackground = !config?.xmppSettings?.keepAliveInBackground;
545
608
  const sub = AppState.addEventListener('change', (next) => {
546
609
  const c = client;
547
610
  if (next === 'active') {
611
+ if (c?.isSuspended) {
612
+ devPushLog('rn', 'AppState active: resuming suspended XMPP client');
613
+ c.resume();
614
+ }
548
615
  // Returned to foreground. If the socket died while backgrounded
549
616
  // (iOS suspends the WebSocket; long background kills it), the
550
617
  // status may still read 'online' until xmpp.js notices the dead
@@ -572,22 +639,52 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
572
639
  }
573
640
  // Going to background/inactive (sleep / app switcher / tray):
574
641
  if (!c) {return;}
642
+ if (next === 'background' && suspendInBackground) {
643
+ c.suspend().catch(() => undefined);
644
+ }
575
645
  const state = store.getState();
576
646
  const rooms = state.rooms?.rooms;
577
647
  const visibleRoomJID = state.rooms?.visibleRoomJID || null;
578
648
  // Mark the open room "not visible" while backgrounded so messages
579
649
  // that arrive (or MAM-replay on reconnect) count as unread instead
580
650
  // of being silently treated as read — the "mounted == visible ==
581
- // read" gap. Stamp lastViewed=now as the read baseline, clear
582
- // visibility, then flush that marker to the server private store.
583
- // Restored on the next 'active' transition above. Handled here in
584
- // the provider so consumers using the component as a package get
585
- // correct unread without reaching into the chat store themselves.
651
+ // read" gap. Stamp lastViewed=<the read boundary, if the user left
652
+ // scrolled up, else the newest server-acked message>, not
653
+ // Date.now(), as the read baseline: a device clock running ahead
654
+ // would otherwise write a future marker that the forward-only
655
+ // private-store merge can never correct again (bug #38). Then
656
+ // clear visibility and flush that marker to the server private
657
+ // store. Restored on the next 'active' transition above. Handled
658
+ // here in the provider so consumers using the component as a
659
+ // package get correct unread without reaching into the chat store
660
+ // themselves.
661
+ //
662
+ // The read boundary (rooms.readBoundaries) is deliberately left
663
+ // untouched here - MessageList normally stays mounted through a
664
+ // simple background/foreground cycle, so its own scroll-tracking
665
+ // ref (the only thing that could re-derive this value) is still
666
+ // intact, and clearing the redux copy would desync the two. It's
667
+ // only USED here for the one-shot stamp+flush, matching customer
668
+ // #42: leaving (or backgrounding) a room while scrolled up must not
669
+ // mark messages the user never reached as read.
586
670
  visibleBeforeBackground = visibleRoomJID;
671
+ let boundaryTs: number | null = null;
587
672
  if (visibleRoomJID) {
588
- store.dispatch(
589
- setLastViewedTimestamp({ chatJID: visibleRoomJID, timestamp: Date.now() })
673
+ boundaryTs = state.rooms?.readBoundaries?.[visibleRoomJID] ?? null;
674
+ const readTs = getReadMarkerTimestamp(
675
+ rooms?.[visibleRoomJID],
676
+ state.roomHeapSlice,
677
+ boundaryTs
590
678
  );
679
+ // Nothing to anchor to yet (no known messages, no prior marker)
680
+ // - skip the local stamp rather than fall back to the device
681
+ // clock. The flush below still runs so the visibility clear
682
+ // isn't blocked on this.
683
+ if (readTs > 0) {
684
+ store.dispatch(
685
+ setLastViewedTimestamp({ chatJID: visibleRoomJID, timestamp: readTs })
686
+ );
687
+ }
591
688
  // Drop the "New messages" divider for the room we're leaving so it
592
689
  // doesn't linger when the user comes back (mirrors ChatRoom's
593
690
  // unmount cleanup, which never runs while the pane stays mounted).
@@ -597,13 +694,24 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
597
694
  store.dispatch(clearVisibleRoom());
598
695
  }
599
696
  // Fire-and-forget — we're going to the background and don't
600
- // care about the resolution path.
601
- c.flushLastViewedToPrivateStoreStanza(rooms, { visibleRoomJID }).catch(
602
- () => {}
603
- );
697
+ // care about the resolution path. `visibleRoomTs` carries the same
698
+ // boundary to the SERVER marker - without it the flush defaults to
699
+ // "everything" for the visible room, overriding a correct smaller
700
+ // local count.
701
+ c.flushLastViewedToPrivateStoreStanza(rooms, {
702
+ visibleRoomJID,
703
+ // Clamped through the same helper as the local stamp above.
704
+ visibleRoomTs: visibleRoomJID
705
+ ? getFlushBoundaryTs(
706
+ rooms?.[visibleRoomJID],
707
+ state.roomHeapSlice,
708
+ boundaryTs
709
+ )
710
+ : undefined,
711
+ }).catch(() => {});
604
712
  });
605
713
  return () => sub.remove();
606
- }, [client]);
714
+ }, [client, config?.xmppSettings?.keepAliveInBackground]);
607
715
 
608
716
  // -----------------------------------------------------------
609
717
  // Consumer visibility signal (`isVisible` prop). For hosts that keep
@@ -612,11 +720,11 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
612
720
  // "shown" from "hidden", so the unread middleware would keep the open
613
721
  // room's badge at 0 and messages arriving while you're elsewhere look
614
722
  // already-read. When the host passes `isVisible`, mirror the AppState
615
- // background/foreground handling: hidden → stamp lastViewed=now + clear
616
- // room visibility (so later messages count) + flush; shown → restore
617
- // visibility for the open room. Doing it here means consumers never
618
- // touch the chat store themselves. (Undefined = host unmounts on hide,
619
- // nothing to do.)
723
+ // background/foreground handling: hidden → stamp lastViewed=<newest
724
+ // server-acked message> + clear room visibility (so later messages
725
+ // count) + flush; shown → restore visibility for the open room. Doing
726
+ // it here means consumers never touch the chat store themselves.
727
+ // (Undefined = host unmounts on hide, nothing to do.)
620
728
  // -----------------------------------------------------------
621
729
  const chatWasVisibleRef = useRef(false);
622
730
  useEffect(() => {
@@ -631,10 +739,30 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
631
739
  store.dispatch(setVisibleRoom({ roomJID: activeRoomJID }));
632
740
  }
633
741
  } else {
742
+ // The read boundary (rooms.readBoundaries) is USED for the stamp
743
+ // and flush below but deliberately left in place - a host using
744
+ // `isVisible` keeps <Chat> mounted while hidden, so MessageList's
745
+ // own scroll-tracking ref is still intact and the redux copy must
746
+ // stay in sync with it. Only consumed, never Date.now(): a fast
747
+ // device clock would write a future marker that the forward-only
748
+ // private-store merge could then never correct (bug #38). And
749
+ // never "the newest acked message" unconditionally either - that
750
+ // silently marks messages the user scrolled past and never reached
751
+ // as read (bug #42, a regression of #33).
752
+ const boundaryTs = activeRoomJID
753
+ ? state.rooms?.readBoundaries?.[activeRoomJID] ?? null
754
+ : null;
634
755
  if (wasVisible && activeRoomJID) {
635
- store.dispatch(
636
- setLastViewedTimestamp({ chatJID: activeRoomJID, timestamp: Date.now() })
756
+ const readTs = getReadMarkerTimestamp(
757
+ rooms?.[activeRoomJID],
758
+ state.roomHeapSlice,
759
+ boundaryTs
637
760
  );
761
+ if (readTs > 0) {
762
+ store.dispatch(
763
+ setLastViewedTimestamp({ chatJID: activeRoomJID, timestamp: readTs })
764
+ );
765
+ }
638
766
  // Drop the "New messages" divider so it's gone when the user
639
767
  // returns to the chat (mirrors ChatRoom's unmount cleanup).
640
768
  store.dispatch(
@@ -645,7 +773,19 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
645
773
  store.dispatch(clearVisibleRoom());
646
774
  if (wasVisible && client?.flushLastViewedToPrivateStoreStanza) {
647
775
  client
648
- .flushLastViewedToPrivateStoreStanza(rooms, { visibleRoomJID: activeRoomJID })
776
+ .flushLastViewedToPrivateStoreStanza(rooms, {
777
+ visibleRoomJID: activeRoomJID,
778
+ // Carry the same boundary to the SERVER marker - without it
779
+ // the flush defaults to "everything" for the visible room.
780
+ // Clamped exactly like the local stamp above.
781
+ visibleRoomTs: activeRoomJID
782
+ ? getFlushBoundaryTs(
783
+ rooms?.[activeRoomJID],
784
+ state.roomHeapSlice,
785
+ boundaryTs
786
+ )
787
+ : undefined,
788
+ })
649
789
  .catch(() => {});
650
790
  }
651
791
  }
@@ -666,26 +806,45 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
666
806
  if (room.messages === lastMessagesRef) {return;}
667
807
  lastMessagesRef = room.messages;
668
808
 
669
- let newest = 0;
670
- const list = room.messages || [];
671
- for (const m of list) {
672
- if (!m || m.id === 'delimiter-new') {continue;}
673
- const ms = msgSortableMs(m);
674
- if (ms > newest) {newest = ms;}
675
- }
676
- if (newest <= lastStampedMs) {return;}
809
+ // getReadMarkerTimestamp (not a hand-rolled scan + Date.now()):
810
+ // it excludes pending/optimistic messages, which carry the DEVICE
811
+ // send time via `date` until the server echoes them back - a
812
+ // manual scan without that exclusion could pick up a pending
813
+ // message's device timestamp here and write a future marker the
814
+ // same way a raw Date.now() would (bug #38). And when the user has
815
+ // scrolled up (a boundary is set for this room), it clamps to that
816
+ // boundary instead of the newest message - without this, every
817
+ // incoming message while scrolled up advanced the marker to
818
+ // "newest" regardless of scroll position, and the later, smaller
819
+ // boundary write on leave was rejected by the forward-only
820
+ // private-store merge, leaving 0 unread even after a restart
821
+ // (customer #42, a regression of #33 reintroduced by #38).
822
+ const boundaryTs = s.rooms?.readBoundaries?.[jid] ?? null;
823
+ const newest = getReadMarkerTimestamp(room, s.roomHeapSlice, boundaryTs);
824
+ if (!newest || newest <= lastStampedMs) {return;}
677
825
  lastStampedMs = newest;
678
826
 
679
827
  store.dispatch(
680
- setLastViewedTimestamp({ chatJID: jid, timestamp: Date.now() })
828
+ setLastViewedTimestamp({ chatJID: jid, timestamp: newest })
681
829
  );
682
830
 
683
831
  if (flushTimer) {clearTimeout(flushTimer);}
684
832
  if (client?.flushLastViewedToPrivateStoreStanza) {
685
833
  flushTimer = setTimeout(() => {
834
+ // Re-read fresh state rather than closing over `boundaryTs`:
835
+ // the user may have scrolled back to the bottom (clearing the
836
+ // boundary) in the 2s between the stamp and this flush, and
837
+ // the flush should reflect that.
838
+ const freshState = store.getState();
839
+ const freshBoundaryTs = freshState.rooms?.readBoundaries?.[jid] ?? null;
686
840
  client
687
- .flushLastViewedToPrivateStoreStanza(store.getState().rooms?.rooms, {
841
+ .flushLastViewedToPrivateStoreStanza(freshState.rooms?.rooms, {
688
842
  visibleRoomJID: jid,
843
+ visibleRoomTs: getFlushBoundaryTs(
844
+ freshState.rooms?.rooms?.[jid],
845
+ freshState.roomHeapSlice,
846
+ freshBoundaryTs
847
+ ),
689
848
  })
690
849
  .catch(() => {});
691
850
  }, 2000);
@@ -93,6 +93,25 @@ export const createMessageFromXml = async (
93
93
  const senderLocal = senderJID.includes('@')
94
94
  ? senderJID.split('@')[0]
95
95
  : senderJID;
96
+
97
+ // Bug #41 root cause: the resource of the MUC `from` (room@conference/
98
+ // occupant-id) is the SAME field getDataFromXml uses to derive
99
+ // `user.id` for live messages and for the wrapped MAM convention
100
+ // (getHistory.xmpp.ts) - it's stamped by the server itself when the
101
+ // sender joined the room, so it's always present and always correct.
102
+ // The positional convention (onMessageHistory's MAM catch-up path)
103
+ // never called getDataFromXml, so it fell back to splitting the
104
+ // sender-supplied `<data senderJID>` attr on '@' instead - usually the
105
+ // same value, but WRONG (picks up the room's own id, not the
106
+ // sender's) whenever senderJID is absent from the stanza, and simply a
107
+ // different derivation than the live path even when it happens to
108
+ // agree. Prefer the resource-of-`from` here too so every path that
109
+ // reaches this function resolves the same sender identity the same
110
+ // way, instead of MAM catch-up rows needing a later correction once
111
+ // the "official" fetch lands.
112
+ const xmppFrom = (merged.xmppFrom || '').toString();
113
+ const fromResource = xmppFrom.includes('/') ? xmppFrom.split('/')[1] : '';
114
+
96
115
  const composed = [firstName, lastName].filter(Boolean).join(' ').trim();
97
116
  const existingName = String(merged?.user?.name || '').trim();
98
117
  const resolvedName =
@@ -107,7 +126,7 @@ export const createMessageFromXml = async (
107
126
  ...merged,
108
127
  user: {
109
128
  ...(merged.user || {}),
110
- id: merged?.user?.id || senderLocal,
129
+ id: merged?.user?.id || fromResource || senderLocal,
111
130
  name: resolvedName,
112
131
  firstName: firstName || merged?.user?.firstName,
113
132
  lastName: lastName || merged?.user?.lastName,
@@ -3,7 +3,7 @@ import { store } from '../roomStore';
3
3
  import { logout } from '../roomStore/chatSettingsSlice';
4
4
  import { setLogoutState } from '../roomStore/roomsSlice';
5
5
  import { asyncLocalStorage } from '../hooks/useLocalStorage';
6
- import { localStorageConstants } from './constants/LOCAL_STORAGE';
6
+ import { secureUserStorage } from './secureUserStorage';
7
7
  import { clearRoomsRestCache } from '../networking/api-requests/rooms.api';
8
8
  import { clearPersistedState } from '../roomStore/persistence';
9
9
  import {
@@ -53,7 +53,7 @@ export async function ensureScopedChatCache(config?: IConfig): Promise<void> {
53
53
  clearRoomsRestCache();
54
54
  store.dispatch(setLogoutState());
55
55
  store.dispatch(logout());
56
- await asyncLocalStorage(localStorageConstants.ETHORA_USER).remove();
56
+ await secureUserStorage().remove();
57
57
  await clearPersistedState();
58
58
  }
59
59
 
@@ -0,0 +1,18 @@
1
+ /** @format */
2
+
3
+ import type { IConfig } from '../types/types';
4
+
5
+ /** Ground behind the conversation, and behind the rounded corners of the
6
+ * header and the composer that sit over it. */
7
+ export const DEFAULT_CHAT_BACKGROUND = '#F3F6FC';
8
+
9
+ /**
10
+ * One place for the conversation's background colour.
11
+ *
12
+ * The message list has always painted it; the chat container behind it was
13
+ * plain white, which is what made the header's rounded bottom corners and
14
+ * the composer's rounded top corners invisible — the corners revealed the
15
+ * white parent, not the conversation.
16
+ */
17
+ export const getChatBackgroundColor = (config?: IConfig): string =>
18
+ config?.backgroundChat?.color || DEFAULT_CHAT_BACKGROUND;
@@ -0,0 +1,87 @@
1
+ import { ensureFilenameHasExtension, filenameFromUrl } from './mimeToExtension';
2
+
3
+ export interface DisplayFileNameOptions {
4
+ originalName?: string | null;
5
+ fileName?: string | null;
6
+ location?: string | null;
7
+ mimetype?: string | null;
8
+ }
9
+
10
+ /**
11
+ * Picks the best human-readable filename for a chat attachment - the
12
+ * single source of truth for every place a file name is rendered in the
13
+ * UI, saved to disk, shared, or downloaded.
14
+ *
15
+ * Priority: `originalName` (the sender's own file name, e.g. "test1.pdf")
16
+ * beats `fileName` (the server's stored/hashed name, e.g.
17
+ * "3f9a1c...c2.pdf") beats the last path segment of `location`. The
18
+ * stored hash name is only a fallback of last resort.
19
+ *
20
+ * Bug #40: display and save/share/download logic used to prefer the
21
+ * stored hash name over the original one, so an attachment sent as
22
+ * "test1.pdf" showed up (and got saved to the phone) as something like
23
+ * "3f9a1c...c2.pdf" - both directions (web -> RN and RN -> RN).
24
+ *
25
+ * Always returns a non-empty string with a valid extension: if the
26
+ * chosen candidate has no extension (a hash name can be `<hex>` with no
27
+ * extension at all, or `<hex>.<ext>`), one is appended from `mimetype`
28
+ * (or `.bin` as a last resort when the mime is unknown/missing too).
29
+ */
30
+ export function getDisplayFileName(options: DisplayFileNameOptions): string {
31
+ const candidate =
32
+ (options.originalName && options.originalName.trim()) ||
33
+ (options.fileName && options.fileName.trim()) ||
34
+ filenameFromUrl(options.location) ||
35
+ '';
36
+ return ensureFilenameHasExtension(candidate, options.mimetype);
37
+ }
38
+
39
+ /**
40
+ * Makes a display name safe to use as an actual path segment when
41
+ * saving/sharing a file to the device: strips path separators (so an
42
+ * odd/hostile server-provided name can't escape the target directory)
43
+ * and control characters. Keeps the rest of the name - including the
44
+ * extension - intact.
45
+ */
46
+ export function sanitizeFileNameForPath(name: string): string {
47
+ const cleaned = (name || '')
48
+ .replace(/[\/\\]/g, '_')
49
+ // eslint-disable-next-line no-control-regex
50
+ .replace(/[\x00-\x1f\x7f]/g, '')
51
+ .trim();
52
+ return cleaned || 'file';
53
+ }
54
+
55
+ /**
56
+ * Resolves a filename that is safe to write into a target directory:
57
+ * sanitizes it, then - if `exists` reports a collision - inserts
58
+ * " (1)", " (2)", ... before the extension until a free name is found,
59
+ * so saving two different attachments that share a display name never
60
+ * silently overwrites the first one.
61
+ *
62
+ * `exists` is injected so callers can back it with whatever existence
63
+ * check makes sense for their storage API (expo-file-system,
64
+ * StorageAccessFramework directory listing, ...) - this function stays
65
+ * pure and easy to unit test.
66
+ */
67
+ export async function getUniqueFileName(
68
+ name: string,
69
+ exists: (candidateName: string) => Promise<boolean>
70
+ ): Promise<string> {
71
+ const safeName = sanitizeFileNameForPath(name);
72
+ if (!(await exists(safeName))) {
73
+ return safeName;
74
+ }
75
+ const dotIndex = safeName.lastIndexOf('.');
76
+ const base = dotIndex > 0 ? safeName.slice(0, dotIndex) : safeName;
77
+ const ext = dotIndex > 0 ? safeName.slice(dotIndex) : '';
78
+ // 999 collisions is already a pathological case; fall back to a
79
+ // timestamp suffix rather than looping forever.
80
+ for (let i = 1; i < 1000; i += 1) {
81
+ const candidate = `${base} (${i})${ext}`;
82
+ if (!(await exists(candidate))) {
83
+ return candidate;
84
+ }
85
+ }
86
+ return `${base} (${Date.now()})${ext}`;
87
+ }