@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.
- package/CHANGELOG.md +26 -0
- package/README.md +40 -0
- package/lib/commonjs/assets/icons.js +4 -2
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +28 -6
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +9 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/EncryptedSendNotice.js +47 -0
- package/lib/commonjs/components/MainComponents/EncryptedSendNotice.js.map +1 -0
- package/lib/commonjs/components/MainComponents/EncryptionCard.js +286 -0
- package/lib/commonjs/components/MainComponents/EncryptionCard.js.map +1 -0
- package/lib/commonjs/components/MainComponents/MediaMessage.js +7 -0
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js +5 -0
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/SealedAttachment.js +231 -0
- package/lib/commonjs/components/MainComponents/SealedAttachment.js.map +1 -0
- package/lib/commonjs/components/MessageBubble/BottomReplyContainer.js +2 -1
- package/lib/commonjs/components/MessageBubble/BottomReplyContainer.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +66 -6
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +2 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +7 -4
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +159 -16
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +4 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +29 -6
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +5 -1
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +32 -9
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/LastMessageItem.js +6 -0
- package/lib/commonjs/components/RoomComponents/LastMessageItem.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js +2 -2
- package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +4 -6
- package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +2 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageSealed.js +41 -0
- package/lib/commonjs/components/RoomComponents/styled/LastMessageSealed.js.map +1 -0
- package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +2 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
- package/lib/commonjs/components/Thread/ThreadWrapper.js +53 -45
- package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
- package/lib/commonjs/components/UsersList/UsersList.js +2 -1
- package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +4 -2
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/e2ee/crypto.js +207 -0
- package/lib/commonjs/e2ee/crypto.js.map +1 -0
- package/lib/commonjs/e2ee/deviceStore.js +84 -0
- package/lib/commonjs/e2ee/deviceStore.js.map +1 -0
- package/lib/commonjs/e2ee/fileCipher.js +95 -0
- package/lib/commonjs/e2ee/fileCipher.js.map +1 -0
- package/lib/commonjs/e2ee/fileEnvelope.js +79 -0
- package/lib/commonjs/e2ee/fileEnvelope.js.map +1 -0
- package/lib/commonjs/e2ee/index.js +210 -0
- package/lib/commonjs/e2ee/index.js.map +1 -0
- package/lib/commonjs/e2ee/limits.js +9 -0
- package/lib/commonjs/e2ee/limits.js.map +1 -0
- package/lib/commonjs/e2ee/ns.js +8 -0
- package/lib/commonjs/e2ee/ns.js.map +1 -0
- package/lib/commonjs/e2ee/omemo.js +622 -0
- package/lib/commonjs/e2ee/omemo.js.map +1 -0
- package/lib/commonjs/e2ee/protobuf.js +149 -0
- package/lib/commonjs/e2ee/protobuf.js.map +1 -0
- package/lib/commonjs/e2ee/ratchet.js +238 -0
- package/lib/commonjs/e2ee/ratchet.js.map +1 -0
- package/lib/commonjs/e2ee/sealedBody.js +23 -0
- package/lib/commonjs/e2ee/sealedBody.js.map +1 -0
- package/lib/commonjs/e2ee/sealedFiles.js +174 -0
- package/lib/commonjs/e2ee/sealedFiles.js.map +1 -0
- package/lib/commonjs/e2ee/send.js +54 -0
- package/lib/commonjs/e2ee/send.js.map +1 -0
- package/lib/commonjs/e2ee/stanza.js +114 -0
- package/lib/commonjs/e2ee/stanza.js.map +1 -0
- package/lib/commonjs/e2ee/store.js +43 -0
- package/lib/commonjs/e2ee/store.js.map +1 -0
- package/lib/commonjs/helpers/accountName.js +23 -0
- package/lib/commonjs/helpers/accountName.js.map +1 -0
- package/lib/commonjs/helpers/createMessageFromXml.js +19 -4
- package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
- package/lib/commonjs/helpers/createUserNameFromSetUser.js +2 -1
- package/lib/commonjs/helpers/createUserNameFromSetUser.js.map +1 -1
- package/lib/commonjs/helpers/displayName.js +16 -0
- package/lib/commonjs/helpers/displayName.js.map +1 -0
- package/lib/commonjs/helpers/persistCrypto.js +5 -0
- package/lib/commonjs/helpers/persistCrypto.js.map +1 -1
- package/lib/commonjs/helpers/secureKeyValue.js +20 -0
- package/lib/commonjs/helpers/secureKeyValue.js.map +1 -1
- package/lib/commonjs/helpers/videoCache.js +136 -0
- package/lib/commonjs/helpers/videoCache.js.map +1 -0
- package/lib/commonjs/hooks/useLogout.js +8 -0
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +71 -7
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +180 -0
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/main.js +13 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +4 -1
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js +111 -17
- package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +40 -0
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js +16 -3
- package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +13 -6
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +14 -6
- package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +6 -0
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/persistBackend.js +9 -12
- package/lib/commonjs/roomStore/persistBackend.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +8 -1
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/assets/icons.js +3 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +29 -7
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +9 -1
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/EncryptedSendNotice.js +42 -0
- package/lib/module/components/MainComponents/EncryptedSendNotice.js.map +1 -0
- package/lib/module/components/MainComponents/EncryptionCard.js +281 -0
- package/lib/module/components/MainComponents/EncryptionCard.js.map +1 -0
- package/lib/module/components/MainComponents/MediaMessage.js +7 -0
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/ReduxWrapper.js +5 -0
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/SealedAttachment.js +224 -0
- package/lib/module/components/MainComponents/SealedAttachment.js.map +1 -0
- package/lib/module/components/MessageBubble/BottomReplyContainer.js +2 -1
- package/lib/module/components/MessageBubble/BottomReplyContainer.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +69 -9
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +2 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +7 -4
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +161 -18
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/PdfView.js +4 -0
- package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +32 -8
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +4 -0
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js.map +1 -1
- package/lib/module/components/RoomComponents/ChatRoomItem.js +32 -9
- package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/module/components/RoomComponents/LastMessageItem.js +6 -0
- package/lib/module/components/RoomComponents/LastMessageItem.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastAudioMessage.js +2 -2
- package/lib/module/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageFile.js +4 -6
- package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +2 -2
- package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageSealed.js +36 -0
- package/lib/module/components/RoomComponents/styled/LastMessageSealed.js.map +1 -0
- package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +2 -2
- package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
- package/lib/module/components/Thread/ThreadWrapper.js +54 -46
- package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
- package/lib/module/components/UsersList/UsersList.js +2 -1
- package/lib/module/components/UsersList/UsersList.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +4 -2
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/e2ee/crypto.js +170 -0
- package/lib/module/e2ee/crypto.js.map +1 -0
- package/lib/module/e2ee/deviceStore.js +77 -0
- package/lib/module/e2ee/deviceStore.js.map +1 -0
- package/lib/module/e2ee/fileCipher.js +90 -0
- package/lib/module/e2ee/fileCipher.js.map +1 -0
- package/lib/module/e2ee/fileEnvelope.js +66 -0
- package/lib/module/e2ee/fileEnvelope.js.map +1 -0
- package/lib/module/e2ee/index.js +185 -0
- package/lib/module/e2ee/index.js.map +1 -0
- package/lib/module/e2ee/limits.js +5 -0
- package/lib/module/e2ee/limits.js.map +1 -0
- package/lib/module/e2ee/ns.js +4 -0
- package/lib/module/e2ee/ns.js.map +1 -0
- package/lib/module/e2ee/omemo.js +610 -0
- package/lib/module/e2ee/omemo.js.map +1 -0
- package/lib/module/e2ee/protobuf.js +140 -0
- package/lib/module/e2ee/protobuf.js.map +1 -0
- package/lib/module/e2ee/ratchet.js +228 -0
- package/lib/module/e2ee/ratchet.js.map +1 -0
- package/lib/module/e2ee/sealedBody.js +19 -0
- package/lib/module/e2ee/sealedBody.js.map +1 -0
- package/lib/module/e2ee/sealedFiles.js +154 -0
- package/lib/module/e2ee/sealedFiles.js.map +1 -0
- package/lib/module/e2ee/send.js +48 -0
- package/lib/module/e2ee/send.js.map +1 -0
- package/lib/module/e2ee/stanza.js +107 -0
- package/lib/module/e2ee/stanza.js.map +1 -0
- package/lib/module/e2ee/store.js +35 -0
- package/lib/module/e2ee/store.js.map +1 -0
- package/lib/module/helpers/accountName.js +18 -0
- package/lib/module/helpers/accountName.js.map +1 -0
- package/lib/module/helpers/createMessageFromXml.js +19 -4
- package/lib/module/helpers/createMessageFromXml.js.map +1 -1
- package/lib/module/helpers/createUserNameFromSetUser.js +3 -1
- package/lib/module/helpers/createUserNameFromSetUser.js.map +1 -1
- package/lib/module/helpers/displayName.js +11 -0
- package/lib/module/helpers/displayName.js.map +1 -0
- package/lib/module/helpers/persistCrypto.js +4 -0
- package/lib/module/helpers/persistCrypto.js.map +1 -1
- package/lib/module/helpers/secureKeyValue.js +19 -0
- package/lib/module/helpers/secureKeyValue.js.map +1 -1
- package/lib/module/helpers/videoCache.js +125 -0
- package/lib/module/helpers/videoCache.js.map +1 -0
- package/lib/module/hooks/useLogout.js +8 -0
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +71 -7
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/i18n/strings.js +180 -0
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/main.js +1 -0
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +4 -1
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/api-requests/rooms.api.js +109 -18
- package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js +38 -0
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js +16 -3
- package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +13 -6
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +14 -6
- package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
- package/lib/module/networking/xmppClient.js +6 -0
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/persistBackend.js +10 -13
- package/lib/module/roomStore/persistBackend.js.map +1 -1
- package/lib/module/roomStore/persistence.js +8 -1
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/assets/icons.d.ts +8 -0
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/EncryptedSendNotice.d.ts +4 -0
- package/lib/typescript/components/MainComponents/EncryptedSendNotice.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/EncryptionCard.d.ts +10 -0
- package/lib/typescript/components/MainComponents/EncryptionCard.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/SealedAttachment.d.ts +13 -0
- package/lib/typescript/components/MainComponents/SealedAttachment.d.ts.map +1 -0
- package/lib/typescript/components/MessageBubble/BottomReplyContainer.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserSettingsModal/UserSettingsModal.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/LastMessageItem.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastAudioMessage.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageSealed.d.ts +7 -0
- package/lib/typescript/components/RoomComponents/styled/LastMessageSealed.d.ts.map +1 -0
- package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
- package/lib/typescript/components/UsersList/UsersList.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts +1 -0
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/e2ee/crypto.d.ts +28 -0
- package/lib/typescript/e2ee/crypto.d.ts.map +1 -0
- package/lib/typescript/e2ee/deviceStore.d.ts +4 -0
- package/lib/typescript/e2ee/deviceStore.d.ts.map +1 -0
- package/lib/typescript/e2ee/fileCipher.d.ts +7 -0
- package/lib/typescript/e2ee/fileCipher.d.ts.map +1 -0
- package/lib/typescript/e2ee/fileEnvelope.d.ts +27 -0
- package/lib/typescript/e2ee/fileEnvelope.d.ts.map +1 -0
- package/lib/typescript/e2ee/index.d.ts +23 -0
- package/lib/typescript/e2ee/index.d.ts.map +1 -0
- package/lib/typescript/e2ee/limits.d.ts +3 -0
- package/lib/typescript/e2ee/limits.d.ts.map +1 -0
- package/lib/typescript/e2ee/ns.d.ts +2 -0
- package/lib/typescript/e2ee/ns.d.ts.map +1 -0
- package/lib/typescript/e2ee/omemo.d.ts +64 -0
- package/lib/typescript/e2ee/omemo.d.ts.map +1 -0
- package/lib/typescript/e2ee/protobuf.d.ts +25 -0
- package/lib/typescript/e2ee/protobuf.d.ts.map +1 -0
- package/lib/typescript/e2ee/ratchet.d.ts +39 -0
- package/lib/typescript/e2ee/ratchet.d.ts.map +1 -0
- package/lib/typescript/e2ee/sealedBody.d.ts +2 -0
- package/lib/typescript/e2ee/sealedBody.d.ts.map +1 -0
- package/lib/typescript/e2ee/sealedFiles.d.ts +31 -0
- package/lib/typescript/e2ee/sealedFiles.d.ts.map +1 -0
- package/lib/typescript/e2ee/send.d.ts +6 -0
- package/lib/typescript/e2ee/send.d.ts.map +1 -0
- package/lib/typescript/e2ee/stanza.d.ts +8 -0
- package/lib/typescript/e2ee/stanza.d.ts.map +1 -0
- package/lib/typescript/e2ee/store.d.ts +16 -0
- package/lib/typescript/e2ee/store.d.ts.map +1 -0
- package/lib/typescript/helpers/accountName.d.ts +7 -0
- package/lib/typescript/helpers/accountName.d.ts.map +1 -0
- package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
- package/lib/typescript/helpers/createUserNameFromSetUser.d.ts.map +1 -1
- package/lib/typescript/helpers/displayName.d.ts +2 -0
- package/lib/typescript/helpers/displayName.d.ts.map +1 -0
- package/lib/typescript/helpers/persistCrypto.d.ts +1 -0
- package/lib/typescript/helpers/persistCrypto.d.ts.map +1 -1
- package/lib/typescript/helpers/secureKeyValue.d.ts +4 -0
- package/lib/typescript/helpers/secureKeyValue.d.ts.map +1 -1
- package/lib/typescript/helpers/videoCache.d.ts +19 -0
- package/lib/typescript/helpers/videoCache.d.ts.map +1 -0
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +2 -0
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts +4 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts +22 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts +1 -0
- package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistBackend.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/types/models/message.model.d.ts +5 -0
- package/lib/typescript/types/models/message.model.d.ts.map +1 -1
- package/lib/typescript/types/models/room.model.d.ts +5 -0
- package/lib/typescript/types/models/room.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +4 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +8 -4
- package/src/assets/icons.tsx +27 -0
- package/src/components/MainComponents/ChatHeader.tsx +30 -9
- package/src/components/MainComponents/ChatRoom.tsx +11 -1
- package/src/components/MainComponents/EncryptedSendNotice.tsx +35 -0
- package/src/components/MainComponents/EncryptionCard.tsx +287 -0
- package/src/components/MainComponents/MediaMessage.tsx +5 -0
- package/src/components/MainComponents/ReduxWrapper.tsx +5 -0
- package/src/components/MainComponents/SealedAttachment.tsx +251 -0
- package/src/components/MessageBubble/BottomReplyContainer.tsx +2 -1
- package/src/components/MessageBubble/Message.tsx +96 -6
- package/src/components/MessageBubble/MessageInteractions.tsx +2 -3
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +7 -4
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +181 -35
- package/src/components/Modals/FilePreviewModal/PdfView.tsx +4 -0
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +53 -8
- package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +5 -0
- package/src/components/RoomComponents/ChatRoomItem.tsx +23 -11
- package/src/components/RoomComponents/LastMessageItem.tsx +5 -0
- package/src/components/RoomComponents/styled/LastAudioMessage.tsx +3 -1
- package/src/components/RoomComponents/styled/LastMessageFile.tsx +2 -2
- package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +1 -1
- package/src/components/RoomComponents/styled/LastMessageSealed.tsx +31 -0
- package/src/components/RoomComponents/styled/LastMessageVideo.tsx +1 -1
- package/src/components/Thread/ThreadWrapper.tsx +13 -0
- package/src/components/UsersList/UsersList.tsx +2 -1
- package/src/components/styled/SendInput.tsx +5 -2
- package/src/e2ee/crypto.ts +194 -0
- package/src/e2ee/deviceStore.ts +80 -0
- package/src/e2ee/fileCipher.ts +86 -0
- package/src/e2ee/fileEnvelope.ts +115 -0
- package/src/e2ee/index.ts +192 -0
- package/src/e2ee/limits.ts +2 -0
- package/src/e2ee/ns.ts +1 -0
- package/src/e2ee/omemo.ts +802 -0
- package/src/e2ee/protobuf.ts +188 -0
- package/src/e2ee/ratchet.ts +271 -0
- package/src/e2ee/sealedBody.ts +17 -0
- package/src/e2ee/sealedFiles.ts +181 -0
- package/src/e2ee/send.ts +70 -0
- package/src/e2ee/stanza.ts +133 -0
- package/src/e2ee/store.ts +54 -0
- package/src/helpers/accountName.ts +15 -0
- package/src/helpers/createMessageFromXml.ts +31 -6
- package/src/helpers/createUserNameFromSetUser.ts +2 -1
- package/src/helpers/displayName.ts +9 -0
- package/src/helpers/persistCrypto.ts +5 -0
- package/src/helpers/secureKeyValue.ts +15 -0
- package/src/helpers/videoCache.ts +138 -0
- package/src/hooks/useLogout.tsx +9 -0
- package/src/hooks/useSendMessage.tsx +71 -5
- package/src/i18n/strings.ts +180 -0
- package/src/main.ts +2 -0
- package/src/networking/api-requests/auth.api.ts +9 -1
- package/src/networking/api-requests/rooms.api.ts +121 -18
- package/src/networking/xmpp/handleStanzas.xmpp.ts +49 -0
- package/src/networking/xmpp/sendMediaMessage.xmpp.ts +19 -1
- package/src/networking/xmpp/sendTextMessage.xmpp.ts +17 -10
- package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +23 -10
- package/src/networking/xmppClient.ts +6 -0
- package/src/roomStore/persistBackend.ts +8 -11
- package/src/roomStore/persistence.ts +15 -0
- package/src/types/models/message.model.ts +5 -0
- package/src/types/models/room.model.ts +5 -0
- package/src/types/types.ts +4 -0
- package/src/version.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useEffect, useRef, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { withFileToken } from '../../../helpers/secureFileUrl';
|
|
3
3
|
import styled from 'styled-components/native';
|
|
4
4
|
import {
|
|
@@ -16,6 +16,7 @@ import { RootState } from '../../../roomStore';
|
|
|
16
16
|
import { FullScreenImage } from '../../styled/StyledInputComponents/MediaComponents';
|
|
17
17
|
import { setActiveFile } from '../../../roomStore/chatSettingsSlice';
|
|
18
18
|
import {
|
|
19
|
+
ActivityIndicator,
|
|
19
20
|
Alert,
|
|
20
21
|
Text,
|
|
21
22
|
View,
|
|
@@ -33,6 +34,13 @@ import PdfViewer from './PdfView';
|
|
|
33
34
|
import DocumentViewer from './DocumentViewer';
|
|
34
35
|
import AudioMessage from '../../styled/AudioMessage';
|
|
35
36
|
import { isLikelyAudio } from '../../../helpers/mimeToExtension';
|
|
37
|
+
import {
|
|
38
|
+
downloadVideoToCache,
|
|
39
|
+
findCachedVideo,
|
|
40
|
+
isRemoteUrl,
|
|
41
|
+
isStreamingUnsupported,
|
|
42
|
+
markStreamingUnsupported,
|
|
43
|
+
} from '../../../helpers/videoCache';
|
|
36
44
|
import {
|
|
37
45
|
getDisplayFileName,
|
|
38
46
|
getUniqueFileName,
|
|
@@ -52,6 +60,15 @@ const GVIEW_PREVIEWABLE = new Set<string>([
|
|
|
52
60
|
'text/csv',
|
|
53
61
|
'application/rtf',
|
|
54
62
|
]);
|
|
63
|
+
|
|
64
|
+
const isLocalFile = (url: string | undefined | null) =>
|
|
65
|
+
/^file:\/\//i.test(url || '');
|
|
66
|
+
|
|
67
|
+
const fetchToCache = async (url: string, cachePath: string) =>
|
|
68
|
+
isLocalFile(url)
|
|
69
|
+
? { status: 200, uri: url }
|
|
70
|
+
: FileSystem.downloadAsync(withFileToken(url), cachePath);
|
|
71
|
+
|
|
55
72
|
const isGviewPreviewable = (mime: string | undefined | null) => {
|
|
56
73
|
if (!mime) {return false;}
|
|
57
74
|
return GVIEW_PREVIEWABLE.has(mime.toLowerCase().split(';')[0]!.trim());
|
|
@@ -62,52 +79,163 @@ const isGviewPreviewable = (mime: string | undefined | null) => {
|
|
|
62
79
|
// the area with the surrounding letterbox painted as the view's own
|
|
63
80
|
// (transparent → theme) background, NOT black. `textureView` so the play
|
|
64
81
|
// overlay composites on top and nothing is clipped on Android.
|
|
65
|
-
|
|
82
|
+
//
|
|
83
|
+
// The clip is streamed when the server allows it. AVPlayer does not play
|
|
84
|
+
// from a server that ignores byte-range requests (it answers 200 instead of
|
|
85
|
+
// 206 and the player stops with "server is not correctly configured"), so
|
|
86
|
+
// a failed stream falls back to a downloaded copy in the cache — which is
|
|
87
|
+
// also what a reopened video plays from.
|
|
88
|
+
const ModalVideo: React.FC<{ uri: string; mimetype?: string }> = ({
|
|
89
|
+
uri,
|
|
90
|
+
mimetype,
|
|
91
|
+
}) => {
|
|
92
|
+
const theme = useTheme();
|
|
93
|
+
const remote = isRemoteUrl(uri);
|
|
94
|
+
// What the player is given; null until we know where to play from.
|
|
95
|
+
const [source, setSource] = useState<string | null>(remote ? null : uri);
|
|
66
96
|
const [showPlay, setShowPlay] = useState(true);
|
|
97
|
+
// null = not downloading, otherwise 0..1 (0 while the size is unknown).
|
|
98
|
+
const [progress, setProgress] = useState<number | null>(null);
|
|
99
|
+
const [failed, setFailed] = useState(false);
|
|
100
|
+
const wantsPlay = useRef(false);
|
|
101
|
+
const downloadStarted = useRef(false);
|
|
102
|
+
const mounted = useRef(true);
|
|
103
|
+
useEffect(
|
|
104
|
+
() => () => {
|
|
105
|
+
mounted.current = false;
|
|
106
|
+
},
|
|
107
|
+
[]
|
|
108
|
+
);
|
|
67
109
|
|
|
68
|
-
const
|
|
110
|
+
const download = useCallback(() => {
|
|
111
|
+
if (downloadStarted.current) {return;}
|
|
112
|
+
downloadStarted.current = true;
|
|
113
|
+
setProgress(0);
|
|
114
|
+
downloadVideoToCache(uri, mimetype, (fraction) => {
|
|
115
|
+
if (mounted.current) {setProgress(fraction);}
|
|
116
|
+
})
|
|
117
|
+
.then((localUri) => {
|
|
118
|
+
if (!mounted.current) {return;}
|
|
119
|
+
setProgress(null);
|
|
120
|
+
setSource(localUri);
|
|
121
|
+
})
|
|
122
|
+
.catch((err) => {
|
|
123
|
+
console.warn('video download failed', err);
|
|
124
|
+
if (!mounted.current) {return;}
|
|
125
|
+
setProgress(null);
|
|
126
|
+
setFailed(true);
|
|
127
|
+
});
|
|
128
|
+
}, [mimetype, uri]);
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (!remote) {return;}
|
|
132
|
+
let active = true;
|
|
133
|
+
findCachedVideo(uri, mimetype).then((cached) => {
|
|
134
|
+
if (!active) {return;}
|
|
135
|
+
if (cached) {
|
|
136
|
+
setSource(cached);
|
|
137
|
+
} else if (isStreamingUnsupported(uri)) {
|
|
138
|
+
download();
|
|
139
|
+
} else {
|
|
140
|
+
setSource(uri);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
return () => {
|
|
144
|
+
active = false;
|
|
145
|
+
};
|
|
146
|
+
}, [download, mimetype, remote, uri]);
|
|
147
|
+
|
|
148
|
+
const player = useVideoPlayer(source, (p) => {
|
|
69
149
|
p.muted = false;
|
|
150
|
+
// A player made for the downloaded copy picks up a play the user
|
|
151
|
+
// already asked for.
|
|
152
|
+
if (wantsPlay.current) {p.play();}
|
|
70
153
|
});
|
|
71
154
|
|
|
72
155
|
useEffect(() => {
|
|
73
|
-
const
|
|
156
|
+
const playing = player.addListener('playingChange', ({ isPlaying }) => {
|
|
74
157
|
if (isPlaying) {setShowPlay(false);}
|
|
75
158
|
});
|
|
76
|
-
|
|
77
|
-
|
|
159
|
+
const status = player.addListener('statusChange', (event) => {
|
|
160
|
+
if (event.status !== 'error') {return;}
|
|
161
|
+
if (source === uri && remote) {
|
|
162
|
+
markStreamingUnsupported(uri);
|
|
163
|
+
download();
|
|
164
|
+
} else {
|
|
165
|
+
setFailed(true);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return () => {
|
|
169
|
+
playing.remove();
|
|
170
|
+
status.remove();
|
|
171
|
+
};
|
|
172
|
+
}, [download, player, remote, source, uri]);
|
|
78
173
|
|
|
79
174
|
const handlePlay = () => {
|
|
175
|
+
wantsPlay.current = true;
|
|
80
176
|
setShowPlay(false);
|
|
81
177
|
player.play();
|
|
82
178
|
};
|
|
83
179
|
|
|
180
|
+
if (failed) {
|
|
181
|
+
return (
|
|
182
|
+
<View style={styles.videoMessage}>
|
|
183
|
+
<Text style={{ fontSize: 16, fontWeight: '600', color: theme.text }}>
|
|
184
|
+
This video can't be played
|
|
185
|
+
</Text>
|
|
186
|
+
<Text style={{ color: theme.textSecondary, textAlign: 'center' }}>
|
|
187
|
+
Tap the save icon above to download it.
|
|
188
|
+
</Text>
|
|
189
|
+
</View>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const loading = progress !== null || source === null;
|
|
194
|
+
|
|
84
195
|
return (
|
|
85
196
|
<View style={{ flex: 1, width: '100%' }}>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
style={
|
|
104
|
-
|
|
105
|
-
<View style={styles.playOverlay}>
|
|
106
|
-
<View style={styles.playButton}>
|
|
107
|
-
<PlayIcon width={28} height={28} />
|
|
108
|
-
</View>
|
|
197
|
+
{/* No surface while the copy downloads: the failed stream would
|
|
198
|
+
show the system's "can't play" glyph under the spinner. */}
|
|
199
|
+
{!loading && (
|
|
200
|
+
<VideoView
|
|
201
|
+
player={player}
|
|
202
|
+
style={{ flex: 1, backgroundColor: 'transparent' }}
|
|
203
|
+
contentFit="contain"
|
|
204
|
+
nativeControls
|
|
205
|
+
surfaceType="textureView"
|
|
206
|
+
// Fullscreen stays available by default on both expo-video lines:
|
|
207
|
+
// `allowsFullscreen` (SDK 54, default true) was replaced by
|
|
208
|
+
// `fullscreenOptions.enable` (SDK 57, default true). Passing
|
|
209
|
+
// neither keeps this file compiling against both.
|
|
210
|
+
/>
|
|
211
|
+
)}
|
|
212
|
+
{loading ? (
|
|
213
|
+
<View style={styles.playOverlay} pointerEvents="none">
|
|
214
|
+
<View style={styles.playButton}>
|
|
215
|
+
<ActivityIndicator color="#FFFFFF" />
|
|
109
216
|
</View>
|
|
110
|
-
|
|
217
|
+
{!!progress && (
|
|
218
|
+
<Text style={[styles.progress, { color: theme.textSecondary }]}>
|
|
219
|
+
{Math.round(progress * 100)}%
|
|
220
|
+
</Text>
|
|
221
|
+
)}
|
|
222
|
+
</View>
|
|
223
|
+
) : (
|
|
224
|
+
showPlay && (
|
|
225
|
+
// Play affordance shown immediately on open; tapping starts
|
|
226
|
+
// playback and the native controls take over.
|
|
227
|
+
<TouchableOpacity
|
|
228
|
+
activeOpacity={0.8}
|
|
229
|
+
onPress={handlePlay}
|
|
230
|
+
style={StyleSheet.absoluteFill}
|
|
231
|
+
>
|
|
232
|
+
<View style={styles.playOverlay}>
|
|
233
|
+
<View style={styles.playButton}>
|
|
234
|
+
<PlayIcon width={28} height={28} />
|
|
235
|
+
</View>
|
|
236
|
+
</View>
|
|
237
|
+
</TouchableOpacity>
|
|
238
|
+
)
|
|
111
239
|
)}
|
|
112
240
|
</View>
|
|
113
241
|
);
|
|
@@ -175,7 +303,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
175
303
|
|
|
176
304
|
try {
|
|
177
305
|
const filePath = FileSystem.cacheDirectory + displayFileName;
|
|
178
|
-
const download = await
|
|
306
|
+
const download = await fetchToCache(activeFile.fileURL, filePath);
|
|
179
307
|
|
|
180
308
|
if (download.status === 200) {
|
|
181
309
|
await getMediaLibrary()?.saveToLibraryAsync(download.uri);
|
|
@@ -222,7 +350,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
222
350
|
const saveFileToDownloads = async () => {
|
|
223
351
|
try {
|
|
224
352
|
const filePath = FileSystem.cacheDirectory + displayFileName;
|
|
225
|
-
const download = await
|
|
353
|
+
const download = await fetchToCache(activeFile.fileURL, filePath);
|
|
226
354
|
|
|
227
355
|
if (download.status !== 200) {
|
|
228
356
|
Alert.alert('Error', 'Failed to save the file.');
|
|
@@ -332,7 +460,14 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
332
460
|
/>
|
|
333
461
|
);
|
|
334
462
|
case activeFile.mimetype.startsWith('video/'):
|
|
335
|
-
return
|
|
463
|
+
return (
|
|
464
|
+
<ModalVideo
|
|
465
|
+
// Remount per file: the player state belongs to one clip.
|
|
466
|
+
key={activeFile.fileURL}
|
|
467
|
+
uri={withFileToken(activeFile.fileURL)}
|
|
468
|
+
mimetype={activeFile.mimetype}
|
|
469
|
+
/>
|
|
470
|
+
);
|
|
336
471
|
case activeFile.mimetype.includes('application/octet-stream'):
|
|
337
472
|
return (
|
|
338
473
|
<View
|
|
@@ -394,13 +529,14 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
394
529
|
/>
|
|
395
530
|
</View>
|
|
396
531
|
);
|
|
397
|
-
case activeFile.mimetype === 'application/pdf'
|
|
532
|
+
case activeFile.mimetype === 'application/pdf' &&
|
|
533
|
+
!(Platform.OS === 'android' && isLocalFile(activeFile.fileURL)):
|
|
398
534
|
return <PdfViewer pdfUrl={withFileToken(activeFile.fileURL)} />;
|
|
399
535
|
default: {
|
|
400
536
|
// Office docs (.docx / .xlsx / .pptx / .doc / .xls / .ppt /
|
|
401
537
|
// .txt / .csv / .rtf) → render inline via Google's gview embed
|
|
402
538
|
// — fixes the "blank preview" complaint for docs (bug #9).
|
|
403
|
-
if (isGviewPreviewable(activeFile.mimetype)) {
|
|
539
|
+
if (isGviewPreviewable(activeFile.mimetype) && !isLocalFile(activeFile.fileURL)) {
|
|
404
540
|
return (
|
|
405
541
|
<DocumentViewer
|
|
406
542
|
url={activeFile.fileURL}
|
|
@@ -486,6 +622,16 @@ const styles = StyleSheet.create({
|
|
|
486
622
|
justifyContent: 'center',
|
|
487
623
|
alignItems: 'center',
|
|
488
624
|
},
|
|
625
|
+
progress: {
|
|
626
|
+
marginTop: 10,
|
|
627
|
+
fontSize: 13,
|
|
628
|
+
fontWeight: '600',
|
|
629
|
+
},
|
|
630
|
+
videoMessage: {
|
|
631
|
+
alignItems: 'center',
|
|
632
|
+
gap: 8,
|
|
633
|
+
padding: 20,
|
|
634
|
+
},
|
|
489
635
|
});
|
|
490
636
|
|
|
491
637
|
export default FilePreviewModal;
|
|
@@ -25,6 +25,10 @@ const PdfViewer: React.FC<PdfViewerProps> = ({ pdfUrl }) => {
|
|
|
25
25
|
let cancelled = false;
|
|
26
26
|
const run = async () => {
|
|
27
27
|
try {
|
|
28
|
+
if (/^file:\/\//i.test(pdfUrl)) {
|
|
29
|
+
setLocalUri(pdfUrl);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
28
32
|
const target = FileSystem.cacheDirectory + `pdf-${Date.now()}.pdf`;
|
|
29
33
|
const result = await FileSystem.downloadAsync(withFileToken(pdfUrl), target);
|
|
30
34
|
if (cancelled) {return;}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
EditIcon,
|
|
18
18
|
IconDoc,
|
|
19
19
|
LeaveIcon,
|
|
20
|
+
LockIcon,
|
|
20
21
|
LogoutIcon,
|
|
21
22
|
ProfileIcon,
|
|
22
23
|
ShareIcon,
|
|
@@ -43,7 +44,21 @@ import {
|
|
|
43
44
|
import { addRoomViaApi, setCurrentRoom } from '../../../roomStore/roomsSlice';
|
|
44
45
|
import { runLogoutFlow } from '../../Menu/HeaderRoomListMenu';
|
|
45
46
|
import { useLogout } from '../../../hooks/useLogout';
|
|
46
|
-
import {
|
|
47
|
+
import {
|
|
48
|
+
ApiRoom,
|
|
49
|
+
ownAppId,
|
|
50
|
+
postPrivateRoom,
|
|
51
|
+
} from '../../../networking/api-requests/rooms.api';
|
|
52
|
+
import EncryptionCard from '../../MainComponents/EncryptionCard';
|
|
53
|
+
import { accountNameOf } from '../../../helpers/accountName';
|
|
54
|
+
import { composeName } from '../../../helpers/displayName';
|
|
55
|
+
import { isUnresolvedSenderId } from '../../../helpers/isUnresolvedSenderId';
|
|
56
|
+
|
|
57
|
+
/** A name, unless it is only the account's id standing in for one. */
|
|
58
|
+
const nameOrNothing = (name?: string | null): string => {
|
|
59
|
+
const trimmed = String(name ?? '').trim();
|
|
60
|
+
return isUnresolvedSenderId(trimmed) ? '' : trimmed;
|
|
61
|
+
};
|
|
47
62
|
import {
|
|
48
63
|
getUserFiles,
|
|
49
64
|
isMediaFile,
|
|
@@ -196,8 +211,8 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
196
211
|
|
|
197
212
|
const handleShare = useCallback(async () => {
|
|
198
213
|
const name =
|
|
199
|
-
profileUser?.name ||
|
|
200
|
-
|
|
214
|
+
nameOrNothing(profileUser?.name) ||
|
|
215
|
+
composeName(profileUser?.firstName, profileUser?.lastName);
|
|
201
216
|
const id =
|
|
202
217
|
profileUser?.userJID ||
|
|
203
218
|
profileUser?.defaultWallet?.walletAddress ||
|
|
@@ -238,7 +253,7 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
238
253
|
}
|
|
239
254
|
};
|
|
240
255
|
|
|
241
|
-
const
|
|
256
|
+
const openPrivateRoom = useCallback(async (e2ee: boolean) => {
|
|
242
257
|
showToast({
|
|
243
258
|
id: Date.now().toString(),
|
|
244
259
|
title: 'Room creation',
|
|
@@ -248,7 +263,8 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
248
263
|
});
|
|
249
264
|
if (config?.newArch) {
|
|
250
265
|
const newRoom = await postPrivateRoom(
|
|
251
|
-
selectedUser?.userJID ?? (selectedUser?.id || '')
|
|
266
|
+
selectedUser?.userJID ?? (selectedUser?.id || ''),
|
|
267
|
+
e2ee
|
|
252
268
|
);
|
|
253
269
|
handleRoomCreation(newRoom, 2);
|
|
254
270
|
} else {
|
|
@@ -283,6 +299,17 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
283
299
|
dispatch(setActiveModal(undefined));
|
|
284
300
|
}, [selectedUser]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
285
301
|
|
|
302
|
+
const handlePrivateMessage = useCallback(
|
|
303
|
+
() => openPrivateRoom(false),
|
|
304
|
+
[openPrivateRoom]
|
|
305
|
+
);
|
|
306
|
+
const handleEncryptedPrivateMessage = useCallback(
|
|
307
|
+
() => openPrivateRoom(true),
|
|
308
|
+
[openPrivateRoom]
|
|
309
|
+
);
|
|
310
|
+
const canStartEncrypted =
|
|
311
|
+
config?.e2ee?.enabled === true && !!config?.newArch;
|
|
312
|
+
|
|
286
313
|
const openFile = (file: UserFile) => {
|
|
287
314
|
dispatch(
|
|
288
315
|
setActiveFile({
|
|
@@ -333,6 +360,16 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
333
360
|
icon: (color: string) => <ChatIcon color={color} />,
|
|
334
361
|
onPress: handlePrivateMessage,
|
|
335
362
|
},
|
|
363
|
+
...(canStartEncrypted
|
|
364
|
+
? [
|
|
365
|
+
{
|
|
366
|
+
key: 'encrypted-message',
|
|
367
|
+
label: t('action.encryptedMessage'),
|
|
368
|
+
icon: (color: string) => <LockIcon color={color} />,
|
|
369
|
+
onPress: handleEncryptedPrivateMessage,
|
|
370
|
+
},
|
|
371
|
+
]
|
|
372
|
+
: []),
|
|
336
373
|
]),
|
|
337
374
|
{
|
|
338
375
|
key: 'share',
|
|
@@ -341,7 +378,7 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
341
378
|
onPress: handleShare,
|
|
342
379
|
},
|
|
343
380
|
],
|
|
344
|
-
[isOwnProfile, t, handleShare, handlePrivateMessage, handleLogout] // eslint-disable-line react-hooks/exhaustive-deps
|
|
381
|
+
[isOwnProfile, t, handleShare, handlePrivateMessage, handleEncryptedPrivateMessage, canStartEncrypted, handleLogout] // eslint-disable-line react-hooks/exhaustive-deps
|
|
345
382
|
);
|
|
346
383
|
|
|
347
384
|
// Collapsed, the hero's round buttons are gone — the "…" menu carries
|
|
@@ -373,8 +410,8 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
373
410
|
}
|
|
374
411
|
|
|
375
412
|
const displayName =
|
|
376
|
-
profileUser?.name ||
|
|
377
|
-
|
|
413
|
+
nameOrNothing(profileUser?.name) ||
|
|
414
|
+
composeName(profileUser?.firstName, profileUser?.lastName) ||
|
|
378
415
|
t('modal.profile.title');
|
|
379
416
|
const heroImage =
|
|
380
417
|
appendFileToken(profileUser?.profileImage, fileToken) || null;
|
|
@@ -529,6 +566,14 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
529
566
|
</Text>
|
|
530
567
|
</View>
|
|
531
568
|
|
|
569
|
+
{!isOwnProfile && config?.e2ee?.enabled === true && (
|
|
570
|
+
<EncryptionCard
|
|
571
|
+
account={accountNameOf(profileUser, ownAppId())}
|
|
572
|
+
style={styles.card}
|
|
573
|
+
testID="user-profile-e2ee"
|
|
574
|
+
/>
|
|
575
|
+
)}
|
|
576
|
+
|
|
532
577
|
{tabs.length > 0 && (
|
|
533
578
|
<View style={styles.card}>
|
|
534
579
|
<View style={styles.tabsRow}>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** @format */
|
|
2
2
|
|
|
3
|
+
import EncryptionCard from '../../MainComponents/EncryptionCard';
|
|
3
4
|
import React, { useCallback, useMemo } from 'react';
|
|
4
5
|
import {
|
|
5
6
|
StyleSheet,
|
|
@@ -159,6 +160,10 @@ const UserSettingsModal: React.FC<UserSettingsModalProps> = ({
|
|
|
159
160
|
</View>
|
|
160
161
|
) : null}
|
|
161
162
|
|
|
163
|
+
{config?.e2ee?.enabled === true ? (
|
|
164
|
+
<EncryptionCard style={styles.card} testID="settings-e2ee" />
|
|
165
|
+
) : null}
|
|
166
|
+
|
|
162
167
|
{options.map((option) => (
|
|
163
168
|
<TouchableOpacity
|
|
164
169
|
key={option.key}
|
|
@@ -20,6 +20,10 @@ import LastMessageItem from './LastMessageItem';
|
|
|
20
20
|
import { LastRoomMessageText } from './styled/StyledRoomComponents';
|
|
21
21
|
import { useTheme } from '../../hooks/useTheme';
|
|
22
22
|
import { resolveTheme } from '../../theme/theme';
|
|
23
|
+
import { LockIcon } from '../../assets/icons';
|
|
24
|
+
import { useT } from '../../i18n/useT';
|
|
25
|
+
import { composeName } from '../../helpers/displayName';
|
|
26
|
+
import { isUnresolvedSenderId } from '../../helpers/isUnresolvedSenderId';
|
|
23
27
|
|
|
24
28
|
interface ChatRoomItemProps {
|
|
25
29
|
chat: IRoom;
|
|
@@ -37,6 +41,7 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
37
41
|
// Rows can be rendered with an explicit `config` prop (tests, hosts
|
|
38
42
|
// composing their own list); honour its colours over the store's.
|
|
39
43
|
const storeTheme = useTheme();
|
|
44
|
+
const t = useT();
|
|
40
45
|
const theme = useMemo(
|
|
41
46
|
() => (config ? resolveTheme(config) : storeTheme),
|
|
42
47
|
[config, storeTheme]
|
|
@@ -61,19 +66,12 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
61
66
|
const localId = rawUserId.split('@')[0];
|
|
62
67
|
const entry = usersSet?.[localId] ?? usersSet?.[rawUserId];
|
|
63
68
|
const fromUsersSet = entry
|
|
64
|
-
?
|
|
69
|
+
? composeName(entry.firstName, entry.lastName)
|
|
65
70
|
: '';
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
// a renamed user updates here too. The message's own `name` is the
|
|
69
|
-
// fallback that carries broadcast/system senders ("Ethora"), which
|
|
70
|
-
// never appear in usersSet.
|
|
72
|
+
const ownName = String(message?.user?.name || '').trim();
|
|
71
73
|
const safeName =
|
|
72
|
-
fromUsersSet ||
|
|
73
|
-
String(message?.user?.name || '').trim() ||
|
|
74
|
-
localId ||
|
|
75
|
-
rawUserId ||
|
|
76
|
-
'Unknown';
|
|
74
|
+
fromUsersSet || (isUnresolvedSenderId(ownName) ? '' : ownName);
|
|
77
75
|
|
|
78
76
|
return {
|
|
79
77
|
...message,
|
|
@@ -176,7 +174,21 @@ const ChatRoomItem: React.FC<ChatRoomItemProps> = ({
|
|
|
176
174
|
}}
|
|
177
175
|
>
|
|
178
176
|
<ChatInfo>
|
|
179
|
-
<
|
|
177
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
|
|
178
|
+
<View style={{ flexShrink: 1 }}>
|
|
179
|
+
<ChatName text={displayName} />
|
|
180
|
+
</View>
|
|
181
|
+
{chat?.e2ee && (
|
|
182
|
+
<View
|
|
183
|
+
accessible
|
|
184
|
+
accessibilityRole="image"
|
|
185
|
+
accessibilityLabel={t('e2ee.roomEncrypted')}
|
|
186
|
+
testID="room-e2ee-lock"
|
|
187
|
+
>
|
|
188
|
+
<LockIcon width={13} height={13} color={theme.textSecondary} />
|
|
189
|
+
</View>
|
|
190
|
+
)}
|
|
191
|
+
</View>
|
|
180
192
|
</ChatInfo>
|
|
181
193
|
{stamp ? (
|
|
182
194
|
<UserCount
|
|
@@ -6,6 +6,7 @@ import LastMessagePhoto from './styled/LastMessagePhoto';
|
|
|
6
6
|
import LastMessageEmoji from './styled/LastMessageEmoji';
|
|
7
7
|
import LastMessageFile from './styled/LastMessageFile';
|
|
8
8
|
import LastAudioMessage from './styled/LastAudioMessage';
|
|
9
|
+
import LastMessageSealed from './styled/LastMessageSealed';
|
|
9
10
|
|
|
10
11
|
interface LastMessageItemProps {
|
|
11
12
|
lastMessage: LastMessage;
|
|
@@ -14,6 +15,10 @@ interface LastMessageItemProps {
|
|
|
14
15
|
const LastMessageItem: FC<LastMessageItemProps> = ({ lastMessage }) => {
|
|
15
16
|
const { body, emoji, mimetype } = lastMessage;
|
|
16
17
|
|
|
18
|
+
if (lastMessage?.clientEncrypted === 'true') {
|
|
19
|
+
return <LastMessageSealed {...lastMessage} />;
|
|
20
|
+
}
|
|
21
|
+
|
|
17
22
|
if (mimetype) {
|
|
18
23
|
if (mimetype.startsWith('image/')) {
|
|
19
24
|
return <LastMessagePhoto {...lastMessage} />;
|
|
@@ -33,7 +33,9 @@ const LastAudioMessage: FC<LastMessageEmojiProps> = ({ user, body }) => {
|
|
|
33
33
|
const theme = useTheme();
|
|
34
34
|
return (
|
|
35
35
|
<LastRoomMessageContainer>
|
|
36
|
-
|
|
36
|
+
{!!user?.name && (
|
|
37
|
+
<LastRoomMessageName numberOfLines={1}>{user.name}</LastRoomMessageName>
|
|
38
|
+
)}
|
|
37
39
|
<AudioRow>
|
|
38
40
|
<PlayButton>
|
|
39
41
|
<PlayIcon width={10} height={10} color={theme.dark ? theme.text : '#1F2937'} />
|
|
@@ -43,7 +43,7 @@ const LastMessageFile: FC<LastMessageFileProps> = ({
|
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
45
|
<LastRoomMessageContainer>
|
|
46
|
-
<LastRoomMessageName>{user
|
|
46
|
+
{!!user?.name && <LastRoomMessageName>{user.name}:</LastRoomMessageName>}
|
|
47
47
|
<View
|
|
48
48
|
style={{
|
|
49
49
|
display: 'flex',
|
|
@@ -67,7 +67,7 @@ const LastMessageFile: FC<LastMessageFileProps> = ({
|
|
|
67
67
|
}}
|
|
68
68
|
/>
|
|
69
69
|
) : (
|
|
70
|
-
<FileIcon
|
|
70
|
+
<FileIcon width={20} height={20} />
|
|
71
71
|
)}
|
|
72
72
|
<LastRoomMessageText>{displayName}</LastRoomMessageText>
|
|
73
73
|
</View>
|
|
@@ -47,7 +47,7 @@ const LastMessagePhoto: FC<LastMessagePhotoProps> = ({
|
|
|
47
47
|
: 'file';
|
|
48
48
|
return (
|
|
49
49
|
<LastRoomMessageContainer>
|
|
50
|
-
<LastRoomMessageName>{user
|
|
50
|
+
{!!user?.name && <LastRoomMessageName>{user.name}:</LastRoomMessageName>}
|
|
51
51
|
<View
|
|
52
52
|
style={{
|
|
53
53
|
display: 'flex',
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React, { FC } from 'react';
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { LastMessage } from '../../../types/types';
|
|
4
|
+
import {
|
|
5
|
+
LastRoomMessageContainer,
|
|
6
|
+
LastRoomMessageName,
|
|
7
|
+
LastRoomMessageText,
|
|
8
|
+
} from './StyledRoomComponents';
|
|
9
|
+
import { LockIcon } from '../../../assets/icons';
|
|
10
|
+
import { useTheme } from '../../../hooks/useTheme';
|
|
11
|
+
import { useT } from '../../../i18n/useT';
|
|
12
|
+
|
|
13
|
+
interface LastMessageSealedProps extends Pick<LastMessage, 'user'> {}
|
|
14
|
+
|
|
15
|
+
const LastMessageSealed: FC<LastMessageSealedProps> = ({ user }) => {
|
|
16
|
+
const t = useT();
|
|
17
|
+
const theme = useTheme();
|
|
18
|
+
const name = user?.name;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<LastRoomMessageContainer>
|
|
22
|
+
{!!name && <LastRoomMessageName>{name}:</LastRoomMessageName>}
|
|
23
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
|
|
24
|
+
<LockIcon width={14} height={14} color={theme.textSecondary} />
|
|
25
|
+
<LastRoomMessageText>{t('media.sealedFile')}</LastRoomMessageText>
|
|
26
|
+
</View>
|
|
27
|
+
</LastRoomMessageContainer>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default LastMessageSealed;
|
|
@@ -62,7 +62,7 @@ const LastMessageVideo: FC<LastMessageVideoProps> = ({
|
|
|
62
62
|
: 'file';
|
|
63
63
|
return (
|
|
64
64
|
<LastRoomMessageContainer>
|
|
65
|
-
<LastRoomMessageName>{user
|
|
65
|
+
{!!user?.name && <LastRoomMessageName>{user.name}:</LastRoomMessageName>}
|
|
66
66
|
<View
|
|
67
67
|
style={{
|
|
68
68
|
display: 'flex',
|
|
@@ -23,6 +23,8 @@ import MessageList from '../MainComponents/MessageList';
|
|
|
23
23
|
import ModalHeaderComponent from '../Modals/ModalHeaderComponent';
|
|
24
24
|
import { setCloseActiveMessage, setEditAction } from '../../roomStore/roomsSlice';
|
|
25
25
|
import { EditWrapper } from '../MainComponents/EditWrapper';
|
|
26
|
+
import EncryptedSendNotice from '../MainComponents/EncryptedSendNotice';
|
|
27
|
+
import { MAX_SEAL_BYTES } from '../../e2ee/limits';
|
|
26
28
|
import { useSendMessage } from '../../hooks/useSendMessage';
|
|
27
29
|
import { createMainMessageForThread } from '../../helpers/createMainMessageForThread';
|
|
28
30
|
import { useChatSettingState } from '../../hooks/useChatSettingState';
|
|
@@ -85,6 +87,10 @@ const ThreadWrapper: FC<ThreadWrapperProps> = ({
|
|
|
85
87
|
// Same field the room header and the list show (`name` can be the id).
|
|
86
88
|
const roomDisplayName = String(room?.title || room?.name || 'chat').trim();
|
|
87
89
|
|
|
90
|
+
const e2eeRoom = !!room?.e2ee;
|
|
91
|
+
const e2eeOn = config?.e2ee?.enabled === true;
|
|
92
|
+
const maxMediaBytes = e2eeRoom && e2eeOn ? MAX_SEAL_BYTES : undefined;
|
|
93
|
+
|
|
88
94
|
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
89
95
|
const [isChecked, setIsChecked] = useState(false);
|
|
90
96
|
|
|
@@ -233,6 +239,10 @@ const ThreadWrapper: FC<ThreadWrapperProps> = ({
|
|
|
233
239
|
DockTag === View ? { paddingBottom: dockPadding } : null,
|
|
234
240
|
]}
|
|
235
241
|
>
|
|
242
|
+
{e2eeRoom && !e2eeOn && !editAction?.isEdit ? (
|
|
243
|
+
<EncryptedSendNotice />
|
|
244
|
+
) : (
|
|
245
|
+
<>
|
|
236
246
|
<Pressable
|
|
237
247
|
testID="thread-also-send"
|
|
238
248
|
accessibilityRole="checkbox"
|
|
@@ -274,11 +284,14 @@ const ThreadWrapper: FC<ThreadWrapperProps> = ({
|
|
|
274
284
|
sendMedia={sendMedia}
|
|
275
285
|
sendMessage={editAction?.isEdit ? sendEditMessage : sendMessage}
|
|
276
286
|
config={config}
|
|
287
|
+
maxMediaBytes={maxMediaBytes}
|
|
277
288
|
onFocus={sendStartComposing}
|
|
278
289
|
onBlur={sendEndComposing}
|
|
279
290
|
isLoading={!!room?.isLoading}
|
|
280
291
|
isMessageProcessing={isLastMessageFromUserAndProcessing(roomJid)}
|
|
281
292
|
/>
|
|
293
|
+
</>
|
|
294
|
+
)}
|
|
282
295
|
</DockTag>
|
|
283
296
|
</KeyboardAvoidingView>
|
|
284
297
|
|