@ethora/chat-component 26.7.4 → 26.7.6

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.
Files changed (152) hide show
  1. package/README.md +72 -16
  2. package/dist/ChatProfileModal-hxsWI8cx.js +2139 -0
  3. package/dist/FilePreviewModal-CwWnHsB1.js +736 -0
  4. package/dist/ManageDataModal-CDPXcC93.js +159 -0
  5. package/dist/MarkdownBody-DBJGraWM.js +16874 -0
  6. package/dist/SideDrawer-Dr_lkaOW.js +226 -0
  7. package/dist/UserProfileModal-Q_jhXpsX.js +568 -0
  8. package/dist/UserSettingsModal-OcAJao-d.js +50 -0
  9. package/dist/{VideoCallOverlay-BUfKp87t.js → VideoCallOverlay-CC4sShdK.js} +9 -10
  10. package/dist/VisibilityModal-DkMhx_2k.js +132 -0
  11. package/dist/assets/icons.d.ts +30 -0
  12. package/dist/components/ContextMenu/ContextMenuComponents.d.ts +1 -3
  13. package/dist/components/EmojiPicker/LazyEmojiPicker.d.ts +3 -0
  14. package/dist/components/ExampleComponents/CustomMessage.d.ts +3 -3
  15. package/dist/components/Files/FilesList.d.ts +12 -0
  16. package/dist/components/Files/FilesPanel.d.ts +3 -0
  17. package/dist/components/Files/fileCategory.d.ts +13 -0
  18. package/dist/components/InputComponents/AttachmentPreview.d.ts +17 -0
  19. package/dist/components/InputComponents/MentionDropdown.d.ts +13 -0
  20. package/dist/components/InputComponents/MentionPickerModal.d.ts +19 -0
  21. package/dist/components/MainComponents/AttachmentList.d.ts +7 -0
  22. package/dist/components/MainComponents/ChatErrorBoundary.d.ts +53 -0
  23. package/dist/components/MainComponents/ChatErrorScreen.d.ts +24 -0
  24. package/dist/components/MainComponents/HeaderLogo.d.ts +18 -0
  25. package/dist/components/MainComponents/MediaMessage.d.ts +5 -0
  26. package/dist/components/MainComponents/MessageContainer.d.ts +2 -2
  27. package/dist/components/MainComponents/ReduxWrapper.d.ts +1 -2
  28. package/dist/components/MainComponents/SystemMessage.d.ts +1 -2
  29. package/dist/components/MenuRoom/MenuRoom.d.ts +1 -0
  30. package/dist/components/MessageBubble/CustomDivider.d.ts +3 -3
  31. package/dist/components/MessageBubble/Message.d.ts +2 -2
  32. package/dist/components/MessageBubble/MessageTranslate.d.ts +28 -10
  33. package/dist/components/MessageBubble/QuickReplies.d.ts +19 -0
  34. package/dist/components/Modals/ChatProfileModal/ChatProfileMemberRow.d.ts +18 -0
  35. package/dist/components/Modals/FilePreviewModal/FilePreviewModal.d.ts +17 -0
  36. package/dist/components/Modals/FilePreviewModal/ImageLightbox.d.ts +35 -0
  37. package/dist/components/Modals/FilePreviewModal/PdfView.d.ts +14 -3
  38. package/dist/components/Modals/NewChatModal/styledNewChatComponents.d.ts +12 -0
  39. package/dist/components/Modals/SettingsModals/Visibility/StyledComponents.d.ts +1 -1
  40. package/dist/components/Modals/SideDrawer/DrawerProfileParts.d.ts +13 -0
  41. package/dist/components/Modals/SideDrawer/SideDrawer.d.ts +44 -0
  42. package/dist/components/Modals/modalComponents.d.ts +6 -0
  43. package/dist/components/Modals/styledModalComponents.d.ts +14 -3
  44. package/dist/components/RoomComponents/ChatRoomItem.d.ts +0 -1
  45. package/dist/components/RoomComponents/OnlineUsersPopover.d.ts +0 -1
  46. package/dist/components/UsersList/StyledComponents.d.ts +5 -1
  47. package/dist/components/UsersList/UsersList.d.ts +23 -0
  48. package/dist/components/styled/Button.d.ts +11 -1
  49. package/dist/components/styled/ChatWrapperBox.d.ts +3 -1
  50. package/dist/components/styled/PdfMessage.d.ts +13 -0
  51. package/dist/components/styled/RoomListComponents/index.d.ts +22 -1
  52. package/dist/components/styled/SendInput.d.ts +19 -5
  53. package/dist/components/styled/StyledComponents.d.ts +1 -1
  54. package/dist/components/styled/StyledInputComponents/MediaComponents.d.ts +18 -0
  55. package/dist/components/styled/StyledInputComponents/StyledInputComponents.d.ts +21 -0
  56. package/dist/components/styled/TreadLabel.d.ts +2 -2
  57. package/dist/components/styled/UnsupportedType.d.ts +1 -1
  58. package/dist/examples/quiz/QuizDemo.d.ts +3 -0
  59. package/dist/examples/quiz/quizScript.d.ts +38 -0
  60. package/dist/examples/quiz/useDemoSession.d.ts +42 -0
  61. package/dist/examples/quiz/useQuizFlow.d.ts +47 -0
  62. package/dist/firebase-config.d.ts +2 -4
  63. package/dist/handleCopyClick-CpmPa6VI.js +32 -0
  64. package/dist/helpers/MarkdownBody.d.ts +7 -0
  65. package/dist/helpers/attachments.d.ts +33 -0
  66. package/dist/helpers/botMarkup.d.ts +30 -0
  67. package/dist/helpers/constants/MODAL_TYPES.d.ts +11 -7
  68. package/dist/helpers/ethoraLogger.d.ts +8 -0
  69. package/dist/helpers/fileKind.d.ts +17 -0
  70. package/dist/helpers/hiddenRooms.d.ts +1 -1
  71. package/dist/helpers/historyPreloadScheduler.d.ts +1 -0
  72. package/dist/helpers/lazyEmoji.d.ts +3 -0
  73. package/dist/helpers/localStorageUser.d.ts +1 -1
  74. package/dist/helpers/markdownSanitizeSchema.d.ts +3 -0
  75. package/dist/helpers/mentions.d.ts +63 -0
  76. package/dist/helpers/parseMessageBody.d.ts +12 -2
  77. package/dist/helpers/pdf/loadPdfjs.d.ts +64 -0
  78. package/dist/helpers/quickReplies.d.ts +31 -0
  79. package/dist/helpers/remarkLineBreaks.d.ts +42 -0
  80. package/dist/helpers/resolveMessageTranslation.d.ts +34 -0
  81. package/dist/helpers/roomImageGallery.d.ts +53 -0
  82. package/dist/helpers/secureFileUrl.d.ts +8 -0
  83. package/dist/helpers/sendFailureWatchdog.d.ts +62 -0
  84. package/dist/helpers/transformTranslatations.d.ts +1 -2
  85. package/dist/hooks/pushSubscriptionSweep.d.ts +41 -0
  86. package/dist/hooks/useChatWrapperInit.d.ts +1 -0
  87. package/dist/hooks/useFilesEndpointSupport.d.ts +9 -0
  88. package/dist/hooks/useInView.d.ts +17 -0
  89. package/dist/hooks/useMentionComposer.d.ts +45 -0
  90. package/dist/hooks/useMessageHeapState.d.ts +1 -1
  91. package/dist/hooks/useMessageTranslation.d.ts +4 -3
  92. package/dist/hooks/useModalDismiss.d.ts +27 -0
  93. package/dist/hooks/useMyFiles.d.ts +16 -0
  94. package/dist/hooks/usePdfThumbnail.d.ts +22 -0
  95. package/dist/hooks/useRoomMute.d.ts +19 -0
  96. package/dist/hooks/useRoomState.d.ts +1 -1
  97. package/dist/hooks/useSendMessage.d.ts +4 -3
  98. package/dist/hooks/useTypography.d.ts +1 -1
  99. package/dist/hooks/useUnreadMessagesCounter.d.ts +11 -2
  100. package/dist/index.esm-B-3fyDHY.js +28 -0
  101. package/dist/index.esm-CRM4VCRa.js +943 -0
  102. package/dist/index.esm-msbp26WN.js +3352 -0
  103. package/dist/index.esm2017-CL0mvq6y.js +1578 -0
  104. package/dist/main-B-8IhwaP.js +31837 -0
  105. package/dist/main.css +1 -1
  106. package/dist/main.d.ts +16 -0
  107. package/dist/main.js +19 -18
  108. package/dist/module-DGXkb0R_.js +2960 -0
  109. package/dist/native-CDi4YD_s.js +13 -0
  110. package/dist/networking/api-requests/files.api.d.ts +19 -0
  111. package/dist/networking/api-requests/rooms.api.d.ts +10 -2
  112. package/dist/networking/api-requests/translate.api.d.ts +15 -0
  113. package/dist/networking/api-requests/user.api.d.ts +2 -0
  114. package/dist/networking/sharedRequest.d.ts +4 -0
  115. package/dist/networking/xmpp/allRoomPresences.xmpp.d.ts +3 -1
  116. package/dist/networking/xmpp/createTimeoutPromise.xmpp.d.ts +14 -0
  117. package/dist/networking/xmpp/sendTextMessage.xmpp.d.ts +2 -1
  118. package/dist/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts +2 -1
  119. package/dist/networking/xmppClient.d.ts +12 -3
  120. package/dist/pdf-B5b7qHu6.js +17130 -0
  121. package/dist/pdf.worker.min-COYn-gId.js +24385 -0
  122. package/dist/roomStore/index.d.ts +20 -0
  123. package/dist/roomStore/persistEncryption.d.ts +51 -0
  124. package/dist/roomStore/roomsSlice.d.ts +49 -6
  125. package/dist/styles/classNames.d.ts +35 -0
  126. package/dist/styles/motion.d.ts +44 -0
  127. package/dist/styles/tokens.d.ts +27 -0
  128. package/dist/testIds.d.ts +1 -1
  129. package/dist/types/models/attachment.model.d.ts +33 -0
  130. package/dist/types/models/config.model.d.ts +179 -19
  131. package/dist/types/models/file.model.d.ts +20 -0
  132. package/dist/types/models/message.model.d.ts +16 -6
  133. package/dist/types/models/room.model.d.ts +12 -2
  134. package/dist/types/types.d.ts +3 -1
  135. package/dist/utils/resendMessage.d.ts +22 -1
  136. package/dist/utils/translateModePolicy.d.ts +1 -0
  137. package/dist/wavesurfer.esm-D_a19qBW.js +952 -0
  138. package/package.json +22 -2
  139. package/dist/VideoCallOverlay-BUfKp87t.js.map +0 -1
  140. package/dist/components/MainComponents/VirtualList.d.ts +0 -10
  141. package/dist/components/Modals/SettingsModals/BlockedUsers/BlockedUsersModal.d.ts +0 -6
  142. package/dist/components/Modals/SettingsModals/DocumentShares/DocumentSharesModal.d.ts +0 -6
  143. package/dist/components/Modals/SettingsModals/ManageDataModal/StyledComponents.d.ts +0 -0
  144. package/dist/components/Modals/SettingsModals/ProfileShares/ProfileShares.d.ts +0 -6
  145. package/dist/components/Modals/SettingsModals/Referrals/Referrals.d.ts +0 -6
  146. package/dist/hooks/useMessageQueue.d.ts +0 -4
  147. package/dist/main-DFqqDiy-.js +0 -55707
  148. package/dist/main-DFqqDiy-.js.map +0 -1
  149. package/dist/main.js.map +0 -1
  150. package/dist/networking/xmpp/getHistory.xmpp.d.ts +0 -3
  151. package/dist/networking/xmpp/listenerManager.d.ts +0 -17
  152. package/dist/utils/xmppMemoryMonitor.d.ts +0 -16
