@ethora/chat-component-rn 26.8.6 → 26.8.8

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 (537) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +64 -2
  3. package/lib/commonjs/assets/icons.js +4 -2
  4. package/lib/commonjs/assets/icons.js.map +1 -1
  5. package/lib/commonjs/components/MainComponents/ChatHeader.js +28 -6
  6. package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
  7. package/lib/commonjs/components/MainComponents/ChatRoom.js +9 -1
  8. package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
  9. package/lib/commonjs/components/MainComponents/ChatWrapper.js +5 -3
  10. package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
  11. package/lib/commonjs/components/MainComponents/EncryptedSendNotice.js +47 -0
  12. package/lib/commonjs/components/MainComponents/EncryptedSendNotice.js.map +1 -0
  13. package/lib/commonjs/components/MainComponents/EncryptionCard.js +286 -0
  14. package/lib/commonjs/components/MainComponents/EncryptionCard.js.map +1 -0
  15. package/lib/commonjs/components/MainComponents/MediaMessage.js +7 -0
  16. package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
  17. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +13 -0
  18. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  19. package/lib/commonjs/components/MainComponents/SealedAttachment.js +231 -0
  20. package/lib/commonjs/components/MainComponents/SealedAttachment.js.map +1 -0
  21. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +26 -13
  22. package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
  23. package/lib/commonjs/components/MenuRoom/MenuRoom.js +5 -3
  24. package/lib/commonjs/components/MenuRoom/MenuRoom.js.map +1 -1
  25. package/lib/commonjs/components/MessageBubble/BottomReplyContainer.js +2 -1
  26. package/lib/commonjs/components/MessageBubble/BottomReplyContainer.js.map +1 -1
  27. package/lib/commonjs/components/MessageBubble/Message.js +69 -9
  28. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  29. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +7 -4
  30. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  31. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +8 -5
  32. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  33. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +2 -2
  34. package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  35. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +166 -21
  36. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  37. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +4 -0
  38. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  39. package/lib/commonjs/components/Modals/Modal/Modal.js +33 -11
  40. package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
  41. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +8 -8
  42. package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  43. package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +279 -0
  44. package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
  45. package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
  46. package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
  47. package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
  48. package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
  49. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +50 -15
  50. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  51. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js +121 -0
  52. package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
  53. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +10 -1
  54. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  55. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +32 -9
  56. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  57. package/lib/commonjs/components/RoomComponents/LastMessageItem.js +6 -0
  58. package/lib/commonjs/components/RoomComponents/LastMessageItem.js.map +1 -1
  59. package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js +2 -2
  60. package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
  61. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +4 -6
  62. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  63. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +2 -2
  64. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  65. package/lib/commonjs/components/RoomComponents/styled/LastMessageSealed.js +41 -0
  66. package/lib/commonjs/components/RoomComponents/styled/LastMessageSealed.js.map +1 -0
  67. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +2 -2
  68. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  69. package/lib/commonjs/components/Thread/ThreadWrapper.js +56 -46
  70. package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
  71. package/lib/commonjs/components/UsersList/UsersList.js +2 -1
  72. package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
  73. package/lib/commonjs/components/styled/SendInput.js +4 -2
  74. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  75. package/lib/commonjs/e2ee/crypto.js +207 -0
  76. package/lib/commonjs/e2ee/crypto.js.map +1 -0
  77. package/lib/commonjs/e2ee/deviceStore.js +84 -0
  78. package/lib/commonjs/e2ee/deviceStore.js.map +1 -0
  79. package/lib/commonjs/e2ee/fileCipher.js +95 -0
  80. package/lib/commonjs/e2ee/fileCipher.js.map +1 -0
  81. package/lib/commonjs/e2ee/fileEnvelope.js +79 -0
  82. package/lib/commonjs/e2ee/fileEnvelope.js.map +1 -0
  83. package/lib/commonjs/e2ee/index.js +210 -0
  84. package/lib/commonjs/e2ee/index.js.map +1 -0
  85. package/lib/commonjs/e2ee/limits.js +9 -0
  86. package/lib/commonjs/e2ee/limits.js.map +1 -0
  87. package/lib/commonjs/e2ee/ns.js +8 -0
  88. package/lib/commonjs/e2ee/ns.js.map +1 -0
  89. package/lib/commonjs/e2ee/omemo.js +622 -0
  90. package/lib/commonjs/e2ee/omemo.js.map +1 -0
  91. package/lib/commonjs/e2ee/protobuf.js +149 -0
  92. package/lib/commonjs/e2ee/protobuf.js.map +1 -0
  93. package/lib/commonjs/e2ee/ratchet.js +238 -0
  94. package/lib/commonjs/e2ee/ratchet.js.map +1 -0
  95. package/lib/commonjs/e2ee/sealedBody.js +23 -0
  96. package/lib/commonjs/e2ee/sealedBody.js.map +1 -0
  97. package/lib/commonjs/e2ee/sealedFiles.js +174 -0
  98. package/lib/commonjs/e2ee/sealedFiles.js.map +1 -0
  99. package/lib/commonjs/e2ee/send.js +54 -0
  100. package/lib/commonjs/e2ee/send.js.map +1 -0
  101. package/lib/commonjs/e2ee/stanza.js +114 -0
  102. package/lib/commonjs/e2ee/stanza.js.map +1 -0
  103. package/lib/commonjs/e2ee/store.js +43 -0
  104. package/lib/commonjs/e2ee/store.js.map +1 -0
  105. package/lib/commonjs/helpers/accountName.js +23 -0
  106. package/lib/commonjs/helpers/accountName.js.map +1 -0
  107. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js +2 -0
  108. package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  109. package/lib/commonjs/helpers/constants/MODAL_TYPES.js +1 -0
  110. package/lib/commonjs/helpers/constants/MODAL_TYPES.js.map +1 -1
  111. package/lib/commonjs/helpers/createMessageFromXml.js +19 -4
  112. package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
  113. package/lib/commonjs/helpers/createUserNameFromSetUser.js +2 -1
  114. package/lib/commonjs/helpers/createUserNameFromSetUser.js.map +1 -1
  115. package/lib/commonjs/helpers/displayName.js +16 -0
  116. package/lib/commonjs/helpers/displayName.js.map +1 -0
  117. package/lib/commonjs/helpers/persistCrypto.js +5 -0
  118. package/lib/commonjs/helpers/persistCrypto.js.map +1 -1
  119. package/lib/commonjs/helpers/preferencesStorage.js.map +1 -1
  120. package/lib/commonjs/helpers/secureKeyValue.js +20 -0
  121. package/lib/commonjs/helpers/secureKeyValue.js.map +1 -1
  122. package/lib/commonjs/helpers/videoCache.js +136 -0
  123. package/lib/commonjs/helpers/videoCache.js.map +1 -0
  124. package/lib/commonjs/hooks/useChatSettingState.js +2 -0
  125. package/lib/commonjs/hooks/useChatSettingState.js.map +1 -1
  126. package/lib/commonjs/hooks/useChatWrapperInit.js +4 -0
  127. package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
  128. package/lib/commonjs/hooks/useLogout.js +8 -0
  129. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  130. package/lib/commonjs/hooks/useSendMessage.js +71 -7
  131. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  132. package/lib/commonjs/i18n/strings.js +367 -1
  133. package/lib/commonjs/i18n/strings.js.map +1 -1
  134. package/lib/commonjs/i18n/useT.js +8 -4
  135. package/lib/commonjs/i18n/useT.js.map +1 -1
  136. package/lib/commonjs/main.js +13 -0
  137. package/lib/commonjs/main.js.map +1 -1
  138. package/lib/commonjs/networking/api-requests/auth.api.js +4 -1
  139. package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
  140. package/lib/commonjs/networking/api-requests/rooms.api.js +111 -17
  141. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  142. package/lib/commonjs/networking/api-requests/user.api.js +13 -0
  143. package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
  144. package/lib/commonjs/networking/stanzaHandlers.js +1 -1
  145. package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
  146. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +40 -0
  147. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  148. package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js +16 -3
  149. package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
  150. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +13 -6
  151. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  152. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +14 -6
  153. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  154. package/lib/commonjs/networking/xmppClient.js +6 -0
  155. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  156. package/lib/commonjs/roomStore/chatSettingsSlice.js +7 -2
  157. package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
  158. package/lib/commonjs/roomStore/persistBackend.js +9 -12
  159. package/lib/commonjs/roomStore/persistBackend.js.map +1 -1
  160. package/lib/commonjs/roomStore/persistence.js +8 -1
  161. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  162. package/lib/commonjs/services/languageSettings.js +177 -0
  163. package/lib/commonjs/services/languageSettings.js.map +1 -0
  164. package/lib/commonjs/version.js +1 -1
  165. package/lib/module/assets/icons.js +3 -1
  166. package/lib/module/assets/icons.js.map +1 -1
  167. package/lib/module/components/MainComponents/ChatHeader.js +29 -7
  168. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  169. package/lib/module/components/MainComponents/ChatRoom.js +9 -1
  170. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  171. package/lib/module/components/MainComponents/ChatWrapper.js +5 -3
  172. package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
  173. package/lib/module/components/MainComponents/EncryptedSendNotice.js +42 -0
  174. package/lib/module/components/MainComponents/EncryptedSendNotice.js.map +1 -0
  175. package/lib/module/components/MainComponents/EncryptionCard.js +281 -0
  176. package/lib/module/components/MainComponents/EncryptionCard.js.map +1 -0
  177. package/lib/module/components/MainComponents/MediaMessage.js +7 -0
  178. package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
  179. package/lib/module/components/MainComponents/ReduxWrapper.js +14 -1
  180. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  181. package/lib/module/components/MainComponents/SealedAttachment.js +224 -0
  182. package/lib/module/components/MainComponents/SealedAttachment.js.map +1 -0
  183. package/lib/module/components/Menu/HeaderRoomListMenu.js +26 -13
  184. package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
  185. package/lib/module/components/MenuRoom/MenuRoom.js +5 -3
  186. package/lib/module/components/MenuRoom/MenuRoom.js.map +1 -1
  187. package/lib/module/components/MessageBubble/BottomReplyContainer.js +2 -1
  188. package/lib/module/components/MessageBubble/BottomReplyContainer.js.map +1 -1
  189. package/lib/module/components/MessageBubble/Message.js +72 -12
  190. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  191. package/lib/module/components/MessageBubble/MessageInteractions.js +7 -4
  192. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  193. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +8 -5
  194. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  195. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +2 -2
  196. package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
  197. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +168 -23
  198. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  199. package/lib/module/components/Modals/FilePreviewModal/PdfView.js +4 -0
  200. package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  201. package/lib/module/components/Modals/Modal/Modal.js +33 -11
  202. package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
  203. package/lib/module/components/Modals/NewChatModal/NewChatModal.js +8 -8
  204. package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
  205. package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +274 -0
  206. package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
  207. package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
  208. package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
  209. package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
  210. package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
  211. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +54 -18
  212. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  213. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js +116 -0
  214. package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
  215. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +10 -1
  216. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  217. package/lib/module/components/RoomComponents/ChatRoomItem.js +32 -9
  218. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  219. package/lib/module/components/RoomComponents/LastMessageItem.js +6 -0
  220. package/lib/module/components/RoomComponents/LastMessageItem.js.map +1 -1
  221. package/lib/module/components/RoomComponents/styled/LastAudioMessage.js +2 -2
  222. package/lib/module/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
  223. package/lib/module/components/RoomComponents/styled/LastMessageFile.js +4 -6
  224. package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  225. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +2 -2
  226. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  227. package/lib/module/components/RoomComponents/styled/LastMessageSealed.js +36 -0
  228. package/lib/module/components/RoomComponents/styled/LastMessageSealed.js.map +1 -0
  229. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +2 -2
  230. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  231. package/lib/module/components/Thread/ThreadWrapper.js +57 -47
  232. package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
  233. package/lib/module/components/UsersList/UsersList.js +2 -1
  234. package/lib/module/components/UsersList/UsersList.js.map +1 -1
  235. package/lib/module/components/styled/SendInput.js +4 -2
  236. package/lib/module/components/styled/SendInput.js.map +1 -1
  237. package/lib/module/e2ee/crypto.js +170 -0
  238. package/lib/module/e2ee/crypto.js.map +1 -0
  239. package/lib/module/e2ee/deviceStore.js +77 -0
  240. package/lib/module/e2ee/deviceStore.js.map +1 -0
  241. package/lib/module/e2ee/fileCipher.js +90 -0
  242. package/lib/module/e2ee/fileCipher.js.map +1 -0
  243. package/lib/module/e2ee/fileEnvelope.js +66 -0
  244. package/lib/module/e2ee/fileEnvelope.js.map +1 -0
  245. package/lib/module/e2ee/index.js +185 -0
  246. package/lib/module/e2ee/index.js.map +1 -0
  247. package/lib/module/e2ee/limits.js +5 -0
  248. package/lib/module/e2ee/limits.js.map +1 -0
  249. package/lib/module/e2ee/ns.js +4 -0
  250. package/lib/module/e2ee/ns.js.map +1 -0
  251. package/lib/module/e2ee/omemo.js +610 -0
  252. package/lib/module/e2ee/omemo.js.map +1 -0
  253. package/lib/module/e2ee/protobuf.js +140 -0
  254. package/lib/module/e2ee/protobuf.js.map +1 -0
  255. package/lib/module/e2ee/ratchet.js +228 -0
  256. package/lib/module/e2ee/ratchet.js.map +1 -0
  257. package/lib/module/e2ee/sealedBody.js +19 -0
  258. package/lib/module/e2ee/sealedBody.js.map +1 -0
  259. package/lib/module/e2ee/sealedFiles.js +154 -0
  260. package/lib/module/e2ee/sealedFiles.js.map +1 -0
  261. package/lib/module/e2ee/send.js +48 -0
  262. package/lib/module/e2ee/send.js.map +1 -0
  263. package/lib/module/e2ee/stanza.js +107 -0
  264. package/lib/module/e2ee/stanza.js.map +1 -0
  265. package/lib/module/e2ee/store.js +35 -0
  266. package/lib/module/e2ee/store.js.map +1 -0
  267. package/lib/module/helpers/accountName.js +18 -0
  268. package/lib/module/helpers/accountName.js.map +1 -0
  269. package/lib/module/helpers/constants/MODAL_COMPONENTS.js +2 -0
  270. package/lib/module/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
  271. package/lib/module/helpers/constants/MODAL_TYPES.js +1 -0
  272. package/lib/module/helpers/constants/MODAL_TYPES.js.map +1 -1
  273. package/lib/module/helpers/createMessageFromXml.js +19 -4
  274. package/lib/module/helpers/createMessageFromXml.js.map +1 -1
  275. package/lib/module/helpers/createUserNameFromSetUser.js +3 -1
  276. package/lib/module/helpers/createUserNameFromSetUser.js.map +1 -1
  277. package/lib/module/helpers/displayName.js +11 -0
  278. package/lib/module/helpers/displayName.js.map +1 -0
  279. package/lib/module/helpers/persistCrypto.js +4 -0
  280. package/lib/module/helpers/persistCrypto.js.map +1 -1
  281. package/lib/module/helpers/preferencesStorage.js.map +1 -1
  282. package/lib/module/helpers/secureKeyValue.js +19 -0
  283. package/lib/module/helpers/secureKeyValue.js.map +1 -1
  284. package/lib/module/helpers/videoCache.js +125 -0
  285. package/lib/module/helpers/videoCache.js.map +1 -0
  286. package/lib/module/hooks/useChatSettingState.js +2 -0
  287. package/lib/module/hooks/useChatSettingState.js.map +1 -1
  288. package/lib/module/hooks/useChatWrapperInit.js +4 -0
  289. package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
  290. package/lib/module/hooks/useLogout.js +8 -0
  291. package/lib/module/hooks/useLogout.js.map +1 -1
  292. package/lib/module/hooks/useSendMessage.js +71 -7
  293. package/lib/module/hooks/useSendMessage.js.map +1 -1
  294. package/lib/module/i18n/strings.js +367 -1
  295. package/lib/module/i18n/strings.js.map +1 -1
  296. package/lib/module/i18n/useT.js +8 -4
  297. package/lib/module/i18n/useT.js.map +1 -1
  298. package/lib/module/main.js +1 -0
  299. package/lib/module/main.js.map +1 -1
  300. package/lib/module/networking/api-requests/auth.api.js +4 -1
  301. package/lib/module/networking/api-requests/auth.api.js.map +1 -1
  302. package/lib/module/networking/api-requests/rooms.api.js +109 -18
  303. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  304. package/lib/module/networking/api-requests/user.api.js +12 -0
  305. package/lib/module/networking/api-requests/user.api.js.map +1 -1
  306. package/lib/module/networking/stanzaHandlers.js +1 -1
  307. package/lib/module/networking/stanzaHandlers.js.map +1 -1
  308. package/lib/module/networking/xmpp/handleStanzas.xmpp.js +38 -0
  309. package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  310. package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js +16 -3
  311. package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
  312. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +13 -6
  313. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  314. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +14 -6
  315. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  316. package/lib/module/networking/xmppClient.js +6 -0
  317. package/lib/module/networking/xmppClient.js.map +1 -1
  318. package/lib/module/roomStore/chatSettingsSlice.js +5 -1
  319. package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
  320. package/lib/module/roomStore/persistBackend.js +10 -13
  321. package/lib/module/roomStore/persistBackend.js.map +1 -1
  322. package/lib/module/roomStore/persistence.js +8 -1
  323. package/lib/module/roomStore/persistence.js.map +1 -1
  324. package/lib/module/services/languageSettings.js +164 -0
  325. package/lib/module/services/languageSettings.js.map +1 -0
  326. package/lib/module/version.js +1 -1
  327. package/lib/typescript/assets/icons.d.ts +8 -0
  328. package/lib/typescript/assets/icons.d.ts.map +1 -1
  329. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  330. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  331. package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
  332. package/lib/typescript/components/MainComponents/EncryptedSendNotice.d.ts +4 -0
  333. package/lib/typescript/components/MainComponents/EncryptedSendNotice.d.ts.map +1 -0
  334. package/lib/typescript/components/MainComponents/EncryptionCard.d.ts +10 -0
  335. package/lib/typescript/components/MainComponents/EncryptionCard.d.ts.map +1 -0
  336. package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
  337. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  338. package/lib/typescript/components/MainComponents/SealedAttachment.d.ts +13 -0
  339. package/lib/typescript/components/MainComponents/SealedAttachment.d.ts.map +1 -0
  340. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts +7 -1
  341. package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
  342. package/lib/typescript/components/MenuRoom/MenuRoom.d.ts.map +1 -1
  343. package/lib/typescript/components/MessageBubble/BottomReplyContainer.d.ts.map +1 -1
  344. package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
  345. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  346. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  347. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  348. package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
  349. package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
  350. package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts +15 -0
  351. package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts.map +1 -0
  352. package/lib/typescript/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.d.ts.map +1 -1
  353. package/lib/typescript/components/Modals/SettingsModals/Visibility/VisibilityModal.d.ts.map +1 -1
  354. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  355. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts +14 -0
  356. package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts.map +1 -0
  357. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  358. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  359. package/lib/typescript/components/RoomComponents/LastMessageItem.d.ts.map +1 -1
  360. package/lib/typescript/components/RoomComponents/styled/LastAudioMessage.d.ts.map +1 -1
  361. package/lib/typescript/components/RoomComponents/styled/LastMessageSealed.d.ts +7 -0
  362. package/lib/typescript/components/RoomComponents/styled/LastMessageSealed.d.ts.map +1 -0
  363. package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
  364. package/lib/typescript/components/UsersList/UsersList.d.ts.map +1 -1
  365. package/lib/typescript/components/styled/SendInput.d.ts +1 -0
  366. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  367. package/lib/typescript/e2ee/crypto.d.ts +28 -0
  368. package/lib/typescript/e2ee/crypto.d.ts.map +1 -0
  369. package/lib/typescript/e2ee/deviceStore.d.ts +4 -0
  370. package/lib/typescript/e2ee/deviceStore.d.ts.map +1 -0
  371. package/lib/typescript/e2ee/fileCipher.d.ts +7 -0
  372. package/lib/typescript/e2ee/fileCipher.d.ts.map +1 -0
  373. package/lib/typescript/e2ee/fileEnvelope.d.ts +27 -0
  374. package/lib/typescript/e2ee/fileEnvelope.d.ts.map +1 -0
  375. package/lib/typescript/e2ee/index.d.ts +23 -0
  376. package/lib/typescript/e2ee/index.d.ts.map +1 -0
  377. package/lib/typescript/e2ee/limits.d.ts +3 -0
  378. package/lib/typescript/e2ee/limits.d.ts.map +1 -0
  379. package/lib/typescript/e2ee/ns.d.ts +2 -0
  380. package/lib/typescript/e2ee/ns.d.ts.map +1 -0
  381. package/lib/typescript/e2ee/omemo.d.ts +64 -0
  382. package/lib/typescript/e2ee/omemo.d.ts.map +1 -0
  383. package/lib/typescript/e2ee/protobuf.d.ts +25 -0
  384. package/lib/typescript/e2ee/protobuf.d.ts.map +1 -0
  385. package/lib/typescript/e2ee/ratchet.d.ts +39 -0
  386. package/lib/typescript/e2ee/ratchet.d.ts.map +1 -0
  387. package/lib/typescript/e2ee/sealedBody.d.ts +2 -0
  388. package/lib/typescript/e2ee/sealedBody.d.ts.map +1 -0
  389. package/lib/typescript/e2ee/sealedFiles.d.ts +31 -0
  390. package/lib/typescript/e2ee/sealedFiles.d.ts.map +1 -0
  391. package/lib/typescript/e2ee/send.d.ts +6 -0
  392. package/lib/typescript/e2ee/send.d.ts.map +1 -0
  393. package/lib/typescript/e2ee/stanza.d.ts +8 -0
  394. package/lib/typescript/e2ee/stanza.d.ts.map +1 -0
  395. package/lib/typescript/e2ee/store.d.ts +16 -0
  396. package/lib/typescript/e2ee/store.d.ts.map +1 -0
  397. package/lib/typescript/helpers/accountName.d.ts +7 -0
  398. package/lib/typescript/helpers/accountName.d.ts.map +1 -0
  399. package/lib/typescript/helpers/constants/MODAL_COMPONENTS.d.ts.map +1 -1
  400. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts +1 -0
  401. package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts.map +1 -1
  402. package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
  403. package/lib/typescript/helpers/createUserNameFromSetUser.d.ts.map +1 -1
  404. package/lib/typescript/helpers/displayName.d.ts +2 -0
  405. package/lib/typescript/helpers/displayName.d.ts.map +1 -0
  406. package/lib/typescript/helpers/persistCrypto.d.ts +1 -0
  407. package/lib/typescript/helpers/persistCrypto.d.ts.map +1 -1
  408. package/lib/typescript/helpers/preferencesStorage.d.ts +4 -0
  409. package/lib/typescript/helpers/preferencesStorage.d.ts.map +1 -1
  410. package/lib/typescript/helpers/secureKeyValue.d.ts +4 -0
  411. package/lib/typescript/helpers/secureKeyValue.d.ts.map +1 -1
  412. package/lib/typescript/helpers/videoCache.d.ts +19 -0
  413. package/lib/typescript/helpers/videoCache.d.ts.map +1 -0
  414. package/lib/typescript/hooks/useChatSettingState.d.ts +1 -0
  415. package/lib/typescript/hooks/useChatSettingState.d.ts.map +1 -1
  416. package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
  417. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  418. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  419. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  420. package/lib/typescript/i18n/useT.d.ts.map +1 -1
  421. package/lib/typescript/main.d.ts +2 -0
  422. package/lib/typescript/main.d.ts.map +1 -1
  423. package/lib/typescript/networking/api-requests/auth.api.d.ts +4 -1
  424. package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
  425. package/lib/typescript/networking/api-requests/rooms.api.d.ts +22 -1
  426. package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
  427. package/lib/typescript/networking/api-requests/user.api.d.ts +6 -0
  428. package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
  429. package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
  430. package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts +1 -0
  431. package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
  432. package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts.map +1 -1
  433. package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
  434. package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
  435. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  436. package/lib/typescript/roomStore/chatSettingsSlice.d.ts +8 -1
  437. package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
  438. package/lib/typescript/roomStore/persistBackend.d.ts.map +1 -1
  439. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  440. package/lib/typescript/services/languageSettings.d.ts +29 -0
  441. package/lib/typescript/services/languageSettings.d.ts.map +1 -0
  442. package/lib/typescript/types/models/message.model.d.ts +5 -0
  443. package/lib/typescript/types/models/message.model.d.ts.map +1 -1
  444. package/lib/typescript/types/models/room.model.d.ts +5 -0
  445. package/lib/typescript/types/models/room.model.d.ts.map +1 -1
  446. package/lib/typescript/types/models/user.model.d.ts +4 -0
  447. package/lib/typescript/types/models/user.model.d.ts.map +1 -1
  448. package/lib/typescript/types/types.d.ts +25 -0
  449. package/lib/typescript/types/types.d.ts.map +1 -1
  450. package/lib/typescript/version.d.ts +1 -1
  451. package/package.json +8 -4
  452. package/src/assets/icons.tsx +27 -0
  453. package/src/components/MainComponents/ChatHeader.tsx +30 -9
  454. package/src/components/MainComponents/ChatRoom.tsx +11 -1
  455. package/src/components/MainComponents/ChatWrapper.tsx +5 -3
  456. package/src/components/MainComponents/EncryptedSendNotice.tsx +35 -0
  457. package/src/components/MainComponents/EncryptionCard.tsx +287 -0
  458. package/src/components/MainComponents/MediaMessage.tsx +5 -0
  459. package/src/components/MainComponents/ReduxWrapper.tsx +11 -0
  460. package/src/components/MainComponents/SealedAttachment.tsx +251 -0
  461. package/src/components/Menu/HeaderRoomListMenu.tsx +40 -13
  462. package/src/components/MenuRoom/MenuRoom.tsx +5 -3
  463. package/src/components/MessageBubble/BottomReplyContainer.tsx +2 -1
  464. package/src/components/MessageBubble/Message.tsx +99 -9
  465. package/src/components/MessageBubble/MessageInteractions.tsx +7 -6
  466. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +8 -5
  467. package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +2 -2
  468. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +188 -40
  469. package/src/components/Modals/FilePreviewModal/PdfView.tsx +4 -0
  470. package/src/components/Modals/Modal/Modal.tsx +44 -16
  471. package/src/components/Modals/NewChatModal/NewChatModal.tsx +8 -8
  472. package/src/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.tsx +316 -0
  473. package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +10 -15
  474. package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +13 -14
  475. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +72 -20
  476. package/src/components/Modals/UserSettingsModal/LanguageCard.tsx +144 -0
  477. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +13 -1
  478. package/src/components/RoomComponents/ChatRoomItem.tsx +23 -11
  479. package/src/components/RoomComponents/LastMessageItem.tsx +5 -0
  480. package/src/components/RoomComponents/styled/LastAudioMessage.tsx +3 -1
  481. package/src/components/RoomComponents/styled/LastMessageFile.tsx +2 -2
  482. package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +1 -1
  483. package/src/components/RoomComponents/styled/LastMessageSealed.tsx +31 -0
  484. package/src/components/RoomComponents/styled/LastMessageVideo.tsx +1 -1
  485. package/src/components/Thread/ThreadWrapper.tsx +17 -2
  486. package/src/components/UsersList/UsersList.tsx +2 -1
  487. package/src/components/styled/SendInput.tsx +5 -2
  488. package/src/e2ee/crypto.ts +194 -0
  489. package/src/e2ee/deviceStore.ts +80 -0
  490. package/src/e2ee/fileCipher.ts +86 -0
  491. package/src/e2ee/fileEnvelope.ts +115 -0
  492. package/src/e2ee/index.ts +192 -0
  493. package/src/e2ee/limits.ts +2 -0
  494. package/src/e2ee/ns.ts +1 -0
  495. package/src/e2ee/omemo.ts +802 -0
  496. package/src/e2ee/protobuf.ts +188 -0
  497. package/src/e2ee/ratchet.ts +271 -0
  498. package/src/e2ee/sealedBody.ts +17 -0
  499. package/src/e2ee/sealedFiles.ts +181 -0
  500. package/src/e2ee/send.ts +70 -0
  501. package/src/e2ee/stanza.ts +133 -0
  502. package/src/e2ee/store.ts +54 -0
  503. package/src/helpers/accountName.ts +15 -0
  504. package/src/helpers/constants/MODAL_COMPONENTS.tsx +2 -0
  505. package/src/helpers/constants/MODAL_TYPES.ts +1 -0
  506. package/src/helpers/createMessageFromXml.ts +31 -6
  507. package/src/helpers/createUserNameFromSetUser.ts +2 -1
  508. package/src/helpers/displayName.ts +9 -0
  509. package/src/helpers/persistCrypto.ts +5 -0
  510. package/src/helpers/preferencesStorage.ts +4 -0
  511. package/src/helpers/secureKeyValue.ts +15 -0
  512. package/src/helpers/videoCache.ts +138 -0
  513. package/src/hooks/useChatSettingState.tsx +4 -0
  514. package/src/hooks/useChatWrapperInit.ts +4 -0
  515. package/src/hooks/useLogout.tsx +9 -0
  516. package/src/hooks/useSendMessage.tsx +71 -5
  517. package/src/i18n/strings.ts +367 -1
  518. package/src/i18n/useT.ts +6 -4
  519. package/src/main.ts +2 -0
  520. package/src/networking/api-requests/auth.api.ts +9 -1
  521. package/src/networking/api-requests/rooms.api.ts +121 -18
  522. package/src/networking/api-requests/user.api.ts +9 -0
  523. package/src/networking/stanzaHandlers.ts +1 -0
  524. package/src/networking/xmpp/handleStanzas.xmpp.ts +49 -0
  525. package/src/networking/xmpp/sendMediaMessage.xmpp.ts +19 -1
  526. package/src/networking/xmpp/sendTextMessage.xmpp.ts +17 -10
  527. package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +23 -10
  528. package/src/networking/xmppClient.ts +6 -0
  529. package/src/roomStore/chatSettingsSlice.ts +13 -0
  530. package/src/roomStore/persistBackend.ts +8 -11
  531. package/src/roomStore/persistence.ts +15 -0
  532. package/src/services/languageSettings.ts +143 -0
  533. package/src/types/models/message.model.ts +5 -0
  534. package/src/types/models/room.model.ts +5 -0
  535. package/src/types/models/user.model.ts +4 -0
  536. package/src/types/types.ts +25 -0
  537. package/src/version.ts +1 -1
