@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
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
StyleSheet,
|
|
6
6
|
findNodeHandle,
|
|
7
7
|
UIManager,
|
|
8
|
-
Dimensions,
|
|
9
8
|
Text,
|
|
9
|
+
Keyboard,
|
|
10
10
|
} from 'react-native';
|
|
11
11
|
import { useDispatch, useSelector } from 'react-redux';
|
|
12
12
|
import { RootState } from '../../roomStore';
|
|
@@ -52,7 +52,9 @@ const CustomMessageBubble = styled.View<{
|
|
|
52
52
|
}>`
|
|
53
53
|
position: relative;
|
|
54
54
|
max-width: 85%;
|
|
55
|
-
min-width: 30
|
|
55
|
+
min-width: ${({ isMedia }) => (isMedia ? '0' : '30%')};
|
|
56
|
+
align-items: ${({ isMedia, isUser }) =>
|
|
57
|
+
isMedia ? (isUser ? 'flex-end' : 'flex-start') : 'stretch'};
|
|
56
58
|
padding: ${({isMedia}) => isMedia ? '0' : '10'}px;
|
|
57
59
|
padding-bottom: ${({isMedia}) => isMedia ? '6' : '10'}px;
|
|
58
60
|
margin-right: ${({isUser}) => isUser ? '0' : '10px'};
|
|
@@ -94,9 +96,12 @@ const CustomMessagePhotoContainer = styled.TouchableOpacity`
|
|
|
94
96
|
margin-right: 10px;
|
|
95
97
|
`;
|
|
96
98
|
|
|
97
|
-
const CustomUserName = styled.Text<{ color?: string }>`
|
|
99
|
+
const CustomUserName = styled.Text<{ color?: string; media: boolean }>`
|
|
98
100
|
font-size: 14px;
|
|
99
101
|
font-weight: 500;
|
|
102
|
+
padding-bottom: 8px;
|
|
103
|
+
padding-left: ${({media}) => media ? '16px': 0};
|
|
104
|
+
padding-top: ${({media}) => media ? '8px': 0};
|
|
100
105
|
color: ${({ color }) => color || '#333'};
|
|
101
106
|
`;
|
|
102
107
|
|
|
@@ -113,6 +118,15 @@ const CustomMessageTimestamp = styled.Text<{
|
|
|
113
118
|
align-self: flex-end;
|
|
114
119
|
`;
|
|
115
120
|
|
|
121
|
+
const CustomTimestampRow = styled.View<{media: boolean}>`
|
|
122
|
+
flex-direction: row;
|
|
123
|
+
align-items: center;
|
|
124
|
+
align-self: flex-end;
|
|
125
|
+
margin-top: 4;
|
|
126
|
+
gap: 4;
|
|
127
|
+
padding-right: ${({media}) => media ? '10px': 0};
|
|
128
|
+
`;
|
|
129
|
+
|
|
116
130
|
const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
117
131
|
const dispatch = useDispatch();
|
|
118
132
|
const { client } = useXmppClient();
|
|
@@ -127,12 +141,15 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
127
141
|
}
|
|
128
142
|
|
|
129
143
|
const [contextMenuPosition, setContextMenuPosition] = useState<{
|
|
130
|
-
|
|
131
|
-
|
|
144
|
+
left: number;
|
|
145
|
+
right: number;
|
|
146
|
+
top: number;
|
|
147
|
+
bottom: number;
|
|
132
148
|
} | null>(null);
|
|
133
149
|
|
|
134
150
|
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
135
151
|
const messageRef = useRef<View>(null);
|
|
152
|
+
const bubbleRef = useRef<View>(null);
|
|
136
153
|
|
|
137
154
|
const handleUserAvatarClick = (user: IUser): void => {
|
|
138
155
|
dispatch(setActiveModal(MODAL_TYPES.PROFILE));
|
|
@@ -219,45 +236,40 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
219
236
|
);
|
|
220
237
|
};
|
|
221
238
|
|
|
239
|
+
// Long-press → capture the bubble's on-screen bounding box. The actual
|
|
240
|
+
// menu placement (above / below, clamped to the viewport) is done in
|
|
241
|
+
// MessageInteractions, which measures the rendered menu height via
|
|
242
|
+
// onLayout — more accurate than estimating it here, and it's what keeps
|
|
243
|
+
// the menu adjacent to the message instead of floating far above (#13).
|
|
222
244
|
const handleLongPress = () => {
|
|
223
|
-
|
|
224
|
-
|
|
245
|
+
const target = (bubbleRef.current ?? messageRef.current) as any;
|
|
246
|
+
if (target?.measureInWindow) {
|
|
247
|
+
// Use measureInWindow — the SAME API the overlay host uses to find
|
|
248
|
+
// its own window origin. Both are then in identical window
|
|
249
|
+
// coordinates, so MessageInteractions' host-local conversion
|
|
250
|
+
// (subtract origin) is exact. Mixing this with UIManager.measure
|
|
251
|
+
// (pageX/pageY) drifted on Android (status-bar offset) and pushed the
|
|
252
|
+
// "below" menu too far from the message.
|
|
253
|
+
target.measureInWindow(
|
|
254
|
+
(x: number, y: number, width: number, height: number) => {
|
|
255
|
+
setContextMenuPosition({
|
|
256
|
+
left: x,
|
|
257
|
+
right: x + width,
|
|
258
|
+
top: y,
|
|
259
|
+
bottom: y + height,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
} else if (target) {
|
|
264
|
+
const nodeHandle = findNodeHandle(target);
|
|
225
265
|
if (nodeHandle) {
|
|
226
|
-
UIManager.measure(nodeHandle, (_x, _y,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const MENU_HEIGHT = 280;
|
|
234
|
-
// Treat the consumer-supplied keyboardVerticalOffset as a
|
|
235
|
-
// proxy for tab bar + bottom safe-area when present; falls
|
|
236
|
-
// back to a reasonable default so the menu doesn't bump into
|
|
237
|
-
// the nav bar on phones without one in config.
|
|
238
|
-
const bottomReserve =
|
|
239
|
-
(config?.keyboardVerticalOffset ?? 0) + 24;
|
|
240
|
-
const topReserve = 16;
|
|
241
|
-
|
|
242
|
-
const spaceBelow = screenHeight - (pageY + height) - bottomReserve;
|
|
243
|
-
const spaceAbove = pageY - topReserve;
|
|
244
|
-
|
|
245
|
-
let menuY: number;
|
|
246
|
-
if (spaceBelow >= MENU_HEIGHT) {
|
|
247
|
-
menuY = pageY + height;
|
|
248
|
-
} else if (spaceAbove >= MENU_HEIGHT) {
|
|
249
|
-
menuY = pageY - MENU_HEIGHT;
|
|
250
|
-
} else {
|
|
251
|
-
// Neither side has room (e.g. very small phone, large
|
|
252
|
-
// menu) — clamp to the visible region so at least the
|
|
253
|
-
// top of the menu is reachable.
|
|
254
|
-
menuY = Math.max(
|
|
255
|
-
topReserve,
|
|
256
|
-
screenHeight - MENU_HEIGHT - bottomReserve
|
|
257
|
-
);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
setContextMenuPosition({ x: pageX, y: menuY });
|
|
266
|
+
UIManager.measure(nodeHandle, (_x, _y, width, height, pageX, pageY) => {
|
|
267
|
+
setContextMenuPosition({
|
|
268
|
+
left: pageX,
|
|
269
|
+
right: pageX + width,
|
|
270
|
+
top: pageY,
|
|
271
|
+
bottom: pageY + height,
|
|
272
|
+
});
|
|
261
273
|
});
|
|
262
274
|
}
|
|
263
275
|
}
|
|
@@ -297,7 +309,19 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
297
309
|
>
|
|
298
310
|
{!isUser && (
|
|
299
311
|
<CustomMessagePhotoContainer
|
|
300
|
-
|
|
312
|
+
// `disableProfilesInteractions` gates every entry point to the
|
|
313
|
+
// user-profile popup: this in-bubble avatar AND the chat-title
|
|
314
|
+
// press in ChatHeader. When disabled we still render the avatar
|
|
315
|
+
// visually but make it non-interactive (no press, no a11y
|
|
316
|
+
// affordance) — consumers who want it gone entirely can return
|
|
317
|
+
// null from a custom message component.
|
|
318
|
+
onPress={
|
|
319
|
+
config?.disableProfilesInteractions
|
|
320
|
+
? undefined
|
|
321
|
+
: () => handleUserAvatarClick(message.user)
|
|
322
|
+
}
|
|
323
|
+
disabled={!!config?.disableProfilesInteractions}
|
|
324
|
+
accessible={!config?.disableProfilesInteractions}
|
|
301
325
|
>
|
|
302
326
|
{message.user?.profileImage ? (
|
|
303
327
|
<CustomMessagePhoto source={{ uri: message.user.profileImage }} />
|
|
@@ -307,6 +331,26 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
307
331
|
</CustomMessagePhotoContainer>
|
|
308
332
|
)}
|
|
309
333
|
<Pressable
|
|
334
|
+
// The Pressable fills the row's content area, so the bubble
|
|
335
|
+
// inside must be aligned to the sender's side — otherwise it
|
|
336
|
+
// hugs the left and own media bubbles sit with a right-side
|
|
337
|
+
// gap (text bubbles only looked right because they're narrow).
|
|
338
|
+
// flex-end for own, flex-start for others.
|
|
339
|
+
style={{
|
|
340
|
+
flex: 1,
|
|
341
|
+
alignItems: isUser ? 'flex-end' : 'flex-start',
|
|
342
|
+
}}
|
|
343
|
+
// A plain tap anywhere on a message bubble dismisses the
|
|
344
|
+
// keyboard. The FlatList's keyboardShouldPersistTaps="handled"
|
|
345
|
+
// already dismisses taps on the empty GAPS between bubbles, but
|
|
346
|
+
// the bubble Pressable itself is a touch responder, so taps that
|
|
347
|
+
// landed on a message were "handled" and the keyboard stayed —
|
|
348
|
+
// which is exactly the "closes only every other time" symptom
|
|
349
|
+
// (hit a gap → close, hit a bubble → stay). Explicitly dismissing
|
|
350
|
+
// here makes it reliable across the whole list. onPress does NOT
|
|
351
|
+
// fire when onLongPress fires, so opening MessageInteractions via
|
|
352
|
+
// long-press never triggers this dismiss.
|
|
353
|
+
onPress={() => Keyboard.dismiss()}
|
|
310
354
|
// disableInteractions hides the long-press → context menu
|
|
311
355
|
// (delete / edit / reply / react). Mirrors web's config gate.
|
|
312
356
|
onLongPress={
|
|
@@ -315,6 +359,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
315
359
|
delayLongPress={500}
|
|
316
360
|
>
|
|
317
361
|
<CustomMessageBubble
|
|
362
|
+
{...({ ref: bubbleRef, collapsable: false } as any)}
|
|
318
363
|
isUser={isUser}
|
|
319
364
|
deleted={message.isDeleted}
|
|
320
365
|
isMedia={message?.isMediafile === 'true' && !message?.isDeleted}
|
|
@@ -322,7 +367,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
322
367
|
backgroundMessage={config?.messageColor?.backgroundMessage}
|
|
323
368
|
>
|
|
324
369
|
{!isUser && (
|
|
325
|
-
<CustomUserName color={config?.colors?.primary}>
|
|
370
|
+
<CustomUserName color={config?.colors?.primary} media={message?.isMediafile === 'true'}>
|
|
326
371
|
{message.user.name}
|
|
327
372
|
</CustomUserName>
|
|
328
373
|
)}
|
|
@@ -341,6 +386,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
341
386
|
messageText={message.locationPreview}
|
|
342
387
|
location={message?.location}
|
|
343
388
|
message={message}
|
|
389
|
+
isUser={isUser}
|
|
344
390
|
/>
|
|
345
391
|
) : (
|
|
346
392
|
<>
|
|
@@ -364,26 +410,31 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
364
410
|
langSource={langSource}
|
|
365
411
|
/>
|
|
366
412
|
)}
|
|
367
|
-
<
|
|
368
|
-
{
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
413
|
+
{/* <View style={styles.timestampRow}> */}
|
|
414
|
+
<CustomTimestampRow media={message?.isMediafile === 'true'}>
|
|
415
|
+
{!config?.disableSentLogic && isUser && isPending && (
|
|
416
|
+
<Text style={styles.timestampText}>sending...</Text>
|
|
417
|
+
)}
|
|
418
|
+
{!config?.disableSentLogic && isUser && isFailed && (
|
|
419
|
+
<Text
|
|
420
|
+
onPress={onRetryPress}
|
|
421
|
+
style={styles.failedText}
|
|
422
|
+
accessibilityRole="button"
|
|
423
|
+
accessibilityLabel="Retry sending message"
|
|
424
|
+
>
|
|
425
|
+
! Failed — tap to retry
|
|
426
|
+
</Text>
|
|
427
|
+
)}
|
|
428
|
+
<Text style={styles.timestampText}>
|
|
429
|
+
{new Date(message.date).toLocaleTimeString([], {
|
|
430
|
+
hour: '2-digit',
|
|
431
|
+
minute: '2-digit',
|
|
432
|
+
})}
|
|
377
433
|
</Text>
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
})}
|
|
383
|
-
{!config?.disableSentLogic && isUser && !isPending && !isFailed && (
|
|
384
|
-
<DoubleTick />
|
|
385
|
-
)}
|
|
386
|
-
</CustomMessageTimestamp>
|
|
434
|
+
{!config?.disableSentLogic && isUser && !isPending && !isFailed && (
|
|
435
|
+
<DoubleTick />
|
|
436
|
+
)}
|
|
437
|
+
</CustomTimestampRow>
|
|
387
438
|
|
|
388
439
|
{message?.reply?.length && message?.reply?.length > 0 ? (
|
|
389
440
|
<BottomReplyContainer
|
|
@@ -455,4 +506,23 @@ const styles = StyleSheet.create({
|
|
|
455
506
|
fontWeight: '600',
|
|
456
507
|
marginRight: 6,
|
|
457
508
|
},
|
|
509
|
+
// Row keeps the time text and the DoubleTick SVG on the same line.
|
|
510
|
+
// The time Text gets an explicit lineHeight equal to the 16px tick so
|
|
511
|
+
// both occupy the same-height box; with alignItems center they line up
|
|
512
|
+
// exactly. Without the lineHeight the Text's natural line box was
|
|
513
|
+
// shorter than the icon, so the centred tick floated above the digits.
|
|
514
|
+
timestampRow: {
|
|
515
|
+
flexDirection: 'row',
|
|
516
|
+
alignItems: 'center',
|
|
517
|
+
alignSelf: 'flex-end',
|
|
518
|
+
marginTop: 4,
|
|
519
|
+
gap: 4,
|
|
520
|
+
},
|
|
521
|
+
timestampText: {
|
|
522
|
+
fontSize: 12,
|
|
523
|
+
lineHeight: 16,
|
|
524
|
+
color: '#999',
|
|
525
|
+
includeFontPadding: false,
|
|
526
|
+
textAlignVertical: 'center',
|
|
527
|
+
},
|
|
458
528
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { useEffect, useId, useMemo, useState } from 'react';
|
|
2
2
|
import { Delimeter, MenuItem } from '../ContextMenu/ContextMenuComponents';
|
|
3
3
|
import { useSelector } from 'react-redux';
|
|
4
4
|
import { RootState } from '../../roomStore';
|
|
@@ -8,20 +8,27 @@ import {
|
|
|
8
8
|
} from '../../helpers/constants/MESSAGE_INTERACTIONS';
|
|
9
9
|
import { IMessage } from '../../types/types';
|
|
10
10
|
import {
|
|
11
|
-
Modal,
|
|
12
11
|
Text,
|
|
13
12
|
StyleSheet,
|
|
14
13
|
View,
|
|
15
14
|
Pressable,
|
|
15
|
+
Dimensions,
|
|
16
|
+
type LayoutChangeEvent,
|
|
16
17
|
} from 'react-native';
|
|
17
18
|
import * as Clipboard from 'expo-clipboard';
|
|
18
19
|
import { useToast } from '../../context/ToastContext';
|
|
20
|
+
import { useInteractionsOverlay } from './InteractionsOverlay';
|
|
19
21
|
|
|
20
22
|
interface MessageInteractionsProps {
|
|
21
23
|
isReply?: boolean;
|
|
22
24
|
isUser?: boolean;
|
|
23
25
|
message: IMessage;
|
|
24
|
-
position: {
|
|
26
|
+
position: {
|
|
27
|
+
left: number;
|
|
28
|
+
right: number;
|
|
29
|
+
top: number;
|
|
30
|
+
bottom: number;
|
|
31
|
+
} | null;
|
|
25
32
|
closeMenu: () => void;
|
|
26
33
|
handleReplyMessage: () => void;
|
|
27
34
|
handleDeleteMessage: () => void;
|
|
@@ -40,11 +47,26 @@ const MessageInteractions: React.FC<MessageInteractionsProps> = ({
|
|
|
40
47
|
handleEditMessage,
|
|
41
48
|
}) => {
|
|
42
49
|
const { showToast } = useToast();
|
|
50
|
+
const { present, dismiss, originX, originY } = useInteractionsOverlay();
|
|
51
|
+
const overlayId = useId();
|
|
43
52
|
|
|
44
53
|
const config = useSelector(
|
|
45
54
|
(state: RootState) => state.chatSettingStore.config
|
|
46
55
|
);
|
|
47
56
|
|
|
57
|
+
const [menuSize, setMenuSize] = useState({ width: 0, height: 0 });
|
|
58
|
+
|
|
59
|
+
const handleMenuLayout = (e: LayoutChangeEvent) => {
|
|
60
|
+
const { width, height } = e.nativeEvent.layout;
|
|
61
|
+
if (
|
|
62
|
+
width &&
|
|
63
|
+
height &&
|
|
64
|
+
(width !== menuSize.width || height !== menuSize.height)
|
|
65
|
+
) {
|
|
66
|
+
setMenuSize({ width, height });
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
48
70
|
const handleCopyMessage = async (text: string) => {
|
|
49
71
|
try {
|
|
50
72
|
await Clipboard.setStringAsync(text);
|
|
@@ -71,58 +93,110 @@ const MessageInteractions: React.FC<MessageInteractionsProps> = ({
|
|
|
71
93
|
};
|
|
72
94
|
|
|
73
95
|
const memoPosition = useMemo(() => {
|
|
74
|
-
if (position) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
if (!position) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (!menuSize.width || !menuSize.height) {
|
|
101
|
+
return { top: position.bottom, left: position.left, opacity: 0 };
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const { width: screenWidth, height: screenHeight } =
|
|
105
|
+
Dimensions.get('window');
|
|
106
|
+
const bottomReserve = (config?.keyboardVerticalOffset ?? 0) + 24;
|
|
107
|
+
const topReserve = 16;
|
|
108
|
+
const sideMargin = 8;
|
|
109
|
+
|
|
110
|
+
const spaceBelow = screenHeight - position.bottom - bottomReserve;
|
|
111
|
+
const spaceAbove = position.top - topReserve;
|
|
112
|
+
|
|
113
|
+
let top: number;
|
|
114
|
+
if (spaceBelow >= menuSize.height) {
|
|
115
|
+
top = position.bottom;
|
|
116
|
+
} else if (spaceAbove >= menuSize.height) {
|
|
117
|
+
top = position.top - menuSize.height;
|
|
118
|
+
} else {
|
|
119
|
+
top = Math.max(topReserve, screenHeight - menuSize.height - bottomReserve);
|
|
86
120
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
+
|
|
122
|
+
const leftMargin = position.left;
|
|
123
|
+
const rightMargin = screenWidth - position.right;
|
|
124
|
+
const rightAligned = rightMargin < leftMargin;
|
|
125
|
+
|
|
126
|
+
let left = rightAligned ? position.right - menuSize.width : position.left;
|
|
127
|
+
left = Math.max(
|
|
128
|
+
sideMargin,
|
|
129
|
+
Math.min(left, screenWidth - menuSize.width - sideMargin)
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
return { top, left };
|
|
133
|
+
}, [position, menuSize, config?.keyboardVerticalOffset]);
|
|
134
|
+
|
|
135
|
+
// Window coords (memoPosition) → host-local coords. The overlay host
|
|
136
|
+
// sits below the status bar / header, so subtract its measured origin.
|
|
137
|
+
const localPosition = useMemo(() => {
|
|
138
|
+
if (!memoPosition) {return undefined;}
|
|
139
|
+
return {
|
|
140
|
+
...memoPosition,
|
|
141
|
+
top: (memoPosition as { top: number }).top - originY,
|
|
142
|
+
left: (memoPosition as { left: number }).left - originX,
|
|
143
|
+
};
|
|
144
|
+
}, [memoPosition, originX, originY]);
|
|
145
|
+
|
|
146
|
+
const content =
|
|
147
|
+
config?.disableInteractions || message.isDeleted ? null : (
|
|
148
|
+
<View style={styles.overlayFill}>
|
|
149
|
+
<Pressable style={StyleSheet.absoluteFill} onPress={closeMenu} />
|
|
150
|
+
<View
|
|
151
|
+
style={[styles.contextMenu, localPosition]}
|
|
152
|
+
onLayout={handleMenuLayout}
|
|
153
|
+
>
|
|
154
|
+
<MenuItem onPress={() => handleCopyMessage(message.body!)}>
|
|
155
|
+
<Text style={styles.menuText}>{MESSAGE_INTERACTIONS.COPY}</Text>
|
|
156
|
+
<MESSAGE_INTERACTIONS_ICONS.COPY />
|
|
157
|
+
</MenuItem>
|
|
158
|
+
{isUser && (
|
|
159
|
+
<>
|
|
160
|
+
{/* Edit only for non-media messages (upstream guard) +
|
|
161
|
+
consistent label styling (menuText). */}
|
|
162
|
+
{message?.isMediafile !== 'true' && (
|
|
163
|
+
<>
|
|
164
|
+
<Delimeter />
|
|
165
|
+
<MenuItem onPress={handleEditMessage}>
|
|
166
|
+
<Text style={styles.menuText}>
|
|
167
|
+
{MESSAGE_INTERACTIONS.EDIT}
|
|
168
|
+
</Text>
|
|
169
|
+
<MESSAGE_INTERACTIONS_ICONS.EDIT />
|
|
170
|
+
</MenuItem>
|
|
171
|
+
</>
|
|
172
|
+
)}
|
|
173
|
+
<Delimeter />
|
|
174
|
+
<MenuItem onPress={handleDeleteMessage}>
|
|
175
|
+
<Text style={styles.menuText}>{MESSAGE_INTERACTIONS.DELETE}</Text>
|
|
176
|
+
<MESSAGE_INTERACTIONS_ICONS.DELETE />
|
|
177
|
+
</MenuItem>
|
|
178
|
+
</>
|
|
179
|
+
)}
|
|
121
180
|
</View>
|
|
122
|
-
|
|
181
|
+
</View>
|
|
182
|
+
);
|
|
123
183
|
|
|
124
|
-
|
|
125
|
-
|
|
184
|
+
// Render the menu in the in-tree overlay host instead of a React Native
|
|
185
|
+
// <Modal>. A Modal opens its own window on Android, which steals focus
|
|
186
|
+
// from the chat input and dismisses the keyboard when the menu opens;
|
|
187
|
+
// hosting it in the same view tree keeps the keyboard up. Re-run every
|
|
188
|
+
// render so menuSize/position updates refresh the hosted node.
|
|
189
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
if (content) {
|
|
192
|
+
present(overlayId, content);
|
|
193
|
+
} else {
|
|
194
|
+
dismiss(overlayId);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
useEffect(() => () => dismiss(overlayId), [dismiss, overlayId]);
|
|
198
|
+
|
|
199
|
+
return null;
|
|
126
200
|
};
|
|
127
201
|
|
|
128
202
|
export default MessageInteractions;
|
|
@@ -135,14 +209,28 @@ const styles = StyleSheet.create({
|
|
|
135
209
|
contextMenu: {
|
|
136
210
|
position: 'absolute',
|
|
137
211
|
backgroundColor: 'white',
|
|
138
|
-
paddingVertical:
|
|
139
|
-
paddingHorizontal:
|
|
140
|
-
borderRadius:
|
|
212
|
+
paddingVertical: 4,
|
|
213
|
+
paddingHorizontal: 8,
|
|
214
|
+
borderRadius: 12,
|
|
141
215
|
shadowColor: '#000',
|
|
142
216
|
shadowOffset: { width: 0, height: 2 },
|
|
143
|
-
shadowOpacity: 0.
|
|
144
|
-
shadowRadius:
|
|
145
|
-
elevation:
|
|
217
|
+
shadowOpacity: 0.18,
|
|
218
|
+
shadowRadius: 8,
|
|
219
|
+
elevation: 6,
|
|
146
220
|
minWidth: 180,
|
|
221
|
+
// Clip the children to the rounded corners (the hairline dividers
|
|
222
|
+
// run full width; without this they'd poke past the rounding on
|
|
223
|
+
// Android).
|
|
224
|
+
overflow: 'hidden',
|
|
225
|
+
},
|
|
226
|
+
// Explicit label styling so rows are the same height on both platforms
|
|
227
|
+
// — Android's default includeFontPadding made the menu rows taller and
|
|
228
|
+
// misaligned vs iOS. marginRight keeps the label off the trailing icon.
|
|
229
|
+
menuText: {
|
|
230
|
+
fontSize: 16,
|
|
231
|
+
color: '#141414',
|
|
232
|
+
includeFontPadding: false,
|
|
233
|
+
textAlignVertical: 'center',
|
|
234
|
+
marginRight: 16,
|
|
147
235
|
},
|
|
148
236
|
});
|