package/README.md CHANGED
@@ -53,6 +53,7 @@ The package exports:
53
53
  - `useInAppNotifications`
54
54
  - `usePushNotifications`
55
55
  - `resendMessage`
56
+ - `useRoomMute`
56
57
 
57
58
  ## Why Ethora
58
59
 
@@ -333,7 +334,6 @@ Below is a grouped reference for all `config` options.
333
334
  | `customAppToken` | `string` | Custom app token for API initialization. |
334
335
  | `xmppSettings` | `{ devServer; host; conference?; xmppPingOnSendEnabled? }` | XMPP connectivity settings. |
335
336
  | `initBeforeLoad` | `boolean` | Initialize XMPP before normal chat load flow. |
336
- | `clearStoreBeforeInit` | `boolean` | Clear local store before initialization. |
337
337
  | `newArch` | `boolean` | Defaults to `true`; set `false` to explicitly force legacy/old architecture paths. |
338
338
  | `useStoreConsoleEnabled` | `boolean` | Enable verbose internal logging in console. |
339
339
 
@@ -343,28 +343,30 @@ Below is a grouped reference for all `config` options.
343
343
  | --- | --- | --- |
344
344
  | `disableHeader` | `boolean` | Hide chat header. |
345
345
  | `disableMedia` | `boolean` | Disable media sending/processing paths. |
