@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
|
@@ -153,26 +153,50 @@ export const VideoCallIcon: React.FC<IconProps> = ({
|
|
|
153
153
|
</Svg>
|
|
154
154
|
);
|
|
155
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Front/back camera flip: a camera between two arrows turning around it
|
|
158
|
+
* (Material "cameraswitch", the glyph Telegram and the Android camera use),
|
|
159
|
+
* so it reads as "use the other camera", not as "reload".
|
|
160
|
+
*/
|
|
156
161
|
export const SwitchCameraIcon: React.FC<IconProps> = ({
|
|
157
162
|
color = '#FFFFFF',
|
|
158
163
|
size = 24,
|
|
159
164
|
}) => (
|
|
160
|
-
<Svg width={size} height={size} viewBox="0 0 24 24"
|
|
165
|
+
<Svg width={size} height={size} viewBox="0 0 24 24">
|
|
161
166
|
<Path
|
|
162
|
-
d="
|
|
163
|
-
|
|
164
|
-
strokeWidth={1.8}
|
|
165
|
-
fill="none"
|
|
166
|
-
strokeLinejoin="round"
|
|
167
|
+
d="M16 7h-1l-1-1h-4L9 7H8c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm-4 7c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"
|
|
168
|
+
fill={color}
|
|
167
169
|
/>
|
|
168
170
|
<Path
|
|
169
|
-
d="
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
171
|
+
d="M8.57.51l4.48 4.48V2.04c4.72.47 8.48 4.23 8.95 8.95h2C23.34 3.02 15.49-1.59 8.57.51zm2.38 21.45c-4.72-.47-8.48-4.23-8.95-8.95H0c.66 7.97 8.51 12.58 15.43 10.48l-4.48-4.48v2.95z"
|
|
172
|
+
fill={color}
|
|
173
|
+
/>
|
|
174
|
+
</Svg>
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
/** Stretch the video to fill the screen (Material "fullscreen"). */
|
|
178
|
+
export const FillVideoIcon: React.FC<IconProps> = ({
|
|
179
|
+
color = '#FFFFFF',
|
|
180
|
+
size = 24,
|
|
181
|
+
}) => (
|
|
182
|
+
<Svg width={size} height={size} viewBox="0 0 24 24">
|
|
183
|
+
<Path
|
|
184
|
+
d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"
|
|
185
|
+
fill={color}
|
|
186
|
+
/>
|
|
187
|
+
</Svg>
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
/** Show the whole video, letterboxed (Material "fit_screen"). */
|
|
191
|
+
export const FitVideoIcon: React.FC<IconProps> = ({
|
|
192
|
+
color = '#FFFFFF',
|
|
193
|
+
size = 24,
|
|
194
|
+
}) => (
|
|
195
|
+
<Svg width={size} height={size} viewBox="0 0 24 24">
|
|
196
|
+
<Path
|
|
197
|
+
d="M17 4h3c1.1 0 2 .9 2 2v2h-2V6h-3V4zM4 8V6h3V4H4c-1.1 0-2 .9-2 2v2h2zm16 8v2h-3v2h3c1.1 0 2-.9 2-2v-2h-2zM7 18H4v-2H2v2c0 1.1.9 2 2 2h3v-2zM18 8H6v8h12V8z"
|
|
198
|
+
fill={color}
|
|
174
199
|
/>
|
|
175
|
-
<Path d="M14 9.5V11h-1.5M10 16.5V15h1.5" stroke={color} strokeWidth={1.8} />
|
|
176
200
|
</Svg>
|
|
177
201
|
);
|
|
178
202
|
|
|
@@ -12,14 +12,17 @@ import {
|
|
|
12
12
|
BackHandler,
|
|
13
13
|
Easing,
|
|
14
14
|
Modal,
|
|
15
|
+
PanResponder,
|
|
15
16
|
Platform,
|
|
16
17
|
StyleSheet,
|
|
17
18
|
Text,
|
|
18
19
|
TouchableOpacity,
|
|
20
|
+
useWindowDimensions,
|
|
19
21
|
Vibration,
|
|
20
22
|
View,
|
|
21
23
|
} from 'react-native';
|
|
22
24
|
import { useDispatch, useSelector } from 'react-redux';
|
|
25
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
23
26
|
import { RootState } from '../../roomStore';
|
|
24
27
|
import {
|
|
25
28
|
acceptIncomingCall,
|
|
@@ -33,7 +36,13 @@ import type { ChatTheme } from '../../theme/theme';
|
|
|
33
36
|
import { VideoCallSession } from './VideoCallSession';
|
|
34
37
|
import { startCallSession } from './callSessionController';
|
|
35
38
|
import { declineActiveCall, terminateActiveCall } from './callActions';
|
|
36
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
CALL_BAR_HEIGHT,
|
|
41
|
+
CALL_BAR_MARGIN_TOP,
|
|
42
|
+
CALL_BAR_MARGIN_X,
|
|
43
|
+
CALL_BAR_RADIUS,
|
|
44
|
+
DockedCallBar,
|
|
45
|
+
} from './ActiveCallBar';
|
|
37
46
|
import { setCallMinimized, useCallUi } from './callUiStore';
|
|
38
47
|
import { ProfileImagePlaceholder } from '../MainComponents/ProfileImagePlaceholder';
|
|
39
48
|
import {
|
|
@@ -44,6 +53,7 @@ import {
|
|
|
44
53
|
import { VideoCallIcons } from '../../types/types';
|
|
45
54
|
import { useT } from '../../i18n/useT';
|
|
46
55
|
import { useCallKeep } from './useCallKeep';
|
|
56
|
+
import { useOngoingCallNotification } from './useOngoingCallNotification';
|
|
47
57
|
|
|
48
58
|
const DEFAULT_PRIMARY = '#0052CD';
|
|
49
59
|
const DANGER = '#E53935';
|
|
@@ -250,6 +260,160 @@ const RingingCard: FC<RingingCardProps> = ({
|
|
|
250
260
|
);
|
|
251
261
|
};
|
|
252
262
|
|
|
263
|
+
/**
|
|
264
|
+
* The full-screen call, collapsible into the header strip, Telegram-style:
|
|
265
|
+
* pulling it up morphs the whole screen into the green bubble under the
|
|
266
|
+
* header (position, width, height and corner radius all travel together,
|
|
267
|
+
* and the bubble's colour fades in on the way), so it visibly *becomes* the
|
|
268
|
+
* strip rather than leaving and the strip popping in. Let go past a quarter
|
|
269
|
+
* of the way, or flick, and it finishes; released early it springs back.
|
|
270
|
+
* The minimize button runs the same morph; expanding from the strip runs it
|
|
271
|
+
* backwards.
|
|
272
|
+
*
|
|
273
|
+
* Buttons and the draggable video tile handle their own touches; a drag
|
|
274
|
+
* anywhere else on the screen is ours, and only its upward part counts.
|
|
275
|
+
*/
|
|
276
|
+
const CollapsibleCallSurface: FC<{
|
|
277
|
+
enterFromTop: boolean;
|
|
278
|
+
barColor: string;
|
|
279
|
+
onCollapsed: () => void;
|
|
280
|
+
children: (collapse: () => void) => ReactNode;
|
|
281
|
+
}> = ({ enterFromTop, barColor, onCollapsed, children }) => {
|
|
282
|
+
const { width, height } = useWindowDimensions();
|
|
283
|
+
const insets = useSafeAreaInsets();
|
|
284
|
+
const { barAnchorY } = useCallUi();
|
|
285
|
+
// Where the bubble sits: under the hosting header, or under the status
|
|
286
|
+
// bar when no header is on screen (the docked fallback).
|
|
287
|
+
const target = {
|
|
288
|
+
top: (barAnchorY ?? insets.top) + CALL_BAR_MARGIN_TOP,
|
|
289
|
+
side: CALL_BAR_MARGIN_X,
|
|
290
|
+
height: CALL_BAR_HEIGHT,
|
|
291
|
+
};
|
|
292
|
+
// 0 = full screen, 1 = the bubble.
|
|
293
|
+
const progress = useRef(new Animated.Value(enterFromTop ? 1 : 0)).current;
|
|
294
|
+
const collapsingRef = useRef(false);
|
|
295
|
+
const onCollapsedRef = useRef(onCollapsed);
|
|
296
|
+
onCollapsedRef.current = onCollapsed;
|
|
297
|
+
const heightRef = useRef(height);
|
|
298
|
+
heightRef.current = height;
|
|
299
|
+
|
|
300
|
+
useEffect(() => {
|
|
301
|
+
if (!enterFromTop) {return;}
|
|
302
|
+
Animated.timing(progress, {
|
|
303
|
+
toValue: 0,
|
|
304
|
+
duration: 300,
|
|
305
|
+
easing: Easing.out(Easing.cubic),
|
|
306
|
+
useNativeDriver: false,
|
|
307
|
+
}).start();
|
|
308
|
+
// Mount-only: the entrance plays once.
|
|
309
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
310
|
+
}, []);
|
|
311
|
+
|
|
312
|
+
const collapse = useCallback(() => {
|
|
313
|
+
if (collapsingRef.current) {return;}
|
|
314
|
+
collapsingRef.current = true;
|
|
315
|
+
Animated.timing(progress, {
|
|
316
|
+
toValue: 1,
|
|
317
|
+
duration: 280,
|
|
318
|
+
easing: Easing.out(Easing.cubic),
|
|
319
|
+
useNativeDriver: false,
|
|
320
|
+
}).start(() => onCollapsedRef.current());
|
|
321
|
+
}, [progress]);
|
|
322
|
+
|
|
323
|
+
const panHandlers = useMemo(() => {
|
|
324
|
+
const springBack = () =>
|
|
325
|
+
Animated.spring(progress, {
|
|
326
|
+
toValue: 0,
|
|
327
|
+
useNativeDriver: false,
|
|
328
|
+
damping: 22,
|
|
329
|
+
stiffness: 260,
|
|
330
|
+
}).start();
|
|
331
|
+
// How far the finger travels for the full morph.
|
|
332
|
+
const travel = () => heightRef.current * 0.6;
|
|
333
|
+
return PanResponder.create({
|
|
334
|
+
// Claim the touch as soon as it starts on the call screen itself
|
|
335
|
+
// (buttons and the video tile are deeper and win their own touches).
|
|
336
|
+
// Waiting for a move does not work here: the Modal's content sits
|
|
337
|
+
// under the host's screens in the React tree, and an ancestor there
|
|
338
|
+
// (a Pressable / keyboard-dismiss wrapper) takes the touch on start,
|
|
339
|
+
// after which no descendant is ever asked again.
|
|
340
|
+
onStartShouldSetPanResponder: () => !collapsingRef.current,
|
|
341
|
+
onMoveShouldSetPanResponder: () => !collapsingRef.current,
|
|
342
|
+
onPanResponderTerminationRequest: () => false,
|
|
343
|
+
onPanResponderMove: (_event, gesture) => {
|
|
344
|
+
progress.setValue(Math.min(1, Math.max(0, -gesture.dy / travel())));
|
|
345
|
+
},
|
|
346
|
+
onPanResponderRelease: (_event, gesture) => {
|
|
347
|
+
if (-gesture.dy / travel() > 0.25 || gesture.vy < -0.8) {
|
|
348
|
+
collapse();
|
|
349
|
+
} else {
|
|
350
|
+
springBack();
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
onPanResponderTerminate: springBack,
|
|
354
|
+
}).panHandlers;
|
|
355
|
+
}, [progress, collapse]);
|
|
356
|
+
|
|
357
|
+
const at = (from: number, to: number) =>
|
|
358
|
+
progress.interpolate({ inputRange: [0, 1], outputRange: [from, to] });
|
|
359
|
+
|
|
360
|
+
return (
|
|
361
|
+
<Animated.View
|
|
362
|
+
{...panHandlers}
|
|
363
|
+
style={[
|
|
364
|
+
styles.collapsible,
|
|
365
|
+
{
|
|
366
|
+
top: at(0, target.top),
|
|
367
|
+
left: at(0, target.side),
|
|
368
|
+
width: at(width, width - target.side * 2),
|
|
369
|
+
height: at(height, target.height),
|
|
370
|
+
// Rounded as soon as it starts moving (a card, like the screen's
|
|
371
|
+
// own corners), then tightening to the bubble's radius.
|
|
372
|
+
borderRadius: progress.interpolate({
|
|
373
|
+
inputRange: [0, 0.08, 0.7, 1],
|
|
374
|
+
outputRange: [0, 36, 28, CALL_BAR_RADIUS],
|
|
375
|
+
extrapolate: 'clamp',
|
|
376
|
+
}),
|
|
377
|
+
},
|
|
378
|
+
]}
|
|
379
|
+
>
|
|
380
|
+
{/* Fixed full-screen size: the content is clipped, never re-laid out
|
|
381
|
+
per frame (the video views would stutter). It fades as the bubble's
|
|
382
|
+
colour takes over. */}
|
|
383
|
+
<Animated.View
|
|
384
|
+
style={[
|
|
385
|
+
styles.sessionFixed,
|
|
386
|
+
{
|
|
387
|
+
width,
|
|
388
|
+
height,
|
|
389
|
+
opacity: progress.interpolate({
|
|
390
|
+
inputRange: [0, 0.55, 0.85],
|
|
391
|
+
outputRange: [1, 0.85, 0],
|
|
392
|
+
extrapolate: 'clamp',
|
|
393
|
+
}),
|
|
394
|
+
},
|
|
395
|
+
]}
|
|
396
|
+
>
|
|
397
|
+
{children(collapse)}
|
|
398
|
+
</Animated.View>
|
|
399
|
+
<Animated.View
|
|
400
|
+
pointerEvents="none"
|
|
401
|
+
style={[
|
|
402
|
+
StyleSheet.absoluteFill,
|
|
403
|
+
{
|
|
404
|
+
backgroundColor: barColor,
|
|
405
|
+
opacity: progress.interpolate({
|
|
406
|
+
inputRange: [0, 0.35, 0.9],
|
|
407
|
+
outputRange: [0, 0, 1],
|
|
408
|
+
extrapolate: 'clamp',
|
|
409
|
+
}),
|
|
410
|
+
},
|
|
411
|
+
]}
|
|
412
|
+
/>
|
|
413
|
+
</Animated.View>
|
|
414
|
+
);
|
|
415
|
+
};
|
|
416
|
+
|
|
253
417
|
/**
|
|
254
418
|
* A crash in the call UI must not take the chat down with it (web wraps
|
|
255
419
|
* the overlay in a silent ChatErrorBoundary). Renders nothing on error and
|
|
@@ -308,15 +472,25 @@ const VideoCallOverlayInner: FC = () => {
|
|
|
308
472
|
// callkeep. No-op otherwise, the in-app ring screen below is the
|
|
309
473
|
// fallback and always renders.
|
|
310
474
|
useCallKeep();
|
|
475
|
+
// Host-provided system notification (Android) with hang up / mute /
|
|
476
|
+
// camera buttons while the call runs.
|
|
477
|
+
useOngoingCallNotification(enabled ? videoCallsConfig?.ongoingCallNotification : undefined);
|
|
311
478
|
|
|
312
479
|
// Shared with the header strip (ActiveCallBar), which expands it again.
|
|
313
|
-
const { minimized } = useCallUi();
|
|
480
|
+
const { minimized, systemRinging } = useCallUi();
|
|
314
481
|
|
|
315
482
|
const canRenderSession =
|
|
316
483
|
!!call.token &&
|
|
317
484
|
(call.phase === 'connecting' || call.phase === 'in-call') &&
|
|
318
485
|
!!livekitUrl;
|
|
319
486
|
const isMinimized = minimized && canRenderSession;
|
|
487
|
+
// Expanding from the header strip slides the call down from the top
|
|
488
|
+
// instead of fading it in.
|
|
489
|
+
const wasMinimizedRef = useRef(false);
|
|
490
|
+
const enterFromTop = wasMinimizedRef.current && !isMinimized;
|
|
491
|
+
useEffect(() => {
|
|
492
|
+
wasMinimizedRef.current = isMinimized;
|
|
493
|
+
}, [isMinimized]);
|
|
320
494
|
|
|
321
495
|
// Join the LiveKit room once the call has a token. Idempotent, and the
|
|
322
496
|
// controller tears itself down when the call slice leaves these phases.
|
|
@@ -352,10 +526,11 @@ const VideoCallOverlayInner: FC = () => {
|
|
|
352
526
|
useEffect(() => {
|
|
353
527
|
const isRinging =
|
|
354
528
|
call.direction === 'incoming' && call.phase === 'ringing-incoming';
|
|
355
|
-
|
|
529
|
+
// CallKit rings (and vibrates) on its own.
|
|
530
|
+
if (!isRinging || systemRinging) {return;}
|
|
356
531
|
Vibration.vibrate(RING_VIBRATION_PATTERN, true);
|
|
357
532
|
return () => Vibration.cancel();
|
|
358
|
-
}, [call.direction, call.phase]);
|
|
533
|
+
}, [call.direction, call.phase, systemRinging]);
|
|
359
534
|
|
|
360
535
|
const hangupCurrent = useCallback(() => {
|
|
361
536
|
if (call.direction === 'incoming' && call.phase === 'ringing-incoming') {
|
|
@@ -410,13 +585,19 @@ const VideoCallOverlayInner: FC = () => {
|
|
|
410
585
|
const showIncomingDecision =
|
|
411
586
|
call.direction === 'incoming' && call.phase === 'ringing-incoming';
|
|
412
587
|
|
|
413
|
-
|
|
588
|
+
// The system's incoming-call banner is up (iOS CallKit); answering or
|
|
589
|
+
// declining it drives the call from there.
|
|
590
|
+
if (showIncomingDecision && systemRinging) {
|
|
591
|
+
return null;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
const renderSession = (collapse: () => void) => (
|
|
414
595
|
<VideoCallSession
|
|
415
596
|
kind={call.kind}
|
|
416
597
|
peerName={call.roomName}
|
|
417
598
|
primaryColor={primaryColor}
|
|
418
599
|
icons={videoCallsConfig?.icons}
|
|
419
|
-
onToggleMinimize={
|
|
600
|
+
onToggleMinimize={collapse}
|
|
420
601
|
onHangup={() => terminateActiveCall('ended')}
|
|
421
602
|
/>
|
|
422
603
|
);
|
|
@@ -432,7 +613,7 @@ const VideoCallOverlayInner: FC = () => {
|
|
|
432
613
|
<Modal
|
|
433
614
|
visible
|
|
434
615
|
transparent
|
|
435
|
-
animationType=
|
|
616
|
+
animationType={enterFromTop ? 'none' : 'fade'}
|
|
436
617
|
statusBarTranslucent
|
|
437
618
|
supportedOrientations={['portrait', 'landscape']}
|
|
438
619
|
onRequestClose={hangupCurrent}
|
|
@@ -440,7 +621,13 @@ const VideoCallOverlayInner: FC = () => {
|
|
|
440
621
|
{canRenderSession ? (
|
|
441
622
|
// Full-bleed: on a phone the call owns the screen, like the native
|
|
442
623
|
// dialer. The audio call keeps the same dark canvas as video.
|
|
443
|
-
<
|
|
624
|
+
<CollapsibleCallSurface
|
|
625
|
+
enterFromTop={enterFromTop}
|
|
626
|
+
barColor={theme.success}
|
|
627
|
+
onCollapsed={() => setCallMinimized(true)}
|
|
628
|
+
>
|
|
629
|
+
{renderSession}
|
|
630
|
+
</CollapsibleCallSurface>
|
|
444
631
|
) : (
|
|
445
632
|
<View style={[styles.backdrop, { backgroundColor: theme.overlay }]}>
|
|
446
633
|
{showIncomingDecision ? (
|
|
@@ -512,6 +699,16 @@ const styles = StyleSheet.create({
|
|
|
512
699
|
flex: 1,
|
|
513
700
|
backgroundColor: '#0B1220',
|
|
514
701
|
},
|
|
702
|
+
// No flex here: `flex: 1` would override the fixed height and re-lay the
|
|
703
|
+
// call out on every frame of the morph.
|
|
704
|
+
sessionFixed: {
|
|
705
|
+
backgroundColor: '#0B1220',
|
|
706
|
+
},
|
|
707
|
+
collapsible: {
|
|
708
|
+
position: 'absolute',
|
|
709
|
+
overflow: 'hidden',
|
|
710
|
+
backgroundColor: '#0B1220',
|
|
711
|
+
},
|
|
515
712
|
ringingCard: {
|
|
516
713
|
width: '100%',
|
|
517
714
|
maxWidth: 420,
|
|
@@ -14,6 +14,8 @@ import { ProfileImagePlaceholder } from '../MainComponents/ProfileImagePlacehold
|
|
|
14
14
|
import {
|
|
15
15
|
CameraOffIcon,
|
|
16
16
|
CameraOnIcon,
|
|
17
|
+
FillVideoIcon,
|
|
18
|
+
FitVideoIcon,
|
|
17
19
|
HangUpIcon,
|
|
18
20
|
MicOffIcon,
|
|
19
21
|
MicOnIcon,
|
|
@@ -31,7 +33,7 @@ import {
|
|
|
31
33
|
toggleCallSpeaker,
|
|
32
34
|
useCallSession,
|
|
33
35
|
} from './callSessionController';
|
|
34
|
-
import {
|
|
36
|
+
import { usePipTile } from './usePipTile';
|
|
35
37
|
import { useT } from '../../i18n/useT';
|
|
36
38
|
|
|
37
39
|
const DEFAULT_PRIMARY = '#0052CD';
|
|
@@ -99,10 +101,14 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
99
101
|
const insets = useSafeAreaInsets();
|
|
100
102
|
const runtime = loadLiveKit();
|
|
101
103
|
const session = useCallSession();
|
|
102
|
-
const
|
|
104
|
+
const pipTile = usePipTile({ topInset: insets.top });
|
|
103
105
|
const elapsed = useSharedCallElapsed(session.anchorAt);
|
|
104
106
|
// Telegram-style: tap the small tile to swap it with the big one.
|
|
105
107
|
const [swapped, setSwapped] = useState(false);
|
|
108
|
+
// The peer's video is shown whole by default: a web camera is landscape,
|
|
109
|
+
// and filling a portrait phone crops most of it away. The button next to
|
|
110
|
+
// minimize stretches it to fill (the old behaviour) and back.
|
|
111
|
+
const [fillRemote, setFillRemote] = useState(false);
|
|
106
112
|
|
|
107
113
|
if (!runtime) {
|
|
108
114
|
return (
|
|
@@ -124,6 +130,7 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
124
130
|
deviceError,
|
|
125
131
|
remoteMicMuted,
|
|
126
132
|
facingMode,
|
|
133
|
+
localVideoEpoch,
|
|
127
134
|
} = session;
|
|
128
135
|
// The call slice's name (the chat title) first, as web does: LiveKit's
|
|
129
136
|
// participant name is often just the opaque xmpp identity.
|
|
@@ -137,8 +144,14 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
137
144
|
const isSwapped = swapped && canSwap;
|
|
138
145
|
const mainVideo = isSwapped ? localVideo : showRemoteVideo ? remoteVideo : null;
|
|
139
146
|
const pipVideo = isSwapped ? remoteVideo : localLive ? localVideo : null;
|
|
147
|
+
const mainIsRemote = !!mainVideo && mainVideo === remoteVideo;
|
|
148
|
+
const mainFit = mainIsRemote && !fillRemote ? 'contain' : 'cover';
|
|
140
149
|
// Only the front camera is mirrored, as in every camera app.
|
|
141
150
|
const selfMirror = facingMode === 'user';
|
|
151
|
+
// The local view remounts when the camera is re-acquired (switching
|
|
152
|
+
// front/back), so it never keeps rendering the stopped stream.
|
|
153
|
+
const videoKey = (ref: any) =>
|
|
154
|
+
ref === localVideo ? `local-${localVideoEpoch}` : 'remote';
|
|
142
155
|
|
|
143
156
|
const statusText =
|
|
144
157
|
elapsed !== null
|
|
@@ -154,12 +167,13 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
154
167
|
return (
|
|
155
168
|
<View style={styles.canvas}>
|
|
156
169
|
{/* Stage */}
|
|
157
|
-
<View style={styles.stage}>
|
|
170
|
+
<View style={styles.stage} onLayout={pipTile.onStageLayout}>
|
|
158
171
|
{mainVideo ? (
|
|
159
172
|
<VideoTrack
|
|
173
|
+
key={videoKey(mainVideo)}
|
|
160
174
|
trackRef={mainVideo}
|
|
161
175
|
style={styles.remoteVideo}
|
|
162
|
-
objectFit=
|
|
176
|
+
objectFit={mainFit}
|
|
163
177
|
mirror={isSwapped && selfMirror}
|
|
164
178
|
zOrder={0}
|
|
165
179
|
/>
|
|
@@ -204,12 +218,12 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
204
218
|
</View>
|
|
205
219
|
)}
|
|
206
220
|
|
|
207
|
-
{/* Picture-in-picture:
|
|
208
|
-
it with the main video. */}
|
|
221
|
+
{/* Picture-in-picture: drag it and it snaps to a corner, pinch it
|
|
222
|
+
for the large size, tap it to swap it with the main video. */}
|
|
209
223
|
{pipVideo && (
|
|
210
224
|
<Animated.View
|
|
211
|
-
{...
|
|
212
|
-
style={[styles.pip,
|
|
225
|
+
{...pipTile.panHandlers}
|
|
226
|
+
style={[styles.pip, pipTile.style]}
|
|
213
227
|
>
|
|
214
228
|
<Pressable
|
|
215
229
|
style={styles.pipVideo}
|
|
@@ -219,6 +233,7 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
219
233
|
accessibilityLabel={t('call.action.swapVideo')}
|
|
220
234
|
>
|
|
221
235
|
<VideoTrack
|
|
236
|
+
key={videoKey(pipVideo)}
|
|
222
237
|
trackRef={pipVideo}
|
|
223
238
|
style={styles.pipVideo}
|
|
224
239
|
objectFit="cover"
|
|
@@ -240,6 +255,23 @@ export const VideoCallSession: FC<VideoCallSessionProps> = ({
|
|
|
240
255
|
</TouchableOpacity>
|
|
241
256
|
)}
|
|
242
257
|
|
|
258
|
+
{mainIsRemote && (
|
|
259
|
+
<TouchableOpacity
|
|
260
|
+
accessibilityRole="button"
|
|
261
|
+
accessibilityLabel={
|
|
262
|
+
fillRemote ? t('call.action.fitVideo') : t('call.action.fillVideo')
|
|
263
|
+
}
|
|
264
|
+
onPress={() => setFillRemote((value) => !value)}
|
|
265
|
+
style={[styles.minimizeButton, styles.fitButton, { top: 16 + insets.top }]}
|
|
266
|
+
>
|
|
267
|
+
{fillRemote ? (
|
|
268
|
+
<FitVideoIcon color={TEXT_ON_DARK} size={20} />
|
|
269
|
+
) : (
|
|
270
|
+
<FillVideoIcon color={TEXT_ON_DARK} size={20} />
|
|
271
|
+
)}
|
|
272
|
+
</TouchableOpacity>
|
|
273
|
+
)}
|
|
274
|
+
|
|
243
275
|
{!!deviceError && (
|
|
244
276
|
<TouchableOpacity
|
|
245
277
|
style={[styles.deviceErrorBanner, { top: 64 + insets.top }]}
|
|
@@ -354,7 +386,7 @@ const styles = StyleSheet.create({
|
|
|
354
386
|
top: 0,
|
|
355
387
|
left: 0,
|
|
356
388
|
right: 0,
|
|
357
|
-
paddingHorizontal:
|
|
389
|
+
paddingHorizontal: 108,
|
|
358
390
|
paddingBottom: 14,
|
|
359
391
|
alignItems: 'center',
|
|
360
392
|
backgroundColor: 'rgba(0,0,0,0.35)',
|
|
@@ -397,10 +429,6 @@ const styles = StyleSheet.create({
|
|
|
397
429
|
fontSize: 12,
|
|
398
430
|
},
|
|
399
431
|
pip: {
|
|
400
|
-
position: 'absolute',
|
|
401
|
-
right: 16,
|
|
402
|
-
width: 104,
|
|
403
|
-
height: 148,
|
|
404
432
|
borderRadius: 12,
|
|
405
433
|
overflow: 'hidden',
|
|
406
434
|
backgroundColor: '#000',
|
|
@@ -422,6 +450,10 @@ const styles = StyleSheet.create({
|
|
|
422
450
|
backgroundColor: 'rgba(0,0,0,0.45)',
|
|
423
451
|
zIndex: 6,
|
|
424
452
|
},
|
|
453
|
+
// Next to minimize, top-left: the top-right corner belongs to the tile.
|
|
454
|
+
fitButton: {
|
|
455
|
+
left: 60,
|
|
456
|
+
},
|
|
425
457
|
controls: {
|
|
426
458
|
flexDirection: 'row',
|
|
427
459
|
alignItems: 'center',
|
|
@@ -33,6 +33,11 @@ export interface CallSessionSnapshot {
|
|
|
33
33
|
speakerOn: boolean;
|
|
34
34
|
/** Which camera the local video comes from; only the front one is mirrored. */
|
|
35
35
|
facingMode: 'user' | 'environment';
|
|
36
|
+
/**
|
|
37
|
+
* Bumped whenever the local camera track is re-acquired, so the self view
|
|
38
|
+
* can remount onto the new stream instead of holding the stopped one.
|
|
39
|
+
*/
|
|
40
|
+
localVideoEpoch: number;
|
|
36
41
|
/** `{ participant, publication, source }` for `<VideoTrack />`, live and unmuted only. */
|
|
37
42
|
remoteVideo: any;
|
|
38
43
|
localVideo: any;
|
|
@@ -56,6 +61,7 @@ const IDLE: CallSessionSnapshot = {
|
|
|
56
61
|
cameraOn: false,
|
|
57
62
|
speakerOn: false,
|
|
58
63
|
facingMode: 'user',
|
|
64
|
+
localVideoEpoch: 0,
|
|
59
65
|
remoteVideo: null,
|
|
60
66
|
localVideo: null,
|
|
61
67
|
remoteName: null,
|
|
@@ -299,7 +305,14 @@ export const startCallSession = ({
|
|
|
299
305
|
// Claims audio focus and sets the right native audio mode. Must
|
|
300
306
|
// start BEFORE connecting or the first seconds route to the earpiece
|
|
301
307
|
// on Android even for a video call.
|
|
302
|
-
|
|
308
|
+
try {
|
|
309
|
+
await AudioSession.startAudioSession();
|
|
310
|
+
} catch {
|
|
311
|
+
// A call answered from the CallKit banner: CallKit owns the iOS
|
|
312
|
+
// audio session and activates it itself (useCallKeep forwards that
|
|
313
|
+
// to WebRTC), so our own activation is refused. Not a reason to
|
|
314
|
+
// fail the call.
|
|
315
|
+
}
|
|
303
316
|
await room.connect(livekitUrl, token);
|
|
304
317
|
} catch (error: any) {
|
|
305
318
|
if (current.disposed) {return;}
|
|
@@ -350,10 +363,12 @@ export const startCallSession = ({
|
|
|
350
363
|
|
|
351
364
|
// ---- controls -----------------------------------------------------------
|
|
352
365
|
|
|
353
|
-
export const toggleCallMic =
|
|
366
|
+
export const toggleCallMic = (): Promise<void> => setCallMicEnabled(!snapshot.micOn);
|
|
367
|
+
|
|
368
|
+
/** Set the mic to a given state (system call UI reports absolute values). */
|
|
369
|
+
export const setCallMicEnabled = async (next: boolean): Promise<void> => {
|
|
354
370
|
const current = session;
|
|
355
|
-
if (!current) {return;}
|
|
356
|
-
const next = !snapshot.micOn;
|
|
371
|
+
if (!current || snapshot.micOn === next) {return;}
|
|
357
372
|
emit({ micOn: next });
|
|
358
373
|
try {
|
|
359
374
|
await current.room.localParticipant.setMicrophoneEnabled(next);
|
|
@@ -379,29 +394,45 @@ export const toggleCallCamera = async (): Promise<void> => {
|
|
|
379
394
|
}
|
|
380
395
|
};
|
|
381
396
|
|
|
397
|
+
let switchingCamera = false;
|
|
398
|
+
|
|
382
399
|
export const switchCallCamera = async (): Promise<void> => {
|
|
383
400
|
const current = session;
|
|
384
401
|
const runtime = loadLiveKit();
|
|
385
|
-
if (!current || !runtime) {return;}
|
|
386
|
-
const
|
|
402
|
+
if (!current || !runtime || switchingCamera) {return;}
|
|
403
|
+
const track = current.room.localParticipant.getTrackPublication?.(
|
|
387
404
|
runtime.Track.Source.Camera
|
|
388
|
-
)?.track
|
|
389
|
-
if (!
|
|
405
|
+
)?.track;
|
|
406
|
+
if (!track?.restartTrack) {return;}
|
|
390
407
|
const next = snapshot.facingMode === 'user' ? 'environment' : 'user';
|
|
408
|
+
switchingCamera = true;
|
|
391
409
|
try {
|
|
392
|
-
//
|
|
393
|
-
//
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
410
|
+
// A real device change needs a new capture: react-native-webrtc's
|
|
411
|
+
// native applyConstraints only applies width/height/frameRate and
|
|
412
|
+
// ignores facingMode on both platforms, so the old approach kept the
|
|
413
|
+
// front camera and merely flipped our mirror flag (the picture looked
|
|
414
|
+
// swapped left to right). restartTrack re-acquires the camera with
|
|
415
|
+
// the new facing mode and swaps it into the published sender; the
|
|
416
|
+
// <VideoTrack /> view follows it through TrackEvent.Restarted.
|
|
417
|
+
await track.restartTrack({
|
|
418
|
+
facingMode: next,
|
|
419
|
+
...(runtime.VideoPresets
|
|
420
|
+
? { resolution: runtime.VideoPresets.h720.resolution }
|
|
421
|
+
: {}),
|
|
422
|
+
});
|
|
423
|
+
if (current.disposed) {return;}
|
|
424
|
+
// Trust what the camera reports: a device with a single camera stays
|
|
425
|
+
// on it, and the mirror must follow the real camera, not the request.
|
|
426
|
+
const actual = track.mediaStreamTrack?.getSettings?.()?.facingMode;
|
|
427
|
+
emit({
|
|
428
|
+
facingMode: actual === 'user' || actual === 'environment' ? actual : next,
|
|
429
|
+
localVideoEpoch: snapshot.localVideoEpoch + 1,
|
|
430
|
+
});
|
|
402
431
|
resync();
|
|
403
|
-
} catch {
|
|
404
|
-
|
|
432
|
+
} catch (error) {
|
|
433
|
+
if (!current.disposed) {emit({ deviceError: humanizeDeviceError(error) });}
|
|
434
|
+
} finally {
|
|
435
|
+
switchingCamera = false;
|
|
405
436
|
}
|
|
406
437
|
};
|
|
407
438
|
|