@ethora/chat-component-rn 26.8.6 → 26.8.7

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 (409) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +40 -0
  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/EncryptedSendNotice.js +47 -0
  10. package/lib/commonjs/components/MainComponents/EncryptedSendNotice.js.map +1 -0
  11. package/lib/commonjs/components/MainComponents/EncryptionCard.js +286 -0
  12. package/lib/commonjs/components/MainComponents/EncryptionCard.js.map +1 -0
  13. package/lib/commonjs/components/MainComponents/MediaMessage.js +7 -0
  14. package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
  15. package/lib/commonjs/components/MainComponents/ReduxWrapper.js +5 -0
  16. package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
  17. package/lib/commonjs/components/MainComponents/SealedAttachment.js +231 -0
  18. package/lib/commonjs/components/MainComponents/SealedAttachment.js.map +1 -0
  19. package/lib/commonjs/components/MessageBubble/BottomReplyContainer.js +2 -1
  20. package/lib/commonjs/components/MessageBubble/BottomReplyContainer.js.map +1 -1
  21. package/lib/commonjs/components/MessageBubble/Message.js +66 -6
  22. package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
  23. package/lib/commonjs/components/MessageBubble/MessageInteractions.js +2 -1
  24. package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
  25. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +7 -4
  26. package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  27. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +159 -16
  28. package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  29. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +4 -0
  30. package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  31. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +29 -6
  32. package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  33. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +5 -1
  34. package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  35. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +32 -9
  36. package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
  37. package/lib/commonjs/components/RoomComponents/LastMessageItem.js +6 -0
  38. package/lib/commonjs/components/RoomComponents/LastMessageItem.js.map +1 -1
  39. package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js +2 -2
  40. package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
  41. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +4 -6
  42. package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  43. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +2 -2
  44. package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  45. package/lib/commonjs/components/RoomComponents/styled/LastMessageSealed.js +41 -0
  46. package/lib/commonjs/components/RoomComponents/styled/LastMessageSealed.js.map +1 -0
  47. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +2 -2
  48. package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  49. package/lib/commonjs/components/Thread/ThreadWrapper.js +53 -45
  50. package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
  51. package/lib/commonjs/components/UsersList/UsersList.js +2 -1
  52. package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
  53. package/lib/commonjs/components/styled/SendInput.js +4 -2
  54. package/lib/commonjs/components/styled/SendInput.js.map +1 -1
  55. package/lib/commonjs/e2ee/crypto.js +207 -0
  56. package/lib/commonjs/e2ee/crypto.js.map +1 -0
  57. package/lib/commonjs/e2ee/deviceStore.js +84 -0
  58. package/lib/commonjs/e2ee/deviceStore.js.map +1 -0
  59. package/lib/commonjs/e2ee/fileCipher.js +95 -0
  60. package/lib/commonjs/e2ee/fileCipher.js.map +1 -0
  61. package/lib/commonjs/e2ee/fileEnvelope.js +79 -0
  62. package/lib/commonjs/e2ee/fileEnvelope.js.map +1 -0
  63. package/lib/commonjs/e2ee/index.js +210 -0
  64. package/lib/commonjs/e2ee/index.js.map +1 -0
  65. package/lib/commonjs/e2ee/limits.js +9 -0
  66. package/lib/commonjs/e2ee/limits.js.map +1 -0
  67. package/lib/commonjs/e2ee/ns.js +8 -0
  68. package/lib/commonjs/e2ee/ns.js.map +1 -0
  69. package/lib/commonjs/e2ee/omemo.js +622 -0
  70. package/lib/commonjs/e2ee/omemo.js.map +1 -0
  71. package/lib/commonjs/e2ee/protobuf.js +149 -0
  72. package/lib/commonjs/e2ee/protobuf.js.map +1 -0
  73. package/lib/commonjs/e2ee/ratchet.js +238 -0
  74. package/lib/commonjs/e2ee/ratchet.js.map +1 -0
  75. package/lib/commonjs/e2ee/sealedBody.js +23 -0
  76. package/lib/commonjs/e2ee/sealedBody.js.map +1 -0
  77. package/lib/commonjs/e2ee/sealedFiles.js +174 -0
  78. package/lib/commonjs/e2ee/sealedFiles.js.map +1 -0
  79. package/lib/commonjs/e2ee/send.js +54 -0
  80. package/lib/commonjs/e2ee/send.js.map +1 -0
  81. package/lib/commonjs/e2ee/stanza.js +114 -0
  82. package/lib/commonjs/e2ee/stanza.js.map +1 -0
  83. package/lib/commonjs/e2ee/store.js +43 -0
  84. package/lib/commonjs/e2ee/store.js.map +1 -0
  85. package/lib/commonjs/helpers/accountName.js +23 -0
  86. package/lib/commonjs/helpers/accountName.js.map +1 -0
  87. package/lib/commonjs/helpers/createMessageFromXml.js +19 -4
  88. package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
  89. package/lib/commonjs/helpers/createUserNameFromSetUser.js +2 -1
  90. package/lib/commonjs/helpers/createUserNameFromSetUser.js.map +1 -1
  91. package/lib/commonjs/helpers/displayName.js +16 -0
  92. package/lib/commonjs/helpers/displayName.js.map +1 -0
  93. package/lib/commonjs/helpers/persistCrypto.js +5 -0
  94. package/lib/commonjs/helpers/persistCrypto.js.map +1 -1
  95. package/lib/commonjs/helpers/secureKeyValue.js +20 -0
  96. package/lib/commonjs/helpers/secureKeyValue.js.map +1 -1
  97. package/lib/commonjs/helpers/videoCache.js +136 -0
  98. package/lib/commonjs/helpers/videoCache.js.map +1 -0
  99. package/lib/commonjs/hooks/useLogout.js +8 -0
  100. package/lib/commonjs/hooks/useLogout.js.map +1 -1
  101. package/lib/commonjs/hooks/useSendMessage.js +71 -7
  102. package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
  103. package/lib/commonjs/i18n/strings.js +180 -0
  104. package/lib/commonjs/i18n/strings.js.map +1 -1
  105. package/lib/commonjs/main.js +13 -0
  106. package/lib/commonjs/main.js.map +1 -1
  107. package/lib/commonjs/networking/api-requests/auth.api.js +4 -1
  108. package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
  109. package/lib/commonjs/networking/api-requests/rooms.api.js +111 -17
  110. package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
  111. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +40 -0
  112. package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  113. package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js +16 -3
  114. package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
  115. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +13 -6
  116. package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  117. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +14 -6
  118. package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  119. package/lib/commonjs/networking/xmppClient.js +6 -0
  120. package/lib/commonjs/networking/xmppClient.js.map +1 -1
  121. package/lib/commonjs/roomStore/persistBackend.js +9 -12
  122. package/lib/commonjs/roomStore/persistBackend.js.map +1 -1
  123. package/lib/commonjs/roomStore/persistence.js +8 -1
  124. package/lib/commonjs/roomStore/persistence.js.map +1 -1
  125. package/lib/commonjs/version.js +1 -1
  126. package/lib/module/assets/icons.js +3 -1
  127. package/lib/module/assets/icons.js.map +1 -1
  128. package/lib/module/components/MainComponents/ChatHeader.js +29 -7
  129. package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
  130. package/lib/module/components/MainComponents/ChatRoom.js +9 -1
  131. package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
  132. package/lib/module/components/MainComponents/EncryptedSendNotice.js +42 -0
  133. package/lib/module/components/MainComponents/EncryptedSendNotice.js.map +1 -0
  134. package/lib/module/components/MainComponents/EncryptionCard.js +281 -0
  135. package/lib/module/components/MainComponents/EncryptionCard.js.map +1 -0
  136. package/lib/module/components/MainComponents/MediaMessage.js +7 -0
  137. package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
  138. package/lib/module/components/MainComponents/ReduxWrapper.js +5 -0
  139. package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
  140. package/lib/module/components/MainComponents/SealedAttachment.js +224 -0
  141. package/lib/module/components/MainComponents/SealedAttachment.js.map +1 -0
  142. package/lib/module/components/MessageBubble/BottomReplyContainer.js +2 -1
  143. package/lib/module/components/MessageBubble/BottomReplyContainer.js.map +1 -1
  144. package/lib/module/components/MessageBubble/Message.js +69 -9
  145. package/lib/module/components/MessageBubble/Message.js.map +1 -1
  146. package/lib/module/components/MessageBubble/MessageInteractions.js +2 -1
  147. package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
  148. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +7 -4
  149. package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
  150. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +161 -18
  151. package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
  152. package/lib/module/components/Modals/FilePreviewModal/PdfView.js +4 -0
  153. package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
  154. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +32 -8
  155. package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
  156. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +4 -0
  157. package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
  158. package/lib/module/components/RoomComponents/ChatRoomItem.js +32 -9
  159. package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
  160. package/lib/module/components/RoomComponents/LastMessageItem.js +6 -0
  161. package/lib/module/components/RoomComponents/LastMessageItem.js.map +1 -1
  162. package/lib/module/components/RoomComponents/styled/LastAudioMessage.js +2 -2
  163. package/lib/module/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
  164. package/lib/module/components/RoomComponents/styled/LastMessageFile.js +4 -6
  165. package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
  166. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +2 -2
  167. package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
  168. package/lib/module/components/RoomComponents/styled/LastMessageSealed.js +36 -0
  169. package/lib/module/components/RoomComponents/styled/LastMessageSealed.js.map +1 -0
  170. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +2 -2
  171. package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
  172. package/lib/module/components/Thread/ThreadWrapper.js +54 -46
  173. package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
  174. package/lib/module/components/UsersList/UsersList.js +2 -1
  175. package/lib/module/components/UsersList/UsersList.js.map +1 -1
  176. package/lib/module/components/styled/SendInput.js +4 -2
  177. package/lib/module/components/styled/SendInput.js.map +1 -1
  178. package/lib/module/e2ee/crypto.js +170 -0
  179. package/lib/module/e2ee/crypto.js.map +1 -0
  180. package/lib/module/e2ee/deviceStore.js +77 -0
  181. package/lib/module/e2ee/deviceStore.js.map +1 -0
  182. package/lib/module/e2ee/fileCipher.js +90 -0
  183. package/lib/module/e2ee/fileCipher.js.map +1 -0
  184. package/lib/module/e2ee/fileEnvelope.js +66 -0
  185. package/lib/module/e2ee/fileEnvelope.js.map +1 -0
  186. package/lib/module/e2ee/index.js +185 -0
  187. package/lib/module/e2ee/index.js.map +1 -0
  188. package/lib/module/e2ee/limits.js +5 -0
  189. package/lib/module/e2ee/limits.js.map +1 -0
  190. package/lib/module/e2ee/ns.js +4 -0
  191. package/lib/module/e2ee/ns.js.map +1 -0
  192. package/lib/module/e2ee/omemo.js +610 -0
  193. package/lib/module/e2ee/omemo.js.map +1 -0
  194. package/lib/module/e2ee/protobuf.js +140 -0
  195. package/lib/module/e2ee/protobuf.js.map +1 -0
  196. package/lib/module/e2ee/ratchet.js +228 -0
  197. package/lib/module/e2ee/ratchet.js.map +1 -0
  198. package/lib/module/e2ee/sealedBody.js +19 -0
  199. package/lib/module/e2ee/sealedBody.js.map +1 -0
  200. package/lib/module/e2ee/sealedFiles.js +154 -0
  201. package/lib/module/e2ee/sealedFiles.js.map +1 -0
  202. package/lib/module/e2ee/send.js +48 -0
  203. package/lib/module/e2ee/send.js.map +1 -0
  204. package/lib/module/e2ee/stanza.js +107 -0
  205. package/lib/module/e2ee/stanza.js.map +1 -0
  206. package/lib/module/e2ee/store.js +35 -0
  207. package/lib/module/e2ee/store.js.map +1 -0
  208. package/lib/module/helpers/accountName.js +18 -0
  209. package/lib/module/helpers/accountName.js.map +1 -0
  210. package/lib/module/helpers/createMessageFromXml.js +19 -4
  211. package/lib/module/helpers/createMessageFromXml.js.map +1 -1
  212. package/lib/module/helpers/createUserNameFromSetUser.js +3 -1
  213. package/lib/module/helpers/createUserNameFromSetUser.js.map +1 -1
  214. package/lib/module/helpers/displayName.js +11 -0
  215. package/lib/module/helpers/displayName.js.map +1 -0
  216. package/lib/module/helpers/persistCrypto.js +4 -0
  217. package/lib/module/helpers/persistCrypto.js.map +1 -1
  218. package/lib/module/helpers/secureKeyValue.js +19 -0
  219. package/lib/module/helpers/secureKeyValue.js.map +1 -1
  220. package/lib/module/helpers/videoCache.js +125 -0
  221. package/lib/module/helpers/videoCache.js.map +1 -0
  222. package/lib/module/hooks/useLogout.js +8 -0
  223. package/lib/module/hooks/useLogout.js.map +1 -1
  224. package/lib/module/hooks/useSendMessage.js +71 -7
  225. package/lib/module/hooks/useSendMessage.js.map +1 -1
  226. package/lib/module/i18n/strings.js +180 -0
  227. package/lib/module/i18n/strings.js.map +1 -1
  228. package/lib/module/main.js +1 -0
  229. package/lib/module/main.js.map +1 -1
  230. package/lib/module/networking/api-requests/auth.api.js +4 -1
  231. package/lib/module/networking/api-requests/auth.api.js.map +1 -1
  232. package/lib/module/networking/api-requests/rooms.api.js +109 -18
  233. package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
  234. package/lib/module/networking/xmpp/handleStanzas.xmpp.js +38 -0
  235. package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
  236. package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js +16 -3
  237. package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
  238. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +13 -6
  239. package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
  240. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +14 -6
  241. package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
  242. package/lib/module/networking/xmppClient.js +6 -0
  243. package/lib/module/networking/xmppClient.js.map +1 -1
  244. package/lib/module/roomStore/persistBackend.js +10 -13
  245. package/lib/module/roomStore/persistBackend.js.map +1 -1
  246. package/lib/module/roomStore/persistence.js +8 -1
  247. package/lib/module/roomStore/persistence.js.map +1 -1
  248. package/lib/module/version.js +1 -1
  249. package/lib/typescript/assets/icons.d.ts +8 -0
  250. package/lib/typescript/assets/icons.d.ts.map +1 -1
  251. package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
  252. package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
  253. package/lib/typescript/components/MainComponents/EncryptedSendNotice.d.ts +4 -0
  254. package/lib/typescript/components/MainComponents/EncryptedSendNotice.d.ts.map +1 -0
  255. package/lib/typescript/components/MainComponents/EncryptionCard.d.ts +10 -0
  256. package/lib/typescript/components/MainComponents/EncryptionCard.d.ts.map +1 -0
  257. package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
  258. package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
  259. package/lib/typescript/components/MainComponents/SealedAttachment.d.ts +13 -0
  260. package/lib/typescript/components/MainComponents/SealedAttachment.d.ts.map +1 -0
  261. package/lib/typescript/components/MessageBubble/BottomReplyContainer.d.ts.map +1 -1
  262. package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
  263. package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
  264. package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
  265. package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
  266. package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
  267. package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
  268. package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
  269. package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
  270. package/lib/typescript/components/RoomComponents/LastMessageItem.d.ts.map +1 -1
  271. package/lib/typescript/components/RoomComponents/styled/LastAudioMessage.d.ts.map +1 -1
  272. package/lib/typescript/components/RoomComponents/styled/LastMessageSealed.d.ts +7 -0
  273. package/lib/typescript/components/RoomComponents/styled/LastMessageSealed.d.ts.map +1 -0
  274. package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
  275. package/lib/typescript/components/UsersList/UsersList.d.ts.map +1 -1
  276. package/lib/typescript/components/styled/SendInput.d.ts +1 -0
  277. package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
  278. package/lib/typescript/e2ee/crypto.d.ts +28 -0
  279. package/lib/typescript/e2ee/crypto.d.ts.map +1 -0
  280. package/lib/typescript/e2ee/deviceStore.d.ts +4 -0
  281. package/lib/typescript/e2ee/deviceStore.d.ts.map +1 -0
  282. package/lib/typescript/e2ee/fileCipher.d.ts +7 -0
  283. package/lib/typescript/e2ee/fileCipher.d.ts.map +1 -0
  284. package/lib/typescript/e2ee/fileEnvelope.d.ts +27 -0
  285. package/lib/typescript/e2ee/fileEnvelope.d.ts.map +1 -0
  286. package/lib/typescript/e2ee/index.d.ts +23 -0
  287. package/lib/typescript/e2ee/index.d.ts.map +1 -0
  288. package/lib/typescript/e2ee/limits.d.ts +3 -0
  289. package/lib/typescript/e2ee/limits.d.ts.map +1 -0
  290. package/lib/typescript/e2ee/ns.d.ts +2 -0
  291. package/lib/typescript/e2ee/ns.d.ts.map +1 -0
  292. package/lib/typescript/e2ee/omemo.d.ts +64 -0
  293. package/lib/typescript/e2ee/omemo.d.ts.map +1 -0
  294. package/lib/typescript/e2ee/protobuf.d.ts +25 -0
  295. package/lib/typescript/e2ee/protobuf.d.ts.map +1 -0
  296. package/lib/typescript/e2ee/ratchet.d.ts +39 -0
  297. package/lib/typescript/e2ee/ratchet.d.ts.map +1 -0
  298. package/lib/typescript/e2ee/sealedBody.d.ts +2 -0
  299. package/lib/typescript/e2ee/sealedBody.d.ts.map +1 -0
  300. package/lib/typescript/e2ee/sealedFiles.d.ts +31 -0
  301. package/lib/typescript/e2ee/sealedFiles.d.ts.map +1 -0
  302. package/lib/typescript/e2ee/send.d.ts +6 -0
  303. package/lib/typescript/e2ee/send.d.ts.map +1 -0
  304. package/lib/typescript/e2ee/stanza.d.ts +8 -0
  305. package/lib/typescript/e2ee/stanza.d.ts.map +1 -0
  306. package/lib/typescript/e2ee/store.d.ts +16 -0
  307. package/lib/typescript/e2ee/store.d.ts.map +1 -0
  308. package/lib/typescript/helpers/accountName.d.ts +7 -0
  309. package/lib/typescript/helpers/accountName.d.ts.map +1 -0
  310. package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
  311. package/lib/typescript/helpers/createUserNameFromSetUser.d.ts.map +1 -1
  312. package/lib/typescript/helpers/displayName.d.ts +2 -0
  313. package/lib/typescript/helpers/displayName.d.ts.map +1 -0
  314. package/lib/typescript/helpers/persistCrypto.d.ts +1 -0
  315. package/lib/typescript/helpers/persistCrypto.d.ts.map +1 -1
  316. package/lib/typescript/helpers/secureKeyValue.d.ts +4 -0
  317. package/lib/typescript/helpers/secureKeyValue.d.ts.map +1 -1
  318. package/lib/typescript/helpers/videoCache.d.ts +19 -0
  319. package/lib/typescript/helpers/videoCache.d.ts.map +1 -0
  320. package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
  321. package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
  322. package/lib/typescript/i18n/strings.d.ts.map +1 -1
  323. package/lib/typescript/main.d.ts +2 -0
  324. package/lib/typescript/main.d.ts.map +1 -1
  325. package/lib/typescript/networking/api-requests/auth.api.d.ts +4 -1
  326. package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
  327. package/lib/typescript/networking/api-requests/rooms.api.d.ts +22 -1
  328. package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
  329. package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts +1 -0
  330. package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
  331. package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts.map +1 -1
  332. package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
  333. package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
  334. package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
  335. package/lib/typescript/roomStore/persistBackend.d.ts.map +1 -1
  336. package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
  337. package/lib/typescript/types/models/message.model.d.ts +5 -0
  338. package/lib/typescript/types/models/message.model.d.ts.map +1 -1
  339. package/lib/typescript/types/models/room.model.d.ts +5 -0
  340. package/lib/typescript/types/models/room.model.d.ts.map +1 -1
  341. package/lib/typescript/types/types.d.ts +4 -0
  342. package/lib/typescript/types/types.d.ts.map +1 -1
  343. package/lib/typescript/version.d.ts +1 -1
  344. package/package.json +8 -4
  345. package/src/assets/icons.tsx +27 -0
  346. package/src/components/MainComponents/ChatHeader.tsx +30 -9
  347. package/src/components/MainComponents/ChatRoom.tsx +11 -1
  348. package/src/components/MainComponents/EncryptedSendNotice.tsx +35 -0
  349. package/src/components/MainComponents/EncryptionCard.tsx +287 -0
  350. package/src/components/MainComponents/MediaMessage.tsx +5 -0
  351. package/src/components/MainComponents/ReduxWrapper.tsx +5 -0
  352. package/src/components/MainComponents/SealedAttachment.tsx +251 -0
  353. package/src/components/MessageBubble/BottomReplyContainer.tsx +2 -1
  354. package/src/components/MessageBubble/Message.tsx +96 -6
  355. package/src/components/MessageBubble/MessageInteractions.tsx +2 -3
  356. package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +7 -4
  357. package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +181 -35
  358. package/src/components/Modals/FilePreviewModal/PdfView.tsx +4 -0
  359. package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +53 -8
  360. package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +5 -0
  361. package/src/components/RoomComponents/ChatRoomItem.tsx +23 -11
  362. package/src/components/RoomComponents/LastMessageItem.tsx +5 -0
  363. package/src/components/RoomComponents/styled/LastAudioMessage.tsx +3 -1
  364. package/src/components/RoomComponents/styled/LastMessageFile.tsx +2 -2
  365. package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +1 -1
  366. package/src/components/RoomComponents/styled/LastMessageSealed.tsx +31 -0
  367. package/src/components/RoomComponents/styled/LastMessageVideo.tsx +1 -1
  368. package/src/components/Thread/ThreadWrapper.tsx +13 -0
  369. package/src/components/UsersList/UsersList.tsx +2 -1
  370. package/src/components/styled/SendInput.tsx +5 -2
  371. package/src/e2ee/crypto.ts +194 -0
  372. package/src/e2ee/deviceStore.ts +80 -0
  373. package/src/e2ee/fileCipher.ts +86 -0
  374. package/src/e2ee/fileEnvelope.ts +115 -0
  375. package/src/e2ee/index.ts +192 -0
  376. package/src/e2ee/limits.ts +2 -0
  377. package/src/e2ee/ns.ts +1 -0
  378. package/src/e2ee/omemo.ts +802 -0
  379. package/src/e2ee/protobuf.ts +188 -0
  380. package/src/e2ee/ratchet.ts +271 -0
  381. package/src/e2ee/sealedBody.ts +17 -0
  382. package/src/e2ee/sealedFiles.ts +181 -0
  383. package/src/e2ee/send.ts +70 -0
  384. package/src/e2ee/stanza.ts +133 -0
  385. package/src/e2ee/store.ts +54 -0
  386. package/src/helpers/accountName.ts +15 -0
  387. package/src/helpers/createMessageFromXml.ts +31 -6
  388. package/src/helpers/createUserNameFromSetUser.ts +2 -1
  389. package/src/helpers/displayName.ts +9 -0
  390. package/src/helpers/persistCrypto.ts +5 -0
  391. package/src/helpers/secureKeyValue.ts +15 -0
  392. package/src/helpers/videoCache.ts +138 -0
  393. package/src/hooks/useLogout.tsx +9 -0
  394. package/src/hooks/useSendMessage.tsx +71 -5
  395. package/src/i18n/strings.ts +180 -0
  396. package/src/main.ts +2 -0
  397. package/src/networking/api-requests/auth.api.ts +9 -1
  398. package/src/networking/api-requests/rooms.api.ts +121 -18
  399. package/src/networking/xmpp/handleStanzas.xmpp.ts +49 -0
  400. package/src/networking/xmpp/sendMediaMessage.xmpp.ts +19 -1
  401. package/src/networking/xmpp/sendTextMessage.xmpp.ts +17 -10
  402. package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +23 -10
  403. package/src/networking/xmppClient.ts +6 -0
  404. package/src/roomStore/persistBackend.ts +8 -11
  405. package/src/roomStore/persistence.ts +15 -0
  406. package/src/types/models/message.model.ts +5 -0
  407. package/src/types/models/room.model.ts +5 -0
  408. package/src/types/types.ts +4 -0
  409. package/src/version.ts +1 -1
