@ethora/chat-component-rn 26.10.4 → 26.10.6
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 +8 -0
- package/README.md +15 -0
- package/app.plugin.js +2 -0
- package/lib/commonjs/assets/icons.js +2 -2
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/MainComponents/AlbumGrid.js +152 -0
- package/lib/commonjs/components/MainComponents/AlbumGrid.js.map +1 -0
- package/lib/commonjs/components/MainComponents/ChatRoom.js +2 -2
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +199 -123
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaUploadOverlay.js +109 -0
- package/lib/commonjs/components/MainComponents/MediaUploadOverlay.js.map +1 -0
- package/lib/commonjs/components/MessageBubble/MediaCaption.js +51 -0
- package/lib/commonjs/components/MessageBubble/MediaCaption.js.map +1 -0
- package/lib/commonjs/components/MessageBubble/Message.js +40 -1
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +2 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +75 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/LastMessageItem.js +20 -4
- package/lib/commonjs/components/RoomComponents/LastMessageItem.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js +3 -2
- package/lib/commonjs/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js +3 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js +3 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js +3 -2
- package/lib/commonjs/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
- package/lib/commonjs/components/Thread/ThreadWrapper.js +3 -2
- package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/ActiveCallBar.js +61 -16
- package/lib/commonjs/components/VideoCalls/ActiveCallBar.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/CallIcons.js +41 -16
- package/lib/commonjs/components/VideoCalls/CallIcons.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js +183 -9
- package/lib/commonjs/components/VideoCalls/VideoCallOverlay.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js +40 -15
- package/lib/commonjs/components/VideoCalls/VideoCallSession.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/callSessionController.js +49 -26
- package/lib/commonjs/components/VideoCalls/callSessionController.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/callUiStore.js +33 -4
- package/lib/commonjs/components/VideoCalls/callUiStore.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/livekitRuntime.js +9 -1
- package/lib/commonjs/components/VideoCalls/livekitRuntime.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/useCallKeep.js +197 -28
- package/lib/commonjs/components/VideoCalls/useCallKeep.js.map +1 -1
- package/lib/commonjs/components/VideoCalls/useOngoingCallNotification.js +88 -0
- package/lib/commonjs/components/VideoCalls/useOngoingCallNotification.js.map +1 -0
- package/lib/commonjs/components/VideoCalls/usePipTile.js +232 -0
- package/lib/commonjs/components/VideoCalls/usePipTile.js.map +1 -0
- package/lib/commonjs/components/styled/MediaFilePreview.js +60 -47
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +16 -6
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +99 -68
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +24 -10
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +46 -0
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/e2ee/fileEnvelope.js +6 -0
- package/lib/commonjs/e2ee/fileEnvelope.js.map +1 -1
- package/lib/commonjs/e2ee/sealedBody.js +32 -2
- package/lib/commonjs/e2ee/sealedBody.js.map +1 -1
- package/lib/commonjs/helpers/albumLayout.js +150 -0
- package/lib/commonjs/helpers/albumLayout.js.map +1 -0
- package/lib/commonjs/helpers/attachments.js +255 -0
- package/lib/commonjs/helpers/attachments.js.map +1 -0
- package/lib/commonjs/helpers/caption.js +214 -0
- package/lib/commonjs/helpers/caption.js.map +1 -0
- package/lib/commonjs/helpers/createMainMessageForThread.js +5 -1
- package/lib/commonjs/helpers/createMainMessageForThread.js.map +1 -1
- package/lib/commonjs/helpers/createMessageFromXml.js +19 -5
- package/lib/commonjs/helpers/createMessageFromXml.js.map +1 -1
- package/lib/commonjs/helpers/fileKind.js +40 -0
- package/lib/commonjs/helpers/fileKind.js.map +1 -0
- package/lib/commonjs/helpers/getDataFromXml.js +6 -1
- package/lib/commonjs/helpers/getDataFromXml.js.map +1 -1
- package/lib/commonjs/helpers/mapWithConcurrency.js +41 -0
- package/lib/commonjs/helpers/mapWithConcurrency.js.map +1 -0
- package/lib/commonjs/helpers/mediaLimits.js +33 -0
- package/lib/commonjs/helpers/mediaLimits.js.map +1 -0
- package/lib/commonjs/helpers/mediaSendRetry.js +64 -0
- package/lib/commonjs/helpers/mediaSendRetry.js.map +1 -0
- package/lib/commonjs/helpers/mediaWireData.js +62 -0
- package/lib/commonjs/helpers/mediaWireData.js.map +1 -0
- package/lib/commonjs/helpers/mentionSpans.js +19 -0
- package/lib/commonjs/helpers/mentionSpans.js.map +1 -0
- package/lib/commonjs/helpers/mimeToExtension.js +45 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -1
- package/lib/commonjs/helpers/readReceipts.js +173 -0
- package/lib/commonjs/helpers/readReceipts.js.map +1 -0
- package/lib/commonjs/helpers/repairFilenameEncoding.js +79 -0
- package/lib/commonjs/helpers/repairFilenameEncoding.js.map +1 -0
- package/lib/commonjs/helpers/safeJson.js +18 -0
- package/lib/commonjs/helpers/safeJson.js.map +1 -0
- package/lib/commonjs/helpers/updateMessagesTillLast.js +3 -1
- package/lib/commonjs/helpers/updateMessagesTillLast.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +384 -193
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +144 -0
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +62 -3
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/stanzaHandlers.js +100 -3
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +4 -2
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendDisplayedMarker.xmpp.js +28 -0
- package/lib/commonjs/networking/xmpp/sendDisplayedMarker.xmpp.js.map +1 -0
- package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js +53 -2
- package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendReceivedReceipt.xmpp.js +28 -0
- package/lib/commonjs/networking/xmpp/sendReceivedReceipt.xmpp.js.map +1 -0
- package/lib/commonjs/networking/xmppClient.js +64 -0
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +78 -5
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/roomStore/roomHeapSlice.js +4 -0
- package/lib/commonjs/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +114 -1
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/commonjs/types/models/attachment.model.js +2 -0
- package/lib/commonjs/types/models/attachment.model.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/module/assets/icons.js +1 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/MainComponents/AlbumGrid.js +146 -0
- package/lib/module/components/MainComponents/AlbumGrid.js.map +1 -0
- package/lib/module/components/MainComponents/ChatRoom.js +2 -2
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +200 -124
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MediaUploadOverlay.js +104 -0
- package/lib/module/components/MainComponents/MediaUploadOverlay.js.map +1 -0
- package/lib/module/components/MessageBubble/MediaCaption.js +46 -0
- package/lib/module/components/MessageBubble/MediaCaption.js.map +1 -0
- package/lib/module/components/MessageBubble/Message.js +44 -5
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +2 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +75 -0
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/RoomComponents/LastMessageItem.js +20 -4
- package/lib/module/components/RoomComponents/LastMessageItem.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastAudioMessage.js +3 -2
- package/lib/module/components/RoomComponents/styled/LastAudioMessage.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageFile.js +3 -2
- package/lib/module/components/RoomComponents/styled/LastMessageFile.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js +3 -2
- package/lib/module/components/RoomComponents/styled/LastMessagePhoto.js.map +1 -1
- package/lib/module/components/RoomComponents/styled/LastMessageVideo.js +3 -2
- package/lib/module/components/RoomComponents/styled/LastMessageVideo.js.map +1 -1
- package/lib/module/components/Thread/ThreadWrapper.js +3 -2
- package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
- package/lib/module/components/VideoCalls/ActiveCallBar.js +63 -18
- package/lib/module/components/VideoCalls/ActiveCallBar.js.map +1 -1
- package/lib/module/components/VideoCalls/CallIcons.js +38 -15
- package/lib/module/components/VideoCalls/CallIcons.js.map +1 -1
- package/lib/module/components/VideoCalls/VideoCallOverlay.js +185 -11
- package/lib/module/components/VideoCalls/VideoCallOverlay.js.map +1 -1
- package/lib/module/components/VideoCalls/VideoCallSession.js +41 -16
- package/lib/module/components/VideoCalls/VideoCallSession.js.map +1 -1
- package/lib/module/components/VideoCalls/callSessionController.js +46 -24
- package/lib/module/components/VideoCalls/callSessionController.js.map +1 -1
- package/lib/module/components/VideoCalls/callUiStore.js +30 -3
- package/lib/module/components/VideoCalls/callUiStore.js.map +1 -1
- package/lib/module/components/VideoCalls/livekitRuntime.js +9 -1
- package/lib/module/components/VideoCalls/livekitRuntime.js.map +1 -1
- package/lib/module/components/VideoCalls/useCallKeep.js +198 -29
- package/lib/module/components/VideoCalls/useCallKeep.js.map +1 -1
- package/lib/module/components/VideoCalls/useOngoingCallNotification.js +84 -0
- package/lib/module/components/VideoCalls/useOngoingCallNotification.js.map +1 -0
- package/lib/module/components/VideoCalls/usePipTile.js +228 -0
- package/lib/module/components/VideoCalls/usePipTile.js.map +1 -0
- package/lib/module/components/styled/MediaFilePreview.js +61 -48
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +16 -6
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +99 -68
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +24 -10
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/xmppProvider.js +46 -0
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/e2ee/fileEnvelope.js +1 -1
- package/lib/module/e2ee/fileEnvelope.js.map +1 -1
- package/lib/module/e2ee/sealedBody.js +32 -2
- package/lib/module/e2ee/sealedBody.js.map +1 -1
- package/lib/module/helpers/albumLayout.js +143 -0
- package/lib/module/helpers/albumLayout.js.map +1 -0
- package/lib/module/helpers/attachments.js +245 -0
- package/lib/module/helpers/attachments.js.map +1 -0
- package/lib/module/helpers/caption.js +207 -0
- package/lib/module/helpers/caption.js.map +1 -0
- package/lib/module/helpers/createMainMessageForThread.js +5 -1
- package/lib/module/helpers/createMainMessageForThread.js.map +1 -1
- package/lib/module/helpers/createMessageFromXml.js +20 -6
- package/lib/module/helpers/createMessageFromXml.js.map +1 -1
- package/lib/module/helpers/fileKind.js +34 -0
- package/lib/module/helpers/fileKind.js.map +1 -0
- package/lib/module/helpers/getDataFromXml.js +6 -1
- package/lib/module/helpers/getDataFromXml.js.map +1 -1
- package/lib/module/helpers/mapWithConcurrency.js +37 -0
- package/lib/module/helpers/mapWithConcurrency.js.map +1 -0
- package/lib/module/helpers/mediaLimits.js +27 -0
- package/lib/module/helpers/mediaLimits.js.map +1 -0
- package/lib/module/helpers/mediaSendRetry.js +55 -0
- package/lib/module/helpers/mediaSendRetry.js.map +1 -0
- package/lib/module/helpers/mediaWireData.js +58 -0
- package/lib/module/helpers/mediaWireData.js.map +1 -0
- package/lib/module/helpers/mentionSpans.js +14 -0
- package/lib/module/helpers/mentionSpans.js.map +1 -0
- package/lib/module/helpers/mimeToExtension.js +43 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -1
- package/lib/module/helpers/readReceipts.js +160 -0
- package/lib/module/helpers/readReceipts.js.map +1 -0
- package/lib/module/helpers/repairFilenameEncoding.js +74 -0
- package/lib/module/helpers/repairFilenameEncoding.js.map +1 -0
- package/lib/module/helpers/safeJson.js +13 -0
- package/lib/module/helpers/safeJson.js.map +1 -0
- package/lib/module/helpers/updateMessagesTillLast.js +3 -1
- package/lib/module/helpers/updateMessagesTillLast.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +387 -195
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/i18n/strings.js +144 -0
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +62 -3
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/stanzaHandlers.js +97 -4
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js +5 -3
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendDisplayedMarker.xmpp.js +25 -0
- package/lib/module/networking/xmpp/sendDisplayedMarker.xmpp.js.map +1 -0
- package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js +53 -2
- package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendReceivedReceipt.xmpp.js +25 -0
- package/lib/module/networking/xmpp/sendReceivedReceipt.xmpp.js.map +1 -0
- package/lib/module/networking/xmppClient.js +64 -0
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/persistence.js +78 -5
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/roomStore/roomHeapSlice.js +4 -0
- package/lib/module/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +109 -0
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/types/models/attachment.model.js +2 -0
- package/lib/module/types/models/attachment.model.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/typescript/assets/icons.d.ts +6 -1
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/AlbumGrid.d.ts +21 -0
- package/lib/typescript/components/MainComponents/AlbumGrid.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaUploadOverlay.d.ts +17 -0
- package/lib/typescript/components/MainComponents/MediaUploadOverlay.d.ts.map +1 -0
- package/lib/typescript/components/MessageBubble/MediaCaption.d.ts +12 -0
- package/lib/typescript/components/MessageBubble/MediaCaption.d.ts.map +1 -0
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/LastMessageItem.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastAudioMessage.d.ts +2 -0
- package/lib/typescript/components/RoomComponents/styled/LastAudioMessage.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts +2 -0
- package/lib/typescript/components/RoomComponents/styled/LastMessageFile.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts +2 -0
- package/lib/typescript/components/RoomComponents/styled/LastMessagePhoto.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts +2 -0
- package/lib/typescript/components/RoomComponents/styled/LastMessageVideo.d.ts.map +1 -1
- package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/ActiveCallBar.d.ts +9 -3
- package/lib/typescript/components/VideoCalls/ActiveCallBar.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/CallIcons.d.ts +9 -0
- package/lib/typescript/components/VideoCalls/CallIcons.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/VideoCallOverlay.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/VideoCallSession.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/callSessionController.d.ts +7 -0
- package/lib/typescript/components/VideoCalls/callSessionController.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/callUiStore.d.ts +13 -0
- package/lib/typescript/components/VideoCalls/callUiStore.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/livekitRuntime.d.ts +5 -0
- package/lib/typescript/components/VideoCalls/livekitRuntime.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/useCallKeep.d.ts +12 -0
- package/lib/typescript/components/VideoCalls/useCallKeep.d.ts.map +1 -1
- package/lib/typescript/components/VideoCalls/useOngoingCallNotification.d.ts +10 -0
- package/lib/typescript/components/VideoCalls/useOngoingCallNotification.d.ts.map +1 -0
- package/lib/typescript/components/VideoCalls/usePipTile.d.ts +46 -0
- package/lib/typescript/components/VideoCalls/usePipTile.d.ts.map +1 -0
- package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts +10 -0
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts +7 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/components/styled/VideoMessage.d.ts +7 -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/e2ee/fileEnvelope.d.ts +1 -1
- package/lib/typescript/e2ee/fileEnvelope.d.ts.map +1 -1
- package/lib/typescript/e2ee/sealedBody.d.ts +16 -0
- package/lib/typescript/e2ee/sealedBody.d.ts.map +1 -1
- package/lib/typescript/helpers/albumLayout.d.ts +66 -0
- package/lib/typescript/helpers/albumLayout.d.ts.map +1 -0
- package/lib/typescript/helpers/attachments.d.ts +55 -0
- package/lib/typescript/helpers/attachments.d.ts.map +1 -0
- package/lib/typescript/helpers/caption.d.ts +64 -0
- package/lib/typescript/helpers/caption.d.ts.map +1 -0
- package/lib/typescript/helpers/createMainMessageForThread.d.ts.map +1 -1
- package/lib/typescript/helpers/createMessageFromXml.d.ts.map +1 -1
- package/lib/typescript/helpers/fileKind.d.ts +20 -0
- package/lib/typescript/helpers/fileKind.d.ts.map +1 -0
- package/lib/typescript/helpers/getDataFromXml.d.ts.map +1 -1
- package/lib/typescript/helpers/mapWithConcurrency.d.ts +9 -0
- package/lib/typescript/helpers/mapWithConcurrency.d.ts.map +1 -0
- package/lib/typescript/helpers/mediaLimits.d.ts +13 -0
- package/lib/typescript/helpers/mediaLimits.d.ts.map +1 -0
- package/lib/typescript/helpers/mediaSendRetry.d.ts +26 -0
- package/lib/typescript/helpers/mediaSendRetry.d.ts.map +1 -0
- package/lib/typescript/helpers/mediaWireData.d.ts +16 -0
- package/lib/typescript/helpers/mediaWireData.d.ts.map +1 -0
- package/lib/typescript/helpers/mentionSpans.d.ts +8 -0
- package/lib/typescript/helpers/mentionSpans.d.ts.map +1 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts +7 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -1
- package/lib/typescript/helpers/readReceipts.d.ts +82 -0
- package/lib/typescript/helpers/readReceipts.d.ts.map +1 -0
- package/lib/typescript/helpers/repairFilenameEncoding.d.ts +12 -0
- package/lib/typescript/helpers/repairFilenameEncoding.d.ts.map +1 -0
- package/lib/typescript/helpers/safeJson.d.ts +2 -0
- package/lib/typescript/helpers/safeJson.d.ts.map +1 -0
- package/lib/typescript/helpers/updateMessagesTillLast.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts +2 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +1 -1
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts +2 -0
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts +7 -3
- 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/sendDisplayedMarker.xmpp.d.ts +3 -0
- package/lib/typescript/networking/xmpp/sendDisplayedMarker.xmpp.d.ts.map +1 -0
- package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts +12 -0
- package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendReceivedReceipt.xmpp.d.ts +3 -0
- package/lib/typescript/networking/xmpp/sendReceivedReceipt.xmpp.d.ts.map +1 -0
- package/lib/typescript/networking/xmppClient.d.ts +15 -0
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts +22 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +67 -3
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/attachment.model.d.ts +52 -0
- package/lib/typescript/types/models/attachment.model.d.ts.map +1 -0
- package/lib/typescript/types/models/message.model.d.ts +26 -0
- package/lib/typescript/types/models/message.model.d.ts.map +1 -1
- package/lib/typescript/types/models/modal.model.d.ts +7 -0
- package/lib/typescript/types/models/modal.model.d.ts.map +1 -1
- package/lib/typescript/types/models/room.model.d.ts +2 -0
- package/lib/typescript/types/models/room.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +69 -1
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/package.json +4 -1
- package/plugins/notification-service/Info.plist +31 -0
- package/plugins/notification-service/NotificationService.swift +82 -0
- package/plugins/withNotificationServiceExtension.js +137 -0
- package/src/assets/icons.tsx +20 -2
- package/src/components/MainComponents/AlbumGrid.tsx +183 -0
- package/src/components/MainComponents/ChatRoom.tsx +4 -2
- package/src/components/MainComponents/MediaMessage.tsx +246 -130
- package/src/components/MainComponents/MediaUploadOverlay.tsx +102 -0
- package/src/components/MessageBubble/MediaCaption.tsx +45 -0
- package/src/components/MessageBubble/Message.tsx +71 -3
- package/src/components/MessageBubble/MessageInteractions.tsx +2 -1
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +64 -0
- package/src/components/RoomComponents/LastMessageItem.tsx +15 -4
- package/src/components/RoomComponents/styled/LastAudioMessage.tsx +6 -3
- package/src/components/RoomComponents/styled/LastMessageFile.tsx +6 -2
- package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +6 -2
- package/src/components/RoomComponents/styled/LastMessageVideo.tsx +6 -2
- package/src/components/Thread/ThreadWrapper.tsx +5 -9
- package/src/components/VideoCalls/ActiveCallBar.tsx +56 -10
- package/src/components/VideoCalls/CallIcons.tsx +36 -12
- package/src/components/VideoCalls/VideoCallOverlay.tsx +205 -8
- package/src/components/VideoCalls/VideoCallSession.tsx +45 -13
- package/src/components/VideoCalls/callSessionController.ts +51 -20
- package/src/components/VideoCalls/callUiStore.ts +33 -3
- package/src/components/VideoCalls/livekitRuntime.ts +13 -0
- package/src/components/VideoCalls/useCallKeep.ts +204 -33
- package/src/components/VideoCalls/useOngoingCallNotification.ts +113 -0
- package/src/components/VideoCalls/usePipTile.ts +214 -0
- package/src/components/styled/MediaFilePreview.tsx +49 -34
- package/src/components/styled/MessageImage.tsx +21 -5
- package/src/components/styled/SendInput.tsx +101 -87
- package/src/components/styled/VideoMessage.tsx +34 -9
- package/src/context/xmppProvider.tsx +32 -0
- package/src/e2ee/fileEnvelope.ts +1 -1
- package/src/e2ee/sealedBody.ts +44 -5
- package/src/helpers/albumLayout.ts +207 -0
- package/src/helpers/attachments.ts +316 -0
- package/src/helpers/caption.ts +283 -0
- package/src/helpers/createMainMessageForThread.ts +6 -1
- package/src/helpers/createMessageFromXml.ts +21 -5
- package/src/helpers/fileKind.ts +38 -0
- package/src/helpers/getDataFromXml.ts +5 -1
- package/src/helpers/mapWithConcurrency.ts +32 -0
- package/src/helpers/mediaLimits.ts +27 -0
- package/src/helpers/mediaSendRetry.ts +59 -0
- package/src/helpers/mediaWireData.ts +57 -0
- package/src/helpers/mentionSpans.ts +17 -0
- package/src/helpers/mimeToExtension.ts +51 -0
- package/src/helpers/readReceipts.ts +219 -0
- package/src/helpers/repairFilenameEncoding.ts +82 -0
- package/src/helpers/safeJson.ts +11 -0
- package/src/helpers/updateMessagesTillLast.tsx +2 -1
- package/src/hooks/useSendMessage.tsx +448 -249
- package/src/i18n/strings.ts +144 -0
- package/src/main.ts +3 -0
- package/src/networking/api-requests/auth.api.ts +60 -3
- package/src/networking/stanzaHandlers.ts +91 -2
- package/src/networking/xmpp/handleStanzas.xmpp.ts +6 -2
- package/src/networking/xmpp/sendDisplayedMarker.xmpp.ts +31 -0
- package/src/networking/xmpp/sendMediaMessage.xmpp.ts +60 -3
- package/src/networking/xmpp/sendReceivedReceipt.xmpp.ts +31 -0
- package/src/networking/xmppClient.ts +48 -0
- package/src/roomStore/persistence.ts +94 -3
- package/src/roomStore/roomHeapSlice.ts +23 -1
- package/src/roomStore/roomsSlice.ts +112 -1
- package/src/types/models/attachment.model.ts +51 -0
- package/src/types/models/message.model.ts +29 -0
- package/src/types/models/modal.model.ts +7 -0
- package/src/types/models/room.model.ts +2 -0
- package/src/types/types.ts +83 -1
- package/src/version.ts +1 -1
- package/lib/commonjs/components/VideoCalls/useDraggable.js +0 -59
- package/lib/commonjs/components/VideoCalls/useDraggable.js.map +0 -1
- package/lib/module/components/VideoCalls/useDraggable.js +0 -55
- package/lib/module/components/VideoCalls/useDraggable.js.map +0 -1
- package/lib/typescript/components/VideoCalls/useDraggable.d.ts +0 -19
- package/lib/typescript/components/VideoCalls/useDraggable.d.ts.map +0 -1
- package/src/components/VideoCalls/useDraggable.ts +0 -46
|
@@ -16,11 +16,26 @@ import { store } from '../../roomStore';
|
|
|
16
16
|
|
|
17
17
|
interface CallUiState {
|
|
18
18
|
minimized: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* iOS shows this incoming call in its own CallKit UI (banner / full
|
|
21
|
+
* screen), so the in-app ring card stays hidden instead of doubling it.
|
|
22
|
+
*/
|
|
23
|
+
systemRinging: boolean;
|
|
19
24
|
/** Id of the header that shows the strip, or null when none is mounted. */
|
|
20
25
|
barHost: number | null;
|
|
26
|
+
/**
|
|
27
|
+
* Window y of the top of the strip slot under the hosting header, so the
|
|
28
|
+
* collapse animation can land exactly on the strip. Null: no header.
|
|
29
|
+
*/
|
|
30
|
+
barAnchorY: number | null;
|
|
21
31
|
}
|
|
22
32
|
|
|
23
|
-
let state: CallUiState = {
|
|
33
|
+
let state: CallUiState = {
|
|
34
|
+
minimized: false,
|
|
35
|
+
systemRinging: false,
|
|
36
|
+
barHost: null,
|
|
37
|
+
barAnchorY: null,
|
|
38
|
+
};
|
|
24
39
|
const hosts: number[] = [];
|
|
25
40
|
let nextHostId = 1;
|
|
26
41
|
const listeners = new Set<() => void>();
|
|
@@ -35,9 +50,13 @@ const emit = (patch: Partial<CallUiState>) => {
|
|
|
35
50
|
const ensureStoreWatcher = () => {
|
|
36
51
|
if (storeUnsubscribe) {return;}
|
|
37
52
|
storeUnsubscribe = store.subscribe(() => {
|
|
38
|
-
|
|
53
|
+
const phase = store.getState().call.phase;
|
|
54
|
+
if (state.minimized && phase === 'idle') {
|
|
39
55
|
emit({ minimized: false });
|
|
40
56
|
}
|
|
57
|
+
if (state.systemRinging && phase !== 'ringing-incoming') {
|
|
58
|
+
emit({ systemRinging: false });
|
|
59
|
+
}
|
|
41
60
|
});
|
|
42
61
|
};
|
|
43
62
|
|
|
@@ -61,6 +80,10 @@ export const setCallMinimized = (minimized: boolean): void => {
|
|
|
61
80
|
if (state.minimized !== minimized) {emit({ minimized });}
|
|
62
81
|
};
|
|
63
82
|
|
|
83
|
+
export const setCallSystemRinging = (systemRinging: boolean): void => {
|
|
84
|
+
if (state.systemRinging !== systemRinging) {emit({ systemRinging });}
|
|
85
|
+
};
|
|
86
|
+
|
|
64
87
|
export const registerCallBarHost = (
|
|
65
88
|
onId?: (id: number) => void
|
|
66
89
|
): (() => void) => {
|
|
@@ -71,6 +94,13 @@ export const registerCallBarHost = (
|
|
|
71
94
|
return () => {
|
|
72
95
|
const index = hosts.indexOf(id);
|
|
73
96
|
if (index >= 0) {hosts.splice(index, 1);}
|
|
74
|
-
|
|
97
|
+
const next = hosts.length ? hosts[hosts.length - 1] : null;
|
|
98
|
+
emit({ barHost: next, barAnchorY: next === null ? null : state.barAnchorY });
|
|
75
99
|
};
|
|
76
100
|
};
|
|
101
|
+
|
|
102
|
+
/** The hosting header reports where its strip slot is on screen. */
|
|
103
|
+
export const setCallBarAnchor = (hostId: number, y: number): void => {
|
|
104
|
+
if (state.barHost !== hostId || state.barAnchorY === y) {return;}
|
|
105
|
+
emit({ barAnchorY: y });
|
|
106
|
+
};
|
|
@@ -34,6 +34,11 @@ export interface LiveKitRuntime {
|
|
|
34
34
|
AudioSession: any;
|
|
35
35
|
/** Installs the WebRTC globals livekit-client expects. */
|
|
36
36
|
registerGlobals: () => void;
|
|
37
|
+
/**
|
|
38
|
+
* `@livekit/react-native-webrtc` RTCAudioSession: tells WebRTC when
|
|
39
|
+
* CallKit activates/deactivates the iOS audio session.
|
|
40
|
+
*/
|
|
41
|
+
RTCAudioSession: any;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
let cached: LiveKitRuntime | null | undefined;
|
|
@@ -59,6 +64,13 @@ export const loadLiveKit = (): LiveKitRuntime | null => {
|
|
|
59
64
|
// moving subset across versions, the core package does not.
|
|
60
65
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
61
66
|
const core = require('livekit-client');
|
|
67
|
+
let webrtc: any = null;
|
|
68
|
+
try {
|
|
69
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
70
|
+
webrtc = require('@livekit/react-native-webrtc');
|
|
71
|
+
} catch {
|
|
72
|
+
// Only needed for CallKit; calls work without it.
|
|
73
|
+
}
|
|
62
74
|
|
|
63
75
|
cached = {
|
|
64
76
|
Room: core.Room,
|
|
@@ -69,6 +81,7 @@ export const loadLiveKit = (): LiveKitRuntime | null => {
|
|
|
69
81
|
VideoTrack: rn.VideoTrack,
|
|
70
82
|
AudioSession: rn.AudioSession,
|
|
71
83
|
registerGlobals: rn.registerGlobals,
|
|
84
|
+
RTCAudioSession: webrtc?.RTCAudioSession ?? null,
|
|
72
85
|
};
|
|
73
86
|
} catch {
|
|
74
87
|
cached = null;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef } from 'react';
|
|
1
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
3
|
import { useDispatch, useSelector } from 'react-redux';
|
|
4
4
|
import { RootState, store } from '../../roomStore';
|
|
5
5
|
import { acceptIncomingCall, declineIncomingCall } from '../../roomStore/callSlice';
|
|
6
6
|
import { sendCallStateSignal } from '../../networking/callTokenStanza';
|
|
7
|
+
import { terminateActiveCall } from './callActions';
|
|
8
|
+
import { setCallMicEnabled, useCallSession } from './callSessionController';
|
|
9
|
+
import { loadLiveKit } from './livekitRuntime';
|
|
10
|
+
import { setCallSystemRinging } from './callUiStore';
|
|
7
11
|
|
|
8
12
|
/**
|
|
9
13
|
* Native incoming-call UI (Android ConnectionService / iOS CallKit) via
|
|
@@ -14,6 +18,12 @@ import { sendCallStateSignal } from '../../networking/callTokenStanza';
|
|
|
14
18
|
* loaded lazily exactly like the LiveKit packages, so hosts that don't
|
|
15
19
|
* install it get the plain in-app ring screen and nothing breaks.
|
|
16
20
|
*
|
|
21
|
+
* On iOS every call, incoming or outgoing, is also reported to CallKit for
|
|
22
|
+
* as long as it lasts. That is what puts it in the Dynamic Island / the
|
|
23
|
+
* green status-bar pill when the app is in the background, with the
|
|
24
|
+
* system's own mute and end buttons, and what keeps the call's audio
|
|
25
|
+
* running in the background.
|
|
26
|
+
*
|
|
17
27
|
* Platform reality, stated plainly:
|
|
18
28
|
* - Android: full value. A ConnectionService call shows the system
|
|
19
29
|
* incoming-call screen over the lock screen.
|
|
@@ -35,6 +45,18 @@ interface CallKeepModule {
|
|
|
35
45
|
) => void;
|
|
36
46
|
endCall: (uuid: string) => void;
|
|
37
47
|
endAllCalls: () => void;
|
|
48
|
+
startCall?: (
|
|
49
|
+
uuid: string,
|
|
50
|
+
handle: string,
|
|
51
|
+
contactIdentifier?: string,
|
|
52
|
+
handleType?: string,
|
|
53
|
+
hasVideo?: boolean
|
|
54
|
+
) => void;
|
|
55
|
+
answerIncomingCall?: (uuid: string) => void;
|
|
56
|
+
reportConnectingOutgoingCallWithUUID?: (uuid: string) => void;
|
|
57
|
+
reportConnectedOutgoingCallWithUUID?: (uuid: string) => void;
|
|
58
|
+
reportEndCallWithUUID?: (uuid: string, reason: number) => void;
|
|
59
|
+
setMutedCall?: (uuid: string, muted: boolean) => void;
|
|
38
60
|
addEventListener: (event: string, handler: (payload: any) => void) => void;
|
|
39
61
|
removeEventListener: (event: string) => void;
|
|
40
62
|
setAvailable?: (available: boolean) => void;
|
|
@@ -95,16 +117,32 @@ const toUuid = (seed: string): string => {
|
|
|
95
117
|
].join('-');
|
|
96
118
|
};
|
|
97
119
|
|
|
120
|
+
const trace = (...args: unknown[]) => {
|
|
121
|
+
if (__DEV__) {console.log('[calls] CallKit:', ...args);}
|
|
122
|
+
};
|
|
123
|
+
|
|
98
124
|
export const useCallKeep = (): void => {
|
|
99
125
|
const dispatch = useDispatch();
|
|
100
126
|
const call = useSelector((state: RootState) => state.call);
|
|
127
|
+
const session = useCallSession();
|
|
101
128
|
const callKeep = useMemo(() => loadCallKeep(), []);
|
|
129
|
+
const [ready, setReady] = useState(false);
|
|
102
130
|
const activeUuidRef = useRef<string | null>(null);
|
|
103
|
-
|
|
131
|
+
// The CallKit call has been answered (from the system screen or in-app).
|
|
132
|
+
const answeredRef = useRef(false);
|
|
133
|
+
const outgoingReportedRef = useRef<'none' | 'connecting' | 'connected'>('none');
|
|
134
|
+
const isIOS = Platform.OS === 'ios';
|
|
104
135
|
|
|
105
136
|
// One-time native setup.
|
|
106
137
|
useEffect(() => {
|
|
107
|
-
if (!callKeep) {
|
|
138
|
+
if (!callKeep) {
|
|
139
|
+
if (isIOS) {
|
|
140
|
+
// The usual reason for "no Dynamic Island": the JS package is there
|
|
141
|
+
// but the binary was built without the RNCallKeep pod.
|
|
142
|
+
trace('unavailable (react-native-callkeep is not linked in this build)');
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
108
146
|
let cancelled = false;
|
|
109
147
|
|
|
110
148
|
(async () => {
|
|
@@ -113,6 +151,11 @@ export const useCallKeep = (): void => {
|
|
|
113
151
|
ios: {
|
|
114
152
|
appName: 'Ethora',
|
|
115
153
|
supportsVideo: true,
|
|
154
|
+
maximumCallGroups: '1',
|
|
155
|
+
maximumCallsPerCallGroup: '1',
|
|
156
|
+
// Our calls are not phone calls: keep them out of the Phone
|
|
157
|
+
// app's Recents, whose entries would dial back into nowhere.
|
|
158
|
+
includesCallsInRecents: false,
|
|
116
159
|
},
|
|
117
160
|
android: {
|
|
118
161
|
alertTitle: 'Permissions required',
|
|
@@ -130,28 +173,35 @@ export const useCallKeep = (): void => {
|
|
|
130
173
|
});
|
|
131
174
|
if (cancelled) {return;}
|
|
132
175
|
callKeep.setAvailable?.(true);
|
|
133
|
-
|
|
134
|
-
|
|
176
|
+
trace('ready');
|
|
177
|
+
setReady(true);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
trace('setup failed', error);
|
|
135
180
|
// Host didn't grant phone-account permission, or the module isn't
|
|
136
181
|
// linked. The in-app ring screen still works, so stay quiet.
|
|
137
|
-
|
|
182
|
+
setReady(false);
|
|
138
183
|
}
|
|
139
184
|
})();
|
|
140
185
|
|
|
141
186
|
return () => {
|
|
142
187
|
cancelled = true;
|
|
143
188
|
};
|
|
144
|
-
}, [callKeep]);
|
|
189
|
+
}, [callKeep, isIOS]);
|
|
145
190
|
|
|
146
|
-
// Bridge native
|
|
191
|
+
// Bridge native actions back into the call.
|
|
147
192
|
useEffect(() => {
|
|
148
193
|
if (!callKeep) {return;}
|
|
149
194
|
|
|
150
195
|
const onAnswer = () => {
|
|
196
|
+
answeredRef.current = true;
|
|
151
197
|
// The user answered from the system screen, which on Android may
|
|
152
198
|
// mean the app was not even in the foreground.
|
|
153
199
|
callKeep.backToForeground?.();
|
|
154
|
-
|
|
200
|
+
// Only from the ring: CallKit also reports the answer we make on its
|
|
201
|
+
// behalf after an in-app accept, and re-accepting then would drop an
|
|
202
|
+
// in-progress call back to 'connecting'.
|
|
203
|
+
const current = store.getState().call;
|
|
204
|
+
if (current.direction === 'incoming' && current.phase === 'ringing-incoming') {
|
|
155
205
|
dispatch(acceptIncomingCall());
|
|
156
206
|
}
|
|
157
207
|
};
|
|
@@ -165,73 +215,198 @@ export const useCallKeep = (): void => {
|
|
|
165
215
|
) {
|
|
166
216
|
sendCallStateSignal('declined');
|
|
167
217
|
dispatch(declineIncomingCall());
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Ended from the Dynamic Island, the lock screen or a headset.
|
|
221
|
+
if (snapshot.phase === 'error') {return;}
|
|
222
|
+
terminateActiveCall(snapshot.phase === 'requesting' ? 'cancelled' : 'ended');
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// The system mute button (Dynamic Island, lock screen, CarPlay).
|
|
226
|
+
const onMuted = ({ muted }: { muted: boolean }) => {
|
|
227
|
+
void setCallMicEnabled(!muted);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
// Another call (e.g. a phone call) put ours on hold: stop sending audio.
|
|
231
|
+
const onHold = ({ hold }: { hold: boolean }) => {
|
|
232
|
+
if (hold) {void setCallMicEnabled(false);}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
// CallKit owns the iOS audio session: WebRTC may only start its audio
|
|
236
|
+
// unit once CallKit has activated the session.
|
|
237
|
+
const onAudioActivated = () => {
|
|
238
|
+
try {
|
|
239
|
+
loadLiveKit()?.RTCAudioSession?.audioSessionDidActivate?.();
|
|
240
|
+
} catch {
|
|
241
|
+
// Older webrtc builds manage the session on their own.
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
const onAudioDeactivated = () => {
|
|
245
|
+
try {
|
|
246
|
+
loadLiveKit()?.RTCAudioSession?.audioSessionDidDeactivate?.();
|
|
247
|
+
} catch {
|
|
248
|
+
// noop
|
|
168
249
|
}
|
|
169
250
|
};
|
|
170
251
|
|
|
171
252
|
callKeep.addEventListener('answerCall', onAnswer);
|
|
172
253
|
callKeep.addEventListener('endCall', onEnd);
|
|
254
|
+
callKeep.addEventListener('didPerformSetMutedCallAction', onMuted);
|
|
255
|
+
callKeep.addEventListener('didToggleHoldCallAction', onHold);
|
|
256
|
+
callKeep.addEventListener('didActivateAudioSession', onAudioActivated);
|
|
257
|
+
// CallKit rejected or dropped our calls (e.g. a build without the voip
|
|
258
|
+
// background mode): there is nothing to end any more.
|
|
259
|
+
const onReset = () => {
|
|
260
|
+
trace('provider reset');
|
|
261
|
+
};
|
|
262
|
+
callKeep.addEventListener('didResetProvider', onReset);
|
|
263
|
+
// The system's verdict on displayIncomingCall ("Unentitled" means the
|
|
264
|
+
// app lacks the voip background mode).
|
|
265
|
+
const onDisplayed = ({ error, errorCode }: { error?: string; errorCode?: string }) => {
|
|
266
|
+
trace('incoming call shown', error ? `failed: ${errorCode || ''} ${error}` : 'ok');
|
|
267
|
+
// CallKit refused it (Do Not Disturb, unentitled...): bring the
|
|
268
|
+
// in-app ring card back so the call can still be answered.
|
|
269
|
+
if (error) {setCallSystemRinging(false);}
|
|
270
|
+
};
|
|
271
|
+
callKeep.addEventListener('didDisplayIncomingCall', onDisplayed);
|
|
272
|
+
callKeep.addEventListener('didDeactivateAudioSession', onAudioDeactivated);
|
|
173
273
|
|
|
174
274
|
return () => {
|
|
175
275
|
callKeep.removeEventListener('answerCall');
|
|
176
276
|
callKeep.removeEventListener('endCall');
|
|
277
|
+
callKeep.removeEventListener('didPerformSetMutedCallAction');
|
|
278
|
+
callKeep.removeEventListener('didToggleHoldCallAction');
|
|
279
|
+
callKeep.removeEventListener('didActivateAudioSession');
|
|
280
|
+
callKeep.removeEventListener('didDeactivateAudioSession');
|
|
281
|
+
callKeep.removeEventListener('didResetProvider');
|
|
282
|
+
callKeep.removeEventListener('didDisplayIncomingCall');
|
|
177
283
|
};
|
|
178
284
|
}, [callKeep, dispatch]);
|
|
179
285
|
|
|
180
|
-
|
|
286
|
+
const displayName = call.roomName || 'Ethora';
|
|
287
|
+
const isRinging =
|
|
288
|
+
call.direction === 'incoming' && call.phase === 'ringing-incoming';
|
|
289
|
+
const isLive = call.phase === 'connecting' || call.phase === 'in-call';
|
|
290
|
+
const isOutgoing = call.direction === 'outgoing';
|
|
291
|
+
const peerConnected = session.anchorAt !== null;
|
|
292
|
+
|
|
293
|
+
// Report the call to the system as its state changes.
|
|
181
294
|
useEffect(() => {
|
|
182
|
-
if (!callKeep || !
|
|
295
|
+
if (!callKeep || !ready) {return;}
|
|
183
296
|
|
|
184
|
-
const
|
|
185
|
-
|
|
297
|
+
const release = () => {
|
|
298
|
+
if (!activeUuidRef.current) {return;}
|
|
299
|
+
try {
|
|
300
|
+
callKeep.endCall(activeUuidRef.current);
|
|
301
|
+
} catch {
|
|
302
|
+
// Screen already gone.
|
|
303
|
+
}
|
|
304
|
+
activeUuidRef.current = null;
|
|
305
|
+
answeredRef.current = false;
|
|
306
|
+
outgoingReportedRef.current = 'none';
|
|
307
|
+
};
|
|
186
308
|
|
|
187
|
-
if (
|
|
309
|
+
if (call.phase === 'idle' || call.phase === 'error') {
|
|
310
|
+
release();
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
if (isRinging) {
|
|
315
|
+
if (activeUuidRef.current) {return;}
|
|
188
316
|
const uuid = toUuid(call.callId || call.roomJid || String(Date.now()));
|
|
189
317
|
activeUuidRef.current = uuid;
|
|
318
|
+
answeredRef.current = false;
|
|
319
|
+
// iOS: the system banner is the ring UI (Telegram-style); the in-app
|
|
320
|
+
// card would only cover the screen under it.
|
|
321
|
+
if (isIOS) {setCallSystemRinging(true);}
|
|
190
322
|
try {
|
|
191
323
|
callKeep.displayIncomingCall(
|
|
192
324
|
uuid,
|
|
193
|
-
|
|
194
|
-
|
|
325
|
+
displayName,
|
|
326
|
+
displayName,
|
|
195
327
|
'generic',
|
|
196
328
|
call.kind === 'video'
|
|
197
329
|
);
|
|
198
330
|
} catch {
|
|
199
331
|
activeUuidRef.current = null;
|
|
332
|
+
setCallSystemRinging(false);
|
|
200
333
|
}
|
|
201
334
|
return;
|
|
202
335
|
}
|
|
203
336
|
|
|
204
|
-
//
|
|
205
|
-
//
|
|
206
|
-
if (
|
|
337
|
+
// iOS: an outgoing call is a CallKit call from the first ring, so it
|
|
338
|
+
// shows in the Dynamic Island even before the peer answers.
|
|
339
|
+
if (isIOS && isOutgoing && !activeUuidRef.current && callKeep.startCall) {
|
|
340
|
+
// Unique per call: CallKit refuses a UUID it has seen before, and
|
|
341
|
+
// the callId only arrives with the token.
|
|
342
|
+
const uuid = toUuid(`${call.roomJid || ''}|${call.startedAt || Date.now()}`);
|
|
343
|
+
activeUuidRef.current = uuid;
|
|
344
|
+
outgoingReportedRef.current = 'none';
|
|
345
|
+
trace('startCall', uuid);
|
|
207
346
|
try {
|
|
208
|
-
callKeep.
|
|
347
|
+
callKeep.startCall(uuid, displayName, displayName, 'generic', call.kind === 'video');
|
|
209
348
|
} catch {
|
|
210
|
-
|
|
349
|
+
activeUuidRef.current = null;
|
|
211
350
|
}
|
|
212
|
-
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const uuid = activeUuidRef.current;
|
|
355
|
+
if (!uuid) {return;}
|
|
356
|
+
|
|
357
|
+
if (isIOS && isOutgoing) {
|
|
358
|
+
if (peerConnected && outgoingReportedRef.current !== 'connected') {
|
|
359
|
+
outgoingReportedRef.current = 'connected';
|
|
360
|
+
callKeep.reportConnectedOutgoingCallWithUUID?.(uuid);
|
|
361
|
+
} else if (
|
|
362
|
+
isLive &&
|
|
363
|
+
!peerConnected &&
|
|
364
|
+
outgoingReportedRef.current === 'none'
|
|
365
|
+
) {
|
|
366
|
+
outgoingReportedRef.current = 'connecting';
|
|
367
|
+
callKeep.reportConnectingOutgoingCallWithUUID?.(uuid);
|
|
368
|
+
}
|
|
369
|
+
return;
|
|
213
370
|
}
|
|
214
371
|
|
|
215
|
-
|
|
372
|
+
// Incoming, accepted with the in-app button: tell CallKit, or its
|
|
373
|
+
// screen keeps ringing on top of the call.
|
|
374
|
+
if (isIOS && isLive && !answeredRef.current) {
|
|
375
|
+
answeredRef.current = true;
|
|
216
376
|
try {
|
|
217
|
-
callKeep.
|
|
377
|
+
callKeep.answerIncomingCall?.(uuid);
|
|
218
378
|
} catch {
|
|
219
379
|
// noop
|
|
220
380
|
}
|
|
221
|
-
activeUuidRef.current = null;
|
|
222
381
|
}
|
|
223
382
|
}, [
|
|
224
383
|
callKeep,
|
|
225
|
-
|
|
384
|
+
ready,
|
|
385
|
+
isIOS,
|
|
386
|
+
isRinging,
|
|
387
|
+
isLive,
|
|
388
|
+
isOutgoing,
|
|
389
|
+
peerConnected,
|
|
390
|
+
displayName,
|
|
226
391
|
call.phase,
|
|
227
392
|
call.callId,
|
|
228
393
|
call.roomJid,
|
|
229
|
-
call.
|
|
230
|
-
call.peerXmppUsername,
|
|
394
|
+
call.startedAt,
|
|
231
395
|
call.kind,
|
|
232
396
|
]);
|
|
233
397
|
|
|
234
|
-
//
|
|
398
|
+
// Keep the system mute button in step with ours.
|
|
399
|
+
useEffect(() => {
|
|
400
|
+
const uuid = activeUuidRef.current;
|
|
401
|
+
if (!callKeep || !ready || !isIOS || !uuid || !isLive) {return;}
|
|
402
|
+
try {
|
|
403
|
+
callKeep.setMutedCall?.(uuid, !session.micOn);
|
|
404
|
+
} catch {
|
|
405
|
+
// noop
|
|
406
|
+
}
|
|
407
|
+
}, [callKeep, ready, isIOS, isLive, session.micOn]);
|
|
408
|
+
|
|
409
|
+
// Nothing to clean up on unmount beyond the active call: this hook
|
|
235
410
|
// lives for the lifetime of the provider.
|
|
236
411
|
useEffect(
|
|
237
412
|
() => () => {
|
|
@@ -245,8 +420,4 @@ export const useCallKeep = (): void => {
|
|
|
245
420
|
},
|
|
246
421
|
[callKeep]
|
|
247
422
|
);
|
|
248
|
-
|
|
249
|
-
// iOS-only note kept as a runtime no-op so the import isn't unused when
|
|
250
|
-
// the platform check is tree-shaken in release builds.
|
|
251
|
-
void Platform.OS;
|
|
252
423
|
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
import { useSelector } from 'react-redux';
|
|
3
|
+
import { RootState } from '../../roomStore';
|
|
4
|
+
import { useT } from '../../i18n/useT';
|
|
5
|
+
import type {
|
|
6
|
+
OngoingCallNotification,
|
|
7
|
+
OngoingCallNotificationAction,
|
|
8
|
+
} from '../../types/types';
|
|
9
|
+
import { terminateActiveCall } from './callActions';
|
|
10
|
+
import { toggleCallCamera, toggleCallMic, useCallSession } from './callSessionController';
|
|
11
|
+
import { setCallMinimized } from './callUiStore';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Drives the host's ongoing-call notification (`videoCalls.
|
|
15
|
+
* ongoingCallNotification`, an Android foreground-service notification in
|
|
16
|
+
* the Ethora app): shown while a call is connecting or connected, updated
|
|
17
|
+
* when the mic, camera or timer anchor change, and its buttons act on the
|
|
18
|
+
* call like the in-app ones.
|
|
19
|
+
*/
|
|
20
|
+
export const useOngoingCallNotification = (
|
|
21
|
+
adapter: OngoingCallNotification | undefined
|
|
22
|
+
): void => {
|
|
23
|
+
const t = useT();
|
|
24
|
+
const call = useSelector((state: RootState) => state.call);
|
|
25
|
+
const session = useCallSession();
|
|
26
|
+
const shownRef = useRef(false);
|
|
27
|
+
|
|
28
|
+
const live =
|
|
29
|
+
!!call.token && (call.phase === 'connecting' || call.phase === 'in-call');
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!adapter) {return;}
|
|
33
|
+
return adapter.addActionListener((action: OngoingCallNotificationAction) => {
|
|
34
|
+
switch (action) {
|
|
35
|
+
case 'hangUp':
|
|
36
|
+
terminateActiveCall('ended');
|
|
37
|
+
break;
|
|
38
|
+
case 'toggleMic':
|
|
39
|
+
void toggleCallMic();
|
|
40
|
+
break;
|
|
41
|
+
case 'toggleCamera':
|
|
42
|
+
void toggleCallCamera();
|
|
43
|
+
break;
|
|
44
|
+
case 'open':
|
|
45
|
+
// Back from the notification: show the call, not the strip.
|
|
46
|
+
setCallMinimized(false);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}, [adapter]);
|
|
51
|
+
|
|
52
|
+
const isVideo = call.kind === 'video';
|
|
53
|
+
const connectedAt = session.anchorAt;
|
|
54
|
+
const text =
|
|
55
|
+
connectedAt !== null
|
|
56
|
+
? isVideo
|
|
57
|
+
? t('call.notification.ongoingVideo')
|
|
58
|
+
: t('call.notification.ongoing')
|
|
59
|
+
: !session.connected
|
|
60
|
+
? t('call.status.connecting')
|
|
61
|
+
: t('call.status.waitingForPeer');
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (!adapter) {return;}
|
|
65
|
+
if (!live) {
|
|
66
|
+
if (shownRef.current) {
|
|
67
|
+
shownRef.current = false;
|
|
68
|
+
adapter.hide();
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
shownRef.current = true;
|
|
73
|
+
adapter.show({
|
|
74
|
+
callId: call.callId || call.roomJid || 'call',
|
|
75
|
+
title: call.roomName || t('call.unknownCaller'),
|
|
76
|
+
text,
|
|
77
|
+
kind: call.kind,
|
|
78
|
+
connectedAt,
|
|
79
|
+
micOn: session.micOn,
|
|
80
|
+
cameraOn: isVideo && session.cameraOn,
|
|
81
|
+
labels: {
|
|
82
|
+
hangUp: t('call.action.hangUp'),
|
|
83
|
+
mute: t('call.notification.mute'),
|
|
84
|
+
unmute: t('call.notification.unmute'),
|
|
85
|
+
cameraOn: t('call.notification.cameraOn'),
|
|
86
|
+
cameraOff: t('call.notification.cameraOff'),
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}, [
|
|
90
|
+
adapter,
|
|
91
|
+
live,
|
|
92
|
+
t,
|
|
93
|
+
text,
|
|
94
|
+
connectedAt,
|
|
95
|
+
isVideo,
|
|
96
|
+
call.callId,
|
|
97
|
+
call.roomJid,
|
|
98
|
+
call.roomName,
|
|
99
|
+
call.kind,
|
|
100
|
+
session.micOn,
|
|
101
|
+
session.cameraOn,
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
useEffect(
|
|
105
|
+
() => () => {
|
|
106
|
+
if (adapter && shownRef.current) {
|
|
107
|
+
shownRef.current = false;
|
|
108
|
+
adapter.hide();
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
[adapter]
|
|
112
|
+
);
|
|
113
|
+
};
|