@ethora/chat-component-rn 26.5.5 → 26.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +177 -0
- package/README.md +67 -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 +7 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +66 -34
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +59 -14
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +15 -7
- 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 +175 -30
- 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/Message.js +117 -19
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +82 -22
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +16 -4
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.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 +175 -40
- 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/ModalWrapper/ModalWrapper.js +78 -39
- 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 +4 -9
- package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +115 -5
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +49 -10
- 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 +53 -29
- package/lib/commonjs/components/styled/SendInput.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 +60 -22
- 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 +315 -34
- 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 +131 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -0
- package/lib/commonjs/helpers/normalizeRoomJid.js +20 -0
- package/lib/commonjs/helpers/normalizeRoomJid.js.map +1 -0
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +73 -1
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/commonjs/hooks/useChatRoomFocus.js +87 -0
- package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -0
- package/lib/commonjs/hooks/useChatWrapperInit.js +22 -10
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useEventHandlers.js +9 -1
- package/lib/commonjs/hooks/useEventHandlers.js.map +1 -1
- package/lib/commonjs/hooks/useHeapSender.js +1 -1
- package/lib/commonjs/hooks/useHeapSender.js.map +1 -1
- package/lib/commonjs/hooks/useLogout.js +3 -3
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/hooks/useMessageHeapState.js +6 -2
- package/lib/commonjs/hooks/useMessageHeapState.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 +249 -14
- 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 +74 -1
- package/lib/commonjs/networking/api-requests/auth.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 +371 -26
- 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/roomHeapSlice.js +26 -8
- package/lib/commonjs/roomStore/roomHeapSlice.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 +7 -1
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +67 -35
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +59 -14
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +15 -7
- 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 +176 -31
- 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/Message.js +118 -20
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +84 -24
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js +15 -3
- package/lib/module/components/Modals/AttachSheet/AttachSheet.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 +179 -42
- 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/ModalWrapper/ModalWrapper.js +80 -41
- 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 +4 -9
- package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +116 -6
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +51 -12
- 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 +54 -30
- package/lib/module/components/styled/SendInput.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 +61 -23
- 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 +319 -37
- 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 +124 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -0
- package/lib/module/helpers/normalizeRoomJid.js +15 -0
- package/lib/module/helpers/normalizeRoomJid.js.map +1 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js +71 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/module/hooks/useChatRoomFocus.js +82 -0
- package/lib/module/hooks/useChatRoomFocus.js.map +1 -0
- package/lib/module/hooks/useChatWrapperInit.js +22 -10
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useEventHandlers.js +9 -1
- package/lib/module/hooks/useEventHandlers.js.map +1 -1
- package/lib/module/hooks/useHeapSender.js +1 -1
- package/lib/module/hooks/useHeapSender.js.map +1 -1
- package/lib/module/hooks/useLogout.js +3 -3
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/hooks/useMessageHeapState.js +6 -2
- package/lib/module/hooks/useMessageHeapState.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 +252 -17
- 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 +74 -2
- package/lib/module/networking/api-requests/auth.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 +371 -26
- 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/roomHeapSlice.js +24 -7
- package/lib/module/roomStore/roomHeapSlice.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/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/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/ModalWrapper/ModalWrapper.d.ts +6 -0
- 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/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 +37 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -0
- package/lib/typescript/helpers/normalizeRoomJid.d.ts +2 -0
- package/lib/typescript/helpers/normalizeRoomJid.d.ts.map +1 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts +18 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatRoomFocus.d.ts +42 -0
- package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useEventHandlers.d.ts +6 -0
- package/lib/typescript/hooks/useEventHandlers.d.ts.map +1 -1
- package/lib/typescript/hooks/useHeapSender.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageHeapState.d.ts +2 -0
- package/lib/typescript/hooks/useMessageHeapState.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 +2 -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/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 +58 -5
- 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/roomHeapSlice.d.ts +22 -1
- package/lib/typescript/roomStore/roomHeapSlice.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 +10 -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 +18 -2
- package/src/assets/icons.tsx +23 -14
- package/src/components/ContextMenu/ContextMenuComponents.tsx +10 -5
- package/src/components/MainComponents/ChatHeader.tsx +5 -1
- package/src/components/MainComponents/ChatRoom.tsx +81 -61
- package/src/components/MainComponents/ChatWrapper.tsx +100 -21
- package/src/components/MainComponents/MediaMessage.tsx +18 -8
- package/src/components/MainComponents/MessageContainer.tsx +4 -2
- package/src/components/MainComponents/MessageList.tsx +185 -31
- package/src/components/MainComponents/ReduxWrapper.tsx +19 -9
- package/src/components/MainComponents/SystemMessage.tsx +38 -26
- package/src/components/MessageBubble/Message.tsx +110 -27
- package/src/components/MessageBubble/MessageInteractions.tsx +98 -29
- package/src/components/Modals/AttachSheet/AttachSheet.tsx +17 -3
- package/src/components/Modals/FilePreviewModal/DocumentViewer.tsx +93 -0
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +182 -37
- package/src/components/Modals/FilePreviewModal/PdfView.tsx +32 -4
- package/src/components/Modals/Modal/Modal.tsx +4 -1
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +77 -44
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -15
- package/src/components/Modals/styledModalComponents.tsx +4 -9
- package/src/components/styled/MediaFilePreview.tsx +111 -5
- package/src/components/styled/MessageImage.tsx +58 -14
- package/src/components/styled/NewMessageLabel.tsx +8 -5
- package/src/components/styled/SendInput.tsx +67 -29
- 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 +59 -18
- package/src/context/MessageNotificationContext.tsx +8 -8
- package/src/context/xmppProvider.tsx +337 -32
- 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 +135 -0
- package/src/helpers/normalizeRoomJid.ts +6 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +79 -0
- package/src/hooks/useChatRoomFocus.ts +95 -0
- package/src/hooks/useChatWrapperInit.ts +51 -46
- package/src/hooks/useEventHandlers.tsx +24 -1
- package/src/hooks/useHeapSender.tsx +2 -1
- package/src/hooks/useLogout.tsx +3 -3
- package/src/hooks/useMessageHeapState.tsx +6 -2
- package/src/hooks/usePushNotifications.ts +21 -8
- package/src/hooks/useRoomState.tsx +4 -0
- package/src/hooks/useSendMessage.tsx +333 -17
- package/src/hooks/useUnreadMessagesCounter.ts +13 -16
- package/src/main.ts +1 -0
- package/src/networking/api-requests/auth.api.ts +60 -2
- 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 +399 -31
- package/src/roomStore/Middleware/unreadMidlleware.tsx +23 -5
- package/src/roomStore/roomHeapSlice.ts +47 -4
- 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 +25 -0
- package/src/utils/installPromiseRejectionTracker.ts +91 -0
- package/src/utils/resendMessage.ts +2 -1
|
@@ -1,42 +1,54 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import styled from 'styled-components/native';
|
|
2
|
+
import { View, Text, StyleSheet } from 'react-native';
|
|
4
3
|
|
|
5
4
|
interface SystemMessageProps {
|
|
6
5
|
messageText?: string;
|
|
7
6
|
colors?: { primary?: string; secondary?: string };
|
|
8
7
|
}
|
|
9
8
|
|
|
10
|
-
export const CustomSystemMessageText = styled.Text<{
|
|
11
|
-
primary?: string;
|
|
12
|
-
secondary?: string;
|
|
13
|
-
}>`
|
|
14
|
-
margin: 0;
|
|
15
|
-
color: ${(props) => props.primary || '#0052cd'};
|
|
16
|
-
border-radius: 118px;
|
|
17
|
-
padding: 5px 8px;
|
|
18
|
-
display: flex;
|
|
19
|
-
align-items: center;
|
|
20
|
-
justify-content: center;
|
|
21
|
-
font-size: 12px;
|
|
22
|
-
line-height: 14px;
|
|
23
|
-
font-weight: 600;
|
|
24
|
-
background-color: ${(props) => props.secondary || '#e7edf9'};
|
|
25
|
-
height: 24px;
|
|
26
|
-
white-space: nowrap;
|
|
27
|
-
`;
|
|
28
|
-
|
|
29
9
|
const SystemMessage: React.FC<SystemMessageProps> = ({
|
|
30
10
|
messageText,
|
|
31
11
|
colors,
|
|
32
12
|
}) => {
|
|
33
13
|
return (
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
14
|
+
<View style={styles.container}>
|
|
15
|
+
{/* maxWidth lives on this View (not the Text) so the Text reliably
|
|
16
|
+
wraps to multiple lines instead of staying on one line and
|
|
17
|
+
getting clipped — a styled.Text with a percentage max-width
|
|
18
|
+
doesn't bound its own line box the way a View does. */}
|
|
19
|
+
<View
|
|
20
|
+
style={[
|
|
21
|
+
styles.bubble,
|
|
22
|
+
{ backgroundColor: colors?.secondary || '#e7edf9' },
|
|
23
|
+
]}
|
|
24
|
+
>
|
|
25
|
+
<Text style={[styles.text, { color: colors?.primary || '#0052cd' }]}>
|
|
26
|
+
{messageText}
|
|
27
|
+
</Text>
|
|
28
|
+
</View>
|
|
29
|
+
</View>
|
|
39
30
|
);
|
|
40
31
|
};
|
|
41
32
|
|
|
42
33
|
export default SystemMessage;
|
|
34
|
+
|
|
35
|
+
const styles = StyleSheet.create({
|
|
36
|
+
container: {
|
|
37
|
+
width: '100%',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
paddingVertical: 8,
|
|
40
|
+
paddingHorizontal: 16,
|
|
41
|
+
},
|
|
42
|
+
bubble: {
|
|
43
|
+
maxWidth: '85%',
|
|
44
|
+
borderRadius: 12,
|
|
45
|
+
paddingVertical: 6,
|
|
46
|
+
paddingHorizontal: 12,
|
|
47
|
+
},
|
|
48
|
+
text: {
|
|
49
|
+
fontSize: 12,
|
|
50
|
+
lineHeight: 16,
|
|
51
|
+
fontWeight: '600',
|
|
52
|
+
textAlign: 'center',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
@@ -5,7 +5,6 @@ import {
|
|
|
5
5
|
StyleSheet,
|
|
6
6
|
findNodeHandle,
|
|
7
7
|
UIManager,
|
|
8
|
-
Dimensions,
|
|
9
8
|
Text,
|
|
10
9
|
} from 'react-native';
|
|
11
10
|
import { useDispatch, useSelector } from 'react-redux';
|
|
@@ -31,6 +30,7 @@ import { parseMessageBody } from '../../helpers/parseMessageBody';
|
|
|
31
30
|
import { useMessageHeapState } from '../../hooks/useMessageHeapState';
|
|
32
31
|
import { DoubleTick } from '../../assets/icons';
|
|
33
32
|
import { useXmppClient } from '../../context/xmppProvider';
|
|
33
|
+
import { useSendMessage } from '../../hooks/useSendMessage';
|
|
34
34
|
import { MessageReaction } from './MessageReaction';
|
|
35
35
|
import { MessageFooter } from '../styled/StyledComponents';
|
|
36
36
|
|
|
@@ -47,14 +47,19 @@ const CustomMessageBubble = styled.View<{
|
|
|
47
47
|
deleted?: boolean;
|
|
48
48
|
backgroundMessageUser?: string;
|
|
49
49
|
backgroundMessage?: string;
|
|
50
|
+
isMedia?: boolean;
|
|
50
51
|
}>`
|
|
51
52
|
position: relative;
|
|
52
53
|
max-width: 85%;
|
|
53
|
-
min-width: 30
|
|
54
|
-
|
|
54
|
+
min-width: ${({ isMedia }) => (isMedia ? '0' : '30%')};
|
|
55
|
+
align-items: ${({ isMedia, isUser }) =>
|
|
56
|
+
isMedia ? (isUser ? 'flex-end' : 'flex-start') : 'stretch'};
|
|
57
|
+
padding: ${({isMedia}) => isMedia ? '0' : '10'}px;
|
|
58
|
+
padding-bottom: ${({isMedia}) => isMedia ? '6' : '10'}px;
|
|
55
59
|
margin-right: ${({isUser}) => isUser ? '0' : '10px'};
|
|
56
60
|
margin-left: ${({isUser}) => isUser ? '10px' : '0'};
|
|
57
61
|
border-radius: 10px;
|
|
62
|
+
overflow: hidden;
|
|
58
63
|
border-bottom-left-radius: ${({ isUser }) => (isUser ? '10' : '0')}px;
|
|
59
64
|
border-bottom-right-radius: ${({ isUser }) => (isUser ? '0' : '10')}px;
|
|
60
65
|
background-color: ${({
|
|
@@ -90,9 +95,12 @@ const CustomMessagePhotoContainer = styled.TouchableOpacity`
|
|
|
90
95
|
margin-right: 10px;
|
|
91
96
|
`;
|
|
92
97
|
|
|
93
|
-
const CustomUserName = styled.Text<{ color?: string }>`
|
|
98
|
+
const CustomUserName = styled.Text<{ color?: string; media: boolean }>`
|
|
94
99
|
font-size: 14px;
|
|
95
100
|
font-weight: 500;
|
|
101
|
+
padding-bottom: 8px;
|
|
102
|
+
padding-left: ${({media}) => media ? '16px': 0};
|
|
103
|
+
padding-top: ${({media}) => media ? '8px': 0};
|
|
96
104
|
color: ${({ color }) => color || '#333'};
|
|
97
105
|
`;
|
|
98
106
|
|
|
@@ -109,11 +117,21 @@ const CustomMessageTimestamp = styled.Text<{
|
|
|
109
117
|
align-self: flex-end;
|
|
110
118
|
`;
|
|
111
119
|
|
|
120
|
+
const CustomTimestampRow = styled.View<{media: boolean}>`
|
|
121
|
+
flex-direction: row;
|
|
122
|
+
align-items: center;
|
|
123
|
+
align-self: flex-end;
|
|
124
|
+
margin-top: 4;
|
|
125
|
+
gap: 4;
|
|
126
|
+
padding-right: ${({media}) => media ? '10px': 0};
|
|
127
|
+
`;
|
|
128
|
+
|
|
112
129
|
const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
113
130
|
const dispatch = useDispatch();
|
|
114
131
|
const { client } = useXmppClient();
|
|
115
132
|
const { config, langSource, user} = useChatSettingState();
|
|
116
|
-
const { idSet } = useMessageHeapState();
|
|
133
|
+
const { idSet, failedIdSet } = useMessageHeapState();
|
|
134
|
+
const { retryMessage } = useSendMessage();
|
|
117
135
|
|
|
118
136
|
const [isPressed, setIsPressed] = useState(false);
|
|
119
137
|
|
|
@@ -122,12 +140,15 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
122
140
|
}
|
|
123
141
|
|
|
124
142
|
const [contextMenuPosition, setContextMenuPosition] = useState<{
|
|
125
|
-
|
|
126
|
-
|
|
143
|
+
left: number;
|
|
144
|
+
right: number;
|
|
145
|
+
top: number;
|
|
146
|
+
bottom: number;
|
|
127
147
|
} | null>(null);
|
|
128
148
|
|
|
129
149
|
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
130
150
|
const messageRef = useRef<View>(null);
|
|
151
|
+
const bubbleRef = useRef<View>(null);
|
|
131
152
|
|
|
132
153
|
const handleUserAvatarClick = (user: IUser): void => {
|
|
133
154
|
dispatch(setActiveModal(MODAL_TYPES.PROFILE));
|
|
@@ -214,17 +235,22 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
214
235
|
);
|
|
215
236
|
};
|
|
216
237
|
|
|
238
|
+
// Long-press → capture the bubble's on-screen bounding box. The actual
|
|
239
|
+
// menu placement (above / below, clamped to the viewport) is done in
|
|
240
|
+
// MessageInteractions, which measures the rendered menu height via
|
|
241
|
+
// onLayout — more accurate than estimating it here, and it's what keeps
|
|
242
|
+
// the menu adjacent to the message instead of floating far above (#13).
|
|
217
243
|
const handleLongPress = () => {
|
|
218
|
-
|
|
219
|
-
|
|
244
|
+
const target = bubbleRef.current ?? messageRef.current;
|
|
245
|
+
if (target) {
|
|
246
|
+
const nodeHandle = findNodeHandle(target);
|
|
220
247
|
if (nodeHandle) {
|
|
221
|
-
UIManager.measure(nodeHandle, (
|
|
222
|
-
const screenHeight = Dimensions.get('window').height;
|
|
223
|
-
|
|
224
|
-
const enoughSpaceBelow = screenHeight - pageY - height > 150;
|
|
248
|
+
UIManager.measure(nodeHandle, (_x, _y, width, height, pageX, pageY) => {
|
|
225
249
|
setContextMenuPosition({
|
|
226
|
-
|
|
227
|
-
|
|
250
|
+
left: pageX,
|
|
251
|
+
right: pageX + width,
|
|
252
|
+
top: pageY,
|
|
253
|
+
bottom: pageY + height,
|
|
228
254
|
});
|
|
229
255
|
});
|
|
230
256
|
}
|
|
@@ -236,7 +262,13 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
236
262
|
? parseMessageBody(config?.messageTextFilter.filterFunction(message.body))
|
|
237
263
|
: parseMessageBody(message.body);
|
|
238
264
|
|
|
239
|
-
const
|
|
265
|
+
const isFailed = failedIdSet.has(message.id);
|
|
266
|
+
const isPending =
|
|
267
|
+
!isFailed && (idSet.has(message.id) || message?.pending || false);
|
|
268
|
+
|
|
269
|
+
const onRetryPress = () => {
|
|
270
|
+
if (isFailed) {retryMessage(message.id);}
|
|
271
|
+
};
|
|
240
272
|
|
|
241
273
|
return (
|
|
242
274
|
<View>
|
|
@@ -269,6 +301,15 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
269
301
|
</CustomMessagePhotoContainer>
|
|
270
302
|
)}
|
|
271
303
|
<Pressable
|
|
304
|
+
// The Pressable fills the row's content area, so the bubble
|
|
305
|
+
// inside must be aligned to the sender's side — otherwise it
|
|
306
|
+
// hugs the left and own media bubbles sit with a right-side
|
|
307
|
+
// gap (text bubbles only looked right because they're narrow).
|
|
308
|
+
// flex-end for own, flex-start for others.
|
|
309
|
+
style={{
|
|
310
|
+
flex: 1,
|
|
311
|
+
alignItems: isUser ? 'flex-end' : 'flex-start',
|
|
312
|
+
}}
|
|
272
313
|
// disableInteractions hides the long-press → context menu
|
|
273
314
|
// (delete / edit / reply / react). Mirrors web's config gate.
|
|
274
315
|
onLongPress={
|
|
@@ -277,13 +318,15 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
277
318
|
delayLongPress={500}
|
|
278
319
|
>
|
|
279
320
|
<CustomMessageBubble
|
|
321
|
+
{...({ ref: bubbleRef, collapsable: false } as any)}
|
|
280
322
|
isUser={isUser}
|
|
281
323
|
deleted={message.isDeleted}
|
|
324
|
+
isMedia={message?.isMediafile === 'true' && !message?.isDeleted}
|
|
282
325
|
backgroundMessageUser={config?.messageColor?.backgroundMessageUser}
|
|
283
326
|
backgroundMessage={config?.messageColor?.backgroundMessage}
|
|
284
327
|
>
|
|
285
328
|
{!isUser && (
|
|
286
|
-
<CustomUserName color={config?.colors?.primary}>
|
|
329
|
+
<CustomUserName color={config?.colors?.primary} media={message?.isMediafile === 'true'}>
|
|
287
330
|
{message.user.name}
|
|
288
331
|
</CustomUserName>
|
|
289
332
|
)}
|
|
@@ -302,6 +345,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
302
345
|
messageText={message.locationPreview}
|
|
303
346
|
location={message?.location}
|
|
304
347
|
message={message}
|
|
348
|
+
isUser={isUser}
|
|
305
349
|
/>
|
|
306
350
|
) : (
|
|
307
351
|
<>
|
|
@@ -325,16 +369,31 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
325
369
|
langSource={langSource}
|
|
326
370
|
/>
|
|
327
371
|
)}
|
|
328
|
-
<
|
|
329
|
-
{
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
372
|
+
{/* <View style={styles.timestampRow}> */}
|
|
373
|
+
<CustomTimestampRow media={message?.isMediafile === 'true'}>
|
|
374
|
+
{!config?.disableSentLogic && isUser && isPending && (
|
|
375
|
+
<Text style={styles.timestampText}>sending...</Text>
|
|
376
|
+
)}
|
|
377
|
+
{!config?.disableSentLogic && isUser && isFailed && (
|
|
378
|
+
<Text
|
|
379
|
+
onPress={onRetryPress}
|
|
380
|
+
style={styles.failedText}
|
|
381
|
+
accessibilityRole="button"
|
|
382
|
+
accessibilityLabel="Retry sending message"
|
|
383
|
+
>
|
|
384
|
+
! Failed — tap to retry
|
|
385
|
+
</Text>
|
|
386
|
+
)}
|
|
387
|
+
<Text style={styles.timestampText}>
|
|
388
|
+
{new Date(message.date).toLocaleTimeString([], {
|
|
389
|
+
hour: '2-digit',
|
|
390
|
+
minute: '2-digit',
|
|
391
|
+
})}
|
|
392
|
+
</Text>
|
|
393
|
+
{!config?.disableSentLogic && isUser && !isPending && !isFailed && (
|
|
394
|
+
<DoubleTick />
|
|
395
|
+
)}
|
|
396
|
+
</CustomTimestampRow>
|
|
338
397
|
|
|
339
398
|
{message?.reply?.length && message?.reply?.length > 0 ? (
|
|
340
399
|
<BottomReplyContainer
|
|
@@ -401,4 +460,28 @@ const styles = StyleSheet.create({
|
|
|
401
460
|
marginTop: 5,
|
|
402
461
|
alignSelf: 'flex-end',
|
|
403
462
|
},
|
|
463
|
+
failedText: {
|
|
464
|
+
color: '#E53935',
|
|
465
|
+
fontWeight: '600',
|
|
466
|
+
marginRight: 6,
|
|
467
|
+
},
|
|
468
|
+
// Row keeps the time text and the DoubleTick SVG on the same line.
|
|
469
|
+
// The time Text gets an explicit lineHeight equal to the 16px tick so
|
|
470
|
+
// both occupy the same-height box; with alignItems center they line up
|
|
471
|
+
// exactly. Without the lineHeight the Text's natural line box was
|
|
472
|
+
// shorter than the icon, so the centred tick floated above the digits.
|
|
473
|
+
timestampRow: {
|
|
474
|
+
flexDirection: 'row',
|
|
475
|
+
alignItems: 'center',
|
|
476
|
+
alignSelf: 'flex-end',
|
|
477
|
+
marginTop: 4,
|
|
478
|
+
gap: 4,
|
|
479
|
+
},
|
|
480
|
+
timestampText: {
|
|
481
|
+
fontSize: 12,
|
|
482
|
+
lineHeight: 16,
|
|
483
|
+
color: '#999',
|
|
484
|
+
includeFontPadding: false,
|
|
485
|
+
textAlignVertical: 'center',
|
|
486
|
+
},
|
|
404
487
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo } from 'react';
|
|
1
|
+
import React, { 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';
|
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
StyleSheet,
|
|
14
14
|
View,
|
|
15
15
|
Pressable,
|
|
16
|
+
Dimensions,
|
|
17
|
+
type LayoutChangeEvent,
|
|
16
18
|
} from 'react-native';
|
|
17
19
|
import * as Clipboard from 'expo-clipboard';
|
|
18
20
|
import { useToast } from '../../context/ToastContext';
|
|
@@ -21,7 +23,12 @@ 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;
|
|
@@ -45,6 +52,19 @@ const MessageInteractions: React.FC<MessageInteractionsProps> = ({
|
|
|
45
52
|
(state: RootState) => state.chatSettingStore.config
|
|
46
53
|
);
|
|
47
54
|
|
|
55
|
+
const [menuSize, setMenuSize] = useState({ width: 0, height: 0 });
|
|
56
|
+
|
|
57
|
+
const handleMenuLayout = (e: LayoutChangeEvent) => {
|
|
58
|
+
const { width, height } = e.nativeEvent.layout;
|
|
59
|
+
if (
|
|
60
|
+
width &&
|
|
61
|
+
height &&
|
|
62
|
+
(width !== menuSize.width || height !== menuSize.height)
|
|
63
|
+
) {
|
|
64
|
+
setMenuSize({ width, height });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
48
68
|
const handleCopyMessage = async (text: string) => {
|
|
49
69
|
try {
|
|
50
70
|
await Clipboard.setStringAsync(text);
|
|
@@ -71,20 +91,44 @@ const MessageInteractions: React.FC<MessageInteractionsProps> = ({
|
|
|
71
91
|
};
|
|
72
92
|
|
|
73
93
|
const memoPosition = useMemo(() => {
|
|
74
|
-
if (position) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
if (!position) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!menuSize.width || !menuSize.height) {
|
|
99
|
+
return { top: position.bottom, left: position.left, opacity: 0 };
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { width: screenWidth, height: screenHeight } =
|
|
103
|
+
Dimensions.get('window');
|
|
104
|
+
const bottomReserve = (config?.keyboardVerticalOffset ?? 0) + 24;
|
|
105
|
+
const topReserve = 16;
|
|
106
|
+
const sideMargin = 8;
|
|
107
|
+
|
|
108
|
+
const spaceBelow = screenHeight - position.bottom - bottomReserve;
|
|
109
|
+
const spaceAbove = position.top - topReserve;
|
|
110
|
+
|
|
111
|
+
let top: number;
|
|
112
|
+
if (spaceBelow >= menuSize.height) {
|
|
113
|
+
top = position.bottom;
|
|
114
|
+
} else if (spaceAbove >= menuSize.height) {
|
|
115
|
+
top = position.top - menuSize.height;
|
|
116
|
+
} else {
|
|
117
|
+
top = Math.max(topReserve, screenHeight - menuSize.height - bottomReserve);
|
|
86
118
|
}
|
|
87
|
-
|
|
119
|
+
|
|
120
|
+
const leftMargin = position.left;
|
|
121
|
+
const rightMargin = screenWidth - position.right;
|
|
122
|
+
const rightAligned = rightMargin < leftMargin;
|
|
123
|
+
|
|
124
|
+
let left = rightAligned ? position.right - menuSize.width : position.left;
|
|
125
|
+
left = Math.max(
|
|
126
|
+
sideMargin,
|
|
127
|
+
Math.min(left, screenWidth - menuSize.width - sideMargin)
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
return { top, left };
|
|
131
|
+
}, [position, menuSize, config?.keyboardVerticalOffset]);
|
|
88
132
|
|
|
89
133
|
if (config?.disableInteractions) {return null;}
|
|
90
134
|
|
|
@@ -98,21 +142,32 @@ const MessageInteractions: React.FC<MessageInteractionsProps> = ({
|
|
|
98
142
|
{!message.isDeleted && (
|
|
99
143
|
<View style={styles.overlayFill}>
|
|
100
144
|
<Pressable style={StyleSheet.absoluteFill} onPress={closeMenu} />
|
|
101
|
-
<View
|
|
145
|
+
<View
|
|
146
|
+
style={[styles.contextMenu, memoPosition]}
|
|
147
|
+
onLayout={handleMenuLayout}
|
|
148
|
+
>
|
|
102
149
|
<MenuItem onPress={() => handleCopyMessage(message.body!)}>
|
|
103
|
-
<Text>{MESSAGE_INTERACTIONS.COPY}</Text>
|
|
150
|
+
<Text style={styles.menuText}>{MESSAGE_INTERACTIONS.COPY}</Text>
|
|
104
151
|
<MESSAGE_INTERACTIONS_ICONS.COPY />
|
|
105
152
|
</MenuItem>
|
|
106
153
|
{isUser && (
|
|
107
154
|
<>
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
155
|
+
{/* Edit only for non-media messages (upstream guard) +
|
|
156
|
+
consistent label styling (menuText). */}
|
|
157
|
+
{message?.isMediafile !== 'true' && (
|
|
158
|
+
<>
|
|
159
|
+
<Delimeter />
|
|
160
|
+
<MenuItem onPress={handleEditMessage}>
|
|
161
|
+
<Text style={styles.menuText}>
|
|
162
|
+
{MESSAGE_INTERACTIONS.EDIT}
|
|
163
|
+
</Text>
|
|
164
|
+
<MESSAGE_INTERACTIONS_ICONS.EDIT />
|
|
165
|
+
</MenuItem>
|
|
166
|
+
</>
|
|
167
|
+
)}
|
|
113
168
|
<Delimeter />
|
|
114
169
|
<MenuItem onPress={handleDeleteMessage}>
|
|
115
|
-
<Text>{MESSAGE_INTERACTIONS.DELETE}</Text>
|
|
170
|
+
<Text style={styles.menuText}>{MESSAGE_INTERACTIONS.DELETE}</Text>
|
|
116
171
|
<MESSAGE_INTERACTIONS_ICONS.DELETE />
|
|
117
172
|
</MenuItem>
|
|
118
173
|
</>
|
|
@@ -135,14 +190,28 @@ const styles = StyleSheet.create({
|
|
|
135
190
|
contextMenu: {
|
|
136
191
|
position: 'absolute',
|
|
137
192
|
backgroundColor: 'white',
|
|
138
|
-
paddingVertical:
|
|
139
|
-
paddingHorizontal:
|
|
140
|
-
borderRadius:
|
|
193
|
+
paddingVertical: 4,
|
|
194
|
+
paddingHorizontal: 8,
|
|
195
|
+
borderRadius: 12,
|
|
141
196
|
shadowColor: '#000',
|
|
142
197
|
shadowOffset: { width: 0, height: 2 },
|
|
143
|
-
shadowOpacity: 0.
|
|
144
|
-
shadowRadius:
|
|
145
|
-
elevation:
|
|
198
|
+
shadowOpacity: 0.18,
|
|
199
|
+
shadowRadius: 8,
|
|
200
|
+
elevation: 6,
|
|
146
201
|
minWidth: 180,
|
|
202
|
+
// Clip the children to the rounded corners (the hairline dividers
|
|
203
|
+
// run full width; without this they'd poke past the rounding on
|
|
204
|
+
// Android).
|
|
205
|
+
overflow: 'hidden',
|
|
206
|
+
},
|
|
207
|
+
// Explicit label styling so rows are the same height on both platforms
|
|
208
|
+
// — Android's default includeFontPadding made the menu rows taller and
|
|
209
|
+
// misaligned vs iOS. marginRight keeps the label off the trailing icon.
|
|
210
|
+
menuText: {
|
|
211
|
+
fontSize: 16,
|
|
212
|
+
color: '#141414',
|
|
213
|
+
includeFontPadding: false,
|
|
214
|
+
textAlignVertical: 'center',
|
|
215
|
+
marginRight: 16,
|
|
147
216
|
},
|
|
148
217
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @format */
|
|
2
2
|
|
|
3
|
-
import React from 'react';
|
|
3
|
+
import React, { useRef } from 'react';
|
|
4
4
|
import {
|
|
5
5
|
Modal,
|
|
6
6
|
Platform,
|
|
@@ -28,9 +28,22 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
28
28
|
onDocument,
|
|
29
29
|
primaryColor = '#0052CD',
|
|
30
30
|
}) => {
|
|
31
|
+
const pendingRef = useRef<(() => void) | null>(null);
|
|
32
|
+
|
|
33
|
+
const runPending = () => {
|
|
34
|
+
const fn = pendingRef.current;
|
|
35
|
+
pendingRef.current = null;
|
|
36
|
+
fn?.();
|
|
37
|
+
};
|
|
38
|
+
|
|
31
39
|
const trigger = (handler: () => void) => () => {
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
if (Platform.OS === 'ios') {
|
|
41
|
+
pendingRef.current = handler;
|
|
42
|
+
onClose();
|
|
43
|
+
} else {
|
|
44
|
+
onClose();
|
|
45
|
+
setTimeout(handler, 150);
|
|
46
|
+
}
|
|
34
47
|
};
|
|
35
48
|
|
|
36
49
|
const rows: {
|
|
@@ -65,6 +78,7 @@ const AttachSheet: React.FC<AttachSheetProps> = ({
|
|
|
65
78
|
visible={visible}
|
|
66
79
|
animationType="slide"
|
|
67
80
|
onRequestClose={onClose}
|
|
81
|
+
onDismiss={runPending}
|
|
68
82
|
>
|
|
69
83
|
<TouchableOpacity
|
|
70
84
|
style={styles.backdrop}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { ActivityIndicator, StyleSheet, Text, View } from 'react-native';
|
|
3
|
+
import { WebView } from 'react-native-webview';
|
|
4
|
+
|
|
5
|
+
interface DocumentViewerProps {
|
|
6
|
+
/** Public CDN URL of the doc. Must be reachable from Google's servers. */
|
|
7
|
+
url: string;
|
|
8
|
+
/** Optional display filename; used for the error fallback only. */
|
|
9
|
+
fileName?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Inline preview for office documents (DOC / DOCX / XLS / XLSX / PPT /
|
|
14
|
+
* PPTX / TXT / RTF / CSV) and other non-PDF formats supported by
|
|
15
|
+
* Google's free gview rendering service.
|
|
16
|
+
*
|
|
17
|
+
* Strategy: embed `https://docs.google.com/gview?url=<encoded>&embedded=true`
|
|
18
|
+
* inside a WebView. Google fetches the doc from its public URL and
|
|
19
|
+
* renders it to a viewable iframe — no client-side dependency on
|
|
20
|
+
* native office libraries, no extra peer dep. Works for any backend
|
|
21
|
+
* whose file URLs are publicly reachable (which Ethora's `/files/`
|
|
22
|
+
* already are — they're CDN URLs returned in `item.location`).
|
|
23
|
+
*
|
|
24
|
+
* Limitations (documented for the integrator):
|
|
25
|
+
* - Requires public URL — won't work for auth-gated downloads.
|
|
26
|
+
* - First load can take 2-5s on slow networks.
|
|
27
|
+
* - Read-only — no editing, no print/share buttons.
|
|
28
|
+
*
|
|
29
|
+
* For PDFs use the existing PdfViewer (downloads then renders locally).
|
|
30
|
+
*/
|
|
31
|
+
const DocumentViewer: React.FC<DocumentViewerProps> = ({ url, fileName }) => {
|
|
32
|
+
const [loaded, setLoaded] = useState(false);
|
|
33
|
+
const [errored, setErrored] = useState(false);
|
|
34
|
+
|
|
35
|
+
const viewerUrl = `https://docs.google.com/gview?url=${encodeURIComponent(
|
|
36
|
+
url
|
|
37
|
+
)}&embedded=true`;
|
|
38
|
+
|
|
39
|
+
if (errored) {
|
|
40
|
+
return (
|
|
41
|
+
<View style={styles.center}>
|
|
42
|
+
<Text style={styles.errorTitle}>
|
|
43
|
+
{fileName || 'Document'}
|
|
44
|
+
</Text>
|
|
45
|
+
<Text style={styles.errorBody}>
|
|
46
|
+
Couldn't render an inline preview. Tap the save icon above to
|
|
47
|
+
download the file.
|
|
48
|
+
</Text>
|
|
49
|
+
</View>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<View style={styles.container}>
|
|
55
|
+
<WebView
|
|
56
|
+
source={{ uri: viewerUrl }}
|
|
57
|
+
style={styles.webview}
|
|
58
|
+
originWhitelist={['*']}
|
|
59
|
+
startInLoadingState
|
|
60
|
+
onLoadEnd={() => setLoaded(true)}
|
|
61
|
+
onError={() => setErrored(true)}
|
|
62
|
+
onHttpError={() => setErrored(true)}
|
|
63
|
+
/>
|
|
64
|
+
{!loaded && (
|
|
65
|
+
<View style={styles.loadingOverlay} pointerEvents="none">
|
|
66
|
+
<ActivityIndicator size="large" />
|
|
67
|
+
</View>
|
|
68
|
+
)}
|
|
69
|
+
</View>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default DocumentViewer;
|
|
74
|
+
|
|
75
|
+
const styles = StyleSheet.create({
|
|
76
|
+
container: { flex: 1, width: '100%', backgroundColor: '#fff' },
|
|
77
|
+
webview: { flex: 1, backgroundColor: '#fff' },
|
|
78
|
+
loadingOverlay: {
|
|
79
|
+
...StyleSheet.absoluteFillObject,
|
|
80
|
+
justifyContent: 'center',
|
|
81
|
+
alignItems: 'center',
|
|
82
|
+
backgroundColor: '#ffffff',
|
|
83
|
+
},
|
|
84
|
+
center: {
|
|
85
|
+
flex: 1,
|
|
86
|
+
alignItems: 'center',
|
|
87
|
+
justifyContent: 'center',
|
|
88
|
+
padding: 24,
|
|
89
|
+
gap: 8,
|
|
90
|
+
},
|
|
91
|
+
errorTitle: { fontSize: 16, fontWeight: '600' },
|
|
92
|
+
errorBody: { color: '#666', textAlign: 'center' },
|
|
93
|
+
});
|