346
+ | `attachments` | `{ maxFiles?; maxFileSizeMb?; accept? }` | Composer attachment limits. `maxFiles` defaults to `5` (hard cap `10`, the stanza payload size); `maxFileSizeMb` adds a client-side per-file check (omit for none); `accept` is passed straight to the file picker. Picking several files sends them as **one** message. |
347
+ | `pdfPreview` | `{ enabled?; workerSrc?; maxFileSizeMb? }` | First-page PDF thumbnails inside bubbles and in the composer tray. On by default; `enabled: false` keeps the static document card. pdf.js is code-split and only fetched when a PDF actually shows up. By default it runs on the main thread, which needs no bundler asset wiring: set `workerSrc` to a pdf.js worker URL you host to move parsing off it. `maxFileSizeMb` (default `25`) is the size past which a document is not auto-rendered. |
346
348
  | `disableRooms` | `boolean` | Hide/disable room list area. |
347
349
  | `disableRoomMenu` | `boolean` | Disable room menu controls. |
348
- | `disableRoomConfig` | `boolean` | Disable room configuration actions. |
350
+ | `disableRoomMute` | `boolean` | Hide the "Mute/Unmute notifications" toggle from the chat header menu and room profile, even on a backend that supports it. |
351
+ | `disableRoomConfig` | `boolean` | Hide every control that mutates a room's configuration, leaving the chat-details panel read-only: room avatar upload/remove, the "Delete chat" menu entry, the add-members action, and the per-member moderator menu (appoint as admin / remove member). |
349
352
  | `disableNewChatButton` | `boolean` | Hide new chat/create room action. |
