@ethora/chat-component-rn 26.5.21 → 26.6.11
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 +80 -0
- package/README.md +3 -3
- package/index.js +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +20 -8
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +17 -0
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/LanguageSelectorButton.js +62 -0
- package/lib/commonjs/components/MainComponents/LanguageSelectorButton.js.map +1 -0
- package/lib/commonjs/components/MainComponents/LanguageSelectorModal.js +253 -0
- package/lib/commonjs/components/MainComponents/LanguageSelectorModal.js.map +1 -0
- package/lib/commonjs/components/MainComponents/MediaMessage.js +7 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/RoomList.js +23 -9
- package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +72 -11
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageTranslate.js +160 -0
- package/lib/commonjs/components/MessageBubble/MessageTranslate.js.map +1 -0
- package/lib/commonjs/components/MessageBubble/TranslatedMessageBody.js +59 -0
- package/lib/commonjs/components/MessageBubble/TranslatedMessageBody.js.map +1 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +3 -3
- package/lib/commonjs/components/UsersList/UsersList.js +3 -1
- package/lib/commonjs/components/UsersList/UsersList.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/CallButtons.js +159 -0
- package/lib/commonjs/components/VideoCalls/CallButtons.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/CallIcons.js +328 -0
- package/lib/commonjs/components/VideoCalls/CallIcons.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js +550 -0
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js +636 -0
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/livekitRuntime.js +91 -0
- package/lib/commonjs/components/VideoCalls/livekitRuntime.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/useCallKeep.js +215 -0
- package/lib/commonjs/components/VideoCalls/useCallKeep.js.map +1 -0
- package/lib/commonjs/components/styled/AudioMessage.js +91 -33
- package/lib/commonjs/components/styled/AudioMessage.js.map +1 -1
- package/lib/commonjs/components/styled/RoomListComponents/index.js +13 -1
- package/lib/commonjs/components/styled/RoomListComponents/index.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +83 -49
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/StyledComponents.js +9 -4
- package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
- package/lib/commonjs/components/styled/StyledInputComponents/Composing.js +2 -0
- package/lib/commonjs/components/styled/StyledInputComponents/Composing.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +110 -26
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +10 -3
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/callLogMessage.js +162 -0
- package/lib/commonjs/helpers/callLogMessage.js.map +1 -0
- package/lib/commonjs/helpers/callPush.js +61 -0
- package/lib/commonjs/helpers/callPush.js.map +1 -0
- package/lib/commonjs/helpers/constants/LANGUAGE_OPTIONS.js +24 -12
- package/lib/commonjs/helpers/constants/LANGUAGE_OPTIONS.js.map +1 -1
- package/lib/commonjs/helpers/createUserNameFromSetUser.js +51 -2
- package/lib/commonjs/helpers/createUserNameFromSetUser.js.map +1 -1
- package/lib/commonjs/helpers/getDataFromXml.js +19 -1
- package/lib/commonjs/helpers/getDataFromXml.js.map +1 -1
- package/lib/commonjs/helpers/incomingCallFromPush.js +74 -0
- package/lib/commonjs/helpers/incomingCallFromPush.js.map +1 -0
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js +13 -1
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/commonjs/helpers/isUnresolvedSenderId.js +32 -0
- package/lib/commonjs/helpers/isUnresolvedSenderId.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/useMessageTranslation.js +51 -0
- package/lib/commonjs/hooks/useMessageTranslation.js.map +1 -0
- package/lib/commonjs/hooks/usePushNotifications.js +13 -3
- package/lib/commonjs/hooks/usePushNotifications.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +14 -4
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +1308 -0
- package/lib/commonjs/i18n/strings.js.map +1 -0
- package/lib/commonjs/i18n/useT.js +60 -0
- package/lib/commonjs/i18n/useT.js.map +1 -0
- package/lib/commonjs/main.js +44 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +81 -52
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/api-requests/push.api.js +34 -5
- package/lib/commonjs/networking/api-requests/push.api.js.map +1 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js +108 -0
- package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/commonjs/networking/callTokenStanza.js +531 -0
- package/lib/commonjs/networking/callTokenStanza.js.map +1 -0
- package/lib/commonjs/networking/outboundQueue.js.map +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +75 -8
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +47 -11
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +2 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +42 -5
- package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +78 -16
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/callSlice.js +144 -0
- package/lib/commonjs/roomStore/callSlice.js.map +1 -0
- package/lib/commonjs/roomStore/chatSettingsSlice.js +8 -2
- package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/commonjs/roomStore/index.js +7 -1
- package/lib/commonjs/roomStore/index.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +69 -5
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +136 -6
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/commonjs/utils/translateModePolicy.js +33 -0
- package/lib/commonjs/utils/translateModePolicy.js.map +1 -0
- package/lib/module/components/MainComponents/ChatHeader.js +20 -8
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +17 -0
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/LanguageSelectorButton.js +57 -0
- package/lib/module/components/MainComponents/LanguageSelectorButton.js.map +1 -0
- package/lib/module/components/MainComponents/LanguageSelectorModal.js +246 -0
- package/lib/module/components/MainComponents/LanguageSelectorModal.js.map +1 -0
- package/lib/module/components/MainComponents/MediaMessage.js +7 -1
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/RoomList.js +23 -9
- package/lib/module/components/MainComponents/RoomList.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +73 -12
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageTranslate.js +155 -0
- package/lib/module/components/MessageBubble/MessageTranslate.js.map +1 -0
- package/lib/module/components/MessageBubble/TranslatedMessageBody.js +53 -0
- package/lib/module/components/MessageBubble/TranslatedMessageBody.js.map +1 -0
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +3 -3
- package/lib/module/components/UsersList/UsersList.js +3 -1
- package/lib/module/components/UsersList/UsersList.js.map +1 -1
- package/lib/module/components/VideoCalls/CallButtons.js +154 -0
- package/lib/module/components/VideoCalls/CallButtons.js.map +1 -0
- package/lib/module/components/VideoCalls/CallIcons.js +309 -0
- package/lib/module/components/VideoCalls/CallIcons.js.map +1 -0
- package/lib/module/components/VideoCalls/VideoCallOverlay.js +544 -0
- package/lib/module/components/VideoCalls/VideoCallOverlay.js.map +1 -0
- package/lib/module/components/VideoCalls/VideoCallSession.js +630 -0
- package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -0
- package/lib/module/components/VideoCalls/livekitRuntime.js +83 -0
- package/lib/module/components/VideoCalls/livekitRuntime.js.map +1 -0
- package/lib/module/components/VideoCalls/useCallKeep.js +210 -0
- package/lib/module/components/VideoCalls/useCallKeep.js.map +1 -0
- package/lib/module/components/styled/AudioMessage.js +91 -33
- package/lib/module/components/styled/AudioMessage.js.map +1 -1
- package/lib/module/components/styled/RoomListComponents/index.js +13 -1
- package/lib/module/components/styled/RoomListComponents/index.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +83 -49
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/StyledComponents.js +9 -4
- package/lib/module/components/styled/StyledComponents.js.map +1 -1
- package/lib/module/components/styled/StyledInputComponents/Composing.js +2 -0
- package/lib/module/components/styled/StyledInputComponents/Composing.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +111 -27
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/xmppProvider.js +11 -4
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/callLogMessage.js +152 -0
- package/lib/module/helpers/callLogMessage.js.map +1 -0
- package/lib/module/helpers/callPush.js +55 -0
- package/lib/module/helpers/callPush.js.map +1 -0
- package/lib/module/helpers/constants/LANGUAGE_OPTIONS.js +24 -12
- package/lib/module/helpers/constants/LANGUAGE_OPTIONS.js.map +1 -1
- package/lib/module/helpers/createUserNameFromSetUser.js +49 -1
- package/lib/module/helpers/createUserNameFromSetUser.js.map +1 -1
- package/lib/module/helpers/getDataFromXml.js +20 -1
- package/lib/module/helpers/getDataFromXml.js.map +1 -1
- package/lib/module/helpers/incomingCallFromPush.js +70 -0
- package/lib/module/helpers/incomingCallFromPush.js.map +1 -0
- package/lib/module/helpers/insertMessageWithDelimiter.js +13 -1
- package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/module/helpers/isUnresolvedSenderId.js +27 -0
- package/lib/module/helpers/isUnresolvedSenderId.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/useMessageTranslation.js +46 -0
- package/lib/module/hooks/useMessageTranslation.js.map +1 -0
- package/lib/module/hooks/usePushNotifications.js +13 -3
- package/lib/module/hooks/usePushNotifications.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +15 -5
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/i18n/strings.js +1300 -0
- package/lib/module/i18n/strings.js.map +1 -0
- package/lib/module/i18n/useT.js +55 -0
- package/lib/module/i18n/useT.js.map +1 -0
- package/lib/module/main.js +7 -1
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +80 -51
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/api-requests/push.api.js +35 -5
- package/lib/module/networking/api-requests/push.api.js.map +1 -1
- package/lib/module/networking/api-requests/rooms.api.js +109 -1
- package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/module/networking/callTokenStanza.js +526 -0
- package/lib/module/networking/callTokenStanza.js.map +1 -0
- package/lib/module/networking/outboundQueue.js.map +1 -1
- package/lib/module/networking/stanzaHandlers.js +76 -9
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js +48 -11
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +1 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +43 -5
- package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
- package/lib/module/networking/xmppClient.js +78 -16
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/callSlice.js +130 -0
- package/lib/module/roomStore/callSlice.js.map +1 -0
- package/lib/module/roomStore/chatSettingsSlice.js +6 -1
- package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/module/roomStore/index.js +6 -1
- package/lib/module/roomStore/index.js.map +1 -1
- package/lib/module/roomStore/persistence.js +69 -5
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +134 -5
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/utils/translateModePolicy.js +27 -0
- package/lib/module/utils/translateModePolicy.js.map +1 -0
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/LanguageSelectorButton.d.ts +12 -0
- package/lib/typescript/components/MainComponents/LanguageSelectorButton.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/LanguageSelectorModal.d.ts +31 -0
- package/lib/typescript/components/MainComponents/LanguageSelectorModal.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageTranslate.d.ts +44 -0
- package/lib/typescript/components/MessageBubble/MessageTranslate.d.ts.map +1 -0
- package/lib/typescript/components/MessageBubble/TranslatedMessageBody.d.ts +24 -0
- package/lib/typescript/components/MessageBubble/TranslatedMessageBody.d.ts.map +1 -0
- package/lib/typescript/components/UsersList/UsersList.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/CallButtons.d.ts +16 -0
- package/lib/typescript/components/VideoCalls/CallButtons.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/CallIcons.d.ts +30 -0
- package/lib/typescript/components/VideoCalls/CallIcons.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts +10 -0
- package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts +38 -0
- package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/livekitRuntime.d.ts +52 -0
- package/lib/typescript/components/VideoCalls/livekitRuntime.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/useCallKeep.d.ts +32 -0
- package/lib/typescript/components/VideoCalls/useCallKeep.d.ts.map +1 -0
- package/lib/typescript/components/styled/AudioMessage.d.ts.map +1 -1
- package/lib/typescript/components/styled/RoomListComponents/index.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledInputComponents/Composing.d.ts.map +1 -1
- package/lib/typescript/components/styled/VideoMessage.d.ts +2 -0
- package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/callLogMessage.d.ts +34 -0
- package/lib/typescript/helpers/callLogMessage.d.ts.map +1 -0
- package/lib/typescript/helpers/callPush.d.ts +23 -0
- package/lib/typescript/helpers/callPush.d.ts.map +1 -0
- package/lib/typescript/helpers/constants/LANGUAGE_OPTIONS.d.ts +14 -0
- package/lib/typescript/helpers/constants/LANGUAGE_OPTIONS.d.ts.map +1 -1
- package/lib/typescript/helpers/createUserNameFromSetUser.d.ts +33 -1
- package/lib/typescript/helpers/createUserNameFromSetUser.d.ts.map +1 -1
- package/lib/typescript/helpers/getDataFromXml.d.ts.map +1 -1
- package/lib/typescript/helpers/incomingCallFromPush.d.ts +14 -0
- package/lib/typescript/helpers/incomingCallFromPush.d.ts.map +1 -0
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
- package/lib/typescript/helpers/isUnresolvedSenderId.d.ts +2 -0
- package/lib/typescript/helpers/isUnresolvedSenderId.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatSettingState.d.ts +2 -1
- package/lib/typescript/hooks/useChatSettingState.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageTranslation.d.ts +25 -0
- package/lib/typescript/hooks/useMessageTranslation.d.ts.map +1 -0
- package/lib/typescript/hooks/usePushNotifications.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts +16 -0
- package/lib/typescript/i18n/strings.d.ts.map +1 -0
- package/lib/typescript/i18n/useT.d.ts +34 -0
- package/lib/typescript/i18n/useT.d.ts.map +1 -0
- package/lib/typescript/main.d.ts +6 -1
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts +27 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/push.api.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts +3 -0
- package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
- package/lib/typescript/networking/callTokenStanza.d.ts +14 -0
- package/lib/typescript/networking/callTokenStanza.d.ts.map +1 -0
- package/lib/typescript/networking/outboundQueue.d.ts +1 -0
- package/lib/typescript/networking/outboundQueue.d.ts.map +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts +10 -0
- package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts +16 -1
- package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +1 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/callSlice.d.ts +39 -0
- package/lib/typescript/roomStore/callSlice.d.ts.map +1 -0
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts +10 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/index.d.ts +4 -0
- package/lib/typescript/roomStore/index.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +6 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/language.model.d.ts +1 -1
- package/lib/typescript/types/models/language.model.d.ts.map +1 -1
- package/lib/typescript/types/models/message.model.d.ts +7 -0
- package/lib/typescript/types/models/message.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +135 -1
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/utils/translateModePolicy.d.ts +20 -0
- package/lib/typescript/utils/translateModePolicy.d.ts.map +1 -0
- package/package.json +20 -4
- package/src/components/MainComponents/ChatHeader.tsx +30 -9
- package/src/components/MainComponents/ChatWrapper.tsx +15 -0
- package/src/components/MainComponents/LanguageSelectorButton.tsx +53 -0
- package/src/components/MainComponents/LanguageSelectorModal.tsx +276 -0
- package/src/components/MainComponents/MediaMessage.tsx +5 -0
- package/src/components/MainComponents/RoomList.tsx +27 -9
- package/src/components/MessageBubble/Message.tsx +109 -17
- package/src/components/MessageBubble/MessageTranslate.tsx +182 -0
- package/src/components/MessageBubble/TranslatedMessageBody.tsx +59 -0
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +3 -3
- package/src/components/UsersList/UsersList.tsx +3 -1
- package/src/components/VideoCalls/CallButtons.tsx +171 -0
- package/src/components/VideoCalls/CallIcons.tsx +246 -0
- package/src/components/VideoCalls/VideoCallOverlay.tsx +627 -0
- package/src/components/VideoCalls/VideoCallSession.tsx +675 -0
- package/src/components/VideoCalls/livekitRuntime.ts +100 -0
- package/src/components/VideoCalls/useCallKeep.ts +252 -0
- package/src/components/styled/AudioMessage.tsx +97 -37
- package/src/components/styled/RoomListComponents/index.tsx +15 -3
- package/src/components/styled/SendInput.tsx +94 -51
- package/src/components/styled/StyledComponents.ts +9 -6
- package/src/components/styled/StyledInputComponents/Composing.tsx +7 -1
- package/src/components/styled/VideoMessage.tsx +114 -20
- package/src/context/xmppProvider.tsx +14 -1
- package/src/helpers/callLogMessage.ts +174 -0
- package/src/helpers/callPush.ts +90 -0
- package/src/helpers/constants/LANGUAGE_OPTIONS.ts +20 -5
- package/src/helpers/createUserNameFromSetUser.ts +68 -2
- package/src/helpers/getDataFromXml.ts +40 -4
- package/src/helpers/incomingCallFromPush.ts +83 -0
- package/src/helpers/insertMessageWithDelimiter.ts +27 -9
- package/src/helpers/isUnresolvedSenderId.ts +25 -0
- package/src/hooks/useChatSettingState.tsx +4 -0
- package/src/hooks/useMessageTranslation.ts +70 -0
- package/src/hooks/usePushNotifications.ts +15 -3
- package/src/hooks/useSendMessage.tsx +18 -5
- package/src/i18n/strings.ts +1322 -0
- package/src/i18n/useT.ts +56 -0
- package/src/main.ts +18 -1
- package/src/networking/api-requests/auth.api.ts +79 -44
- package/src/networking/api-requests/push.api.ts +39 -8
- package/src/networking/api-requests/rooms.api.ts +109 -1
- package/src/networking/callTokenStanza.ts +636 -0
- package/src/networking/outboundQueue.ts +1 -0
- package/src/networking/stanzaHandlers.ts +74 -15
- package/src/networking/xmpp/handleStanzas.xmpp.ts +52 -11
- package/src/networking/xmpp/sendTextMessage.xmpp.ts +1 -1
- package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +41 -5
- package/src/networking/xmppClient.ts +97 -28
- package/src/roomStore/callSlice.ts +190 -0
- package/src/roomStore/chatSettingsSlice.ts +16 -0
- package/src/roomStore/index.ts +5 -0
- package/src/roomStore/persistence.ts +103 -3
- package/src/roomStore/roomsSlice.ts +149 -4
- package/src/types/models/language.model.ts +17 -1
- package/src/types/models/message.model.ts +9 -0
- package/src/types/types.ts +142 -2
- package/src/utils/translateModePolicy.ts +31 -0
|
@@ -9,12 +9,14 @@ import {
|
|
|
9
9
|
setCurrentRoom,
|
|
10
10
|
setRoomRole,
|
|
11
11
|
updateRoom,
|
|
12
|
+
mergeUsersSet,
|
|
12
13
|
} from '../roomStore/roomsSlice';
|
|
13
14
|
import { IRoom, RoomMember } from '../types/types';
|
|
14
15
|
import { createMessageFromXml } from '../helpers/createMessageFromXml';
|
|
15
16
|
import { getDataFromXml } from '../helpers/getDataFromXml';
|
|
16
17
|
import { setDeleteModal } from '../roomStore/chatSettingsSlice';
|
|
17
18
|
import { messageNotificationManager } from '../utils/messageNotificationManager';
|
|
19
|
+
import { transformCallLogMessage } from '../helpers/callLogMessage';
|
|
18
20
|
|
|
19
21
|
// TO DO: we are thinking to refactor this code in the following way:
|
|
20
22
|
// each stanza will be parsed for 'type'
|
|
@@ -51,10 +53,21 @@ const onRealtimeMessage = async (stanza: Element) => {
|
|
|
51
53
|
return;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
// Not every sender stamps `senderJID` onto `<data>` — the web SDK's
|
|
57
|
+
// translate-tagged send path in particular builds `<data>` from a
|
|
58
|
+
// differently-named attr bag (roomJID/firstName/userMessage/…) that
|
|
59
|
+
// has no senderJID at all. This used to hard-drop the message here —
|
|
60
|
+
// live AND, via the identical check in onMessageHistory, in the MAM
|
|
61
|
+
// backfill too — so anything sent through that path just never
|
|
62
|
+
// appeared, on this device or after a restart. The stanza's own
|
|
63
|
+
// `from` is always the full MUC occupant jid (`room@conference/nick`,
|
|
64
|
+
// exactly what senderJID would have held), so fall back to it instead
|
|
65
|
+
// of dropping the message. Web's own onRealtimeMessage only requires
|
|
66
|
+
// `<data>` to exist at all — no senderJID check — so this brings RN
|
|
67
|
+
// to the same tolerance.
|
|
68
|
+
const senderJID = data.attrs.senderJID || stanza.attrs.from;
|
|
69
|
+
if (!senderJID) {
|
|
55
70
|
console.log(stanza.toString());
|
|
56
|
-
console.log(data.attrs.senderJID);
|
|
57
|
-
|
|
58
71
|
console.log('Missing sender information in real-time message.');
|
|
59
72
|
return;
|
|
60
73
|
}
|
|
@@ -66,17 +79,29 @@ const onRealtimeMessage = async (stanza: Element) => {
|
|
|
66
79
|
const parsed = await getDataFromXml(stanza);
|
|
67
80
|
const { data: pData, id: pId, body: pBody, ...pRest } =
|
|
68
81
|
parsed ?? ({} as Partial<NonNullable<typeof parsed>>);
|
|
82
|
+
const mergedData: Record<string, unknown> = { ...(pData || data.attrs) };
|
|
83
|
+
if (!mergedData.senderJID) {mergedData.senderJID = senderJID;}
|
|
69
84
|
// Cast at the call site: createMessageFromXml accepts the merged
|
|
70
85
|
// wrapped/positional shape; IUser type drift between models prevents
|
|
71
86
|
// a narrower type here without a wider refactor.
|
|
72
|
-
const
|
|
73
|
-
data:
|
|
87
|
+
const rawMessage = await createMessageFromXml({
|
|
88
|
+
data: mergedData,
|
|
74
89
|
id: pId || id,
|
|
75
90
|
body: pBody ?? '',
|
|
76
91
|
...pRest,
|
|
77
92
|
isDeleted: !!deleted || !!pRest?.deleted,
|
|
78
93
|
} as Parameters<typeof createMessageFromXml>[0]);
|
|
79
94
|
|
|
95
|
+
// Turn server call-state stanzas into a friendly call-log entry
|
|
96
|
+
// ("Outgoing call · 12 sec" / "Missed call"). Non-call messages pass
|
|
97
|
+
// through unchanged. Without this the raw message keeps body
|
|
98
|
+
// "call-state" and gets dropped by the call-signal filter in
|
|
99
|
+
// roomsSlice, so call history silently disappears.
|
|
100
|
+
const message = transformCallLogMessage(
|
|
101
|
+
rawMessage,
|
|
102
|
+
store.getState().chatSettingStore.user?.xmppUsername || ''
|
|
103
|
+
);
|
|
104
|
+
|
|
80
105
|
const roomJID = stanza.attrs.from.split('/')[0];
|
|
81
106
|
store.dispatch(
|
|
82
107
|
addRoomMessage({
|
|
@@ -90,8 +115,8 @@ const onRealtimeMessage = async (stanza: Element) => {
|
|
|
90
115
|
try {
|
|
91
116
|
const state = store.getState();
|
|
92
117
|
const currentUserWallet = (state.chatSettingStore.user?.walletAddress || '').toLowerCase();
|
|
93
|
-
const
|
|
94
|
-
if (currentUserWallet &&
|
|
118
|
+
const senderJIDLower = String(senderJID || '').toLowerCase();
|
|
119
|
+
if (currentUserWallet && senderJIDLower.includes(currentUserWallet)) {
|
|
95
120
|
return message; // own message, skip toast
|
|
96
121
|
}
|
|
97
122
|
const room = state.rooms.rooms[roomJID];
|
|
@@ -193,25 +218,44 @@ const onMessageHistory = async (stanza: any) => {
|
|
|
193
218
|
}
|
|
194
219
|
// console.log(stanza.attrs.from);
|
|
195
220
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
)
|
|
221
|
+
// Mirror the realtime path's tolerance: don't hard-require
|
|
222
|
+
// senderFirstName/senderLastName/senderJID on <data> — the web SDK's
|
|
223
|
+
// translate-tagged send path doesn't stamp any of them, and this used
|
|
224
|
+
// to drop those messages out of MAM backfill entirely (so they never
|
|
225
|
+
// appeared even after a restart). The inner forwarded <message>'s own
|
|
226
|
+
// `from` is the full MUC occupant jid (room@conference/nick), exactly
|
|
227
|
+
// what senderJID would have held — fall back to it. createMessageFromXml
|
|
228
|
+
// already derives a display name from the jid when senderFirstName/
|
|
229
|
+
// senderLastName are absent.
|
|
230
|
+
const innerFrom =
|
|
231
|
+
stanza
|
|
232
|
+
.getChild('result')
|
|
233
|
+
?.getChild('forwarded')
|
|
234
|
+
?.getChild('message')?.attrs?.from || stanza.attrs.from;
|
|
235
|
+
const senderJID = data?.attrs?.senderJID || innerFrom;
|
|
236
|
+
if (!data?.attrs || !senderJID) {
|
|
202
237
|
// console.log(
|
|
203
238
|
// "Missing sender information in message history.",
|
|
204
239
|
// stanza.toString()
|
|
205
240
|
// );
|
|
206
241
|
return;
|
|
207
242
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
243
|
+
const mergedAttrs = { ...data.attrs };
|
|
244
|
+
if (!mergedAttrs.senderJID) {mergedAttrs.senderJID = senderJID;}
|
|
245
|
+
const rawMessage = await createMessageFromXml(
|
|
246
|
+
mergedAttrs,
|
|
210
247
|
body,
|
|
211
248
|
id,
|
|
212
249
|
stanza.attrs.from,
|
|
213
250
|
!!deleted
|
|
214
251
|
);
|
|
252
|
+
|
|
253
|
+
// Same call-log transform as the realtime path, applied to archived
|
|
254
|
+
// history so calls received while offline still render as log entries.
|
|
255
|
+
const message = transformCallLogMessage(
|
|
256
|
+
rawMessage,
|
|
257
|
+
store.getState().chatSettingStore.user?.xmppUsername || ''
|
|
258
|
+
);
|
|
215
259
|
store.dispatch(
|
|
216
260
|
addRoomMessage({
|
|
217
261
|
roomJID: stanza.attrs.from,
|
|
@@ -349,6 +393,21 @@ const onGetMembers = (stanza: Element) => {
|
|
|
349
393
|
});
|
|
350
394
|
|
|
351
395
|
store.dispatch(updateRoom({ jid, updates: { roomMembers } }));
|
|
396
|
+
|
|
397
|
+
// Also feed the identity cache Message.tsx reads sender names from
|
|
398
|
+
// (state.rooms.usersSet). Keyed by both the bare local part and the
|
|
399
|
+
// full jid since a message's `user.id` can be either depending on
|
|
400
|
+
// how it was parsed (see createUserNameFromSetUser).
|
|
401
|
+
const usersSetUpdates: Record<string, RoomMember> = {};
|
|
402
|
+
for (const member of roomMembers) {
|
|
403
|
+
if (!member.jid) {continue;}
|
|
404
|
+
const local = member.jid.split('@')[0];
|
|
405
|
+
usersSetUpdates[local] = member;
|
|
406
|
+
usersSetUpdates[member.jid] = member;
|
|
407
|
+
}
|
|
408
|
+
if (Object.keys(usersSetUpdates).length > 0) {
|
|
409
|
+
store.dispatch(mergeUsersSet({ members: usersSetUpdates }));
|
|
410
|
+
}
|
|
352
411
|
} catch (err) {
|
|
353
412
|
console.warn('onGetMembers parse failed', err);
|
|
354
413
|
}
|
|
@@ -18,22 +18,63 @@ import {
|
|
|
18
18
|
onMessageError,
|
|
19
19
|
} from '../stanzaHandlers';
|
|
20
20
|
import XmppClient from '../xmppClient';
|
|
21
|
+
import { onCallTokenMessage } from '../callTokenStanza';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Unwrap a mucsub event wrapper so the chat handlers see the real inner
|
|
25
|
+
* `<message>` (the one carrying `<data senderJID=…>` and `<body>`).
|
|
26
|
+
*
|
|
27
|
+
* We subscribe every room to `urn:xmpp:mucsub:nodes:messages` (see
|
|
28
|
+
* subscribeToRoomMessages / pushSubscriptionService), so ejabberd pushes
|
|
29
|
+
* room traffic as:
|
|
30
|
+
*
|
|
31
|
+
* <message from="room@conference/…">
|
|
32
|
+
* <event xmlns="http://jabber.org/protocol/pubsub#event">
|
|
33
|
+
* <items node="urn:xmpp:mucsub:nodes:messages">
|
|
34
|
+
* <item><message …><data senderJID=…/><body>…</body></message></item>
|
|
35
|
+
*
|
|
36
|
+
* Without unwrapping, onRealtimeMessage reads `<data>` off the OUTER
|
|
37
|
+
* wrapper, finds nothing, logs "Missing data elements in real-time
|
|
38
|
+
* message" and drops the stanza — so live messages never render and only
|
|
39
|
+
* surface later through the MAM history fetch (i.e. after an app restart
|
|
40
|
+
* or re-opening the room). Mirrors the web SDK's handleStanza.
|
|
41
|
+
*/
|
|
42
|
+
const unwrapMucsubMessage = (stanza: Element): Element => {
|
|
43
|
+
const inner = (stanza as any)
|
|
44
|
+
?.getChild?.('event', 'http://jabber.org/protocol/pubsub#event')
|
|
45
|
+
?.getChild?.('items')
|
|
46
|
+
?.getChild?.('item')
|
|
47
|
+
?.getChild?.('message');
|
|
48
|
+
return (inner as Element) || stanza;
|
|
49
|
+
};
|
|
21
50
|
|
|
22
51
|
export function handleStanza(stanza: Element, xmppWs: XmppClient) {
|
|
23
52
|
if (stanza?.attrs?.type === 'headline') {return;}
|
|
53
|
+
|
|
54
|
+
// Call signaling is swallowed before any chat handler sees it. A
|
|
55
|
+
// `<data type="call-*">` frame is not user-visible content, and letting
|
|
56
|
+
// it through renders bubbles reading "Deleted User: call-state" and
|
|
57
|
+
// fires new-message notifications for a call that never happened.
|
|
58
|
+
// Returns false for server call-LOGS, which do belong in the chat.
|
|
59
|
+
if (stanza?.name === 'message' && onCallTokenMessage(stanza)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
24
63
|
switch (stanza.name) {
|
|
25
|
-
case 'message':
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
64
|
+
case 'message': {
|
|
65
|
+
const unwrapped = unwrapMucsubMessage(stanza);
|
|
66
|
+
onMessageError(unwrapped, xmppWs);
|
|
67
|
+
onReactionMessage(unwrapped);
|
|
68
|
+
onReactionHistory(unwrapped);
|
|
69
|
+
onDeleteMessage(unwrapped);
|
|
70
|
+
onEditMessage(unwrapped);
|
|
71
|
+
onChatInvite(unwrapped, xmppWs);
|
|
72
|
+
onRealtimeMessage(unwrapped);
|
|
73
|
+
onMessageHistory(unwrapped);
|
|
74
|
+
handleComposing(unwrapped, xmppWs.username);
|
|
75
|
+
onPresenceInRoom(unwrapped);
|
|
36
76
|
break;
|
|
77
|
+
}
|
|
37
78
|
case 'presence':
|
|
38
79
|
onRoomKicked(stanza);
|
|
39
80
|
onPresenceInRoom(stanza);
|
|
@@ -12,7 +12,7 @@ let _sendTextSeq = 0;
|
|
|
12
12
|
*
|
|
13
13
|
* Mirrors web's `SERVICE` derivation (utils/runtimeHostConfig.ts).
|
|
14
14
|
*/
|
|
15
|
-
const toServiceXmlns = (devServer: string | undefined, client: Client): string => {
|
|
15
|
+
export const toServiceXmlns = (devServer: string | undefined, client: Client): string => {
|
|
16
16
|
// Prefer the URL the client is actually connected to — guaranteed to
|
|
17
17
|
// be the one the server expects.
|
|
18
18
|
const clientService = (client as any)?.options?.service as string | undefined;
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { Client, xml } from '@xmpp/client';
|
|
2
2
|
import { Iso639_1Codes } from '../../types/types';
|
|
3
|
+
import { toServiceXmlns } from './sendTextMessage.xmpp';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Same wire message as `sendTextMessage`, plus a `<translate source="xx"/>`
|
|
7
|
+
* child that DECLARES the message's source language so the backend can
|
|
8
|
+
* translate it for readers in other languages. No pre-translation happens
|
|
9
|
+
* client-side.
|
|
10
|
+
*
|
|
11
|
+
* The `<data>` element MUST be built identically to `sendTextMessage`
|
|
12
|
+
* (correct `xmlns` = the `wss://<host>/ws` service URL, and the
|
|
13
|
+
* `senderFirstName` / `senderLastName` / `senderJID` / `roomJid` attr
|
|
14
|
+
* names the server + parser expect). An earlier version spread a loose
|
|
15
|
+
* `stanzaMessage` bag into `<data>` with no xmlns and mismatched attr
|
|
16
|
+
* names — the server silently dropped those stanzas, so no echo came back
|
|
17
|
+
* and every sent message stayed stuck in the "pending" state. Keep this in
|
|
18
|
+
* lockstep with sendTextMessage.xmpp.ts.
|
|
19
|
+
*/
|
|
4
20
|
export const sendTextMessageWithTranslateTag = (
|
|
5
21
|
client: Client,
|
|
6
22
|
stanzaMessage: {
|
|
@@ -18,27 +34,47 @@ export const sendTextMessageWithTranslateTag = (
|
|
|
18
34
|
},
|
|
19
35
|
source: Iso639_1Codes,
|
|
20
36
|
customId?: string
|
|
21
|
-
) => {
|
|
22
|
-
const id = customId || `
|
|
37
|
+
): boolean => {
|
|
38
|
+
const id = customId || `send-text-message-${Date.now()}`;
|
|
23
39
|
|
|
24
40
|
try {
|
|
41
|
+
const dataXmlns = toServiceXmlns(stanzaMessage.devServer, client);
|
|
25
42
|
const message = xml(
|
|
26
43
|
'message',
|
|
27
44
|
{
|
|
28
45
|
to: stanzaMessage.roomJID,
|
|
29
46
|
type: 'groupchat',
|
|
30
|
-
id
|
|
47
|
+
id,
|
|
31
48
|
},
|
|
32
49
|
xml('data', {
|
|
33
|
-
|
|
50
|
+
xmlns: dataXmlns,
|
|
51
|
+
senderFirstName: stanzaMessage.firstName,
|
|
52
|
+
senderLastName: stanzaMessage.lastName,
|
|
53
|
+
fullName: `${stanzaMessage.firstName} ${stanzaMessage.lastName}`,
|
|
54
|
+
photoURL: stanzaMessage.photo,
|
|
55
|
+
senderJID: client.jid?.toString(),
|
|
56
|
+
senderWalletAddress: stanzaMessage.walletAddress,
|
|
57
|
+
roomJid: stanzaMessage.roomJID,
|
|
58
|
+
isSystemMessage: false,
|
|
59
|
+
tokenAmount: 0,
|
|
60
|
+
quickReplies: '',
|
|
61
|
+
notDisplayedValue: '',
|
|
62
|
+
showInChannel: stanzaMessage.showInChannel || false,
|
|
63
|
+
isReply: stanzaMessage.isReply || false,
|
|
64
|
+
mainMessage: stanzaMessage.mainMessage || '',
|
|
34
65
|
push: 'true',
|
|
35
66
|
}),
|
|
36
67
|
xml('body', {}, stanzaMessage.userMessage),
|
|
37
|
-
|
|
68
|
+
// `<translate source>` only DECLARES the language this text is in; it
|
|
69
|
+
// costs nothing to send and is what lets each reader translate the
|
|
70
|
+
// message into their own language on their side.
|
|
71
|
+
xml('translate', { source })
|
|
38
72
|
);
|
|
39
73
|
|
|
40
74
|
client.send(message);
|
|
75
|
+
return true;
|
|
41
76
|
} catch (error) {
|
|
42
77
|
console.error('An error occurred while sending message:', error);
|
|
78
|
+
return false;
|
|
43
79
|
}
|
|
44
80
|
};
|
|
@@ -10,6 +10,7 @@ import { sendTypingRequest } from './xmpp/sendTypingRequest.xmpp';
|
|
|
10
10
|
import { sendPing } from './xmpp/sendPing.xmpp';
|
|
11
11
|
import { getHistory } from './xmpp/getHistory.xmpp';
|
|
12
12
|
import { sendTextMessage } from './xmpp/sendTextMessage.xmpp';
|
|
13
|
+
import { sendTextMessageWithTranslateTag } from './xmpp/sendTextMessageWithTranslateTag.xmpp';
|
|
13
14
|
import { deleteMessage } from './xmpp/deleteMessage.xmpp';
|
|
14
15
|
import { presenceInRoom } from './xmpp/presenceInRoom.xmpp';
|
|
15
16
|
import { getLastMessage } from './xmpp/getLastMessageArchive.xmpp';
|
|
@@ -35,6 +36,31 @@ import {
|
|
|
35
36
|
// Canonical production XMPP WSS endpoint (standard wss/443, no port suffix).
|
|
36
37
|
const DEFAULT_DEV_SERVER = 'xmpp.chat.ethora.com';
|
|
37
38
|
|
|
39
|
+
// How long to wait for the old client's stop() during a reconnect before
|
|
40
|
+
// giving up on it. Short on purpose: we are already tearing this client
|
|
41
|
+
// down, and a socket that hasn't closed in 3s is exactly the dead one we
|
|
42
|
+
// must not block on. See the call site in reconnect().
|
|
43
|
+
const STOP_TIMEOUT_MS = 3000;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Resolve when `promise` settles or when `ms` elapses, whichever is first.
|
|
47
|
+
* Never rejects: a teardown that fails or hangs must not break the caller's
|
|
48
|
+
* control flow (that is the whole point of using it around stop()).
|
|
49
|
+
*/
|
|
50
|
+
function withTimeout(promise: Promise<unknown>, ms: number): Promise<void> {
|
|
51
|
+
return new Promise<void>((resolve) => {
|
|
52
|
+
let settled = false;
|
|
53
|
+
const done = () => {
|
|
54
|
+
if (settled) {return;}
|
|
55
|
+
settled = true;
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
resolve();
|
|
58
|
+
};
|
|
59
|
+
const timer = setTimeout(done, ms);
|
|
60
|
+
Promise.resolve(promise).then(done, done);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
38
64
|
// @xmpp/client surfaces SASL/stream errors in a few shapes depending on
|
|
39
65
|
// where it fails — XMPPError on stream:error, SASLError on SASL bind, or
|
|
40
66
|
// a generic Error whose message contains "not-authorized". Match all of
|
|
@@ -697,9 +723,17 @@ export class XmppClient {
|
|
|
697
723
|
const old = this.client;
|
|
698
724
|
if (old) {
|
|
699
725
|
this.detachEventListeners();
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
726
|
+
// NEVER await a bare stop(): on a half-dead socket (the exact case
|
|
727
|
+
// we're reconnecting for) @xmpp/client's stop() can hang forever
|
|
728
|
+
// waiting on a close handshake that never lands. That leaves this
|
|
729
|
+
// function parked before `finally`, so `reconnecting` stays true and
|
|
730
|
+
// EVERY later reconnect — watchdog, NetInfo, AppState — silently
|
|
731
|
+
// returns at the single-flight guard. The client then never comes
|
|
732
|
+
// back until the app is killed, which reads as "new messages just
|
|
733
|
+
// stop arriving". Cap the teardown and move on: initializeClient()
|
|
734
|
+
// replaces `this.client` anyway, and the old one's listeners are
|
|
735
|
+
// already detached above, so a late-settling stop() is harmless.
|
|
736
|
+
await withTimeout(old.stop(), STOP_TIMEOUT_MS);
|
|
703
737
|
}
|
|
704
738
|
this.initializeClient();
|
|
705
739
|
} finally {
|
|
@@ -755,12 +789,17 @@ export class XmppClient {
|
|
|
755
789
|
// handshake can't re-enter handleStanza and dispatch into a store
|
|
756
790
|
// that's being wiped (or, on re-login, the new session's store).
|
|
757
791
|
this.detachEventListeners();
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
792
|
+
// Bounded like the reconnect teardown: a stop() that never settles on
|
|
793
|
+
// a dead socket would otherwise hang logout (the LOGOUT_EVENT handler
|
|
794
|
+
// awaits this) and leave the app wedged on the sign-out screen. The
|
|
795
|
+
// rejection is still logged — only the *waiting* is capped.
|
|
796
|
+
await withTimeout(
|
|
797
|
+
Promise.resolve(this.client.stop()).catch((error: unknown) => {
|
|
798
|
+
console.error('Error closing the xmpp client:', error);
|
|
799
|
+
}),
|
|
800
|
+
STOP_TIMEOUT_MS
|
|
801
|
+
);
|
|
802
|
+
console.log('XMPP client connection closed.');
|
|
764
803
|
}
|
|
765
804
|
this.status = 'offline';
|
|
766
805
|
this.presencesReady = false;
|
|
@@ -1031,6 +1070,13 @@ export class XmppClient {
|
|
|
1031
1070
|
console.warn('sendMessageReactionStanza: not implemented in RN xmpp client');
|
|
1032
1071
|
}
|
|
1033
1072
|
|
|
1073
|
+
// Sends a groupchat message carrying a `<translate source="xx"/>` tag so
|
|
1074
|
+
// the backend knows the message's source language and can translate it
|
|
1075
|
+
// for each reader (mirrors the web SDK's send path). `langSource` is the
|
|
1076
|
+
// sender's own language; it only DECLARES the source, no pre-translation
|
|
1077
|
+
// happens client-side. Structure mirrors `sendMessage`: buffer + replay
|
|
1078
|
+
// when the stream isn't ready so a reconnect flush re-sends it, and
|
|
1079
|
+
// forward `customId` so the optimistic bubble reconciles with the echo.
|
|
1034
1080
|
sendTextMessageWithTranslateTagStanza(
|
|
1035
1081
|
roomJID: string,
|
|
1036
1082
|
firstName: string,
|
|
@@ -1042,26 +1088,49 @@ export class XmppClient {
|
|
|
1042
1088
|
isReply?: boolean,
|
|
1043
1089
|
showInChannel?: boolean,
|
|
1044
1090
|
mainMessage?: string,
|
|
1045
|
-
|
|
1091
|
+
langSource?: string,
|
|
1046
1092
|
customId?: string
|
|
1047
|
-
) {
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1093
|
+
): boolean {
|
|
1094
|
+
const source = (langSource || 'en') as any;
|
|
1095
|
+
if (!this.isStreamReady()) {
|
|
1096
|
+
enqueueOutboundSend({
|
|
1097
|
+
optimisticId: customId || `send-text-message-${Date.now()}`,
|
|
1098
|
+
roomJID,
|
|
1099
|
+
enqueuedAt: Date.now(),
|
|
1100
|
+
send: (c) =>
|
|
1101
|
+
c.sendTextMessageWithTranslateTagStanza(
|
|
1102
|
+
roomJID,
|
|
1103
|
+
firstName,
|
|
1104
|
+
lastName,
|
|
1105
|
+
photo,
|
|
1106
|
+
walletAddress,
|
|
1107
|
+
userMessage,
|
|
1108
|
+
notDisplayedValue,
|
|
1109
|
+
isReply,
|
|
1110
|
+
showInChannel,
|
|
1111
|
+
mainMessage,
|
|
1112
|
+
langSource,
|
|
1113
|
+
customId
|
|
1114
|
+
),
|
|
1115
|
+
});
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
return sendTextMessageWithTranslateTag(
|
|
1119
|
+
this.client,
|
|
1120
|
+
{
|
|
1121
|
+
roomJID,
|
|
1122
|
+
firstName,
|
|
1123
|
+
lastName,
|
|
1124
|
+
photo,
|
|
1125
|
+
walletAddress,
|
|
1126
|
+
userMessage,
|
|
1127
|
+
notDisplayedValue,
|
|
1128
|
+
isReply,
|
|
1129
|
+
showInChannel,
|
|
1130
|
+
mainMessage,
|
|
1131
|
+
devServer: this.devServer || DEFAULT_DEV_SERVER,
|
|
1132
|
+
},
|
|
1133
|
+
source,
|
|
1065
1134
|
customId
|
|
1066
1135
|
);
|
|
1067
1136
|
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
|
|
2
|
+
|
|
3
|
+
export type CallPhase =
|
|
4
|
+
| 'idle'
|
|
5
|
+
| 'requesting'
|
|
6
|
+
| 'ringing-incoming'
|
|
7
|
+
| 'connecting'
|
|
8
|
+
| 'in-call'
|
|
9
|
+
| 'error';
|
|
10
|
+
|
|
11
|
+
export type CallDirection = 'outgoing' | 'incoming' | null;
|
|
12
|
+
export type CallKind = 'audio' | 'video';
|
|
13
|
+
|
|
14
|
+
export interface CallState {
|
|
15
|
+
phase: CallPhase;
|
|
16
|
+
direction: CallDirection;
|
|
17
|
+
kind: CallKind;
|
|
18
|
+
roomJid: string | null;
|
|
19
|
+
roomName: string | null;
|
|
20
|
+
// Bare room name (JID localpart). Server's call-state stanzas reference
|
|
21
|
+
// calls by this value, and we echo it back on hangup signaling.
|
|
22
|
+
roomBareName: string | null;
|
|
23
|
+
// Stable callId from the call-token data attr (or JWT metadata). Used
|
|
24
|
+
// when emitting our own call-state hangup so the peer can correlate.
|
|
25
|
+
callId: string | null;
|
|
26
|
+
// Peer's XMPP localpart (bare username, no @host). For outgoing we
|
|
27
|
+
// resolve it from members[]; for incoming we derive it from the room
|
|
28
|
+
// name format "<userA>-<userB>" minus our own username.
|
|
29
|
+
peerXmppUsername: string | null;
|
|
30
|
+
token: string | null;
|
|
31
|
+
error: string | null;
|
|
32
|
+
startedAt: number | null;
|
|
33
|
+
// When the call actually connected (phase -> 'in-call'). Null until then.
|
|
34
|
+
// Used to compute a duration for the local "call ended" log fallback.
|
|
35
|
+
connectedAt: number | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const initialState: CallState = {
|
|
39
|
+
phase: 'idle',
|
|
40
|
+
direction: null,
|
|
41
|
+
kind: 'video',
|
|
42
|
+
roomJid: null,
|
|
43
|
+
roomName: null,
|
|
44
|
+
roomBareName: null,
|
|
45
|
+
callId: null,
|
|
46
|
+
peerXmppUsername: null,
|
|
47
|
+
token: null,
|
|
48
|
+
error: null,
|
|
49
|
+
startedAt: null,
|
|
50
|
+
connectedAt: null,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const resetState = (): CallState => ({ ...initialState });
|
|
54
|
+
|
|
55
|
+
const callSlice = createSlice({
|
|
56
|
+
name: 'call',
|
|
57
|
+
initialState,
|
|
58
|
+
reducers: {
|
|
59
|
+
startOutgoingCall(
|
|
60
|
+
state,
|
|
61
|
+
action: PayloadAction<{
|
|
62
|
+
roomJid: string;
|
|
63
|
+
roomName?: string | null;
|
|
64
|
+
roomBareName?: string | null;
|
|
65
|
+
kind?: CallKind;
|
|
66
|
+
peerXmppUsername?: string | null;
|
|
67
|
+
}>
|
|
68
|
+
) {
|
|
69
|
+
state.phase = 'requesting';
|
|
70
|
+
state.direction = 'outgoing';
|
|
71
|
+
state.kind = action.payload.kind || 'video';
|
|
72
|
+
state.roomJid = action.payload.roomJid;
|
|
73
|
+
state.roomName = action.payload.roomName || null;
|
|
74
|
+
state.roomBareName =
|
|
75
|
+
action.payload.roomBareName ||
|
|
76
|
+
(action.payload.roomJid || '').split('@')[0] ||
|
|
77
|
+
null;
|
|
78
|
+
state.peerXmppUsername = action.payload.peerXmppUsername || null;
|
|
79
|
+
state.callId = null;
|
|
80
|
+
state.token = null;
|
|
81
|
+
state.error = null;
|
|
82
|
+
state.startedAt = Date.now();
|
|
83
|
+
state.connectedAt = null;
|
|
84
|
+
},
|
|
85
|
+
setIncomingCallToken(
|
|
86
|
+
state,
|
|
87
|
+
action: PayloadAction<{
|
|
88
|
+
roomJid: string;
|
|
89
|
+
roomName?: string | null;
|
|
90
|
+
roomBareName?: string | null;
|
|
91
|
+
token: string;
|
|
92
|
+
kind?: CallKind;
|
|
93
|
+
callId?: string | null;
|
|
94
|
+
peerXmppUsername?: string | null;
|
|
95
|
+
}>
|
|
96
|
+
) {
|
|
97
|
+
state.phase = 'ringing-incoming';
|
|
98
|
+
state.direction = 'incoming';
|
|
99
|
+
state.kind = action.payload.kind || 'video';
|
|
100
|
+
state.roomJid = action.payload.roomJid;
|
|
101
|
+
state.roomName = action.payload.roomName || null;
|
|
102
|
+
state.roomBareName =
|
|
103
|
+
action.payload.roomBareName ||
|
|
104
|
+
(action.payload.roomJid || '').split('@')[0] ||
|
|
105
|
+
null;
|
|
106
|
+
state.callId = action.payload.callId || null;
|
|
107
|
+
state.peerXmppUsername = action.payload.peerXmppUsername || null;
|
|
108
|
+
state.token = action.payload.token;
|
|
109
|
+
state.error = null;
|
|
110
|
+
state.startedAt = Date.now();
|
|
111
|
+
state.connectedAt = null;
|
|
112
|
+
},
|
|
113
|
+
setOutgoingCallToken(
|
|
114
|
+
state,
|
|
115
|
+
action: PayloadAction<{
|
|
116
|
+
roomJid: string;
|
|
117
|
+
token: string;
|
|
118
|
+
callId?: string | null;
|
|
119
|
+
}>
|
|
120
|
+
) {
|
|
121
|
+
if (state.direction !== 'outgoing') {return;}
|
|
122
|
+
|
|
123
|
+
const currentRoom = state.roomJid || '';
|
|
124
|
+
if (currentRoom && currentRoom !== action.payload.roomJid) {return;}
|
|
125
|
+
|
|
126
|
+
state.phase = 'connecting';
|
|
127
|
+
state.roomJid = action.payload.roomJid;
|
|
128
|
+
state.token = action.payload.token;
|
|
129
|
+
if (action.payload.callId) {state.callId = action.payload.callId;}
|
|
130
|
+
state.error = null;
|
|
131
|
+
state.startedAt = state.startedAt || Date.now();
|
|
132
|
+
},
|
|
133
|
+
acceptIncomingCall(state) {
|
|
134
|
+
if (state.direction !== 'incoming') {return;}
|
|
135
|
+
state.phase = 'connecting';
|
|
136
|
+
state.error = null;
|
|
137
|
+
state.startedAt = state.startedAt || Date.now();
|
|
138
|
+
},
|
|
139
|
+
declineIncomingCall() {
|
|
140
|
+
return resetState();
|
|
141
|
+
},
|
|
142
|
+
endCall() {
|
|
143
|
+
return resetState();
|
|
144
|
+
},
|
|
145
|
+
setCallError(state, action: PayloadAction<string>) {
|
|
146
|
+
state.phase = 'error';
|
|
147
|
+
state.error = action.payload;
|
|
148
|
+
state.startedAt = state.startedAt || Date.now();
|
|
149
|
+
},
|
|
150
|
+
setCallPhase(state, action: PayloadAction<CallPhase>) {
|
|
151
|
+
state.phase = action.payload;
|
|
152
|
+
if (action.payload === 'in-call') {
|
|
153
|
+
state.error = null;
|
|
154
|
+
// Anchor the connect moment once, so a mid-call reconnect blip
|
|
155
|
+
// doesn't reset the duration used by the local call-end log.
|
|
156
|
+
state.connectedAt = state.connectedAt || Date.now();
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
// Patch the call kind in-place. Used when the server's call-token
|
|
160
|
+
// stanza doesn't carry a `kind` attribute and we receive the
|
|
161
|
+
// client-side `call-invite` hint AFTER the call-token has already
|
|
162
|
+
// landed (race window: token relays through server, invite is direct
|
|
163
|
+
// chat, normally invite wins but not always).
|
|
164
|
+
setCallKind(state, action: PayloadAction<CallKind>) {
|
|
165
|
+
if (state.phase === 'idle') {return;}
|
|
166
|
+
state.kind = action.payload;
|
|
167
|
+
},
|
|
168
|
+
resetCall() {
|
|
169
|
+
return resetState();
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
extraReducers: (builder) => {
|
|
173
|
+
builder.addCase('chatSettingStore/logout' as any, () => resetState());
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
export const {
|
|
178
|
+
startOutgoingCall,
|
|
179
|
+
setIncomingCallToken,
|
|
180
|
+
setOutgoingCallToken,
|
|
181
|
+
acceptIncomingCall,
|
|
182
|
+
declineIncomingCall,
|
|
183
|
+
endCall,
|
|
184
|
+
setCallError,
|
|
185
|
+
setCallPhase,
|
|
186
|
+
setCallKind,
|
|
187
|
+
resetCall,
|
|
188
|
+
} = callSlice.actions;
|
|
189
|
+
|
|
190
|
+
export default callSlice.reducer;
|