@ethora/chat-component-rn 26.5.7 → 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 +133 -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/ChatRoom.js +64 -38
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +57 -13
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +4 -2
- 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/Message.js +84 -39
- 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 +140 -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/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 +4 -9
- 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/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 -14
- 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/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 +3 -3
- 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/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/ChatRoom.js +65 -39
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +57 -13
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +4 -2
- 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/Message.js +85 -40
- 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 +143 -25
- 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 +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 +4 -9
- 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/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 -15
- 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/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 +3 -3
- 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/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/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.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/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/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/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 +4 -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/ChatRoom.tsx +81 -66
- package/src/components/MainComponents/ChatWrapper.tsx +99 -21
- package/src/components/MainComponents/MediaMessage.tsx +3 -0
- 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/Message.tsx +91 -62
- 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 +152 -25
- 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 +70 -58
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -15
- package/src/components/Modals/styledModalComponents.tsx +4 -9
- 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/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 -11
- 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/normalizeRoomJid.ts +6 -0
- package/src/hooks/useChatRoomFocus.ts +95 -0
- package/src/hooks/useHeapSender.tsx +2 -1
- package/src/hooks/useLogout.tsx +3 -3
- 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/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 +15 -0
- package/src/utils/installPromiseRejectionTracker.ts +91 -0
- package/src/utils/resendMessage.ts +2 -1
|
@@ -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';
|
|
@@ -52,7 +51,9 @@ const CustomMessageBubble = styled.View<{
|
|
|
52
51
|
}>`
|
|
53
52
|
position: relative;
|
|
54
53
|
max-width: 85%;
|
|
55
|
-
min-width: 30
|
|
54
|
+
min-width: ${({ isMedia }) => (isMedia ? '0' : '30%')};
|
|
55
|
+
align-items: ${({ isMedia, isUser }) =>
|
|
56
|
+
isMedia ? (isUser ? 'flex-end' : 'flex-start') : 'stretch'};
|
|
56
57
|
padding: ${({isMedia}) => isMedia ? '0' : '10'}px;
|
|
57
58
|
padding-bottom: ${({isMedia}) => isMedia ? '6' : '10'}px;
|
|
58
59
|
margin-right: ${({isUser}) => isUser ? '0' : '10px'};
|
|
@@ -94,9 +95,12 @@ const CustomMessagePhotoContainer = styled.TouchableOpacity`
|
|
|
94
95
|
margin-right: 10px;
|
|
95
96
|
`;
|
|
96
97
|
|
|
97
|
-
const CustomUserName = styled.Text<{ color?: string }>`
|
|
98
|
+
const CustomUserName = styled.Text<{ color?: string; media: boolean }>`
|
|
98
99
|
font-size: 14px;
|
|
99
100
|
font-weight: 500;
|
|
101
|
+
padding-bottom: 8px;
|
|
102
|
+
padding-left: ${({media}) => media ? '16px': 0};
|
|
103
|
+
padding-top: ${({media}) => media ? '8px': 0};
|
|
100
104
|
color: ${({ color }) => color || '#333'};
|
|
101
105
|
`;
|
|
102
106
|
|
|
@@ -113,6 +117,15 @@ const CustomMessageTimestamp = styled.Text<{
|
|
|
113
117
|
align-self: flex-end;
|
|
114
118
|
`;
|
|
115
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
|
+
|
|
116
129
|
const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
117
130
|
const dispatch = useDispatch();
|
|
118
131
|
const { client } = useXmppClient();
|
|
@@ -127,12 +140,15 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
127
140
|
}
|
|
128
141
|
|
|
129
142
|
const [contextMenuPosition, setContextMenuPosition] = useState<{
|
|
130
|
-
|
|
131
|
-
|
|
143
|
+
left: number;
|
|
144
|
+
right: number;
|
|
145
|
+
top: number;
|
|
146
|
+
bottom: number;
|
|
132
147
|
} | null>(null);
|
|
133
148
|
|
|
134
149
|
const timerRef = useRef<NodeJS.Timeout | null>(null);
|
|
135
150
|
const messageRef = useRef<View>(null);
|
|
151
|
+
const bubbleRef = useRef<View>(null);
|
|
136
152
|
|
|
137
153
|
const handleUserAvatarClick = (user: IUser): void => {
|
|
138
154
|
dispatch(setActiveModal(MODAL_TYPES.PROFILE));
|
|
@@ -219,45 +235,23 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
219
235
|
);
|
|
220
236
|
};
|
|
221
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).
|
|
222
243
|
const handleLongPress = () => {
|
|
223
|
-
|
|
224
|
-
|
|
244
|
+
const target = bubbleRef.current ?? messageRef.current;
|
|
245
|
+
if (target) {
|
|
246
|
+
const nodeHandle = findNodeHandle(target);
|
|
225
247
|
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 });
|
|
248
|
+
UIManager.measure(nodeHandle, (_x, _y, width, height, pageX, pageY) => {
|
|
249
|
+
setContextMenuPosition({
|
|
250
|
+
left: pageX,
|
|
251
|
+
right: pageX + width,
|
|
252
|
+
top: pageY,
|
|
253
|
+
bottom: pageY + height,
|
|
254
|
+
});
|
|
261
255
|
});
|
|
262
256
|
}
|
|
263
257
|
}
|
|
@@ -307,6 +301,15 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
307
301
|
</CustomMessagePhotoContainer>
|
|
308
302
|
)}
|
|
309
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
|
+
}}
|
|
310
313
|
// disableInteractions hides the long-press → context menu
|
|
311
314
|
// (delete / edit / reply / react). Mirrors web's config gate.
|
|
312
315
|
onLongPress={
|
|
@@ -315,6 +318,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
315
318
|
delayLongPress={500}
|
|
316
319
|
>
|
|
317
320
|
<CustomMessageBubble
|
|
321
|
+
{...({ ref: bubbleRef, collapsable: false } as any)}
|
|
318
322
|
isUser={isUser}
|
|
319
323
|
deleted={message.isDeleted}
|
|
320
324
|
isMedia={message?.isMediafile === 'true' && !message?.isDeleted}
|
|
@@ -322,7 +326,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
322
326
|
backgroundMessage={config?.messageColor?.backgroundMessage}
|
|
323
327
|
>
|
|
324
328
|
{!isUser && (
|
|
325
|
-
<CustomUserName color={config?.colors?.primary}>
|
|
329
|
+
<CustomUserName color={config?.colors?.primary} media={message?.isMediafile === 'true'}>
|
|
326
330
|
{message.user.name}
|
|
327
331
|
</CustomUserName>
|
|
328
332
|
)}
|
|
@@ -341,6 +345,7 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
341
345
|
messageText={message.locationPreview}
|
|
342
346
|
location={message?.location}
|
|
343
347
|
message={message}
|
|
348
|
+
isUser={isUser}
|
|
344
349
|
/>
|
|
345
350
|
) : (
|
|
346
351
|
<>
|
|
@@ -364,26 +369,31 @@ const Message: React.FC<MessageProps> = ({ message, isUser, isReply }) => {
|
|
|
364
369
|
langSource={langSource}
|
|
365
370
|
/>
|
|
366
371
|
)}
|
|
367
|
-
<
|
|
368
|
-
{
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
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
|
+
})}
|
|
377
392
|
</Text>
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
})}
|
|
383
|
-
{!config?.disableSentLogic && isUser && !isPending && !isFailed && (
|
|
384
|
-
<DoubleTick />
|
|
385
|
-
)}
|
|
386
|
-
</CustomMessageTimestamp>
|
|
393
|
+
{!config?.disableSentLogic && isUser && !isPending && !isFailed && (
|
|
394
|
+
<DoubleTick />
|
|
395
|
+
)}
|
|
396
|
+
</CustomTimestampRow>
|
|
387
397
|
|
|
388
398
|
{message?.reply?.length && message?.reply?.length > 0 ? (
|
|
389
399
|
<BottomReplyContainer
|
|
@@ -455,4 +465,23 @@ const styles = StyleSheet.create({
|
|
|
455
465
|
fontWeight: '600',
|
|
456
466
|
marginRight: 6,
|
|
457
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
|
+
},
|
|
458
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
|
+
});
|