350
- | `disableUserCount` | `boolean` | Hide user count in header/UI. |
353
+ | `disableUserCount` | `boolean` | Hide the member-count subtitle in the chat header ("N users", plus the online-users popover attached to it). The 1:1 online/offline line is a presence state, not a count, so it stays. |
351
354
  | `disableChatInfo` | `{ disableHeader?; disableDescription?; disableType?; disableMembers?; hideMembers?; disableChatHeaderMenu? }` | Fine-grained chat info panel toggles. |
352
355
  | `chatHeaderBurgerMenu` | `boolean` | Toggle burger menu in chat header. |
353
356
  | `chatHeaderSettings` | `{ hide?; disableCreate?; disableMenu?; hideSearch? }` | Additional header-level controls. |
354
357
  | `chatHeaderAdditional` | `{ enabled: boolean; element: any }` | Inject custom element into header area. |
355
- | `headerLogo` | `string \| React.ReactElement` | Custom logo in header. |
356
- | `headerMenu` | `() => void` | Custom menu handler. |
357
- | `headerChatMenu` | `() => void` | Custom room header menu handler. |
358
+ | `headerLogo` | `string \| React.ReactElement` | Host logo rendered at the left of the chat header, before the back button / burger menu. A plain string is treated as an image URL and rendered as a 32px-tall `<img>` (aspect preserved); any other React element renders as-is. Same string-or-node duality as `fallbackScreens`. |
359
+ | `headerMenu` | `() => void` | Takes over the room-list burger menu. When set, the built-in Profile/Settings/Logout dropdown is not rendered: the same burger button calls your handler instead, so you can open your own account menu or drawer. |
360
+ | `headerChatMenu` | `() => void` | Same for the chat header's room menu (the "more" button carrying Report and Leave). When set, that dropdown is not rendered and the button calls your handler. |
358
361
  | `colors` | `{ primary; secondary; icons?; ownMessageBackground?; otherMessageBackground?; inputBackground? }` | Theme colours. `primary` drives icon colours and the sender name. `icons` themes every accent icon/icon-button (attach, mic, active send, new-chat, header, empty-state) — defaults to `primary`, so set a *distinct* value to decouple. `ownMessageBackground`/`otherMessageBackground`/`inputBackground` recolour the message bubbles and input bar. |