@@ -0,0 +1,251 @@
1
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
+ import { ActivityIndicator, StyleSheet, View } from 'react-native';
3
+ import { LockIcon } from '../../assets/icons';
4
+ import FileDownload from '../styled/UnsupportedType';
5
+ import CustomMessageImage from '../styled/MessageImage';
6
+ import CustomMessageVideo from '../styled/VideoMessage';
7
+ import AudioMessage from '../styled/AudioMessage';
8
+ import {
9
+ BackgroundFile,
10
+ FileInformation,
11
+ FileName,
12
+ FileSize,
13
+ FileSizeContainer,
14
+ UnsupportedContainer,
15
+ } from '../styled/StyledInputComponents/MediaComponents';
16
+ import { useTheme } from '../../hooks/useTheme';
17
+ import { useT } from '../../i18n/useT';
18
+ import { useChatSettingState } from '../../hooks/useChatSettingState';
19
+ import { IMessage } from '../../types/types';
20
+ import { withFileToken } from '../../helpers/secureFileUrl';
21
+ import type { OpenedFile } from '../../e2ee/sealedFiles';
22
+
23
+ const sealedFiles = () =>
24
+ require('../../e2ee/sealedFiles') as typeof import('../../e2ee/sealedFiles');
25
+
26
+ interface SealedRef {
27
+ location: string;
28
+ size?: string | number;
29
+ }
30
+
31
+ export const sealedAttachmentsOf = (message?: IMessage | null): SealedRef[] => {
32
+ if (!message) {return [];}
33
+ let raw: unknown = (message as any).attachments;
34
+ if (typeof raw === 'string') {
35
+ try {
36
+ raw = JSON.parse(raw);
37
+ } catch {
38
+ raw = undefined;
39
+ }
40
+ }
41
+ if (Array.isArray(raw) && raw.length > 0) {
42
+ return raw
43
+ .filter((item) => item && typeof item.location === 'string' && item.location)
44
+ .map((item) => ({ location: item.location, size: item.size }));
45
+ }
46
+ return message.location
47
+ ? [{ location: message.location, size: message.size }]
48
+ : [];
49
+ };
50
+
51
+ const formatBytes = (value?: string | number): string => {
52
+ const bytes = Number(value);
53
+ if (!Number.isFinite(bytes) || bytes <= 0) {return '';}
54
+ if (bytes < 1024) {return `${bytes} B`;}
55
+ if (bytes < 1024 * 1024) {return `${(bytes / 1024).toFixed(0)} KB`;}
56
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
57
+ };
58
+
59
+ type CardState = 'idle' | 'working' | 'failed';
60
+
61
+ const SealedItem: React.FC<{
62
+ attachment: SealedRef;
63
+ keyMaterial?: string;
64
+ isUser: boolean;
65
+ }> = ({ attachment, keyMaterial, isUser }) => {
66
+ const theme = useTheme();
67
+ const t = useT();
68
+ const { config } = useChatSettingState();
69
+ const [state, setState] = useState<CardState>('idle');
70
+ const [progress, setProgress] = useState(0);
71
+ const [opened, setOpened] = useState<OpenedFile | null>(null);
72
+ const mounted = useRef(true);
73
+ useEffect(
74
+ () => () => {
75
+ mounted.current = false;
76
+ },
77
+ []
78
+ );
79
+
80
+ const { location } = attachment;
81
+
82
+ useEffect(() => {
83
+ if (!keyMaterial || !location) {return;}
84
+ let active = true;
85
+ sealedFiles()
86
+ .findOpened(location)
87
+ .then((found) => {
88
+ if (active && found) {setOpened(found);}
89
+ })
90
+ .catch(() => {});
91
+ return () => {
92
+ active = false;
93
+ };
94
+ }, [keyMaterial, location]);
95
+
96
+ const handlePress = useCallback(async () => {
97
+ if (opened || !keyMaterial || !location || state === 'working') {return;}
98
+ setState('working');
99
+ setProgress(0);
100
+ try {
101
+ const file = await sealedFiles().openSealedAttachment(
102
+ location,
103
+ withFileToken(location),
104
+ keyMaterial,
105
+ (fraction) => {
106
+ if (mounted.current) {setProgress(fraction);}
107
+ }
108
+ );
109
+ if (!mounted.current) {return;}
110
+ setOpened(file);
111
+ setState('idle');
112
+ } catch (error) {
113
+ console.warn('sealed attachment could not be opened', error);
114
+ if (mounted.current) {setState('failed');}
115
+ }
116
+ }, [keyMaterial, location, opened, state]);
117
+
118
+ if (opened) {
119
+ if (opened.mimetype.startsWith('image/')) {
120
+ return (
121
+ <View testID="sealed-attachment-image">
122
+ <CustomMessageImage
123
+ fileName={opened.name}
124
+ originalName={opened.name}
125
+ fileURL={opened.uri}
126
+ locationPreview={opened.uri}
127
+ mimetype={opened.mimetype}
128
+ />
129
+ </View>
130
+ );
131
+ }
132
+ if (opened.mimetype.startsWith('video/')) {
133
+ return (
134
+ <CustomMessageVideo
135
+ fileName={opened.name}
136
+ originalName={opened.name}
137
+ fileURL={opened.uri}
138
+ mimetype={opened.mimetype}
139
+ />
140
+ );
141
+ }
142
+ if (opened.mimetype.startsWith('audio/')) {
143
+ return (
144
+ <AudioMessage
145
+ src={opened.uri}
146
+ mimeType={opened.mimetype}
147
+ fileName={opened.name}
148
+ originalName={opened.name}
149
+ />
150
+ );
151
+ }
152
+ return (
153
+ <View testID="sealed-attachment">
154
+ <FileDownload
155
+ fileURL={opened.uri}
156
+ fileName={opened.name}
157
+ originalName={opened.name}
158
+ mimetype={opened.mimetype}
159
+ isUser={isUser}
160
+ />
161
+ </View>
162
+ );
163
+ }
164
+
165
+ const canOpen = !!keyMaterial && !!location;
166
+ const working = state === 'working';
167
+ const note = !canOpen
168
+ ? t(
169
+ config?.e2ee?.enabled === true
170
+ ? 'media.sealedUnavailable'
171
+ : 'media.sealedUnsupported'
172
+ )
173
+ : working
174
+ ? `${t('media.sealedDownloading')} ${Math.round(progress * 100)}%`
175
+ : state === 'failed'
176
+ ? t('media.sealedDownloadFailed')
177
+ : formatBytes(attachment.size) || t('media.sealedDownload');
178
+
179
+ return (
180
+ <UnsupportedContainer
181
+ isUser={isUser}
182
+ onPress={handlePress}
183
+ disabled={!canOpen || working}
184
+ activeOpacity={canOpen && !working ? 0.7 : 1}
185
+ testID="sealed-attachment"
186
+ accessibilityRole="button"
187
+ accessibilityLabel={t(canOpen ? 'media.sealedDownload' : 'media.sealedFile')}
188
+ >
189
+ <BackgroundFile>
190
+ {working ? (
191
+ <ActivityIndicator size="small" color={theme.textSecondary} />
192
+ ) : (
193
+ <LockIcon width={26} height={26} color={theme.textSecondary} />
194
+ )}
195
+ </BackgroundFile>
196
+ <FileInformation>
197
+ <FileName
198
+ numberOfLines={1}
199
+ isUser={isUser}
200
+ colorIsUser={config?.colors?.primary}
201
+ colorUsers={config?.colors?.secondary}
202
+ >
203
+ {t('media.sealedFile')}
204
+ </FileName>
205
+ <FileSizeContainer style={styles.note}>
206
+ <FileSize
207
+ numberOfLines={2}
208
+ style={state === 'failed' && canOpen ? { color: theme.danger } : undefined}
209
+ >
210
+ {note}
211
+ </FileSize>
212
+ </FileSizeContainer>
213
+ </FileInformation>
214
+ </UnsupportedContainer>
215
+ );
216
+ };
217
+
218
+ const SealedAttachment: React.FC<{ message?: IMessage; isUser: boolean }> = ({
219
+ message,
220
+ isUser,
221
+ }) => {
222
+ const attachments = sealedAttachmentsOf(message);
223
+ const keys = message?.e2eeKeys;
224
+ if (attachments.length === 0) {
225
+ return <SealedItem attachment={{ location: '' }} isUser={isUser} />;
226
+ }
227
+ return (
228
+ <View style={styles.stack}>
229
+ {attachments.map((attachment, index) => (
230
+ <SealedItem
231
+ key={attachment.location || index}
232
+ attachment={attachment}
233
+ keyMaterial={keys?.[index]}
234
+ isUser={isUser}
235
+ />
236
+ ))}
237
+ </View>
238
+ );
239
+ };
240
+
241
+ export default SealedAttachment;
242
+
243
+ const styles = StyleSheet.create({
244
+ stack: {
245
+ gap: 8,
246
+ },
247
+ note: {
248
+ flexShrink: 1,
249
+ borderRadius: 10,
250
+ },
251
+ });
@@ -1,4 +1,5 @@
1
1
  import { FC, useMemo } from 'react';