@@ -266,10 +266,18 @@ const canFallBackToLegacyUpload = (error: unknown): boolean => {
266
266
 
267
267
  let secureUploadUnavailable = false;
268
268
 
269
+ export interface UploadFileOptions {
270
+ clientEncrypted?: boolean;
271
+ }
272
+
269
273
  export async function uploadFileV2(
270
274
  formData: FormData,
271
- activeRoomJID: string
275
+ activeRoomJID: string,
276
+ options: UploadFileOptions = {}
272
277
  ): Promise<{ data: any }> {
278
+ if (options.clientEncrypted) {
279
+ formData.append('clientEncrypted', 'true');
280
+ }
273
281
  const chatName = (activeRoomJID || '').split('@')[0];
274
282
  const apiRoot = getCurrentBaseURL().replace(/\/$/, '');
275
283
 
@@ -1,6 +1,6 @@
1
1
  import { ApiRoom, DeleteRoomMember, PostAddRoomMember, PostReportRoom, PostRoom, RoomMember } from '../../types/models/room.model';
2
2
  import { store } from '../../roomStore';
3
- import { addRoom, mergeUsersSet } from '../../roomStore/roomsSlice';
3
+ import { addRoom, mergeUsersSet, updateRoom } from '../../roomStore/roomsSlice';
4
4
  import { IRoom } from '../../types/types';
5
5
  import http from '../apiClient';
6
6
 
@@ -19,6 +19,11 @@ import http from '../apiClient';
19
19
  * - `_id` (fallback)
20
20
  * - `xmppUsername` (raw + localpart) when the API does return one
21
21
  */
22
+ const usableImage = (value: unknown): string => {
23
+ const url = typeof value === 'string' ? value.trim() : '';
24
+ return url && url !== 'none' ? url : '';
25
+ };
26
+
22
27
  function dispatchUsersSetFromRestItems(items: ApiRoom[]): void {
23
28
  if (!items?.length) {return;}
24
29
  const ownXmpp = String(
@@ -26,16 +31,24 @@ function dispatchUsersSetFromRestItems(items: ApiRoom[]): void {
26
31
  );
27
32
  const appId = ownXmpp.includes('_') ? ownXmpp.split('_')[0] : '';
28
33
 
34
+ const known = (store.getState().rooms?.usersSet || {}) as Record<string, RoomMember>;
29
35
  const members: Record<string, RoomMember> = {};
30
36
  for (const item of items) {
31
37
  const list = Array.isArray((item as any)?.members) ? (item as any).members : [];
32
38
  for (const m of list) {
33
39
  if (!m) {continue;}
40
+ const before: RoomMember | undefined =
41
+ (m._id && (members[m._id] || known[m._id])) || undefined;
34
42
  const entry: RoomMember = {
35
- firstName: m.firstName || '',
36
- lastName: m.lastName || '',
43
+ firstName: m.firstName ?? before?.firstName ?? '',
44
+ lastName: m.lastName ?? before?.lastName ?? '',
37
45
  xmppUsername: m.xmppUsername || (appId && m._id ? `${appId}_${m._id}` : m._id || ''),
38
46
  _id: m._id || '',
47
+ profileImage:
48
+ m.profileImage !== undefined
49
+ ? usableImage(m.profileImage)
50
+ : before?.profileImage ?? '',
51
+ description: m.description ?? before?.description,
39
52
  role: m.role,
40
53
  ban_status: m.ban_status,
41
54
  last_active: m.last_active,
@@ -85,9 +98,53 @@ interface ApiRoomMember {
85
98
  * manifested as a phantom "ethora" room stub on third-party servers,
86
99
  * customer-reported #23)
87
100
  */
101
+ export function memberAccount(member: any, appId: string): string {
102
+ const explicit = String(member?.xmppUsername || '').split('@')[0];
103
+ if (explicit) {return explicit;}
104
+ return appId && member?._id ? `${appId}_${member._id}` : '';
105
+ }
106
+
107
+ export function ownAppId(): string {
108
+ const ownXmpp = String(
109
+ store.getState().chatSettingStore?.user?.xmppUsername || ''
110
+ );
111
+ return ownXmpp.includes('_') ? ownXmpp.split('_')[0]! : '';
112
+ }
113
+
114
+ const toRoomMembers = (members: any[] | undefined): RoomMember[] => {
115
+ const known = (store.getState().rooms?.usersSet || {}) as Record<string, RoomMember>;
116
+ return (members || []).map((m: any) => ({
117
+ firstName: m.firstName,
118
+ lastName: m.lastName,
119
+ profileImage:
120
+ m.profileImage !== undefined
121
+ ? usableImage(m.profileImage)
122
+ : known[m._id]?.profileImage ?? '',
123
+ xmppUsername: m._id || '',
124
+ role: m.role,
125
+ ban_status: m.ban_status,
126
+ last_active: m.last_active,
127
+ jid: m.jid || '',
128
+ })) as any;
129
+ };
130
+
131
+ const toE2eeMembers = (members: any[] | undefined, appId: string): RoomMember[] =>
132
+ (members || [])
133
+ .map((m: any) => ({
134
+ _id: m._id || '',
135
+ firstName: m.firstName || '',
136
+ lastName: m.lastName || '',
137
+ xmppUsername: memberAccount(m, appId),
138
+ }))
139
+ .filter((m) => m.xmppUsername) as RoomMember[];
140
+
141
+ const memberCount = (item: ApiRoom): number =>
142
+ item.usersCnt ?? item.participants ?? item.members?.length ?? 0;
143
+
88
144
  function dispatchRoomsFromRestItems(items: ApiRoom[]): void {
89
145
  if (!items?.length) return;
90
146
  const config = store.getState().chatSettingStore?.config as any;
147
+ const appId = ownAppId();
91
148
  // Best: explicit xmpp settings.
92
149
  let host: string | undefined =
93
150
  config?.xmppSettings?.host ||
@@ -118,12 +175,16 @@ function dispatchRoomsFromRestItems(items: ApiRoom[]): void {
118
175
  jid = `${item.name}@${conference}`;
119
176
  }
120
177
  if (!jid.includes('@')) continue;
178
+ const known = store.getState().rooms.rooms?.[jid];
179
+ const preview = (item.members?.length ?? 0) < memberCount(item);
180
+ const keep = <T,>(fresh: T[], existing: T[] | undefined): T[] =>
181
+ preview && (existing?.length ?? 0) > fresh.length ? existing! : fresh;
121
182
  const room: IRoom = {
122
183
  id: item._id || jid,
123
184
  jid,
124
185
  name: item.name,
125
186
  title: item.title || item.name,
126
- usersCnt: item.participants ?? item.members?.length ?? 0,
187
+ usersCnt: memberCount(item),
127
188
  messages: [],
128
189
  isLoading: false,
129
190
  roomBg: '',
@@ -133,18 +194,14 @@ function dispatchRoomsFromRestItems(items: ApiRoom[]): void {
133
194
  muted: item.muted === true,
134
195
  description: (item as any).description,
135
196
  type: (item as any).type,
136
- // ChatProfileModal renders this list under the description/type
137
- // fields. The REST API returns `members` (an array of {_id,
138
- // firstName?, lastName?}); map to the shape RoomMember expects.
139
- roomMembers: (item.members || []).map((m: any) => ({
140
- firstName: m.firstName,
141
- lastName: m.lastName,
142
- xmppUsername: m._id || '',
143
- role: m.role,
144
- ban_status: m.ban_status,
145
- last_active: m.last_active,
146
- jid: m.jid || '',
147
- })) as any,
197
+
198
+ ...(item.e2ee === true
199
+ ? {
200
+ e2ee: true,
201
+ members: keep(toE2eeMembers(item.members, appId), known?.members),
202
+ }
203
+ : {}),
204
+ roomMembers: keep(toRoomMembers(item.members), known?.roomMembers),
148
205
  };
149
206
  store.dispatch(addRoom({ roomData: room }));
150
207
  }
@@ -152,6 +209,51 @@ function dispatchRoomsFromRestItems(items: ApiRoom[]): void {
152
209
  dispatchUsersSetFromRestItems(items);
153
210
  }
154
211
 
212
+ const ROOM_MEMBERS_TTL_MS = 5 * 60_000;
213
+ const roomMembersLoads = new Map<string, { at: number; done: Promise<boolean> }>();
214
+
215
+ export function loadRoomMembers(roomJid: string): Promise<boolean> {
216
+ const jid = String(roomJid || '').split('/')[0]!;
217
+ const room = store.getState().rooms.rooms?.[jid];
218
+ if (!room) {return Promise.resolve(false);}
219
+ if ((room.roomMembers?.length ?? 0) >= Number(room.usersCnt || 0)) {
220
+ return Promise.resolve(false);
221
+ }
222
+ const running = roomMembersLoads.get(jid);
223
+ if (running && Date.now() - running.at < ROOM_MEMBERS_TTL_MS) {return running.done;}
224
+
225
+ const done = (async () => {
226
+ try {
227
+ const response: any = await getRoomByName(jid.split('@')[0]!);
228
+ const item: ApiRoom = response?.result ?? response;
229
+ const members = Array.isArray(item?.members) ? item.members : [];
230
+ if (members.length === 0) {return false;}
231
+ dispatchUsersSetFromRestItems([item]);
232
+ const current = store.getState().rooms.rooms?.[jid];
233
+ if (!current) {return false;}
234
+ store.dispatch(
235
+ updateRoom({
236
+ jid,
237
+ updates: {
238
+ roomMembers: toRoomMembers(members),
239
+ usersCnt: Math.max(memberCount(item), members.length),
240
+ ...(current.e2ee
241
+ ? { members: toE2eeMembers(members, ownAppId()) }
242
+ : {}),
243
+ },
244
+ })
245
+ );
246
+ return true;
247
+ } catch (error) {
248
+ roomMembersLoads.delete(jid);
249
+ console.warn('[ethora-rn] rooms.api: could not load room members', jid, error);
250
+ return false;
251
+ }
252
+ })();
253
+ roomMembersLoads.set(jid, { at: Date.now(), done });
254
+ return done;
255
+ }
256
+
155
257
  const GET_ROOMS_CACHE_MS = 60_000;
156
258
  let getRoomsInFlight: Promise<{ items: ApiRoom[] }> | null = null;
157
259
  let getRoomsInFlightToken = '';
@@ -235,14 +337,14 @@ export async function postRoom(data: PostRoom) {
235
337
 
236
338
  export async function postPrivateRoom(
237
339
  username: string,
238
- title: string = 'Private chat'
340
+ e2ee: boolean = false
239
341
  ): Promise<ApiRoom> {
240
342
  const token = store.getState().chatSettingStore.user.token || '';
241
343
 
242
344
  try {
243
345
  const response = await http.post(
244
346
  '/v1/chats/private',
245
- { username },
347
+ e2ee === true ? { username, e2ee: true } : { username },
246
348
  {
247
349
  headers: {
248
350
  Authorization: token,
@@ -391,6 +493,7 @@ export async function createChatCall(
391
493
  }
392
494
 
393
495
  export function clearRoomsRestCache() {
496
+ roomMembersLoads.clear();
394
497
  lastGetRoomsResponse = null;
395
498
  lastGetRoomsResponseAt = 0;
396
499
  lastGetRoomsResponseToken = '';
@@ -59,6 +59,15 @@ export function updateMe(data: any) {
59
59
  return http.put('/v1/users', data);
60
60
  }
61
61
 
62
+ /**
63
+ * Change the account password. The backend checks `currentPassword` and
64
+ * answers with a 4xx and a reason when it does not match or the new one is
65
+ * not acceptable; the caller shows that reason.
66
+ */
67
+ export function changePassword(currentPassword: string, newPassword: string) {
68
+ return http.put('/v2/users/me/password', { currentPassword, newPassword });
69
+ }
70
+
62
71
  export async function updateProfile(fd: FormData): Promise<{ user: User }> {
63
72
  const token = store.getState().chatSettingStore.user.token || '';
64
73
 
@@ -132,6 +132,7 @@ const onRealtimeMessage = async (stanza: Element) => {
132
132
  // (stanza handler, not a component), so resolve the locale from the
133
133
  // store directly and call `translateKey` instead of `useT()`.
134
134
  const locale =
135
+ state.chatSettingStore.uiLocale ||
135
136
  state.chatSettingStore.config?.i18n?.locale ||
136
137
  state.chatSettingStore.langSource;
137
138
  const overrides = state.chatSettingStore.config?.i18n?.strings;
@@ -20,6 +20,12 @@ import {
20
20
  } from '../stanzaHandlers';
21
21
  import XmppClient from '../xmppClient';
22
22
  import { onCallTokenMessage } from '../callTokenStanza';
23
+ import { accountDomain, isE2eeEnabled } from '../../e2ee';
24
+ import {
25
+ decryptStanzaInPlace,
26
+ encryptedCarrier,
27
+ rewriteEncryptedStanza,
28
+ } from '../../e2ee/stanza';
23
29
 
24
30
  /**
25
31
  * Unwrap a mucsub event wrapper so the chat handlers see the real inner
@@ -49,7 +55,46 @@ const unwrapMucsubMessage = (stanza: Element): Element => {
49
55
  return (inner as Element) || stanza;
50
56
  };
51
57
 
58
+ let held = 0;
59
+ let queue: Promise<void> = Promise.resolve();
60
+
52
61
  export function handleStanza(stanza: Element, xmppWs: XmppClient) {
62
+ if (!isE2eeEnabled()) {
63
+ dispatchStanza(stanza, xmppWs);
64
+ return;
65
+ }
66
+ const carrier =
67
+ stanza?.name === 'message' ? encryptedCarrier(stanza) : undefined;
68
+ if (!carrier && held === 0) {
69
+ dispatchStanza(stanza, xmppWs);
70
+ return;
71
+ }
72
+
73
+ held++;
74
+ queue = queue.then(async () => {
75
+ try {
76
+ if (carrier) {
77
+ const outcome = await decryptStanzaInPlace(
78
+ stanza,
79
+ accountDomain(xmppWs.client)
80
+ );
81
+ if (outcome === 'drop') {return;}
82
+ }
83
+ dispatchStanza(stanza, xmppWs);
84
+ } catch (err) {
85
+ console.warn('OMEMO: failed to handle stanza', err);
86
+ } finally {
87
+ held--;
88
+ }
89
+ });
90
+ }
91
+
92
+ export const __resetStanzaQueueForTests = (): void => {
93
+ held = 0;
94
+ queue = Promise.resolve();
95
+ };
96
+
97
+ function dispatchStanza(stanza: Element, xmppWs: XmppClient) {
53
98
  if (stanza?.attrs?.type === 'headline') {return;}
54
99
 
55
100
  // Call signaling is swallowed before any chat handler sees it. A
@@ -61,6 +106,10 @@ export function handleStanza(stanza: Element, xmppWs: XmppClient) {
61
106
  return;
62
107
  }
63
108
 
109
+ if (stanza?.name === 'message' && rewriteEncryptedStanza(stanza) === 'drop') {
110
+ return;
111
+ }
112
+
64
113
  switch (stanza.name) {
65
114
  case 'message': {
66
115
  const unwrapped = unwrapMucsubMessage(stanza);
@@ -1,4 +1,5 @@
1
1
  import { Client, xml } from '@xmpp/client';
2
+ import { sendSealedMedia, shouldEncrypt } from '../../e2ee/send';
2
3
 
3
4
  // Monotonic counter — see sendTextMessage for the rationale (avoids
4
5
  // Date.now() id collisions on <1ms-apart sends).
@@ -63,6 +64,23 @@ export function sendMediaMessage(
63
64
  push: 'true',
64
65
  };
65
66
 
67
+ const keys: string[] | undefined = data?.e2eeKeys;
68
+ if (keys?.length) {
69
+ (dataToSend as Record<string, unknown>).clientEncrypted = 'true';
70
+ }
71
+ const hints = xml('store', { xmlns: 'urn:xmpp:hints' });
72
+
73
+ if (keys?.length && shouldEncrypt(roomJID)) {
74
+ sendSealedMedia(
75
+ client,
76
+ roomJID,
77
+ id,
78
+ xml('body', {}, JSON.stringify({ v: 1, keys })),
79
+ [xml('data', dataToSend), hints]
80
+ );
81
+ return id;
82
+ }
83
+
66
84
  const message = xml(
67
85
  'message',
68
86
  {
@@ -72,7 +90,7 @@ export function sendMediaMessage(
72
90
  to: roomJID,
73
91
  },
74
92
  xml('body', {}, 'media'),
75
- xml('store', { xmlns: 'urn:xmpp:hints' }),
93
+ hints,
76
94
  xml('data', dataToSend)
77
95
  );
78
96
 
@@ -1,4 +1,5 @@
1
1
  import { Client, xml } from '@xmpp/client';
2
+ import { sendEncrypted, shouldEncrypt } from '../../e2ee/send';
2
3
 
3
4
  // Local monotonic counter — see comment in id construction below.
4
5
  let _sendTextSeq = 0;
@@ -52,14 +53,7 @@ export const sendTextMessage = (
52
53
 
53
54
  try {
54
55
  const dataXmlns = toServiceXmlns(devServer, client);
55
- const message = xml(
56
- 'message',
57
- {
58
- to: roomJID,
59
- type: 'groupchat',
60
- id: id,
61
- },
62
- xml('data', {
56
+ const data = xml('data', {
63
57
  xmlns: dataXmlns,
64
58
  senderFirstName: firstName,
65
59
  senderLastName: lastName,
@@ -76,9 +70,22 @@ export const sendTextMessage = (
76
70
  isReply: isReply || false,
77
71
  mainMessage: mainMessage || '',
78
72
  push: 'true',
79
- }),
80
- xml('body', {}, userMessage)
73
+ });
74
+ const body = xml('body', {}, userMessage);
75
+ const message = xml(
76
+ 'message',
77
+ {
78
+ to: roomJID,
79
+ type: 'groupchat',
80
+ id: id,
81
+ },
82
+ data,
83
+ body
81
84
  );
85
+ if (shouldEncrypt(roomJID)) {
86
+ sendEncrypted(client, roomJID, id, data, body, message);
87
+ return;
88
+ }
82
89
  const sendResult = client.send(message);
83
90
  if (sendResult && typeof (sendResult as any).then === 'function') {
84
91
  (sendResult as Promise<unknown>)
@@ -1,6 +1,7 @@
1
1
  import { Client, xml } from '@xmpp/client';
2
2
  import { Iso639_1Codes } from '../../types/types';
3
3
  import { toServiceXmlns } from './sendTextMessage.xmpp';
4
+ import { sendEncrypted, shouldEncrypt } from '../../e2ee/send';
4
5
 
5
6
  /**
6
7
  * Same wire message as `sendTextMessage`, plus a `<translate source="xx"/>`
@@ -39,14 +40,7 @@ export const sendTextMessageWithTranslateTag = (
39
40
 
40
41
  try {
41
42
  const dataXmlns = toServiceXmlns(stanzaMessage.devServer, client);
42
- const message = xml(
43
- 'message',
44
- {
45
- to: stanzaMessage.roomJID,
46
- type: 'groupchat',
47
- id,
48
- },
49
- xml('data', {
43
+ const data = xml('data', {
50
44
  xmlns: dataXmlns,
51
45
  senderFirstName: stanzaMessage.firstName,
52
46
  senderLastName: stanzaMessage.lastName,
@@ -63,8 +57,27 @@ export const sendTextMessageWithTranslateTag = (
63
57
  isReply: stanzaMessage.isReply || false,
64
58
  mainMessage: stanzaMessage.mainMessage || '',
65
59
  push: 'true',
66
- }),
67
- xml('body', {}, stanzaMessage.userMessage),
60
+ });
61
+ const body = xml('body', {}, stanzaMessage.userMessage);
62
+ const envelope = { to: stanzaMessage.roomJID, type: 'groupchat', id };
63
+
64
+ if (shouldEncrypt(stanzaMessage.roomJID)) {
65
+ sendEncrypted(
66
+ client,
67
+ stanzaMessage.roomJID,
68
+ id,
69
+ data,
70
+ body,
71
+ xml('message', envelope, data, body)
72
+ );
73
+ return true;
74
+ }
75
+
76
+ const message = xml(
77
+ 'message',
78
+ envelope,
79
+ data,
80
+ body,
68
81
  // `<translate source>` only DECLARES the language this text is in; it
69
82
  // costs nothing to send and is what lets each reader translate the
70
83
  // message into their own language on their side.
@@ -24,6 +24,7 @@ import { editMessage } from './xmpp/editMessage.xmpp';
24
24
  import { inviteRoomRequest } from './xmpp/inviteRoomRequest.xmpp';
25
25
  import { getRooms } from './xmpp/getRooms.xmpp';
26
26
  import { handleStanza } from './xmpp/handleStanzas.xmpp';
27
+ import { onOnline as e2eeOnOnline } from '../e2ee';
27
28
  import { pushLog as devPushLog, isDevLogActive } from '../utils/devLogger';
28
29
  import { normalizeRoomJid } from '../helpers/normalizeRoomJid';
29
30
  import { store } from '../roomStore';
@@ -569,6 +570,11 @@ export class XmppClient {
569
570
  } catch (err) {
570
571
  console.warn('onOnline callback failed', err);
571
572
  }
573
+ try {
574
+ e2eeOnOnline(this.client);
575
+ } catch (err) {
576
+ console.warn('e2ee onOnline failed', err);
577
+ }
572
578
  // Drain any sends that were buffered while the stream was down. The
573
579
  // presence stanzas from onOnlineCallback above were written to the
574
580
  // socket synchronously (allRoomPresences → presenceInRoom send the
@@ -38,6 +38,12 @@ export interface ChatState {
38
38
  themePreference?: ThemePreference;
39
39
  /** Push notifications toggle from Settings. `undefined` = on. */
40
40
  pushEnabled?: boolean;
41
+ /**
42
+ * The interface language the user picked in Settings (BCP-47, e.g.
43
+ * "fr-CA") - the backend's `user.appLanguage`. Wins over the host's
44
+ * `config.i18n.locale`, which is the default for a user who never chose.
45
+ */
46
+ uiLocale?: string;
41
47
  }
42
48
 
43
49
  export const unpackAndTransform = (input?: User): User => {
@@ -219,6 +225,12 @@ const reducers = {
219
225
  ) => {
220
226
  state.translateMode = action.payload;
221
227
  },
228
+ setUiLocale: (
229
+ state: WritableDraft<ChatState>,
230
+ action: PayloadAction<string | undefined>
231
+ ) => {
232
+ state.uiLocale = action.payload || undefined;
233
+ },
222
234
  };
223
235
 
224
236
  export const chatSlice: Slice<ChatState, typeof reducers, 'chat'> = createSlice({
@@ -242,6 +254,7 @@ export const {
242
254
  setTranslateMode,
243
255
  setThemePreference,
244
256
  setPushEnabled,
257
+ setUiLocale,
245
258
  } = chatSlice.actions;
246
259
 
247
260
  export default chatSlice.reducer;
@@ -1,5 +1,5 @@
1
1
  import AsyncStorage from '@react-native-async-storage/async-storage';
2
- import { secureGet, secureSet } from '../helpers/secureKeyValue';
2
+ import { secureGetOrCreate } from '../helpers/secureKeyValue';
3
3
  import { encryptForPersist, decryptFromPersist } from '../helpers/persistCrypto';
4
4
 
5
5
 
@@ -12,7 +12,7 @@ export interface PersistBackend {
12
12
  }
13
13
 
14
14
  const MMKV_INSTANCE_ID = 'ethora-chat-persist';
15
- const MMKV_KEY_STORE_KEY = '@ethora/persist:mmkvKey';
15
+ const MMKV_KEY_STORE_KEY = 'ethora_persist_mmkv_key';
16
16
  const MMKV_KEY_LENGTH = 16;
17
17
 
18
18
  const randomKey = (length: number): string => {
@@ -25,13 +25,6 @@ const randomKey = (length: number): string => {
25
25
  return out;
26
26
  };
27
27
 
28
- const loadOrCreateMmkvKey = async (): Promise<string> => {
29
- const existing = await secureGet(MMKV_KEY_STORE_KEY);
30
- if (existing) {return existing;}
31
- const key = randomKey(MMKV_KEY_LENGTH);
32
- await secureSet(MMKV_KEY_STORE_KEY, key);
33
- return key;
34
- };
35
28
 
36
29
  const createMmkvBackend = async (): Promise<PersistBackend | null> => {
37
30
  let MMKV: any;
@@ -42,9 +35,13 @@ const createMmkvBackend = async (): Promise<PersistBackend | null> => {
42
35
  }
43
36
  if (typeof MMKV !== 'function') {return null;}
44
37
  try {
45
- const encryptionKey = await loadOrCreateMmkvKey();
38
+ const key = await secureGetOrCreate(MMKV_KEY_STORE_KEY, () =>
39
+ randomKey(MMKV_KEY_LENGTH)
40
+ );
41
+ if (!key) {return null;}
46
42
  // Throws when the native module is missing from the binary.
47
- const storage = new MMKV({ id: MMKV_INSTANCE_ID, encryptionKey });
43
+ const storage = new MMKV({ id: MMKV_INSTANCE_ID, encryptionKey: key.value });
44
+ if (key.created) {storage.clearAll();}
48
45
  return {
49
46
  name: 'mmkv',
50
47
  getMany: async (keys) => keys.map((k) => storage.getString(k) ?? null),
@@ -132,6 +132,11 @@ const PERSISTED_MESSAGE_FIELDS: (keyof IMessage)[] = [
132
132
  // computeBootTimeFailures below) find exactly the messages that never
133
133
  // got confirmed and flip them to failed instead.
134
134
  'pending',
135
+ 'unencrypted',
136
+ 'undecryptable',
137
+ 'e2eeError',
138
+ 'clientEncrypted',
139
+ 'e2eeKeys',
135
140
  ];
136
141
 
137
142
  // The sender identity that rides along on every message over the wire
@@ -164,6 +169,7 @@ const PERSISTED_MESSAGE_USER_FIELDS = ['id', 'name'] as const;
164
169
  // repopulates from /chats/my on the very next load. `usersCnt`, which the
165
170
  // header actually reads, is its own scalar field and is preserved below.
166
171
  const REFETCHED_ROOM_FIELDS = ['members'] as const;
172
+ const PERSISTED_ROOM_MEMBERS = 30;
167
173
 
168
174
  const pickDefined = <T extends object>(
169
175
  source: T,
@@ -218,6 +224,15 @@ const sanitizeRooms = (
218
224
  for (const field of REFETCHED_ROOM_FIELDS) {
219
225
  delete compactRoom[field];
220
226
  }
227
+ // The same reasoning, one size down: the full roster a room gets once
228
+ // it is opened (loadRoomMembers) is re-fetched on the next open, so only
229
+ // the preview-sized head of it is worth a place in the cache.
230
+ if (
231
+ Array.isArray(compactRoom.roomMembers) &&
232
+ compactRoom.roomMembers.length > PERSISTED_ROOM_MEMBERS
233
+ ) {
234
+ compactRoom.roomMembers = compactRoom.roomMembers.slice(0, PERSISTED_ROOM_MEMBERS);
235
+ }
221
236
 
222
237
  out[jid] = {
223
238
  ...(compactRoom as IRoom),