359
362
  | `backgroundChat` | `{ color?; image? }` | Background colour and/or image for the messages area. (`image` as a string URL; pass an object URL for a `File`.) |
360
363
  | `typography` | `TypographyConfig` | Font family + size for the chat UI: `fontFamily` (or just `googleFontsFamily`) is applied across all chat text incl. messages and sender names; `fontSize` (px) scales message text, sender names, timestamps, inputs, room names and badges. Plus loaders (`googleFontsUrl`/`fontFaces`) and weight tokens. |
361
- | `fallbackScreens` | `{ noUser?; noConnection?; noRoom? }` | Replace the built-in screens (Ethora login form, "Connecting...", empty room state) with your own text or React nodes. A plain string is rendered as centered text. |
364
+ | `fallbackScreens` | `{ noUser?; noConnection?; noRoom?; error? }` | Replace the built-in screens (Ethora login form, "Connecting...", empty room state, crash screen) with your own text or React nodes. A plain string is rendered as centered text. `error` also accepts a function `({ error, componentStack, scope, reset }) => ReactNode`, see [Error handling](#error-handling-and-crash-containment). |
362
365
  | `hiddenRooms` | `{ titles?: string[]; jids?: string[] }` | Hide specific rooms from the room list and unread counters (e.g. `{ titles: ['Main chat'] }` to suppress the auto-created default room). |
363
366
  | `roomListStyles` | `React.CSSProperties` | Styles for room list pane. |
364
367
  | `chatRoomStyles` | `React.CSSProperties` | Styles for chat pane. |
365
368
  | `noMessagesPlaceholder` | `React.ComponentType` | Replace empty-chat placeholder component (same render position as default placeholder). |
366
369
  | `backgroundChat` | `{ color?: string; image?: string \| File }` | Chat background customization. |
367
- | `bubleMessage` | `MessageBubble` | Bubble-level style overrides (as defined in types). |
368
370
  | `setRoomJidInPath` | `boolean` | Sync room JID to URL path. |
369
371
  | `qrUrl` | `string` | Base URL for QR deep link behavior. |
370
372
 
@@ -384,8 +386,6 @@ Below is a grouped reference for all `config` options.
384
386
  | Option | Type | Description |
385
387
  | --- | --- | --- |
386
388
  | `defaultRooms` | `ConfigRoom[]` | Seed/default rooms. |
387
- | `customRooms` | `{ rooms: PartialRoomWithMandatoryKeys[]; disableGetRooms?: boolean; singleRoom: boolean }` | Fully controlled room source. |
388
- | `forceSetRoom` | `boolean` | Force room setup path in init flow. |
389
389
  | `enableRoomsRetry` | `{ enabled: boolean; helperText: string }` | Enable retry UX when rooms fail to load. |
390
390
 
391
391
  ### Messaging and Interactions
@@ -396,10 +396,9 @@ Below is a grouped reference for all `config` options.
396
396
  | `disableProfilesInteractions` | `boolean` | Disable profile interactions from chat UI. |
397
397
  | `disableSentLogic` | `boolean` | Disable default sent-state logic when needed. |
398
398
  | `secondarySendButton` | `{ enabled: boolean; messageEdit: string; label?: React.ReactNode; buttonStyles?: React.CSSProperties; hideInputSendButton?: boolean; overwriteEnterClick?: true }` | Extra send action/button config. |
399
- | `botMessageAutoScroll` | `boolean` | Force auto-scroll behavior on bot messages. |
400
399
  | `messageTextFilter` | `{ enabled: boolean; filterFunction: (text: string) => string }` | Transform/filter outgoing message text. |
401
- | `eventHandlers` | `{ onMessageSent?; onMessageFailed?; onMessageEdited? }` | Lifecycle callbacks for message operations. |
402
- | `translates` | `{ enabled: boolean; translations?: Iso639_1Codes }` | Message translation-related options. |
400
+ | `eventHandlers` | `{ onMessageSent?; onMessageFailed?; onMessageEdited?; onError? }` | Lifecycle callbacks for message operations, plus `onError` for uncaught render errors caught by the SDK's error boundary, see [Error handling](#error-handling-and-crash-containment). |
401
+ | `translates` | `{ enabled: boolean; translations?: Iso639_1Codes; mode?: 'auto' \| 'manual'; forceType?: boolean; readerLocale?: string; showLanguageSelector?: boolean; showLanguageList?: boolean; onTranslate?: (text, ctx) => Promise<string>; showTranslateForMessage?: (message) => boolean; endpoint?: string }` | Message translation-related options. In manual mode, an on-demand translate click shows exactly what `mode: 'auto'` would have shown automatically - the same `message.translations` lookup, no network call - unless `onTranslate` is provided, in which case it wins and may do its own HTTP. The built-in translate-service fetch is strictly opt-in: it only runs when the host sets `endpoint` explicitly (there is no default derived from `config.baseUrl`), and the result is cached onto the message so a second click, or switching to 'auto', sees it for free. The call is made directly from the browser, so `endpoint` must respond with `Access-Control-Allow-Origin` for that origin (a self-hosted translate service needs its `CORS_ORIGIN` env var set) or the fetch is blocked with no error shown beyond the retry link; if you can't set that on the endpoint, use `onTranslate` and proxy the call through your own backend instead. When there is genuinely nothing to reveal (no attached translation, no `onTranslate`, no `endpoint`), no "Translate" link is shown at all. |
403
402
  | `whitelistSystemMessage` | `string[]` | Restrict/render only selected system message types. |
404
403
  | `customSystemMessage` | `React.ComponentType<MessageProps>` | Replace system message component renderer. |
405
404
 
@@ -431,6 +430,62 @@ Below is a grouped reference for all `config` options.
431
430
  | `pushNotifications.softAsk` | `boolean` | Do not immediately trigger browser permission prompt. |
432
431
  | `pushNotifications.onClick` | `(params) => void \| Promise<void>` | Callback invoked when the user clicks an OS push notification (including cold start via URL marker). |
433
432
 
433
+ ### Error handling and crash containment
434
+
435
+ The SDK renders inside your application's React tree. Without a boundary, one
436
+ uncaught render error inside the chat would propagate to your root and unmount
437
+ your whole app, so `@ethora/chat-component` ships an error boundary of its own:
438
+
439
+ - one boundary wraps everything `<Chat>` renders (it sits inside `<Chat>`'s
440
+ redux provider, above the persist gate and the whole chat tree);
441
+ - a second one wraps the video/audio call overlay, which `<XmppProvider>`
442
+ renders as a sibling of your children so it can ring while the user is on
443
+ another page. A crash there disappears quietly instead of leaving a dead
444
+ panel over your UI, and is still logged and reported.
445
+
446
+ The error is never swallowed: it is always written to the console together
447
+ with React's component stack, regardless of `useStoreConsoleEnabled`.
448
+
449
+ | Option | Type | Description |
450
+ | --- | --- | --- |
451
+ | `fallbackScreens.error` | `React.ReactNode \| ((ctx) => React.ReactNode)` | Replaces the built-in crash screen. A plain string renders as centered text, a React node renders as-is, a function receives `{ error, componentStack, scope, reset }`. |
452
+ | `eventHandlers.onError` | `(event: ChatErrorInfo) => void` | Called with `{ error, componentStack, scope }` when the boundary catches a crash. Wire it to your crash reporter. A throw inside your handler is caught and logged, never rethrown. |
453
+
454
+ `scope` is `'chat'` for the chat tree and `'call-overlay'` for the call
455
+ overlay. The built-in screen is themed from your `colors` / `typography` and
456
+ translated through the same `config.i18n` locale as the rest of the UI, and it
457
+ offers a "try again" button that clears the error and re-mounts the chat, since
458
+ most of these failures are transient state problems.
459
+
460
+ ```tsx
461
+ <Chat
462
+ config={{
463
+ eventHandlers: {
464
+ onError: ({ error, componentStack, scope }) =>
465
+ Sentry.captureException(error, { extra: { componentStack, scope } }),
466
+ },
467
+ fallbackScreens: {
468
+ // Simplest form: replace it with your own text.
469
+ // error: 'Chat is temporarily unavailable',
470
+
471
+ // Or take full control, including your own retry action:
472
+ error: ({ error, reset }) => (
473
+ <MyErrorPanel message={error.message} onRetry={reset} />
474
+ ),
475
+ },
476
+ }}
477
+ />
478
+ ```
479
+
480
+ A string or node fallback is only used for the chat pane: for a crashed call
481
+ overlay the SDK renders nothing, and only the function form (which can inspect
482
+ `scope`) is consulted.
483
+
484
+ The call overlay is rendered by `<XmppProvider>`, so pass the same config
485
+ object to the provider as to `<Chat>` (which the [single XMPP initialization
486
+ contract](#single-xmpp-initialization-contract) already recommends) if you want
487
+ `'call-overlay'` crashes to reach your `onError` too.
488
+
434
489
  ## Custom Widgets and Overrides
435
490
 
436
491
  You can replace key UI parts without forking the package.
@@ -606,13 +661,14 @@ function PushPermissionButton() {
606
661
  | --- | --- | --- |
607
662
  | `Chat` | React component | Main chat component. |
608
663
  | `XmppProvider` | React provider | Provides XMPP client context for internal hooks/state. |
609
- | `useUnread` | hook | Returns unread counters (`totalCount`, per-room maps) plus a `loading` flag that stays `true` until the room list has loaded at least once. |
664
+ | `useUnread` | hook | Returns unread counters (`totalCount`, per-room maps) plus a `loading` flag that stays `true` until the room list has loaded at least once. `totalCount`/`hasUnread` exclude any room the caller has muted - a muted room still reports its own count in `unreadByRoom`/`displayByRoom`, it just doesn't inflate the aggregate. |
610
665
  | `logoutService` | service | Programmatic logout utility. |
611
666
  | `useQRCodeChat` | hook | Handle QR-based room links. |
612
667
  | `handleQRChatId` | function | Parse/process QR chat ID from URL. |
613
668
  | `useInAppNotifications` | hook | Enables and handles in-app notifications. |
614
669
  | `usePushNotifications` | hook | Push subscription + foreground handling workflow. |
615
670
  | `resendMessage` | function | Retry sending failed/pending messages. |
671
+ | `useRoomMute` | hook | `useRoomMute(roomJid)` returns `{ muted, isSupported, isPending, toggleMute, setMuted }` for a room's mute preference - optimistic with rollback on failure. `isSupported` is only `true` once the backend has reported a `muted` boolean for that room (it hasn't shipped to prod yet), so hosts building their own UI should hide a mute control until then. |
616
672
 
617
673
  Basic hook usage:
618
674
 
@@ -680,7 +736,7 @@ This is a practical planning snapshot for cross-platform consumers. It is not a
680
736
  | Issue | Likely cause | Fix |
681
737
  | --- | --- | --- |
682
738
  | `useXmppClient must be used within an XmppProvider` | Using internal XMPP-dependent logic without provider context | Wrap the app tree with `XmppProvider` where needed. |
683
- | Chat loads but no rooms appear | Auth/app context mismatch or room fetching restrictions | Verify `appId`, user credentials/tokens, `baseUrl`, and `customRooms` settings. |
739
+ | Chat loads but no rooms appear | Auth/app context mismatch or room fetching restrictions | Verify `appId`, user credentials/tokens, `baseUrl`, and `defaultRooms` settings. |
684
740
  | Push permission never appears | `softAsk: true` without manual trigger, insecure origin, or missing VAPID key | Trigger `requestPermission()`, use HTTPS/localhost, set valid VAPID key. |
685
741
  | Service worker not found | `firebase-messaging-sw.js` missing in public dir | Run `npx @ethora/chat-component ethora-chat` or copy file manually. |
686
742
  | Login loop / auth failure | Wrong token/user object shape | Validate `jwtLogin`, `userLogin.user`, and refresh token flow. |
@@ -780,4 +836,4 @@ from `src/test/testIds.ts` here.
780
836
 
781
837
  ## License
782
838
 
783
- AGPL. See [LICENSE.txt](./LICENSE.txt).
839
+ MIT. See [LICENSE](./LICENSE).