@ethora/chat-component-rn 26.5.20 → 26.6.10
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 +43 -3
- package/index.js +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +34 -9
- 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/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/AttachSheet/AttachSheet.js +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +6 -0
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +26 -8
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalHeaderComponent.js +15 -1
- package/lib/commonjs/components/Modals/ModalHeaderComponent.js.map +1 -1
- 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 +111 -51
- 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/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/getElementFont.js +29 -0
- package/lib/commonjs/helpers/getElementFont.js.map +1 -0
- package/lib/commonjs/helpers/headerLayout.js +35 -0
- package/lib/commonjs/helpers/headerLayout.js.map +1 -0
- 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 +12 -2
- 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/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 +34 -9
- 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/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/AttachSheet/AttachSheet.js +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +6 -0
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +27 -9
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/ModalHeaderComponent.js +15 -1
- package/lib/module/components/Modals/ModalHeaderComponent.js.map +1 -1
- 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 +112 -52
- 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/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/getElementFont.js +24 -0
- package/lib/module/helpers/getElementFont.js.map +1 -0
- package/lib/module/helpers/headerLayout.js +30 -0
- package/lib/module/helpers/headerLayout.js.map +1 -0
- 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 +12 -2
- 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/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/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/Modals/AttachSheet/AttachSheet.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/ModalHeaderComponent.d.ts +3 -0
- package/lib/typescript/components/Modals/ModalHeaderComponent.d.ts.map +1 -1
- 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/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/getElementFont.d.ts +13 -0
- package/lib/typescript/helpers/getElementFont.d.ts.map +1 -0
- package/lib/typescript/helpers/headerLayout.d.ts +26 -0
- package/lib/typescript/helpers/headerLayout.d.ts.map +1 -0
- 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/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 +165 -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 +44 -11
- 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/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/AttachSheet/AttachSheet.tsx +1 -3
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +10 -4
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +25 -8
- package/src/components/Modals/ModalHeaderComponent.tsx +20 -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 +125 -55
- package/src/components/styled/StyledComponents.ts +9 -6
- package/src/components/styled/StyledInputComponents/Composing.tsx +7 -1
- 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/getElementFont.ts +25 -0
- package/src/helpers/headerLayout.ts +30 -0
- 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 +15 -2
- 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/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 +178 -2
- package/src/utils/translateModePolicy.ts +31 -0
|
@@ -25,6 +25,7 @@ import Button from '../styled/Button';
|
|
|
25
25
|
import { HeaderRoomList } from '../Header/HeaderRoomList';
|
|
26
26
|
import { HeaderRoomListMenu } from '../Menu/HeaderRoomListMenu';
|
|
27
27
|
import { getIconColor } from '../../helpers/getIconColor';
|
|
28
|
+
import { useT } from '../../i18n/useT';
|
|
28
29
|
|
|
29
30
|
const LONG_PRESS_THRESHOLD = 200;
|
|
30
31
|
|
|
@@ -40,6 +41,7 @@ const RoomList: React.FC<RoomListProps> = ({
|
|
|
40
41
|
onRoomClick,
|
|
41
42
|
}) => {
|
|
42
43
|
const { config } = useChatSettingState();
|
|
44
|
+
const t = useT();
|
|
43
45
|
|
|
44
46
|
const [open, setOpen] = useState(false);
|
|
45
47
|
const [searchTerm, setSearchTerm] = useState('');
|
|
@@ -178,6 +180,20 @@ const RoomList: React.FC<RoomListProps> = ({
|
|
|
178
180
|
<>
|
|
179
181
|
<View style={styles.scrollContainer}>
|
|
180
182
|
<HeaderRoomList setDrawerOpen={toggleDrawer} />
|
|
183
|
+
{/* Search sits ABOVE the list rather than in its
|
|
184
|
+
ListHeaderComponent. As a list header it was simply the
|
|
185
|
+
first scrolling row, so the moment you scrolled the rooms
|
|
186
|
+
it slid up and disappeared behind the opaque header band.
|
|
187
|
+
Fixed here it stays reachable, which is the entire point
|
|
188
|
+
of a search field over a long list. */}
|
|
189
|
+
<View style={styles.searchBar}>
|
|
190
|
+
<SearchInput
|
|
191
|
+
icon={<SearchIcon height={20} />}
|
|
192
|
+
value={searchTerm}
|
|
193
|
+
onChangeText={handleSearchChange}
|
|
194
|
+
placeholder={t('search.placeholder')}
|
|
195
|
+
/>
|
|
196
|
+
</View>
|
|
181
197
|
<FlatList
|
|
182
198
|
data={filteredChats}
|
|
183
199
|
keyExtractor={(item) => item.jid}
|
|
@@ -195,14 +211,6 @@ const RoomList: React.FC<RoomListProps> = ({
|
|
|
195
211
|
<ChatRoomItem chat={item} config={config} />
|
|
196
212
|
</Pressable>
|
|
197
213
|
)}
|
|
198
|
-
ListHeaderComponent={
|
|
199
|
-
<SearchInput
|
|
200
|
-
icon={<SearchIcon height={20} />}
|
|
201
|
-
value={searchTerm}
|
|
202
|
-
onChangeText={handleSearchChange}
|
|
203
|
-
placeholder="Search..."
|
|
204
|
-
/>
|
|
205
|
-
}
|
|
206
214
|
style={styles.chatList}
|
|
207
215
|
/>
|
|
208
216
|
|
|
@@ -241,9 +249,19 @@ const styles = StyleSheet.create({
|
|
|
241
249
|
padding: 16,
|
|
242
250
|
justifyContent: 'space-between',
|
|
243
251
|
},
|
|
252
|
+
searchBar: {
|
|
253
|
+
// `row` matters: SearchInputWrapper is `flex: 1` plus a fixed 44px
|
|
254
|
+
// height. In a column parent that flex resolves VERTICALLY against a
|
|
255
|
+
// parent with no height of its own and collapses the field to nothing
|
|
256
|
+
// but its magnifier. As a row it resolves to width, which is what it
|
|
257
|
+
// meant back when the field was a list-header child.
|
|
258
|
+
flexDirection: 'row',
|
|
259
|
+
paddingTop: 8,
|
|
260
|
+
paddingHorizontal: 16,
|
|
261
|
+
backgroundColor: '#FAFAFA',
|
|
262
|
+
},
|
|
244
263
|
chatList: {
|
|
245
264
|
flex: 1,
|
|
246
|
-
paddingTop: 8,
|
|
247
265
|
paddingHorizontal: 16,
|
|
248
266
|
backgroundColor: '#FAFAFA',
|
|
249
267
|
},
|
|
@@ -25,7 +25,11 @@ import { setActiveMessage, setEditAction } from '../../roomStore/roomsSlice';
|
|
|
25
25
|
import styled from 'styled-components/native';
|
|
26
26
|
import { IUser, MessageProps } from '../../types/types';
|
|
27
27
|
import MediaMessage from '../MainComponents/MediaMessage';
|
|
28
|
-
import
|
|
28
|
+
import MessageTranslate from './MessageTranslate';
|
|
29
|
+
import { isUnresolvedSenderId } from '../../helpers/isUnresolvedSenderId';
|
|
30
|
+
import TranslatedMessageBody from './TranslatedMessageBody';
|
|
31
|
+
import { useMessageTranslation } from '../../hooks/useMessageTranslation';
|
|
32
|
+
import { resolveTranslateMode } from '../../utils/translateModePolicy';
|
|
29
33
|
import { useChatSettingState } from '../../hooks/useChatSettingState';
|
|
30
34
|
import { parseMessageBody } from '../../helpers/parseMessageBody';
|
|
31
35
|
import { chatTextStyle } from '../../helpers/typography';
|
|
@@ -139,7 +143,69 @@ const CustomTimestampRow = styled.View<{media: boolean}>`
|
|
|
139
143
|
const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
140
144
|
const dispatch = useDispatch();
|
|
141
145
|
const { client } = useXmppClient();
|
|
142
|
-
const { config, langSource, user} = useChatSettingState();
|
|
146
|
+
const { config, langSource, user, translateMode } = useChatSettingState();
|
|
147
|
+
|
|
148
|
+
// `enableTranslates` predates the `translates` config block; keep it
|
|
149
|
+
// working so existing hosts don't lose translations on upgrade.
|
|
150
|
+
const isTranslatesEnabled = Boolean(
|
|
151
|
+
config?.translates?.enabled || config?.enableTranslates
|
|
152
|
+
);
|
|
153
|
+
const effectiveTranslateMode = resolveTranslateMode(
|
|
154
|
+
config?.translates,
|
|
155
|
+
translateMode
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// Auto mode (the default): show the translation inline as the primary body,
|
|
159
|
+
// with the original quoted above. Own messages are never translated — the
|
|
160
|
+
// sender already knows what they wrote (TranslatedMessageBody skips the
|
|
161
|
+
// quote for isUser, and we simply render the original for them). Mirrors
|
|
162
|
+
// the web SDK's Message.tsx.
|
|
163
|
+
const isAutoTranslate =
|
|
164
|
+
isTranslatesEnabled && effectiveTranslateMode !== 'manual';
|
|
165
|
+
const readerLocale =
|
|
166
|
+
config?.translates?.readerLocale || config?.i18n?.locale || langSource;
|
|
167
|
+
const translationDisplay = useMessageTranslation(
|
|
168
|
+
message,
|
|
169
|
+
readerLocale,
|
|
170
|
+
isAutoTranslate
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
// `usersSet` is the canonical, continuously-updated identity store; the
|
|
174
|
+
// copy riding on a message is a snapshot of whoever sent it, whenever
|
|
175
|
+
// they sent it. Resolve both the avatar and the display name through
|
|
176
|
+
// usersSet first, falling back to the message for senders usersSet has
|
|
177
|
+
// never seen (broadcast/system accounts).
|
|
178
|
+
//
|
|
179
|
+
// This matters more since the persist layer stopped caching per-message
|
|
180
|
+
// avatars: a cache-restored message carries no profileImage at all (see
|
|
181
|
+
// PERSISTED_MESSAGE_USER_FIELDS), so reading only the message-level copy
|
|
182
|
+
// leaves a blank initials circle for senders whose name resolved fine.
|
|
183
|
+
const usersSet = useSelector(
|
|
184
|
+
(state: RootState) => state.rooms.usersSet
|
|
185
|
+
) as Record<string, any> | undefined;
|
|
186
|
+
const senderRawId = String(message.user?.id || '');
|
|
187
|
+
const senderLocal = senderRawId.split('@')[0];
|
|
188
|
+
const senderEntry = usersSet?.[senderLocal] || usersSet?.[senderRawId];
|
|
189
|
+
// usersSet FIRST (mirrors the web SDK's Message.tsx): a message stored
|
|
190
|
+
// before usersSet hydrated carries the raw JID localpart as its
|
|
191
|
+
// `user.name`, so preferring `message.user.name` (as resolveSenderDisplayName
|
|
192
|
+
// does) would pin that JID on screen forever even after the real name is
|
|
193
|
+
// known. Reading usersSet first lets the name self-heal the moment the
|
|
194
|
+
// REST roster populates the cache. Falls back to the message's own name
|
|
195
|
+
// (which may carry senderFirstName/senderLastName from the wire) only when
|
|
196
|
+
// usersSet has never seen this sender.
|
|
197
|
+
const senderDisplayName = senderEntry
|
|
198
|
+
? `${senderEntry.firstName ?? ''} ${senderEntry.lastName ?? ''}`.trim() ||
|
|
199
|
+
senderEntry.name ||
|
|
200
|
+
senderLocal
|
|
201
|
+
: message.user?.name || senderLocal || 'Unknown';
|
|
202
|
+
// A broadcast posted by the app itself arrives with the ROOM's own id as
|
|
203
|
+
// its occupant resource, so no roster ever resolves it and the name chain
|
|
204
|
+
// ends at 50 characters of hex. Captioning a bubble with that tells the
|
|
205
|
+
// reader strictly less than showing nothing.
|
|
206
|
+
const hasRealSenderName = !isUnresolvedSenderId(senderDisplayName);
|
|
207
|
+
const senderProfileImage =
|
|
208
|
+
senderEntry?.profileImage || message.user?.profileImage || '';
|
|
143
209
|
const { idSet, failedIdSet } = useMessageHeapState();
|
|
144
210
|
const { retryMessage } = useSendMessage();
|
|
145
211
|
|
|
@@ -289,12 +355,19 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
289
355
|
// wraps content in <View>s which break Text-style inheritance, so the bubble
|
|
290
356
|
// wrapper's fontSize alone never reached the actual text.
|
|
291
357
|
const bodyTextStyle = chatTextStyle(config?.typography?.messageText);
|
|
358
|
+
// In auto mode, render the translation as the primary body — but NEVER for
|
|
359
|
+
// the reader's own messages (they wrote it; no point translating it back).
|
|
360
|
+
const showInlineTranslation =
|
|
361
|
+
isAutoTranslate && translationDisplay.hasTranslation && !isUser;
|
|
362
|
+
const bodyToRender = showInlineTranslation
|
|
363
|
+
? translationDisplay.displayText
|
|
364
|
+
: message.body;
|
|
292
365
|
const messageText = config?.messageTextFilter?.enabled
|
|
293
366
|
? parseMessageBody(
|
|
294
|
-
config?.messageTextFilter.filterFunction(
|
|
367
|
+
config?.messageTextFilter.filterFunction(bodyToRender),
|
|
295
368
|
bodyTextStyle
|
|
296
369
|
)
|
|
297
|
-
: parseMessageBody(
|
|
370
|
+
: parseMessageBody(bodyToRender, bodyTextStyle);
|
|
298
371
|
|
|
299
372
|
const isFailed = failedIdSet.has(message.id);
|
|
300
373
|
const isPending =
|
|
@@ -339,10 +412,10 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
339
412
|
disabled={!!config?.disableProfilesInteractions}
|
|
340
413
|
accessible={!config?.disableProfilesInteractions}
|
|
341
414
|
>
|
|
342
|
-
{
|
|
343
|
-
<CustomMessagePhoto source={{ uri:
|
|
415
|
+
{senderProfileImage ? (
|
|
416
|
+
<CustomMessagePhoto source={{ uri: senderProfileImage }} />
|
|
344
417
|
) : (
|
|
345
|
-
<Avatar username={
|
|
418
|
+
<Avatar username={senderDisplayName} />
|
|
346
419
|
)}
|
|
347
420
|
</CustomMessagePhotoContainer>
|
|
348
421
|
)}
|
|
@@ -382,14 +455,14 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
382
455
|
backgroundMessageUser={config?.messageColor?.backgroundMessageUser}
|
|
383
456
|
backgroundMessage={config?.messageColor?.backgroundMessage}
|
|
384
457
|
>
|
|
385
|
-
{!isUser && (
|
|
458
|
+
{!isUser && hasRealSenderName && (
|
|
386
459
|
<CustomUserName
|
|
387
460
|
color={config?.colors?.primary}
|
|
388
461
|
media={message?.isMediafile === 'true'}
|
|
389
462
|
fontSize={config?.typography?.senderName?.fontSize}
|
|
390
463
|
fontWeight={config?.typography?.senderName?.fontWeight as any}
|
|
391
464
|
>
|
|
392
|
-
{
|
|
465
|
+
{senderDisplayName}
|
|
393
466
|
</CustomUserName>
|
|
394
467
|
)}
|
|
395
468
|
{!isReply && message.mainMessage && (
|
|
@@ -421,18 +494,37 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
421
494
|
fontSize={config?.typography?.messageText?.fontSize}
|
|
422
495
|
fontWeight={config?.typography?.messageText?.fontWeight as any}
|
|
423
496
|
>
|
|
424
|
-
|
|
497
|
+
{/* Auto mode: the parsed body IS the translation; wrap it
|
|
498
|
+
so the original shows as a dimmed accent-bar quote
|
|
499
|
+
above it. Plain body otherwise. */}
|
|
500
|
+
{showInlineTranslation ? (
|
|
501
|
+
<TranslatedMessageBody
|
|
502
|
+
isUser={isUser}
|
|
503
|
+
originalText={translationDisplay.originalText}
|
|
504
|
+
accentColor={config?.colors?.primary}
|
|
505
|
+
>
|
|
506
|
+
<Text>{messageText}</Text>
|
|
507
|
+
</TranslatedMessageBody>
|
|
508
|
+
) : (
|
|
509
|
+
<Text>{messageText}</Text>
|
|
510
|
+
)}
|
|
425
511
|
</CustomMessageText>
|
|
426
512
|
)}
|
|
427
513
|
</>
|
|
428
514
|
)}
|
|
429
|
-
{
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
515
|
+
{/* Manual mode: a "Translate" link the reader taps (auto mode
|
|
516
|
+
renders the translation inline in the body above). Never on
|
|
517
|
+
the reader's own messages. */}
|
|
518
|
+
{!isUser &&
|
|
519
|
+
isTranslatesEnabled &&
|
|
520
|
+
effectiveTranslateMode === 'manual' && (
|
|
521
|
+
<MessageTranslate
|
|
522
|
+
message={message}
|
|
523
|
+
config={config}
|
|
524
|
+
isUser={isUser}
|
|
525
|
+
readerLocale={readerLocale}
|
|
526
|
+
/>
|
|
527
|
+
)}
|
|
436
528
|
{/* <View style={styles.timestampRow}> */}
|
|
437
529
|
<CustomTimestampRow media={message?.isMediafile === 'true'}>
|
|
438
530
|
{!config?.disableSentLogic && isUser && isPending && (
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import React, { FC, useCallback, useState } from 'react';
|
|
2
|
+
import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
|
|
3
|
+
import { IConfig, IMessage } from '../../types/types';
|
|
4
|
+
import { CustomDivider } from './CustomDivider';
|
|
5
|
+
import { CustomMessageText } from '../styled/StyledComponents';
|
|
6
|
+
import { useT } from '../../i18n/useT';
|
|
7
|
+
import { toBaseLanguage } from '../../i18n/strings';
|
|
8
|
+
import { useMessageTranslation } from '../../hooks/useMessageTranslation';
|
|
9
|
+
|
|
10
|
+
interface MessageTranslateProps {
|
|
11
|
+
message: IMessage;
|
|
12
|
+
isUser: boolean;
|
|
13
|
+
config?: IConfig;
|
|
14
|
+
/**
|
|
15
|
+
* The reader's target language, resolved ONCE by the parent (Message.tsx)
|
|
16
|
+
* and shared with auto mode, so the two can never ask for different
|
|
17
|
+
* languages.
|
|
18
|
+
*/
|
|
19
|
+
readerLocale?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type HostPhase = 'idle' | 'loading' | 'done' | 'error';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Manual-mode message translation (LinkedIn-style "Translate" link).
|
|
26
|
+
*
|
|
27
|
+
* Manual is AUTO BEHIND A TAP — the same translation, revealed on press,
|
|
28
|
+
* not a second mechanism. Both read what the stanza already carries on
|
|
29
|
+
* `message.translations`; neither calls a translation service.
|
|
30
|
+
*
|
|
31
|
+
* That is enforced by sharing `useMessageTranslation` with auto rather than
|
|
32
|
+
* re-deriving the lookup here. The previous copy (ported verbatim from web,
|
|
33
|
+
* which still has it) drifted in two ways that both pointed the same
|
|
34
|
+
* direction — a link that could not deliver:
|
|
35
|
+
*
|
|
36
|
+
* - its target language ended at the literal `'en'` instead of the
|
|
37
|
+
* reader's own `langSource`, so for every host that lets the reader
|
|
38
|
+
* pick — the normal case — a French reader's tap asked the message for
|
|
39
|
+
* an ENGLISH translation and fell into `translation.failed`;
|
|
40
|
+
* - it offered the link on a source-vs-target language compare alone,
|
|
41
|
+
* without checking a translation was actually attached, so even with
|
|
42
|
+
* the right locale a never-translated message showed a dead link.
|
|
43
|
+
*
|
|
44
|
+
* The link now appears only when there is something to reveal, which makes
|
|
45
|
+
* the failure state unreachable on this path.
|
|
46
|
+
*
|
|
47
|
+
* A host-supplied `config.translates.onTranslate` is the one asynchronous
|
|
48
|
+
* case: it can produce a translation nothing on the stanza predicts, so
|
|
49
|
+
* there the link is offered on the language compare and loading/error still
|
|
50
|
+
* apply.
|
|
51
|
+
*/
|
|
52
|
+
const MessageTranslate: FC<MessageTranslateProps> = ({
|
|
53
|
+
message,
|
|
54
|
+
isUser,
|
|
55
|
+
config,
|
|
56
|
+
readerLocale,
|
|
57
|
+
}) => {
|
|
58
|
+
const t = useT();
|
|
59
|
+
const translates = config?.translates;
|
|
60
|
+
const hasHostTranslator = typeof translates?.onTranslate === 'function';
|
|
61
|
+
|
|
62
|
+
const originalText = String(message?.body || '');
|
|
63
|
+
const sourceLocale = (message as { langSource?: string })?.langSource;
|
|
64
|
+
const targetLocale =
|
|
65
|
+
readerLocale || translates?.readerLocale || config?.i18n?.locale || 'en';
|
|
66
|
+
|
|
67
|
+
// The exact call auto mode makes, with the exact same locale.
|
|
68
|
+
const attached = useMessageTranslation(message, targetLocale, true);
|
|
69
|
+
|
|
70
|
+
const [revealed, setRevealed] = useState(false);
|
|
71
|
+
const [showOriginal, setShowOriginal] = useState(false);
|
|
72
|
+
const [hostPhase, setHostPhase] = useState<HostPhase>('idle');
|
|
73
|
+
const [hostText, setHostText] = useState<string | null>(null);
|
|
74
|
+
const linkColor = config?.colors?.primary || '#0052CD';
|
|
75
|
+
|
|
76
|
+
// Region ignored on purpose: en-US vs en-CA is the same language, not a
|
|
77
|
+
// translation job. The FULL locale is still what `onTranslate` receives.
|
|
78
|
+
const languagesDiffer =
|
|
79
|
+
!!originalText.trim() &&
|
|
80
|
+
!!sourceLocale &&
|
|
81
|
+
toBaseLanguage(sourceLocale) !== toBaseLanguage(targetLocale);
|
|
82
|
+
|
|
83
|
+
const shouldShow = (() => {
|
|
84
|
+
if (isUser) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
// A host that supplies this keeps the locale logic and just tells us
|
|
88
|
+
// yes/no.
|
|
89
|
+
if (typeof translates?.showTranslateForMessage === 'function') {
|
|
90
|
+
return translates.showTranslateForMessage(message);
|
|
91
|
+
}
|
|
92
|
+
// Host translator: the outcome isn't knowable until it runs.
|
|
93
|
+
if (hasHostTranslator) {
|
|
94
|
+
return languagesDiffer;
|
|
95
|
+
}
|
|
96
|
+
// Stanza-attached: only offer what we can actually deliver.
|
|
97
|
+
return attached.hasTranslation;
|
|
98
|
+
})();
|
|
99
|
+
|
|
100
|
+
const runHostTranslate = useCallback(async () => {
|
|
101
|
+
if (!originalText.trim()) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
setHostPhase('loading');
|
|
105
|
+
try {
|
|
106
|
+
const result = await translates?.onTranslate?.(originalText, {
|
|
107
|
+
sourceLocale,
|
|
108
|
+
targetLocale,
|
|
109
|
+
message,
|
|
110
|
+
});
|
|
111
|
+
if (result && result.trim()) {
|
|
112
|
+
setHostText(result);
|
|
113
|
+
setHostPhase('done');
|
|
114
|
+
} else {
|
|
115
|
+
setHostPhase('error');
|
|
116
|
+
}
|
|
117
|
+
} catch {
|
|
118
|
+
setHostPhase('error');
|
|
119
|
+
}
|
|
120
|
+
}, [originalText, translates, sourceLocale, targetLocale, message]);
|
|
121
|
+
|
|
122
|
+
if (!shouldShow) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const renderLink = (label: string, onPress: () => void) => (
|
|
127
|
+
<TouchableOpacity onPress={onPress} hitSlop={6}>
|
|
128
|
+
<Text style={[styles.link, { color: linkColor }]}>{label}</Text>
|
|
129
|
+
</TouchableOpacity>
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const renderRevealed = (translatedText: string) => (
|
|
133
|
+
<View>
|
|
134
|
+
<CustomDivider
|
|
135
|
+
configColor={
|
|
136
|
+
isUser ? config?.colors?.secondary : config?.colors?.primary
|
|
137
|
+
}
|
|
138
|
+
/>
|
|
139
|
+
<CustomMessageText colorUser="">
|
|
140
|
+
{showOriginal ? originalText : translatedText}
|
|
141
|
+
</CustomMessageText>
|
|
142
|
+
{renderLink(
|
|
143
|
+
showOriginal ? t('action.translate') : t('action.showOriginal'),
|
|
144
|
+
() => setShowOriginal((v) => !v)
|
|
145
|
+
)}
|
|
146
|
+
</View>
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
// Host-provided translator: asynchronous, and can genuinely fail.
|
|
150
|
+
if (hasHostTranslator) {
|
|
151
|
+
if (hostPhase === 'loading') {
|
|
152
|
+
return (
|
|
153
|
+
<Text style={[styles.link, { color: linkColor }]}>
|
|
154
|
+
{t('translation.translating')}
|
|
155
|
+
</Text>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
if (hostPhase === 'error') {
|
|
159
|
+
return renderLink(t('translation.failed'), runHostTranslate);
|
|
160
|
+
}
|
|
161
|
+
if (hostPhase === 'done' && hostText) {
|
|
162
|
+
return renderRevealed(hostText);
|
|
163
|
+
}
|
|
164
|
+
return renderLink(t('action.translate'), runHostTranslate);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Stanza-attached: nothing to await, nothing to fail.
|
|
168
|
+
if (!revealed) {
|
|
169
|
+
return renderLink(t('action.translate'), () => setRevealed(true));
|
|
170
|
+
}
|
|
171
|
+
return renderRevealed(attached.displayText);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const styles = StyleSheet.create({
|
|
175
|
+
link: {
|
|
176
|
+
marginTop: 4,
|
|
177
|
+
fontSize: 12,
|
|
178
|
+
fontWeight: '600',
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
export default MessageTranslate;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { StyleSheet, Text, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
interface TranslatedMessageBodyProps {
|
|
5
|
+
/** Text as sent, in the sender's language. */
|
|
6
|
+
originalText: string;
|
|
7
|
+
accentColor?: string;
|
|
8
|
+
/** Renders the translated text (the parsed message body). */
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
/**
|
|
11
|
+
* Whether this message was sent by the current user. The sender already
|
|
12
|
+
* knows what they wrote, so their own messages skip the quote-plus-
|
|
13
|
+
* translation treatment and just show the original (never translated).
|
|
14
|
+
*/
|
|
15
|
+
isUser: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A message body that is showing a translation: the translated text reads
|
|
20
|
+
* as the primary content, with the original quoted above it (accent bar,
|
|
21
|
+
* dimmed) for reference — the same visual language MessageReply uses.
|
|
22
|
+
* Ported from the web SDK's TranslatedMessageBody. Own messages (`isUser`)
|
|
23
|
+
* show only the original.
|
|
24
|
+
*/
|
|
25
|
+
export const TranslatedMessageBody: React.FC<TranslatedMessageBodyProps> = ({
|
|
26
|
+
originalText,
|
|
27
|
+
accentColor = '#0052CD',
|
|
28
|
+
children,
|
|
29
|
+
isUser,
|
|
30
|
+
}) => {
|
|
31
|
+
if (isUser) {
|
|
32
|
+
return <View>{children}</View>;
|
|
33
|
+
}
|
|
34
|
+
return (
|
|
35
|
+
<View>
|
|
36
|
+
<View style={[styles.quote, { borderLeftColor: accentColor }]}>
|
|
37
|
+
<Text style={styles.quoteText}>{originalText}</Text>
|
|
38
|
+
</View>
|
|
39
|
+
<View>{children}</View>
|
|
40
|
+
</View>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const styles = StyleSheet.create({
|
|
45
|
+
quote: {
|
|
46
|
+
borderLeftWidth: 2,
|
|
47
|
+
paddingLeft: 8,
|
|
48
|
+
marginBottom: 6,
|
|
49
|
+
},
|
|
50
|
+
quoteText: {
|
|
51
|
+
fontSize: 13,
|
|
52
|
+
lineHeight: 19,
|
|
53
|
+
// Dimmed relative to the translated body — matches the web quote's
|
|
54
|
+
// opacity:0.6 look without depending on the (variable) text colour.
|
|
55
|
+
color: '#71717A',
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export default TranslatedMessageBody;
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
View,
|
|
13
13
|
} from 'react-native';
|
|
14
14
|
import { CameraIcon, DocumentIcon, MediaIcon } from '../../../assets/icons';
|
|
15
|
-
import { IConfig } from '../../../types/types';
|
|
16
15
|
import { useChatSettingState } from '../../../hooks/useChatSettingState';
|
|
17
16
|
import { chatTextStyle } from '../../../helpers/typography';
|
|
18
17
|
|
|
@@ -23,7 +22,6 @@ interface AttachSheetProps {
|
|
|
23
22
|
onGallery: () => void;
|
|
24
23
|
onDocument: () => void;
|
|
25
24
|
primaryColor?: string;
|
|
26
|
-
/** For `typography.elements.attachSheet*` font overrides. */
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
// Starting translateY for the sheet. Larger than any realistic sheet
|
|
@@ -206,7 +204,7 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
206
204
|
</View>
|
|
207
205
|
<View style={styles.rowText}>
|
|
208
206
|
<Text style={[styles.rowLabel, chatTextStyle(ts?.rowLabel)]}>{label}</Text>
|
|
209
|
-
<Text style={styles.rowHint}>{hint}</Text>
|
|
207
|
+
<Text style={[styles.rowHint, chatTextStyle(ts?.rowHint)]}>{hint}</Text>
|
|
210
208
|
</View>
|
|
211
209
|
</TouchableOpacity>
|
|
212
210
|
))}
|
|
@@ -26,6 +26,7 @@ import { DeleteIcon, MoreIcon, QrIcon } from '../../../assets/icons';
|
|
|
26
26
|
import Switch from '../../MainComponents/Switch';
|
|
27
27
|
import { useChatSettingState } from '../../../hooks/useChatSettingState';
|
|
28
28
|
import { chatTextStyle } from '../../../helpers/typography';
|
|
29
|
+
import { getElementFont } from '../../../helpers/getElementFont';
|
|
29
30
|
import { deleteRoomMember } from '../../../networking/api-requests/rooms.api';
|
|
30
31
|
import { RoomMember } from '../../../types/models/room.model';
|
|
31
32
|
import { setActiveModal, setSelectedUser } from '../../../roomStore/chatSettingsSlice';
|
|
@@ -268,6 +269,7 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
268
269
|
<ModalHeaderComponent
|
|
269
270
|
handleCloseModal={handleCloseModal}
|
|
270
271
|
headerTitle={'Chat Profile'}
|
|
272
|
+
titleStyle={chatTextStyle(config?.typography?.profile?.screenTitle)}
|
|
271
273
|
rightMenu={
|
|
272
274
|
<>
|
|
273
275
|
{activeRoom?.type === 'public' && (
|
|
@@ -320,7 +322,7 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
320
322
|
>
|
|
321
323
|
{activeRoom.title || activeRoom.name}
|
|
322
324
|
</UserName>
|
|
323
|
-
<UserStatus>
|
|
325
|
+
<UserStatus style={getElementFont(config, 'profileStatus')}>
|
|
324
326
|
{activeRoom.usersCnt}{' '}
|
|
325
327
|
{activeRoom.usersCnt > 1 ? 'members' : 'member'}
|
|
326
328
|
</UserStatus>
|
|
@@ -333,13 +335,17 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
333
335
|
)}
|
|
334
336
|
{!config?.disableChatInfo?.disableDescription && (
|
|
335
337
|
<BorderedContainer>
|
|
336
|
-
<LabelData>
|
|
338
|
+
<LabelData style={getElementFont(config, 'profileSectionLabel')}>
|
|
339
|
+
Description
|
|
340
|
+
</LabelData>
|
|
337
341
|
<Label>{activeRoom?.description || '—'}</Label>
|
|
338
342
|
</BorderedContainer>
|
|
339
343
|
)}
|
|
340
344
|
{!config?.disableChatInfo?.disableType && (
|
|
341
345
|
<BorderedContainer>
|
|
342
|
-
<LabelData
|
|
346
|
+
<LabelData style={getElementFont(config, 'profileSectionLabel')}>
|
|
347
|
+
Chat type
|
|
348
|
+
</LabelData>
|
|
343
349
|
<Label>{activeRoom.type || '—'}</Label>
|
|
344
350
|
</BorderedContainer>
|
|
345
351
|
)}
|
|
@@ -428,7 +434,7 @@ const ChatProfileModal: React.FC<ChatProfileModalProps> = ({
|
|
|
428
434
|
{user.firstName} {user.lastName}
|
|
429
435
|
</Label>
|
|
430
436
|
{user.last_active && (
|
|
431
|
-
<LabelData>
|
|
437
|
+
<LabelData style={getElementFont(config, 'profileSectionLabel')}>
|
|
432
438
|
{new Date(user.last_active * 1000).toLocaleString()}
|
|
433
439
|
</LabelData>
|
|
434
440
|
)}
|
|
@@ -6,6 +6,8 @@ import {
|
|
|
6
6
|
} from '../styledModalComponents';
|
|
7
7
|
import { SaveIcon } from '../../../assets/icons';
|
|
8
8
|
import ModalHeaderComponent from '../ModalHeaderComponent';
|
|
9
|
+
import { useChatSettingState } from '../../../hooks/useChatSettingState';
|
|
10
|
+
import { chatTextStyle } from '../../../helpers/typography';
|
|
9
11
|
import { useDispatch, useSelector } from 'react-redux';
|
|
10
12
|
import Button from '../../styled/Button';
|
|
11
13
|
import { RootState } from '../../../roomStore';
|
|
@@ -18,6 +20,7 @@ import {
|
|
|
18
20
|
Platform,
|
|
19
21
|
TouchableOpacity,
|
|
20
22
|
StyleSheet,
|
|
23
|
+
Share,
|
|
21
24
|
} from 'react-native';
|
|
22
25
|
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
23
26
|
import { PlayIcon } from '../../../assets/icons';
|
|
@@ -47,8 +50,8 @@ const isGviewPreviewable = (mime: string | undefined | null) => {
|
|
|
47
50
|
return GVIEW_PREVIEWABLE.has(mime.toLowerCase().split(';')[0]!.trim());
|
|
48
51
|
};
|
|
49
52
|
|
|
50
|
-
// Full-screen video preview on expo-video (expo-av
|
|
51
|
-
//
|
|
53
|
+
// Full-screen video preview on expo-video (the discontinued expo-av
|
|
54
|
+
// <Video> rendered blank on Android). `contentFit: contain` fits the clip to
|
|
52
55
|
// the area with the surrounding letterbox painted as the view's own
|
|
53
56
|
// (transparent → theme) background, NOT black. `textureView` so the play
|
|
54
57
|
// overlay composites on top and nothing is clipped on Android.
|
|
@@ -109,6 +112,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
109
112
|
}) => {
|
|
110
113
|
const dispatch = useDispatch();
|
|
111
114
|
const { showToast } = useToast();
|
|
115
|
+
const { config } = useChatSettingState();
|
|
112
116
|
|
|
113
117
|
// Cache the SAF directory the user granted so saving several documents
|
|
114
118
|
// in a row doesn't re-prompt for a folder every time (Android only).
|
|
@@ -204,13 +208,25 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
204
208
|
await FileSystem.writeAsStringAsync(destUri, base64, {
|
|
205
209
|
encoding: FileSystem.EncodingType.Base64,
|
|
206
210
|
});
|
|
211
|
+
|
|
212
|
+
showToast({
|
|
213
|
+
id: Date.now().toString(),
|
|
214
|
+
title: 'Success',
|
|
215
|
+
message: 'Save successful',
|
|
216
|
+
type: 'success',
|
|
217
|
+
});
|
|
218
|
+
return;
|
|
207
219
|
}
|
|
208
220
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
221
|
+
// iOS (and any non-Android): there is no app-writable "Downloads"
|
|
222
|
+
// folder, and MediaLibrary only accepts images/videos — which is why
|
|
223
|
+
// documents previously hit the success toast without ever being
|
|
224
|
+
// saved. Present the system share sheet so the user can "Save to
|
|
225
|
+
// Files", AirDrop, etc. The sheet itself is the confirmation (the
|
|
226
|
+
// user may cancel), so we don't show a "Save successful" toast here.
|
|
227
|
+
await Share.share({
|
|
228
|
+
url: download.uri,
|
|
229
|
+
title: fileName,
|
|
214
230
|
});
|
|
215
231
|
} catch (err) {
|
|
216
232
|
console.error('Error saving file:', err);
|
|
@@ -377,6 +393,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
377
393
|
<ModalHeaderComponent
|
|
378
394
|
handleCloseModal={closeModal}
|
|
379
395
|
headerTitle={'File preview'}
|
|
396
|
+
titleStyle={chatTextStyle(config?.typography?.profile?.screenTitle)}
|
|
380
397
|
rightMenu={
|
|
381
398
|
<>
|
|
382
399
|
<Button onPress={saveClick}>
|
|
@@ -392,7 +409,7 @@ const FilePreviewModal: React.FC<FilePreviewModalProps> = ({
|
|
|
392
409
|
flex: 1,
|
|
393
410
|
justifyContent: 'center',
|
|
394
411
|
// NOTE: do NOT set overflow:'hidden' here — on Android it clips
|
|
395
|
-
// hardware-accelerated children (expo-
|
|
412
|
+
// hardware-accelerated children (expo-video TextureView and
|
|
396
413
|
// react-native-webview) to nothing, so video/PDF/doc previews
|
|
397
414
|
// render blank while plain <Image> survives.
|
|
398
415
|
overflow: 'visible',
|