@ethora/chat-component 26.10.5 → 26.10.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.
Files changed (43) hide show
  1. package/README.md +32 -1
  2. package/dist/{ChatProfileModal-Dw7pPDv8.js → ChatProfileModal-BDZvd0rm.js} +145 -145
  3. package/dist/{FilePreviewModal-CEcb5HZ2.js → FilePreviewModal-DlOjnYzv.js} +79 -79
  4. package/dist/{ManageDataModal-Qma0dQja.js → ManageDataModal-BZLGJZze.js} +16 -16
  5. package/dist/{MarkdownBody-DiVdEIJH.js → MarkdownBody-CtArwCDa.js} +1 -1
  6. package/dist/{MessageSearchModal-DVJTW9WM.js → MessageSearchModal-CcUnfZlU.js} +46 -46
  7. package/dist/{PublicChatsModal-CX1qZbEc.js → PublicChatsModal-BWn0NXVo.js} +10 -10
  8. package/dist/{SideDrawer-BzfNGNbq.js → SideDrawer-CqZl9sxK.js} +28 -28
  9. package/dist/UserProfileModal-D0JZ3-uy.js +635 -0
  10. package/dist/{UserSettingsModal-DdbURRR3.js → UserSettingsModal-OvykYDsT.js} +4 -4
  11. package/dist/{VideoCallOverlay-D1lGzbw3.js → VideoCallOverlay-DrvO2v_g.js} +4616 -4477
  12. package/dist/{VisibilityModal-yGZ0eOJx.js → VisibilityModal-pOF9-UXR.js} +11 -11
  13. package/dist/components/Modals/styledModalComponents.d.ts +4 -4
  14. package/dist/components/VideoCalls/VideoCallSession.d.ts +2 -0
  15. package/dist/components/styled/SendInput.d.ts +3 -2
  16. package/dist/firebase-messaging-sw.js +918 -96
  17. package/dist/{handleCopyClick-C-w304_U.js → handleCopyClick-BUbVvd2G.js} +1 -1
  18. package/dist/helpers/callClaim.d.ts +17 -0
  19. package/dist/helpers/callOutcomeSync.d.ts +23 -0
  20. package/dist/helpers/callPush.d.ts +23 -0
  21. package/dist/helpers/incomingCallPush.d.ts +89 -0
  22. package/dist/helpers/pushRoomHandoff.d.ts +13 -0
  23. package/dist/hooks/useChatSettingState.d.ts +1 -0
  24. package/dist/hooks/usePushNotifications.d.ts +2 -0
  25. package/dist/{main-Cdwk7Rjj.js → main-CpHMnydn.js} +12241 -11463
  26. package/dist/main.js +17 -17
  27. package/dist/networking/api-requests/rooms.api.d.ts +9 -0
  28. package/dist/networking/xmpp/sendMessageReaction.xmpp.d.ts +13 -1
  29. package/dist/networking/xmppClient.d.ts +2 -1
  30. package/dist/roomStore/Middleware/blockedHydrationMiddleware.d.ts +2 -0
  31. package/dist/roomStore/chatSettingsSlice.d.ts +2 -1
  32. package/dist/types/models/config.model.d.ts +42 -0
  33. package/dist/types/models/xmpp.model.d.ts +2 -1
  34. package/dist/utils/callAuthMirror.d.ts +1 -0
  35. package/dist/utils/callBroadcast.d.ts +12 -0
  36. package/dist/utils/callNotifications.d.ts +67 -0
  37. package/dist/utils/firebasePushNotifications.d.ts +14 -0
  38. package/dist/utils/handledCalls.d.ts +5 -0
  39. package/dist/utils/pushServiceWorkerBridge.d.ts +19 -0
  40. package/dist/utils/webLock.d.ts +13 -0
  41. package/package.json +1 -1
  42. package/public/firebase-messaging-sw.js +918 -96
  43. package/dist/UserProfileModal-DdW_nEsM.js +0 -594
package/README.md CHANGED
@@ -363,7 +363,7 @@ Below is a grouped reference for all `config` options.
363
363
  | --- | --- | --- |
364
364
  | `disableHeader` | `boolean` | Hide chat header. |
365
365
  | `disableMedia` | `boolean` | Disable media sending/processing paths. |
