@ethora/chat-component-rn 26.9.0 → 26.10.0
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 +34 -0
- package/README.md +19 -0
- package/lib/commonjs/assets/icons.js +2 -2
- package/lib/commonjs/assets/icons.js.map +1 -1
- package/lib/commonjs/components/Header/HeaderRoomList.js +22 -6
- package/lib/commonjs/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/commonjs/components/InputComponents/Search.js +38 -1
- package/lib/commonjs/components/InputComponents/Search.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ArchivedMessageCard.js +166 -0
- package/lib/commonjs/components/MainComponents/ArchivedMessageCard.js.map +1 -0
- package/lib/commonjs/components/MainComponents/ChatHeader.js +22 -5
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +56 -25
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +53 -4
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +18 -3
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +739 -42
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageSearchButton.js +58 -0
- package/lib/commonjs/components/MainComponents/MessageSearchButton.js.map +1 -0
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js +15 -6
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/RoomList.js +110 -1
- package/lib/commonjs/components/MainComponents/RoomList.js.map +1 -1
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js +14 -3
- package/lib/commonjs/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/BubbleHighlight.js +112 -0
- package/lib/commonjs/components/MessageBubble/BubbleHighlight.js.map +1 -0
- package/lib/commonjs/components/MessageBubble/Message.js +169 -125
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js +98 -78
- package/lib/commonjs/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/messageMenuLayout.js +50 -0
- package/lib/commonjs/components/MessageBubble/messageMenuLayout.js.map +1 -0
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js +73 -37
- package/lib/commonjs/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/commonjs/components/Modals/MessageSearchModal/MessageHitResults.js +253 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/MessageHitResults.js.map +1 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/MessageSearchModal.js +488 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/MessageSearchModal.js.map +1 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/openHit.js +51 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/openHit.js.map +1 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/resolveSender.js +47 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/resolveSender.js.map +1 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/searchFilters.js +83 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/searchFilters.js.map +1 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/snippet.js +61 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/snippet.js.map +1 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/useMessageSearch.js +136 -0
- package/lib/commonjs/components/Modals/MessageSearchModal/useMessageSearch.js.map +1 -0
- package/lib/commonjs/components/Modals/PublicChatsModal/PublicChatsModal.js +306 -0
- package/lib/commonjs/components/Modals/PublicChatsModal/PublicChatsModal.js.map +1 -0
- package/lib/commonjs/components/Modals/PublicChatsModal/publicChatsLogic.js +36 -0
- package/lib/commonjs/components/Modals/PublicChatsModal/publicChatsLogic.js.map +1 -0
- package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js +8 -1
- package/lib/commonjs/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js +13 -2
- package/lib/commonjs/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/commonjs/components/RoomComponents/SwipeableRoomRow.js +38 -6
- package/lib/commonjs/components/RoomComponents/SwipeableRoomRow.js.map +1 -1
- package/lib/commonjs/components/Thread/ThreadHeader.js +3 -1
- package/lib/commonjs/components/Thread/ThreadHeader.js.map +1 -1
- package/lib/commonjs/components/Thread/ThreadWrapper.js +90 -10
- package/lib/commonjs/components/Thread/ThreadWrapper.js.map +1 -1
- package/lib/commonjs/components/styled/AudioDecoderHost.js +338 -0
- package/lib/commonjs/components/styled/AudioDecoderHost.js.map +1 -0
- package/lib/commonjs/components/styled/AudioMessage.js +493 -420
- package/lib/commonjs/components/styled/AudioMessage.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +31 -5
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/context/MessageNotificationContext.js +14 -4
- package/lib/commonjs/context/MessageNotificationContext.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +54 -79
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/audioWaveform.js +165 -0
- package/lib/commonjs/helpers/audioWaveform.js.map +1 -0
- package/lib/commonjs/helpers/backgroundJoinSweep.js +36 -0
- package/lib/commonjs/helpers/backgroundJoinSweep.js.map +1 -0
- package/lib/commonjs/helpers/bubbleHighlight.js +44 -0
- package/lib/commonjs/helpers/bubbleHighlight.js.map +1 -0
- package/lib/commonjs/helpers/checkUniqueUsers.js +14 -12
- package/lib/commonjs/helpers/checkUniqueUsers.js.map +1 -1
- package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js +5 -1
- package/lib/commonjs/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
- package/lib/commonjs/helpers/constants/MODAL_TYPES.js +3 -1
- package/lib/commonjs/helpers/constants/MODAL_TYPES.js.map +1 -1
- package/lib/commonjs/helpers/createRoomFromApi.js +40 -3
- package/lib/commonjs/helpers/createRoomFromApi.js.map +1 -1
- package/lib/commonjs/helpers/dedupeMembers.js +34 -0
- package/lib/commonjs/helpers/dedupeMembers.js.map +1 -0
- package/lib/commonjs/helpers/ethoraLogger.js +56 -0
- package/lib/commonjs/helpers/ethoraLogger.js.map +1 -0
- package/lib/commonjs/helpers/getUnnamedUsers.js +9 -4
- package/lib/commonjs/helpers/getUnnamedUsers.js.map +1 -1
- package/lib/commonjs/helpers/historyPreloadConfig.js +44 -0
- package/lib/commonjs/helpers/historyPreloadConfig.js.map +1 -0
- package/lib/commonjs/helpers/historyPreloadScheduler.js +372 -137
- package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/commonjs/helpers/initRoomsPresence.js +17 -5
- package/lib/commonjs/helpers/initRoomsPresence.js.map +1 -1
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js +5 -0
- package/lib/commonjs/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/commonjs/helpers/isLikelyMucJid.js +67 -0
- package/lib/commonjs/helpers/isLikelyMucJid.js.map +1 -0
- package/lib/commonjs/helpers/isMessageSearchEnabled.js +18 -0
- package/lib/commonjs/helpers/isMessageSearchEnabled.js.map +1 -0
- package/lib/commonjs/helpers/joiningRoom.js +14 -0
- package/lib/commonjs/helpers/joiningRoom.js.map +1 -0
- package/lib/commonjs/helpers/jumpThread.js +100 -0
- package/lib/commonjs/helpers/jumpThread.js.map +1 -0
- package/lib/commonjs/helpers/jumpToMessage.js +58 -0
- package/lib/commonjs/helpers/jumpToMessage.js.map +1 -0
- package/lib/commonjs/helpers/jumpWindow.js +187 -0
- package/lib/commonjs/helpers/jumpWindow.js.map +1 -0
- package/lib/commonjs/helpers/loadRoomHistory.js +75 -0
- package/lib/commonjs/helpers/loadRoomHistory.js.map +1 -0
- package/lib/commonjs/helpers/notificationPolicy.js +77 -0
- package/lib/commonjs/helpers/notificationPolicy.js.map +1 -0
- package/lib/commonjs/helpers/openRoomAtMessage.js +47 -0
- package/lib/commonjs/helpers/openRoomAtMessage.js.map +1 -0
- package/lib/commonjs/helpers/openThreadForJump.js +72 -0
- package/lib/commonjs/helpers/openThreadForJump.js.map +1 -0
- package/lib/commonjs/helpers/parseMessageReference.js +27 -8
- package/lib/commonjs/helpers/parseMessageReference.js.map +1 -1
- package/lib/commonjs/helpers/publicChatsEntry.js +17 -0
- package/lib/commonjs/helpers/publicChatsEntry.js.map +1 -0
- package/lib/commonjs/helpers/roomActivityScore.js +37 -0
- package/lib/commonjs/helpers/roomActivityScore.js.map +1 -0
- package/lib/commonjs/helpers/roomUserCount.js +36 -0
- package/lib/commonjs/helpers/roomUserCount.js.map +1 -0
- package/lib/commonjs/helpers/runConfiguredHistoryPreload.js +68 -0
- package/lib/commonjs/helpers/runConfiguredHistoryPreload.js.map +1 -0
- package/lib/commonjs/helpers/sessionAppId.js +24 -0
- package/lib/commonjs/helpers/sessionAppId.js.map +1 -0
- package/lib/commonjs/helpers/timestamp.js +43 -0
- package/lib/commonjs/helpers/timestamp.js.map +1 -0
- package/lib/commonjs/helpers/userResolver.js +517 -0
- package/lib/commonjs/helpers/userResolver.js.map +1 -0
- package/lib/commonjs/helpers/xmppIdShape.js +52 -0
- package/lib/commonjs/helpers/xmppIdShape.js.map +1 -0
- package/lib/commonjs/hooks/useChatWrapperInit.js +27 -5
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useHeapSender.js +54 -3
- package/lib/commonjs/hooks/useHeapSender.js.map +1 -1
- package/lib/commonjs/hooks/useJumpToMessage.js +411 -0
- package/lib/commonjs/hooks/useJumpToMessage.js.map +1 -0
- package/lib/commonjs/hooks/useMessageLoaderQueue.js +32 -5
- package/lib/commonjs/hooks/useMessageLoaderQueue.js.map +1 -1
- package/lib/commonjs/hooks/useMessageQueue.js +13 -5
- package/lib/commonjs/hooks/useMessageQueue.js.map +1 -1
- package/lib/commonjs/hooks/useRoomDirectory.js +29 -0
- package/lib/commonjs/hooks/useRoomDirectory.js.map +1 -0
- package/lib/commonjs/hooks/useRoomInitialization.js +27 -5
- package/lib/commonjs/hooks/useRoomInitialization.js.map +1 -1
- package/lib/commonjs/hooks/useRoomMute.js +62 -0
- package/lib/commonjs/hooks/useRoomMute.js.map +1 -0
- package/lib/commonjs/hooks/useRoomState.js +3 -1
- package/lib/commonjs/hooks/useRoomState.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +13 -3
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/i18n/strings.js +318 -6
- package/lib/commonjs/i18n/strings.js.map +1 -1
- package/lib/commonjs/networking/api-requests/messageSearch.api.js +87 -0
- package/lib/commonjs/networking/api-requests/messageSearch.api.js.map +1 -0
- package/lib/commonjs/networking/api-requests/publicChats.api.js +48 -0
- package/lib/commonjs/networking/api-requests/publicChats.api.js.map +1 -0
- package/lib/commonjs/networking/api-requests/roomMembers.api.js +253 -4
- package/lib/commonjs/networking/api-requests/roomMembers.api.js.map +1 -1
- package/lib/commonjs/networking/api-requests/rooms.api.js +48 -12
- package/lib/commonjs/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/commonjs/networking/api-requests/xmppToken.api.js +71 -0
- package/lib/commonjs/networking/api-requests/xmppToken.api.js.map +1 -0
- package/lib/commonjs/networking/ethoraEvents.js +227 -0
- package/lib/commonjs/networking/ethoraEvents.js.map +1 -0
- package/lib/commonjs/networking/stanzaHandlers.js +153 -16
- package/lib/commonjs/networking/stanzaHandlers.js.map +1 -1
- package/lib/commonjs/networking/xmpp/allRoomPresences.xmpp.js +124 -3
- package/lib/commonjs/networking/xmpp/allRoomPresences.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/getHistory.xmpp.js +319 -35
- package/lib/commonjs/networking/xmpp/getHistory.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js +7 -0
- package/lib/commonjs/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/historyCursor.js +101 -0
- package/lib/commonjs/networking/xmpp/historyCursor.js.map +1 -0
- package/lib/commonjs/networking/xmpp/mamQueryIds.js +17 -0
- package/lib/commonjs/networking/xmpp/mamQueryIds.js.map +1 -0
- package/lib/commonjs/networking/xmpp/mamRouter.js +24 -9
- package/lib/commonjs/networking/xmpp/mamRouter.js.map +1 -1
- package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js +70 -65
- package/lib/commonjs/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/roomJoinSweep.js +389 -0
- package/lib/commonjs/networking/xmpp/roomJoinSweep.js.map +1 -0
- package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js +0 -1
- package/lib/commonjs/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js +0 -1
- package/lib/commonjs/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +0 -1
- package/lib/commonjs/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +269 -41
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/networking/xmppCredentials.js +80 -0
- package/lib/commonjs/networking/xmppCredentials.js.map +1 -0
- package/lib/commonjs/roomStore/Middleware/jumpThreadMiddleware.js +158 -0
- package/lib/commonjs/roomStore/Middleware/jumpThreadMiddleware.js.map +1 -0
- package/lib/commonjs/roomStore/Middleware/reactionsMiddleware.js +6 -0
- package/lib/commonjs/roomStore/Middleware/reactionsMiddleware.js.map +1 -1
- package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js +45 -7
- package/lib/commonjs/roomStore/Middleware/unreadMidlleware.js.map +1 -1
- package/lib/commonjs/roomStore/chatSettingsSlice.js +15 -1
- package/lib/commonjs/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/commonjs/roomStore/index.js +13 -3
- package/lib/commonjs/roomStore/index.js.map +1 -1
- package/lib/commonjs/roomStore/persistence.js +48 -1
- package/lib/commonjs/roomStore/persistence.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +474 -60
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/commonjs/roomStore/safeKey.js +44 -0
- package/lib/commonjs/roomStore/safeKey.js.map +1 -0
- package/lib/commonjs/roomStore/usersSetCap.js +37 -0
- package/lib/commonjs/roomStore/usersSetCap.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/assets/icons.js +1 -1
- package/lib/module/assets/icons.js.map +1 -1
- package/lib/module/components/Header/HeaderRoomList.js +23 -7
- package/lib/module/components/Header/HeaderRoomList.js.map +1 -1
- package/lib/module/components/InputComponents/Search.js +39 -2
- package/lib/module/components/InputComponents/Search.js.map +1 -1
- package/lib/module/components/MainComponents/ArchivedMessageCard.js +161 -0
- package/lib/module/components/MainComponents/ArchivedMessageCard.js.map +1 -0
- package/lib/module/components/MainComponents/ChatHeader.js +22 -5
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +57 -26
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +54 -5
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +18 -3
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +740 -42
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MainComponents/MessageSearchButton.js +48 -0
- package/lib/module/components/MainComponents/MessageSearchButton.js.map +1 -0
- package/lib/module/components/MainComponents/ReduxWrapper.js +15 -7
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/RoomList.js +111 -2
- package/lib/module/components/MainComponents/RoomList.js.map +1 -1
- package/lib/module/components/Menu/HeaderRoomListMenu.js +15 -4
- package/lib/module/components/Menu/HeaderRoomListMenu.js.map +1 -1
- package/lib/module/components/MessageBubble/BubbleHighlight.js +106 -0
- package/lib/module/components/MessageBubble/BubbleHighlight.js.map +1 -0
- package/lib/module/components/MessageBubble/Message.js +172 -127
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/MessageBubble/MessageInteractions.js +98 -78
- package/lib/module/components/MessageBubble/MessageInteractions.js.map +1 -1
- package/lib/module/components/MessageBubble/messageMenuLayout.js +45 -0
- package/lib/module/components/MessageBubble/messageMenuLayout.js.map +1 -0
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js +74 -38
- package/lib/module/components/Modals/ChatProfileModal/ChatProfileModal.js.map +1 -1
- package/lib/module/components/Modals/MessageSearchModal/MessageHitResults.js +243 -0
- package/lib/module/components/Modals/MessageSearchModal/MessageHitResults.js.map +1 -0
- package/lib/module/components/Modals/MessageSearchModal/MessageSearchModal.js +482 -0
- package/lib/module/components/Modals/MessageSearchModal/MessageSearchModal.js.map +1 -0
- package/lib/module/components/Modals/MessageSearchModal/openHit.js +45 -0
- package/lib/module/components/Modals/MessageSearchModal/openHit.js.map +1 -0
- package/lib/module/components/Modals/MessageSearchModal/resolveSender.js +41 -0
- package/lib/module/components/Modals/MessageSearchModal/resolveSender.js.map +1 -0
- package/lib/module/components/Modals/MessageSearchModal/searchFilters.js +74 -0
- package/lib/module/components/Modals/MessageSearchModal/searchFilters.js.map +1 -0
- package/lib/module/components/Modals/MessageSearchModal/snippet.js +57 -0
- package/lib/module/components/Modals/MessageSearchModal/snippet.js.map +1 -0
- package/lib/module/components/Modals/MessageSearchModal/useMessageSearch.js +131 -0
- package/lib/module/components/Modals/MessageSearchModal/useMessageSearch.js.map +1 -0
- package/lib/module/components/Modals/PublicChatsModal/PublicChatsModal.js +300 -0
- package/lib/module/components/Modals/PublicChatsModal/PublicChatsModal.js.map +1 -0
- package/lib/module/components/Modals/PublicChatsModal/publicChatsLogic.js +30 -0
- package/lib/module/components/Modals/PublicChatsModal/publicChatsLogic.js.map +1 -0
- package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js +8 -1
- package/lib/module/components/Modals/SelectUsersModal/SelectUsersModal.js.map +1 -1
- package/lib/module/components/RoomComponents/ChatRoomItem.js +14 -3
- package/lib/module/components/RoomComponents/ChatRoomItem.js.map +1 -1
- package/lib/module/components/RoomComponents/SwipeableRoomRow.js +39 -7
- package/lib/module/components/RoomComponents/SwipeableRoomRow.js.map +1 -1
- package/lib/module/components/Thread/ThreadHeader.js +3 -1
- package/lib/module/components/Thread/ThreadHeader.js.map +1 -1
- package/lib/module/components/Thread/ThreadWrapper.js +89 -9
- package/lib/module/components/Thread/ThreadWrapper.js.map +1 -1
- package/lib/module/components/styled/AudioDecoderHost.js +332 -0
- package/lib/module/components/styled/AudioDecoderHost.js.map +1 -0
- package/lib/module/components/styled/AudioMessage.js +495 -422
- package/lib/module/components/styled/AudioMessage.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +32 -6
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/context/MessageNotificationContext.js +15 -5
- package/lib/module/context/MessageNotificationContext.js.map +1 -1
- package/lib/module/context/xmppProvider.js +54 -79
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/audioWaveform.js +153 -0
- package/lib/module/helpers/audioWaveform.js.map +1 -0
- package/lib/module/helpers/backgroundJoinSweep.js +30 -0
- package/lib/module/helpers/backgroundJoinSweep.js.map +1 -0
- package/lib/module/helpers/bubbleHighlight.js +38 -0
- package/lib/module/helpers/bubbleHighlight.js.map +1 -0
- package/lib/module/helpers/checkUniqueUsers.js +15 -13
- package/lib/module/helpers/checkUniqueUsers.js.map +1 -1
- package/lib/module/helpers/constants/MODAL_COMPONENTS.js +5 -1
- package/lib/module/helpers/constants/MODAL_COMPONENTS.js.map +1 -1
- package/lib/module/helpers/constants/MODAL_TYPES.js +3 -1
- package/lib/module/helpers/constants/MODAL_TYPES.js.map +1 -1
- package/lib/module/helpers/createRoomFromApi.js +37 -3
- package/lib/module/helpers/createRoomFromApi.js.map +1 -1
- package/lib/module/helpers/dedupeMembers.js +28 -0
- package/lib/module/helpers/dedupeMembers.js.map +1 -0
- package/lib/module/helpers/ethoraLogger.js +52 -0
- package/lib/module/helpers/ethoraLogger.js.map +1 -0
- package/lib/module/helpers/getUnnamedUsers.js +9 -4
- package/lib/module/helpers/getUnnamedUsers.js.map +1 -1
- package/lib/module/helpers/historyPreloadConfig.js +39 -0
- package/lib/module/helpers/historyPreloadConfig.js.map +1 -0
- package/lib/module/helpers/historyPreloadScheduler.js +368 -134
- package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/module/helpers/initRoomsPresence.js +18 -5
- package/lib/module/helpers/initRoomsPresence.js.map +1 -1
- package/lib/module/helpers/insertMessageWithDelimiter.js +5 -0
- package/lib/module/helpers/insertMessageWithDelimiter.js.map +1 -1
- package/lib/module/helpers/isLikelyMucJid.js +60 -0
- package/lib/module/helpers/isLikelyMucJid.js.map +1 -0
- package/lib/module/helpers/isMessageSearchEnabled.js +13 -0
- package/lib/module/helpers/isMessageSearchEnabled.js.map +1 -0
- package/lib/module/helpers/joiningRoom.js +9 -0
- package/lib/module/helpers/joiningRoom.js.map +1 -0
- package/lib/module/helpers/jumpThread.js +83 -0
- package/lib/module/helpers/jumpThread.js.map +1 -0
- package/lib/module/helpers/jumpToMessage.js +52 -0
- package/lib/module/helpers/jumpToMessage.js.map +1 -0
- package/lib/module/helpers/jumpWindow.js +177 -0
- package/lib/module/helpers/jumpWindow.js.map +1 -0
- package/lib/module/helpers/loadRoomHistory.js +69 -0
- package/lib/module/helpers/loadRoomHistory.js.map +1 -0
- package/lib/module/helpers/notificationPolicy.js +70 -0
- package/lib/module/helpers/notificationPolicy.js.map +1 -0
- package/lib/module/helpers/openRoomAtMessage.js +41 -0
- package/lib/module/helpers/openRoomAtMessage.js.map +1 -0
- package/lib/module/helpers/openThreadForJump.js +68 -0
- package/lib/module/helpers/openThreadForJump.js.map +1 -0
- package/lib/module/helpers/parseMessageReference.js +26 -6
- package/lib/module/helpers/parseMessageReference.js.map +1 -1
- package/lib/module/helpers/publicChatsEntry.js +12 -0
- package/lib/module/helpers/publicChatsEntry.js.map +1 -0
- package/lib/module/helpers/roomActivityScore.js +30 -0
- package/lib/module/helpers/roomActivityScore.js.map +1 -0
- package/lib/module/helpers/roomUserCount.js +29 -0
- package/lib/module/helpers/roomUserCount.js.map +1 -0
- package/lib/module/helpers/runConfiguredHistoryPreload.js +63 -0
- package/lib/module/helpers/runConfiguredHistoryPreload.js.map +1 -0
- package/lib/module/helpers/sessionAppId.js +20 -0
- package/lib/module/helpers/sessionAppId.js.map +1 -0
- package/lib/module/helpers/timestamp.js +37 -0
- package/lib/module/helpers/timestamp.js.map +1 -0
- package/lib/module/helpers/userResolver.js +503 -0
- package/lib/module/helpers/userResolver.js.map +1 -0
- package/lib/module/helpers/xmppIdShape.js +46 -0
- package/lib/module/helpers/xmppIdShape.js.map +1 -0
- package/lib/module/hooks/useChatWrapperInit.js +16 -5
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useHeapSender.js +54 -3
- package/lib/module/hooks/useHeapSender.js.map +1 -1
- package/lib/module/hooks/useJumpToMessage.js +389 -0
- package/lib/module/hooks/useJumpToMessage.js.map +1 -0
- package/lib/module/hooks/useMessageLoaderQueue.js +32 -5
- package/lib/module/hooks/useMessageLoaderQueue.js.map +1 -1
- package/lib/module/hooks/useMessageQueue.js +13 -5
- package/lib/module/hooks/useMessageQueue.js.map +1 -1
- package/lib/module/hooks/useRoomDirectory.js +24 -0
- package/lib/module/hooks/useRoomDirectory.js.map +1 -0
- package/lib/module/hooks/useRoomInitialization.js +29 -7
- package/lib/module/hooks/useRoomInitialization.js.map +1 -1
- package/lib/module/hooks/useRoomMute.js +58 -0
- package/lib/module/hooks/useRoomMute.js.map +1 -0
- package/lib/module/hooks/useRoomState.js +3 -1
- package/lib/module/hooks/useRoomState.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +13 -3
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/i18n/strings.js +318 -6
- package/lib/module/i18n/strings.js.map +1 -1
- package/lib/module/networking/api-requests/messageSearch.api.js +81 -0
- package/lib/module/networking/api-requests/messageSearch.api.js.map +1 -0
- package/lib/module/networking/api-requests/publicChats.api.js +43 -0
- package/lib/module/networking/api-requests/publicChats.api.js.map +1 -0
- package/lib/module/networking/api-requests/roomMembers.api.js +248 -4
- package/lib/module/networking/api-requests/roomMembers.api.js.map +1 -1
- package/lib/module/networking/api-requests/rooms.api.js +48 -12
- package/lib/module/networking/api-requests/rooms.api.js.map +1 -1
- package/lib/module/networking/api-requests/xmppToken.api.js +66 -0
- package/lib/module/networking/api-requests/xmppToken.api.js.map +1 -0
- package/lib/module/networking/ethoraEvents.js +220 -0
- package/lib/module/networking/ethoraEvents.js.map +1 -0
- package/lib/module/networking/stanzaHandlers.js +155 -18
- package/lib/module/networking/stanzaHandlers.js.map +1 -1
- package/lib/module/networking/xmpp/allRoomPresences.xmpp.js +125 -3
- package/lib/module/networking/xmpp/allRoomPresences.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/getHistory.xmpp.js +318 -35
- package/lib/module/networking/xmpp/getHistory.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js +7 -0
- package/lib/module/networking/xmpp/handleStanzas.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/historyCursor.js +95 -0
- package/lib/module/networking/xmpp/historyCursor.js.map +1 -0
- package/lib/module/networking/xmpp/mamQueryIds.js +12 -0
- package/lib/module/networking/xmpp/mamQueryIds.js.map +1 -0
- package/lib/module/networking/xmpp/mamRouter.js +22 -8
- package/lib/module/networking/xmpp/mamRouter.js.map +1 -1
- package/lib/module/networking/xmpp/presenceInRoom.xmpp.js +68 -62
- package/lib/module/networking/xmpp/presenceInRoom.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/roomJoinSweep.js +385 -0
- package/lib/module/networking/xmpp/roomJoinSweep.js.map +1 -0
- package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js +0 -1
- package/lib/module/networking/xmpp/sendMediaMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js +0 -1
- package/lib/module/networking/xmpp/sendTextMessage.xmpp.js.map +1 -1
- package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js +0 -1
- package/lib/module/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.js.map +1 -1
- package/lib/module/networking/xmppClient.js +269 -41
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/networking/xmppCredentials.js +76 -0
- package/lib/module/networking/xmppCredentials.js.map +1 -0
- package/lib/module/roomStore/Middleware/jumpThreadMiddleware.js +153 -0
- package/lib/module/roomStore/Middleware/jumpThreadMiddleware.js.map +1 -0
- package/lib/module/roomStore/Middleware/reactionsMiddleware.js +6 -0
- package/lib/module/roomStore/Middleware/reactionsMiddleware.js.map +1 -1
- package/lib/module/roomStore/Middleware/unreadMidlleware.js +46 -7
- package/lib/module/roomStore/Middleware/unreadMidlleware.js.map +1 -1
- package/lib/module/roomStore/chatSettingsSlice.js +13 -0
- package/lib/module/roomStore/chatSettingsSlice.js.map +1 -1
- package/lib/module/roomStore/index.js +7 -3
- package/lib/module/roomStore/index.js.map +1 -1
- package/lib/module/roomStore/persistence.js +46 -1
- package/lib/module/roomStore/persistence.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +459 -58
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/roomStore/safeKey.js +37 -0
- package/lib/module/roomStore/safeKey.js.map +1 -0
- package/lib/module/roomStore/usersSetCap.js +32 -0
- package/lib/module/roomStore/usersSetCap.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/assets/icons.d.ts +4 -0
- package/lib/typescript/assets/icons.d.ts.map +1 -1
- package/lib/typescript/components/Header/HeaderRoomList.d.ts.map +1 -1
- package/lib/typescript/components/InputComponents/Search.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ArchivedMessageCard.d.ts +12 -0
- package/lib/typescript/components/MainComponents/ArchivedMessageCard.d.ts.map +1 -0
- 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.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts +22 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageSearchButton.d.ts +7 -0
- package/lib/typescript/components/MainComponents/MessageSearchButton.d.ts.map +1 -0
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/RoomList.d.ts.map +1 -1
- package/lib/typescript/components/Menu/HeaderRoomListMenu.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/BubbleHighlight.d.ts +12 -0
- package/lib/typescript/components/MessageBubble/BubbleHighlight.d.ts.map +1 -0
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts +5 -0
- package/lib/typescript/components/MessageBubble/MessageInteractions.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/messageMenuLayout.d.ts +29 -0
- package/lib/typescript/components/MessageBubble/messageMenuLayout.d.ts.map +1 -0
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts +2 -0
- package/lib/typescript/components/Modals/ChatProfileModal/ChatProfileModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/MessageSearchModal/MessageHitResults.d.ts +44 -0
- package/lib/typescript/components/Modals/MessageSearchModal/MessageHitResults.d.ts.map +1 -0
- package/lib/typescript/components/Modals/MessageSearchModal/MessageSearchModal.d.ts +12 -0
- package/lib/typescript/components/Modals/MessageSearchModal/MessageSearchModal.d.ts.map +1 -0
- package/lib/typescript/components/Modals/MessageSearchModal/openHit.d.ts +15 -0
- package/lib/typescript/components/Modals/MessageSearchModal/openHit.d.ts.map +1 -0
- package/lib/typescript/components/Modals/MessageSearchModal/resolveSender.d.ts +34 -0
- package/lib/typescript/components/Modals/MessageSearchModal/resolveSender.d.ts.map +1 -0
- package/lib/typescript/components/Modals/MessageSearchModal/searchFilters.d.ts +41 -0
- package/lib/typescript/components/Modals/MessageSearchModal/searchFilters.d.ts.map +1 -0
- package/lib/typescript/components/Modals/MessageSearchModal/snippet.d.ts +15 -0
- package/lib/typescript/components/Modals/MessageSearchModal/snippet.d.ts.map +1 -0
- package/lib/typescript/components/Modals/MessageSearchModal/useMessageSearch.d.ts +23 -0
- package/lib/typescript/components/Modals/MessageSearchModal/useMessageSearch.d.ts.map +1 -0
- package/lib/typescript/components/Modals/PublicChatsModal/PublicChatsModal.d.ts +16 -0
- package/lib/typescript/components/Modals/PublicChatsModal/PublicChatsModal.d.ts.map +1 -0
- package/lib/typescript/components/Modals/PublicChatsModal/publicChatsLogic.d.ts +14 -0
- package/lib/typescript/components/Modals/PublicChatsModal/publicChatsLogic.d.ts.map +1 -0
- package/lib/typescript/components/Modals/SelectUsersModal/SelectUsersModal.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/ChatRoomItem.d.ts.map +1 -1
- package/lib/typescript/components/RoomComponents/SwipeableRoomRow.d.ts +5 -1
- package/lib/typescript/components/RoomComponents/SwipeableRoomRow.d.ts.map +1 -1
- package/lib/typescript/components/Thread/ThreadHeader.d.ts.map +1 -1
- package/lib/typescript/components/Thread/ThreadWrapper.d.ts +1 -0
- package/lib/typescript/components/Thread/ThreadWrapper.d.ts.map +1 -1
- package/lib/typescript/components/styled/AudioDecoderHost.d.ts +39 -0
- package/lib/typescript/components/styled/AudioDecoderHost.d.ts.map +1 -0
- package/lib/typescript/components/styled/AudioMessage.d.ts +14 -1
- package/lib/typescript/components/styled/AudioMessage.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/context/MessageNotificationContext.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts +2 -0
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/audioWaveform.d.ts +54 -0
- package/lib/typescript/helpers/audioWaveform.d.ts.map +1 -0
- package/lib/typescript/helpers/backgroundJoinSweep.d.ts +14 -0
- package/lib/typescript/helpers/backgroundJoinSweep.d.ts.map +1 -0
- package/lib/typescript/helpers/bubbleHighlight.d.ts +17 -0
- package/lib/typescript/helpers/bubbleHighlight.d.ts.map +1 -0
- package/lib/typescript/helpers/checkUniqueUsers.d.ts +2 -2
- package/lib/typescript/helpers/checkUniqueUsers.d.ts.map +1 -1
- package/lib/typescript/helpers/constants/MODAL_COMPONENTS.d.ts.map +1 -1
- package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts +2 -0
- package/lib/typescript/helpers/constants/MODAL_TYPES.d.ts.map +1 -1
- package/lib/typescript/helpers/createRoomFromApi.d.ts +25 -0
- package/lib/typescript/helpers/createRoomFromApi.d.ts.map +1 -1
- package/lib/typescript/helpers/dedupeMembers.d.ts +11 -0
- package/lib/typescript/helpers/dedupeMembers.d.ts.map +1 -0
- package/lib/typescript/helpers/ethoraLogger.d.ts +13 -0
- package/lib/typescript/helpers/ethoraLogger.d.ts.map +1 -0
- package/lib/typescript/helpers/getUnnamedUsers.d.ts.map +1 -1
- package/lib/typescript/helpers/historyPreloadConfig.d.ts +26 -0
- package/lib/typescript/helpers/historyPreloadConfig.d.ts.map +1 -0
- package/lib/typescript/helpers/historyPreloadScheduler.d.ts +8 -4
- package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
- package/lib/typescript/helpers/initRoomsPresence.d.ts +7 -0
- package/lib/typescript/helpers/initRoomsPresence.d.ts.map +1 -1
- package/lib/typescript/helpers/insertMessageWithDelimiter.d.ts.map +1 -1
- package/lib/typescript/helpers/isLikelyMucJid.d.ts +19 -0
- package/lib/typescript/helpers/isLikelyMucJid.d.ts.map +1 -0
- package/lib/typescript/helpers/isMessageSearchEnabled.d.ts +12 -0
- package/lib/typescript/helpers/isMessageSearchEnabled.d.ts.map +1 -0
- package/lib/typescript/helpers/joiningRoom.d.ts +7 -0
- package/lib/typescript/helpers/joiningRoom.d.ts.map +1 -0
- package/lib/typescript/helpers/jumpThread.d.ts +48 -0
- package/lib/typescript/helpers/jumpThread.d.ts.map +1 -0
- package/lib/typescript/helpers/jumpToMessage.d.ts +26 -0
- package/lib/typescript/helpers/jumpToMessage.d.ts.map +1 -0
- package/lib/typescript/helpers/jumpWindow.d.ts +74 -0
- package/lib/typescript/helpers/jumpWindow.d.ts.map +1 -0
- package/lib/typescript/helpers/loadRoomHistory.d.ts +34 -0
- package/lib/typescript/helpers/loadRoomHistory.d.ts.map +1 -0
- package/lib/typescript/helpers/notificationPolicy.d.ts +42 -0
- package/lib/typescript/helpers/notificationPolicy.d.ts.map +1 -0
- package/lib/typescript/helpers/openRoomAtMessage.d.ts +17 -0
- package/lib/typescript/helpers/openRoomAtMessage.d.ts.map +1 -0
- package/lib/typescript/helpers/openThreadForJump.d.ts +27 -0
- package/lib/typescript/helpers/openThreadForJump.d.ts.map +1 -0
- package/lib/typescript/helpers/parseMessageReference.d.ts +18 -5
- package/lib/typescript/helpers/parseMessageReference.d.ts.map +1 -1
- package/lib/typescript/helpers/publicChatsEntry.d.ts +11 -0
- package/lib/typescript/helpers/publicChatsEntry.d.ts.map +1 -0
- package/lib/typescript/helpers/roomActivityScore.d.ts +5 -0
- package/lib/typescript/helpers/roomActivityScore.d.ts.map +1 -0
- package/lib/typescript/helpers/roomUserCount.d.ts +20 -0
- package/lib/typescript/helpers/roomUserCount.d.ts.map +1 -0
- package/lib/typescript/helpers/runConfiguredHistoryPreload.d.ts +21 -0
- package/lib/typescript/helpers/runConfiguredHistoryPreload.d.ts.map +1 -0
- package/lib/typescript/helpers/sessionAppId.d.ts +8 -0
- package/lib/typescript/helpers/sessionAppId.d.ts.map +1 -0
- package/lib/typescript/helpers/timestamp.d.ts +3 -0
- package/lib/typescript/helpers/timestamp.d.ts.map +1 -0
- package/lib/typescript/helpers/userResolver.d.ts +58 -0
- package/lib/typescript/helpers/userResolver.d.ts.map +1 -0
- package/lib/typescript/helpers/xmppIdShape.d.ts +10 -0
- package/lib/typescript/helpers/xmppIdShape.d.ts.map +1 -0
- package/lib/typescript/hooks/useChatWrapperInit.d.ts +2 -0
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useHeapSender.d.ts.map +1 -1
- package/lib/typescript/hooks/useJumpToMessage.d.ts +116 -0
- package/lib/typescript/hooks/useJumpToMessage.d.ts.map +1 -0
- package/lib/typescript/hooks/useMessageLoaderQueue.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageQueue.d.ts.map +1 -1
- package/lib/typescript/hooks/useRoomDirectory.d.ts +12 -0
- package/lib/typescript/hooks/useRoomDirectory.d.ts.map +1 -0
- package/lib/typescript/hooks/useRoomInitialization.d.ts.map +1 -1
- package/lib/typescript/hooks/useRoomMute.d.ts +8 -0
- package/lib/typescript/hooks/useRoomMute.d.ts.map +1 -0
- 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/i18n/strings.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/messageSearch.api.d.ts +57 -0
- package/lib/typescript/networking/api-requests/messageSearch.api.d.ts.map +1 -0
- package/lib/typescript/networking/api-requests/publicChats.api.d.ts +24 -0
- package/lib/typescript/networking/api-requests/publicChats.api.d.ts.map +1 -0
- package/lib/typescript/networking/api-requests/roomMembers.api.d.ts +19 -1
- package/lib/typescript/networking/api-requests/roomMembers.api.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/rooms.api.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/xmppToken.api.d.ts +2 -0
- package/lib/typescript/networking/api-requests/xmppToken.api.d.ts.map +1 -0
- package/lib/typescript/networking/ethoraEvents.d.ts +45 -0
- package/lib/typescript/networking/ethoraEvents.d.ts.map +1 -0
- package/lib/typescript/networking/stanzaHandlers.d.ts +1 -1
- package/lib/typescript/networking/stanzaHandlers.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/allRoomPresences.xmpp.d.ts +32 -1
- package/lib/typescript/networking/xmpp/allRoomPresences.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/getHistory.xmpp.d.ts +64 -0
- package/lib/typescript/networking/xmpp/getHistory.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/handleStanzas.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/historyCursor.d.ts +35 -0
- package/lib/typescript/networking/xmpp/historyCursor.d.ts.map +1 -0
- package/lib/typescript/networking/xmpp/mamQueryIds.d.ts +10 -0
- package/lib/typescript/networking/xmpp/mamQueryIds.d.ts.map +1 -0
- package/lib/typescript/networking/xmpp/mamRouter.d.ts +7 -0
- package/lib/typescript/networking/xmpp/mamRouter.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts +13 -2
- package/lib/typescript/networking/xmpp/presenceInRoom.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/roomJoinSweep.d.ts +82 -0
- package/lib/typescript/networking/xmpp/roomJoinSweep.d.ts.map +1 -0
- package/lib/typescript/networking/xmpp/sendMediaMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessage.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +90 -4
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/networking/xmppCredentials.d.ts +12 -0
- package/lib/typescript/networking/xmppCredentials.d.ts.map +1 -0
- package/lib/typescript/roomStore/Middleware/jumpThreadMiddleware.d.ts +3 -0
- package/lib/typescript/roomStore/Middleware/jumpThreadMiddleware.d.ts.map +1 -0
- package/lib/typescript/roomStore/Middleware/reactionsMiddleware.d.ts.map +1 -1
- package/lib/typescript/roomStore/Middleware/unreadMidlleware.d.ts.map +1 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts +8 -1
- package/lib/typescript/roomStore/chatSettingsSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/index.d.ts +2 -1
- package/lib/typescript/roomStore/index.d.ts.map +1 -1
- package/lib/typescript/roomStore/persistence.d.ts +8 -0
- package/lib/typescript/roomStore/persistence.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +138 -2
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/roomStore/safeKey.d.ts +13 -0
- package/lib/typescript/roomStore/safeKey.d.ts.map +1 -0
- package/lib/typescript/roomStore/usersSetCap.d.ts +16 -0
- package/lib/typescript/roomStore/usersSetCap.d.ts.map +1 -0
- package/lib/typescript/types/models/media.model.d.ts +2 -0
- package/lib/typescript/types/models/media.model.d.ts.map +1 -1
- package/lib/typescript/types/models/room.model.d.ts +18 -5
- package/lib/typescript/types/models/room.model.d.ts.map +1 -1
- package/lib/typescript/types/models/xmpp.model.d.ts +8 -1
- package/lib/typescript/types/models/xmpp.model.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +90 -5
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/lib/typescript/version.d.ts +1 -1
- package/lib/typescript/version.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/assets/icons.tsx +13 -0
- package/src/components/Header/HeaderRoomList.tsx +21 -4
- package/src/components/InputComponents/Search.tsx +33 -0
- package/src/components/MainComponents/ArchivedMessageCard.tsx +139 -0
- package/src/components/MainComponents/ChatHeader.tsx +19 -3
- package/src/components/MainComponents/ChatRoom.tsx +60 -23
- package/src/components/MainComponents/ChatWrapper.tsx +50 -9
- package/src/components/MainComponents/MediaMessage.tsx +17 -0
- package/src/components/MainComponents/MessageList.tsx +823 -84
- package/src/components/MainComponents/MessageSearchButton.tsx +48 -0
- package/src/components/MainComponents/ReduxWrapper.tsx +16 -5
- package/src/components/MainComponents/RoomList.tsx +125 -0
- package/src/components/Menu/HeaderRoomListMenu.tsx +26 -2
- package/src/components/MessageBubble/BubbleHighlight.tsx +106 -0
- package/src/components/MessageBubble/Message.tsx +265 -177
- package/src/components/MessageBubble/MessageInteractions.tsx +109 -86
- package/src/components/MessageBubble/messageMenuLayout.ts +59 -0
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +92 -21
- package/src/components/Modals/MessageSearchModal/MessageHitResults.tsx +271 -0
- package/src/components/Modals/MessageSearchModal/MessageSearchModal.tsx +487 -0
- package/src/components/Modals/MessageSearchModal/openHit.ts +50 -0
- package/src/components/Modals/MessageSearchModal/resolveSender.ts +57 -0
- package/src/components/Modals/MessageSearchModal/searchFilters.ts +109 -0
- package/src/components/Modals/MessageSearchModal/snippet.ts +58 -0
- package/src/components/Modals/MessageSearchModal/useMessageSearch.ts +151 -0
- package/src/components/Modals/PublicChatsModal/PublicChatsModal.tsx +288 -0
- package/src/components/Modals/PublicChatsModal/publicChatsLogic.ts +36 -0
- package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +8 -1
- package/src/components/RoomComponents/ChatRoomItem.tsx +16 -3
- package/src/components/RoomComponents/SwipeableRoomRow.tsx +39 -6
- package/src/components/Thread/ThreadHeader.tsx +3 -1
- package/src/components/Thread/ThreadWrapper.tsx +96 -10
- package/src/components/styled/AudioDecoderHost.tsx +351 -0
- package/src/components/styled/AudioMessage.tsx +482 -425
- package/src/components/styled/SendInput.tsx +42 -4
- package/src/context/MessageNotificationContext.tsx +19 -5
- package/src/context/xmppProvider.tsx +56 -91
- package/src/helpers/audioWaveform.ts +142 -0
- package/src/helpers/backgroundJoinSweep.ts +35 -0
- package/src/helpers/bubbleHighlight.ts +47 -0
- package/src/helpers/checkUniqueUsers.tsx +15 -17
- package/src/helpers/constants/MODAL_COMPONENTS.tsx +4 -0
- package/src/helpers/constants/MODAL_TYPES.ts +3 -0
- package/src/helpers/createRoomFromApi.tsx +45 -4
- package/src/helpers/dedupeMembers.ts +29 -0
- package/src/helpers/ethoraLogger.ts +50 -0
- package/src/helpers/getUnnamedUsers.ts +7 -4
- package/src/helpers/historyPreloadConfig.ts +68 -0
- package/src/helpers/historyPreloadScheduler.ts +437 -199
- package/src/helpers/initRoomsPresence.ts +20 -7
- package/src/helpers/insertMessageWithDelimiter.ts +3 -0
- package/src/helpers/isLikelyMucJid.ts +72 -0
- package/src/helpers/isMessageSearchEnabled.ts +18 -0
- package/src/helpers/joiningRoom.ts +13 -0
- package/src/helpers/jumpThread.ts +102 -0
- package/src/helpers/jumpToMessage.ts +57 -0
- package/src/helpers/jumpWindow.ts +212 -0
- package/src/helpers/loadRoomHistory.ts +83 -0
- package/src/helpers/notificationPolicy.ts +82 -0
- package/src/helpers/openRoomAtMessage.ts +38 -0
- package/src/helpers/openThreadForJump.ts +96 -0
- package/src/helpers/parseMessageReference.ts +37 -8
- package/src/helpers/publicChatsEntry.ts +15 -0
- package/src/helpers/roomActivityScore.ts +45 -0
- package/src/helpers/roomUserCount.ts +44 -0
- package/src/helpers/runConfiguredHistoryPreload.ts +76 -0
- package/src/helpers/sessionAppId.ts +17 -0
- package/src/helpers/timestamp.ts +44 -0
- package/src/helpers/userResolver.ts +542 -0
- package/src/helpers/xmppIdShape.ts +46 -0
- package/src/hooks/useChatWrapperInit.ts +22 -4
- package/src/hooks/useHeapSender.tsx +54 -3
- package/src/hooks/useJumpToMessage.ts +538 -0
- package/src/hooks/useMessageLoaderQueue.tsx +40 -4
- package/src/hooks/useMessageQueue.ts +9 -5
- package/src/hooks/useRoomDirectory.ts +39 -0
- package/src/hooks/useRoomInitialization.tsx +33 -7
- package/src/hooks/useRoomMute.ts +42 -0
- package/src/hooks/useRoomState.tsx +6 -0
- package/src/hooks/useSendMessage.tsx +14 -2
- package/src/i18n/strings.ts +312 -0
- package/src/networking/api-requests/messageSearch.api.ts +130 -0
- package/src/networking/api-requests/publicChats.api.ts +71 -0
- package/src/networking/api-requests/roomMembers.api.ts +263 -11
- package/src/networking/api-requests/rooms.api.ts +52 -12
- package/src/networking/api-requests/xmppToken.api.ts +62 -0
- package/src/networking/ethoraEvents.ts +262 -0
- package/src/networking/stanzaHandlers.ts +145 -19
- package/src/networking/xmpp/allRoomPresences.xmpp.ts +155 -5
- package/src/networking/xmpp/getHistory.xmpp.ts +433 -47
- package/src/networking/xmpp/handleStanzas.xmpp.ts +8 -0
- package/src/networking/xmpp/historyCursor.ts +124 -0
- package/src/networking/xmpp/mamQueryIds.ts +11 -0
- package/src/networking/xmpp/mamRouter.ts +24 -10
- package/src/networking/xmpp/presenceInRoom.xmpp.ts +91 -68
- package/src/networking/xmpp/roomJoinSweep.ts +412 -0
- package/src/networking/xmpp/sendMediaMessage.xmpp.ts +0 -1
- package/src/networking/xmpp/sendTextMessage.xmpp.ts +0 -1
- package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +0 -1
- package/src/networking/xmppClient.ts +323 -47
- package/src/networking/xmppCredentials.ts +87 -0
- package/src/roomStore/Middleware/jumpThreadMiddleware.ts +163 -0
- package/src/roomStore/Middleware/reactionsMiddleware.tsx +4 -0
- package/src/roomStore/Middleware/unreadMidlleware.tsx +59 -11
- package/src/roomStore/chatSettingsSlice.ts +11 -0
- package/src/roomStore/index.ts +10 -3
- package/src/roomStore/persistence.ts +54 -0
- package/src/roomStore/roomsSlice.ts +547 -65
- package/src/roomStore/safeKey.ts +49 -0
- package/src/roomStore/usersSetCap.ts +37 -0
- package/src/types/models/media.model.ts +4 -0
- package/src/types/models/room.model.ts +18 -5
- package/src/types/models/xmpp.model.ts +15 -1
- package/src/types/types.ts +95 -5
- package/src/version.ts +1 -1
|
@@ -31,6 +31,18 @@ import {
|
|
|
31
31
|
requestRecordingPermissionsAsync,
|
|
32
32
|
RecordingPresets,
|
|
33
33
|
} from 'expo-audio';
|
|
34
|
+
import {
|
|
35
|
+
WAVEFORM_RESOLUTION,
|
|
36
|
+
encodeWaveForm,
|
|
37
|
+
meteringToLevel,
|
|
38
|
+
resamplePeaks,
|
|
39
|
+
scaleLevels,
|
|
40
|
+
} from '../../helpers/audioWaveform';
|
|
41
|
+
|
|
42
|
+
// The voice preset with metering on: the recorder's level, sampled while
|
|
43
|
+
// recording, becomes the waveform the message carries (Telegram-style), so
|
|
44
|
+
// receivers draw it without downloading and decoding the clip first.
|
|
45
|
+
const VOICE_PRESET = { ...RecordingPresets.HIGH_QUALITY, isMeteringEnabled: true };
|
|
34
46
|
|
|
35
47
|
// iOS photos default to HEIC; many web backends (incl. ours) 500 on
|
|
36
48
|
// HEIC uploads because they can't decode it. Convert to JPEG before
|
|
@@ -121,12 +133,15 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
121
133
|
// Nothing claims the mic, writes a file, or switches the iOS session to
|
|
122
134
|
// playAndRecord until `prepareToRecordAsync`, so consumers with
|
|
123
135
|
// `enableAudio` off carry an idle object and nothing more.
|
|
124
|
-
const audioRecorder = useAudioRecorder(
|
|
136
|
+
const audioRecorder = useAudioRecorder(VOICE_PRESET);
|
|
125
137
|
// Tracks whether a recording is actually in flight, so cancel/stop and
|
|
126
138
|
// the unmount teardown can tell "never started" from "needs stopping"
|
|
127
139
|
// without reading native state.
|
|
128
140
|
const isRecordingRef = useRef(false);
|
|
129
141
|
const recordingTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
|
142
|
+
// Level samples of the take in flight, and when it started.
|
|
143
|
+
const recordingLevelsRef = useRef<number[]>([]);
|
|
144
|
+
const recordingStartedAtRef = useRef(0);
|
|
130
145
|
|
|
131
146
|
// Refs shadow `message` and `filePreviews` so handleSendClick can:
|
|
132
147
|
// (a) read the LATEST typed value even when React state hasn't
|
|
@@ -425,16 +440,26 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
425
440
|
// side allocate a FRESH output file for this take. Without it the
|
|
426
441
|
// recorder reuses the previous URL, so a second voice message would
|
|
427
442
|
// overwrite the first while its upload is still in flight.
|
|
428
|
-
await audioRecorder.prepareToRecordAsync(
|
|
443
|
+
await audioRecorder.prepareToRecordAsync(VOICE_PRESET);
|
|
429
444
|
audioRecorder.record();
|
|
430
445
|
isRecordingRef.current = true;
|
|
431
446
|
setIsRecording(true);
|
|
432
447
|
setRecordingDuration(0);
|
|
433
448
|
const startedAt = Date.now();
|
|
434
|
-
|
|
449
|
+
recordingStartedAtRef.current = startedAt;
|
|
450
|
+
recordingLevelsRef.current = [];
|
|
451
|
+
// 100ms: often enough for the waveform's level samples; the seconds
|
|
452
|
+
// counter only re-renders when its value actually changes.
|
|
435
453
|
recordingTimerRef.current = setInterval(() => {
|
|
454
|
+
try {
|
|
455
|
+
recordingLevelsRef.current.push(
|
|
456
|
+
meteringToLevel(audioRecorder.getStatus().metering)
|
|
457
|
+
);
|
|
458
|
+
} catch {
|
|
459
|
+
/* no level this tick */
|
|
460
|
+
}
|
|
436
461
|
setRecordingDuration(Math.floor((Date.now() - startedAt) / 1000));
|
|
437
|
-
},
|
|
462
|
+
}, 100);
|
|
438
463
|
} catch (err) {
|
|
439
464
|
console.warn('startRecording failed', err);
|
|
440
465
|
isRecordingRef.current = false;
|
|
@@ -495,10 +520,23 @@ const SendInput: React.FC<SendInputProps> = ({
|
|
|
495
520
|
// matches the receiver's audio branch in MediaMessage (and
|
|
496
521
|
// isLikelyAudio for any backend that strips mimetype).
|
|
497
522
|
const ts = Date.now();
|
|
523
|
+
const levels = recordingLevelsRef.current;
|
|
524
|
+
recordingLevelsRef.current = [];
|
|
498
525
|
const file: MediaFile = {
|
|
499
526
|
uri,
|
|
500
527
|
type: 'audio/m4a',
|
|
501
528
|
name: `voice-${ts}.m4a`,
|
|
529
|
+
duration: Math.max(
|
|
530
|
+
1,
|
|
531
|
+
Math.round((ts - recordingStartedAtRef.current) / 1000)
|
|
532
|
+
),
|
|
533
|
+
// No levels (metering unsupported) → no waveForm; receivers then
|
|
534
|
+
// decode the clip for its bars.
|
|
535
|
+
waveForm: levels.some((level) => level > 0)
|
|
536
|
+
? encodeWaveForm(
|
|
537
|
+
scaleLevels(resamplePeaks(levels, WAVEFORM_RESOLUTION))
|
|
538
|
+
)
|
|
539
|
+
: undefined,
|
|
502
540
|
};
|
|
503
541
|
try {
|
|
504
542
|
await sendMedia(file, file.type);
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
View,
|
|
25
25
|
} from 'react-native';
|
|
26
26
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
27
|
-
import { useDispatch, useSelector } from 'react-redux';
|
|
27
|
+
import { useDispatch, useSelector, useStore } from 'react-redux';
|
|
28
28
|
import { messageNotificationManager } from '../utils/messageNotificationManager';
|
|
29
29
|
import { setCurrentRoom } from '../roomStore/roomsSlice';
|
|
30
30
|
import { IConfig, IMessage } from '../types/types';
|
|
@@ -33,6 +33,7 @@ import { useTheme } from '../hooks/useTheme';
|
|
|
33
33
|
import { ProfileImagePlaceholder } from '../components/MainComponents/ProfileImagePlaceholder';
|
|
34
34
|
import { useFileToken } from '../hooks/useFileToken';
|
|
35
35
|
import { appendFileToken } from '../helpers/secureFileUrl';
|
|
36
|
+
import { bareJid, shouldToastForRoom } from '../helpers/notificationPolicy';
|
|
36
37
|
|
|
37
38
|
interface ToastItem {
|
|
38
39
|
id: string;
|
|
@@ -102,6 +103,7 @@ export const MessageNotificationProvider: React.FC<ProviderProps> = ({
|
|
|
102
103
|
// below is only its safety net.
|
|
103
104
|
const pruneAfter = bannerMode ? duration + 2000 : duration;
|
|
104
105
|
|
|
106
|
+
const store = useStore<RootState>();
|
|
105
107
|
const [toasts, setToasts] = useState<ToastItem[]>([]);
|
|
106
108
|
const appActiveRef = useRef(AppState.currentState === 'active');
|
|
107
109
|
|
|
@@ -134,7 +136,8 @@ export const MessageNotificationProvider: React.FC<ProviderProps> = ({
|
|
|
134
136
|
// Clear toasts when their room becomes active.
|
|
135
137
|
useEffect(() => {
|
|
136
138
|
if (!visibleRoomJID) {return;}
|
|
137
|
-
|
|
139
|
+
const open = bareJid(visibleRoomJID);
|
|
140
|
+
setToasts((prev) => prev.filter((t) => bareJid(t.roomJID) !== open));
|
|
138
141
|
}, [visibleRoomJID]);
|
|
139
142
|
|
|
140
143
|
const dismiss = useCallback((id: string) => {
|
|
@@ -170,8 +173,19 @@ export const MessageNotificationProvider: React.FC<ProviderProps> = ({
|
|
|
170
173
|
roomJID: string
|
|
171
174
|
) => {
|
|
172
175
|
if (!isEnabled) {return;}
|
|
173
|
-
//
|
|
174
|
-
|
|
176
|
+
// Decided on the store as it is NOW, not on this render's closure:
|
|
177
|
+
// the open chat, a muted chat and a backgrounded app never toast.
|
|
178
|
+
const rooms = store.getState().rooms;
|
|
179
|
+
if (
|
|
180
|
+
!shouldToastForRoom({
|
|
181
|
+
roomJID,
|
|
182
|
+
visibleRoomJID: rooms.visibleRoomJID,
|
|
183
|
+
appActive: appActiveRef.current,
|
|
184
|
+
muted: rooms.rooms[roomJID]?.muted,
|
|
185
|
+
})
|
|
186
|
+
) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
175
189
|
const id = `msg-notification-${message.id}-${Date.now()}`;
|
|
176
190
|
const item: ToastItem = {
|
|
177
191
|
id,
|
|
@@ -188,7 +202,7 @@ export const MessageNotificationProvider: React.FC<ProviderProps> = ({
|
|
|
188
202
|
: next;
|
|
189
203
|
});
|
|
190
204
|
},
|
|
191
|
-
[isEnabled,
|
|
205
|
+
[isEnabled, store, maxNotifications]
|
|
192
206
|
);
|
|
193
207
|
|
|
194
208
|
// Register with the global manager.
|
|
@@ -14,6 +14,7 @@ import { VideoCallOverlay } from '../components/VideoCalls/VideoCallOverlay';
|
|
|
14
14
|
import XmppClient, {
|
|
15
15
|
XmppCredentialsProvider,
|
|
16
16
|
} from '../networking/xmppClient';
|
|
17
|
+
import { recoverXmppCredentials } from '../networking/xmppCredentials';
|
|
17
18
|
import { refreshAuthTokensQuietly } from '../networking/authRefresh';
|
|
18
19
|
import {
|
|
19
20
|
IConfig,
|
|
@@ -31,12 +32,11 @@ import {
|
|
|
31
32
|
} from '../utils/clientRegistry';
|
|
32
33
|
import {
|
|
33
34
|
applyResolvedUserToStore,
|
|
34
|
-
refreshUserCredentialsForXmpp,
|
|
35
35
|
resolveInitBeforeLoadUser,
|
|
36
36
|
} from '../helpers/resolveInitBeforeLoadUser';
|
|
37
37
|
import { ensureScopedChatCache } from '../helpers/ensureScopedChatCache';
|
|
38
38
|
import { getRooms as prefetchRoomsViaRest } from '../networking/api-requests/rooms.api';
|
|
39
|
-
import {
|
|
39
|
+
import { startBackgroundJoinSweep } from '../helpers/backgroundJoinSweep';
|
|
40
40
|
import { pushSubscriptionService } from '../services/pushSubscriptionService';
|
|
41
41
|
import { store } from '../roomStore';
|
|
42
42
|
import {
|
|
@@ -58,7 +58,7 @@ import {
|
|
|
58
58
|
getFlushBoundaryTs,
|
|
59
59
|
getReadMarkerTimestamp,
|
|
60
60
|
} from '../helpers/getServerReadTimestamp';
|
|
61
|
-
import {
|
|
61
|
+
import { runConfiguredHistoryPreload } from '../helpers/runConfiguredHistoryPreload';
|
|
62
62
|
import { updateMessagesTillLast } from '../helpers/updateMessagesTillLast';
|
|
63
63
|
import { secureUserStorage } from '../helpers/secureUserStorage';
|
|
64
64
|
import { clearPersistedState } from '../roomStore/persistence';
|
|
@@ -103,10 +103,16 @@ const subscribeAllRoomsForPush = (client: any, reason: string) => {
|
|
|
103
103
|
.catch((e) => devPushLog('warn', `${reason}: mucsub subscribe failed`, e));
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
+
/** Emitted once the session ended because the XMPP password is gone for good. */
|
|
107
|
+
export const SESSION_LOST_EVENT = 'ethora:sessionLost';
|
|
108
|
+
|
|
106
109
|
export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, isVisible }) => {
|
|
107
110
|
const [client, setClient] = useState<XmppClient | null>(null);
|
|
108
111
|
const [providerBootstrapStatus, setProviderBootstrapStatus] =
|
|
109
112
|
useState<ProviderBootstrapStatus>('idle');
|
|
113
|
+
// Bumped by "Retry": the bootstrap effect keys on it, so a retry re-runs
|
|
114
|
+
// the bootstrap with the same config instead of waiting for a change.
|
|
115
|
+
const [bootstrapNonce, setBootstrapNonce] = useState(0);
|
|
110
116
|
|
|
111
117
|
// Track which "init mode" this provider runs in. When config.initBeforeLoad
|
|
112
118
|
// is true, the provider owns bootstrap and ChatWrapper just waits.
|
|
@@ -126,62 +132,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
126
132
|
// Returns last-known cached creds if nothing usable is available so
|
|
127
133
|
// the XmppClient at least doesn't crash on `undefined.password`.
|
|
128
134
|
const credentialsProvider = useMemo<XmppCredentialsProvider>(() => {
|
|
129
|
-
return
|
|
130
|
-
// 1. Make sure the REST tokens are fresh before re-minting XMPP
|
|
131
|
-
// creds. This used to call `config.refreshTokens.refreshFunction`
|
|
132
|
-
// directly and then fall into step 2, which refreshes again —
|
|
133
|
-
// two rotations back to back, which the new backend scheme
|
|
134
|
-
// reads as a race at best and token reuse at worst. One call to
|
|
135
|
-
// the shared rotation point covers both the consumer-supplied
|
|
136
|
-
// function and the built-in endpoint.
|
|
137
|
-
if (config?.refreshTokens?.enabled) {
|
|
138
|
-
const rotated = await refreshAuthTokensQuietly({ force: true });
|
|
139
|
-
|
|
140
|
-
if (rotated?.xmppPassword) {
|
|
141
|
-
const rotatedUser = store.getState().chatSettingStore.user;
|
|
142
|
-
return {
|
|
143
|
-
username:
|
|
144
|
-
rotatedUser?.xmppUsername ||
|
|
145
|
-
rotatedUser?.defaultWallet?.walletAddress ||
|
|
146
|
-
'',
|
|
147
|
-
password: rotated.xmppPassword,
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 2. Re-mint XMPP creds via the right priority chain for the
|
|
153
|
-
// current auth mode. This call ALWAYS hydrates (unlike
|
|
154
|
-
// `resolveInitBeforeLoadUser` which short-circuits when a
|
|
155
|
-
// cached user already has xmppCredentials).
|
|
156
|
-
const fresh = await refreshUserCredentialsForXmpp(config).catch(
|
|
157
|
-
(err) => {
|
|
158
|
-
devPushLog('warn', 'XMPP creds refresh: full chain failed', err);
|
|
159
|
-
return null;
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
if (fresh) {
|
|
163
|
-
applyResolvedUserToStore(fresh);
|
|
164
|
-
return {
|
|
165
|
-
username:
|
|
166
|
-
fresh.xmppUsername ||
|
|
167
|
-
fresh.defaultWallet?.walletAddress ||
|
|
168
|
-
'',
|
|
169
|
-
password: fresh.xmppPassword || '',
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 3. Last-resort: return the cached creds so reconnect() can
|
|
174
|
-
// still attempt a connection. If the original failure was
|
|
175
|
-
// a stale JWT this will fail again and the user has to
|
|
176
|
-
// re-mount the chat — but at least we don't break the
|
|
177
|
-
// transient-network-blip case where the cached creds are
|
|
178
|
-
// still valid.
|
|
179
|
-
const u = store.getState().chatSettingStore.user;
|
|
180
|
-
return {
|
|
181
|
-
username: u?.xmppUsername || u?.defaultWallet?.walletAddress || '',
|
|
182
|
-
password: u?.xmppPassword || '',
|
|
183
|
-
};
|
|
184
|
-
};
|
|
135
|
+
return () => recoverXmppCredentials(config);
|
|
185
136
|
}, [
|
|
186
137
|
config?.jwtLogin?.enabled,
|
|
187
138
|
config?.jwtLogin?.token,
|
|
@@ -248,6 +199,10 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
248
199
|
.performLogout()
|
|
249
200
|
.catch(() => {})
|
|
250
201
|
.finally(() => {
|
|
202
|
+
// The chat says so on its own screen (ChatWrapper's overlay)
|
|
203
|
+
// for a host that keeps it mounted; the host is told too, so
|
|
204
|
+
// it can route to its sign-in.
|
|
205
|
+
DeviceEventEmitter.emit(SESSION_LOST_EVENT);
|
|
251
206
|
try {
|
|
252
207
|
Promise.resolve(config?.logout?.onAfterLogout?.()).catch(() => {});
|
|
253
208
|
} catch {
|
|
@@ -258,23 +213,30 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
258
213
|
|
|
259
214
|
// Re-join MUC rooms on every 'online'. After a reconnect the new
|
|
260
215
|
// XMPP stream isn't a member of any room, so a sent message gets a
|
|
261
|
-
// local double-tick but never reaches the room (bug #21).
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
216
|
+
// local double-tick but never reaches the room (bug #21). The join is
|
|
217
|
+
// a background sweep (open room first, then recent activity, a few at
|
|
218
|
+
// a time) shared with the client's own online handler, so it neither
|
|
219
|
+
// blocks anything nor doubles up. A send / history fetch / room open
|
|
220
|
+
// also joins its own room on demand. On the very first connect the
|
|
221
|
+
// room list isn't loaded yet so this joins little - the bootstrap
|
|
222
|
+
// starts its own sweep once /chats/my has landed.
|
|
265
223
|
created.setOnOnline(() => {
|
|
266
224
|
const underlying = (created as any).client;
|
|
267
225
|
if (!underlying) {return;}
|
|
268
|
-
// The headers say "Updating
|
|
226
|
+
// The headers say "Updating..." until the rooms are joined again and
|
|
269
227
|
// the archive caught up - a stream that is up is not yet a chat
|
|
270
228
|
// that is. Same tick as the client's own 'online', so the title
|
|
271
229
|
// never shows the plain state in between.
|
|
272
230
|
store.dispatch(setConnectionState('syncing'));
|
|
273
|
-
|
|
231
|
+
// The join sweep is shared with the client's own online handler
|
|
232
|
+
// (it dedupes); here it is only awaited so the state can settle.
|
|
233
|
+
const rejoin = Promise.resolve()
|
|
234
|
+
.then(() => created.sendAllPresencesAndMarkReady?.())
|
|
274
235
|
.catch((e) =>
|
|
275
|
-
devPushLog('warn', 'reconnect:
|
|
276
|
-
)
|
|
277
|
-
|
|
236
|
+
devPushLog('warn', 'reconnect: background join sweep failed', e)
|
|
237
|
+
);
|
|
238
|
+
// Push (mucsub) does not depend on the join: subscribe right away.
|
|
239
|
+
subscribeAllRoomsForPush(underlying, 'reconnect');
|
|
278
240
|
// Also refresh the private store so unread / lastViewed markers
|
|
279
241
|
// are accurate after a long reconnect — the MUC re-join above only
|
|
280
242
|
// restores delivery, not unread state. Idempotent on first connect.
|
|
@@ -448,7 +410,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
448
410
|
}
|
|
449
411
|
}
|
|
450
412
|
|
|
451
|
-
// Kick off REST /chats/my;
|
|
413
|
+
// Kick off REST /chats/my; the background join sweep below needs the
|
|
452
414
|
// room list to be in redux, otherwise it joins 0 MUCs and the
|
|
453
415
|
// user receives zero realtime messages until they manually tap
|
|
454
416
|
// into each room. Track the promise so we can await it before
|
|
@@ -485,14 +447,15 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
485
447
|
try {
|
|
486
448
|
await restRoomsPromise;
|
|
487
449
|
} catch {}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
450
|
+
// The room list is complete (REST /chats/my seeded it): join the
|
|
451
|
+
// rooms in the BACKGROUND. READY below does not wait for it: a
|
|
452
|
+
// sweep over hundreds of rooms would otherwise hold the whole room
|
|
453
|
+
// list behind it. Open room first, then recent activity; sends,
|
|
454
|
+
// history fetches and opening a room join their own room on demand.
|
|
455
|
+
const roomCount = Object.keys(store.getState().rooms.rooms || {}).length;
|
|
456
|
+
devPushLog('xmpp', `initBeforeLoad: joining ${roomCount} rooms in the background`);
|
|
457
|
+
startBackgroundJoinSweep(c);
|
|
458
|
+
// Push (mucsub) needs the room list, not the joins.
|
|
496
459
|
subscribeAllRoomsForPush((c as any).client, 'initBeforeLoad');
|
|
497
460
|
|
|
498
461
|
store.dispatch(setStoreClient(c));
|
|
@@ -503,21 +466,14 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
503
466
|
setProviderBootstrapStatus('ready');
|
|
504
467
|
devPushLog('rn', 'initBeforeLoad: READY');
|
|
505
468
|
|
|
506
|
-
// Background
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
typeof r === 'string' ? r : r?.jid
|
|
512
|
-
).filter(Boolean) || [];
|
|
513
|
-
runHistoryPreloadScheduler({
|
|
469
|
+
// Background history preload (fire-and-forget; does not wait for
|
|
470
|
+
// the join sweep: MAM needs no join, and each fetch joins its own
|
|
471
|
+
// room best-effort). Staged by default: the top rooms by activity
|
|
472
|
+
// first, everything else loads when opened. See `historyPreload`.
|
|
473
|
+
runConfiguredHistoryPreload({
|
|
514
474
|
client: c,
|
|
515
475
|
signal: abortController.signal,
|
|
516
|
-
|
|
517
|
-
defaultRoomJids,
|
|
518
|
-
concurrency: qos?.stagedPreloadConcurrency,
|
|
519
|
-
pageSize: qos?.stagedPreloadFirstPassSize,
|
|
520
|
-
roomLimit: qos?.preloadTopKRooms,
|
|
476
|
+
config,
|
|
521
477
|
}).catch((err) => console.warn('History preload scheduler failed', err));
|
|
522
478
|
} catch (error: any) {
|
|
523
479
|
if (cancelled || abortController.signal.aborted) {return;}
|
|
@@ -584,6 +540,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
584
540
|
config?.jwtLogin?.enabled,
|
|
585
541
|
config?.jwtLogin?.token,
|
|
586
542
|
config?.xmppSettings?.devServer,
|
|
543
|
+
bootstrapNonce,
|
|
587
544
|
]);
|
|
588
545
|
|
|
589
546
|
// -----------------------------------------------------------
|
|
@@ -701,7 +658,14 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
701
658
|
// only USED here for the one-shot stamp+flush, matching customer
|
|
702
659
|
// #42: leaving (or backgrounding) a room while scrolled up must not
|
|
703
660
|
// mark messages the user never reached as read.
|
|
704
|
-
|
|
661
|
+
// iOS leaves in two steps, 'inactive' then 'background', and the
|
|
662
|
+
// first one already cleared visibility below. Overwriting here on the
|
|
663
|
+
// second would forget the open chat, so it was never re-marked
|
|
664
|
+
// visible on return: the chat on screen then counted unread and
|
|
665
|
+
// raised in-app toasts for its own messages. Remember, never forget.
|
|
666
|
+
if (visibleRoomJID) {
|
|
667
|
+
visibleBeforeBackground = visibleRoomJID;
|
|
668
|
+
}
|
|
705
669
|
let boundaryTs: number | null = null;
|
|
706
670
|
if (visibleRoomJID) {
|
|
707
671
|
boundaryTs = state.rooms?.readBoundaries?.[visibleRoomJID] ?? null;
|
|
@@ -933,6 +897,7 @@ export const XmppProvider: React.FC<XmppProviderProps> = ({ children, config, is
|
|
|
933
897
|
completedBootstrapKeyRef.current = '';
|
|
934
898
|
inflightBootstrapKeyRef.current = '';
|
|
935
899
|
setProviderBootstrapStatus('idle');
|
|
900
|
+
setBootstrapNonce((n) => n + 1);
|
|
936
901
|
});
|
|
937
902
|
return () => sub.remove();
|
|
938
903
|
}, []);
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waveform helpers for voice messages: the bars a bubble draws, the
|
|
3
|
+
* `waveForm` string a sender attaches to the message, and the recorder's
|
|
4
|
+
* metering turned into the same bars.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Floor for a bar, as a fraction of the box: silence is still a dot. */
|
|
8
|
+
export const MIN_BAR = 0.08;
|
|
9
|
+
|
|
10
|
+
/** Resolution a waveform is computed and sent at; bubbles resample it. */
|
|
11
|
+
export const WAVEFORM_RESOLUTION = 64;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Bars for one clip, from its PCM samples — the same curve as the web
|
|
15
|
+
* client's `buildWaveformPeaks`, so a voice note looks the same on both.
|
|
16
|
+
*
|
|
17
|
+
* RMS per bucket (what the ear hears, not the worst sample), scaled against
|
|
18
|
+
* the 95th percentile so a single click cannot set the scale, then a
|
|
19
|
+
* square-root curve because loudness is perceived that way, and a floor so
|
|
20
|
+
* a quiet passage still reads as a bar rather than as nothing.
|
|
21
|
+
*
|
|
22
|
+
* The decoder WebView carries a copy of this in plain JS (it cannot import
|
|
23
|
+
* modules); keep the two in step.
|
|
24
|
+
*/
|
|
25
|
+
export const buildWaveformPeaks = (
|
|
26
|
+
samples: ArrayLike<number>,
|
|
27
|
+
barCount: number
|
|
28
|
+
): number[] => {
|
|
29
|
+
const bars = Math.max(1, Math.floor(barCount));
|
|
30
|
+
const bucket = Math.floor(samples.length / bars);
|
|
31
|
+
if (bucket < 1) {return new Array(bars).fill(MIN_BAR);}
|
|
32
|
+
|
|
33
|
+
const rms: number[] = [];
|
|
34
|
+
for (let i = 0; i < bars; i += 1) {
|
|
35
|
+
let sum = 0;
|
|
36
|
+
for (let j = i * bucket; j < (i + 1) * bucket; j += 1) {
|
|
37
|
+
sum += samples[j]! * samples[j]!;
|
|
38
|
+
}
|
|
39
|
+
rms.push(Math.sqrt(sum / bucket));
|
|
40
|
+
}
|
|
41
|
+
return scaleLevels(rms);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Raw per-bar levels (RMS, or linear amplitude from the recorder) → 0..1
|
|
46
|
+
* bars, against the 95th percentile with the square-root curve and floor.
|
|
47
|
+
*/
|
|
48
|
+
export const scaleLevels = (levels: number[]): number[] => {
|
|
49
|
+
if (!levels.length) {return [];}
|
|
50
|
+
const sorted = [...levels].sort((a, b) => a - b);
|
|
51
|
+
const reference =
|
|
52
|
+
sorted[Math.floor(sorted.length * 0.95)] || sorted[sorted.length - 1] || 0;
|
|
53
|
+
if (reference <= 0) {return levels.map(() => MIN_BAR);}
|
|
54
|
+
return levels.map((value) => {
|
|
55
|
+
const scaled = Math.sqrt(Math.min(value / reference, 1));
|
|
56
|
+
return Math.min(1, MIN_BAR + scaled * (1 - MIN_BAR));
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Stretch or squeeze bars to `count`, taking the loudest bar in each slot
|
|
62
|
+
* when squeezing so a short loud word is not averaged away.
|
|
63
|
+
*/
|
|
64
|
+
export const resamplePeaks = (peaks: number[], count: number): number[] => {
|
|
65
|
+
const target = Math.max(1, Math.floor(count));
|
|
66
|
+
if (!peaks.length) {return new Array(target).fill(MIN_BAR);}
|
|
67
|
+
if (peaks.length === target) {return peaks;}
|
|
68
|
+
const out: number[] = [];
|
|
69
|
+
for (let i = 0; i < target; i += 1) {
|
|
70
|
+
const from = Math.floor((i * peaks.length) / target);
|
|
71
|
+
const to = Math.max(from + 1, Math.floor(((i + 1) * peaks.length) / target));
|
|
72
|
+
let max = 0;
|
|
73
|
+
for (let j = from; j < to && j < peaks.length; j += 1) {
|
|
74
|
+
max = Math.max(max, peaks[j]!);
|
|
75
|
+
}
|
|
76
|
+
out.push(max);
|
|
77
|
+
}
|
|
78
|
+
return out;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Recorder metering (dBFS, about -160..0) → linear amplitude 0..1, which
|
|
83
|
+
* `scaleLevels` then treats like an RMS. Anything at or below -60 dB is
|
|
84
|
+
* room noise and counts as silence.
|
|
85
|
+
*/
|
|
86
|
+
export const meteringToLevel = (db: number | undefined): number => {
|
|
87
|
+
if (typeof db !== 'number' || !Number.isFinite(db) || db <= -60) {return 0;}
|
|
88
|
+
return Math.pow(10, Math.min(db, 0) / 20);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The `waveForm` attribute a voice message carries: comma-separated bar
|
|
93
|
+
* heights, 0..100. Short enough for a stanza attribute, plain enough for
|
|
94
|
+
* any client to read.
|
|
95
|
+
*/
|
|
96
|
+
export const encodeWaveForm = (peaks: number[]): string =>
|
|
97
|
+
peaks
|
|
98
|
+
.map((p) => Math.round(Math.max(0, Math.min(1, p)) * 100))
|
|
99
|
+
.join(',');
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Bars from a message's `waveForm`, or null when it has none / nothing
|
|
103
|
+
* usable. Accepts the comma list above and a JSON array, in 0..1 or 0..100.
|
|
104
|
+
*/
|
|
105
|
+
export const parseWaveForm = (value: unknown): number[] | null => {
|
|
106
|
+
if (typeof value !== 'string' || !value.trim()) {return null;}
|
|
107
|
+
let raw: unknown[];
|
|
108
|
+
const text = value.trim();
|
|
109
|
+
if (text.startsWith('[')) {
|
|
110
|
+
try {
|
|
111
|
+
const parsed = JSON.parse(text);
|
|
112
|
+
if (!Array.isArray(parsed)) {return null;}
|
|
113
|
+
raw = parsed;
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
raw = text.split(',');
|
|
119
|
+
}
|
|
120
|
+
const numbers = raw.map((n) => Number(n));
|
|
121
|
+
if (numbers.length < 2 || numbers.some((n) => !Number.isFinite(n) || n < 0)) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const max = Math.max(...numbers);
|
|
125
|
+
const scale = max > 1 ? 100 : 1;
|
|
126
|
+
return numbers.map((n) => Math.max(MIN_BAR, Math.min(1, n / scale)));
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/** Seconds from a message's `duration` attribute, or 0 when absent. */
|
|
130
|
+
export const parseDurationSeconds = (value: unknown): number => {
|
|
131
|
+
const n = Number(value);
|
|
132
|
+
return Number.isFinite(n) && n > 0 ? n : 0;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/** `0:07`, `1:23`, `12:05`. */
|
|
136
|
+
export const formatClipTime = (millis: number): string => {
|
|
137
|
+
const safe = Number.isFinite(millis) && millis > 0 ? millis : 0;
|
|
138
|
+
const totalSec = Math.floor(safe / 1000);
|
|
139
|
+
const min = Math.floor(totalSec / 60);
|
|
140
|
+
const sec = totalSec % 60;
|
|
141
|
+
return `${min}:${sec.toString().padStart(2, '0')}`;
|
|
142
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starting the MUC join sweep without ever waiting for it.
|
|
3
|
+
*
|
|
4
|
+
* The room list is usable as soon as /chats/my has returned (rooms are
|
|
5
|
+
* seeded with lastMessage / unread / usersCnt), so joining every room is a
|
|
6
|
+
* background job: open room first, then recent activity, a few at a time.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
type SweepClient = { sendAllPresencesAndMarkReady?: () => Promise<unknown> };
|
|
10
|
+
|
|
11
|
+
// Fire-and-forget: never awaited by the room list, never throws.
|
|
12
|
+
export const startBackgroundJoinSweep = (client: SweepClient | null | undefined) => {
|
|
13
|
+
if (!client || typeof client.sendAllPresencesAndMarkReady !== 'function') {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
Promise.resolve()
|
|
17
|
+
.then(() => client.sendAllPresencesAndMarkReady?.())
|
|
18
|
+
.catch((error) => {
|
|
19
|
+
console.warn('[loadRooms] background join sweep failed', error);
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Ends the loading state right after the rooms fetch and joins in the
|
|
24
|
+
// background. Resolves without waiting for any join; a failing fetch starts
|
|
25
|
+
// no sweep and never calls `onListReady`.
|
|
26
|
+
export const loadRoomsThenJoinInBackground = async <T,>(
|
|
27
|
+
client: SweepClient,
|
|
28
|
+
fetchRooms: () => Promise<T>,
|
|
29
|
+
onListReady: () => void
|
|
30
|
+
): Promise<T> => {
|
|
31
|
+
const rooms = await fetchRooms();
|
|
32
|
+
startBackgroundJoinSweep(client);
|
|
33
|
+
onListReady();
|
|
34
|
+
return rooms;
|
|
35
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useSyncExternalStore } from 'react';
|
|
2
|
+
|
|
3
|
+
/** How long the jump highlight stays on a bubble. */
|
|
4
|
+
export const HIGHLIGHT_MS = 1000;
|
|
5
|
+
|
|
6
|
+
interface Highlight {
|
|
7
|
+
id: string;
|
|
8
|
+
/** Epoch ms the highlight ends. */
|
|
9
|
+
until: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let current: Highlight | null = null;
|
|
13
|
+
const listeners = new Set<() => void>();
|
|
14
|
+
const emit = () => listeners.forEach((listener) => listener());
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Highlight the bubble of one message for HIGHLIGHT_MS (a jump just landed on
|
|
18
|
+
* it), or clear the highlight with null. Kept outside the list on purpose: a
|
|
19
|
+
* row that is unmounted and mounted again while the highlight is running (the
|
|
20
|
+
* list recycles rows as the scroll settles) reads the same state, so the
|
|
21
|
+
* highlight follows the message instead of being lost with the row.
|
|
22
|
+
*/
|
|
23
|
+
export const setBubbleHighlight = (id: string | null, now = Date.now()): void => {
|
|
24
|
+
current = id === null ? null : { id, until: now + HIGHLIGHT_MS };
|
|
25
|
+
emit();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const getBubbleHighlightUntil = (id: string): number =>
|
|
29
|
+
current && current.id === id ? current.until : 0;
|
|
30
|
+
|
|
31
|
+
const subscribe = (listener: () => void) => {
|
|
32
|
+
listeners.add(listener);
|
|
33
|
+
return () => {
|
|
34
|
+
listeners.delete(listener);
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* End time (epoch ms) of the highlight of this message, 0 when it has none.
|
|
40
|
+
* The snapshot is a number, so only the highlighted row re-renders.
|
|
41
|
+
*/
|
|
42
|
+
export const useBubbleHighlightUntil = (id: string): number =>
|
|
43
|
+
useSyncExternalStore(
|
|
44
|
+
subscribe,
|
|
45
|
+
() => getBubbleHighlightUntil(id),
|
|
46
|
+
() => 0
|
|
47
|
+
);
|