2
+ import { composeName } from '../../helpers/displayName';
2
3
  import { IReply, IUser } from '../../types/types';
3
4
  import { Avatar } from './Avatar';
4
5
  import { styled } from 'styled-components/native';
@@ -68,7 +69,7 @@ export const BottomReplyContainer: FC<BottomReplyContainerProps> = ({
68
69
  const raw = String(u?.id || '');
69
70
  const entry = usersSet?.[raw.split('@')[0]] || usersSet?.[raw];
70
71
  const full = entry
71
- ? `${entry.firstName || ''} ${entry.lastName || ''}`.trim() || entry.name
72
+ ? composeName(entry.firstName, entry.lastName) || entry.name
72
73
  : '';
73
74
  return full || u?.name || '';
74
75
  };
@@ -1,5 +1,6 @@
1
1
  import React, { useEffect, useMemo, useRef, useState } from 'react';
2
2
  import {
3
+ Alert,
3
4
  Animated,
4
5
  View,
5
6
  Pressable,
@@ -36,7 +37,16 @@ import { useChatSettingState } from '../../hooks/useChatSettingState';
36
37
  import { parseMessageBody } from '../../helpers/parseMessageBody';
37
38
  import { chatTextStyle } from '../../helpers/typography';
38
39
  import { useMessageHeapState } from '../../hooks/useMessageHeapState';
39
- import { DoubleTick } from '../../assets/icons';
40
+ import { DoubleTick, LockIcon, LockOffIcon } from '../../assets/icons';
41
+ import { useT } from '../../i18n/useT';
42
+ import { composeName } from '../../helpers/displayName';
43
+ import { useFileToken } from '../../hooks/useFileToken';
44
+ import {
45
+ appendFileToken,
46
+ isSecureFileUrl,
47
+ requestFileTokenRecovery,
48
+ } from '../../helpers/secureFileUrl';
49
+ import { placeholderKey } from '../../e2ee/stanza';
40
50
  import { useXmppClient } from '../../context/xmppProvider';
41
51
  import { useSendMessage } from '../../hooks/useSendMessage';
42
52
  import { MessageReaction } from './MessageReaction';
@@ -168,6 +178,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
168
178
  // only per-render allocations added for theming (memoized on the theme
169
179
  // object, which useTheme keeps stable across renders).
170
180
  const theme = useTheme();
181
+ const t = useT();
171
182
  const themedStyles = useMemo(
172
183
  () => ({
173
184
  muted: { color: theme.textMuted },
@@ -226,7 +237,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
226
237
  // (which may carry senderFirstName/senderLastName from the wire) only when
227
238
  // usersSet has never seen this sender.
228
239
  const senderDisplayName = senderEntry
229
- ? `${senderEntry.firstName ?? ''} ${senderEntry.lastName ?? ''}`.trim() ||
240
+ ? composeName(senderEntry.firstName, senderEntry.lastName) ||
230
241
  senderEntry.name ||
231
242
  senderLocal
232
243
  : message.user?.name || senderLocal || 'Unknown';
@@ -235,8 +246,18 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
235
246
  // ends at 50 characters of hex. Captioning a bubble with that tells the
236
247
  // reader strictly less than showing nothing.
237
248
  const hasRealSenderName = !isUnresolvedSenderId(senderDisplayName);
249
+ const fileToken = useFileToken();
250
+ const [avatarFailed, setAvatarFailed] = useState<string | null>(null);
251
+ const rawProfileImage = String(
252
+ senderEntry?.profileImage ||
253
+ message.user?.profileImage ||
254
+ (message.user as any)?.photoURL ||
255
+ ''
256
+ ).trim();
238
257
  const senderProfileImage =
239
- senderEntry?.profileImage || message.user?.profileImage || '';
258
+ rawProfileImage && rawProfileImage !== 'none' && rawProfileImage !== avatarFailed
259
+ ? appendFileToken(rawProfileImage, fileToken)
260
+ : '';
240
261
  const { idSet, failedIdSet } = useMessageHeapState();
241
262
  const { retryMessage } = useSendMessage();
242
263
 
@@ -407,8 +428,13 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
407
428
  );
408
429
  // In auto mode, render the translation as the primary body — but NEVER for
409
430
  // the reader's own messages (they wrote it; no point translating it back).
431
+ const isUndecryptable =
432
+ message.undecryptable === 'true' && !message.isDeleted;
410
433
  const showInlineTranslation =
411
- isAutoTranslate && translationDisplay.hasTranslation && !isUser;
434
+ isAutoTranslate &&
435
+ translationDisplay.hasTranslation &&
436
+ !isUser &&
437
+ !isUndecryptable;
412
438
  const bodyToRender = showInlineTranslation
413
439
  ? translationDisplay.displayText
414
440
  : message.body;
@@ -460,13 +486,32 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
460
486
  onPress={
461
487
  config?.disableProfilesInteractions
462
488
  ? undefined
463
- : () => handleUserAvatarClick(message.user)
489
+ : () =>
490
+ handleUserAvatarClick({
491
+ ...message.user,
492
+ ...(senderEntry
493
+ ? {
494
+ firstName: senderEntry.firstName,
495
+ lastName: senderEntry.lastName,
496
+ profileImage: senderEntry.profileImage,
497
+ description: senderEntry.description,
498
+ }
499
+ : {}),
500
+ name: hasRealSenderName ? senderDisplayName : '',
501
+ } as IUser)
464
502
  }
465
503
  disabled={!!config?.disableProfilesInteractions}
466
504
  accessible={!config?.disableProfilesInteractions}
467
505
  >
468
506
  {senderProfileImage ? (
469
- <CustomMessagePhoto source={{ uri: senderProfileImage }} />
507
+ <CustomMessagePhoto
508
+ testID="message-sender-avatar"
509
+ source={{ uri: senderProfileImage }}
510
+ onError={() => {
511
+ if (isSecureFileUrl(rawProfileImage)) {requestFileTokenRecovery();}
512
+ setAvatarFailed(rawProfileImage);
513
+ }}
514
+ />
470
515
  ) : (
471
516
  <Avatar username={senderDisplayName} />
472
517
  )}
@@ -537,6 +582,26 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
537
582
  <>
538
583
  {message.isDeleted && message.id !== 'delimiter-new' ? (
539
584
  <DeletedMessage />
585
+ ) : isUndecryptable ? (
586
+ <View style={styles.undecryptable}>
587
+ <LockIcon
588
+ width={15}
589
+ height={15}
590
+ color={theme.textSecondary}
591
+ />
592
+ <Text
593
+ style={[
594
+ styles.undecryptableText,
595
+ themedStyles.muted,
596
+ {
597
+ fontSize:
598
+ config?.typography?.messageText?.fontSize ?? 15,
599
+ },
600
+ ]}
601
+ >
602
+ {t(placeholderKey(message.e2eeError))}
603
+ </Text>
604
+ </View>
540
605
  ) : (
541
606
  <CustomMessageText
542
607
  isUser={isUser}
@@ -565,6 +630,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
565
630
  renders the translation inline in the body above). Never on
566
631
  the reader's own messages. */}
567
632
  {!isUser &&
633
+ !isUndecryptable &&
568
634
  isTranslatesEnabled &&
569
635
  effectiveTranslateMode === 'manual' && (
570
636
  <MessageTranslate
@@ -594,6 +660,20 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
594
660
  {message?.isEdited && !message?.isDeleted && (
595
661
  <Text style={[styles.editedText, themedStyles.muted]}>edited</Text>
596
662
  )}
663
+ {message?.unencrypted && !message?.isDeleted && (
664
+ <Pressable
665
+ hitSlop={10}
666
+ accessibilityRole="button"
667
+ accessibilityLabel={t('e2ee.notEncrypted')}
668
+ accessibilityHint={t('e2ee.notEncryptedHint')}
669
+ testID="message-not-encrypted"
670
+ onPress={() =>
671
+ Alert.alert(t('e2ee.notEncrypted'), t('e2ee.notEncryptedHint'))
672
+ }
673
+ >
674
+ <LockOffIcon width={13} height={13} color={theme.danger} />
675
+ </Pressable>
676
+ )}
597
677
  <Text style={[styles.timestampText, themedStyles.muted]}>
598
678
  {timeLabel}
599
679
  </Text>
@@ -718,6 +798,16 @@ const styles = StyleSheet.create({
718
798
  marginTop: 4,
719
799
  gap: 4,
720
800
  },
801
+ undecryptable: {
802
+ flexDirection: 'row',
803
+ alignItems: 'flex-start',
804
+ gap: 6,
805
+ maxWidth: 260,
806
+ },
807
+ undecryptableText: {
808
+ flexShrink: 1,
809
+ fontStyle: 'italic',
810
+ },
721
811
  timestampText: {
722
812
  fontSize: 12,
723
813
  lineHeight: 16,
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useId, useMemo, useRef, useState } from 'react';
2
+ import { canEditMessage } from '../../e2ee';
2
3
  import { Delimeter, MenuItem } from '../ContextMenu/ContextMenuComponents';
3
4
  import { useSelector } from 'react-redux';
4
5
  import { RootState } from '../../roomStore';
@@ -362,9 +363,7 @@ const MessageInteractions: React.FC<MessageInteractionsProps> = ({
362
363
  </MenuItem>
363
364
  {isUser && (
364
365
  <>
365
- {/* Edit only for non-media messages (upstream guard) +
366
- consistent label styling (menuText). */}
367
- {message?.isMediafile !== 'true' && (
366
+ {message?.isMediafile !== 'true' && canEditMessage(message) && (
368
367
  <>
369
368
  <Delimeter />
370
369
  <MenuItem onPress={handleEditMessage}>
@@ -1,5 +1,6 @@
1
1
  /** @format */
2
2
 
3
+ import { composeName } from '../../../helpers/displayName';
3
4
  import React, { useEffect, useMemo, useRef, useState } from 'react';
4
5
  import {
5
6
  Alert,
@@ -268,7 +269,7 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
268
269
  const confirmRemoveMember = (user: RoomMember) => {
269
270
  Alert.alert(
270
271
  t('modal.chatProfile.removeMember'),
271
- `${user.firstName} ${user.lastName}`.trim(),
272
+ composeName(user.firstName, user.lastName),
272
273
  [
273
274
  { text: t('action.cancel'), style: 'cancel' },
274
275
  {
@@ -287,7 +288,8 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
287
288
  id: user._id,
288
289
  firstName: user.firstName,
289
290
  lastName: user.lastName,
290
- name: `${user.firstName} ${user.lastName}`,
291
+ name: composeName(user.firstName, user.lastName),
292
+ profileImage: user.profileImage,
291
293
  userJID: user?.xmppUsername,
292
294
  token: '',
293
295
  refreshToken: '',
@@ -488,7 +490,7 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
488
490
  const query = memberQuery.trim().toLowerCase();
489
491
  const visibleMembers = query
490
492
  ? members.filter((user) =>
491
- `${user.firstName ?? ''} ${user.lastName ?? ''}`
493
+ composeName(user.firstName, user.lastName)
492
494
  .toLowerCase()
493
495
  .includes(query)
494
496
  )
@@ -648,7 +650,8 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
648
650
  disabled={!!config?.disableChatInfo?.disableMemberTap}
649
651
  >
650
652
  <ProfileImagePlaceholder
651
- name={`${user.firstName} ${user.lastName}`}
653
+ name={composeName(user.firstName, user.lastName)}
654
+ icon={appendFileToken(user.profileImage, fileToken) || null}
652
655
  size={40}
653
656
  />
654
657
  <View style={styles.memberText}>