@ethora/chat-component-rn 26.5.5 → 26.5.7
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 +44 -0
- package/lib/commonjs/components/MainComponents/ChatHeader.js +7 -1
- package/lib/commonjs/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatRoom.js +8 -2
- package/lib/commonjs/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js +2 -1
- package/lib/commonjs/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MediaMessage.js +11 -5
- package/lib/commonjs/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/commonjs/components/MainComponents/MessageList.js +10 -2
- package/lib/commonjs/components/MainComponents/MessageList.js.map +1 -1
- package/lib/commonjs/components/MessageBubble/Message.js +60 -7
- package/lib/commonjs/components/MessageBubble/Message.js.map +1 -1
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js +35 -16
- package/lib/commonjs/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js +11 -2
- package/lib/commonjs/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js +1 -1
- package/lib/commonjs/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/commonjs/components/styled/MediaFilePreview.js +96 -5
- package/lib/commonjs/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/commonjs/components/styled/MessageImage.js +1 -2
- package/lib/commonjs/components/styled/MessageImage.js.map +1 -1
- package/lib/commonjs/components/styled/SendInput.js +4 -2
- package/lib/commonjs/components/styled/SendInput.js.map +1 -1
- package/lib/commonjs/components/styled/VideoMessage.js +2 -10
- package/lib/commonjs/components/styled/VideoMessage.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +71 -2
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/mimeToExtension.js +131 -0
- package/lib/commonjs/helpers/mimeToExtension.js.map +1 -0
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js +73 -1
- package/lib/commonjs/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/commonjs/hooks/useChatWrapperInit.js +22 -10
- package/lib/commonjs/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/commonjs/hooks/useEventHandlers.js +9 -1
- package/lib/commonjs/hooks/useEventHandlers.js.map +1 -1
- package/lib/commonjs/hooks/useMessageHeapState.js +6 -2
- package/lib/commonjs/hooks/useMessageHeapState.js.map +1 -1
- package/lib/commonjs/hooks/useSendMessage.js +48 -4
- package/lib/commonjs/hooks/useSendMessage.js.map +1 -1
- package/lib/commonjs/networking/api-requests/auth.api.js +7 -1
- package/lib/commonjs/networking/api-requests/auth.api.js.map +1 -1
- package/lib/commonjs/networking/xmppClient.js +87 -1
- package/lib/commonjs/networking/xmppClient.js.map +1 -1
- package/lib/commonjs/roomStore/roomHeapSlice.js +26 -8
- package/lib/commonjs/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/module/components/MainComponents/ChatHeader.js +7 -1
- package/lib/module/components/MainComponents/ChatHeader.js.map +1 -1
- package/lib/module/components/MainComponents/ChatRoom.js +8 -2
- package/lib/module/components/MainComponents/ChatRoom.js.map +1 -1
- package/lib/module/components/MainComponents/ChatWrapper.js +2 -1
- package/lib/module/components/MainComponents/ChatWrapper.js.map +1 -1
- package/lib/module/components/MainComponents/MediaMessage.js +11 -5
- package/lib/module/components/MainComponents/MediaMessage.js.map +1 -1
- package/lib/module/components/MainComponents/MessageList.js +11 -3
- package/lib/module/components/MainComponents/MessageList.js.map +1 -1
- package/lib/module/components/MessageBubble/Message.js +60 -7
- package/lib/module/components/MessageBubble/Message.js.map +1 -1
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js +36 -17
- package/lib/module/components/Modals/FilePreviewModal/FilePreviewModal.js.map +1 -1
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js +11 -2
- package/lib/module/components/Modals/ModalWrapper/ModalWrapper.js.map +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js +1 -1
- package/lib/module/components/Modals/UserProfileModal/UserProfileModal.js.map +1 -1
- package/lib/module/components/styled/MediaFilePreview.js +97 -6
- package/lib/module/components/styled/MediaFilePreview.js.map +1 -1
- package/lib/module/components/styled/MessageImage.js +1 -2
- package/lib/module/components/styled/MessageImage.js.map +1 -1
- package/lib/module/components/styled/SendInput.js +4 -2
- package/lib/module/components/styled/SendInput.js.map +1 -1
- package/lib/module/components/styled/VideoMessage.js +2 -10
- package/lib/module/components/styled/VideoMessage.js.map +1 -1
- package/lib/module/context/xmppProvider.js +73 -3
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/mimeToExtension.js +124 -0
- package/lib/module/helpers/mimeToExtension.js.map +1 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js +71 -0
- package/lib/module/helpers/resolveInitBeforeLoadUser.js.map +1 -1
- package/lib/module/hooks/useChatWrapperInit.js +22 -10
- package/lib/module/hooks/useChatWrapperInit.js.map +1 -1
- package/lib/module/hooks/useEventHandlers.js +9 -1
- package/lib/module/hooks/useEventHandlers.js.map +1 -1
- package/lib/module/hooks/useMessageHeapState.js +6 -2
- package/lib/module/hooks/useMessageHeapState.js.map +1 -1
- package/lib/module/hooks/useSendMessage.js +49 -5
- package/lib/module/hooks/useSendMessage.js.map +1 -1
- package/lib/module/networking/api-requests/auth.api.js +7 -1
- package/lib/module/networking/api-requests/auth.api.js.map +1 -1
- package/lib/module/networking/xmppClient.js +87 -1
- package/lib/module/networking/xmppClient.js.map +1 -1
- package/lib/module/roomStore/roomHeapSlice.js +24 -7
- package/lib/module/roomStore/roomHeapSlice.js.map +1 -1
- package/lib/typescript/components/MainComponents/ChatHeader.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatRoom.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/ChatWrapper.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MediaMessage.d.ts.map +1 -1
- package/lib/typescript/components/MainComponents/MessageList.d.ts.map +1 -1
- package/lib/typescript/components/MessageBubble/Message.d.ts.map +1 -1
- package/lib/typescript/components/Modals/FilePreviewModal/FilePreviewModal.d.ts.map +1 -1
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts +6 -0
- package/lib/typescript/components/Modals/ModalWrapper/ModalWrapper.d.ts.map +1 -1
- package/lib/typescript/components/styled/MediaFilePreview.d.ts.map +1 -1
- package/lib/typescript/components/styled/MessageImage.d.ts.map +1 -1
- package/lib/typescript/components/styled/SendInput.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/mimeToExtension.d.ts +37 -0
- package/lib/typescript/helpers/mimeToExtension.d.ts.map +1 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts +18 -0
- package/lib/typescript/helpers/resolveInitBeforeLoadUser.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatWrapperInit.d.ts.map +1 -1
- package/lib/typescript/hooks/useEventHandlers.d.ts +6 -0
- package/lib/typescript/hooks/useEventHandlers.d.ts.map +1 -1
- package/lib/typescript/hooks/useMessageHeapState.d.ts +2 -0
- package/lib/typescript/hooks/useMessageHeapState.d.ts.map +1 -1
- package/lib/typescript/hooks/useSendMessage.d.ts +2 -1
- package/lib/typescript/hooks/useSendMessage.d.ts.map +1 -1
- package/lib/typescript/networking/api-requests/auth.api.d.ts.map +1 -1
- package/lib/typescript/networking/xmppClient.d.ts +25 -1
- package/lib/typescript/networking/xmppClient.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts +22 -1
- package/lib/typescript/roomStore/roomHeapSlice.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +6 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/MainComponents/ChatHeader.tsx +5 -1
- package/src/components/MainComponents/ChatRoom.tsx +6 -1
- package/src/components/MainComponents/ChatWrapper.tsx +1 -0
- package/src/components/MainComponents/MediaMessage.tsx +15 -8
- package/src/components/MainComponents/MessageList.tsx +10 -3
- package/src/components/MessageBubble/Message.tsx +64 -10
- package/src/components/Modals/FilePreviewModal/FilePreviewModal.tsx +30 -12
- package/src/components/Modals/ModalWrapper/ModalWrapper.tsx +22 -1
- package/src/components/Modals/UserProfileModal/UserProfileModal.tsx +1 -1
- package/src/components/styled/MediaFilePreview.tsx +91 -5
- package/src/components/styled/MessageImage.tsx +1 -2
- package/src/components/styled/SendInput.tsx +3 -0
- package/src/components/styled/VideoMessage.tsx +3 -10
- package/src/context/xmppProvider.tsx +90 -2
- package/src/helpers/mimeToExtension.ts +135 -0
- package/src/helpers/resolveInitBeforeLoadUser.ts +79 -0
- package/src/hooks/useChatWrapperInit.ts +51 -46
- package/src/hooks/useEventHandlers.tsx +24 -1
- package/src/hooks/useMessageHeapState.tsx +6 -2
- package/src/hooks/useSendMessage.tsx +75 -4
- package/src/networking/api-requests/auth.api.ts +5 -1
- package/src/networking/xmppClient.ts +95 -1
- package/src/roomStore/roomHeapSlice.ts +47 -4
- package/src/types/types.ts +10 -0
|
@@ -26,6 +26,25 @@ import { pushLog as devPushLog } from '../utils/devLogger';
|
|
|
26
26
|
// Canonical production XMPP WSS endpoint (standard wss/443, no port suffix).
|
|
27
27
|
const DEFAULT_DEV_SERVER = 'xmpp.chat.ethora.com';
|
|
28
28
|
|
|
29
|
+
// @xmpp/client surfaces SASL/stream errors in a few shapes depending on
|
|
30
|
+
// where it fails — XMPPError on stream:error, SASLError on SASL bind, or
|
|
31
|
+
// a generic Error whose message contains "not-authorized". Match all of
|
|
32
|
+
// them so we trigger the credentials refresh path consistently.
|
|
33
|
+
function isNotAuthorizedError(err: any): boolean {
|
|
34
|
+
if (!err) {return false;}
|
|
35
|
+
const condition =
|
|
36
|
+
err?.condition ||
|
|
37
|
+
err?.name ||
|
|
38
|
+
err?.type ||
|
|
39
|
+
err?.error?.condition ||
|
|
40
|
+
'';
|
|
41
|
+
if (typeof condition === 'string' && condition.includes('not-authorized')) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
const message = (err?.message || err?.text || '').toString();
|
|
45
|
+
return /not-authorized|SASLError/i.test(message);
|
|
46
|
+
}
|
|
47
|
+
|
|
29
48
|
type HistorySource = 'active' | 'send_ack' | 'background' | 'default';
|
|
30
49
|
|
|
31
50
|
interface HistoryOptions {
|
|
@@ -40,6 +59,11 @@ interface MamInFlightEntry {
|
|
|
40
59
|
startedAt: number;
|
|
41
60
|
}
|
|
42
61
|
|
|
62
|
+
export type XmppCredentialsProvider = () => Promise<{
|
|
63
|
+
username: string;
|
|
64
|
+
password: string;
|
|
65
|
+
}>;
|
|
66
|
+
|
|
43
67
|
export class XmppClient {
|
|
44
68
|
client!: Client;
|
|
45
69
|
xmppSettings?: xmppSettingsInterface;
|
|
@@ -56,6 +80,13 @@ export class XmppClient {
|
|
|
56
80
|
reconnectDelay = 2000;
|
|
57
81
|
suppressReconnect = false;
|
|
58
82
|
|
|
83
|
+
// Set when SASL fails with `not-authorized` (typically a stale JWT-
|
|
84
|
+
// derived XMPP password after idle). Triggers the credentialsProvider
|
|
85
|
+
// refresh path in reconnect().
|
|
86
|
+
lastAuthError: 'not-authorized' | null = null;
|
|
87
|
+
private credentialsProvider: XmppCredentialsProvider | null = null;
|
|
88
|
+
private credentialsRefreshInFlight: Promise<void> | null = null;
|
|
89
|
+
|
|
59
90
|
// ---- QoS state (mirrors web XmppClient) ----------------------------
|
|
60
91
|
presencesReady = false;
|
|
61
92
|
disableLastRead = false;
|
|
@@ -74,6 +105,23 @@ export class XmppClient {
|
|
|
74
105
|
return this.client && this.client.status === 'online';
|
|
75
106
|
}
|
|
76
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Inject (or replace) the callback used by reconnect() to fetch fresh
|
|
110
|
+
* XMPP credentials after a `not-authorized` SASL failure. The provider
|
|
111
|
+
* is responsible for refreshing whatever upstream token is needed
|
|
112
|
+
* (REST JWT, /users/client, etc.) and returning the resulting
|
|
113
|
+
* username + password.
|
|
114
|
+
*/
|
|
115
|
+
setCredentialsProvider(provider: XmppCredentialsProvider | null) {
|
|
116
|
+
this.credentialsProvider = provider;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Swap in fresh credentials before the next reconnect. */
|
|
120
|
+
updateCredentials(username: string, password: string) {
|
|
121
|
+
this.username = username;
|
|
122
|
+
this.password = password;
|
|
123
|
+
}
|
|
124
|
+
|
|
77
125
|
constructor(
|
|
78
126
|
username: string,
|
|
79
127
|
password: string,
|
|
@@ -285,6 +333,9 @@ export class XmppClient {
|
|
|
285
333
|
this.attachEventListeners();
|
|
286
334
|
this.client.start().catch((error: any) => {
|
|
287
335
|
console.error('Error starting xmpp client:', error);
|
|
336
|
+
if (isNotAuthorizedError(error)) {
|
|
337
|
+
this.lastAuthError = 'not-authorized';
|
|
338
|
+
}
|
|
288
339
|
this.status = 'error';
|
|
289
340
|
});
|
|
290
341
|
} catch (error) {
|
|
@@ -320,6 +371,9 @@ export class XmppClient {
|
|
|
320
371
|
|
|
321
372
|
this.client.on('error', (error: any) => {
|
|
322
373
|
console.error('XMPP client error:', error);
|
|
374
|
+
if (isNotAuthorizedError(error)) {
|
|
375
|
+
this.lastAuthError = 'not-authorized';
|
|
376
|
+
}
|
|
323
377
|
try {
|
|
324
378
|
devPushLog(
|
|
325
379
|
'xmpp',
|
|
@@ -385,9 +439,25 @@ export class XmppClient {
|
|
|
385
439
|
setTimeout(() => this.reconnect(), delay);
|
|
386
440
|
}
|
|
387
441
|
|
|
388
|
-
reconnect() {
|
|
442
|
+
async reconnect() {
|
|
389
443
|
if (this.suppressReconnect) {return;}
|
|
390
444
|
console.log('Attempting to reconnect xmpp client...');
|
|
445
|
+
|
|
446
|
+
// If the last failure was a SASL `not-authorized` (typically a stale
|
|
447
|
+
// JWT-derived XMPP password after idle), try to fetch fresh creds
|
|
448
|
+
// before retrying. Without this, reconnect retries with the same
|
|
449
|
+
// stale password forever and the user has to kill the app.
|
|
450
|
+
if (this.lastAuthError === 'not-authorized' && this.credentialsProvider) {
|
|
451
|
+
try {
|
|
452
|
+
await this.refreshCredentialsOnce();
|
|
453
|
+
} catch (err) {
|
|
454
|
+
console.warn(
|
|
455
|
+
'XMPP credential refresh failed; reconnecting with cached creds',
|
|
456
|
+
err
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
391
461
|
if (this.client) {
|
|
392
462
|
this.client.stop().finally(() => {
|
|
393
463
|
this.initializeClient();
|
|
@@ -397,6 +467,30 @@ export class XmppClient {
|
|
|
397
467
|
}
|
|
398
468
|
}
|
|
399
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Single-flight wrapper around credentialsProvider. Multiple concurrent
|
|
472
|
+
* reconnect() calls (e.g. from the provider's reconnect effect firing
|
|
473
|
+
* twice quickly) share one in-flight request and update `this.password`
|
|
474
|
+
* exactly once.
|
|
475
|
+
*/
|
|
476
|
+
private refreshCredentialsOnce(): Promise<void> {
|
|
477
|
+
if (this.credentialsRefreshInFlight) {return this.credentialsRefreshInFlight;}
|
|
478
|
+
if (!this.credentialsProvider) {return Promise.resolve();}
|
|
479
|
+
const provider = this.credentialsProvider;
|
|
480
|
+
this.credentialsRefreshInFlight = (async () => {
|
|
481
|
+
try {
|
|
482
|
+
const fresh = await provider();
|
|
483
|
+
if (fresh?.username && fresh?.password) {
|
|
484
|
+
this.updateCredentials(fresh.username, fresh.password);
|
|
485
|
+
this.lastAuthError = null;
|
|
486
|
+
}
|
|
487
|
+
} finally {
|
|
488
|
+
this.credentialsRefreshInFlight = null;
|
|
489
|
+
}
|
|
490
|
+
})();
|
|
491
|
+
return this.credentialsRefreshInFlight;
|
|
492
|
+
}
|
|
493
|
+
|
|
400
494
|
async disconnect(options?: { suppressReconnect?: boolean }): Promise<void> {
|
|
401
495
|
if (options?.suppressReconnect) {this.suppressReconnect = true;}
|
|
402
496
|
return this.close();
|
|
@@ -2,18 +2,43 @@ import { createSlice, PayloadAction, type Slice } from '@reduxjs/toolkit';
|
|
|
2
2
|
import type { WritableDraft } from 'immer';
|
|
3
3
|
import { IMessage } from '../types/types';
|
|
4
4
|
|
|
5
|
+
// Saved alongside a failed-message id so the retry button can resend
|
|
6
|
+
// without the bubble needing to remember the original draft itself.
|
|
7
|
+
// `kind === 'text'` carries the plain body; `kind === 'media'` carries
|
|
8
|
+
// the upload payload so we don't have to make the user re-pick the file.
|
|
9
|
+
export type FailedMessagePayload =
|
|
10
|
+
| {
|
|
11
|
+
kind: 'text';
|
|
12
|
+
id: string;
|
|
13
|
+
roomJID: string;
|
|
14
|
+
body: string;
|
|
15
|
+
isReply?: boolean;
|
|
16
|
+
isChecked?: boolean;
|
|
17
|
+
mainMessage?: string;
|
|
18
|
+
}
|
|
19
|
+
| {
|
|
20
|
+
kind: 'media';
|
|
21
|
+
id: string;
|
|
22
|
+
roomJID: string;
|
|
23
|
+
data: any;
|
|
24
|
+
type: string;
|
|
25
|
+
isReply?: boolean;
|
|
26
|
+
isChecked?: boolean;
|
|
27
|
+
mainMessage?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
5
30
|
export interface roomHeapSliceState {
|
|
6
31
|
messageHeap: IMessage[];
|
|
32
|
+
// Keyed by message id so the bubble's `isFailed = failedMessages[id]`
|
|
33
|
+
// check is O(1). Carries enough payload data to actually retry.
|
|
34
|
+
failedMessages: Record<string, FailedMessagePayload>;
|
|
7
35
|
}
|
|
8
36
|
|
|
9
37
|
const initialState: roomHeapSliceState = {
|
|
10
38
|
messageHeap: [],
|
|
39
|
+
failedMessages: {},
|
|
11
40
|
};
|
|
12
41
|
|
|
13
|
-
// Reducers extracted as a named const so we can give the slice an
|
|
14
|
-
// explicit Slice<State, typeof reducers, Name> type. Without that, tsc's
|
|
15
|
-
// declaration emission inlines immer's internal WritableNonArrayDraft
|
|
16
|
-
// type and fails with TS4023.
|
|
17
42
|
const reducers = {
|
|
18
43
|
addMessageToHeap: (state: WritableDraft<roomHeapSliceState>, action: PayloadAction<IMessage>) => {
|
|
19
44
|
state.messageHeap.push(action.payload);
|
|
@@ -26,6 +51,22 @@ const reducers = {
|
|
|
26
51
|
},
|
|
27
52
|
clearHeap: (state: WritableDraft<roomHeapSliceState>) => {
|
|
28
53
|
state.messageHeap = [];
|
|
54
|
+
state.failedMessages = {};
|
|
55
|
+
},
|
|
56
|
+
markMessageFailed: (
|
|
57
|
+
state: WritableDraft<roomHeapSliceState>,
|
|
58
|
+
action: PayloadAction<FailedMessagePayload>
|
|
59
|
+
) => {
|
|
60
|
+
state.failedMessages[action.payload.id] = action.payload;
|
|
61
|
+
// Drop from the pending heap — the bubble looks at both, and
|
|
62
|
+
// showing "sending..." alongside a failure indicator is confusing.
|
|
63
|
+
const index = state.messageHeap.findIndex((m) => m.id === action.payload.id);
|
|
64
|
+
if (index !== -1) {
|
|
65
|
+
state.messageHeap.splice(index, 1);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
clearMessageFailure: (state: WritableDraft<roomHeapSliceState>, action: PayloadAction<string>) => {
|
|
69
|
+
delete state.failedMessages[action.payload];
|
|
29
70
|
},
|
|
30
71
|
};
|
|
31
72
|
|
|
@@ -39,6 +80,8 @@ export const {
|
|
|
39
80
|
addMessageToHeap,
|
|
40
81
|
clearHeap,
|
|
41
82
|
removeMessageFromHeapById,
|
|
83
|
+
markMessageFailed,
|
|
84
|
+
clearMessageFailure,
|
|
42
85
|
} = roomHeapSlice.actions;
|
|
43
86
|
|
|
44
87
|
export default roomHeapSlice.reducer;
|
package/src/types/types.ts
CHANGED
|
@@ -249,6 +249,11 @@ export interface IConfig {
|
|
|
249
249
|
disableHeader?: boolean;
|
|
250
250
|
disableMedia?: boolean;
|
|
251
251
|
chatHeaderBurgerMenu?: boolean;
|
|
252
|
+
// Hide the burger icon entirely (the icon that opens the chatHeader-
|
|
253
|
+
// BurgerMenu dropdown). `chatHeaderBurgerMenu` controls dropdown
|
|
254
|
+
// visibility only — set this flag when you want neither the icon nor
|
|
255
|
+
// the dropdown to render (e.g. patient-facing apps with a single room).
|
|
256
|
+
disableChatHeaderBurgerMenuIcon?: boolean;
|
|
252
257
|
chatHeaderAdditional?: { enabled: boolean; element: any };
|
|
253
258
|
headerMenu?: () => void;
|
|
254
259
|
headerChatMenu?: () => void;
|
|
@@ -420,6 +425,11 @@ export interface IConfig {
|
|
|
420
425
|
roomJID: string;
|
|
421
426
|
user: any;
|
|
422
427
|
}) => void;
|
|
428
|
+
onMessageRetry?: (event: {
|
|
429
|
+
messageId: string;
|
|
430
|
+
roomJID: string;
|
|
431
|
+
messageType: 'text' | 'media';
|
|
432
|
+
}) => void;
|
|
423
433
|
};
|
|
424
434
|
}
|
|
425
435
|
|