@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
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,139 @@
|
|
|
3
3
|
All notable changes to `@ethora/chat-component-rn` are listed here.
|
|
4
4
|
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this project doesn't follow strict semver yet — version corresponds to the `package.json` field.
|
|
5
5
|
|
|
6
|
+
## [26.5.10]
|
|
7
|
+
|
|
8
|
+
Lifecycle hardening on top of 26.5.9, driven by live on-device testing: a full reconnect-after-loss overhaul (a live test surfaced — and this release fixes — a reconnect storm), cache no longer wiped on re-entry, automatic AppState-driven unread visibility plus a new `isVisible` prop for tab hosts, `initBeforeLoad` auto-retry, and the "New messages" divider polish. Full regression sweep — typecheck clean, 583 jest tests green.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
#### Connectivity / reconnect (the big one)
|
|
13
|
+
|
|
14
|
+
- **Never permanently gives up.** `scheduleReconnect` used to hard-stop at `maxReconnectAttempts` (5) — ~62s, after which only a NetInfo/foreground event could revive the client. It now retries indefinitely while mounted, with the exponential backoff **clamped to `maxReconnectDelay` (30s)**.
|
|
15
|
+
- **Connect-time failures retry.** A failed `client.start()` lands in `status: 'error'`, which previously had no retry path (only a drop *after* being online did). It now schedules a backoff reconnect (refreshing creds first on a SASL `not-authorized`).
|
|
16
|
+
- **Reconnect storm fixed (found by the live bad-host test: 397 schedule calls / 0 actual reconnects / 3 orphan clients).** Three causes addressed: (a) the `initBeforeLoad` auto-retry no longer leaves orphan `XmppClient` instances — `initializeClient` closes the prior global client before creating a new one; (b) `scheduleReconnect` now coalesces — a burst of `disconnect` events no longer re-arms the timer faster than it can fire (which starved `reconnect()` and spammed the counter); (c) **`@xmpp/client`'s built-in reconnect is disabled** so this SDK is the single reconnect driver (no dual-layer ~1s socket storm against a dead host).
|
|
17
|
+
- **`forceReconnect` debounced (2s)** so NetInfo + AppState + the new watchdog firing together can't spawn a storm.
|
|
18
|
+
- **New foreground watchdog.** While the app is active, a 30s timer forces a reconnect when the client isn't online and reconnect isn't suppressed — covering a stuck `connecting`/`error` and server-side outages NetInfo never reports. Replaces the old provider reconnect effect, which keyed on `client.status` (a mutated class field React doesn't track) and so frequently never re-ran.
|
|
19
|
+
- **NetInfo reconnect loosened.** Forces a reconnect on any "reachable while offline/error", not only after a prior offline→online transition — a missed/coalesced offline event no longer strands the client.
|
|
20
|
+
|
|
21
|
+
#### initBeforeLoad
|
|
22
|
+
|
|
23
|
+
- **Auto-retries a transient bootstrap failure** up to 3× with backoff before surfacing the error modal (a flaky network at launch self-heals; auth/credential failures still fail fast).
|
|
24
|
+
- **Overall 45s time budget** — a hung step can no longer strand the loader in `running` forever.
|
|
25
|
+
- **Private store re-synced on reconnect** (not just MUC re-join), so unread / `lastViewedTimestamp` stays accurate after a long reconnect.
|
|
26
|
+
|
|
27
|
+
#### Unread tracking
|
|
28
|
+
|
|
29
|
+
- **Re-entry no longer wipes the cache.** History is now **merged by message id** (the microsecond-resolution stanza id) instead of replaced — older cached messages and the unread derived from them survive; only a true gap (the fetched page shares no id with the cache) clears that one chat's cache. `addRoom` also preserves cached messages + unread when the `/chats/my` refetch omits them (it sends `messages: []`).
|
|
30
|
+
- **AppState now drives room visibility automatically** (library-level). Backgrounding stamps `lastViewedTimestamp = now` and clears the open room's "visible" state — so messages arriving while away count as unread instead of being silently marked read; foreground restores it. No consumer wiring required.
|
|
31
|
+
- **New `<Chat isVisible={…} />` prop.** For hosts that keep `<Chat>` **mounted while hidden** (tab/route navigators), pass `isVisible={currentTab === 'chat'}` — the library clears/restores room visibility from it internally, so consumers never reach into the store. Complements `useChatRoomFocus`.
|
|
32
|
+
|
|
33
|
+
#### "New messages" divider
|
|
34
|
+
|
|
35
|
+
- **White text.** The label sits on a dark pill but rendered in the (often blue) primary color — unreadable. It's now white.
|
|
36
|
+
- **Removed when you leave the chat** (tab switch / navigation / app background) and **spliced out rather than tombstoned**, so it correctly re-appears for the next batch of unread — previously it was a one-shot (the tombstone blocked every future divider).
|
|
37
|
+
|
|
38
|
+
#### Misc
|
|
39
|
+
|
|
40
|
+
- **Benign unhandled-rejection red box gone.** The dev rejection tracker now reports only *genuinely* unhandled rejections (`allRejections: false`), and `createTimeoutPromise` self-observes its timeout so a settled `Promise.race` no longer leaks a `reject(undefined)`.
|
|
41
|
+
- **Input bar spacing.** The send button's horizontal margin is removed so its gap from the input matches the attach button's.
|
|
42
|
+
|
|
43
|
+
### Tests / internal
|
|
44
|
+
|
|
45
|
+
- Testbed harness (`AppLoginChatsRn`): opens on the **Setup** tab by default; runtime credentials moved to a **gitignored** local file (no secrets in tracked source — `DEFAULT_CREDS` is blank, `seed-jwt-creds.example.json` carries placeholders); LogBox dev-noise filtered via `setupLogBox`; a `METRO_NO_WATCHMAN=1` escape hatch in `metro.config.js` for flaky watchman.
|
|
46
|
+
- New regression tests: reconnect coalesce + `forceReconnect` debounce + uncapped/clamped backoff, history merge / gap-clear / no-wipe, `addRoom` preservation, and the divider splice. Full sweep — typecheck clean, **583 jest tests** green.
|
|
47
|
+
|
|
48
|
+
## [26.5.9]
|
|
49
|
+
|
|
50
|
+
Hardening round on top of 26.5.8: the critical reconnect/MUC delivery bug, unread-tracking gaps in tab navigators, a stale-JWT idle loop, translated-message reconciliation, and the `expo-av → expo-video` migration for video playback. Full regression sweep — typecheck clean, 554 jest tests green.
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
#### Connectivity (the critical one)
|
|
55
|
+
|
|
56
|
+
- **Bug #21 — reconnect didn't re-join MUC rooms (local double-tick, never delivered).** On a new stream after an extended drop the client was no longer joined to any room, so sends got a local double-tick but never reached the other end. `XmppClient` now fires an `onOnline` callback that the provider wires to `allRoomPresences(...)` — every room's presence is re-sent on reconnect. Reconnect is also single-flight guarded (no leaked concurrent clients), detaches the old client's listeners before re-init, and tracks the reconnect timer so logout can cancel it.
|
|
57
|
+
- **Bug #21 (race) — `presencesReady` never reset on disconnect.** The flag stayed `true` across a drop, so (a) the heap sender could fire into a dead socket and (b) the `false→true` transition that flushes offline-queued messages never re-armed on reconnect. `onDisconnect` now resets `presencesReady = false`; on reconnect `onOnline` flips it back `true` only after `allRoomPresences` has synchronously re-sent presence — queued messages flush after the re-join, not before.
|
|
58
|
+
- **Idle stale-JWT loop (follow-up to #17).** When a JWT expired during idle and the credential refresh produced no new password, the client used to retry forever with stale creds (`not-authorized` loop). It now detects two consecutive no-progress refreshes, latches `authExpired`, suppresses further reconnects, and emits an `ethora:authExpired` DeviceEventEmitter event so the host can re-authenticate (e.g. re-mount `<Chat>` with a fresh `jwtLogin.token`). `ethora:retryBootstrap` clears the latch.
|
|
59
|
+
- **Bug #4 (residual) — fire-and-forget `client.send()` leaks.** A global send wrapper attaches a no-op `.catch` to every underlying send promise (while returning the same promise to awaiting callers), so a send that rejects during socket teardown no longer surfaces as `Uncaught (in promise)`.
|
|
60
|
+
|
|
61
|
+
#### Unread tracking
|
|
62
|
+
|
|
63
|
+
- **Bug #19 — `useUnread()` stuck at 0 in tab navigators.** When `<ChatRoom>` stays mounted across tabs, blur never released the active-room marker, so the unread middleware treated the room as "always being viewed". `useChatRoomFocus` now releases the active room (`setCurrentRoom({ roomJID: null })`) and stamps `lastViewedTimestamp` on blur — counting resumes the moment the user leaves the tab.
|
|
64
|
+
- **Bug #20 — scroll-to-bottom badge inflated by loading older history.** The badge now snapshots the newest message timestamp when you leave the bottom and counts only messages newer than that snapshot, so back-pagination (load-more) of older messages can never bump the count.
|
|
65
|
+
- **Cold-start badge — incoming `lastViewedTimestamp: 0` clobbered the persisted marker.** `addRoom` now ignores an incoming `0` placeholder (the stanzaHandlers default) and preserves the hydrated/persisted value, so badges are correct on first paint after a cold start.
|
|
66
|
+
|
|
67
|
+
#### Messaging
|
|
68
|
+
|
|
69
|
+
- **Translated / resent messages stuck pending + duplicated.** `sendTextMessageWithTranslateTagStanza` didn't forward a client message id, so translated sends (and every resend that took the translate path) went out without an id — the server echo arrived with a different id and never reconciled with the optimistic bubble (stuck "pending" + a duplicate). It now accepts and forwards `customId`; `useHeapSender` and `resendMessage` pass it.
|
|
70
|
+
|
|
71
|
+
#### UI / customization
|
|
72
|
+
|
|
73
|
+
- **Bug #14 — delete confirmation is now a small centered dialog with a white action label.** Confirm-style modals render in a dedicated bounded `compactDialog` view (never full-screen), and the filled (e.g. red Delete) button now passes `color="#FFFFFF"` explicitly so the label isn't black-on-red.
|
|
74
|
+
- **Bug #13 — context-menu placement is now measured, not estimated.** `MessageInteractions` measures the rendered menu height via `onLayout` and places the menu just above/below the message's actual bounding box, clamped to the viewport — the menu sits adjacent to the message instead of floating far above it.
|
|
75
|
+
- **New `config.disableConnectionErrorOverlay`.** Swaps the full-screen "Connection error" overlay for a small non-blocking `ConnectionBanner`, so a transient reconnect doesn't take over the whole screen.
|
|
76
|
+
- **Android context menu polish.** Hairline dividers (instead of an all-sides border that rendered badly on Android) and explicit row label styling (`includeFontPadding: false`) so menu rows match iOS.
|
|
77
|
+
|
|
78
|
+
#### Media
|
|
79
|
+
|
|
80
|
+
- **`expo-av → expo-video` migration for video.** `VideoMessage`, `FilePreviewModal`, and `MediaFilePreview` now use `expo-video` (`useVideoPlayer` / `VideoView`); the inline bubble shows a tappable poster that opens the full-screen player. **`expo-video` is now a peer dependency** — run `npx expo install expo-video`. Audio still uses `expo-av`.
|
|
81
|
+
|
|
82
|
+
### Tests / internal
|
|
83
|
+
|
|
84
|
+
- Added regression tests: unread cold-start + tab focus/blur, `useUnread` perturbations, the `presencesReady` online/disconnect cycle, and the JWT-login bootstrap mock now stubs `setOnOnline` / `setOnAuthExpired`.
|
|
85
|
+
- Repaired stale tests that lagged source changes (apiClient token getters, `onGetLastMessageArchive(stanza, xmppWs)`, `createRoom` arity) and re-pointed the package-shape test at the `exports` map (the field consumers actually resolve), since the repo root doubles as the Expo testbed and `main` must stay `index.js`.
|
|
86
|
+
|
|
87
|
+
## [26.5.8]
|
|
88
|
+
|
|
89
|
+
Follow-up to 26.5.7 covering the customer-retest list — every "Not in 26.5.7 / Worsened" item, plus a usability gap in `useUnread` and a new scroll-to-bottom UX affordance.
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
|
|
93
|
+
#### Media (the long tail of bug #10 and #9)
|
|
94
|
+
|
|
95
|
+
- **Bug #10 — `/files/` 500 retries with singular field name.** Removing the manual Content-Type header in 26.5.6 wasn't enough — some Ethora deployments expect the field name `file` (singular) instead of `files` (plural). The plural form works for image uploads via permissive server sniffing but rejects video/audio/docs with 500. `useSendMessage.sendMedia` now: (a) coerces iOS `assets-library://` URIs to `file://` so RN's FormData polyfill builds a real multipart blob, then (b) tries `files` (plural — current SDK default), and (c) on 500 retries with `file` (singular). Also surfaces `serverBody` / `fileBlob` shape in the diagnostic log for any remaining 500s.
|
|
96
|
+
- **Bug #9 — video controls hidden behind tab bar; audio preview blank.** `FilePreviewModal`: video player now sits inside a wrapper with `paddingBottom: 80` so the `useNativeControls` overlay clears the host app's tab bar + iOS home indicator. New `audio/*` switch case renders the existing `AudioMessage` (expo-av) component inside an info card with filename — audio messages from other users are now actually playable in the preview.
|
|
97
|
+
|
|
98
|
+
#### Sending / send-state
|
|
99
|
+
|
|
100
|
+
- **Bug #18 — silent send failures stuck on "sending..." forever.** Send paths (`sendMessage` + `sendMedia` in `useSendMessage`) now arm a 30-second watchdog after the optimistic bubble lands. If no server echo arrives in that window AND the message wasn't already explicitly marked failed by the catch path, the watchdog flips it to "Failed — tap to retry". Covers the no-internet case where XMPP buffers the send without throwing.
|
|
101
|
+
|
|
102
|
+
#### UX
|
|
103
|
+
|
|
104
|
+
- **Bug #6 — Android keyboard blocking the chat input + flicker.** 26.5.7's `behavior={undefined}` on Android broke hosts that disable `adjustResize` via `softInputMode`. Reverted to `behavior="padding"` on both platforms — padding adds bottom-padding equal to the keyboard height without changing layout height, so no double-resize (no flicker) and the input is always lifted regardless of the host's softInputMode.
|
|
105
|
+
- **Bug #13 — context menu overcorrected too high.** The 26.5.7 `MENU_HEIGHT=280` over-estimate (based on a phantom reactions strip) forced the menu above the bubble even when there was room below. Real `MessageInteractions` is 1-3 rows × ~40px (40 for non-own, ~140 for own). Lowered to 160; the prefer-below path now wins for normal cases and only switches to above when the bubble genuinely lacks bottom space.
|
|
106
|
+
- **Bug #14 — delete confirmation still full-screen.** The 26.5.7 `compact` style used `height: 'auto'` which RN doesn't honour — the styled-component's `height: 100%` won. Replaced with `height: undefined` + `minHeight: 0` + `alignSelf: 'center'`. Now a properly small (max 360 wide) centered dialog.
|
|
107
|
+
|
|
108
|
+
#### Promise hygiene (bug #4 part 2 — exhaustive sweep)
|
|
109
|
+
|
|
110
|
+
The `(in promise, id: 0)` and `(in promise, id: 2)` red screens were not all in `useChatWrapperInit`. An exhaustive sweep across `src/` found and patched:
|
|
111
|
+
|
|
112
|
+
- `ChatWrapper.tsx` — the outer `await initializeClient(...).then(c => {...})` callback had no `.catch()`. Converted to `await` + inner try/catch.
|
|
113
|
+
- `ChatWrapper.tsx` — three fire-and-forget `refresh()` calls (legacy / storedClient / provider branches) — wrapped each with `.catch((err) => console.warn('refresh failed', err))`.
|
|
114
|
+
- `usePushNotifications.ts:81` — `getInitialNotification().then(...)` without `.catch()` — added one.
|
|
115
|
+
- `usePushNotifications.ts:54` — `initToken()` was fire-and-forget in the bootstrap `useEffect`; any sync throw before the inner try-block leaked. Added `.catch`.
|
|
116
|
+
- `networking/xmpp/getRoomsPaged.xmpp.ts` — **the most likely id:0/id:2 culprit.** `client.send(message)` was NOT awaited inside an `async` Promise executor, so when the socket was closing during reconnect, the send rejection escaped the try/catch entirely. Rewrote without the async executor, captured the send promise, attached `.catch` synchronously, and rewrote the timeout chain to attach its rejection handler at construction time (no race).
|
|
117
|
+
- `networking/xmpp/presenceInRoom.xmpp.ts` — same `new Promise(async (resolve, reject) => …)` anti-pattern with a racy `.catch(reject)` on the timeout. Rewrote to use a regular promise constructor + an inner async IIFE that explicitly funnels every failure path through `reject()`.
|
|
118
|
+
|
|
119
|
+
Also installed a **dev-only global unhandled-rejection tracker** (`src/utils/installPromiseRejectionTracker.ts`, mounted from `ReduxWrapper`) that catches any future leaks and prints the actual rejection value + stack to Metro logs (works on Hermes via `HermesInternal.enablePromiseRejectionTracker` and on the standard `unhandledrejection` event). No-op in production builds. If a new red-screen ever appears, the integrator now sees exactly where it originates.
|
|
120
|
+
|
|
121
|
+
#### Media preview (bug #9 — true inline preview)
|
|
122
|
+
|
|
123
|
+
`FilePreviewModal` now renders office docs (DOC / DOCX / XLS / XLSX / PPT / PPTX / TXT / CSV / RTF) inline via a new `DocumentViewer` component that embeds Google's free `docs.google.com/gview?url=…&embedded=true` viewer in a `react-native-webview`. The previous default case showed only an info card; for these MIME types the user now sees the actual document content. PDF keeps its existing local-download-then-WebView path (`PdfViewer`). Truly unrenderable binary types still fall through to the info card with filename + download prompt.
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
|
|
127
|
+
- **`useChatRoomFocus({ roomJID, isFocused })` hook** — public unread-tracking hook for tab-based navigators where `<ChatRoom>` never unmounts. Mirrors the mount/unmount lifecycle internally — focus stamps `lastViewedTimestamp = 0` (clears badge, marks active room), blur stamps `Date.now()` (so future messages count). Eliminates the consumer workaround of importing `store` / `setLastViewedTimestamp` / `setCurrentRoom` from internal `src/` paths.
|
|
128
|
+
- **Unread-count badge on the scroll-to-bottom arrow.** When the user is scrolled up and new messages arrive, the down-arrow now shows a count chip (capped at `99+`). Resets when they scroll back to the bottom.
|
|
129
|
+
- **New granular config flags** for member-list actions (bug #16 done right this time):
|
|
130
|
+
- `disableMemberProfileActions?: boolean` — hide the whole action block.
|
|
131
|
+
- `hideMemberSendMessageAction?: boolean` — hide only "Message".
|
|
132
|
+
- `hideMemberCopyIdAction?: boolean` — hide only "Copy User Id".
|
|
133
|
+
|
|
134
|
+
### Changed
|
|
135
|
+
|
|
136
|
+
- **Reverted 26.5.7 widening of `disableProfilesInteractions`.** It now controls message-list avatar taps only (its original scope) — the new granular flags above handle the chat-info member actions per-button instead of all-or-nothing.
|
|
137
|
+
- **`roomsSlice.addRoom` cold-start fix.** The previous `Date.now()` default for `lastViewedTimestamp` (used when the payload didn't carry one and there was no existing room) stamped a "now" marker that made messages sent while the app was killed look already-read on next launch. Now anchors to the newest message in the payload (so already-loaded history is "seen" but anything strictly newer counts as unread), falling back to `0` only when there are no messages yet (lets the private-store hydration set the real marker).
|
|
138
|
+
|
|
6
139
|
## [26.5.6]
|
|
7
140
|
|
|
8
141
|
Closes the open items from the 26.5.5 customer bug tracker plus seven new ones (uploads, media preview, XMPP idle recovery, send failures, UI polish, customization gates). One existing config flag (`disableProfilesInteractions`) gets its semantics widened — everything else is additive.
|
package/README.md
CHANGED
|
@@ -15,6 +15,8 @@ React Native chat UI + chat core for iOS and Android, powered by the Ethora plat
|
|
|
15
15
|
- [Configuration](#configuration) — full `IConfig` reference in [instructions.md](instructions.md)
|
|
16
16
|
- [Authentication modes](#authentication-modes)
|
|
17
17
|
- [Pinning a single room](#pinning-a-single-room)
|
|
18
|
+
- [Unread tracking in tab-based hosts](#unread-tracking-in-tab-based-hosts)
|
|
19
|
+
- [Customization flags worth knowing](#customization-flags-worth-knowing)
|
|
18
20
|
- [Quality & test coverage](#quality--test-coverage)
|
|
19
21
|
- [Local development](#local-development)
|
|
20
22
|
- [Changelog](CHANGELOG.md)
|
|
@@ -42,7 +44,7 @@ The package defaults to the canonical Ethora Cloud endpoints:
|
|
|
42
44
|
| Web / sign up | `https://app.chat.ethora.com` |
|
|
43
45
|
| Swagger / API docs | `https://api.chat.ethora.com/api-docs/#/` |
|
|
44
46
|
|
|
45
|
-
To target QA, point the equivalent props/env vars at
|
|
47
|
+
To target a QA or staging environment, point the equivalent props/env vars at that environment's API + XMPP hosts. To self-host, override with your own `xmppSettings` and `baseUrl` — see the example below.
|
|
46
48
|
|
|
47
49
|
## Install
|
|
48
50
|
|
|
@@ -66,10 +68,12 @@ Image / video / document / audio send & receive, HEIC→JPEG conversion, profile
|
|
|
66
68
|
|
|
67
69
|
```bash
|
|
68
70
|
npx expo install \
|
|
69
|
-
expo-av expo-clipboard expo-document-picker \
|
|
71
|
+
expo-av expo-video expo-clipboard expo-document-picker \
|
|
70
72
|
expo-image-manipulator expo-image-picker expo-media-library
|
|
71
73
|
```
|
|
72
74
|
|
|
75
|
+
> Video playback uses **`expo-video`** (`useVideoPlayer` / `VideoView`); `expo-av` is still used for audio. Install both.
|
|
76
|
+
|
|
73
77
|
> No `metro.config.js` shim is required. As of `26.5.5` the SDK no longer statically imports any legacy `react-native-*` native modules; the bundled `withEthoraShims` helper is preserved as a no-op for backward compat with older setups.
|
|
74
78
|
|
|
75
79
|
### 3. iOS pods
|
|
@@ -202,6 +206,59 @@ The complete field-by-field reference — every option in `IConfig`, grouped by
|
|
|
202
206
|
/>
|
|
203
207
|
```
|
|
204
208
|
|
|
209
|
+
## Unread tracking in tab-based hosts
|
|
210
|
+
|
|
211
|
+
`useUnread()` and the room-list badge are wired to the `<ChatRoom>` mount/unmount lifecycle by default, and **app background/foreground is handled automatically** — backgrounding stamps "read up to now" and clears the open room's "viewed" state (so messages that arrive while you're away count as unread instead of looking already-read); foreground restores it. No wiring needed for that.
|
|
212
|
+
|
|
213
|
+
What the SDK *can't* see on its own is an in-app **tab/route switch** where the chat screen **stays mounted while hidden** — there the lifecycle never fires and the room looks "always viewed". Signal it one of two ways (don't reach into the store):
|
|
214
|
+
|
|
215
|
+
**Option A — the `isVisible` prop (simplest):**
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
function ChatTab({ currentTab }: { currentTab: string }) {
|
|
219
|
+
// Library clears/restores the room's unread state from this flag.
|
|
220
|
+
return <Chat config={{...}} isVisible={currentTab === 'chat'} />;
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
**Option B — the `useChatRoomFocus` hook** (drive it from a navigator focus signal):
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
import { useIsFocused } from '@react-navigation/native';
|
|
228
|
+
import { Chat, useUnread, useChatRoomFocus } from '@ethora/chat-component-rn';
|
|
229
|
+
|
|
230
|
+
function ChatTab() {
|
|
231
|
+
const isFocused = useIsFocused();
|
|
232
|
+
// Focus marks the room visible (clears the badge in-memory).
|
|
233
|
+
// Blur stamps `Date.now()` so future messages count as unread.
|
|
234
|
+
useChatRoomFocus({
|
|
235
|
+
roomJID: 'general@conference.xmpp.chat.ethora.com',
|
|
236
|
+
isFocused,
|
|
237
|
+
});
|
|
238
|
+
return <Chat roomJID="general@conference.xmpp.chat.ethora.com" config={{...}} />;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function TabBar() {
|
|
242
|
+
const { totalCount } = useUnread();
|
|
243
|
+
return <Badge count={totalCount} />;
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
(If instead you **unmount** `<Chat>` when it's hidden, you need neither — mount/unmount already handles it.)
|
|
248
|
+
|
|
249
|
+
Full details (including the cold-start fix and the scroll-to-bottom unread chip) live in [`docs/unread-tracking.md`](docs/unread-tracking.md).
|
|
250
|
+
|
|
251
|
+
## Customization flags worth knowing
|
|
252
|
+
|
|
253
|
+
| Flag | What it does |
|
|
254
|
+
| --- | --- |
|
|
255
|
+
| `disableChatHeaderBurgerMenuIcon` | Hides the burger icon in the chat header (the icon that opens the room-list dropdown). `chatHeaderBurgerMenu` controls only the dropdown — set this when you want neither rendered. |
|
|
256
|
+
| `disableMemberProfileActions` | Hides the whole "Message / Copy User Id" action block in the chat-info member modal. Use when no per-user actions are appropriate (e.g. patient-facing apps). |
|
|
257
|
+
| `hideMemberSendMessageAction` | Hides only the "Message" button, keeps everything else. |
|
|
258
|
+
| `hideMemberCopyIdAction` | Hides only the "Copy User Id" button, keeps everything else. |
|
|
259
|
+
| `disableConnectionErrorOverlay` | Replaces the full-screen "Connection error" overlay with a small, non-blocking `ConnectionBanner`. Set this when a transient reconnect shouldn't take over the whole screen. |
|
|
260
|
+
| `eventHandlers.onMessageRetry` | `(event) => void` fired when the user taps the "Failed — tap to retry" indicator on a stuck send. Use for telemetry / surfacing a retry banner. |
|
|
261
|
+
|
|
205
262
|
## Quality & test coverage
|
|
206
263
|
|
|
207
264
|
### Jest (unit + integration)
|
|
@@ -210,7 +267,7 @@ The complete field-by-field reference — every option in `IConfig`, grouped by
|
|
|
210
267
|
npm test # ~2s, full suite
|
|
211
268
|
```
|
|
212
269
|
|
|
213
|
-
|
|
270
|
+
54 files, 583 tests cover the SDK's substantive surface:
|
|
214
271
|
|
|
215
272
|
| Layer | Coverage |
|
|
216
273
|
|--------------------------------|----------|
|
|
@@ -234,7 +291,7 @@ npm run e2e:android # ditto Pixel_6
|
|
|
234
291
|
Uses any profile in `~/.ethora/profiles.json` (the same file the
|
|
235
292
|
`@ethora/setup` CLI writes to). The runner logs the test user via
|
|
236
293
|
REST, seeds the testbed's AsyncStorage with the resolved Creds, and
|
|
237
|
-
exercises the full pipeline against a real
|
|
294
|
+
exercises the full pipeline against a real environment:
|
|
238
295
|
|
|
239
296
|
> REST login → AsyncStorage persisted Creds → app boot →
|
|
240
297
|
> `/chats/my` → XMPP WebSocket → MUC presence join → MAM history →
|
|
@@ -245,9 +302,9 @@ single high-signal smoke for the most-likely class of regressions
|
|
|
245
302
|
(auth flow, XMPP transport, room hydration).
|
|
246
303
|
|
|
247
304
|
### Live deep test
|
|
248
|
-
A
|
|
249
|
-
|
|
250
|
-
|
|
305
|
+
A generic deep-test runbook for side-by-side iOS ↔ Android validation
|
|
306
|
+
lives at `docs/deep-test-chat-runbook.md`. Use it as a reproducible
|
|
307
|
+
checklist for your own QA environment.
|
|
251
308
|
|
|
252
309
|
### Bugs surfaced + fixed (full history on PR #4)
|
|
253
310
|
The test pass surfaced a handful of latent bugs that had been
|
|
@@ -272,8 +329,8 @@ silently shipping. All fixed in the same branch:
|
|
|
272
329
|
This repo doubles as an Expo testbed app: `App.tsx` mounts
|
|
273
330
|
`AppLoginChatsRn`, a 3-tab (Setup / Chat / Logs) shell that drives the
|
|
274
331
|
SDK end-to-end via either paste-a-JWT or email + app-token login. Run
|
|
275
|
-
it against the canonical Ethora Cloud endpoints, your QA
|
|
276
|
-
self-hosted Ethora instance — all configurable from the Setup tab at
|
|
332
|
+
it against the canonical Ethora Cloud endpoints, your QA/staging
|
|
333
|
+
environment, or a self-hosted Ethora instance — all configurable from the Setup tab at
|
|
277
334
|
runtime.
|
|
278
335
|
|
|
279
336
|
### Prerequisites
|
|
@@ -384,7 +441,7 @@ export PATH="$PATH:$HOME/.maestro/bin"
|
|
|
384
441
|
Run against an already-built + installed app + a booted simulator:
|
|
385
442
|
|
|
386
443
|
```bash
|
|
387
|
-
#
|
|
444
|
+
# Uses the first profile from ~/.ethora/profiles.json, room "Main chat"
|
|
388
445
|
npm run e2e:ios
|
|
389
446
|
npm run e2e:android
|
|
390
447
|
|
package/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @format
|
|
3
|
+
*
|
|
4
|
+
* Expo entry — registerRootComponent handles both Expo Go and bare/
|
|
5
|
+
* prebuild flows. The gesture-handler import has to be the very first
|
|
6
|
+
* thing the app evaluates.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import 'react-native-gesture-handler';
|
|
10
|
+
// Polyfill `crypto.getRandomValues()` before anything that pulls in
|
|
11
|
+
// uuid — RN's JS runtime doesn't ship one, and uuid throws
|
|
12
|
+
// "crypto.getRandomValues() not supported" on the first send.
|
|
13
|
+
// The library entry (src/main.ts) loads this too, but the testbed
|
|
14
|
+
// here mounts the chat directly without going through that entry, so
|
|
15
|
+
// we need it again at the testbed root.
|
|
16
|
+
import 'react-native-get-random-values';
|
|
17
|
+
// Configure LogBox before App (and its expo-av / styled-components
|
|
18
|
+
// imports) evaluate, so import-time dev warnings don't flash the on-screen
|
|
19
|
+
// "view warnings" toast over the chat UI. Testbed-only.
|
|
20
|
+
import './setupLogBox';
|
|
21
|
+
import { registerRootComponent } from 'expo';
|
|
22
|
+
import App from './App';
|
|
23
|
+
|
|
24
|
+
registerRootComponent(App);
|