@ethora/chat-component-rn 26.4.1
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/LICENSE +661 -0
- package/README.md +148 -0
- package/empty-shim.js +15 -0
- package/index.js +13 -0
- package/metro.js +72 -0
- package/package.json +99 -0
- package/src/api.config.ts +34 -0
- package/src/assets/BG.png +0 -0
- package/src/assets/BG.tsx +56 -0
- package/src/assets/File.svg +4 -0
- package/src/assets/ForzaCare.png +0 -0
- package/src/assets/ForzaCare.tsx +27 -0
- package/src/assets/icons.tsx +685 -0
- package/src/assets/images.tsx +41 -0
- package/src/assets/test.xml +243 -0
- package/src/components/AuthForms/Login.tsx +295 -0
- package/src/components/AuthForms/LoginAnonym.tsx +68 -0
- package/src/components/AuthForms/Register.tsx +8 -0
- package/src/components/ContextMenu/ContextMenuComponents.tsx +87 -0
- package/src/components/DropdownMenu/DropdownMenu.tsx +244 -0
- package/src/components/ExampleComponents/CustomMessage.tsx +92 -0
- package/src/components/ExampleComponents/CustomTypingIndicatorExamples.tsx +239 -0
- package/src/components/Header/HeaderRoomList.tsx +104 -0
- package/src/components/InputComponents/AudioInput.tsx +24 -0
- package/src/components/InputComponents/AudioRecorder.tsx +100 -0
- package/src/components/InputComponents/MediaInput.tsx +114 -0
- package/src/components/InputComponents/RecordingIndicator.tsx +77 -0
- package/src/components/InputComponents/Search.tsx +135 -0
- package/src/components/InputComponents/TextInput.tsx +66 -0
- package/src/components/MainComponents/ChatHeader.tsx +163 -0
- package/src/components/MainComponents/ChatRoom.tsx +392 -0
- package/src/components/MainComponents/ChatWrapper.tsx +318 -0
- package/src/components/MainComponents/ChooseChatMessage.tsx +44 -0
- package/src/components/MainComponents/ConnectionBanner.tsx +33 -0
- package/src/components/MainComponents/EditWrapper.tsx +72 -0
- package/src/components/MainComponents/LoginWrapper.tsx +134 -0
- package/src/components/MainComponents/MediaMessage.tsx +55 -0
- package/src/components/MainComponents/MessageContainer.tsx +122 -0
- package/src/components/MainComponents/MessageList.tsx +429 -0
- package/src/components/MainComponents/NoMessagesPlaceholder.tsx +49 -0
- package/src/components/MainComponents/ProfileImagePlaceholder.tsx +143 -0
- package/src/components/MainComponents/RNStyled.tsx +34 -0
- package/src/components/MainComponents/ReduxWrapper.tsx +40 -0
- package/src/components/MainComponents/RoomList.tsx +246 -0
- package/src/components/MainComponents/Select.tsx +165 -0
- package/src/components/MainComponents/Switch.tsx +73 -0
- package/src/components/MainComponents/SystemMessage.tsx +42 -0
- package/src/components/Menu/HeaderRoomListMenu.tsx +169 -0
- package/src/components/MenuRoom/MenuRoom.tsx +46 -0
- package/src/components/MessageBubble/Avatar.tsx +84 -0
- package/src/components/MessageBubble/BottomReplyContainer.tsx +117 -0
- package/src/components/MessageBubble/CustomDivider.tsx +10 -0
- package/src/components/MessageBubble/DeletedMessage.tsx +36 -0
- package/src/components/MessageBubble/Message.tsx +400 -0
- package/src/components/MessageBubble/MessageInteractions.tsx +247 -0
- package/src/components/MessageBubble/MessageReaction.tsx +149 -0
- package/src/components/MessageBubble/MessageReply.tsx +50 -0
- package/src/components/MessageBubble/MessageTranslations.tsx +30 -0
- package/src/components/Modals/AddMembersModal/AddMembersModal.tsx +142 -0
- package/src/components/Modals/ChatProfileModal/ChatProfileModal.tsx +471 -0
- package/src/components/Modals/ChatProfileModal/DeleteChatModal.tsx +91 -0
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +298 -0
- package/src/components/Modals/Modal/Modal.tsx +52 -0
- package/src/components/Modals/ModalHeaderComponent.tsx +41 -0
- package/src/components/Modals/ModalSelectMedia/ModalSelectMedia.tsx +285 -0
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +103 -0
- package/src/components/Modals/NewChatModal/ModalContent.tsx +151 -0
- package/src/components/Modals/NewChatModal/NewChatModal.tsx +391 -0
- package/src/components/Modals/NewChatModal/UpdNewChatModal.tsx +136 -0
- package/src/components/Modals/SelectUsersModal/SelectUsersModal.tsx +134 -0
- package/src/components/Modals/SettingsModals/BlockedUsers/BlockedUsersModal.tsx +63 -0
- package/src/components/Modals/SettingsModals/DocumentShares/DocumentSharesModal.tsx +115 -0
- package/src/components/Modals/SettingsModals/ManageDataModal/ManageDataModal.tsx +121 -0
- package/src/components/Modals/SettingsModals/ManageDataModal/StyledComponents.ts +0 -0
- package/src/components/Modals/SettingsModals/ProfileShares/ProfileShares.tsx +65 -0
- package/src/components/Modals/SettingsModals/Referrals/Referrals.tsx +90 -0
- package/src/components/Modals/SettingsModals/SharedStyledComponents.ts +74 -0
- package/src/components/Modals/SettingsModals/Visibility/RadioInput.tsx +59 -0
- package/src/components/Modals/SettingsModals/Visibility/StyledComponents.ts +32 -0
- package/src/components/Modals/SettingsModals/Visibility/VisibilityModal.tsx +146 -0
- package/src/components/Modals/UserProfileModal/EditUserModal.tsx +163 -0
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +410 -0
- package/src/components/Modals/UserSettingsModal/UserSettingsModal.tsx +85 -0
- package/src/components/Modals/styledModalComponents.tsx +181 -0
- package/src/components/OperationalModal/OperationalModal.tsx +78 -0
- package/src/components/RoomComponents/ChatRoomItem.tsx +219 -0
- package/src/components/RoomComponents/LastMessageItem.tsx +47 -0
- package/src/components/RoomComponents/styled/LastAudioMessage.tsx +62 -0
- package/src/components/RoomComponents/styled/LastMessageEmoji.tsx +26 -0
- package/src/components/RoomComponents/styled/LastMessageFile.tsx +54 -0
- package/src/components/RoomComponents/styled/LastMessagePhoto.tsx +54 -0
- package/src/components/RoomComponents/styled/LastMessageVideo.tsx +70 -0
- package/src/components/RoomComponents/styled/LastTextMessage.tsx +65 -0
- package/src/components/RoomComponents/styled/StyledRoomComponents.ts +53 -0
- package/src/components/SortDropDown/index.tsx +76 -0
- package/src/components/Thread/ThreadHeader.tsx +41 -0
- package/src/components/Thread/ThreadWrapper.tsx +270 -0
- package/src/components/Toast/Toast.tsx +128 -0
- package/src/components/Toast/index.ts +13 -0
- package/src/components/UsersList/StyledComponents.ts +30 -0
- package/src/components/UsersList/UsersList.tsx +112 -0
- package/src/components/styled/ActionButton.tsx +40 -0
- package/src/components/styled/AudioMessage.tsx +82 -0
- package/src/components/styled/Button.tsx +107 -0
- package/src/components/styled/ChatWrapperBox.tsx +9 -0
- package/src/components/styled/DateLabel.tsx +77 -0
- package/src/components/styled/Loader.tsx +65 -0
- package/src/components/styled/MediaFilePreview.tsx +42 -0
- package/src/components/styled/MediaModal.tsx +54 -0
- package/src/components/styled/MessageImage.tsx +54 -0
- package/src/components/styled/NewMessageLabel.tsx +50 -0
- package/src/components/styled/RoomListComponents/index.tsx +164 -0
- package/src/components/styled/SendInput.tsx +297 -0
- package/src/components/styled/StyledComponents.ts +320 -0
- package/src/components/styled/StyledInput.tsx +101 -0
- package/src/components/styled/StyledInputComponents/AudioComponents.tsx +1 -0
- package/src/components/styled/StyledInputComponents/Composing.tsx +97 -0
- package/src/components/styled/StyledInputComponents/CustomTypingIndicator.tsx +261 -0
- package/src/components/styled/StyledInputComponents/MediaComponents.tsx +90 -0
- package/src/components/styled/StyledInputComponents/StyledInputComponents.tsx +131 -0
- package/src/components/styled/StyledInputComponents/VideoComponents.tsx +49 -0
- package/src/components/styled/TreadLabel.tsx +50 -0
- package/src/components/styled/UnsupportedType.tsx +95 -0
- package/src/components/styled/VideoMessage.tsx +68 -0
- package/src/context/MessageNotificationContext.tsx +335 -0
- package/src/context/PushNotificationProvider.tsx +78 -0
- package/src/context/ToastContext.tsx +63 -0
- package/src/context/toastProvider.tsx +0 -0
- package/src/context/xmppProvider.tsx +364 -0
- package/src/helpers/block_scroll.ts +95 -0
- package/src/helpers/chatAutoEnterer.ts +46 -0
- package/src/helpers/checkUniqueUsers.tsx +31 -0
- package/src/helpers/constants/CHAT_TYPES.ts +6 -0
- package/src/helpers/constants/LANGUAGE_OPTIONS.ts +14 -0
- package/src/helpers/constants/LOCAL_STORAGE.ts +3 -0
- package/src/helpers/constants/MESSAGE_INTERACTIONS.ts +29 -0
- package/src/helpers/constants/MODAL_TYPES.ts +57 -0
- package/src/helpers/constants/PLATFORM_CONSTANTS.ts +3 -0
- package/src/helpers/createMainMessageForThread.ts +23 -0
- package/src/helpers/createMessageFromXml.ts +118 -0
- package/src/helpers/createRoomFromApi.tsx +27 -0
- package/src/helpers/createUserNameFromSetUser.ts +15 -0
- package/src/helpers/dateComparison.ts +12 -0
- package/src/helpers/debounce.ts +10 -0
- package/src/helpers/ensureScopedChatCache.ts +61 -0
- package/src/helpers/extractUniqueMembersFromRooms.ts +45 -0
- package/src/helpers/formatNumberWithCommas.ts +3 -0
- package/src/helpers/getBooleanFromString.ts +7 -0
- package/src/helpers/getDataFromXml.ts +80 -0
- package/src/helpers/getNumberFromString.ts +5 -0
- package/src/helpers/getRoomsWithRetry.ts +45 -0
- package/src/helpers/getTintedColor.ts +28 -0
- package/src/helpers/getUnnamedUsers.ts +39 -0
- package/src/helpers/handleCopyClick.ts +3 -0
- package/src/helpers/handleXmppError.ts +14 -0
- package/src/helpers/hashcolor.ts +34 -0
- package/src/helpers/historyPreloadScheduler.ts +264 -0
- package/src/helpers/initRoomsPresence.ts +32 -0
- package/src/helpers/initXmppRooms.tsx +71 -0
- package/src/helpers/insertMessageWithDelimiter.ts +96 -0
- package/src/helpers/isChatIdPresentInArray.ts +54 -0
- package/src/helpers/localStorageUser.ts +9 -0
- package/src/helpers/markdownParser.tsx +295 -0
- package/src/helpers/nanoToMs.ts +3 -0
- package/src/helpers/parseMessageBody.tsx +516 -0
- package/src/helpers/parseUrls.tsx +42 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +240 -0
- package/src/helpers/storeConsole.ts +26 -0
- package/src/helpers/transformTranslatations.ts +16 -0
- package/src/helpers/updateMessagesTillLast.tsx +104 -0
- package/src/helpers/updatedChatLastTimestamps.ts +29 -0
- package/src/helpers/validator.ts +20 -0
- package/src/helpers/walletUsername.ts +12 -0
- package/src/hooks/hooks.ts +6 -0
- package/src/hooks/useChatSettingState.tsx +38 -0
- package/src/hooks/useChatWrapperInit.ts +266 -0
- package/src/hooks/useComposing.tsx +59 -0
- package/src/hooks/useCustomTypingIndicator.tsx +193 -0
- package/src/hooks/useEventHandlers.tsx +81 -0
- package/src/hooks/useGetNewArchRoom.tsx +57 -0
- package/src/hooks/useHeapSender.tsx +88 -0
- package/src/hooks/useLocalStorage.tsx +53 -0
- package/src/hooks/useLogout.tsx +31 -0
- package/src/hooks/useMessageHeapState.tsx +11 -0
- package/src/hooks/useMessageLoaderQueue.tsx +90 -0
- package/src/hooks/useMessageQueue.ts +146 -0
- package/src/hooks/usePendingNotification.ts +49 -0
- package/src/hooks/usePrevious.tsx +15 -0
- package/src/hooks/usePushNotifications.ts +106 -0
- package/src/hooks/useQRCodeChatHandler.ts +58 -0
- package/src/hooks/useRoomInitialization.tsx +160 -0
- package/src/hooks/useRoomState.tsx +47 -0
- package/src/hooks/useRoomUrl.tsx +41 -0
- package/src/hooks/useSendMessage.tsx +306 -0
- package/src/hooks/useUnreadMessagesCounter.ts +55 -0
- package/src/hooks/useXmppInitialization.ts +148 -0
- package/src/main.ts +45 -0
- package/src/networking/api-requests/auth.api.ts +140 -0
- package/src/networking/api-requests/push.api.ts +55 -0
- package/src/networking/api-requests/roomMembers.api.ts +20 -0
- package/src/networking/api-requests/rooms.api.ts +142 -0
- package/src/networking/api-requests/user.api.ts +65 -0
- package/src/networking/apiClient.ts +149 -0
- package/src/networking/helpers/refreshChecker.ts +13 -0
- package/src/networking/stanzaHandlers.ts +418 -0
- package/src/networking/xmpp/actionSetTimestampToPrivateStore.xmpp.ts +37 -0
- package/src/networking/xmpp/allRoomPresences.xmpp.ts +10 -0
- package/src/networking/xmpp/createPrivateRoom.xmpp.ts +26 -0
- package/src/networking/xmpp/createRoom.xmpp.ts +35 -0
- package/src/networking/xmpp/createRoomPresence.xmpp.ts +74 -0
- package/src/networking/xmpp/createTimeoutPromise.xmpp.ts +15 -0
- package/src/networking/xmpp/deleteMessage.xmpp.ts +19 -0
- package/src/networking/xmpp/editMessage.xmpp.ts +46 -0
- package/src/networking/xmpp/getChatsPrivateStoreRequest.xmpp.ts +57 -0
- package/src/networking/xmpp/getHistory.xmpp.ts +140 -0
- package/src/networking/xmpp/getLastMessageArchive.xmpp.ts +24 -0
- package/src/networking/xmpp/getRoomInfo.xmpp.ts +15 -0
- package/src/networking/xmpp/getRoomMembers.xmpp.ts +13 -0
- package/src/networking/xmpp/getRooms.xmpp.ts +43 -0
- package/src/networking/xmpp/getRoomsPaged.xmpp.ts +59 -0
- package/src/networking/xmpp/handlePong.xmpp.ts +7 -0
- package/src/networking/xmpp/handleStanzas.xmpp.ts +55 -0
- package/src/networking/xmpp/inviteRoomRequest.xmpp.ts +25 -0
- package/src/networking/xmpp/leaveTheRoom.xmpp.ts +15 -0
- package/src/networking/xmpp/listenerManager.ts +116 -0
- package/src/networking/xmpp/presenceInRoom.xmpp.ts +57 -0
- package/src/networking/xmpp/roomConfig.xmpp.ts +71 -0
- package/src/networking/xmpp/sendMediaMessage.xmpp.ts +97 -0
- package/src/networking/xmpp/sendMessageReaction.xmpp.ts +41 -0
- package/src/networking/xmpp/sendPing.xmpp.ts +21 -0
- package/src/networking/xmpp/sendTextMessage.xmpp.ts +99 -0
- package/src/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.ts +44 -0
- package/src/networking/xmpp/sendTypingRequest.xmpp.ts +26 -0
- package/src/networking/xmpp/setChatsPrivateStoreRequest.xmpp.ts +48 -0
- package/src/networking/xmpp/setMeAsOwner.xmpp.ts +52 -0
- package/src/networking/xmpp/setRoomImage.xmpp.ts +26 -0
- package/src/networking/xmpp/setVCard.xmpp.ts +19 -0
- package/src/networking/xmpp/subscribeToRoomMessages.xmpp.ts +75 -0
- package/src/networking/xmppClient.ts +603 -0
- package/src/roomStore/Middleware/logoutMiddleware.tsx +24 -0
- package/src/roomStore/Middleware/newMessageMidlleware.tsx +87 -0
- package/src/roomStore/Middleware/reactionsMiddleware.tsx +77 -0
- package/src/roomStore/Middleware/testMiddleware.tsx +20 -0
- package/src/roomStore/Middleware/unreadMidlleware.tsx +58 -0
- package/src/roomStore/chatSettingsSlice.ts +178 -0
- package/src/roomStore/index.ts +68 -0
- package/src/roomStore/persistence.ts +152 -0
- package/src/roomStore/roomHeapSlice.ts +37 -0
- package/src/roomStore/roomsSlice.ts +353 -0
- package/src/services/pushNotifications.ts +170 -0
- package/src/services/pushSubscriptionService.ts +145 -0
- package/src/types/messages.ts +61 -0
- package/src/types/models/action.model.ts +30 -0
- package/src/types/models/config.model.ts +16 -0
- package/src/types/models/customComponents.model.ts +53 -0
- package/src/types/models/language.model.ts +11 -0
- package/src/types/models/media.model.ts +5 -0
- package/src/types/models/message.model.ts +69 -0
- package/src/types/models/modal.model.ts +9 -0
- package/src/types/models/room.model.ts +120 -0
- package/src/types/models/user.model.ts +90 -0
- package/src/types/models/xmpp.model.ts +155 -0
- package/src/types/types.ts +505 -0
- package/src/utils/PriorityQueue.ts +47 -0
- package/src/utils/actionHelpers.ts +40 -0
- package/src/utils/actionLogger.ts +64 -0
- package/src/utils/clientRegistry.ts +80 -0
- package/src/utils/devLogger.ts +197 -0
- package/src/utils/messageNotificationManager.ts +108 -0
- package/src/utils/resendMessage.ts +87 -0
- package/src/utils/toastEmitter.ts +27 -0
- package/src/utils/xmppMemoryMonitor.ts +63 -0
- package/src/version.ts +1 -0
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
import xmpp, { Client } from '@xmpp/client';
|
|
2
|
+
import { walletToUsername } from '../helpers/walletUsername';
|
|
3
|
+
import { xmppSettingsInterface } from '../types/types';
|
|
4
|
+
|
|
5
|
+
import { sendMediaMessage } from './xmpp/sendMediaMessage.xmpp';
|
|
6
|
+
import { getChatsPrivateStoreRequest } from './xmpp/getChatsPrivateStoreRequest.xmpp';
|
|
7
|
+
import { actionSetTimestampToPrivateStore } from './xmpp/actionSetTimestampToPrivateStore.xmpp';
|
|
8
|
+
import { sendTypingRequest } from './xmpp/sendTypingRequest.xmpp';
|
|
9
|
+
import { getHistory } from './xmpp/getHistory.xmpp';
|
|
10
|
+
import { sendTextMessage } from './xmpp/sendTextMessage.xmpp';
|
|
11
|
+
import { deleteMessage } from './xmpp/deleteMessage.xmpp';
|
|
12
|
+
import { presenceInRoom } from './xmpp/presenceInRoom.xmpp';
|
|
13
|
+
import { getLastMessage } from './xmpp/getLastMessageArchive.xmpp';
|
|
14
|
+
import { createRoom } from './xmpp/createRoom.xmpp';
|
|
15
|
+
import { setRoomImage } from './xmpp/setRoomImage.xmpp';
|
|
16
|
+
import { getRoomMembers } from './xmpp/getRoomMembers.xmpp';
|
|
17
|
+
import { getRoomInfo } from './xmpp/getRoomInfo.xmpp';
|
|
18
|
+
import { leaveTheRoom } from './xmpp/leaveTheRoom.xmpp';
|
|
19
|
+
import { editMessage } from './xmpp/editMessage.xmpp';
|
|
20
|
+
import { inviteRoomRequest } from './xmpp/inviteRoomRequest.xmpp';
|
|
21
|
+
import { getRooms } from './xmpp/getRooms.xmpp';
|
|
22
|
+
import { handleStanza } from './xmpp/handleStanzas.xmpp';
|
|
23
|
+
import { pushLog as devPushLog } from '../utils/devLogger';
|
|
24
|
+
|
|
25
|
+
// Canonical production XMPP WSS endpoint (standard wss/443, no port suffix).
|
|
26
|
+
const DEFAULT_DEV_SERVER = 'xmpp.chat.ethora.com';
|
|
27
|
+
|
|
28
|
+
type HistorySource = 'active' | 'send_ack' | 'background' | 'default';
|
|
29
|
+
|
|
30
|
+
interface HistoryOptions {
|
|
31
|
+
coalesceRoom?: boolean;
|
|
32
|
+
skipIfPreloaded?: boolean;
|
|
33
|
+
source?: HistorySource;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface MamInFlightEntry {
|
|
37
|
+
promise: Promise<any>;
|
|
38
|
+
source: HistorySource;
|
|
39
|
+
startedAt: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class XmppClient {
|
|
43
|
+
client!: Client;
|
|
44
|
+
xmppSettings?: xmppSettingsInterface;
|
|
45
|
+
devServer: string | undefined;
|
|
46
|
+
host: string = '';
|
|
47
|
+
service: string = '';
|
|
48
|
+
conference: string = '';
|
|
49
|
+
username: string;
|
|
50
|
+
status: 'offline' | 'connecting' | 'online' | 'error' = 'offline';
|
|
51
|
+
|
|
52
|
+
password = '';
|
|
53
|
+
reconnectAttempts = 0;
|
|
54
|
+
maxReconnectAttempts = 5;
|
|
55
|
+
reconnectDelay = 2000;
|
|
56
|
+
suppressReconnect = false;
|
|
57
|
+
|
|
58
|
+
// ---- QoS state (mirrors web XmppClient) ----------------------------
|
|
59
|
+
disableLastRead = false;
|
|
60
|
+
private activeRoomJID: string | null = null;
|
|
61
|
+
private activeRoomBoostUntil = 0;
|
|
62
|
+
private softPauseUntil = 0;
|
|
63
|
+
private mamInFlightByRoom: Map<string, MamInFlightEntry> = new Map();
|
|
64
|
+
private maxInFlightHistory = 3;
|
|
65
|
+
private softPauseAfterSendMs = 250;
|
|
66
|
+
private activeRoomBoostTtlMs = 4000;
|
|
67
|
+
private alwaysPrioritizeActiveRoom = true;
|
|
68
|
+
|
|
69
|
+
// -------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
checkOnline() {
|
|
72
|
+
return this.client && this.client.status === 'online';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
constructor(
|
|
76
|
+
username: string,
|
|
77
|
+
password: string,
|
|
78
|
+
xmppSettings?: xmppSettingsInterface | string
|
|
79
|
+
) {
|
|
80
|
+
// Back-compat: third arg used to be a bare devServer string.
|
|
81
|
+
if (typeof xmppSettings === 'string') {
|
|
82
|
+
this.xmppSettings = { devServer: xmppSettings };
|
|
83
|
+
this.devServer = xmppSettings;
|
|
84
|
+
} else {
|
|
85
|
+
this.xmppSettings = xmppSettings;
|
|
86
|
+
this.devServer = xmppSettings?.devServer;
|
|
87
|
+
}
|
|
88
|
+
this.disableLastRead = this.xmppSettings?.disableLastRead === true;
|
|
89
|
+
|
|
90
|
+
const qos = this.xmppSettings?.historyQoS;
|
|
91
|
+
if (qos) {
|
|
92
|
+
if (typeof qos.maxInFlightHistory === 'number')
|
|
93
|
+
{this.maxInFlightHistory = qos.maxInFlightHistory;}
|
|
94
|
+
if (typeof qos.softPauseAfterSendMs === 'number')
|
|
95
|
+
{this.softPauseAfterSendMs = qos.softPauseAfterSendMs;}
|
|
96
|
+
if (typeof qos.activeRoomBoostTtlMs === 'number')
|
|
97
|
+
{this.activeRoomBoostTtlMs = qos.activeRoomBoostTtlMs;}
|
|
98
|
+
if (typeof qos.alwaysPrioritizeActiveRoom === 'boolean')
|
|
99
|
+
{this.alwaysPrioritizeActiveRoom = qos.alwaysPrioritizeActiveRoom;}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.username = username;
|
|
103
|
+
this.password = password;
|
|
104
|
+
this.initializeClient();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ===================================================================
|
|
108
|
+
// QoS API — mirrors web XmppClientInterface
|
|
109
|
+
// ===================================================================
|
|
110
|
+
setActiveRoomJid(roomJID: string | null) {
|
|
111
|
+
this.activeRoomJID = roomJID;
|
|
112
|
+
if (roomJID) {this.promoteRoomHistory(roomJID);}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
promoteRoomHistory(_roomJID: string) {
|
|
116
|
+
this.activeRoomBoostUntil = Date.now() + this.activeRoomBoostTtlMs;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Active-room gate is "open" whenever the boost has expired OR there's
|
|
121
|
+
* room for more concurrent MAM fetches. Scheduler uses this to backoff.
|
|
122
|
+
*/
|
|
123
|
+
isActiveRoomGateOpen(): boolean {
|
|
124
|
+
if (this.mamInFlightByRoom.size >= this.maxInFlightHistory) {return false;}
|
|
125
|
+
if (Date.now() < this.softPauseUntil) {return false;}
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Called right before a critical send. Soft-pauses background MAM. */
|
|
130
|
+
onCriticalSend(roomJID: string, _messageId?: string) {
|
|
131
|
+
this.softPauseUntil = Date.now() + this.softPauseAfterSendMs;
|
|
132
|
+
if (roomJID) {this.promoteRoomHistory(roomJID);}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Higher-priority presence than presenceInRoomStanza. For now just
|
|
137
|
+
* delegates — kept distinct so callers don't change when full priority
|
|
138
|
+
* lanes land later.
|
|
139
|
+
*/
|
|
140
|
+
async prioritizeRoomPresence(roomJID: string): Promise<boolean> {
|
|
141
|
+
try {
|
|
142
|
+
this.presenceInRoomStanza(roomJID);
|
|
143
|
+
return true;
|
|
144
|
+
} catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Queued history fetch. Coalesces by room: if the same room already has
|
|
151
|
+
* a higher-priority request in flight, return that promise. Honors
|
|
152
|
+
* `skipIfPreloaded` by checking redux state (lazy import to avoid cycle).
|
|
153
|
+
*/
|
|
154
|
+
async enqueueHistoryTask(params: {
|
|
155
|
+
chatJID: string;
|
|
156
|
+
max: number;
|
|
157
|
+
before?: number;
|
|
158
|
+
id?: string;
|
|
159
|
+
source?: HistorySource;
|
|
160
|
+
}): Promise<any> {
|
|
161
|
+
const { chatJID, max, before, id, source = 'default' } = params;
|
|
162
|
+
|
|
163
|
+
// Coalesce — if a fetch for the same room is in-flight, reuse it
|
|
164
|
+
// unless the new request is higher priority.
|
|
165
|
+
const existing = this.mamInFlightByRoom.get(chatJID);
|
|
166
|
+
if (existing && this.sourceRank(existing.source) <= this.sourceRank(source)) {
|
|
167
|
+
return existing.promise;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Wait for the gate (in-flight cap + soft-pause). For active-room
|
|
171
|
+
// requests we still proceed past the cap when the boost is fresh.
|
|
172
|
+
while (
|
|
173
|
+
this.mamInFlightByRoom.size >= this.maxInFlightHistory &&
|
|
174
|
+
!(this.alwaysPrioritizeActiveRoom && this.activeRoomJID === chatJID)
|
|
175
|
+
) {
|
|
176
|
+
await new Promise((r) => setTimeout(r, 80));
|
|
177
|
+
}
|
|
178
|
+
if (Date.now() < this.softPauseUntil && source === 'background') {
|
|
179
|
+
const wait = this.softPauseUntil - Date.now();
|
|
180
|
+
await new Promise((r) => setTimeout(r, wait));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Self-reference via an outer holder so the IIFE's `finally` can
|
|
184
|
+
// identify "is the registry entry I started still the current one?"
|
|
185
|
+
// without TS's TDZ false-positive (TS2454 on a bare `let promise`).
|
|
186
|
+
const handle: { p?: Promise<any> } = {};
|
|
187
|
+
handle.p = (async () => {
|
|
188
|
+
try {
|
|
189
|
+
return await getHistory(this.client, chatJID, max, before, id);
|
|
190
|
+
} finally {
|
|
191
|
+
const cur = this.mamInFlightByRoom.get(chatJID);
|
|
192
|
+
if (cur && cur.promise === handle.p) {
|
|
193
|
+
this.mamInFlightByRoom.delete(chatJID);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
})();
|
|
197
|
+
|
|
198
|
+
this.mamInFlightByRoom.set(chatJID, {
|
|
199
|
+
promise: handle.p,
|
|
200
|
+
source,
|
|
201
|
+
startedAt: Date.now(),
|
|
202
|
+
});
|
|
203
|
+
return handle.p;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private sourceRank(s: HistorySource): number {
|
|
207
|
+
switch (s) {
|
|
208
|
+
case 'active':
|
|
209
|
+
return 0;
|
|
210
|
+
case 'send_ack':
|
|
211
|
+
return 1;
|
|
212
|
+
case 'default':
|
|
213
|
+
return 2;
|
|
214
|
+
case 'background':
|
|
215
|
+
return 3;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
initializeClient() {
|
|
220
|
+
try {
|
|
221
|
+
const devServer = this.devServer || DEFAULT_DEV_SERVER;
|
|
222
|
+
const url = `wss://${devServer}/ws`;
|
|
223
|
+
this.service = url;
|
|
224
|
+
this.host =
|
|
225
|
+
this.xmppSettings?.host || url.match(/wss:\/\/([^:/]+)/)?.[1] || '';
|
|
226
|
+
this.conference =
|
|
227
|
+
this.xmppSettings?.conference || `conference.${this.host}`;
|
|
228
|
+
this.status = 'connecting';
|
|
229
|
+
|
|
230
|
+
this.client = xmpp.client({
|
|
231
|
+
service: url,
|
|
232
|
+
username: walletToUsername(this.username),
|
|
233
|
+
password: this.password,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Wrap `send` so the dev logger sees outgoing stanzas too.
|
|
237
|
+
// Guarded: some @xmpp/client builds define `send` as a getter or
|
|
238
|
+
// non-writable property, and overwriting would throw silently and
|
|
239
|
+
// strand the whole pipeline. We catch everything and fall back to
|
|
240
|
+
// the unwrapped client.
|
|
241
|
+
try {
|
|
242
|
+
const origSend = this.client.send?.bind(this.client);
|
|
243
|
+
if (origSend) {
|
|
244
|
+
const wrapped = (stanza: any) => {
|
|
245
|
+
try {
|
|
246
|
+
const tag = stanza?.name || 'stanza';
|
|
247
|
+
const id = stanza?.attrs?.id || '';
|
|
248
|
+
const to = stanza?.attrs?.to || '';
|
|
249
|
+
devPushLog(
|
|
250
|
+
'xmpp',
|
|
251
|
+
`→ ${tag}${id ? ` id=${id}` : ''}${to ? ` to=${to.split('/')[0]}` : ''}`,
|
|
252
|
+
stanza?.toString ? stanza.toString() : undefined
|
|
253
|
+
);
|
|
254
|
+
} catch {}
|
|
255
|
+
return origSend(stanza);
|
|
256
|
+
};
|
|
257
|
+
// Property may be non-writable on some builds; defineProperty
|
|
258
|
+
// gives us a clearer error than a plain assignment.
|
|
259
|
+
Object.defineProperty(this.client, 'send', {
|
|
260
|
+
value: wrapped,
|
|
261
|
+
writable: true,
|
|
262
|
+
configurable: true,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.warn(
|
|
267
|
+
'XmppClient: could not wrap client.send for dev logging',
|
|
268
|
+
err
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
this.attachEventListeners();
|
|
273
|
+
this.client.start().catch((error) => {
|
|
274
|
+
console.error('Error starting xmpp client:', error);
|
|
275
|
+
this.status = 'error';
|
|
276
|
+
});
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error('Error initializing client:', error);
|
|
279
|
+
this.status = 'error';
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
attachEventListeners() {
|
|
284
|
+
this.client.on('disconnect', () => {
|
|
285
|
+
console.log('XMPP disconnected.');
|
|
286
|
+
this.status = 'offline';
|
|
287
|
+
try {
|
|
288
|
+
// lazy-require to avoid pulling devLogger into prod bundles
|
|
289
|
+
// that don't reference it; tree-shaken via dead-code elim.
|
|
290
|
+
devPushLog('xmpp', 'disconnect');
|
|
291
|
+
} catch {}
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
this.client.on('online', () => {
|
|
295
|
+
console.log('XMPP online.', new Date());
|
|
296
|
+
this.status = 'online';
|
|
297
|
+
this.reconnectAttempts = 0;
|
|
298
|
+
try {
|
|
299
|
+
devPushLog(
|
|
300
|
+
'xmpp',
|
|
301
|
+
'online',
|
|
302
|
+
this.username
|
|
303
|
+
);
|
|
304
|
+
} catch {}
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
this.client.on('error', (error) => {
|
|
308
|
+
console.error('XMPP client error:', error);
|
|
309
|
+
try {
|
|
310
|
+
devPushLog(
|
|
311
|
+
'xmpp',
|
|
312
|
+
'error',
|
|
313
|
+
(error && error.message) || error
|
|
314
|
+
);
|
|
315
|
+
} catch {}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
this.client.on('stanza', (stanza: any) => {
|
|
319
|
+
try {
|
|
320
|
+
const tag = stanza?.name || 'stanza';
|
|
321
|
+
const id = stanza?.attrs?.id || '';
|
|
322
|
+
const from = stanza?.attrs?.from || '';
|
|
323
|
+
const type = stanza?.attrs?.type || '';
|
|
324
|
+
devPushLog(
|
|
325
|
+
'xmpp',
|
|
326
|
+
`← ${tag}${id ? ` id=${id}` : ''}${type ? ` type=${type}` : ''}${from ? ` from=${from.split('/')[0]}` : ''}`,
|
|
327
|
+
stanza?.toString ? stanza.toString() : undefined
|
|
328
|
+
);
|
|
329
|
+
} catch {}
|
|
330
|
+
handleStanza.bind(this, stanza, this)();
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Resolves once status === 'online' or rejects when status === 'error'.
|
|
336
|
+
* Mirrors the web client's `ensureConnected` helper.
|
|
337
|
+
*/
|
|
338
|
+
waitForOnline(timeoutMs: number = 15000): Promise<void> {
|
|
339
|
+
if (this.status === 'online') {return Promise.resolve();}
|
|
340
|
+
return new Promise((resolve, reject) => {
|
|
341
|
+
const start = Date.now();
|
|
342
|
+
const tick = () => {
|
|
343
|
+
if (this.status === 'online') {return resolve();}
|
|
344
|
+
if (this.status === 'error') {
|
|
345
|
+
return reject(new Error('XMPP client error'));
|
|
346
|
+
}
|
|
347
|
+
if (Date.now() - start > timeoutMs) {
|
|
348
|
+
return reject(new Error('XMPP connect timeout'));
|
|
349
|
+
}
|
|
350
|
+
setTimeout(tick, 250);
|
|
351
|
+
};
|
|
352
|
+
tick();
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Alias to match the web XmppClientInterface.
|
|
357
|
+
ensureConnected(timeout?: number): Promise<void> {
|
|
358
|
+
return this.waitForOnline(timeout);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
scheduleReconnect() {
|
|
362
|
+
if (this.suppressReconnect) {return;}
|
|
363
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
364
|
+
console.error('Max reconnect attempts reached.');
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
this.reconnectAttempts++;
|
|
368
|
+
const delay =
|
|
369
|
+
this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
370
|
+
console.log(`Reconnecting attempt ${this.reconnectAttempts} in ${delay}ms`);
|
|
371
|
+
setTimeout(() => this.reconnect(), delay);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
reconnect() {
|
|
375
|
+
if (this.suppressReconnect) {return;}
|
|
376
|
+
console.log('Attempting to reconnect xmpp client...');
|
|
377
|
+
if (this.client) {
|
|
378
|
+
this.client.stop().finally(() => {
|
|
379
|
+
this.initializeClient();
|
|
380
|
+
});
|
|
381
|
+
} else {
|
|
382
|
+
this.initializeClient();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
async disconnect(options?: { suppressReconnect?: boolean }): Promise<void> {
|
|
387
|
+
if (options?.suppressReconnect) {this.suppressReconnect = true;}
|
|
388
|
+
return this.close();
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
async close() {
|
|
392
|
+
if (this.client) {
|
|
393
|
+
try {
|
|
394
|
+
await this.client.stop();
|
|
395
|
+
console.log('XMPP client connection closed.');
|
|
396
|
+
} catch (error) {
|
|
397
|
+
console.error('Error closing the xmpp client:', error);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
this.status = 'offline';
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
getRoomsStanza = async () => {
|
|
404
|
+
await getRooms(this.client);
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
//room functions
|
|
408
|
+
|
|
409
|
+
async createRoomStanza(title: string, description: string, to?: string) {
|
|
410
|
+
return await createRoom(title, description, this.client, to);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
async inviteRoomRequestStanza(to: string, roomJid: string) {
|
|
414
|
+
await inviteRoomRequest(this.client, to, roomJid);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
leaveTheRoomStanza = (roomJID: string) => {
|
|
418
|
+
leaveTheRoom(roomJID, this.client);
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
presenceInRoomStanza = (roomJID: string) => {
|
|
422
|
+
presenceInRoom(this.client, roomJID);
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
getHistoryStanza = async (
|
|
426
|
+
chatJID: string,
|
|
427
|
+
max: number,
|
|
428
|
+
before?: number,
|
|
429
|
+
id?: string,
|
|
430
|
+
options?: HistoryOptions
|
|
431
|
+
) => {
|
|
432
|
+
if (options?.coalesceRoom) {
|
|
433
|
+
return this.enqueueHistoryTask({
|
|
434
|
+
chatJID,
|
|
435
|
+
max,
|
|
436
|
+
before,
|
|
437
|
+
id,
|
|
438
|
+
source: options?.source || 'default',
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
return await getHistory(this.client, chatJID, max, before, id);
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
getLastMessageArchiveStanza(roomJID: string) {
|
|
445
|
+
getLastMessage(this.client, roomJID);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
setRoomImageStanza = (
|
|
449
|
+
roomJid: string,
|
|
450
|
+
roomThumbnail: string,
|
|
451
|
+
type: string,
|
|
452
|
+
roomBackground?: string
|
|
453
|
+
) => {
|
|
454
|
+
setRoomImage(roomJid, roomThumbnail, type, this.client, roomBackground);
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
getRoomInfoStanza = (roomJID: string) => {
|
|
458
|
+
getRoomInfo(roomJID, this.client);
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
getRoomMembersStanza = (roomJID: string) => {
|
|
462
|
+
getRoomMembers(roomJID, this.client);
|
|
463
|
+
};
|
|
464
|
+
|
|
465
|
+
//messages
|
|
466
|
+
sendMessage = (
|
|
467
|
+
roomJID: string,
|
|
468
|
+
firstName: string,
|
|
469
|
+
lastName: string,
|
|
470
|
+
photo: string,
|
|
471
|
+
walletAddress: string,
|
|
472
|
+
userMessage: string,
|
|
473
|
+
notDisplayedValue?: string,
|
|
474
|
+
isReply?: boolean,
|
|
475
|
+
showInChannel?: boolean,
|
|
476
|
+
mainMessage?: string,
|
|
477
|
+
customId?: string
|
|
478
|
+
) => {
|
|
479
|
+
sendTextMessage(
|
|
480
|
+
this.client,
|
|
481
|
+
roomJID,
|
|
482
|
+
firstName,
|
|
483
|
+
lastName,
|
|
484
|
+
photo,
|
|
485
|
+
walletAddress,
|
|
486
|
+
userMessage,
|
|
487
|
+
notDisplayedValue,
|
|
488
|
+
isReply,
|
|
489
|
+
showInChannel,
|
|
490
|
+
mainMessage,
|
|
491
|
+
this.devServer || DEFAULT_DEV_SERVER,
|
|
492
|
+
customId
|
|
493
|
+
);
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
deleteMessageStanza(room: string, msgId: string) {
|
|
497
|
+
deleteMessage(this.client, room, msgId);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
editMessageStanza(room: string, msgId: string, text: string) {
|
|
501
|
+
editMessage(this.client, room, msgId, text);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
sendTypingRequestStanza(chatId: string, fullName: string, start: boolean) {
|
|
505
|
+
sendTypingRequest(this.client, chatId, fullName, start);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
getChatsPrivateStoreRequestStanza = async () => {
|
|
509
|
+
if (this.disableLastRead) {return null;}
|
|
510
|
+
try {
|
|
511
|
+
return await getChatsPrivateStoreRequest(this.client);
|
|
512
|
+
} catch (error) {
|
|
513
|
+
console.log(error);
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
async actionSetTimestampToPrivateStoreStanza(
|
|
519
|
+
chatId: string,
|
|
520
|
+
timestamp: number,
|
|
521
|
+
chats?: string[]
|
|
522
|
+
) {
|
|
523
|
+
if (this.disableLastRead) {return;}
|
|
524
|
+
try {
|
|
525
|
+
await actionSetTimestampToPrivateStore(
|
|
526
|
+
this.client,
|
|
527
|
+
chatId,
|
|
528
|
+
timestamp,
|
|
529
|
+
chats
|
|
530
|
+
);
|
|
531
|
+
} catch (error) {}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
sendMediaMessageStanza(roomJID: string, data: any, customId?: string) {
|
|
535
|
+
return sendMediaMessage(
|
|
536
|
+
this.client,
|
|
537
|
+
roomJID,
|
|
538
|
+
data,
|
|
539
|
+
customId,
|
|
540
|
+
this.devServer || DEFAULT_DEV_SERVER
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// -------------------------------------------------------------------
|
|
545
|
+
// Method stubs to satisfy `XmppClientInterface`. Concrete RN xmpp
|
|
546
|
+
// helpers don't exist yet — the stubs log a single warning and no-op
|
|
547
|
+
// so consumers don't blow up at runtime. Replace with real impls when
|
|
548
|
+
// their `*.xmpp.ts` helpers are ported from the web side.
|
|
549
|
+
// -------------------------------------------------------------------
|
|
550
|
+
|
|
551
|
+
setVCardStanza(_xmppUsername: string) {
|
|
552
|
+
console.warn('setVCardStanza: not implemented in RN xmpp client');
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
async createPrivateRoomStanza(
|
|
556
|
+
title: string,
|
|
557
|
+
description: string,
|
|
558
|
+
to: string
|
|
559
|
+
): Promise<string> {
|
|
560
|
+
console.warn('createPrivateRoomStanza: not implemented; falling back to createRoom');
|
|
561
|
+
const result = await this.createRoomStanza(title, description, to);
|
|
562
|
+
return typeof result === 'string' ? result : '';
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
sendMessageReactionStanza(
|
|
566
|
+
_messageId: string,
|
|
567
|
+
_roomJid: string,
|
|
568
|
+
_reactionsList: string[],
|
|
569
|
+
_reactionSymbol?: string
|
|
570
|
+
) {
|
|
571
|
+
console.warn('sendMessageReactionStanza: not implemented in RN xmpp client');
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
sendTextMessageWithTranslateTagStanza(
|
|
575
|
+
roomJID: string,
|
|
576
|
+
firstName: string,
|
|
577
|
+
lastName: string,
|
|
578
|
+
photo: string,
|
|
579
|
+
walletAddress: string,
|
|
580
|
+
userMessage: string,
|
|
581
|
+
notDisplayedValue?: string,
|
|
582
|
+
isReply?: boolean,
|
|
583
|
+
showInChannel?: boolean,
|
|
584
|
+
mainMessage?: string,
|
|
585
|
+
_langSource?: string
|
|
586
|
+
) {
|
|
587
|
+
// No translate tag support yet — fall back to a regular text send.
|
|
588
|
+
this.sendMessage(
|
|
589
|
+
roomJID,
|
|
590
|
+
firstName,
|
|
591
|
+
lastName,
|
|
592
|
+
photo,
|
|
593
|
+
walletAddress,
|
|
594
|
+
userMessage,
|
|
595
|
+
notDisplayedValue,
|
|
596
|
+
isReply,
|
|
597
|
+
showInChannel,
|
|
598
|
+
mainMessage
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
export default XmppClient;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Middleware } from '@reduxjs/toolkit';
|
|
2
|
+
import { DeviceEventEmitter } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export const logoutMiddleware: Middleware =
|
|
5
|
+
(storeAPI) => (next) => (action: any) => {
|
|
6
|
+
if (!action || !action.type) {
|
|
7
|
+
console.error('Invalid action in logoutMiddleware:', action);
|
|
8
|
+
return next(action);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const result = next(action);
|
|
12
|
+
|
|
13
|
+
if (action.type === 'chatSettingStore/logout') {
|
|
14
|
+
try {
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
DeviceEventEmitter.emit('ethora-xmpp-logout');
|
|
17
|
+
}, 0);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.error('Error dispatching ethora-xmpp-logout event:', error);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Middleware } from '@reduxjs/toolkit';
|
|
2
|
+
import { updateRoom } from '../roomsSlice';
|
|
3
|
+
import { IRoom } from '../../types/types';
|
|
4
|
+
|
|
5
|
+
export const newMessageMidlleware: Middleware =
|
|
6
|
+
(storeAPI) => (next) => (action: any) => {
|
|
7
|
+
if (!action || !action.type) {
|
|
8
|
+
console.error('Invalid action in newMessageMiddleware:', action);
|
|
9
|
+
return next(action);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (action.type !== 'roomMessages/addRoomMessage') {
|
|
13
|
+
return next(action);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (!action.payload || typeof action.payload !== 'object') {
|
|
17
|
+
console.error('Invalid action payload for addRoomMessage:', action);
|
|
18
|
+
return next(action);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = next(action);
|
|
22
|
+
const state = storeAPI.getState();
|
|
23
|
+
const rooms: { [jid: string]: IRoom } = state.rooms.rooms;
|
|
24
|
+
|
|
25
|
+
const { roomJID, message } = action.payload;
|
|
26
|
+
|
|
27
|
+
if (rooms[roomJID]?.lastMessageTimestamp <= Number(message.id)) {
|
|
28
|
+
storeAPI.dispatch(
|
|
29
|
+
updateRoom({
|
|
30
|
+
jid: roomJID,
|
|
31
|
+
updates: { lastMessageTimestamp: Number(message.id) ?? 0 },
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// import { Middleware, PayloadAction } from '@reduxjs/toolkit';
|
|
40
|
+
// import { updateRoom } from '../roomsSlice';
|
|
41
|
+
// import { AddRoomMessageAction, IRoom } from '../../types/types';
|
|
42
|
+
// import { nanoToMs } from '../../helpers/nanoToMs';
|
|
43
|
+
|
|
44
|
+
// export const newMessageMidlleware: Middleware =
|
|
45
|
+
// (storeAPI) =>
|
|
46
|
+
// (next) =>
|
|
47
|
+
// (action: PayloadAction<Partial<AddRoomMessageAction>>) => {
|
|
48
|
+
// if (action.type !== 'roomMessages/addRoomMessage') {
|
|
49
|
+
// return next(action);
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// const result = next(action);
|
|
53
|
+
// const state = storeAPI.getState();
|
|
54
|
+
// const rooms: { [jid: string]: IRoom } = state.rooms.rooms;
|
|
55
|
+
// const { roomJID, message } = action.payload;
|
|
56
|
+
|
|
57
|
+
// const updLastMessage = () => {
|
|
58
|
+
// const updates = {
|
|
59
|
+
// lastMessageTimestamp: nanoToMs(message.id) ?? 0,
|
|
60
|
+
// lastMessage: { ...message },
|
|
61
|
+
// };
|
|
62
|
+
|
|
63
|
+
// storeAPI.dispatch(
|
|
64
|
+
// updateRoom({
|
|
65
|
+
// jid: roomJID,
|
|
66
|
+
// updates,
|
|
67
|
+
// })
|
|
68
|
+
// );
|
|
69
|
+
// };
|
|
70
|
+
|
|
71
|
+
// if (!message.body) {
|
|
72
|
+
// return result;
|
|
73
|
+
// }
|
|
74
|
+
|
|
75
|
+
// try {
|
|
76
|
+
// if (
|
|
77
|
+
// rooms[roomJID]?.lastMessageTimestamp <= nanoToMs(message.id) ||
|
|
78
|
+
// !rooms[roomJID]?.lastMessageTimestamp
|
|
79
|
+
// ) {
|
|
80
|
+
// updLastMessage();
|
|
81
|
+
// }
|
|
82
|
+
// } catch (error) {
|
|
83
|
+
// console.error('Error updating room last message:', error);
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// return result;
|
|
87
|
+
// };
|