@ethora/chat-component-rn 26.5.5 → 26.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +177 -0
- package/README.md +67 -10
- package/index.js +24 -0
- package/lib/commonjs/assets/icons.js +5 -1
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js +11 -5
- package/lib/commonjs/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js +7 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +66 -34
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +59 -14
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +15 -7
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageContainer.js +2 -2
- package/lib/commonjs/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +175 -30
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js +17 -8
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/SystemMessage.js +34 -22
- package/lib/commonjs/components/MainComponents/SystemMessage.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +117 -19
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +82 -22
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js +16 -4
- package/lib/commonjs/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/DocumentViewer.js +104 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/DocumentViewer.js.map +1 -0
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +175 -40
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js +29 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
- package/lib/commonjs/components/Modals/Modal/Modal.js +5 -1
- package/lib/commonjs/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +78 -39
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +3 -3
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/styledModalComponents.js +4 -9
- package/lib/commonjs/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +115 -5
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +49 -10
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/NewMessageLabel.js +8 -6
- package/lib/commonjs/components/styled/NewMessageLabel.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +53 -29
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/StyledInputComponents/MediaComponents.js +14 -4
- package/lib/commonjs/components/styled/StyledInputComponents/MediaComponents.js.map +1 -1
- package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js +7 -2
- package/lib/commonjs/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
- package/lib/commonjs/components/styled/UnsupportedType.js +5 -1
- package/lib/commonjs/components/styled/UnsupportedType.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +60 -22
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/MessageNotificationContext.js +7 -7
- package/lib/commonjs/context/MessageNotificationContext.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +315 -34
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/chatAutoEnterer.js +2 -7
- package/lib/commonjs/helpers/chatAutoEnterer.js.map +1 -1
- package/lib/commonjs/helpers/historyPreloadScheduler.js +4 -1
- package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js +15 -5
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/commonjs/helpers/keyboardLayout.js +18 -0
- package/lib/commonjs/helpers/keyboardLayout.js.map +1 -0
- package/lib/commonjs/helpers/mediaDimensions.js +51 -0
- package/lib/commonjs/helpers/mediaDimensions.js.map +1 -0
- package/lib/commonjs/helpers/mimeToExtension.js +131 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -0
- package/lib/commonjs/helpers/normalizeRoomJid.js +20 -0
- package/lib/commonjs/helpers/normalizeRoomJid.js.map +1 -0
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +73 -1
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/commonjs/hooks/useChatRoomFocus.js +87 -0
- package/lib/commonjs/hooks/useChatRoomFocus.js.map +1 -0
- package/lib/commonjs/hooks/useChatWrapperInit.js +22 -10
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useEventHandlers.js +9 -1
- package/lib/commonjs/hooks/useEventHandlers.js.map +1 -1
- package/lib/commonjs/hooks/useHeapSender.js +1 -1
- package/lib/commonjs/hooks/useHeapSender.js.map +1 -1
- package/lib/commonjs/hooks/useLogout.js +3 -3
- package/lib/commonjs/hooks/useLogout.js.map +1 -1
- package/lib/commonjs/hooks/useMessageHeapState.js +6 -2
- package/lib/commonjs/hooks/useMessageHeapState.js.map +1 -1
- package/lib/commonjs/hooks/usePushNotifications.js +6 -2
- package/lib/commonjs/hooks/usePushNotifications.js.map +1 -1
- package/lib/commonjs/hooks/useRoomState.js +2 -0
- package/lib/commonjs/hooks/useRoomState.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +249 -14
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/hooks/useUnreadMessagesCounter.js +12 -14
- package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
- package/lib/commonjs/main.js +7 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +74 -1
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/apiClient.js +2 -1
- package/lib/commonjs/networking/apiClient.js.map +1 -1
- package/lib/commonjs/networking/outboundQueue.js +92 -0
- package/lib/commonjs/networking/outboundQueue.js.map +1 -0
- package/lib/commonjs/networking/xmpp/createTimeoutPromise.xmpp.js +4 -1
- package/lib/commonjs/networking/xmpp/createTimeoutPromise.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js +7 -8
- package/lib/commonjs/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
- package/lib/commonjs/networking/xmpp/getRoomsPaged.xmpp.js +26 -3
- package/lib/commonjs/networking/xmpp/getRoomsPaged.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +26 -8
- package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +2 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +371 -26
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js +22 -6
- package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js.map +1 -1
- package/lib/commonjs/roomStore/roomHeapSlice.js +26 -8
- package/lib/commonjs/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +157 -23
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/commonjs/utils/installPromiseRejectionTracker.js +83 -0
- package/lib/commonjs/utils/installPromiseRejectionTracker.js.map +1 -0
- package/lib/commonjs/utils/resendMessage.js +1 -1
- package/lib/commonjs/utils/resendMessage.js.map +1 -1
- package/lib/module/assets/icons.js +5 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/ContextMenu/ContextMenuComponents.js +11 -5
- package/lib/module/components/ContextMenu/ContextMenuComponents.js.map +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +7 -1
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +67 -35
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +59 -14
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +15 -7
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageContainer.js +2 -2
- package/lib/module/components/MainComponents/MessageContainer.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +176 -31
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MainComponents/ReduxWrapper.js +18 -8
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/SystemMessage.js +33 -21
- package/lib/module/components/MainComponents/SystemMessage.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +118 -20
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +84 -24
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js +15 -3
- package/lib/module/components/Modals/AttachSheet/AttachSheet.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/DocumentViewer.js +99 -0
- package/lib/module/components/Modals/FilePreviewModal/DocumentViewer.js.map +1 -0
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +179 -42
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/PdfView.js +31 -3
- package/lib/module/components/Modals/FilePreviewModal/PdfView.js.map +1 -1
- package/lib/module/components/Modals/Modal/Modal.js +5 -1
- package/lib/module/components/Modals/Modal/Modal.js.map +1 -1
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +80 -41
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +3 -3
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/Modals/styledModalComponents.js +4 -9
- package/lib/module/components/Modals/styledModalComponents.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +116 -6
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +51 -12
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/NewMessageLabel.js +8 -6
- package/lib/module/components/styled/NewMessageLabel.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +54 -30
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/StyledInputComponents/MediaComponents.js +14 -4
- package/lib/module/components/styled/StyledInputComponents/MediaComponents.js.map +1 -1
- package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js +7 -2
- package/lib/module/components/styled/StyledInputComponents/StyledInputComponents.js.map +1 -1
- package/lib/module/components/styled/UnsupportedType.js +5 -1
- package/lib/module/components/styled/UnsupportedType.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +61 -23
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/MessageNotificationContext.js +7 -7
- package/lib/module/context/MessageNotificationContext.js.map +1 -1
- package/lib/module/context/xmppProvider.js +319 -37
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/chatAutoEnterer.js +2 -7
- package/lib/module/helpers/chatAutoEnterer.js.map +1 -1
- package/lib/module/helpers/historyPreloadScheduler.js +4 -1
- package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/module/helpers/insertMessageWithDelimiter.js +15 -5
- package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/module/helpers/keyboardLayout.js +12 -0
- package/lib/module/helpers/keyboardLayout.js.map +1 -0
- package/lib/module/helpers/mediaDimensions.js +46 -0
- package/lib/module/helpers/mediaDimensions.js.map +1 -0
- package/lib/module/helpers/mimeToExtension.js +124 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -0
- package/lib/module/helpers/normalizeRoomJid.js +15 -0
- package/lib/module/helpers/normalizeRoomJid.js.map +1 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js +71 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/module/hooks/useChatRoomFocus.js +82 -0
- package/lib/module/hooks/useChatRoomFocus.js.map +1 -0
- package/lib/module/hooks/useChatWrapperInit.js +22 -10
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useEventHandlers.js +9 -1
- package/lib/module/hooks/useEventHandlers.js.map +1 -1
- package/lib/module/hooks/useHeapSender.js +1 -1
- package/lib/module/hooks/useHeapSender.js.map +1 -1
- package/lib/module/hooks/useLogout.js +3 -3
- package/lib/module/hooks/useLogout.js.map +1 -1
- package/lib/module/hooks/useMessageHeapState.js +6 -2
- package/lib/module/hooks/useMessageHeapState.js.map +1 -1
- package/lib/module/hooks/usePushNotifications.js +6 -2
- package/lib/module/hooks/usePushNotifications.js.map +1 -1
- package/lib/module/hooks/useRoomState.js +2 -0
- package/lib/module/hooks/useRoomState.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +252 -17
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/hooks/useUnreadMessagesCounter.js +12 -14
- package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
- package/lib/module/main.js +1 -0
- package/lib/module/main.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +74 -2
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/apiClient.js +2 -1
- package/lib/module/networking/apiClient.js.map +1 -1
- package/lib/module/networking/outboundQueue.js +84 -0
- package/lib/module/networking/outboundQueue.js.map +1 -0
- package/lib/module/networking/xmpp/createTimeoutPromise.xmpp.js +4 -1
- package/lib/module/networking/xmpp/createTimeoutPromise.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js +7 -8
- package/lib/module/networking/xmpp/flushLastViewedToPrivateStore.js.map +1 -1
- package/lib/module/networking/xmpp/getRoomsPaged.xmpp.js +26 -3
- package/lib/module/networking/xmpp/getRoomsPaged.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +26 -8
- package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +2 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmppClient.js +371 -26
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/Middleware/unreadMidlleware.js +22 -6
- package/lib/module/roomStore/Middleware/unreadMidlleware.js.map +1 -1
- package/lib/module/roomStore/roomHeapSlice.js +24 -7
- package/lib/module/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +154 -22
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/utils/installPromiseRejectionTracker.js +78 -0
- package/lib/module/utils/installPromiseRejectionTracker.js.map +1 -0
- package/lib/module/utils/resendMessage.js +1 -1
- package/lib/module/utils/resendMessage.js.map +1 -1
- package/lib/typescript/assets/icons.d.ts +8 -4
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/ContextMenu/ContextMenuComponents.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts +1 -0
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageContainer.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts +1 -0
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/SystemMessage.d.ts +0 -7
- package/lib/typescript/components/MainComponents/SystemMessage.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts +4 -2
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/Modals/AttachSheet/AttachSheet.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/DocumentViewer.d.ts +29 -0
- package/lib/typescript/components/Modals/FilePreviewModal/DocumentViewer.d.ts.map +1 -0
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts +0 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/PdfView.d.ts.map +1 -1
- package/lib/typescript/components/Modals/Modal/Modal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts +6 -0
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
- package/lib/typescript/components/Modals/UserProfileModal/UserProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/styledModalComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/NewMessageLabel.d.ts +1 -5
- package/lib/typescript/components/styled/NewMessageLabel.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledInputComponents/MediaComponents.d.ts +9 -1
- package/lib/typescript/components/styled/StyledInputComponents/MediaComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/StyledInputComponents/StyledInputComponents.d.ts.map +1 -1
- package/lib/typescript/components/styled/UnsupportedType.d.ts +1 -0
- package/lib/typescript/components/styled/UnsupportedType.d.ts.map +1 -1
- package/lib/typescript/components/styled/VideoMessage.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts +1 -0
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/chatAutoEnterer.d.ts.map +1 -1
- package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
- package/lib/typescript/helpers/keyboardLayout.d.ts +9 -0
- package/lib/typescript/helpers/keyboardLayout.d.ts.map +1 -0
- package/lib/typescript/helpers/mediaDimensions.d.ts +9 -0
- package/lib/typescript/helpers/mediaDimensions.d.ts.map +1 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts +37 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -0
- package/lib/typescript/helpers/normalizeRoomJid.d.ts +2 -0
- package/lib/typescript/helpers/normalizeRoomJid.d.ts.map +1 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts +18 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatRoomFocus.d.ts +42 -0
- package/lib/typescript/hooks/useChatRoomFocus.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useEventHandlers.d.ts +6 -0
- package/lib/typescript/hooks/useEventHandlers.d.ts.map +1 -1
- package/lib/typescript/hooks/useHeapSender.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageHeapState.d.ts +2 -0
- package/lib/typescript/hooks/useMessageHeapState.d.ts.map +1 -1
- package/lib/typescript/hooks/usePushNotifications.d.ts.map +1 -1
- package/lib/typescript/hooks/useRoomState.d.ts +1 -0
- package/lib/typescript/hooks/useRoomState.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts +2 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +1 -0
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts +3 -0
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/apiClient.d.ts.map +1 -1
- package/lib/typescript/networking/outboundQueue.d.ts +57 -0
- package/lib/typescript/networking/outboundQueue.d.ts.map +1 -0
- package/lib/typescript/networking/xmpp/createTimeoutPromise.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts +1 -1
- package/lib/typescript/networking/xmpp/flushLastViewedToPrivateStore.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/getRoomsPaged.xmpp.d.ts +1 -1
- package/lib/typescript/networking/xmpp/getRoomsPaged.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +58 -5
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/Middleware/unreadMidlleware.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts +22 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +8 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/models/media.model.d.ts +1 -0
- package/lib/typescript/types/models/media.model.d.ts.map +1 -1
- package/lib/typescript/types/models/xmpp.model.d.ts +1 -1
- package/lib/typescript/types/models/xmpp.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +10 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/utils/installPromiseRejectionTracker.d.ts +20 -0
- package/lib/typescript/utils/installPromiseRejectionTracker.d.ts.map +1 -0
- package/lib/typescript/utils/resendMessage.d.ts.map +1 -1
- package/package.json +18 -2
- package/src/assets/icons.tsx +23 -14
- package/src/components/ContextMenu/ContextMenuComponents.tsx +10 -5
- package/src/components/MainComponents/ChatHeader.tsx +5 -1
- package/src/components/MainComponents/ChatRoom.tsx +81 -61
- package/src/components/MainComponents/ChatWrapper.tsx +100 -21
- package/src/components/MainComponents/MediaMessage.tsx +18 -8
- package/src/components/MainComponents/MessageContainer.tsx +4 -2
- package/src/components/MainComponents/MessageList.tsx +185 -31
- package/src/components/MainComponents/ReduxWrapper.tsx +19 -9
- package/src/components/MainComponents/SystemMessage.tsx +38 -26
- package/src/components/MessageBubble/Message.tsx +110 -27
- package/src/components/MessageBubble/MessageInteractions.tsx +98 -29
- package/src/components/Modals/AttachSheet/AttachSheet.tsx +17 -3
- package/src/components/Modals/FilePreviewModal/DocumentViewer.tsx +93 -0
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +182 -37
- package/src/components/Modals/FilePreviewModal/PdfView.tsx +32 -4
- package/src/components/Modals/Modal/Modal.tsx +4 -1
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +77 -44
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +19 -15
- package/src/components/Modals/styledModalComponents.tsx +4 -9
- package/src/components/styled/MediaFilePreview.tsx +111 -5
- package/src/components/styled/MessageImage.tsx +58 -14
- package/src/components/styled/NewMessageLabel.tsx +8 -5
- package/src/components/styled/SendInput.tsx +67 -29
- package/src/components/styled/StyledInputComponents/MediaComponents.tsx +15 -5
- package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +7 -2
- package/src/components/styled/UnsupportedType.tsx +7 -1
- package/src/components/styled/VideoMessage.tsx +59 -18
- package/src/context/MessageNotificationContext.tsx +8 -8
- package/src/context/xmppProvider.tsx +337 -32
- package/src/helpers/chatAutoEnterer.ts +2 -8
- package/src/helpers/historyPreloadScheduler.ts +4 -1
- package/src/helpers/insertMessageWithDelimiter.ts +22 -15
- package/src/helpers/keyboardLayout.ts +18 -0
- package/src/helpers/mediaDimensions.ts +47 -0
- package/src/helpers/mimeToExtension.ts +135 -0
- package/src/helpers/normalizeRoomJid.ts +6 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +79 -0
- package/src/hooks/useChatRoomFocus.ts +95 -0
- package/src/hooks/useChatWrapperInit.ts +51 -46
- package/src/hooks/useEventHandlers.tsx +24 -1
- package/src/hooks/useHeapSender.tsx +2 -1
- package/src/hooks/useLogout.tsx +3 -3
- package/src/hooks/useMessageHeapState.tsx +6 -2
- package/src/hooks/usePushNotifications.ts +21 -8
- package/src/hooks/useRoomState.tsx +4 -0
- package/src/hooks/useSendMessage.tsx +333 -17
- package/src/hooks/useUnreadMessagesCounter.ts +13 -16
- package/src/main.ts +1 -0
- package/src/networking/api-requests/auth.api.ts +60 -2
- package/src/networking/apiClient.ts +2 -1
- package/src/networking/outboundQueue.ts +98 -0
- package/src/networking/xmpp/createTimeoutPromise.xmpp.ts +5 -1
- package/src/networking/xmpp/flushLastViewedToPrivateStore.ts +11 -13
- package/src/networking/xmpp/getRoomsPaged.xmpp.ts +27 -3
- package/src/networking/xmpp/presenceInRoom.xmpp.ts +24 -9
- package/src/networking/xmpp/sendTextMessage.xmpp.ts +2 -1
- package/src/networking/xmppClient.ts +399 -31
- package/src/roomStore/Middleware/unreadMidlleware.tsx +23 -5
- package/src/roomStore/roomHeapSlice.ts +47 -4
- package/src/roomStore/roomsSlice.ts +177 -27
- package/src/types/models/media.model.ts +3 -0
- package/src/types/models/xmpp.model.ts +2 -1
- package/src/types/types.ts +25 -0
- package/src/utils/installPromiseRejectionTracker.ts +91 -0
- package/src/utils/resendMessage.ts +2 -1
|
@@ -1,31 +1,79 @@
|
|
|
1
|
-
import { View } from 'react-native';
|
|
1
|
+
import { View, Text, StyleSheet, Modal, TouchableOpacity, SafeAreaView } from 'react-native';
|
|
2
2
|
import {
|
|
3
3
|
MediaContainer,
|
|
4
4
|
MediaImage,
|
|
5
5
|
} from './StyledInputComponents/StyledInputComponents';
|
|
6
6
|
import { FileIcon } from '../../assets/icons';
|
|
7
7
|
import { RemoveButton, RemoveButtonText } from './StyledComponents';
|
|
8
|
-
import { FC } from 'react';
|
|
8
|
+
import { FC, useState } from 'react';
|
|
9
9
|
import { MediaFile } from '../../types/types';
|
|
10
|
+
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
10
11
|
|
|
11
12
|
interface MediaFilePreviewProps {
|
|
12
13
|
filePreviews: MediaFile[];
|
|
13
14
|
handleRemoveImage: (index: number) => void;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
const VideoThumb: FC<{ uri: string; onPress: () => void }> = ({
|
|
18
|
+
uri,
|
|
19
|
+
onPress,
|
|
20
|
+
}) => {
|
|
21
|
+
const player = useVideoPlayer(uri, (p) => {
|
|
22
|
+
p.muted = true;
|
|
23
|
+
});
|
|
24
|
+
return (
|
|
25
|
+
<TouchableOpacity
|
|
26
|
+
activeOpacity={0.8}
|
|
27
|
+
onPress={onPress}
|
|
28
|
+
style={styles.videoThumb}
|
|
29
|
+
>
|
|
30
|
+
<VideoView
|
|
31
|
+
player={player}
|
|
32
|
+
style={StyleSheet.absoluteFill}
|
|
33
|
+
contentFit="cover"
|
|
34
|
+
nativeControls={false}
|
|
35
|
+
surfaceType="textureView"
|
|
36
|
+
pointerEvents="none"
|
|
37
|
+
/>
|
|
38
|
+
<View style={styles.playOverlay}>
|
|
39
|
+
<Text style={styles.playIcon}>▶</Text>
|
|
40
|
+
</View>
|
|
41
|
+
</TouchableOpacity>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const FullscreenPreviewVideo: FC<{ uri: string }> = ({ uri }) => {
|
|
46
|
+
const player = useVideoPlayer(uri, (p) => {
|
|
47
|
+
p.play();
|
|
48
|
+
});
|
|
49
|
+
return (
|
|
50
|
+
<VideoView
|
|
51
|
+
player={player}
|
|
52
|
+
style={styles.fullVideo}
|
|
53
|
+
contentFit="contain"
|
|
54
|
+
nativeControls
|
|
55
|
+
surfaceType="textureView"
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
16
60
|
export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
17
61
|
filePreviews,
|
|
18
62
|
handleRemoveImage,
|
|
19
63
|
}) => {
|
|
64
|
+
const [previewUri, setPreviewUri] = useState<string | null>(null);
|
|
65
|
+
|
|
20
66
|
return (
|
|
21
67
|
<MediaContainer>
|
|
22
68
|
{filePreviews.map((file, index) => {
|
|
23
|
-
const
|
|
24
|
-
|
|
69
|
+
const isImage = file.type?.startsWith('image');
|
|
70
|
+
const isVideo = file.type?.startsWith('video');
|
|
25
71
|
return (
|
|
26
72
|
<View key={`${file.name}_${index}`}>
|
|
27
|
-
{
|
|
73
|
+
{isImage ? (
|
|
28
74
|
<MediaImage source={{ uri: file.uri }} />
|
|
75
|
+
) : isVideo ? (
|
|
76
|
+
<VideoThumb uri={file.uri} onPress={() => setPreviewUri(file.uri)} />
|
|
29
77
|
) : (
|
|
30
78
|
<View style={{ width: 70, height: 70, borderRadius: 8 }}>
|
|
31
79
|
<FileIcon width={70} height={70} />
|
|
@@ -37,6 +85,64 @@ export const MediaFilePreview: FC<MediaFilePreviewProps> = ({
|
|
|
37
85
|
</View>
|
|
38
86
|
);
|
|
39
87
|
})}
|
|
88
|
+
|
|
89
|
+
<Modal visible={!!previewUri} animationType="fade" transparent>
|
|
90
|
+
<SafeAreaView style={styles.modalContainer}>
|
|
91
|
+
<TouchableOpacity
|
|
92
|
+
style={styles.closeButton}
|
|
93
|
+
onPress={() => setPreviewUri(null)}
|
|
94
|
+
>
|
|
95
|
+
<Text style={styles.closeText}>✕</Text>
|
|
96
|
+
</TouchableOpacity>
|
|
97
|
+
{previewUri && <FullscreenPreviewVideo uri={previewUri} />}
|
|
98
|
+
</SafeAreaView>
|
|
99
|
+
</Modal>
|
|
40
100
|
</MediaContainer>
|
|
41
101
|
);
|
|
42
102
|
};
|
|
103
|
+
|
|
104
|
+
const styles = StyleSheet.create({
|
|
105
|
+
videoThumb: {
|
|
106
|
+
width: 70,
|
|
107
|
+
height: 70,
|
|
108
|
+
borderRadius: 8,
|
|
109
|
+
overflow: 'hidden',
|
|
110
|
+
backgroundColor: '#1a1a1a',
|
|
111
|
+
},
|
|
112
|
+
playOverlay: {
|
|
113
|
+
...StyleSheet.absoluteFillObject,
|
|
114
|
+
justifyContent: 'center',
|
|
115
|
+
alignItems: 'center',
|
|
116
|
+
backgroundColor: 'rgba(0,0,0,0.3)',
|
|
117
|
+
},
|
|
118
|
+
playIcon: {
|
|
119
|
+
fontSize: 24,
|
|
120
|
+
color: '#fff',
|
|
121
|
+
},
|
|
122
|
+
modalContainer: {
|
|
123
|
+
flex: 1,
|
|
124
|
+
backgroundColor: '#000',
|
|
125
|
+
justifyContent: 'center',
|
|
126
|
+
},
|
|
127
|
+
closeButton: {
|
|
128
|
+
position: 'absolute',
|
|
129
|
+
top: 60,
|
|
130
|
+
right: 20,
|
|
131
|
+
zIndex: 10,
|
|
132
|
+
width: 36,
|
|
133
|
+
height: 36,
|
|
134
|
+
borderRadius: 18,
|
|
135
|
+
backgroundColor: 'rgba(255,255,255,0.2)',
|
|
136
|
+
justifyContent: 'center',
|
|
137
|
+
alignItems: 'center',
|
|
138
|
+
},
|
|
139
|
+
closeText: {
|
|
140
|
+
fontSize: 18,
|
|
141
|
+
color: '#fff',
|
|
142
|
+
fontWeight: '600',
|
|
143
|
+
},
|
|
144
|
+
fullVideo: {
|
|
145
|
+
width: '100%',
|
|
146
|
+
height: '70%',
|
|
147
|
+
},
|
|
148
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState } from 'react';
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import { Container } from './StyledInputComponents/MediaComponents';
|
|
3
3
|
import { useDispatch } from 'react-redux';
|
|
4
4
|
import {
|
|
@@ -6,44 +6,88 @@ import {
|
|
|
6
6
|
setActiveModal,
|
|
7
7
|
} from '../../roomStore/chatSettingsSlice';
|
|
8
8
|
import { MODAL_TYPES } from '../../helpers/constants/MODAL_TYPES';
|
|
9
|
-
import { ActivityIndicator, Image, TouchableOpacity } from 'react-native';
|
|
9
|
+
import { ActivityIndicator, Image, TouchableOpacity, View } from 'react-native';
|
|
10
|
+
import {
|
|
11
|
+
defaultMediaDims,
|
|
12
|
+
fitMediaDimensions,
|
|
13
|
+
MediaDims,
|
|
14
|
+
} from '../../helpers/mediaDimensions';
|
|
15
|
+
|
|
10
16
|
interface CustomMessageImageProps {
|
|
11
17
|
fileURL: string;
|
|
12
18
|
fileName: string;
|
|
13
19
|
mimetype: string;
|
|
14
20
|
}
|
|
15
21
|
|
|
22
|
+
const FALLBACK_IMAGE =
|
|
23
|
+
'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg';
|
|
24
|
+
|
|
16
25
|
const CustomMessageImage: React.FC<CustomMessageImageProps> = ({
|
|
17
26
|
fileURL,
|
|
18
27
|
fileName,
|
|
19
28
|
mimetype,
|
|
20
29
|
}) => {
|
|
21
|
-
const [error, setError] = useState(false);
|
|
22
30
|
const [loading, setLoading] = useState(true);
|
|
31
|
+
// Start with a neutral box; swap to the real aspect ratio once the
|
|
32
|
+
// image's natural dimensions are known so it's shown scaled, not cropped.
|
|
33
|
+
const [dims, setDims] = useState<MediaDims>(defaultMediaDims());
|
|
23
34
|
|
|
24
35
|
const dispatch = useDispatch();
|
|
25
36
|
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!fileURL) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
let active = true;
|
|
42
|
+
Image.getSize(
|
|
43
|
+
fileURL,
|
|
44
|
+
(w, h) => {
|
|
45
|
+
if (active) {
|
|
46
|
+
setDims(fitMediaDimensions(w, h));
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
() => {
|
|
50
|
+
/* keep the default box if the size probe fails */
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
return () => {
|
|
54
|
+
active = false;
|
|
55
|
+
};
|
|
56
|
+
}, [fileURL]);
|
|
57
|
+
|
|
26
58
|
const handleOpen = () => {
|
|
27
59
|
dispatch(setActiveFile({ fileName, fileURL, mimetype }));
|
|
28
60
|
dispatch(setActiveModal(MODAL_TYPES.FILE_PREVIEW));
|
|
29
61
|
};
|
|
30
62
|
|
|
31
63
|
return (
|
|
32
|
-
<Container>
|
|
33
|
-
<TouchableOpacity onPress={handleOpen}>
|
|
34
|
-
{loading &&
|
|
64
|
+
<Container style={{ width: dims.width }}>
|
|
65
|
+
<TouchableOpacity onPress={handleOpen} activeOpacity={0.9}>
|
|
66
|
+
{loading && (
|
|
67
|
+
<View
|
|
68
|
+
style={{
|
|
69
|
+
position: 'absolute',
|
|
70
|
+
width: dims.width,
|
|
71
|
+
height: dims.height,
|
|
72
|
+
alignItems: 'center',
|
|
73
|
+
justifyContent: 'center',
|
|
74
|
+
zIndex: 1,
|
|
75
|
+
}}
|
|
76
|
+
>
|
|
77
|
+
<ActivityIndicator size="small" color="#0052CD" />
|
|
78
|
+
</View>
|
|
79
|
+
)}
|
|
35
80
|
<Image
|
|
36
|
-
|
|
37
|
-
fileURL ||
|
|
38
|
-
'https://as2.ftcdn.net/v2/jpg/02/51/95/53/1000_F_251955356_FAQH0U1y1TZw3ZcdPGybwUkH90a3VAhb.jpg'
|
|
39
|
-
}
|
|
81
|
+
source={{ uri: fileURL || FALLBACK_IMAGE }}
|
|
40
82
|
style={{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
83
|
+
width: dims.width,
|
|
84
|
+
height: dims.height,
|
|
85
|
+
borderRadius: 10,
|
|
86
|
+
backgroundColor: 'rgba(0, 0, 0, 0)',
|
|
44
87
|
}}
|
|
45
|
-
onError={() => setError(true)}
|
|
46
88
|
onLoadEnd={() => setLoading(false)}
|
|
89
|
+
// The box already matches the natural aspect ratio, so 'cover'
|
|
90
|
+
// fills it edge-to-edge with no actual cropping or letterboxing.
|
|
47
91
|
resizeMode="cover"
|
|
48
92
|
/>
|
|
49
93
|
</TouchableOpacity>
|
|
@@ -24,23 +24,26 @@ export const StyledLabel = styled.View`
|
|
|
24
24
|
margin: 10px 0px;
|
|
25
25
|
`;
|
|
26
26
|
|
|
27
|
-
export const StyledLabelText = styled.Text
|
|
28
|
-
color:
|
|
27
|
+
export const StyledLabelText = styled.Text`
|
|
28
|
+
color: #ffffff;
|
|
29
29
|
font-size: 12px;
|
|
30
30
|
line-height: 14px;
|
|
31
|
-
font-weight:
|
|
31
|
+
font-weight: 500;
|
|
32
32
|
`;
|
|
33
33
|
|
|
34
|
+
// `color` is kept for CustomNewMessageLabel API parity, but the built-in
|
|
35
|
+
// label always renders WHITE text — it sits on a dark (#3f3f3f) pill, where
|
|
36
|
+
// the previous primary/blue text was unreadable.
|
|
34
37
|
interface NewMessageLabelProps {
|
|
35
38
|
color?: string;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
const NewMessageLabel: React.FC<NewMessageLabelProps> = (
|
|
41
|
+
const NewMessageLabel: React.FC<NewMessageLabelProps> = () => {
|
|
39
42
|
return (
|
|
40
43
|
<Container>
|
|
41
44
|
<Line />
|
|
42
45
|
<StyledLabel>
|
|
43
|
-
<StyledLabelText
|
|
46
|
+
<StyledLabelText>New messages</StyledLabelText>
|
|
44
47
|
</StyledLabel>
|
|
45
48
|
<Line />
|
|
46
49
|
</Container>
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { IConfig, MediaFile } from '../../types/types';
|
|
10
10
|
import Button from './Button';
|
|
11
11
|
import { SendIcon, AttachIcon } from '../../assets/icons';
|
|
12
|
-
import { KeyboardAvoidingView,
|
|
12
|
+
import { KeyboardAvoidingView, View, TouchableOpacity, Alert, Linking } from 'react-native';
|
|
13
13
|
import AttachSheet from '../Modals/AttachSheet/AttachSheet';
|
|
14
14
|
import { MediaFilePreview } from './MediaFilePreview';
|
|
15
15
|
import * as ImagePicker from 'expo-image-picker';
|
|
@@ -19,6 +19,21 @@ import * as ImageManipulator from 'expo-image-manipulator';
|
|
|
19
19
|
// iOS photos default to HEIC; many web backends (incl. ours) 500 on
|
|
20
20
|
// HEIC uploads because they can't decode it. Convert to JPEG before
|
|
21
21
|
// upload — JPEG is universally supported. JPEGs pass through.
|
|
22
|
+
// Server rejects uploads over its body-size cap with HTTP 413 (Request
|
|
23
|
+
// Entity Too Large). Guard client-side so the user gets a clear message
|
|
24
|
+
// instead of a silent failed bubble. 50 MB matches the backend limit.
|
|
25
|
+
const MAX_MEDIA_BYTES = 50 * 1024 * 1024;
|
|
26
|
+
|
|
27
|
+
const formatBytes = (bytes: number): string => {
|
|
28
|
+
if (bytes >= 1024 * 1024) {
|
|
29
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
30
|
+
}
|
|
31
|
+
if (bytes >= 1024) {
|
|
32
|
+
return `${(bytes / 1024).toFixed(0)} KB`;
|
|
33
|
+
}
|
|
34
|
+
return `${bytes} B`;
|
|
35
|
+
};
|
|
36
|
+
|
|
22
37
|
const normalizeImageAsset = async (asset: ImagePicker.ImagePickerAsset) => {
|
|
23
38
|
const mime = (asset.mimeType || '').toLowerCase();
|
|
24
39
|
const looksLikeHeic =
|
|
@@ -72,7 +87,6 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
72
87
|
const [isRecording, setIsRecording] = useState(false);
|
|
73
88
|
const [isFocused, setIsFocused] = useState(false);
|
|
74
89
|
const [filePreviews, setFilePreviews] = useState<MediaFile[]>([]);
|
|
75
|
-
const [inputHeight, setInputHeight] = useState(40);
|
|
76
90
|
const [showMediaMenu, setShowMediaMenu] = useState(false);
|
|
77
91
|
|
|
78
92
|
// Refs shadow `message` and `filePreviews` so handleSendClick can:
|
|
@@ -90,6 +104,21 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
90
104
|
const sendingRef = useRef(false);
|
|
91
105
|
|
|
92
106
|
const handleFileSelect = (files: MediaFile[]) => {
|
|
107
|
+
// Enforce the upload size cap before anything reaches the network.
|
|
108
|
+
// The backend rejects oversized bodies with HTTP 413; catching it
|
|
109
|
+
// here gives a clear message instead of a silent failed bubble.
|
|
110
|
+
const oversize = files.find(
|
|
111
|
+
(f) => typeof f.size === 'number' && f.size > MAX_MEDIA_BYTES
|
|
112
|
+
);
|
|
113
|
+
if (oversize) {
|
|
114
|
+
Alert.alert(
|
|
115
|
+
'File too large',
|
|
116
|
+
`"${oversize.name}" is ${formatBytes(oversize.size!)}. The maximum allowed size is ${Math.round(
|
|
117
|
+
MAX_MEDIA_BYTES / (1024 * 1024)
|
|
118
|
+
)} MB.`
|
|
119
|
+
);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
93
122
|
filePreviewsRef.current = files;
|
|
94
123
|
setFilePreviews([...files]);
|
|
95
124
|
};
|
|
@@ -117,6 +146,7 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
117
146
|
const result = await ImagePicker.launchCameraAsync({
|
|
118
147
|
mediaTypes: ['images', 'videos'],
|
|
119
148
|
quality: 0.9,
|
|
149
|
+
videoQuality: ImagePicker.UIImagePickerControllerQualityType.Medium,
|
|
120
150
|
});
|
|
121
151
|
if (result.canceled || !result.assets?.[0]) {return;}
|
|
122
152
|
const asset = result.assets[0];
|
|
@@ -126,13 +156,19 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
126
156
|
uri: asset.uri,
|
|
127
157
|
type: asset.mimeType || 'video/mp4',
|
|
128
158
|
name: asset.fileName || asset.uri.split('/').pop() || `camera_${Date.now()}.mp4`,
|
|
159
|
+
size: (asset as any).fileSize,
|
|
129
160
|
},
|
|
130
161
|
]);
|
|
131
162
|
return;
|
|
132
163
|
}
|
|
133
164
|
const normalized = await normalizeImageAsset(asset);
|
|
134
165
|
handleFileSelect([
|
|
135
|
-
{
|
|
166
|
+
{
|
|
167
|
+
uri: normalized.uri,
|
|
168
|
+
type: normalized.mime,
|
|
169
|
+
name: normalized.name,
|
|
170
|
+
size: (asset as any).fileSize,
|
|
171
|
+
},
|
|
136
172
|
]);
|
|
137
173
|
} catch (error) {
|
|
138
174
|
console.error('Camera error:', error);
|
|
@@ -151,6 +187,8 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
151
187
|
mediaTypes: ['images', 'videos'],
|
|
152
188
|
allowsEditing: false,
|
|
153
189
|
quality: 0.9,
|
|
190
|
+
preferredAssetRepresentationMode:
|
|
191
|
+
ImagePicker.UIImagePickerPreferredAssetRepresentationMode.Compatible,
|
|
154
192
|
});
|
|
155
193
|
if (result.canceled || !result.assets?.[0]) {return;}
|
|
156
194
|
const asset = result.assets[0];
|
|
@@ -162,13 +200,19 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
162
200
|
uri: asset.uri,
|
|
163
201
|
type: asset.mimeType || 'video/mp4',
|
|
164
202
|
name: asset.fileName || asset.uri.split('/').pop() || `gallery_${Date.now()}.mp4`,
|
|
203
|
+
size: (asset as any).fileSize,
|
|
165
204
|
},
|
|
166
205
|
]);
|
|
167
206
|
return;
|
|
168
207
|
}
|
|
169
208
|
const normalized = await normalizeImageAsset(asset);
|
|
170
209
|
handleFileSelect([
|
|
171
|
-
{
|
|
210
|
+
{
|
|
211
|
+
uri: normalized.uri,
|
|
212
|
+
type: normalized.mime,
|
|
213
|
+
name: normalized.name,
|
|
214
|
+
size: (asset as any).fileSize,
|
|
215
|
+
},
|
|
172
216
|
]);
|
|
173
217
|
} catch (error) {
|
|
174
218
|
console.error('Gallery error:', error);
|
|
@@ -189,6 +233,7 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
189
233
|
uri: asset.uri,
|
|
190
234
|
type: asset.mimeType || 'application/octet-stream',
|
|
191
235
|
name: asset.name || `file_${Date.now()}`,
|
|
236
|
+
size: asset.size ?? undefined,
|
|
192
237
|
},
|
|
193
238
|
]);
|
|
194
239
|
} catch (err) {
|
|
@@ -197,21 +242,7 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
197
242
|
};
|
|
198
243
|
|
|
199
244
|
const handleAttachPress = () => {
|
|
200
|
-
|
|
201
|
-
ActionSheetIOS.showActionSheetWithOptions(
|
|
202
|
-
{
|
|
203
|
-
options: ['Cancel', 'Camera', 'Photo Library', 'Document'],
|
|
204
|
-
cancelButtonIndex: 0,
|
|
205
|
-
},
|
|
206
|
-
(buttonIndex) => {
|
|
207
|
-
if (buttonIndex === 1) {handleCameraSelection();}
|
|
208
|
-
else if (buttonIndex === 2) {handleGallerySelection();}
|
|
209
|
-
else if (buttonIndex === 3) {handleFileSelection();}
|
|
210
|
-
}
|
|
211
|
-
);
|
|
212
|
-
} else {
|
|
213
|
-
setShowMediaMenu(true);
|
|
214
|
-
}
|
|
245
|
+
setShowMediaMenu(true);
|
|
215
246
|
};
|
|
216
247
|
|
|
217
248
|
const handleRemoveImage = (index: number) => {
|
|
@@ -333,17 +364,15 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
333
364
|
}}
|
|
334
365
|
editable={!isLoading || !isMessageProcessing}
|
|
335
366
|
multiline={true}
|
|
336
|
-
//
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
)
|
|
343
|
-
);
|
|
344
|
-
}}
|
|
367
|
+
// No fixed height: a multiline TextInput auto-grows to fit
|
|
368
|
+
// its content between min/max. Locking `height` made iOS
|
|
369
|
+
// top-align the text inside the taller box (it looked like
|
|
370
|
+
// the text had dropped). minHeight keeps the 40px tap
|
|
371
|
+
// target; the row's align-items:center vertically centres
|
|
372
|
+
// the content-sized input.
|
|
345
373
|
style={{
|
|
346
|
-
|
|
374
|
+
minHeight: 40,
|
|
375
|
+
maxHeight: 120,
|
|
347
376
|
flex: 1,
|
|
348
377
|
}}
|
|
349
378
|
/>
|
|
@@ -368,6 +397,15 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
368
397
|
borderRadius: 20,
|
|
369
398
|
alignItems: 'center',
|
|
370
399
|
justifyContent: 'center',
|
|
400
|
+
// The shared Button (CustomButton) bakes in `margin: 0 10px`,
|
|
401
|
+
// which pushed the send button 10px further from the input
|
|
402
|
+
// and from the right edge than the attach button (a raw
|
|
403
|
+
// TouchableOpacity with no margin). Zero it so both sides of
|
|
404
|
+
// the input use the row's uniform gap:8 + 16px container
|
|
405
|
+
// padding. Longhand left/right to override the styled
|
|
406
|
+
// longhand (marginHorizontal loses to marginLeft/Right in RN).
|
|
407
|
+
marginLeft: 0,
|
|
408
|
+
marginRight: 0,
|
|
371
409
|
backgroundColor:
|
|
372
410
|
message || filePreviews.length > 0
|
|
373
411
|
? config?.colors?.primary
|
|
@@ -3,9 +3,15 @@ import styled from 'styled-components/native';
|
|
|
3
3
|
export const Container = styled.View`
|
|
4
4
|
margin: 0;
|
|
5
5
|
cursor: pointer;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/* The media has an explicit (scaled) width set inline. Its horizontal
|
|
7
|
+
position inside the bubble is driven by the bubble's align-items
|
|
8
|
+
(set per-sender in Message.tsx): own messages push the media to the
|
|
9
|
+
right edge, others to the left — so the media stays flush with the
|
|
10
|
+
text bubbles on the same side instead of leaving a gap. */
|
|
11
|
+
align-items: flex-start;
|
|
12
|
+
align-self: auto;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
border-radius: 10px;
|
|
9
15
|
`;
|
|
10
16
|
|
|
11
17
|
export const FullScreenImage = styled.Image`
|
|
@@ -66,11 +72,15 @@ export const FileInformation = styled.View`
|
|
|
66
72
|
gap: 8px;
|
|
67
73
|
`;
|
|
68
74
|
|
|
69
|
-
export const FileName = styled.Text
|
|
75
|
+
export const FileName = styled.Text<{
|
|
76
|
+
isUser: boolean;
|
|
77
|
+
colorIsUser: string| undefined;
|
|
78
|
+
colorUsers: string | undefined;
|
|
79
|
+
}>`
|
|
70
80
|
font-size: 14px;
|
|
71
81
|
font-weight: 500;
|
|
72
82
|
flex-grow: 1;
|
|
73
|
-
color:
|
|
83
|
+
color: ${({isUser, colorIsUser, colorUsers}) => isUser? colorIsUser : colorUsers};
|
|
74
84
|
overflow: hidden;
|
|
75
85
|
`;
|
|
76
86
|
|
|
@@ -46,16 +46,21 @@ export const MessageInput = styled.TextInput<{
|
|
|
46
46
|
isFocused?: boolean;
|
|
47
47
|
color?: string;
|
|
48
48
|
}>`
|
|
49
|
-
padding:
|
|
49
|
+
padding: 8px 14px;
|
|
50
50
|
border-radius: 20px;
|
|
51
51
|
border-width: 1px;
|
|
52
52
|
border-color: ${(props) =>
|
|
53
53
|
props.isFocused ? props.color || '#0052CD' : 'transparent'};
|
|
54
54
|
color: #141414;
|
|
55
|
+
font-size: 16px;
|
|
55
56
|
background-color: #f5f7f9;
|
|
56
57
|
flex: 1;
|
|
58
|
+
/* No explicit line-height: on iOS a line-height larger than the
|
|
59
|
+
font's natural metrics drops the glyph to the bottom of the line
|
|
60
|
+
box (looked like the text "sank"). Equal vertical padding + the
|
|
61
|
+
natural line height centers single-line text in the min-height
|
|
62
|
+
box. text-align-vertical / include-font-padding stay for Android. */
|
|
57
63
|
text-align-vertical: center;
|
|
58
|
-
line-height: 20px;
|
|
59
64
|
include-font-padding: false;
|
|
60
65
|
`;
|
|
61
66
|
|
|
@@ -23,6 +23,7 @@ interface FileDownloadProps {
|
|
|
23
23
|
fileURL: string;
|
|
24
24
|
mimetype: string;
|
|
25
25
|
size?: string;
|
|
26
|
+
isUser: boolean;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const FileDownload: React.FC<FileDownloadProps> = ({
|
|
@@ -30,6 +31,7 @@ const FileDownload: React.FC<FileDownloadProps> = ({
|
|
|
30
31
|
fileURL,
|
|
31
32
|
mimetype,
|
|
32
33
|
size,
|
|
34
|
+
isUser,
|
|
33
35
|
}) => {
|
|
34
36
|
const dispatch = useDispatch();
|
|
35
37
|
const { config } = useChatSettingState();
|
|
@@ -81,7 +83,11 @@ const FileDownload: React.FC<FileDownloadProps> = ({
|
|
|
81
83
|
<FileIcon />
|
|
82
84
|
</BackgroundFile>
|
|
83
85
|
<FileInformation>
|
|
84
|
-
<FileName
|
|
86
|
+
<FileName
|
|
87
|
+
isUser={isUser}
|
|
88
|
+
colorIsUser={config?.colors?.primary}
|
|
89
|
+
colorUsers={config?.colors?.secondary}
|
|
90
|
+
>{formatFileName(fileName, 20)}</FileName>
|
|
85
91
|
{size && (
|
|
86
92
|
<FileSizeContainer>
|
|
87
93
|
<FileSize>{formatFileSize(size)}</FileSize>
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
-
import {
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { TouchableOpacity, StyleSheet, View } from 'react-native';
|
|
3
|
+
import { useVideoPlayer, VideoView } from 'expo-video';
|
|
4
4
|
import { useDispatch } from 'react-redux';
|
|
5
5
|
import {
|
|
6
6
|
setActiveFile,
|
|
7
7
|
setActiveModal,
|
|
8
8
|
} from '../../roomStore/chatSettingsSlice';
|
|
9
9
|
import { MODAL_TYPES } from '../../helpers/constants/MODAL_TYPES';
|
|
10
|
+
import { PlayIcon } from '../../assets/icons';
|
|
11
|
+
import {
|
|
12
|
+
defaultMediaDims,
|
|
13
|
+
fitMediaDimensions,
|
|
14
|
+
MediaDims,
|
|
15
|
+
} from '../../helpers/mediaDimensions';
|
|
10
16
|
|
|
11
17
|
interface CustomMessageVideoProps {
|
|
12
18
|
fileName: string;
|
|
@@ -20,6 +26,21 @@ const CustomMessageVideo: React.FC<CustomMessageVideoProps> = ({
|
|
|
20
26
|
mimetype,
|
|
21
27
|
}) => {
|
|
22
28
|
const dispatch = useDispatch();
|
|
29
|
+
const [dims, setDims] = useState<MediaDims>(defaultMediaDims());
|
|
30
|
+
|
|
31
|
+
const player = useVideoPlayer(fileURL, (p) => {
|
|
32
|
+
p.muted = true;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
const sub = player.addListener('statusChange', () => {
|
|
37
|
+
const size = player.videoTrack?.size;
|
|
38
|
+
if (size?.width && size?.height) {
|
|
39
|
+
setDims(fitMediaDimensions(size.width, size.height));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return () => sub.remove();
|
|
43
|
+
}, [player]);
|
|
23
44
|
|
|
24
45
|
const handleOpen = () => {
|
|
25
46
|
dispatch(setActiveFile({ fileName, fileURL, mimetype }));
|
|
@@ -27,14 +48,24 @@ const CustomMessageVideo: React.FC<CustomMessageVideoProps> = ({
|
|
|
27
48
|
};
|
|
28
49
|
|
|
29
50
|
return (
|
|
30
|
-
<TouchableOpacity
|
|
31
|
-
|
|
32
|
-
|
|
51
|
+
<TouchableOpacity
|
|
52
|
+
onPress={handleOpen}
|
|
53
|
+
activeOpacity={0.9}
|
|
54
|
+
style={[styles.wrapper, { width: dims.width, height: dims.height }]}
|
|
55
|
+
>
|
|
56
|
+
<VideoView
|
|
57
|
+
player={player}
|
|
33
58
|
style={styles.video}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
contentFit="cover"
|
|
60
|
+
nativeControls={false}
|
|
61
|
+
surfaceType="textureView"
|
|
62
|
+
pointerEvents="none"
|
|
37
63
|
/>
|
|
64
|
+
<View style={styles.overlay} pointerEvents="none">
|
|
65
|
+
<View style={styles.playButton}>
|
|
66
|
+
<PlayIcon width={28} height={28} />
|
|
67
|
+
</View>
|
|
68
|
+
</View>
|
|
38
69
|
</TouchableOpacity>
|
|
39
70
|
);
|
|
40
71
|
};
|
|
@@ -42,16 +73,26 @@ const CustomMessageVideo: React.FC<CustomMessageVideoProps> = ({
|
|
|
42
73
|
export default CustomMessageVideo;
|
|
43
74
|
|
|
44
75
|
const styles = StyleSheet.create({
|
|
45
|
-
|
|
46
|
-
margin: 0,
|
|
47
|
-
alignItems: 'center',
|
|
48
|
-
justifyContent: 'center',
|
|
49
|
-
width: '100%',
|
|
50
|
-
},
|
|
51
|
-
video: {
|
|
52
|
-
width: 300,
|
|
53
|
-
height: 200,
|
|
76
|
+
wrapper: {
|
|
54
77
|
borderRadius: 10,
|
|
78
|
+
overflow: 'hidden',
|
|
55
79
|
backgroundColor: '#000',
|
|
56
80
|
},
|
|
81
|
+
video: {
|
|
82
|
+
width: '100%',
|
|
83
|
+
height: '100%',
|
|
84
|
+
},
|
|
85
|
+
overlay: {
|
|
86
|
+
...StyleSheet.absoluteFillObject,
|
|
87
|
+
justifyContent: 'center',
|
|
88
|
+
alignItems: 'center',
|
|
89
|
+
},
|
|
90
|
+
playButton: {
|
|
91
|
+
width: 48,
|
|
92
|
+
height: 48,
|
|
93
|
+
borderRadius: 24,
|
|
94
|
+
backgroundColor: 'rgba(0, 0, 0, 0.55)',
|
|
95
|
+
justifyContent: 'center',
|
|
96
|
+
alignItems: 'center',
|
|
97
|
+
},
|
|
57
98
|
});
|