@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
|
@@ -2,18 +2,43 @@ import { createSlice, PayloadAction, type Slice } from '@reduxjs/toolkit';
|
|
|
2
2
|
import type { WritableDraft } from 'immer';
|
|
3
3
|
import { IMessage } from '../types/types';
|
|
4
4
|
|
|
5
|
+
// Saved alongside a failed-message id so the retry button can resend
|
|
6
|
+
// without the bubble needing to remember the original draft itself.
|
|
7
|
+
// `kind === 'text'` carries the plain body; `kind === 'media'` carries
|
|
8
|
+
// the upload payload so we don't have to make the user re-pick the file.
|
|
9
|
+
export type FailedMessagePayload =
|
|
10
|
+
| {
|
|
11
|
+
kind: 'text';
|
|
12
|
+
id: string;
|
|
13
|
+
roomJID: string;
|
|
14
|
+
body: string;
|
|
15
|
+
isReply?: boolean;
|
|
16
|
+
isChecked?: boolean;
|
|
17
|
+
mainMessage?: string;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
kind: 'media';
|
|
21
|
+
id: string;
|
|
22
|
+
roomJID: string;
|
|
23
|
+
data: any;
|
|
24
|
+
type: string;
|
|
25
|
+
isReply?: boolean;
|
|
26
|
+
isChecked?: boolean;
|
|
27
|
+
mainMessage?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
5
30
|
export interface roomHeapSliceState {
|
|
6
31
|
messageHeap: IMessage[];
|
|
32
|
+
// Keyed by message id so the bubble's `isFailed = failedMessages[id]`
|
|
33
|
+
// check is O(1). Carries enough payload data to actually retry.
|
|
34
|
+
failedMessages: Record<string, FailedMessagePayload>;
|
|
7
35
|
}
|
|
8
36
|
|
|
9
37
|
const initialState: roomHeapSliceState = {
|
|
10
38
|
messageHeap: [],
|
|
39
|
+
failedMessages: {},
|
|
11
40
|
};
|
|
12
41
|
|
|
13
|
-
// Reducers extracted as a named const so we can give the slice an
|
|
14
|
-
// explicit Slice<State, typeof reducers, Name> type. Without that, tsc's
|
|
15
|
-
// declaration emission inlines immer's internal WritableNonArrayDraft
|
|
16
|
-
// type and fails with TS4023.
|
|
17
42
|
const reducers = {
|
|
18
43
|
addMessageToHeap: (state: WritableDraft<roomHeapSliceState>, action: PayloadAction<IMessage>) => {
|
|
19
44
|
state.messageHeap.push(action.payload);
|
|
@@ -26,6 +51,22 @@ const reducers = {
|
|
|
26
51
|
},
|
|
27
52
|
clearHeap: (state: WritableDraft<roomHeapSliceState>) => {
|
|
28
53
|
state.messageHeap = [];
|
|
54
|
+
state.failedMessages = {};
|
|
55
|
+
},
|
|
56
|
+
markMessageFailed: (
|
|
57
|
+
state: WritableDraft<roomHeapSliceState>,
|
|
58
|
+
action: PayloadAction<FailedMessagePayload>
|
|
59
|
+
) => {
|
|
60
|
+
state.failedMessages[action.payload.id] = action.payload;
|
|
61
|
+
// Drop from the pending heap — the bubble looks at both, and
|
|
62
|
+
// showing "sending..." alongside a failure indicator is confusing.
|
|
63
|
+
const index = state.messageHeap.findIndex((m) => m.id === action.payload.id);
|
|
64
|
+
if (index !== -1) {
|
|
65
|
+
state.messageHeap.splice(index, 1);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
clearMessageFailure: (state: WritableDraft<roomHeapSliceState>, action: PayloadAction<string>) => {
|
|
69
|
+
delete state.failedMessages[action.payload];
|
|
29
70
|
},
|
|
30
71
|
};
|
|
31
72
|
|
|
@@ -39,6 +80,8 @@ export const {
|
|
|
39
80
|
addMessageToHeap,
|
|
40
81
|
clearHeap,
|
|
41
82
|
removeMessageFromHeapById,
|
|
83
|
+
markMessageFailed,
|
|
84
|
+
clearMessageFailure,
|
|
42
85
|
} = roomHeapSlice.actions;
|
|
43
86
|
|
|
44
87
|
export default roomHeapSlice.reducer;
|
|
@@ -23,6 +23,64 @@ const enforceMessageCap = (messages: IMessage[]): void => {
|
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
+
// Merge a freshly-fetched recent history page into a room's cached
|
|
27
|
+
// messages instead of REPLACING them — so re-entering the app no longer
|
|
28
|
+
// wipes older history (and the unread derived from it). Mirrors the web
|
|
29
|
+
// SDK's incremental sync:
|
|
30
|
+
// • union + dedupe by message id (the server-authoritative,
|
|
31
|
+
// microsecond-resolution stanza id) — overlapping messages collapse
|
|
32
|
+
// and older cached history is kept;
|
|
33
|
+
// • if the fetched page shares NO id with the cache, a gap has opened
|
|
34
|
+
// (more than a page of new messages arrived while away) and stitching
|
|
35
|
+
// them would leave a hole — so we clear THIS chat's cache and keep
|
|
36
|
+
// just the fresh page;
|
|
37
|
+
// • locally-pending (optimistic) sends are always preserved;
|
|
38
|
+
// • an empty fetch leaves the cache untouched (the old replace wiped it);
|
|
39
|
+
// • the transient 'delimiter-new' marker is dropped (the realtime insert
|
|
40
|
+
// path re-derives it) so it can't mis-sort.
|
|
41
|
+
// `function` (hoisted) so the reducers above can call it regardless of
|
|
42
|
+
// where it sits in the file. msgSortableMs (defined below) is referenced
|
|
43
|
+
// at call time, after module init.
|
|
44
|
+
function mergeHistoryIntoCache(
|
|
45
|
+
existing: IMessage[] | undefined,
|
|
46
|
+
fetched: IMessage[] | undefined
|
|
47
|
+
): IMessage[] {
|
|
48
|
+
const ex = Array.isArray(existing) ? existing : [];
|
|
49
|
+
const fe = Array.isArray(fetched) ? fetched : [];
|
|
50
|
+
|
|
51
|
+
const pending = ex.filter((m) => m?.pending);
|
|
52
|
+
const realExisting = ex.filter(
|
|
53
|
+
(m) => m && !m.pending && m.id !== 'delimiter-new'
|
|
54
|
+
);
|
|
55
|
+
const realFetched = fe.filter((m) => m && m.id !== 'delimiter-new');
|
|
56
|
+
|
|
57
|
+
// Nothing usable came back → keep the cache exactly as it was.
|
|
58
|
+
if (realFetched.length === 0) {return ex;}
|
|
59
|
+
|
|
60
|
+
const byMs = (a: IMessage, b: IMessage) =>
|
|
61
|
+
msgSortableMs(a) - msgSortableMs(b);
|
|
62
|
+
const capTail = (arr: IMessage[]) =>
|
|
63
|
+
arr.length > RUNTIME_MESSAGE_LIMIT
|
|
64
|
+
? arr.slice(-RUNTIME_MESSAGE_LIMIT)
|
|
65
|
+
: arr;
|
|
66
|
+
|
|
67
|
+
const existingIds = new Set(realExisting.map((m) => String(m.id)));
|
|
68
|
+
const overlaps = realFetched.some((m) => existingIds.has(String(m.id)));
|
|
69
|
+
|
|
70
|
+
// Cold room, or a gap (no shared id) → can't merge → use the fresh page.
|
|
71
|
+
if (realExisting.length === 0 || !overlaps) {
|
|
72
|
+
return [...capTail(realFetched.slice().sort(byMs)), ...pending];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Overlap → union + dedupe by id. Fetched wins on collision: it carries
|
|
76
|
+
// the freshest server state (reactions / edits / deletions).
|
|
77
|
+
const byId = new Map<string, IMessage>();
|
|
78
|
+
for (const m of realExisting) {byId.set(String(m.id), m);}
|
|
79
|
+
for (const m of realFetched) {byId.set(String(m.id), m);}
|
|
80
|
+
const merged = Array.from(byId.values()).sort(byMs);
|
|
81
|
+
return [...capTail(merged), ...pending];
|
|
82
|
+
}
|
|
83
|
+
|
|
26
84
|
export interface RoomPreloadPatch {
|
|
27
85
|
jid: string;
|
|
28
86
|
messages?: IMessage[];
|
|
@@ -34,6 +92,7 @@ export interface RoomPreloadPatch {
|
|
|
34
92
|
export interface RoomMessagesState {
|
|
35
93
|
rooms: { [jid: string]: IRoom };
|
|
36
94
|
activeRoomJID: string | null;
|
|
95
|
+
visibleRoomJID: string | null;
|
|
37
96
|
editAction?: EditAction;
|
|
38
97
|
isLoading: boolean;
|
|
39
98
|
loadingText?: string;
|
|
@@ -44,6 +103,7 @@ export interface RoomMessagesState {
|
|
|
44
103
|
const initialState: RoomMessagesState = {
|
|
45
104
|
rooms: {},
|
|
46
105
|
activeRoomJID: null,
|
|
106
|
+
visibleRoomJID: null,
|
|
47
107
|
isLoading: false,
|
|
48
108
|
editAction: {
|
|
49
109
|
isEdit: false,
|
|
@@ -79,22 +139,77 @@ const reducers = {
|
|
|
79
139
|
addRoom(state: WritableDraft<RoomMessagesState>, action: PayloadAction<{ roomData: IRoom }>) {
|
|
80
140
|
const { roomData } = action.payload;
|
|
81
141
|
const existing = state.rooms[roomData.jid];
|
|
82
|
-
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
142
|
+
// Default-marker resolution (cold-start unread bug):
|
|
143
|
+
// 1. Explicit value on the payload wins.
|
|
144
|
+
// 2. Existing redux value wins (preserves persisted/hydrated
|
|
145
|
+
// markers when the privateStore pull lands before
|
|
146
|
+
// /chats/my).
|
|
147
|
+
// 3. Otherwise, anchor to the *newest known message* in the
|
|
148
|
+
// payload — this marks everything currently in the room
|
|
149
|
+
// as "seen" but lets any NEWER incoming message count as
|
|
150
|
+
// unread. Previously this fell back to `Date.now()`, which
|
|
151
|
+
// stamped a future-leaning marker that hid genuinely-new
|
|
152
|
+
// messages received while the app was closed.
|
|
153
|
+
// 4. If there are no messages at all yet, stamp `0` (=
|
|
154
|
+
// "unknown — let the privateStore hydration set the real
|
|
155
|
+
// marker before any future message arrives").
|
|
156
|
+
let lastViewed: number;
|
|
157
|
+
// Treat an incoming `0` as "unset". stanzaHandlers' addRoom passes
|
|
158
|
+
// `lastViewedTimestamp: 0` as a placeholder; the old `!= null` check
|
|
159
|
+
// let that 0 win and OVERWROTE the persisted/hydrated marker from
|
|
160
|
+
// the previous session, so cold-start showed no unread badge for
|
|
161
|
+
// messages received while the app was closed (bug #19/#20). A real
|
|
162
|
+
// (non-zero) explicit value still wins; otherwise keep the existing
|
|
163
|
+
// value; otherwise anchor to the newest message in the payload.
|
|
164
|
+
if (roomData.lastViewedTimestamp != null && roomData.lastViewedTimestamp !== 0) {
|
|
165
|
+
lastViewed = roomData.lastViewedTimestamp;
|
|
166
|
+
} else if (existing?.lastViewedTimestamp != null) {
|
|
167
|
+
lastViewed = existing.lastViewedTimestamp;
|
|
168
|
+
} else {
|
|
169
|
+
const msgs = roomData.messages || [];
|
|
170
|
+
let newest = 0;
|
|
171
|
+
for (const m of msgs) {
|
|
172
|
+
const t = (m as any)?.messageTimestampMs ||
|
|
173
|
+
(m?.date ? new Date(m.date).getTime() : 0);
|
|
174
|
+
if (t > newest) {newest = t;}
|
|
175
|
+
}
|
|
176
|
+
lastViewed = newest; // 0 if no messages → cold-start safe
|
|
177
|
+
}
|
|
178
|
+
// Preserve cached messages + unread when the incoming room carries
|
|
179
|
+
// none. The /chats/my fetch (rooms.api) builds rooms with
|
|
180
|
+
// `messages: []` and no unread; without this guard, re-entering the
|
|
181
|
+
// app replaced every cached room with an empty one — wiping history
|
|
182
|
+
// AND the unread badge before the history scheduler could re-merge
|
|
183
|
+
// (the user's "it clears cache, unread and messages" bug). New rooms
|
|
184
|
+
// (no existing) fall through to the incoming values. Mirrors
|
|
185
|
+
// addRoomFromApi's preservation.
|
|
186
|
+
const incomingMessages = Array.isArray(roomData.messages)
|
|
187
|
+
? roomData.messages
|
|
188
|
+
: [];
|
|
189
|
+
const existingMessages = Array.isArray(existing?.messages)
|
|
190
|
+
? existing!.messages
|
|
191
|
+
: [];
|
|
192
|
+
state.rooms[roomData.jid] = {
|
|
193
|
+
...roomData,
|
|
194
|
+
messages:
|
|
195
|
+
existingMessages.length > 0 ? existingMessages : incomingMessages,
|
|
196
|
+
lastViewedTimestamp: lastViewed,
|
|
197
|
+
unreadMessages:
|
|
198
|
+
roomData.unreadMessages ?? existing?.unreadMessages ?? 0,
|
|
199
|
+
unreadBaselineTimestamp:
|
|
200
|
+
existing?.unreadBaselineTimestamp ??
|
|
201
|
+
existing?.lastViewedTimestamp ??
|
|
202
|
+
(roomData as any).unreadBaselineTimestamp ??
|
|
203
|
+
0,
|
|
204
|
+
};
|
|
93
205
|
},
|
|
94
206
|
deleteRoom(state: WritableDraft<RoomMessagesState>, action: PayloadAction<{ jid: string }>) {
|
|
95
207
|
const { jid } = action.payload;
|
|
96
208
|
if (state.rooms[jid]) {
|
|
97
209
|
delete state.rooms[jid];
|
|
210
|
+
if (state.visibleRoomJID === jid) {
|
|
211
|
+
state.visibleRoomJID = null;
|
|
212
|
+
}
|
|
98
213
|
}
|
|
99
214
|
},
|
|
100
215
|
updateRoom(
|
|
@@ -132,13 +247,23 @@ const reducers = {
|
|
|
132
247
|
action: PayloadAction<{ roomJID: string; messageId: string }>
|
|
133
248
|
) {
|
|
134
249
|
const { roomJID, messageId } = action.payload;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
250
|
+
const room = state.rooms[roomJID];
|
|
251
|
+
if (!room?.messages) {return;}
|
|
252
|
+
// The "New messages" divider is a transient UI marker, not a real
|
|
253
|
+
// message — SPLICE it out so it can be re-inserted for the next
|
|
254
|
+
// unread batch. Marking it isDeleted (like a real message) left it in
|
|
255
|
+
// the array, where insertMessageWithDelimiter's "already present"
|
|
256
|
+
// guard then blocked every future divider (one-shot bug).
|
|
257
|
+
if (messageId === 'delimiter-new') {
|
|
258
|
+
const idx = room.messages.findIndex((m) => m.id === 'delimiter-new');
|
|
259
|
+
if (idx !== -1) {room.messages.splice(idx, 1);}
|
|
260
|
+
return;
|
|
141
261
|
}
|
|
262
|
+
room.messages.map((message) => {
|
|
263
|
+
if (message.id === messageId) {
|
|
264
|
+
message.isDeleted = true;
|
|
265
|
+
}
|
|
266
|
+
});
|
|
142
267
|
},
|
|
143
268
|
setEditAction: (state: WritableDraft<RoomMessagesState>, action: PayloadAction<EditAction | undefined>) => {
|
|
144
269
|
if (action.payload?.isEdit) {
|
|
@@ -199,9 +324,13 @@ const reducers = {
|
|
|
199
324
|
if (roomMessages.length === 0 || start) {
|
|
200
325
|
roomMessages.unshift(message);
|
|
201
326
|
} else {
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
327
|
+
const lastViewedValue = state.rooms[roomJID].lastViewedTimestamp;
|
|
328
|
+
const lastViewedTimestamp =
|
|
329
|
+
state.visibleRoomJID === roomJID
|
|
330
|
+
? null
|
|
331
|
+
: lastViewedValue
|
|
332
|
+
? new Date(lastViewedValue)
|
|
333
|
+
: null;
|
|
205
334
|
|
|
206
335
|
insertMessageWithDelimiter(roomMessages, message, lastViewedTimestamp);
|
|
207
336
|
}
|
|
@@ -216,6 +345,7 @@ const reducers = {
|
|
|
216
345
|
},
|
|
217
346
|
deleteAllRooms(state: WritableDraft<RoomMessagesState>) {
|
|
218
347
|
state.rooms = {};
|
|
348
|
+
state.visibleRoomJID = null;
|
|
219
349
|
},
|
|
220
350
|
setComposing(
|
|
221
351
|
state: WritableDraft<RoomMessagesState>,
|
|
@@ -247,10 +377,12 @@ const reducers = {
|
|
|
247
377
|
const { chatJID, timestamp } = action.payload;
|
|
248
378
|
if (state.rooms[chatJID]) {
|
|
249
379
|
state.rooms[chatJID].lastViewedTimestamp = timestamp;
|
|
250
|
-
//
|
|
251
|
-
// unread
|
|
252
|
-
//
|
|
253
|
-
|
|
380
|
+
// A non-positive timestamp means "no persisted marker yet" and
|
|
381
|
+
// must not inflate unread from history that predates the first
|
|
382
|
+
// successful private-store hydration. The visible-room state is
|
|
383
|
+
// tracked separately via `visibleRoomJID`; no read/unread meaning
|
|
384
|
+
// is encoded in the timestamp itself anymore.
|
|
385
|
+
if (!(timestamp > 0)) {
|
|
254
386
|
state.rooms[chatJID].unreadMessages = 0;
|
|
255
387
|
} else {
|
|
256
388
|
state.rooms[chatJID].unreadMessages = countNewerMessages(
|
|
@@ -286,6 +418,19 @@ const reducers = {
|
|
|
286
418
|
// back button from chat → return to RoomList). Mirrors web.
|
|
287
419
|
state.activeRoomJID = action.payload.roomJID || '';
|
|
288
420
|
},
|
|
421
|
+
setVisibleRoom: (
|
|
422
|
+
state: WritableDraft<RoomMessagesState>,
|
|
423
|
+
action: PayloadAction<{ roomJID: string | null }>
|
|
424
|
+
) => {
|
|
425
|
+
state.visibleRoomJID = action.payload.roomJID || null;
|
|
426
|
+
const jid = state.visibleRoomJID;
|
|
427
|
+
if (jid && state.rooms[jid]) {
|
|
428
|
+
state.rooms[jid].unreadMessages = 0;
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
clearVisibleRoom: (state: WritableDraft<RoomMessagesState>) => {
|
|
432
|
+
state.visibleRoomJID = null;
|
|
433
|
+
},
|
|
289
434
|
/**
|
|
290
435
|
* Stash a JID that a push notification asked us to open before
|
|
291
436
|
* the rooms list has loaded. The Chat component clears this once
|
|
@@ -329,6 +474,7 @@ const reducers = {
|
|
|
329
474
|
setLogoutState: (state: WritableDraft<RoomMessagesState>) => {
|
|
330
475
|
state.rooms = {};
|
|
331
476
|
state.activeRoomJID = null;
|
|
477
|
+
state.visibleRoomJID = null;
|
|
332
478
|
state.isLoading = false;
|
|
333
479
|
},
|
|
334
480
|
setActiveMessage: (
|
|
@@ -425,9 +571,11 @@ const reducers = {
|
|
|
425
571
|
room.historyComplete = patch.historyComplete;
|
|
426
572
|
}
|
|
427
573
|
if (Array.isArray(patch.messages)) {
|
|
428
|
-
// Merge
|
|
429
|
-
|
|
430
|
-
|
|
574
|
+
// Merge the fetched page into cache by message id rather than
|
|
575
|
+
// replacing — preserves older history + unread on re-entry. Only
|
|
576
|
+
// a true gap (no overlapping id) clears this chat's cache. See
|
|
577
|
+
// mergeHistoryIntoCache.
|
|
578
|
+
room.messages = mergeHistoryIntoCache(room.messages, patch.messages);
|
|
431
579
|
}
|
|
432
580
|
}
|
|
433
581
|
},
|
|
@@ -521,6 +669,8 @@ export const {
|
|
|
521
669
|
setLastViewedTimestamp,
|
|
522
670
|
setRoomNoMessages,
|
|
523
671
|
setCurrentRoom,
|
|
672
|
+
setVisibleRoom,
|
|
673
|
+
clearVisibleRoom,
|
|
524
674
|
setRoomRole,
|
|
525
675
|
setLogoutState,
|
|
526
676
|
setActiveMessage,
|
package/src/types/types.ts
CHANGED
|
@@ -249,6 +249,19 @@ export interface IConfig {
|
|
|
249
249
|
disableHeader?: boolean;
|
|
250
250
|
disableMedia?: boolean;
|
|
251
251
|
chatHeaderBurgerMenu?: boolean;
|
|
252
|
+
// Hide the burger icon entirely (the icon that opens the chatHeader-
|
|
253
|
+
// BurgerMenu dropdown). `chatHeaderBurgerMenu` controls dropdown
|
|
254
|
+
// visibility only — set this flag when you want neither the icon nor
|
|
255
|
+
// the dropdown to render (e.g. patient-facing apps with a single room).
|
|
256
|
+
disableChatHeaderBurgerMenuIcon?: boolean;
|
|
257
|
+
// ----- granular gates inside the user-profile modal (chat info →
|
|
258
|
+
// tap a member). Use these to keep the profile section visible
|
|
259
|
+
// but hide individual actions that aren't appropriate for the
|
|
260
|
+
// embedding app (e.g. patient-facing apps that don't allow
|
|
261
|
+
// direct messaging between patients).
|
|
262
|
+
disableMemberProfileActions?: boolean; // hides the whole action block
|
|
263
|
+
hideMemberSendMessageAction?: boolean; // hides only "Message"
|
|
264
|
+
hideMemberCopyIdAction?: boolean; // hides only "Copy User Id"
|
|
252
265
|
chatHeaderAdditional?: { enabled: boolean; element: any };
|
|
253
266
|
headerMenu?: () => void;
|
|
254
267
|
headerChatMenu?: () => void;
|
|
@@ -341,6 +354,13 @@ export interface IConfig {
|
|
|
341
354
|
disableUserCount?: boolean;
|
|
342
355
|
disableSentLogic?: boolean;
|
|
343
356
|
disableTypingIndicator?: boolean;
|
|
357
|
+
// Hide the full-screen "Connection error" overlay (the dark modal with
|
|
358
|
+
// a Retry button shown when bootstrap/connect fails). For patient-facing
|
|
359
|
+
// / kiosk apps where a full-screen error reads as a crash, set this and
|
|
360
|
+
// surface connection state your own way (or let it recover silently —
|
|
361
|
+
// reconnect + re-join now happen automatically). A subtle inline
|
|
362
|
+
// "Connection lost. Retrying…" banner is shown instead.
|
|
363
|
+
disableConnectionErrorOverlay?: boolean;
|
|
344
364
|
// disableChatInfo already declared above (line ~338) — granular gates
|
|
345
365
|
// (disableHeader / disableDescription / disableType / hideMembers /
|
|
346
366
|
// disableMembers / disableChatHeaderMenu). Don't redeclare here.
|
|
@@ -420,6 +440,11 @@ export interface IConfig {
|
|
|
420
440
|
roomJID: string;
|
|
421
441
|
user: any;
|
|
422
442
|
}) => void;
|
|
443
|
+
onMessageRetry?: (event: {
|
|
444
|
+
messageId: string;
|
|
445
|
+
roomJID: string;
|
|
446
|
+
messageType: 'text' | 'media';
|
|
447
|
+
}) => void;
|
|
423
448
|
};
|
|
424
449
|
}
|
|
425
450
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dev-only unhandled-promise-rejection tracker.
|
|
3
|
+
*
|
|
4
|
+
* RN's red-screen for `Uncaught (in promise, id: N)` famously hides the
|
|
5
|
+
* actual rejection's stack trace — it only shows the promise id. When a
|
|
6
|
+
* leak slips past the SDK's coverage, the integrator gets a useless
|
|
7
|
+
* red box that they can't diagnose.
|
|
8
|
+
*
|
|
9
|
+
* This installer attaches a global `unhandledrejection` listener that
|
|
10
|
+
* prints the rejection value AND a stack trace (best-effort) so the
|
|
11
|
+
* source is visible in Metro logs. It's a no-op in production builds.
|
|
12
|
+
*
|
|
13
|
+
* Installed automatically from `ReduxWrapper` on mount. Safe to call
|
|
14
|
+
* multiple times — guarded by a module-level flag.
|
|
15
|
+
*
|
|
16
|
+
* Bug #4 follow-up.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare const __DEV__: boolean | undefined;
|
|
20
|
+
|
|
21
|
+
let installed = false;
|
|
22
|
+
|
|
23
|
+
export function installPromiseRejectionTracker() {
|
|
24
|
+
if (typeof __DEV__ !== 'undefined' && !__DEV__) {return;}
|
|
25
|
+
if (installed) {return;}
|
|
26
|
+
installed = true;
|
|
27
|
+
|
|
28
|
+
// RN's RCTPromise polyfill emits `unhandledrejection` on the global
|
|
29
|
+
// (HermesInternal / global). It also forwards through the
|
|
30
|
+
// `process.on('unhandledRejection', ...)` shim on some builds.
|
|
31
|
+
const g: any = globalThis as any;
|
|
32
|
+
|
|
33
|
+
const onRejection = (eventOrReason: any, maybePromise?: Promise<any>) => {
|
|
34
|
+
// Two calling conventions across RN versions:
|
|
35
|
+
// - `(event)` where event has `.reason` / `.promise`
|
|
36
|
+
// - `(reason, promise)` (older)
|
|
37
|
+
const reason = eventOrReason?.reason ?? eventOrReason;
|
|
38
|
+
const promise = eventOrReason?.promise ?? maybePromise;
|
|
39
|
+
const stack =
|
|
40
|
+
(reason && reason.stack) ||
|
|
41
|
+
new Error('unhandledrejection (captured at handler)').stack;
|
|
42
|
+
// console.WARN (not error): RN's LogBox turns every console.error into
|
|
43
|
+
// a full-screen red overlay. With `allRejections: true` Hermes reports
|
|
44
|
+
// rejections that get handled a microtask later (false positives, e.g.
|
|
45
|
+
// a bare `undefined` rejection during connect teardown), so escalating
|
|
46
|
+
// to a red box was pure noise. warn keeps the trace in Metro/Logs.
|
|
47
|
+
// eslint-disable-next-line no-console
|
|
48
|
+
console.warn(
|
|
49
|
+
'[ethora-rn] UNHANDLED PROMISE REJECTION:',
|
|
50
|
+
typeof reason === 'object' ? JSON.stringify(reason, null, 2) : String(reason),
|
|
51
|
+
'\nstack:',
|
|
52
|
+
stack,
|
|
53
|
+
'\npromise:',
|
|
54
|
+
promise
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
if (typeof g.addEventListener === 'function') {
|
|
60
|
+
g.addEventListener('unhandledrejection', onRejection);
|
|
61
|
+
}
|
|
62
|
+
} catch {}
|
|
63
|
+
try {
|
|
64
|
+
if (g.process && typeof g.process.on === 'function') {
|
|
65
|
+
g.process.on('unhandledRejection', onRejection);
|
|
66
|
+
}
|
|
67
|
+
} catch {}
|
|
68
|
+
try {
|
|
69
|
+
// Hermes-only hook — newer RN exposes this.
|
|
70
|
+
if (typeof g.HermesInternal?.enablePromiseRejectionTracker === 'function') {
|
|
71
|
+
g.HermesInternal.enablePromiseRejectionTracker({
|
|
72
|
+
allRejections: false,
|
|
73
|
+
onUnhandled: (id: number, error: any) => {
|
|
74
|
+
// warn, not error — see note above. `allRejections: true` fires
|
|
75
|
+
// this for rejections handled a tick later, so a red box here
|
|
76
|
+
// was a false alarm. Stays visible in Metro/Logs as a warning.
|
|
77
|
+
// eslint-disable-next-line no-console
|
|
78
|
+
console.warn(
|
|
79
|
+
`[ethora-rn] Hermes unhandled rejection id=${id}:`,
|
|
80
|
+
error?.message ?? error,
|
|
81
|
+
'\nstack:',
|
|
82
|
+
error?.stack
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
onHandled: () => {},
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
} catch {}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export default installPromiseRejectionTracker;
|
|
@@ -62,7 +62,8 @@ export async function resendMessage(
|
|
|
62
62
|
message.isReply || false,
|
|
63
63
|
message.showInChannel === 'true' || false,
|
|
64
64
|
message.mainMessage || '',
|
|
65
|
-
(state.chatSettingStore.langSource as any) || 'en'
|
|
65
|
+
(state.chatSettingStore.langSource as any) || 'en',
|
|
66
|
+
id
|
|
66
67
|
);
|
|
67
68
|
} else {
|
|
68
69
|
client.sendMessage(
|