366
- | `attachments` | `{ maxFiles?; maxFileSizeMb?; accept? }` | Composer attachment limits. `maxFiles` defaults to `10` (also the hard cap, set by 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. |
366
+ | `attachments` | `{ maxFiles?; maxFileSizeMb?; accept?; captionMode? }` | Composer attachment limits. `maxFiles` defaults to `10` (also the hard cap, set by 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. `captionMode` (`'inline' \| 'separate'`, default `'separate'`) sets where the text typed with the files goes: `'separate'` sends the media message without the caption and then the text as a normal text message once the media send settles (also in e2ee rooms); `'inline'` puts the caption on the media message (`<data caption>`, `captionMentions`). See Backend compatibility. |
367
367
  | `pdfPreview` | `{ enabled?; workerSrc?; libUrl?; 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. Set `libUrl` to the URL of a pdf.js ES module build to load it at runtime instead of the copy bundled with the component (pair it with `workerSrc`); useful when you ship the component as one self-contained script and do not want pdf.js (about 1.7 MB) inside it. `maxFileSizeMb` (default `25`) is the size past which a document is not auto-rendered. |
368
368
  | `disableRooms` | `boolean` | Hide/disable room list area. |
369
369
  | `disableRoomMenu` | `boolean` | Disable room menu controls. |
@@ -450,9 +450,27 @@ Below is a grouped reference for all `config` options.
450
450
  | `pushNotifications.serviceWorkerScope` | `string` | Service worker scope, default `/`. |
451
451
  | `pushNotifications.iconPath` | `string` | Custom icon URL/path for OS push notifications. |
452
452
  | `pushNotifications.badgePath` | `string` | Custom badge URL/path for OS push notifications. Falls back to `iconPath`. |
453
+ | `pushNotifications.clickPath` | `string` | Same-origin path a push tap opens when no window is open yet (for example `/app/chat`). The tapped room and message are appended as `fromPush=1&chatId=...&messageId=...` (ids only). Defaults to the origin root. |
453
454
  | `pushNotifications.softAsk` | `boolean` | Do not immediately trigger browser permission prompt. |
454
455
  | `pushNotifications.onClick` | `(params) => void \| Promise<void>` | Callback invoked when the user clicks an OS push notification (including cold start via URL marker). |
455
456
 
457
+ ### Backend compatibility
458
+
459
+ Some features call routes that not every backend deployment serves yet. Each
460
+ switch below keeps that client code off until your backend has the route. The
461
+ defaults are the safe choice for a backend that has not been updated.
462
+
463
+ | Option | Default | Why |
464
+ | --- | --- | --- |
465
+ | `features.userBlock` | `false` | `/v1/chats/blocked` is not served by the production backend yet (404), so the "Block user" item would always fail. Set `true` once your backend serves it. |
466
+ | `attachments.captionMode` | `'separate'` | The caption goes out as its own text message after the media (the 26.9.8 wire shape), which older web builds, React Native and server push all show. `'inline'` puts it on the media message as `<data caption>`, which those readers do not render yet. |
467
+ | `uploads.endpoint` | `'auto'` | `'auto'` tries `/v2/files/secure` and falls back to `/v1/files/`. Secure-files URLs can be unreadable on a backend that is not updated, so `'legacy'` posts straight to `/v1/files/`. `'secure'` never falls back. |
468
+
469
+ | Option | Type | Description |
470
+ | --- | --- | --- |
471
+ | `features` | `{ userBlock?: boolean }` | Opt-in backend features. `userBlock` (default `false`) shows the "Block user" item in 1-1 chat menus and enables the `/v1/chats/blocked` calls. `disableUserBlock: true` still hides the item. |
472
+ | `uploads` | `{ endpoint?: 'auto' \| 'secure' \| 'legacy' }` | Attachment upload route. `'auto'` (default) tries `POST /v2/files/secure` and falls back to `POST /v1/files/` when the backend rejects it. `'legacy'` always uses `/v1/files/` (no `chatName`); `'secure'` uses the secure route and never falls back. |
473
+
456
474
  ### Error handling and crash containment
457
475
 
458
476
  The SDK renders inside your application's React tree. Without a boundary, one
@@ -645,6 +663,19 @@ The badge has no per-push override: it is `pushNotifications.badgePath`, then th
645
663
 
646
664
  Clicking a push opens `<origin>/chat?chatId=<room>&messageId=<message>` (or the `url` carried by the push) and calls `pushNotifications.onClick`; see the deep link section above.
647
665
 
666
+ #### Incoming call pushes (web)
667
+
668
+ With `videoCalls.enabled: true` and push enabled, a data-only call push (`type: "call"`, `callId`, `callToken`, `room`, `kind`, `callerName`, `callerXmppUsername`) rings the same way as on mobile:
669
+
670
+ - The worker asks every open window to ring (`CALL_PUSH`). A visible page that shows the ring answers (`CALL_PUSH_ACK`) and nothing else is shown. With no ack within 1.5 s (no window, a hidden tab, a dead socket) the worker shows a sticky notification "Incoming video call" with **Answer** and **Decline** actions, tag `call:<callId>` (`call:room:<room>` when the push has no `callId`). A page that already has that call connecting or in progress acks it, hidden or not, so a duplicate push never rings again; a page busy with a different call acks it as busy and the worker shows a plain "Missed call" instead of a ring. A push without `callToken` cannot be answered: it shows Decline only, and a tap opens the room. A tap or Answer with no window opens `pushNotifications.clickPath` (the page that mounts the chat); the call itself travels in the pending click, never in the url.
671
+ - The push has no TTL, so freshness is read from the `exp` of `callToken`. With less than 3 s left nothing rings and a plain "Missed video call" notification (tag `missed-call:<room>`, tap opens the room) is shown instead. A token with no readable `exp` is treated as fresh. A ring the worker shows is never sticky for longer than 60 s (the backend's TTL for a call): at `exp`, or 60 s after the push when `exp` is unreadable or further away, it is replaced by the "Missed call" notification. A page that times a ring out in a hidden tab shows the same "Missed call" notification itself (same tag, shown once), so the result does not depend on whether the page or the worker gets there first.
672
+ - Answer focuses or opens the app, raises the call and accepts it at once, so LiveKit connects with the push token (the browser may ask for microphone or camera). Tapping the notification body shows the ring screen. The click goes to every open window that announced it takes calls (the page has the call push listener mounted with `videoCalls.enabled`; `CALL_CLIENT_READY`), and the one that took it answers `CALL_PUSH_ANSWER_ACK` and is focused; a host page with no `<Chat>` is never picked just because it was focused last. With no ready window the worker does not wait: it keeps the click as the pending click and focuses and navigates an open tab to `pushNotifications.clickPath` (or opens it), and the new page accepts the call. The same happens when a ready window does not ack within 1.5 s, except that a refused `openWindow` (the click's user activation is short-lived) leaves the pending click for the next page load (2 min). The focus and the no-ready fallback run while the click is fresh; only the ack wait can outlast it, which is why a tab that was ready but silent is never the one navigated.
673
+ - Decline goes to every open window the same way. The page that takes it (XMPP `call-state` plus `POST /v1/chats/call/state/decline/:callId`) answers `CALL_PUSH_DECLINE_ACK`; if no ack comes within 1.5 s (a host page with no `<Chat>`, the config not loaded yet) the worker declines over REST itself. With no page open the worker calls that endpoint directly, using the user token the page mirrors into Cache Storage (the token the SDK already keeps in this origin's localStorage; deleted on logout). Without that token Decline only closes the notification and the caller times out.
674
+ - Several tabs of one origin can ring for the same call. Accepting or declining takes one per-call claim (a Web Lock), whether it comes from the notification's Answer and Decline or from the Accept and Decline buttons on the ring screen, so two tabs never both accept. A tab that does not get the claim does nothing. The tab that accepts, declines or sees the caller cancel broadcasts the outcome to the other tabs of the origin (on a `BroadcastChannel` named `ethora-call` and, for tabs without `BroadcastChannel`, as a `localStorage` write picked up by the `storage` event; a tab acts on whichever arrives first), and a tab still ringing for that call ends its ring quietly: no "Missed call", nothing sent to the caller, its notification closed. A ring that merely runs out is each tab's own. The outcome is also remembered for about 2 minutes (call keys and timestamps only, in `localStorage`), so a late push, a stale Answer or Decline, or a replay of the call token never raises, accepts or hangs up a call another tab already handled. A call with no `callId` is keyed by its room and is not remembered. Without Web Locks the tabs behave as before, and only the remembered outcome protects against a second accept.
675
+ - Set `pushNotifications.clickPath` to the route where `<Chat>` is mounted (for example `/chat`), even though it is optional. It decides where Answer, a tap or a refused `openWindow` goes when no window that can take calls is open. It defaults to the origin root, which in most apps is a landing page or a login screen that does not mount `<Chat>`: the worker then opens a page that never hears the call push listener, so Answer lands on that page, nothing accepts, the pending click waits for the next page load (2 min) and the call is lost for the user. With `clickPath` pointing at the chat route, the new page mounts the chat, picks up the pending click and accepts the call. The same applies to a tab that is open on a page without `<Chat>`: it is not offered the click, the worker navigates it to `clickPath` instead.
676
+ - A ring a page shows through the service worker registration (a hidden tab with a live socket) is persistent, so the page tells the worker (`CALL_RING_SHOWN`, with the call's `exp` and no token) and the worker ends it like a ring of its own, even if the tab is closed in the meantime. A "Missed call" shown by the page and by the worker at the same moment is shown once (both check and show under one Web Lock).
677
+ - The call notification is closed whenever the ring ends (answered, declined, cancelled, timed out). A push that arrives before the chat config and the user are in Redux is held until they are, or until its token expires. On logout (or a switch to another account) the held call, the tap the worker keeps for the next page load and every call notification on screen are cleared.
678
+
648
679
  ## Auth Strategies
649
680
 
650
681
  | Strategy | Config shape | Best for |