@ethora/chat-component-rn 26.5.7 → 26.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +191 -0
- package/README.md +95 -10
- package/index.js +24 -0
- package/lib/commonjs/assets/icons.js +5 -1
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js +11 -5
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +31 -16
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +78 -38
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +74 -27
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +16 -11
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageContainer.js +2 -2
- package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +165 -28
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js +17 -8
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/SystemMessage.js +34 -22
- package/lib/commonjs/components/MainComponents/SystemMessage.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/InteractionsOverlay.js +119 -0
- package/lib/commonjs/components/MessageBubble/InteractionsOverlay.js.map +1 -0
- package/lib/commonjs/components/MessageBubble/Message.js +122 -41
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +132 -44
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +155 -52
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -5
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/DocumentViewer.js +104 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/DocumentViewer.js.map +1 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +144 -24
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +29 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
- package/lib/commonjs/components/Modals/Modal/Modal.js +5 -1
- package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalHeaderComponent.js +10 -0
- package/lib/commonjs/components/Modals/ModalHeaderComponent.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +77 -47
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +3 -3
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/styledModalComponents.js +17 -13
- package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +47 -28
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +49 -9
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/NewMessageLabel.js +8 -6
- package/lib/commonjs/components/styled/NewMessageLabel.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +49 -27
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/StyledComponents.js +6 -3
- package/lib/commonjs/components/styled/StyledComponents.js.map +1 -1
- package/lib/commonjs/components/styled/StyledInputComponents/MediaComponents.js +14 -4
- package/lib/commonjs/components/styled/StyledInputComponents/MediaComponents.js.map +1 -1
- package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +7 -2
- package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
- package/lib/commonjs/components/styled/UnsupportedType.js +5 -1
- package/lib/commonjs/components/styled/UnsupportedType.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +81 -16
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/MessageNotificationContext.js +7 -7
- package/lib/commonjs/context/MessageNotificationContext.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +244 -32
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/chatAutoEnterer.js +2 -7
- package/lib/commonjs/helpers/chatAutoEnterer.js.map +1 -1
- package/lib/commonjs/helpers/historyPreloadScheduler.js +4 -1
- package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js +15 -5
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/commonjs/helpers/keyboardLayout.js +18 -0
- package/lib/commonjs/helpers/keyboardLayout.js.map +1 -0
- package/lib/commonjs/helpers/mediaDimensions.js +51 -0
- package/lib/commonjs/helpers/mediaDimensions.js.map +1 -0
- package/lib/commonjs/helpers/mimeToExtension.js +56 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -1
- package/lib/commonjs/helpers/normalizeRoomJid.js +20 -0
- package/lib/commonjs/helpers/normalizeRoomJid.js.map +1 -0
- package/lib/commonjs/hooks/useChatRoomFocus.js +87 -0
- package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -0
- package/lib/commonjs/hooks/useHeapSender.js +1 -1
- package/lib/commonjs/hooks/useHeapSender.js.map +1 -1
- package/lib/commonjs/hooks/useLogout.js +36 -11
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/hooks/usePushNotifications.js +6 -2
- package/lib/commonjs/hooks/usePushNotifications.js.map +1 -1
- package/lib/commonjs/hooks/useRoomState.js +2 -0
- package/lib/commonjs/hooks/useRoomState.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +201 -10
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/hooks/useUnreadMessagesCounter.js +12 -14
- package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
- package/lib/commonjs/main.js +7 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +67 -0
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js +29 -4
- package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/commonjs/networking/apiClient.js +2 -1
- package/lib/commonjs/networking/apiClient.js.map +1 -1
- package/lib/commonjs/networking/outboundQueue.js +92 -0
- package/lib/commonjs/networking/outboundQueue.js.map +1 -0
- package/lib/commonjs/networking/xmpp/createTimeoutPromise.xmpp.js +4 -1
- package/lib/commonjs/networking/xmpp/createTimeoutPromise.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +7 -8
- package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
- package/lib/commonjs/networking/xmpp/getRoomsPaged.xmpp.js +26 -3
- package/lib/commonjs/networking/xmpp/getRoomsPaged.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +26 -8
- package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +2 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +294 -35
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js +22 -6
- package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +157 -23
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/commonjs/utils/installPromiseRejectionTracker.js +83 -0
- package/lib/commonjs/utils/installPromiseRejectionTracker.js.map +1 -0
- package/lib/commonjs/utils/resendMessage.js +1 -1
- package/lib/commonjs/utils/resendMessage.js.map +1 -1
- package/lib/module/assets/icons.js +5 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/ContextMenu/ContextMenuComponents.js +11 -5
- package/lib/module/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +31 -16
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +80 -40
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +74 -27
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +17 -12
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageContainer.js +2 -2
- package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +166 -29
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MainComponents/ReduxWrapper.js +18 -8
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/SystemMessage.js +33 -21
- package/lib/module/components/MainComponents/SystemMessage.js.map +1 -1
- package/lib/module/components/MessageBubble/InteractionsOverlay.js +112 -0
- package/lib/module/components/MessageBubble/InteractionsOverlay.js.map +1 -0
- package/lib/module/components/MessageBubble/Message.js +123 -42
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +134 -46
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js +155 -52
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +20 -5
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/DocumentViewer.js +99 -0
- package/lib/module/components/Modals/FilePreviewModal/DocumentViewer.js.map +1 -0
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +148 -26
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/PdfView.js +31 -3
- package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
- package/lib/module/components/Modals/Modal/Modal.js +5 -1
- package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/module/components/Modals/ModalHeaderComponent.js +10 -0
- package/lib/module/components/Modals/ModalHeaderComponent.js.map +1 -1
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +79 -49
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +3 -3
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/Modals/styledModalComponents.js +17 -13
- package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +47 -28
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +51 -11
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/NewMessageLabel.js +8 -6
- package/lib/module/components/styled/NewMessageLabel.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +50 -28
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/StyledComponents.js +6 -3
- package/lib/module/components/styled/StyledComponents.js.map +1 -1
- package/lib/module/components/styled/StyledInputComponents/MediaComponents.js +14 -4
- package/lib/module/components/styled/StyledInputComponents/MediaComponents.js.map +1 -1
- package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +7 -2
- package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
- package/lib/module/components/styled/UnsupportedType.js +5 -1
- package/lib/module/components/styled/UnsupportedType.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +82 -17
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/MessageNotificationContext.js +7 -7
- package/lib/module/context/MessageNotificationContext.js.map +1 -1
- package/lib/module/context/xmppProvider.js +246 -34
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/chatAutoEnterer.js +2 -7
- package/lib/module/helpers/chatAutoEnterer.js.map +1 -1
- package/lib/module/helpers/historyPreloadScheduler.js +4 -1
- package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/module/helpers/insertMessageWithDelimiter.js +15 -5
- package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/module/helpers/keyboardLayout.js +12 -0
- package/lib/module/helpers/keyboardLayout.js.map +1 -0
- package/lib/module/helpers/mediaDimensions.js +46 -0
- package/lib/module/helpers/mediaDimensions.js.map +1 -0
- package/lib/module/helpers/mimeToExtension.js +55 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -1
- package/lib/module/helpers/normalizeRoomJid.js +15 -0
- package/lib/module/helpers/normalizeRoomJid.js.map +1 -0
- package/lib/module/hooks/useChatRoomFocus.js +82 -0
- package/lib/module/hooks/useChatRoomFocus.js.map +1 -0
- package/lib/module/hooks/useHeapSender.js +1 -1
- package/lib/module/hooks/useHeapSender.js.map +1 -1
- package/lib/module/hooks/useLogout.js +36 -11
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/hooks/usePushNotifications.js +6 -2
- package/lib/module/hooks/usePushNotifications.js.map +1 -1
- package/lib/module/hooks/useRoomState.js +2 -0
- package/lib/module/hooks/useRoomState.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +203 -12
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/hooks/useUnreadMessagesCounter.js +12 -14
- package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
- package/lib/module/main.js +1 -0
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +67 -1
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/api-requests/rooms.api.js +29 -4
- package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/module/networking/apiClient.js +2 -1
- package/lib/module/networking/apiClient.js.map +1 -1
- package/lib/module/networking/outboundQueue.js +84 -0
- package/lib/module/networking/outboundQueue.js.map +1 -0
- package/lib/module/networking/xmpp/createTimeoutPromise.xmpp.js +4 -1
- package/lib/module/networking/xmpp/createTimeoutPromise.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +7 -8
- package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
- package/lib/module/networking/xmpp/getRoomsPaged.xmpp.js +26 -3
- package/lib/module/networking/xmpp/getRoomsPaged.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +26 -8
- package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +2 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmppClient.js +294 -35
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/Middleware/unreadMidlleware.js +22 -6
- package/lib/module/roomStore/Middleware/unreadMidlleware.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +154 -22
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/utils/installPromiseRejectionTracker.js +78 -0
- package/lib/module/utils/installPromiseRejectionTracker.js.map +1 -0
- package/lib/module/utils/resendMessage.js +1 -1
- package/lib/module/utils/resendMessage.js.map +1 -1
- package/lib/typescript/assets/icons.d.ts +8 -4
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts +1 -0
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts +1 -0
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/SystemMessage.d.ts +0 -7
- package/lib/typescript/components/MainComponents/SystemMessage.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/InteractionsOverlay.d.ts +13 -0
- package/lib/typescript/components/MessageBubble/InteractionsOverlay.d.ts.map +1 -0
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts +4 -2
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/DocumentViewer.d.ts +29 -0
- package/lib/typescript/components/Modals/FilePreviewModal/DocumentViewer.d.ts.map +1 -0
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts +0 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
- package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ModalHeaderComponent.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/NewMessageLabel.d.ts +1 -5
- package/lib/typescript/components/styled/NewMessageLabel.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledInputComponents/MediaComponents.d.ts +9 -1
- package/lib/typescript/components/styled/StyledInputComponents/MediaComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/UnsupportedType.d.ts +1 -0
- package/lib/typescript/components/styled/UnsupportedType.d.ts.map +1 -1
- package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts +1 -0
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/chatAutoEnterer.d.ts.map +1 -1
- package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
- package/lib/typescript/helpers/keyboardLayout.d.ts +9 -0
- package/lib/typescript/helpers/keyboardLayout.d.ts.map +1 -0
- package/lib/typescript/helpers/mediaDimensions.d.ts +9 -0
- package/lib/typescript/helpers/mediaDimensions.d.ts.map +1 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts +8 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -1
- package/lib/typescript/helpers/normalizeRoomJid.d.ts +2 -0
- package/lib/typescript/helpers/normalizeRoomJid.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatRoomFocus.d.ts +42 -0
- package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -0
- package/lib/typescript/hooks/useHeapSender.d.ts.map +1 -1
- package/lib/typescript/hooks/useLogout.d.ts +23 -1
- package/lib/typescript/hooks/useLogout.d.ts.map +1 -1
- package/lib/typescript/hooks/usePushNotifications.d.ts.map +1 -1
- package/lib/typescript/hooks/useRoomState.d.ts +1 -0
- package/lib/typescript/hooks/useRoomState.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +1 -0
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts +3 -0
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
- package/lib/typescript/networking/apiClient.d.ts.map +1 -1
- package/lib/typescript/networking/outboundQueue.d.ts +57 -0
- package/lib/typescript/networking/outboundQueue.d.ts.map +1 -0
- package/lib/typescript/networking/xmpp/createTimeoutPromise.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +1 -1
- package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/getRoomsPaged.xmpp.d.ts +1 -1
- package/lib/typescript/networking/xmpp/getRoomsPaged.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +33 -4
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/Middleware/unreadMidlleware.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +8 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/media.model.d.ts +1 -0
- package/lib/typescript/types/models/media.model.d.ts.map +1 -1
- package/lib/typescript/types/models/xmpp.model.d.ts +1 -1
- package/lib/typescript/types/models/xmpp.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +20 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/utils/installPromiseRejectionTracker.d.ts +20 -0
- package/lib/typescript/utils/installPromiseRejectionTracker.d.ts.map +1 -0
- package/lib/typescript/utils/resendMessage.d.ts.map +1 -1
- package/package.json +23 -4
- package/src/assets/icons.tsx +23 -14
- package/src/components/ContextMenu/ContextMenuComponents.tsx +10 -5
- package/src/components/MainComponents/ChatHeader.tsx +46 -15
- package/src/components/MainComponents/ChatRoom.tsx +95 -66
- package/src/components/MainComponents/ChatWrapper.tsx +127 -42
- package/src/components/MainComponents/MediaMessage.tsx +14 -8
- package/src/components/MainComponents/MessageContainer.tsx +4 -2
- package/src/components/MainComponents/MessageList.tsx +175 -28
- package/src/components/MainComponents/ReduxWrapper.tsx +19 -9
- package/src/components/MainComponents/SystemMessage.tsx +38 -26
- package/src/components/MessageBubble/InteractionsOverlay.tsx +121 -0
- package/src/components/MessageBubble/Message.tsx +133 -63
- package/src/components/MessageBubble/MessageInteractions.tsx +146 -58
- package/src/components/Modals/AttachSheet/AttachSheet.tsx +146 -39
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +25 -3
- package/src/components/Modals/FilePreviewModal/DocumentViewer.tsx +93 -0
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +161 -26
- package/src/components/Modals/FilePreviewModal/PdfView.tsx +32 -4
- package/src/components/Modals/Modal/Modal.tsx +4 -1
- package/src/components/Modals/ModalHeaderComponent.tsx +8 -1
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +70 -58
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -15
- package/src/components/Modals/styledModalComponents.tsx +17 -13
- package/src/components/styled/MediaFilePreview.tsx +46 -26
- package/src/components/styled/MessageImage.tsx +58 -13
- package/src/components/styled/NewMessageLabel.tsx +8 -5
- package/src/components/styled/SendInput.tsx +64 -29
- package/src/components/styled/StyledComponents.ts +6 -3
- package/src/components/styled/StyledInputComponents/MediaComponents.tsx +15 -5
- package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +7 -2
- package/src/components/styled/UnsupportedType.tsx +7 -1
- package/src/components/styled/VideoMessage.tsx +76 -12
- package/src/context/MessageNotificationContext.tsx +8 -8
- package/src/context/xmppProvider.tsx +247 -30
- package/src/helpers/chatAutoEnterer.ts +2 -8
- package/src/helpers/historyPreloadScheduler.ts +4 -1
- package/src/helpers/insertMessageWithDelimiter.ts +22 -15
- package/src/helpers/keyboardLayout.ts +18 -0
- package/src/helpers/mediaDimensions.ts +47 -0
- package/src/helpers/mimeToExtension.ts +64 -0
- package/src/helpers/normalizeRoomJid.ts +6 -0
- package/src/hooks/useChatRoomFocus.ts +95 -0
- package/src/hooks/useHeapSender.tsx +2 -1
- package/src/hooks/useLogout.tsx +36 -13
- package/src/hooks/usePushNotifications.ts +21 -8
- package/src/hooks/useRoomState.tsx +4 -0
- package/src/hooks/useSendMessage.tsx +258 -13
- package/src/hooks/useUnreadMessagesCounter.ts +13 -16
- package/src/main.ts +1 -0
- package/src/networking/api-requests/auth.api.ts +55 -1
- package/src/networking/api-requests/rooms.api.ts +31 -7
- package/src/networking/apiClient.ts +2 -1
- package/src/networking/outboundQueue.ts +98 -0
- package/src/networking/xmpp/createTimeoutPromise.xmpp.ts +5 -1
- package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +11 -13
- package/src/networking/xmpp/getRoomsPaged.xmpp.ts +27 -3
- package/src/networking/xmpp/presenceInRoom.xmpp.ts +24 -9
- package/src/networking/xmpp/sendTextMessage.xmpp.ts +2 -1
- package/src/networking/xmppClient.ts +317 -43
- package/src/roomStore/Middleware/unreadMidlleware.tsx +23 -5
- package/src/roomStore/roomsSlice.ts +177 -27
- package/src/types/models/media.model.ts +3 -0
- package/src/types/models/xmpp.model.ts +2 -1
- package/src/types/types.ts +31 -0
- package/src/utils/installPromiseRejectionTracker.ts +91 -0
- package/src/utils/resendMessage.ts +2 -1
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { BackIcon, MoreIcon, QrIcon } from '../../assets/icons';
|
|
8
8
|
import Button from '../styled/Button';
|
|
9
9
|
import { Text } from 'react-native';
|
|
10
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
10
11
|
|
|
11
12
|
interface ModalHeaderComponentProps {
|
|
12
13
|
handleCloseModal?: any;
|
|
@@ -21,8 +22,14 @@ const ModalHeaderComponent: React.FC<ModalHeaderComponentProps> = ({
|
|
|
21
22
|
rightMenu,
|
|
22
23
|
leftMenu,
|
|
23
24
|
}) => {
|
|
25
|
+
// The library's full-screen modals are an absolute-fill overlay inside
|
|
26
|
+
// ModalBackground (NOT a native Modal), so the OS doesn't apply any
|
|
27
|
+
// status-bar inset automatically — we have to. SafeAreaProvider is
|
|
28
|
+
// mounted by ReduxWrapper, so this reads the live per-device inset
|
|
29
|
+
// (notch / Dynamic Island / nothing).
|
|
30
|
+
const insets = useSafeAreaInsets();
|
|
24
31
|
return (
|
|
25
|
-
<HeaderContainer>
|
|
32
|
+
<HeaderContainer style={{ paddingTop: insets.top + 8 }}>
|
|
26
33
|
<HeaderLeft>
|
|
27
34
|
{leftMenu ? (
|
|
28
35
|
leftMenu
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '../styledModalComponents';
|
|
10
10
|
import { TextareaInput } from '../../styled/StyledInputComponents/StyledInputComponents';
|
|
11
11
|
import Button from '../../styled/Button';
|
|
12
|
-
import { Modal, Text, TextInput } from 'react-native';
|
|
12
|
+
import { Modal, Text, TextInput, View, StyleSheet } from 'react-native';
|
|
13
13
|
|
|
14
14
|
interface ModalWrapperProps {
|
|
15
15
|
iconTitle?: any;
|
|
@@ -53,6 +53,47 @@ export const ModalWrapper: FC<ModalWrapperProps> = ({
|
|
|
53
53
|
// }
|
|
54
54
|
// };
|
|
55
55
|
|
|
56
|
+
const inner = (
|
|
57
|
+
<>
|
|
58
|
+
<CloseButton onPress={handleCloseModal}>
|
|
59
|
+
<Text style={{ fontSize: 24 }}>×</Text>
|
|
60
|
+
</CloseButton>
|
|
61
|
+
{IconTitle ? <IconTitle /> : <ModalTitle>{title}</ModalTitle>}
|
|
62
|
+
{description && <ModalDescription>{description}</ModalDescription>}
|
|
63
|
+
{isTextarea && (
|
|
64
|
+
<GroupContainer
|
|
65
|
+
style={{ flexDirection: 'column', position: 'relative' }}
|
|
66
|
+
/>
|
|
67
|
+
)}
|
|
68
|
+
{!buttonText && <GroupContainer />}
|
|
69
|
+
<GroupContainer>
|
|
70
|
+
<Button
|
|
71
|
+
onPress={handleCloseModal}
|
|
72
|
+
text={'Cancel'}
|
|
73
|
+
style={{ width: '100%' }}
|
|
74
|
+
unstyled
|
|
75
|
+
variant="outlined"
|
|
76
|
+
/>
|
|
77
|
+
{buttonText && (
|
|
78
|
+
<Button
|
|
79
|
+
onPress={handleClick}
|
|
80
|
+
text={buttonText}
|
|
81
|
+
// White label on the filled (e.g. red Delete) button. Button
|
|
82
|
+
// applies an inline `color: color || 'black'` that overrides
|
|
83
|
+
// the filled-variant white, so pass it explicitly.
|
|
84
|
+
color="#FFFFFF"
|
|
85
|
+
style={{
|
|
86
|
+
width: '100%',
|
|
87
|
+
backgroundColor: backgroundColorButton,
|
|
88
|
+
}}
|
|
89
|
+
unstyled
|
|
90
|
+
variant="filled"
|
|
91
|
+
/>
|
|
92
|
+
)}
|
|
93
|
+
</GroupContainer>
|
|
94
|
+
</>
|
|
95
|
+
);
|
|
96
|
+
|
|
56
97
|
return (
|
|
57
98
|
<Modal
|
|
58
99
|
transparent
|
|
@@ -61,64 +102,35 @@ export const ModalWrapper: FC<ModalWrapperProps> = ({
|
|
|
61
102
|
onRequestClose={handleCloseModal}
|
|
62
103
|
>
|
|
63
104
|
<ModalBackground>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
: { maxWidth: 640 }
|
|
77
|
-
}
|
|
78
|
-
>
|
|
79
|
-
<CloseButton onPress={handleCloseModal}>
|
|
80
|
-
<Text style={{ fontSize: 24 }}>×</Text>
|
|
81
|
-
</CloseButton>
|
|
82
|
-
{IconTitle ? <IconTitle /> : <ModalTitle>{title}</ModalTitle>}
|
|
83
|
-
{description && <ModalDescription>{description}</ModalDescription>}
|
|
84
|
-
{isTextarea && (
|
|
85
|
-
<GroupContainer
|
|
86
|
-
style={{ flexDirection: 'column', position: 'relative' }}
|
|
87
|
-
>
|
|
88
|
-
{/* <TextareaInput
|
|
89
|
-
ref={textareaRef}
|
|
90
|
-
onInput={handleInput}
|
|
91
|
-
id="additionalDetails"
|
|
92
|
-
value={textarea}
|
|
93
|
-
onChangeText={(text) => setTextarea(text)}
|
|
94
|
-
placeholder="Additional Details"
|
|
95
|
-
/> */}
|
|
96
|
-
</GroupContainer>
|
|
97
|
-
)}
|
|
98
|
-
{!buttonText && <GroupContainer />}
|
|
99
|
-
<GroupContainer>
|
|
100
|
-
<Button
|
|
101
|
-
onPress={handleCloseModal}
|
|
102
|
-
text={'Cancel'}
|
|
103
|
-
style={{ width: '100%' }}
|
|
104
|
-
unstyled
|
|
105
|
-
variant="outlined"
|
|
106
|
-
/>
|
|
107
|
-
{buttonText && (
|
|
108
|
-
<Button
|
|
109
|
-
onPress={handleClick}
|
|
110
|
-
text={buttonText}
|
|
111
|
-
style={{
|
|
112
|
-
width: '100%',
|
|
113
|
-
backgroundColor: backgroundColorButton,
|
|
114
|
-
}}
|
|
115
|
-
unstyled
|
|
116
|
-
variant="filled"
|
|
117
|
-
/>
|
|
118
|
-
)}
|
|
119
|
-
</GroupContainer>
|
|
120
|
-
</ModalContainer>
|
|
105
|
+
{compact ? (
|
|
106
|
+
// Dedicated small centered dialog. The base ModalContainer is
|
|
107
|
+
// flex:1 / width:100% / height:100% (full-screen); style-merge
|
|
108
|
+
// overrides proved unreliable, so confirm-style modals render in
|
|
109
|
+
// their own bounded View instead — never full-screen (#14).
|
|
110
|
+
// (Upstream also shrank this modal; this keeps that intent while
|
|
111
|
+
// adding the white filled-button label via `inner` below.)
|
|
112
|
+
<View style={styles.compactDialog}>{inner}</View>
|
|
113
|
+
) : (
|
|
114
|
+
<ModalContainer style={{ maxWidth: 640 }}>{inner}</ModalContainer>
|
|
115
|
+
)}
|
|
121
116
|
</ModalBackground>
|
|
122
117
|
</Modal>
|
|
123
118
|
);
|
|
124
119
|
};
|
|
120
|
+
|
|
121
|
+
const styles = StyleSheet.create({
|
|
122
|
+
compactDialog: {
|
|
123
|
+
width: '85%',
|
|
124
|
+
maxWidth: 360,
|
|
125
|
+
alignSelf: 'center',
|
|
126
|
+
backgroundColor: '#fff',
|
|
127
|
+
borderRadius: 16,
|
|
128
|
+
padding: 24,
|
|
129
|
+
gap: 16,
|
|
130
|
+
shadowColor: '#000',
|
|
131
|
+
shadowOffset: { width: 0, height: 4 },
|
|
132
|
+
shadowOpacity: 0.2,
|
|
133
|
+
shadowRadius: 12,
|
|
134
|
+
elevation: 8,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
@@ -285,22 +285,26 @@ const UserProfileModal: React.FC<UserProfileModalProps> = ({
|
|
|
285
285
|
</LabelData>
|
|
286
286
|
</BorderedContainer>
|
|
287
287
|
|
|
288
|
-
{selectedUser && !config?.
|
|
288
|
+
{selectedUser && !config?.disableMemberProfileActions && (
|
|
289
289
|
<>
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
290
|
+
{!config?.hideMemberSendMessageAction && (
|
|
291
|
+
<ActionButton
|
|
292
|
+
StartIcon={<ChatIcon />}
|
|
293
|
+
onPress={handlePrivateMessage}
|
|
294
|
+
variant="filled"
|
|
295
|
+
>
|
|
296
|
+
<Text style={{ color: '#ffffff' }}>Message</Text>
|
|
297
|
+
</ActionButton>
|
|
298
|
+
)}
|
|
299
|
+
{!config?.hideMemberCopyIdAction && (
|
|
300
|
+
<ActionButton
|
|
301
|
+
onPress={() => {}}
|
|
302
|
+
// onPress={() => handleCopyClick(selectedUser.id)}
|
|
303
|
+
variant="filled"
|
|
304
|
+
>
|
|
305
|
+
<Text style={{ color: '#ffffff' }}>Copy User Id</Text>
|
|
306
|
+
</ActionButton>
|
|
307
|
+
)}
|
|
304
308
|
</>
|
|
305
309
|
)}
|
|
306
310
|
|
|
@@ -21,17 +21,12 @@ export const CloseButton = styled.TouchableOpacity`
|
|
|
21
21
|
font-size: 20px;
|
|
22
22
|
cursor: pointer;
|
|
23
23
|
color: #888;
|
|
24
|
-
|
|
25
|
-
&:hover {
|
|
26
|
-
color: #555;
|
|
27
|
-
background-color: #dddddd;
|
|
28
|
-
}
|
|
29
24
|
`;
|
|
30
25
|
|
|
31
26
|
export const ModalContainer = styled.View`
|
|
32
|
-
flex: 1;
|
|
33
|
-
width: 100%;
|
|
34
|
-
height: 100%;
|
|
27
|
+
// flex: 1;
|
|
28
|
+
// width: 100%;
|
|
29
|
+
// height: 100%;
|
|
35
30
|
background: white;
|
|
36
31
|
padding: 32px 64px;
|
|
37
32
|
box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.2);
|
|
@@ -57,7 +52,7 @@ export const ModalDescription = styled.Text`
|
|
|
57
52
|
|
|
58
53
|
export const GroupContainer = styled.View`
|
|
59
54
|
display: flex;
|
|
60
|
-
gap:
|
|
55
|
+
gap: 16px;
|
|
61
56
|
width: 100%;
|
|
62
57
|
padding: 0;
|
|
63
58
|
`;
|
|
@@ -77,10 +72,19 @@ export const HeaderContainer = styled.View`
|
|
|
77
72
|
position: relative;
|
|
78
73
|
top: 0;
|
|
79
74
|
width: 100%;
|
|
80
|
-
padding:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
75
|
+
/* The previous incarnation had padding-top:62px (hard-coded status-bar
|
|
76
|
+
* offset) clamped to min/max-height:24px — content overflowed the
|
|
77
|
+
* visible band and the back arrow hugged the bottom edge. The earlier
|
|
78
|
+
* fix dropped the clamp but kept a hard-coded 56px top inset, which on
|
|
79
|
+
* top of this modal's absolute-fill overlay (no system inset is auto-
|
|
80
|
+
* applied) made the header eat far more space than it should.
|
|
81
|
+
*
|
|
82
|
+
* Now: compact 8px vertical padding here; the dynamic top inset for
|
|
83
|
+
* the status bar / Dynamic Island is supplied by ModalHeaderComponent
|
|
84
|
+
* via useSafeAreaInsets() — accurate per-device (~59px on a 16 Pro,
|
|
85
|
+
* 20px on an SE). Together that's status-bar + 8px above the back
|
|
86
|
+
* button and 8px below — properly sized and properly centered. */
|
|
87
|
+
padding: 8px 16px;
|
|
84
88
|
background-color: #fff;
|
|
85
89
|
border-bottom-width: 1px;
|
|
86
90
|
border-bottom-color: #f0f0f0;
|
|
@@ -7,13 +7,56 @@ import { FileIcon } from '../../assets/icons';
|
|
|
7
7
|
import { RemoveButton, RemoveButtonText } from './StyledComponents';
|
|
8
8
|
import { FC, useState } from 'react';
|
|
9
9
|
import { MediaFile } from '../../types/types';
|
|
10
|
-
import {
|
|
10
|
+
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
11
11
|
|
|
12
12
|
interface MediaFilePreviewProps {
|
|
13
13
|
filePreviews: MediaFile[];
|
|
14
14
|
handleRemoveImage: (index: number) => void;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
const VideoThumb: FC<{ uri: string; onPress: () => void }> = ({
|
|
18
|
+
uri,
|
|
19
|
+
onPress,
|
|
20
|
+
}) => {
|
|
21
|
+
const player = useVideoPlayer(uri, (p) => {
|
|
22
|
+
p.muted = true;
|
|
23
|
+
});
|
|
24
|
+
return (
|
|
25
|
+
<TouchableOpacity
|
|
26
|
+
activeOpacity={0.8}
|
|
27
|
+
onPress={onPress}
|
|
28
|
+
style={styles.videoThumb}
|
|
29
|
+
>
|
|
30
|
+
<VideoView
|
|
31
|
+
player={player}
|
|
32
|
+
style={StyleSheet.absoluteFill}
|
|
33
|
+
contentFit="cover"
|
|
34
|
+
nativeControls={false}
|
|
35
|
+
surfaceType="textureView"
|
|
36
|
+
pointerEvents="none"
|
|
37
|
+
/>
|
|
38
|
+
<View style={styles.playOverlay}>
|
|
39
|
+
<Text style={styles.playIcon}>▶</Text>
|
|
40
|
+
</View>
|
|
41
|
+
</TouchableOpacity>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const FullscreenPreviewVideo: FC<{ uri: string }> = ({ uri }) => {
|
|
46
|
+
const player = useVideoPlayer(uri, (p) => {
|
|
47
|
+
p.play();
|
|
48
|
+
});
|
|
49
|
+
return (
|
|
50
|
+
<VideoView
|
|
51
|
+
player={player}
|
|
52
|
+
style={styles.fullVideo}
|
|
53
|
+
contentFit="contain"
|
|
54
|
+
nativeControls
|
|
55
|
+
surfaceType="textureView"
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
17
60
|
export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
18
61
|
filePreviews,
|
|
19
62
|
handleRemoveImage,
|
|
@@ -30,22 +73,7 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
|
30
73
|
{isImage ? (
|
|
31
74
|
<MediaImage source={{ uri: file.uri }} />
|
|
32
75
|
) : isVideo ? (
|
|
33
|
-
<
|
|
34
|
-
activeOpacity={0.8}
|
|
35
|
-
onPress={() => setPreviewUri(file.uri)}
|
|
36
|
-
style={styles.videoThumb}
|
|
37
|
-
>
|
|
38
|
-
<Video
|
|
39
|
-
source={{ uri: file.uri }}
|
|
40
|
-
style={StyleSheet.absoluteFill}
|
|
41
|
-
resizeMode={ResizeMode.COVER}
|
|
42
|
-
shouldPlay={false}
|
|
43
|
-
isMuted
|
|
44
|
-
/>
|
|
45
|
-
<View style={styles.playOverlay}>
|
|
46
|
-
<Text style={styles.playIcon}>▶</Text>
|
|
47
|
-
</View>
|
|
48
|
-
</TouchableOpacity>
|
|
76
|
+
<VideoThumb uri={file.uri} onPress={() => setPreviewUri(file.uri)} />
|
|
49
77
|
) : (
|
|
50
78
|
<View style={{ width: 70, height: 70, borderRadius: 8 }}>
|
|
51
79
|
<FileIcon width={70} height={70} />
|
|
@@ -66,15 +94,7 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
|
66
94
|
>
|
|
67
95
|
<Text style={styles.closeText}>✕</Text>
|
|
68
96
|
</TouchableOpacity>
|
|
69
|
-
{previewUri &&
|
|
70
|
-
<Video
|
|
71
|
-
source={{ uri: previewUri }}
|
|
72
|
-
style={styles.fullVideo}
|
|
73
|
-
resizeMode={ResizeMode.CONTAIN}
|
|
74
|
-
useNativeControls
|
|
75
|
-
shouldPlay
|
|
76
|
-
/>
|
|
77
|
-
)}
|
|
97
|
+
{previewUri && <FullscreenPreviewVideo uri={previewUri} />}
|
|
78
98
|
</SafeAreaView>
|
|
79
99
|
</Modal>
|
|
80
100
|
</MediaContainer>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { Container } from './StyledInputComponents/MediaComponents';
|
|
3
3
|
import { useDispatch } from 'react-redux';
|
|
4
4
|
import {
|
|
@@ -6,43 +6,88 @@ import {
|
|
|
6
6
|
setActiveModal,
|
|
7
7
|
} from '../../roomStore/chatSettingsSlice';
|
|
8
8
|
import { MODAL_TYPES } from '../../helpers/constants/MODAL_TYPES';
|
|
9
|
-
import { ActivityIndicator, Image, TouchableOpacity } from 'react-native';
|
|
9
|
+
import { ActivityIndicator, Image, TouchableOpacity, View } from 'react-native';
|
|
10
|
+
import {
|
|
11
|
+
defaultMediaDims,
|
|
12
|
+
fitMediaDimensions,
|
|
13
|
+
MediaDims,
|
|
14
|
+
} from '../../helpers/mediaDimensions';
|
|
15
|
+
|
|
10
16
|
interface CustomMessageImageProps {
|
|
11
17
|
fileURL: string;
|
|
12
18
|
fileName: string;
|
|
13
19
|
mimetype: string;
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
const FALLBACK_IMAGE =
|
|
23
|
+
'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg';
|
|
24
|
+
|
|
16
25
|
const CustomMessageImage: React.FC<CustomMessageImageProps> = ({
|
|
17
26
|
fileURL,
|
|
18
27
|
fileName,
|
|
19
28
|
mimetype,
|
|
20
29
|
}) => {
|
|
21
|
-
const [error, setError] = useState(false);
|
|
22
30
|
const [loading, setLoading] = useState(true);
|
|
31
|
+
// Start with a neutral box; swap to the real aspect ratio once the
|
|
32
|
+
// image's natural dimensions are known so it's shown scaled, not cropped.
|
|
33
|
+
const [dims, setDims] = useState<MediaDims>(defaultMediaDims());
|
|
23
34
|
|
|
24
35
|
const dispatch = useDispatch();
|
|
25
36
|
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!fileURL) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let active = true;
|
|
42
|
+
Image.getSize(
|
|
43
|
+
fileURL,
|
|
44
|
+
(w, h) => {
|
|
45
|
+
if (active) {
|
|
46
|
+
setDims(fitMediaDimensions(w, h));
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
() => {
|
|
50
|
+
/* keep the default box if the size probe fails */
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
return () => {
|
|
54
|
+
active = false;
|
|
55
|
+
};
|
|
56
|
+
}, [fileURL]);
|
|
57
|
+
|
|
26
58
|
const handleOpen = () => {
|
|
27
59
|
dispatch(setActiveFile({ fileName, fileURL, mimetype }));
|
|
28
60
|
dispatch(setActiveModal(MODAL_TYPES.FILE_PREVIEW));
|
|
29
61
|
};
|
|
30
62
|
|
|
31
63
|
return (
|
|
32
|
-
<Container>
|
|
33
|
-
<TouchableOpacity onPress={handleOpen}>
|
|
34
|
-
{loading &&
|
|
64
|
+
<Container style={{ width: dims.width }}>
|
|
65
|
+
<TouchableOpacity onPress={handleOpen} activeOpacity={0.9}>
|
|
66
|
+
{loading && (
|
|
67
|
+
<View
|
|
68
|
+
style={{
|
|
69
|
+
position: 'absolute',
|
|
70
|
+
width: dims.width,
|
|
71
|
+
height: dims.height,
|
|
72
|
+
alignItems: 'center',
|
|
73
|
+
justifyContent: 'center',
|
|
74
|
+
zIndex: 1,
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<ActivityIndicator size="small" color="#0052CD" />
|
|
78
|
+
</View>
|
|
79
|
+
)}
|
|
35
80
|
<Image
|
|
36
|
-
|
|
37
|
-
fileURL ||
|
|
38
|
-
'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg'
|
|
39
|
-
}
|
|
81
|
+
source={{ uri: fileURL || FALLBACK_IMAGE }}
|
|
40
82
|
style={{
|
|
41
|
-
width:
|
|
42
|
-
height:
|
|
83
|
+
width: dims.width,
|
|
84
|
+
height: dims.height,
|
|
85
|
+
borderRadius: 10,
|
|
86
|
+
backgroundColor: 'rgba(0, 0, 0, 0)',
|
|
43
87
|
}}
|
|
44
|
-
onError={() => setError(true)}
|
|
45
88
|
onLoadEnd={() => setLoading(false)}
|
|
89
|
+
// The box already matches the natural aspect ratio, so 'cover'
|
|
90
|
+
// fills it edge-to-edge with no actual cropping or letterboxing.
|
|
46
91
|
resizeMode="cover"
|
|
47
92
|
/>
|
|
48
93
|
</TouchableOpacity>
|
|
@@ -24,23 +24,26 @@ export const StyledLabel = styled.View`
|
|
|
24
24
|
margin: 10px 0px;
|
|
25
25
|
`;
|
|
26
26
|
|
|
27
|
-
export const StyledLabelText = styled.Text
|
|
28
|
-
color:
|
|
27
|
+
export const StyledLabelText = styled.Text`
|
|
28
|
+
color: #ffffff;
|
|
29
29
|
font-size: 12px;
|
|
30
30
|
line-height: 14px;
|
|
31
|
-
font-weight:
|
|
31
|
+
font-weight: 500;
|
|
32
32
|
`;
|
|
33
33
|
|
|
34
|
+
// `color` is kept for CustomNewMessageLabel API parity, but the built-in
|
|
35
|
+
// label always renders WHITE text — it sits on a dark (#3f3f3f) pill, where
|
|
36
|
+
// the previous primary/blue text was unreadable.
|
|
34
37
|
interface NewMessageLabelProps {
|
|
35
38
|
color?: string;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
const NewMessageLabel: React.FC<NewMessageLabelProps> = (
|
|
41
|
+
const NewMessageLabel: React.FC<NewMessageLabelProps> = () => {
|
|
39
42
|
return (
|
|
40
43
|
<Container>
|
|
41
44
|
<Line />
|
|
42
45
|
<StyledLabel>
|
|
43
|
-
<StyledLabelText
|
|
46
|
+
<StyledLabelText>New messages</StyledLabelText>
|
|
44
47
|
</StyledLabel>
|
|
45
48
|
<Line />
|
|
46
49
|
</Container>
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { IConfig, MediaFile } from '../../types/types';
|
|
10
10
|
import Button from './Button';
|
|
11
11
|
import { SendIcon, AttachIcon } from '../../assets/icons';
|
|
12
|
-
import { KeyboardAvoidingView,
|
|
12
|
+
import { KeyboardAvoidingView, View, TouchableOpacity, Alert, Linking } from 'react-native';
|
|
13
13
|
import AttachSheet from '../Modals/AttachSheet/AttachSheet';
|
|
14
14
|
import { MediaFilePreview } from './MediaFilePreview';
|
|
15
15
|
import * as ImagePicker from 'expo-image-picker';
|
|
@@ -19,6 +19,21 @@ import * as ImageManipulator from 'expo-image-manipulator';
|
|
|
19
19
|
// iOS photos default to HEIC; many web backends (incl. ours) 500 on
|
|
20
20
|
// HEIC uploads because they can't decode it. Convert to JPEG before
|
|
21
21
|
// upload — JPEG is universally supported. JPEGs pass through.
|
|
22
|
+
// Server rejects uploads over its body-size cap with HTTP 413 (Request
|
|
23
|
+
// Entity Too Large). Guard client-side so the user gets a clear message
|
|
24
|
+
// instead of a silent failed bubble. 50 MB matches the backend limit.
|
|
25
|
+
const MAX_MEDIA_BYTES = 50 * 1024 * 1024;
|
|
26
|
+
|
|
27
|
+
const formatBytes = (bytes: number): string => {
|
|
28
|
+
if (bytes >= 1024 * 1024) {
|
|
29
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
30
|
+
}
|
|
31
|
+
if (bytes >= 1024) {
|
|
32
|
+
return `${(bytes / 1024).toFixed(0)} KB`;
|
|
33
|
+
}
|
|
34
|
+
return `${bytes} B`;
|
|
35
|
+
};
|
|
36
|
+
|
|
22
37
|
const normalizeImageAsset = async (asset: ImagePicker.ImagePickerAsset) => {
|
|
23
38
|
const mime = (asset.mimeType || '').toLowerCase();
|
|
24
39
|
const looksLikeHeic =
|
|
@@ -72,7 +87,6 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
72
87
|
const [isRecording, setIsRecording] = useState(false);
|
|
73
88
|
const [isFocused, setIsFocused] = useState(false);
|
|
74
89
|
const [filePreviews, setFilePreviews] = useState<MediaFile[]>([]);
|
|
75
|
-
const [inputHeight, setInputHeight] = useState(40);
|
|
76
90
|
const [showMediaMenu, setShowMediaMenu] = useState(false);
|
|
77
91
|
|
|
78
92
|
// Refs shadow `message` and `filePreviews` so handleSendClick can:
|
|
@@ -90,6 +104,21 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
90
104
|
const sendingRef = useRef(false);
|
|
91
105
|
|
|
92
106
|
const handleFileSelect = (files: MediaFile[]) => {
|
|
107
|
+
// Enforce the upload size cap before anything reaches the network.
|
|
108
|
+
// The backend rejects oversized bodies with HTTP 413; catching it
|
|
109
|
+
// here gives a clear message instead of a silent failed bubble.
|
|
110
|
+
const oversize = files.find(
|
|
111
|
+
(f) => typeof f.size === 'number' && f.size > MAX_MEDIA_BYTES
|
|
112
|
+
);
|
|
113
|
+
if (oversize) {
|
|
114
|
+
Alert.alert(
|
|
115
|
+
'File too large',
|
|
116
|
+
`"${oversize.name}" is ${formatBytes(oversize.size!)}. The maximum allowed size is ${Math.round(
|
|
117
|
+
MAX_MEDIA_BYTES / (1024 * 1024)
|
|
118
|
+
)} MB.`
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
93
122
|
filePreviewsRef.current = files;
|
|
94
123
|
setFilePreviews([...files]);
|
|
95
124
|
};
|
|
@@ -127,13 +156,19 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
127
156
|
uri: asset.uri,
|
|
128
157
|
type: asset.mimeType || 'video/mp4',
|
|
129
158
|
name: asset.fileName || asset.uri.split('/').pop() || `camera_${Date.now()}.mp4`,
|
|
159
|
+
size: (asset as any).fileSize,
|
|
130
160
|
},
|
|
131
161
|
]);
|
|
132
162
|
return;
|
|
133
163
|
}
|
|
134
164
|
const normalized = await normalizeImageAsset(asset);
|
|
135
165
|
handleFileSelect([
|
|
136
|
-
{
|
|
166
|
+
{
|
|
167
|
+
uri: normalized.uri,
|
|
168
|
+
type: normalized.mime,
|
|
169
|
+
name: normalized.name,
|
|
170
|
+
size: (asset as any).fileSize,
|
|
171
|
+
},
|
|
137
172
|
]);
|
|
138
173
|
} catch (error) {
|
|
139
174
|
console.error('Camera error:', error);
|
|
@@ -165,13 +200,19 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
165
200
|
uri: asset.uri,
|
|
166
201
|
type: asset.mimeType || 'video/mp4',
|
|
167
202
|
name: asset.fileName || asset.uri.split('/').pop() || `gallery_${Date.now()}.mp4`,
|
|
203
|
+
size: (asset as any).fileSize,
|
|
168
204
|
},
|
|
169
205
|
]);
|
|
170
206
|
return;
|
|
171
207
|
}
|
|
172
208
|
const normalized = await normalizeImageAsset(asset);
|
|
173
209
|
handleFileSelect([
|
|
174
|
-
{
|
|
210
|
+
{
|
|
211
|
+
uri: normalized.uri,
|
|
212
|
+
type: normalized.mime,
|
|
213
|
+
name: normalized.name,
|
|
214
|
+
size: (asset as any).fileSize,
|
|
215
|
+
},
|
|
175
216
|
]);
|
|
176
217
|
} catch (error) {
|
|
177
218
|
console.error('Gallery error:', error);
|
|
@@ -192,6 +233,7 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
192
233
|
uri: asset.uri,
|
|
193
234
|
type: asset.mimeType || 'application/octet-stream',
|
|
194
235
|
name: asset.name || `file_${Date.now()}`,
|
|
236
|
+
size: asset.size ?? undefined,
|
|
195
237
|
},
|
|
196
238
|
]);
|
|
197
239
|
} catch (err) {
|
|
@@ -200,21 +242,7 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
200
242
|
};
|
|
201
243
|
|
|
202
244
|
const handleAttachPress = () => {
|
|
203
|
-
|
|
204
|
-
ActionSheetIOS.showActionSheetWithOptions(
|
|
205
|
-
{
|
|
206
|
-
options: ['Cancel', 'Camera', 'Photo Library', 'Document'],
|
|
207
|
-
cancelButtonIndex: 0,
|
|
208
|
-
},
|
|
209
|
-
(buttonIndex) => {
|
|
210
|
-
if (buttonIndex === 1) {handleCameraSelection();}
|
|
211
|
-
else if (buttonIndex === 2) {handleGallerySelection();}
|
|
212
|
-
else if (buttonIndex === 3) {handleFileSelection();}
|
|
213
|
-
}
|
|
214
|
-
);
|
|
215
|
-
} else {
|
|
216
|
-
setShowMediaMenu(true);
|
|
217
|
-
}
|
|
245
|
+
setShowMediaMenu(true);
|
|
218
246
|
};
|
|
219
247
|
|
|
220
248
|
const handleRemoveImage = (index: number) => {
|
|
@@ -336,17 +364,15 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
336
364
|
}}
|
|
337
365
|
editable={!isLoading || !isMessageProcessing}
|
|
338
366
|
multiline={true}
|
|
339
|
-
//
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
)
|
|
346
|
-
);
|
|
347
|
-
}}
|
|
367
|
+
// No fixed height: a multiline TextInput auto-grows to fit
|
|
368
|
+
// its content between min/max. Locking `height` made iOS
|
|
369
|
+
// top-align the text inside the taller box (it looked like
|
|
370
|
+
// the text had dropped). minHeight keeps the 40px tap
|
|
371
|
+
// target; the row's align-items:center vertically centres
|
|
372
|
+
// the content-sized input.
|
|
348
373
|
style={{
|
|
349
|
-
|
|
374
|
+
minHeight: 40,
|
|
375
|
+
maxHeight: 120,
|
|
350
376
|
flex: 1,
|
|
351
377
|
}}
|
|
352
378
|
/>
|
|
@@ -371,6 +397,15 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
371
397
|
borderRadius: 20,
|
|
372
398
|
alignItems: 'center',
|
|
373
399
|
justifyContent: 'center',
|
|
400
|
+
// The shared Button (CustomButton) bakes in `margin: 0 10px`,
|
|
401
|
+
// which pushed the send button 10px further from the input
|
|
402
|
+
// and from the right edge than the attach button (a raw
|
|
403
|
+
// TouchableOpacity with no margin). Zero it so both sides of
|
|
404
|
+
// the input use the row's uniform gap:8 + 16px container
|
|
405
|
+
// padding. Longhand left/right to override the styled
|
|
406
|
+
// longhand (marginHorizontal loses to marginLeft/Right in RN).
|
|
407
|
+
marginLeft: 0,
|
|
408
|
+
marginRight: 0,
|
|
374
409
|
backgroundColor:
|
|
375
410
|
message || filePreviews.length > 0
|
|
376
411
|
? config?.colors?.primary
|