@ethora/chat-component-rn 26.8.6 → 26.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/README.md +64 -2
- 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/ChatWrapper.js +5 -3
- package/lib/commonjs/components/MainComponents/ChatWrapper.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 +13 -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/Menu/HeaderRoomListMenu.js +26 -13
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/commonjs/components/MenuRoom/MenuRoom.js +5 -3
- package/lib/commonjs/components/MenuRoom/MenuRoom.js.map +1 -1
- 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 +69 -9
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +7 -4
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +8 -5
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js +2 -2
- package/lib/commonjs/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +166 -21
- 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/Modal/Modal.js +33 -11
- package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js +8 -8
- package/lib/commonjs/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
- package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +279 -0
- package/lib/commonjs/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
- package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
- package/lib/commonjs/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
- package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
- package/lib/commonjs/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +50 -15
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js +121 -0
- package/lib/commonjs/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
- package/lib/commonjs/components/Modals/UserSettingsModal/UserSettingsModal.js +10 -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 +56 -46
- 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/constants/MODAL_COMPONENTS.js +2 -0
- package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
- package/lib/commonjs/helpers/constants/MODAL_TYPES.js +1 -0
- package/lib/commonjs/helpers/constants/MODAL_TYPES.js.map +1 -1
- 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/preferencesStorage.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/useChatSettingState.js +2 -0
- package/lib/commonjs/hooks/useChatSettingState.js.map +1 -1
- package/lib/commonjs/hooks/useChatWrapperInit.js +4 -0
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- 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 +367 -1
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/i18n/useT.js +8 -4
- package/lib/commonjs/i18n/useT.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/api-requests/user.api.js +13 -0
- package/lib/commonjs/networking/api-requests/user.api.js.map +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +1 -1
- package/lib/commonjs/networking/stanzaHandlers.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/chatSettingsSlice.js +7 -2
- package/lib/commonjs/roomStore/chatSettingsSlice.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/services/languageSettings.js +177 -0
- package/lib/commonjs/services/languageSettings.js.map +1 -0
- 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/ChatWrapper.js +5 -3
- package/lib/module/components/MainComponents/ChatWrapper.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 +14 -1
- 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/Menu/HeaderRoomListMenu.js +26 -13
- package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/module/components/MenuRoom/MenuRoom.js +5 -3
- package/lib/module/components/MenuRoom/MenuRoom.js.map +1 -1
- 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 +72 -12
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +7 -4
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +8 -5
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js +2 -2
- package/lib/module/components/Modals/ChatProfileModal/ReportChatModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +168 -23
- 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/Modal/Modal.js +33 -11
- package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/module/components/Modals/NewChatModal/NewChatModal.js +8 -8
- package/lib/module/components/Modals/NewChatModal/NewChatModal.js.map +1 -1
- package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js +274 -0
- package/lib/module/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.js.map +1 -0
- package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js +10 -8
- package/lib/module/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.js.map +1 -1
- package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js +13 -11
- package/lib/module/components/Modals/SettingsModals/Visibility/VisibilityModal.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +54 -18
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js +116 -0
- package/lib/module/components/Modals/UserSettingsModal/LanguageCard.js.map +1 -0
- package/lib/module/components/Modals/UserSettingsModal/UserSettingsModal.js +10 -1
- 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 +57 -47
- 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/constants/MODAL_COMPONENTS.js +2 -0
- package/lib/module/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
- package/lib/module/helpers/constants/MODAL_TYPES.js +1 -0
- package/lib/module/helpers/constants/MODAL_TYPES.js.map +1 -1
- 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/preferencesStorage.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/useChatSettingState.js +2 -0
- package/lib/module/hooks/useChatSettingState.js.map +1 -1
- package/lib/module/hooks/useChatWrapperInit.js +4 -0
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- 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 +367 -1
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/i18n/useT.js +8 -4
- package/lib/module/i18n/useT.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/api-requests/user.api.js +12 -0
- package/lib/module/networking/api-requests/user.api.js.map +1 -1
- package/lib/module/networking/stanzaHandlers.js +1 -1
- package/lib/module/networking/stanzaHandlers.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/chatSettingsSlice.js +5 -1
- package/lib/module/roomStore/chatSettingsSlice.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/services/languageSettings.js +164 -0
- package/lib/module/services/languageSettings.js.map +1 -0
- 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/ChatWrapper.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/Menu/HeaderRoomListMenu.d.ts +7 -1
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
- package/lib/typescript/components/MenuRoom/MenuRoom.d.ts.map +1 -1
- 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/Modal/Modal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts +15 -0
- package/lib/typescript/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.d.ts.map +1 -0
- package/lib/typescript/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/SettingsModals/Visibility/VisibilityModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts +14 -0
- package/lib/typescript/components/Modals/UserSettingsModal/LanguageCard.d.ts.map +1 -0
- 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/constants/MODAL_COMPONENTS.d.ts.map +1 -1
- package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts +1 -0
- package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts.map +1 -1
- 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/preferencesStorage.d.ts +4 -0
- package/lib/typescript/helpers/preferencesStorage.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/useChatSettingState.d.ts +1 -0
- package/lib/typescript/hooks/useChatSettingState.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- 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/i18n/useT.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/api-requests/user.api.d.ts +6 -0
- package/lib/typescript/networking/api-requests/user.api.d.ts.map +1 -1
- package/lib/typescript/networking/stanzaHandlers.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/chatSettingsSlice.d.ts +8 -1
- package/lib/typescript/roomStore/chatSettingsSlice.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/services/languageSettings.d.ts +29 -0
- package/lib/typescript/services/languageSettings.d.ts.map +1 -0
- 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/models/user.model.d.ts +4 -0
- package/lib/typescript/types/models/user.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +25 -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/ChatWrapper.tsx +5 -3
- 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 +11 -0
- package/src/components/MainComponents/SealedAttachment.tsx +251 -0
- package/src/components/Menu/HeaderRoomListMenu.tsx +40 -13
- package/src/components/MenuRoom/MenuRoom.tsx +5 -3
- package/src/components/MessageBubble/BottomReplyContainer.tsx +2 -1
- package/src/components/MessageBubble/Message.tsx +99 -9
- package/src/components/MessageBubble/MessageInteractions.tsx +7 -6
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +8 -5
- package/src/components/Modals/ChatProfileModal/ReportChatModal.tsx +2 -2
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +188 -40
- package/src/components/Modals/FilePreviewModal/PdfView.tsx +4 -0
- package/src/components/Modals/Modal/Modal.tsx +44 -16
- package/src/components/Modals/NewChatModal/NewChatModal.tsx +8 -8
- package/src/components/Modals/SettingsModals/ChangePassword/ChangePasswordModal.tsx +316 -0
- package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +10 -15
- package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +13 -14
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +72 -20
- package/src/components/Modals/UserSettingsModal/LanguageCard.tsx +144 -0
- package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +13 -1
- 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 +17 -2
- 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/constants/MODAL_COMPONENTS.tsx +2 -0
- package/src/helpers/constants/MODAL_TYPES.ts +1 -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/preferencesStorage.ts +4 -0
- package/src/helpers/secureKeyValue.ts +15 -0
- package/src/helpers/videoCache.ts +138 -0
- package/src/hooks/useChatSettingState.tsx +4 -0
- package/src/hooks/useChatWrapperInit.ts +4 -0
- package/src/hooks/useLogout.tsx +9 -0
- package/src/hooks/useSendMessage.tsx +71 -5
- package/src/i18n/strings.ts +367 -1
- package/src/i18n/useT.ts +6 -4
- 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/api-requests/user.api.ts +9 -0
- package/src/networking/stanzaHandlers.ts +1 -0
- 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/chatSettingsSlice.ts +13 -0
- package/src/roomStore/persistBackend.ts +8 -11
- package/src/roomStore/persistence.ts +15 -0
- package/src/services/languageSettings.ts +143 -0
- package/src/types/models/message.model.ts +5 -0
- package/src/types/models/room.model.ts +5 -0
- package/src/types/models/user.model.ts +4 -0
- package/src/types/types.ts +25 -0
- package/src/version.ts +1 -1
package/src/e2ee/send.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { Client } from '@xmpp/client';
|
|
2
|
+
import type { Element } from 'ltx';
|
|
3
|
+
import {
|
|
4
|
+
accountDomain,
|
|
5
|
+
isE2eeEnabled,
|
|
6
|
+
isE2eeRoom,
|
|
7
|
+
omemoReady,
|
|
8
|
+
resolveRecipients,
|
|
9
|
+
} from './index';
|
|
10
|
+
|
|
11
|
+
export function shouldEncrypt(roomJID: string): boolean {
|
|
12
|
+
return isE2eeEnabled() && isE2eeRoom(roomJID);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let queue: Promise<void> = Promise.resolve();
|
|
16
|
+
|
|
17
|
+
export function sendEncrypted(
|
|
18
|
+
client: Client,
|
|
19
|
+
roomJID: string,
|
|
20
|
+
id: string,
|
|
21
|
+
data: Element,
|
|
22
|
+
body: Element,
|
|
23
|
+
plain: Element
|
|
24
|
+
): void {
|
|
25
|
+
queue = queue.then(async () => {
|
|
26
|
+
let stanza = plain;
|
|
27
|
+
try {
|
|
28
|
+
const crypto = await omemoReady();
|
|
29
|
+
if (!crypto) {throw new Error('omemo_not_ready');}
|
|
30
|
+
const recipients = await resolveRecipients(roomJID, accountDomain(client));
|
|
31
|
+
stanza = await crypto.encryptGroupMessage(roomJID, recipients, [body], id, [data]);
|
|
32
|
+
} catch (error) {
|
|
33
|
+
const reason = String((error as Error)?.message || error);
|
|
34
|
+
if (reason.startsWith('omemo_members_unknown')) {
|
|
35
|
+
console.warn(`OMEMO: not sending to ${roomJID} - ${reason}`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
console.warn(`OMEMO: sending to ${roomJID} in clear - ${reason}`);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
await client.send(stanza);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('An error occurred while sending message:', error);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function sendSealedMedia(
|
|
49
|
+
client: Client,
|
|
50
|
+
roomJID: string,
|
|
51
|
+
id: string,
|
|
52
|
+
body: Element,
|
|
53
|
+
cleartext: Element[]
|
|
54
|
+
): void {
|
|
55
|
+
queue = queue.then(async () => {
|
|
56
|
+
try {
|
|
57
|
+
const crypto = await omemoReady();
|
|
58
|
+
if (!crypto) {throw new Error('omemo_not_ready');}
|
|
59
|
+
const recipients = await resolveRecipients(roomJID, accountDomain(client));
|
|
60
|
+
const stanza = await crypto.encryptGroupMessage(roomJID, recipients, [body], id, cleartext);
|
|
61
|
+
await client.send(stanza);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error(
|
|
64
|
+
`OMEMO: refusing to send sealed attachment to ${roomJID} - ${String(
|
|
65
|
+
(error as Error)?.message || error
|
|
66
|
+
)}`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Element, parse } from 'ltx';
|
|
2
|
+
import { store } from '../roomStore';
|
|
3
|
+
import { translateKey } from '../i18n/strings';
|
|
4
|
+
import { NS_OMEMO } from './ns';
|
|
5
|
+
import { omemoReady, senderJidFromMuc } from './index';
|
|
6
|
+
|
|
7
|
+
export type DecryptOutcome =
|
|
8
|
+
| 'not-encrypted'
|
|
9
|
+
| 'decrypted'
|
|
10
|
+
| 'undecryptable'
|
|
11
|
+
| 'drop';
|
|
12
|
+
|
|
13
|
+
export type E2eeError =
|
|
14
|
+
| 'unsupported'
|
|
15
|
+
| 'other-device'
|
|
16
|
+
| 'failed';
|
|
17
|
+
|
|
18
|
+
const READY_TIMEOUT_MS = 8000;
|
|
19
|
+
|
|
20
|
+
export function encryptedCarrier(
|
|
21
|
+
stanza: Element,
|
|
22
|
+
depth = 0
|
|
23
|
+
): Element | undefined {
|
|
24
|
+
if (depth > 4 || !stanza?.getChild) {return undefined;}
|
|
25
|
+
if (stanza.name === 'message' && stanza.getChild('encrypted', NS_OMEMO)) {
|
|
26
|
+
return stanza;
|
|
27
|
+
}
|
|
28
|
+
for (const child of stanza.children ?? []) {
|
|
29
|
+
if (typeof child === 'string') {continue;}
|
|
30
|
+
const found = encryptedCarrier(child as Element, depth + 1);
|
|
31
|
+
if (found) {return found;}
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const PLACEHOLDER_KEY: Record<E2eeError, string> = {
|
|
37
|
+
unsupported: 'e2ee.unsupportedMessage',
|
|
38
|
+
'other-device': 'e2ee.otherDevice',
|
|
39
|
+
failed: 'e2ee.undecryptable',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export function placeholderKey(error?: string): string {
|
|
43
|
+
return PLACEHOLDER_KEY[error as E2eeError] ?? PLACEHOLDER_KEY.failed;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function placeholder(error: E2eeError): Element {
|
|
47
|
+
const settings = store.getState()?.chatSettingStore;
|
|
48
|
+
return new Element('body', {}).t(
|
|
49
|
+
translateKey(
|
|
50
|
+
placeholderKey(error),
|
|
51
|
+
settings?.uiLocale || settings?.config?.i18n?.locale || settings?.langSource,
|
|
52
|
+
settings?.config?.i18n?.strings
|
|
53
|
+
)
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function mark(carrier: Element, error?: E2eeError): void {
|
|
58
|
+
let data = carrier.getChild('data');
|
|
59
|
+
if (!data) {
|
|
60
|
+
data = new Element('data', {});
|
|
61
|
+
carrier.append(data);
|
|
62
|
+
}
|
|
63
|
+
data.attrs.omemoEncrypted = 'true';
|
|
64
|
+
if (error) {
|
|
65
|
+
data.attrs.undecryptable = 'true';
|
|
66
|
+
data.attrs.e2eeError = error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function strip(carrier: Element): void {
|
|
71
|
+
carrier.remove('encrypted', NS_OMEMO);
|
|
72
|
+
carrier.remove('encryption', 'urn:xmpp:eme:0');
|
|
73
|
+
carrier.remove('body');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function close(carrier: Element, error: E2eeError): DecryptOutcome {
|
|
77
|
+
strip(carrier);
|
|
78
|
+
carrier.append(placeholder(error));
|
|
79
|
+
mark(carrier, error);
|
|
80
|
+
return 'undecryptable';
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function rewriteEncryptedStanza(stanza: Element): DecryptOutcome {
|
|
84
|
+
const carrier = encryptedCarrier(stanza);
|
|
85
|
+
if (!carrier) {return 'not-encrypted';}
|
|
86
|
+
const encrypted = carrier.getChild('encrypted', NS_OMEMO);
|
|
87
|
+
if (!encrypted?.getChild('payload')) {return 'drop';}
|
|
88
|
+
return close(carrier, 'unsupported');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const waitForDevice = () => {
|
|
92
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
93
|
+
const timeout = new Promise<undefined>((resolve) => {
|
|
94
|
+
timer = setTimeout(() => resolve(undefined), READY_TIMEOUT_MS);
|
|
95
|
+
});
|
|
96
|
+
return Promise.race([omemoReady(), timeout]).finally(() => {
|
|
97
|
+
if (timer) {clearTimeout(timer);}
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export async function decryptStanzaInPlace(
|
|
102
|
+
stanza: Element,
|
|
103
|
+
domain: string
|
|
104
|
+
): Promise<DecryptOutcome> {
|
|
105
|
+
const carrier = encryptedCarrier(stanza);
|
|
106
|
+
if (!carrier) {return 'not-encrypted';}
|
|
107
|
+
|
|
108
|
+
const encrypted = carrier.getChild('encrypted', NS_OMEMO);
|
|
109
|
+
if (!encrypted?.getChild('payload')) {return 'drop';}
|
|
110
|
+
|
|
111
|
+
const from = String(carrier.attrs?.from || '');
|
|
112
|
+
const roomJid = from.split('/')[0]!;
|
|
113
|
+
const sender = senderJidFromMuc(from, domain);
|
|
114
|
+
const crypto = await waitForDevice();
|
|
115
|
+
const decrypted = sender
|
|
116
|
+
? await crypto?.decrypt(carrier, sender, roomJid)
|
|
117
|
+
: undefined;
|
|
118
|
+
|
|
119
|
+
if (!decrypted?.content) {
|
|
120
|
+
return close(
|
|
121
|
+
carrier,
|
|
122
|
+
decrypted?.error === 'omemo_not_encrypted_for_this_device'
|
|
123
|
+
? 'other-device'
|
|
124
|
+
: 'failed'
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
strip(carrier);
|
|
129
|
+
const wrapper = parse(`<omemo-content>${decrypted.content}</omemo-content>`);
|
|
130
|
+
carrier.append(...wrapper.children);
|
|
131
|
+
mark(carrier);
|
|
132
|
+
return 'decrypted';
|
|
133
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { fromBase64, toBase64 } from './crypto';
|
|
2
|
+
|
|
3
|
+
export interface OmemoStore {
|
|
4
|
+
get<T>(key: string): Promise<T | undefined>;
|
|
5
|
+
set(key: string, value: unknown): Promise<void>;
|
|
6
|
+
delete(key: string): Promise<void>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const BYTES_TAG = '$bytes';
|
|
10
|
+
|
|
11
|
+
export function encodeValue(value: unknown): string {
|
|
12
|
+
return JSON.stringify(value, (_key, item) =>
|
|
13
|
+
item instanceof Uint8Array ? { [BYTES_TAG]: toBase64(item) } : item
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function decodeValue<T>(text: string): T {
|
|
18
|
+
return JSON.parse(text, (_key, item) =>
|
|
19
|
+
item && typeof item === 'object' && typeof item[BYTES_TAG] === 'string'
|
|
20
|
+
? fromBase64(item[BYTES_TAG])
|
|
21
|
+
: item
|
|
22
|
+
) as T;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface StringBackend {
|
|
26
|
+
getItem(key: string): Promise<string | null>;
|
|
27
|
+
setItem(key: string, value: string): Promise<void>;
|
|
28
|
+
removeItem(key: string): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createStore(backend: StringBackend, jid: string): OmemoStore {
|
|
32
|
+
const prefix = `${jid.toLowerCase()}|`;
|
|
33
|
+
return {
|
|
34
|
+
get: async <T>(key: string) => {
|
|
35
|
+
const raw = await backend.getItem(prefix + key);
|
|
36
|
+
return raw === null ? undefined : decodeValue<T>(raw);
|
|
37
|
+
},
|
|
38
|
+
set: (key, value) => backend.setItem(prefix + key, encodeValue(value)),
|
|
39
|
+
delete: (key) => backend.removeItem(prefix + key),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function createMemoryBackend(): StringBackend {
|
|
44
|
+
const data = new Map<string, string>();
|
|
45
|
+
return {
|
|
46
|
+
getItem: async (key) => data.get(key) ?? null,
|
|
47
|
+
setItem: async (key, value) => void data.set(key, value),
|
|
48
|
+
removeItem: async (key) => void data.delete(key),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function createMemoryStore(jid = 'memory'): OmemoStore {
|
|
53
|
+
return createStore(createMemoryBackend(), jid);
|
|
54
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const accountNameOf = (
|
|
2
|
+
user:
|
|
3
|
+
| { xmppUsername?: string; userJID?: string; id?: string; _id?: string }
|
|
4
|
+
| null
|
|
5
|
+
| undefined,
|
|
6
|
+
appId: string
|
|
7
|
+
): string => {
|
|
8
|
+
for (const raw of [user?.xmppUsername, user?.userJID, user?.id, user?._id]) {
|
|
9
|
+
const value = String(raw || '').split('@')[0]!.trim();
|
|
10
|
+
if (!value) {continue;}
|
|
11
|
+
if (value.includes('_')) {return value;}
|
|
12
|
+
if (appId) {return `${appId}_${value}`;}
|
|
13
|
+
}
|
|
14
|
+
return '';
|
|
15
|
+
};
|
|
@@ -14,6 +14,7 @@ import ManageDataModal from '../../components/Modals/SettingsModals/ManageDataMo
|
|
|
14
14
|
import ProfileSharesModal from '../../components/Modals/SettingsModals/ProfileShares/ProfileShares';
|
|
15
15
|
import ReferralsModal from '../../components/Modals/SettingsModals/Referrals/Referrals';
|
|
16
16
|
import VisibilityModal from '../../components/Modals/SettingsModals/Visibility/VisibilityModal';
|
|
17
|
+
import ChangePasswordModal from '../../components/Modals/SettingsModals/ChangePassword/ChangePasswordModal';
|
|
17
18
|
import UserProfileModal from '../../components/Modals/UserProfileModal/UserProfileModal';
|
|
18
19
|
import UserSettingsModal from '../../components/Modals/UserSettingsModal/UserSettingsModal';
|
|
19
20
|
|
|
@@ -27,6 +28,7 @@ export const MODAL_COMPONENTS: Record<
|
|
|
27
28
|
[MODAL_TYPES.CHAT_PROFILE]: ChatProfileModal,
|
|
28
29
|
[MODAL_TYPES.MANAGE_DATA]: ManageDataModal,
|
|
29
30
|
[MODAL_TYPES.VISIBILITY]: VisibilityModal,
|
|
31
|
+
[MODAL_TYPES.CHANGE_PASSWORD]: ChangePasswordModal,
|
|
30
32
|
[MODAL_TYPES.REFERRALS]: ReferralsModal,
|
|
31
33
|
[MODAL_TYPES.DOCUMENT_SHARES]: DocumentSharesModal,
|
|
32
34
|
[MODAL_TYPES.PROFILE_SHARES]: ProfileSharesModal,
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { IMessage } from '../types/types';
|
|
2
|
+
import { isE2eeRoom } from '../e2ee';
|
|
3
|
+
import { composeName } from './displayName';
|
|
4
|
+
import { parseSealedMediaBody } from '../e2ee/sealedBody';
|
|
2
5
|
|
|
3
6
|
interface IMessageWithNewData extends IMessage {
|
|
4
7
|
[x: string]: any;
|
|
@@ -86,13 +89,25 @@ export const createMessageFromXml = async (
|
|
|
86
89
|
// Synthesize user.name from sender attrs (web reads usersSet from
|
|
87
90
|
// redux in <Message>; we fix it once at the source so Avatar /
|
|
88
91
|
// MessageHeader render the actual sender instead of "??").
|
|
89
|
-
const firstName = (merged.senderFirstName || '')
|
|
90
|
-
|
|
92
|
+
const firstName = (merged.senderFirstName || merged.firstName || '')
|
|
93
|
+
.toString()
|
|
94
|
+
.trim();
|
|
95
|
+
const lastName = (merged.senderLastName || merged.lastName || '')
|
|
96
|
+
.toString()
|
|
97
|
+
.trim();
|
|
91
98
|
const fullName = (merged.fullName || '').toString().trim();
|
|
92
99
|
const senderJID = (merged.senderJID || '').toString();
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
const senderBare = senderJID.split('/')[0] || '';
|
|
101
|
+
const senderResource = senderJID.includes('/') ? senderJID.split('/')[1] || '' : '';
|
|
102
|
+
const senderIsOccupant =
|
|
103
|
+
!!senderResource &&
|
|
104
|
+
(senderBare === String(merged.roomJid || '') ||
|
|
105
|
+
/@conference\./i.test(senderBare));
|
|
106
|
+
const senderLocal = senderIsOccupant
|
|
107
|
+
? senderResource
|
|
108
|
+
: senderBare.includes('@')
|
|
109
|
+
? senderBare.split('@')[0]
|
|
110
|
+
: senderBare;
|
|
96
111
|
|
|
97
112
|
// Bug #41 root cause: the resource of the MUC `from` (room@conference/
|
|
98
113
|
// occupant-id) is the SAME field getDataFromXml uses to derive
|
|
@@ -112,7 +127,7 @@ export const createMessageFromXml = async (
|
|
|
112
127
|
const xmppFrom = (merged.xmppFrom || '').toString();
|
|
113
128
|
const fromResource = xmppFrom.includes('/') ? xmppFrom.split('/')[1] : '';
|
|
114
129
|
|
|
115
|
-
const composed =
|
|
130
|
+
const composed = composeName(firstName, lastName);
|
|
116
131
|
const existingName = String(merged?.user?.name || '').trim();
|
|
117
132
|
const resolvedName =
|
|
118
133
|
existingName ||
|
|
@@ -122,8 +137,18 @@ export const createMessageFromXml = async (
|
|
|
122
137
|
merged?.user?.id ||
|
|
123
138
|
'';
|
|
124
139
|
|
|
140
|
+
const unencrypted =
|
|
141
|
+
merged.omemoEncrypted !== 'true' && isE2eeRoom(String(merged.roomJid || ''));
|
|
142
|
+
|
|
143
|
+
const sealedKeys =
|
|
144
|
+
merged.clientEncrypted === 'true'
|
|
145
|
+
? parseSealedMediaBody(merged.body)
|
|
146
|
+
: undefined;
|
|
147
|
+
|
|
125
148
|
const message: IMessage = {
|
|
126
149
|
...merged,
|
|
150
|
+
...(unencrypted ? { unencrypted: true } : {}),
|
|
151
|
+
...(sealedKeys ? { e2eeKeys: sealedKeys, body: 'media' } : {}),
|
|
127
152
|
user: {
|
|
128
153
|
...(merged.user || {}),
|
|
129
154
|
id: merged?.user?.id || fromResource || senderLocal,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IMessage, RoomMember } from '../types/types';
|
|
2
|
+
import { composeName } from './displayName';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Cache-only lookup. Returns the literal "Deleted User" as a MISS sentinel
|
|
@@ -21,7 +22,7 @@ export const createUserNameFromSetUser = (
|
|
|
21
22
|
// fall back to that before giving up and returning the raw id.
|
|
22
23
|
const bareName = user.name?.trim() || '';
|
|
23
24
|
|
|
24
|
-
return
|
|
25
|
+
return composeName(firstName, lastName) || bareName || userId;
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
/**
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const composeName = (
|
|
2
|
+
first?: string | null,
|
|
3
|
+
last?: string | null
|
|
4
|
+
): string => {
|
|
5
|
+
const f = String(first ?? '').trim();
|
|
6
|
+
const l = String(last ?? '').trim();
|
|
7
|
+
if (f && f.includes('@') && f.toLowerCase() === l.toLowerCase()) {return f;}
|
|
8
|
+
return `${f} ${l}`.trim();
|
|
9
|
+
};
|
|
@@ -69,6 +69,11 @@ const loadOrCreateKey = (): Promise<CryptoJS.lib.WordArray> => {
|
|
|
69
69
|
return cachedKeyPromise;
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
+
export async function isPersistKeyKept(): Promise<boolean> {
|
|
73
|
+
const key = await loadOrCreateKey();
|
|
74
|
+
return (await secureGet(CIPHER_KEY_STORE_KEY)) === CryptoJS.enc.Base64.stringify(key);
|
|
75
|
+
}
|
|
76
|
+
|
|
72
77
|
/** Encrypt a JSON-serialisable payload for storage. Returns the string to persist. */
|
|
73
78
|
export async function encryptForPersist(plaintext: string): Promise<string> {
|
|
74
79
|
const key = await loadOrCreateKey();
|
|
@@ -9,6 +9,10 @@ const KEY = '@ethora/preferences';
|
|
|
9
9
|
export interface StoredPreferences {
|
|
10
10
|
theme?: ThemePreference;
|
|
11
11
|
pushEnabled?: boolean;
|
|
12
|
+
/** Interface language picked in Settings (BCP-47). */
|
|
13
|
+
uiLocale?: string;
|
|
14
|
+
/** Language messages are translated into, picked in Settings (BCP-47). */
|
|
15
|
+
chatLanguage?: string;
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
export const loadPreferences = async (): Promise<StoredPreferences> => {
|
|
@@ -74,6 +74,21 @@ export async function secureRemove(key: string): Promise<void> {
|
|
|
74
74
|
await AsyncStorage.removeItem(FALLBACK_PREFIX + key).catch(() => undefined);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
export async function secureGetOrCreate(
|
|
78
|
+
key: string,
|
|
79
|
+
create: () => string
|
|
80
|
+
): Promise<{ value: string; created: boolean } | null> {
|
|
81
|
+
const existing = await secureGet(key);
|
|
82
|
+
if (existing) {return { value: existing, created: false };}
|
|
83
|
+
const value = create();
|
|
84
|
+
await secureSet(key, value);
|
|
85
|
+
if ((await secureGet(key)) !== value) {
|
|
86
|
+
pushLog('warn', `secureStore: ${key} was not kept`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return { value, created: true };
|
|
90
|
+
}
|
|
91
|
+
|
|
77
92
|
/** Test seam only. */
|
|
78
93
|
export const __resetSecureKeyValueWarningForTests = (): void => {
|
|
79
94
|
warnedFallback = false;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import * as FileSystem from 'expo-file-system/legacy';
|
|
2
|
+
import { filenameFromUrl, getExtensionForMime } from './mimeToExtension';
|
|
3
|
+
|
|
4
|
+
// Containers the native players open from a local file by extension.
|
|
5
|
+
const VIDEO_EXT_RE = /\.(mp4|mov|m4v|webm|3gp|mkv|mpeg)$/i;
|
|
6
|
+
|
|
7
|
+
const hashString = (value: string) => {
|
|
8
|
+
let hash = 5381;
|
|
9
|
+
for (let i = 0; i < value.length; i++) {
|
|
10
|
+
hash = (hash * 33) ^ value.charCodeAt(i);
|
|
11
|
+
}
|
|
12
|
+
return (hash >>> 0).toString(36);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const isRemoteUrl = (url?: string | null): boolean =>
|
|
16
|
+
/^https?:\/\//i.test(url || '');
|
|
17
|
+
|
|
18
|
+
const hostOf = (url: string): string =>
|
|
19
|
+
(/^https?:\/\/(?:[^@/]+@)?([^:/?#]+)/i.exec(url)?.[1] || '').toLowerCase();
|
|
20
|
+
|
|
21
|
+
// The query carries the short-lived file token; the file is the same.
|
|
22
|
+
const withoutQuery = (url: string): string => url.split('#')[0]!.split('?')[0]!;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Where a remote video is kept once downloaded. The extension matters:
|
|
26
|
+
* AVFoundation picks the demuxer of a local file by it.
|
|
27
|
+
*/
|
|
28
|
+
export const getVideoCacheUri = (
|
|
29
|
+
url: string,
|
|
30
|
+
mimetype: string | undefined | null,
|
|
31
|
+
cacheDirectory: string
|
|
32
|
+
): string => {
|
|
33
|
+
const fromUrl = VIDEO_EXT_RE.exec(filenameFromUrl(url))?.[0];
|
|
34
|
+
const fromMime = getExtensionForMime(mimetype);
|
|
35
|
+
const ext = (
|
|
36
|
+
fromUrl || (VIDEO_EXT_RE.test(fromMime) ? fromMime : '.mp4')
|
|
37
|
+
).toLowerCase();
|
|
38
|
+
return `${cacheDirectory}ethora-video-${hashString(withoutQuery(url))}${ext}`;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Hosts that answered a streaming attempt with an error. AVPlayer refuses a
|
|
43
|
+
* server that replies 200 to a byte-range request ("server is not correctly
|
|
44
|
+
* configured"), so for those the next video skips the doomed stream and
|
|
45
|
+
* downloads straight away.
|
|
46
|
+
*/
|
|
47
|
+
const hostsWithoutStreaming = new Set<string>();
|
|
48
|
+
|
|
49
|
+
export const markStreamingUnsupported = (url: string): void => {
|
|
50
|
+
const host = hostOf(url);
|
|
51
|
+
if (host) {hostsWithoutStreaming.add(host);}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const isStreamingUnsupported = (url: string): boolean =>
|
|
55
|
+
hostsWithoutStreaming.has(hostOf(url));
|
|
56
|
+
|
|
57
|
+
export const findCachedVideo = async (
|
|
58
|
+
url: string,
|
|
59
|
+
mimetype?: string | null
|
|
60
|
+
): Promise<string | null> => {
|
|
61
|
+
const cacheDirectory = FileSystem.cacheDirectory;
|
|
62
|
+
if (!cacheDirectory || !isRemoteUrl(url)) {return null;}
|
|
63
|
+
try {
|
|
64
|
+
const uri = getVideoCacheUri(url, mimetype, cacheDirectory);
|
|
65
|
+
const info = await FileSystem.getInfoAsync(uri);
|
|
66
|
+
return info.exists ? uri : null;
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
type ProgressListener = (fraction: number) => void;
|
|
73
|
+
|
|
74
|
+
const inFlight = new Map<
|
|
75
|
+
string,
|
|
76
|
+
{ promise: Promise<string>; listeners: Set<ProgressListener> }
|
|
77
|
+
>();
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Downloads the video next to the app's other caches and resolves with the
|
|
81
|
+
* local uri. One download per file however many callers ask; `onProgress`
|
|
82
|
+
* gets 0..1 when the server reports a length.
|
|
83
|
+
*/
|
|
84
|
+
export const downloadVideoToCache = (
|
|
85
|
+
url: string,
|
|
86
|
+
mimetype?: string | null,
|
|
87
|
+
onProgress?: ProgressListener
|
|
88
|
+
): Promise<string> => {
|
|
89
|
+
const cacheDirectory = FileSystem.cacheDirectory;
|
|
90
|
+
if (!cacheDirectory) {
|
|
91
|
+
return Promise.reject(new Error('video_cache_unavailable'));
|
|
92
|
+
}
|
|
93
|
+
const finalUri = getVideoCacheUri(url, mimetype, cacheDirectory);
|
|
94
|
+
|
|
95
|
+
const running = inFlight.get(finalUri);
|
|
96
|
+
if (running) {
|
|
97
|
+
if (onProgress) {running.listeners.add(onProgress);}
|
|
98
|
+
return running.promise;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const listeners = new Set<ProgressListener>();
|
|
102
|
+
if (onProgress) {listeners.add(onProgress);}
|
|
103
|
+
|
|
104
|
+
const run = async (): Promise<string> => {
|
|
105
|
+
// Download under another name: an interrupted download must not be
|
|
106
|
+
// mistaken for the cached file next time.
|
|
107
|
+
const part = `${finalUri}.part`;
|
|
108
|
+
await FileSystem.deleteAsync(part, { idempotent: true }).catch(() => {});
|
|
109
|
+
const task = FileSystem.createDownloadResumable(url, part, {}, (p) => {
|
|
110
|
+
if (p.totalBytesExpectedToWrite > 0) {
|
|
111
|
+
const fraction = Math.min(
|
|
112
|
+
1,
|
|
113
|
+
p.totalBytesWritten / p.totalBytesExpectedToWrite
|
|
114
|
+
);
|
|
115
|
+
listeners.forEach((listener) => listener(fraction));
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
const result = await task.downloadAsync();
|
|
119
|
+
if (!result || result.status < 200 || result.status >= 300) {
|
|
120
|
+
await FileSystem.deleteAsync(part, { idempotent: true }).catch(() => {});
|
|
121
|
+
throw new Error(`video_download_status_${result?.status ?? 'cancelled'}`);
|
|
122
|
+
}
|
|
123
|
+
await FileSystem.deleteAsync(finalUri, { idempotent: true }).catch(() => {});
|
|
124
|
+
await FileSystem.moveAsync({ from: part, to: finalUri });
|
|
125
|
+
return finalUri;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const promise = run().finally(() => {
|
|
129
|
+
inFlight.delete(finalUri);
|
|
130
|
+
});
|
|
131
|
+
inFlight.set(finalUri, { promise, listeners });
|
|
132
|
+
return promise;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const __resetVideoCacheForTests = (): void => {
|
|
136
|
+
hostsWithoutStreaming.clear();
|
|
137
|
+
inFlight.clear();
|
|
138
|
+
};
|
|
@@ -9,6 +9,9 @@ export const useChatSettingState = () => {
|
|
|
9
9
|
const activeModal = useSelector(
|
|
10
10
|
(state: RootState) => state.chatSettingStore.activeModal
|
|
11
11
|
);
|
|
12
|
+
const uiLocale = useSelector(
|
|
13
|
+
(state: RootState) => state.chatSettingStore.uiLocale
|
|
14
|
+
);
|
|
12
15
|
const config = useSelector(
|
|
13
16
|
(state: RootState) => state.chatSettingStore.config
|
|
14
17
|
);
|
|
@@ -29,6 +32,7 @@ export const useChatSettingState = () => {
|
|
|
29
32
|
);
|
|
30
33
|
|
|
31
34
|
return {
|
|
35
|
+
uiLocale,
|
|
32
36
|
user,
|
|
33
37
|
activeFile,
|
|
34
38
|
activeModal,
|
|
@@ -12,6 +12,7 @@ import { initRoomsPresence } from '../helpers/initRoomsPresence';
|
|
|
12
12
|
import { updateMessagesTillLast } from '../helpers/updateMessagesTillLast';
|
|
13
13
|
import { refreshAuthTokensQuietly } from '../networking/authRefresh';
|
|
14
14
|
import { setLangSource, setConfig } from '../roomStore/chatSettingsSlice';
|
|
15
|
+
import { applyProfileLanguages } from '../services/languageSettings';
|
|
15
16
|
import { setIsLoading } from '../roomStore/roomsSlice';
|
|
16
17
|
import { useRoomState } from './useRoomState';
|
|
17
18
|
import { useChatSettingState } from './useChatSettingState';
|
|
@@ -120,6 +121,9 @@ const useChatWrapperInit = ({
|
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
dispatch(setConfig(config));
|
|
124
|
+
// The profile's languages are the account's truth, over what the
|
|
125
|
+
// device remembered.
|
|
126
|
+
applyProfileLanguages(user as any, config);
|
|
123
127
|
try {
|
|
124
128
|
if (!user.xmppUsername) {
|
|
125
129
|
setShowModal(true);
|
package/src/hooks/useLogout.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import { clearRoomsRestCache } from '../networking/api-requests/rooms.api';
|
|
|
12
12
|
import { clearPersistedState } from '../roomStore/persistence';
|
|
13
13
|
import { secureUserStorage } from '../helpers/secureUserStorage';
|
|
14
14
|
import { getFlushBoundaryTs } from '../helpers/getServerReadTimestamp';
|
|
15
|
+
import { stopOmemo } from '../e2ee';
|
|
15
16
|
|
|
16
17
|
// AsyncStorage keys the library writes but that aren't cleared by any
|
|
17
18
|
// slice reducer. Listed here so a single logout call wipes the full
|
|
@@ -109,6 +110,14 @@ const logoutService = {
|
|
|
109
110
|
console.warn('logoutService: push reset failed', e);
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
stopOmemo();
|
|
114
|
+
try {
|
|
115
|
+
const { clearOpenedFiles } =
|
|
116
|
+
require('../e2ee/sealedFiles') as typeof import('../e2ee/sealedFiles');
|
|
117
|
+
clearOpenedFiles();
|
|
118
|
+
} catch {
|
|
119
|
+
}
|
|
120
|
+
|
|
112
121
|
// 3. REST: nuke the in-memory `/chats/my` cache so the next login
|
|
113
122
|
// doesn't read user A's rooms while user B is bootstrapping.
|
|
114
123
|
try {
|