@ethora/chat-component 26.10.6 → 26.10.8

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 (94) hide show
  1. package/README.md +102 -3
  2. package/dist/ChatProfileModal-83t5BRkI.js +2298 -0
  3. package/dist/{FilePreviewModal-DwNUEHei.js → FilePreviewModal-DxUGjSHe.js} +135 -135
  4. package/dist/{ManageDataModal-CaQ2VBPn.js → ManageDataModal-DFE_Wegj.js} +24 -24
  5. package/dist/{MarkdownBody-BeoG2cpo.js → MarkdownBody-uFITrPjT.js} +1 -1
  6. package/dist/{MessageSearchModal-DMw9o49-.js → MessageSearchModal-CsbTWgNm.js} +46 -46
  7. package/dist/{PublicChatsModal-CWdYILv_.js → PublicChatsModal-bDOp3IL9.js} +18 -18
  8. package/dist/{SideDrawer-Cl-vbuIG.js → SideDrawer-A_1ECqD2.js} +29 -29
  9. package/dist/UserProfileModal-Ca5wHYvr.js +639 -0
  10. package/dist/{UserSettingsModal-DgCAHmNh.js → UserSettingsModal-CAyyQGV6.js} +4 -4
  11. package/dist/{VideoCallOverlay-Cq2cECWj.js → VideoCallOverlay-BMiQh8kI.js} +6605 -4726
  12. package/dist/{VisibilityModal-D7vqGbrA.js → VisibilityModal-BXyIy7_J.js} +12 -12
  13. package/dist/assets/icons.d.ts +4 -0
  14. package/dist/calls/callDisplay.d.ts +22 -0
  15. package/dist/calls/callMode.d.ts +105 -0
  16. package/dist/calls/openScheduledCall.d.ts +20 -0
  17. package/dist/calls/p2p/P2PCallController.d.ts +160 -0
  18. package/dist/calls/p2p/icePolicy.d.ts +36 -0
  19. package/dist/calls/p2p/negotiator.d.ts +56 -0
  20. package/dist/calls/p2p/p2pRuntime.d.ts +35 -0
  21. package/dist/calls/p2p/signalInbox.d.ts +34 -0
  22. package/dist/calls/p2p/signalStanza.d.ts +51 -0
  23. package/dist/calls/placeCall.d.ts +20 -0
  24. package/dist/calls/scheduledCall.d.ts +101 -0
  25. package/dist/calls/scheduledCallActions.d.ts +12 -0
  26. package/dist/calls/scheduledCallFormat.d.ts +13 -0
  27. package/dist/calls/scheduledCallsConfig.d.ts +27 -0
  28. package/dist/calls/senderTrust.d.ts +7 -0
  29. package/dist/calls/startCall.d.ts +16 -0
  30. package/dist/components/MainComponents/ChatWrapper.d.ts +1 -0
  31. package/dist/components/MainComponents/LoginWrapper.d.ts +1 -0
  32. package/dist/components/MainComponents/ProfileImagePlaceholder.d.ts +1 -0
  33. package/dist/components/MainComponents/ReduxWrapper.d.ts +6 -0
  34. package/dist/components/MenuRoom/MenuRoom.d.ts +1 -0
  35. package/dist/components/Modals/NewChatModal/styledNewChatComponents.d.ts +27 -0
  36. package/dist/components/Modals/styledModalComponents.d.ts +25 -4
  37. package/dist/components/ScheduledCalls/ScheduleCallModal.d.ts +3 -0
  38. package/dist/components/ScheduledCalls/ScheduledCallCancelConfirm.d.ts +8 -0
  39. package/dist/components/ScheduledCalls/ScheduledCallCard.d.ts +7 -0
  40. package/dist/components/ScheduledCalls/ScheduledCallLayer.d.ts +15 -0
  41. package/dist/components/ScheduledCalls/ScheduledCallPreJoin.d.ts +3 -0
  42. package/dist/components/VideoCalls/P2PCallRunner.d.ts +1 -0
  43. package/dist/components/VideoCalls/P2PCallSession.d.ts +14 -0
  44. package/dist/components/VideoCalls/VideoCallSession.d.ts +39 -0
  45. package/dist/firebase-messaging-sw.js +918 -96
  46. package/dist/{handleCopyClick-Crn2jEEu.js → handleCopyClick-BX1fcFGN.js} +1 -1
  47. package/dist/helpers/callClaim.d.ts +17 -0
  48. package/dist/helpers/callOutcomeSync.d.ts +23 -0
  49. package/dist/helpers/callPush.d.ts +25 -0
  50. package/dist/helpers/canLeaveRoom.d.ts +3 -0
  51. package/dist/helpers/chatComponentConfigEvents.d.ts +16 -0
  52. package/dist/helpers/incomingCallPush.d.ts +89 -0
  53. package/dist/helpers/liveConfig.d.ts +46 -0
  54. package/dist/helpers/pushRoomHandoff.d.ts +13 -0
  55. package/dist/helpers/reportRoom.d.ts +18 -0
  56. package/dist/helpers/scheduledCallMessage.d.ts +23 -0
  57. package/dist/helpers/storeConsole.d.ts +1 -0
  58. package/dist/hooks/useChatSettingState.d.ts +1 -0
  59. package/dist/hooks/useNow.d.ts +6 -0
  60. package/dist/hooks/usePushNotifications.d.ts +2 -0
  61. package/dist/hooks/useRemoteAppearance.d.ts +21 -0
  62. package/dist/hooks/useTypography.d.ts +4 -0
  63. package/dist/{main-36gqdbJ8.js → main-B25iFKAC.js} +16623 -13399
  64. package/dist/main.d.ts +3 -1
  65. package/dist/main.js +25 -23
  66. package/dist/networking/api-requests/callState.api.d.ts +24 -0
  67. package/dist/networking/api-requests/remoteAppearance.api.d.ts +20 -0
  68. package/dist/networking/api-requests/rooms.api.d.ts +11 -1
  69. package/dist/networking/api-requests/scheduledCalls.api.d.ts +19 -0
  70. package/dist/networking/ethoraEvents.d.ts +14 -1
  71. package/dist/networking/xmpp/notifyXmppEvent.d.ts +6 -0
  72. package/dist/networking/xmpp/sendMessageReaction.xmpp.d.ts +13 -1
  73. package/dist/networking/xmppClient.d.ts +2 -1
  74. package/dist/roomStore/Middleware/blockedHydrationMiddleware.d.ts +2 -0
  75. package/dist/roomStore/callSlice.d.ts +23 -1
  76. package/dist/roomStore/chatSettingsSlice.d.ts +11 -2
  77. package/dist/roomStore/index.d.ts +4 -0
  78. package/dist/roomStore/scheduledCallSlice.d.ts +47 -0
  79. package/dist/types/models/config.model.d.ts +78 -1
  80. package/dist/types/models/message.model.d.ts +2 -0
  81. package/dist/types/models/room.model.d.ts +2 -0
  82. package/dist/types/models/scheduledCall.model.d.ts +116 -0
  83. package/dist/types/models/xmpp.model.d.ts +2 -1
  84. package/dist/utils/callAuthMirror.d.ts +1 -0
  85. package/dist/utils/callBroadcast.d.ts +12 -0
  86. package/dist/utils/callNotifications.d.ts +67 -0
  87. package/dist/utils/firebasePushNotifications.d.ts +14 -0
  88. package/dist/utils/handledCalls.d.ts +5 -0
  89. package/dist/utils/pushServiceWorkerBridge.d.ts +19 -0
  90. package/dist/utils/webLock.d.ts +13 -0
  91. package/package.json +1 -1
  92. package/public/firebase-messaging-sw.js +918 -96
  93. package/dist/ChatProfileModal-OJCKwdNp.js +0 -2168
  94. package/dist/UserProfileModal-B8KtGnwZ.js +0 -594
@@ -1,4 +1,4 @@
1
- import { E as e, G as t } from "./main-36gqdbJ8.js";
1
+ import { a4 as e, a6 as t } from "./main-B25iFKAC.js";
2
2
  const i = e.div`
3
3
  display: flex;
4
4
  flex-direction: column;
@@ -0,0 +1,17 @@
1
+ /** Records that this tab took the decision for the call (see wonCallDecision). */
2
+ export declare const rememberCallDecision: (key: string | null | undefined) => void;
3
+ /** True when this tab took the accept or decline for `key` itself. */
4
+ export declare const wonCallDecision: (key: string | null | undefined) => boolean;
5
+ export declare const resetCallClaims: () => void;
6
+ /**
7
+ * Takes the per-call claim for accepting or declining `key`. A plain boolean
8
+ * without Web Locks (nothing to yield for), otherwise a promise. Both actions
9
+ * share the one lock, so an Accept here and a Decline in another tab cannot
10
+ * both go through either.
11
+ */
12
+ export declare const claimCallDecision: (key: string) => boolean | Promise<boolean>;
13
+ /**
14
+ * Runs `run` when this tab gets the claim, and not at all when another tab
15
+ * has it. Synchronous when the claim is (no Web Locks).
16
+ */
17
+ export declare const runIfCallClaimed: (key: string | null | undefined, run: () => void) => void;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Marks the end of the ring `key` as local-only: the next time this tab's ring
3
+ * for it ends, nothing is broadcast. For a timeout, and for an end that came
4
+ * from another tab (no echo).
5
+ */
6
+ export declare const silenceCallOutcome: (key: string | null | undefined) => void;
7
+ type CallLike = {
8
+ direction: string | null;
9
+ phase: string;
10
+ callId: string | null;
11
+ roomJid: string | null;
12
+ roomBareName: string | null;
13
+ };
14
+ export declare const incomingCallKey: (call: CallLike) => string | null;
15
+ interface StoreLike {
16
+ getState: () => {
17
+ call: CallLike;
18
+ };
19
+ subscribe: (listener: () => void) => () => void;
20
+ dispatch: (action: any) => unknown;
21
+ }
22
+ export declare function startCallOutcomeSync(store: StoreLike): () => void;
23
+ export {};
@@ -11,6 +11,8 @@ export interface ParsedCallPush {
11
11
  callerName: string | null;
12
12
  /** Caller's xmpp localpart, when provided. */
13
13
  callerXmppUsername: string | null;
14
+ /** The call is for a group room (always LiveKit). */
15
+ isGroup: boolean;
14
16
  }
15
17
  /**
16
18
  * True when a push `data` payload represents an incoming call. Matches on an
@@ -20,3 +22,26 @@ export interface ParsedCallPush {
20
22
  */
21
23
  export declare const isCallPush: (data: Record<string, any> | null | undefined) => boolean;
22
24
  export declare const parseCallPush: (data: Record<string, any> | null | undefined) => ParsedCallPush;
25
+ /**
26
+ * Decode the claims of a JWT without verifying it. Only non-sensitive claims
27
+ * are ever read from the result; the server (and LiveKit on connect) is the
28
+ * authority on validity. Returns null for anything that is not a JWT.
29
+ */
30
+ export declare const decodeJwtPayload: (token: string | null | undefined) => Record<string, any> | null;
31
+ /** Expiry of a JWT (`exp`, seconds) as epoch milliseconds, or null. */
32
+ export declare const jwtExpiresAtMs: (token: string | null | undefined) => number | null;
33
+ /** A call token with less than this left is treated as already expired. */
34
+ export declare const CALL_TOKEN_MIN_REMAINING_MS = 3000;
35
+ /**
36
+ * Whether a call push is still worth ringing for. The backend sets no push TTL,
37
+ * so a device that was offline can receive a call push long after the call.
38
+ * The LiveKit token lives 60 s, so its `exp` is the freshness clock.
39
+ *
40
+ * When no `exp` can be read (no token, malformed token) the push is treated
41
+ * as fresh: it cannot be proven stale, and the ring's own 45 s timeout bounds
42
+ * how long it can stay on screen.
43
+ */
44
+ export declare const getCallPushFreshness: (data: Record<string, any> | null | undefined, now?: number) => {
45
+ fresh: boolean;
46
+ expiresAt: number | null;
47
+ };
@@ -0,0 +1,3 @@
1
+ import { ConfigRoom } from '../types/models/room.model';
2
+ /** Ordinary rooms are leaveable; configured app rooms require an explicit opt-in. */
3
+ export declare const canLeaveRoom: (jid: string | undefined, defaultRooms: ConfigRoom[] | undefined) => boolean;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * In-process bus for the `chat-component-config-updated` server event, so the
3
+ * XMPP stanza handler (networking/ethoraEvents.ts) and whoever acts on it
4
+ * (`config.remoteAppearance`, see hooks/useRemoteAppearance.ts) do not import
5
+ * each other.
6
+ */
7
+ export interface ChatComponentConfigUpdatedEvent {
8
+ appId: string;
9
+ /** Opaque state id from the server, pass it to the config endpoint as `v`. */
10
+ version: string;
11
+ }
12
+ type Listener = (event: ChatComponentConfigUpdatedEvent) => void;
13
+ export declare const subscribeChatComponentConfigUpdated: (listener: Listener) => (() => void);
14
+ export declare const publishChatComponentConfigUpdated: (event: ChatComponentConfigUpdatedEvent) => void;
15
+ export declare const resetChatComponentConfigListeners: () => void;
16
+ export {};
@@ -0,0 +1,89 @@
1
+ export interface CallPushContext {
2
+ dispatch: (action: any) => unknown;
3
+ getState: () => any;
4
+ normalizeRoomJid: (jid?: string) => string;
5
+ }
6
+ export type CallPushOutcome =
7
+ /** The ring is on (or already was) for this call. */
8
+ 'ringing'
9
+ /** Ringing and accepted in the same step (Answer action). */
10
+ | 'accepted'
11
+ /** This call is already answered / in progress; nothing to do. */
12
+ | 'active'
13
+ /** Another call is in progress; this one was ignored. */
14
+ | 'busy'
15
+ /** The push is stale; nothing rings. */
16
+ | 'expired'
17
+ /** Another tab already accepted, declined or ended this call; nothing to do. */
18
+ | 'handled'
19
+ /** Held until the chat config and the user are ready. */
20
+ | 'held'
21
+ /** The push carries no LiveKit token, so it cannot ring. */
22
+ | 'no-token';
23
+ export declare const markCallRaisedFromPush: (key: string | null | undefined) => void;
24
+ export declare const unmarkCallRaisedFromPush: (key: string | null | undefined) => void;
25
+ export declare const wasCallRaisedFromPush: (key: string | null | undefined) => boolean;
26
+ interface PendingCallPush {
27
+ data: Record<string, any>;
28
+ answer: boolean;
29
+ heldAt: number;
30
+ /** The worker is showing this call's notification (see raisedFromPush). */
31
+ swShows: boolean;
32
+ }
33
+ export declare const holdCallPush: (data: Record<string, any>, answer: boolean, swShows?: boolean) => void;
34
+ export declare const takePendingCallPush: (now?: number) => PendingCallPush | null;
35
+ export declare const dropPendingCallPush: (callId: string | null | undefined) => void;
36
+ export declare const resetCallPushState: () => void;
37
+ /**
38
+ * Everything the call push flow holds that belongs to the session: a call push
39
+ * held for the config, the pushed-ring marks, the decline dedupe, the click the
40
+ * worker keeps for the next page load, and the call notifications on screen.
41
+ * Logout (and an account switch) clears it, so the next user never replays or
42
+ * answers the previous one's call.
43
+ */
44
+ export declare const clearCallPushSession: (scope?: string) => Promise<void>;
45
+ /**
46
+ * Several tabs get the same tap or Answer from the worker. Only one may act on
47
+ * it: the first to take the lock for this call does, the rest leave it. This
48
+ * only routes the click. Whether THIS tab may then accept or decline the call
49
+ * is the per-call claim in callClaim (shared with the ring screen's buttons).
50
+ */
51
+ export declare const claimCallAction: (action: "click", key: string) => boolean | Promise<boolean>;
52
+ /**
53
+ * Puts the ring up from a call push (through the guarded reducer) and, for the
54
+ * Answer action, accepts it right away so LiveKit connects with the push's own
55
+ * token and no second click.
56
+ */
57
+ export declare const raiseIncomingCallFromPush: (ctx: CallPushContext, data: Record<string, any>, options?: {
58
+ answer?: boolean;
59
+ swShows?: boolean;
60
+ }) => CallPushOutcome;
61
+ export declare const flushPendingCallPush: (ctx: CallPushContext) => CallPushOutcome | null;
62
+ /**
63
+ * CALL_PUSH from the worker: ring (or hold) and tell the worker what this page
64
+ * did, so it knows whether to add an OS notification:
65
+ * - ring shown and this page visible: ack, the worker shows nothing;
66
+ * - this call is already connecting or in progress here: ack whether the page
67
+ * is visible or not (a duplicate push must not ring again, nor end as a
68
+ * "Missed call" for a call that was answered);
69
+ * - a DIFFERENT call is in progress: ack with `busy`, the worker shows a plain
70
+ * "Missed call" instead of a ring that Answer could not take;
71
+ * - anything else (hidden page, held, expired, no token): no ack, the worker
72
+ * notifies. The hidden or held ring is then the worker's to announce, so it
73
+ * is marked and the page does not notify a second time.
74
+ */
75
+ export declare const handleCallPushFromWorker: (ctx: CallPushContext, data: Record<string, any>) => CallPushOutcome;
76
+ /**
77
+ * Declines a call from a notification action. Both mounted hook instances get
78
+ * the worker's message, so a repeat for the same call is dropped. A call this
79
+ * page has already answered is left alone: a stale Decline must never hang up
80
+ * a live call.
81
+ *
82
+ * Tells the worker (CALL_PUSH_DECLINE_ACK) once the decline was actually
83
+ * handled, and only then: the worker waits for it and otherwise declines over
84
+ * REST itself. A page that cannot do the XMPP part (the chat config is not in
85
+ * Redux yet) still has the user token, so it does the REST decline and acks
86
+ * when the server took it.
87
+ */
88
+ export declare const declineIncomingCallFromPush: (ctx: CallPushContext, data: Record<string, any>) => Promise<void>;
89
+ export {};
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Which `config` keys the chat applies LIVE, and how an operator-saved record
3
+ * is laid over the host's config.
4
+ *
5
+ * Live means: changing the key on a mounted chat re-renders the affected
6
+ * pieces from the store and the CSS variables, with the XMPP connection, the
7
+ * rooms, the messages and every draft left alone. The list is exactly the
8
+ * visual and layout switches; everything else (identity, endpoints, login,
9
+ * history, e2ee, receipts, ...) is read when the chat starts and a new value
10
+ * is picked up by the next mount.
11
+ *
12
+ * The keys below also form the allowlist for `config.remoteAppearance`: a
13
+ * record fetched from the server can set these keys and no others, each with
14
+ * a strict validator, because the record comes over the network and ends up
15
+ * in CSS variables and a stylesheet.
16
+ */
17
+ type Parse = (value: unknown) => string | boolean | number | null;
18
+ /** Live keys and their validators. Mirrors ethora-backend modules/apps/chatComponentConfig.js. */
19
+ export declare const LIVE_CONFIG_KEYS: Readonly<Record<string, Parse>>;
20
+ export declare const isLiveConfigPath: (path: string) => boolean;
21
+ /** Flattens to dotted leaf paths. Functions, nodes and class instances are leaves compared by identity. */
22
+ export declare const flattenConfig: (input: unknown, out?: Map<string, unknown>, prefix?: string, depth?: number) => Map<string, unknown>;
23
+ export interface ConfigChange {
24
+ /** Changed paths the chat applies live. */
25
+ live: string[];
26
+ /** Changed paths read when the chat starts: applied by the next mount. */
27
+ restart: string[];
28
+ }
29
+ /**
30
+ * Splits what differs between two host configs into live and start-time
31
+ * paths. A function that is a new closure on every render counts as changed
32
+ * (it is compared by identity) and lands in `restart`; that only affects the
33
+ * log line, the chat applies the whole new config either way.
34
+ */
35
+ export declare function classifyConfigChange(prev: unknown, next: unknown): ConfigChange;
36
+ export type RemoteConfigRecord = Record<string, string | boolean | number>;
37
+ /**
38
+ * Keeps only allowlisted keys with a valid value. Anything else (an unknown
39
+ * key, a wrong type, markup, a URL, an out of range number) is dropped, so a
40
+ * wrong or hostile answer cannot do more than restyle the chat within the
41
+ * validators' limits.
42
+ */
43
+ export declare function parseRemoteConfigRecord(raw: unknown): RemoteConfigRecord;
44
+ /** The config with the record laid over it, copying only the objects on the way. Siblings stay. */
45
+ export declare function applyRemoteConfigRecord<T extends object | undefined>(base: T, record: RemoteConfigRecord | null | undefined): T;
46
+ export {};
@@ -0,0 +1,13 @@
1
+ /**
2
+ * A push tap names the room the user wants. The address bar and the parked
3
+ * QR / deep-link id may still name another one: a host that redirects `/` to
4
+ * its saved last path lands the window on `/chat?chatId=<last room>`, and
5
+ * `useQRCodeChat` re-asserts that room for as long as it is parked, which
6
+ * used to undo the push a moment after it was applied.
7
+ *
8
+ * Call this right before opening the pushed room so every source of truth
9
+ * agrees: a `chatId` already in the url is rewritten to the pushed room (the
10
+ * way `useRoomUrl` writes it, without adding a history entry), and a parked
11
+ * id is dropped. A url with no `chatId` is left alone.
12
+ */
13
+ export declare const claimRoomForPush: (roomJid: string) => void;
@@ -0,0 +1,18 @@
1
+ import { PostReportRoom } from '../types/models/room.model';
2
+ export interface ReportCategory {
3
+ id: string;
4
+ labelKey: string;
5
+ apiCategory: string;
6
+ /** English name, used in `text` (the report e-mail is not localized). */
7
+ name: string;
8
+ }
9
+ export declare const REPORT_CATEGORIES: ReportCategory[];
10
+ export declare const OTHER_REPORT_CATEGORY: ReportCategory;
11
+ export declare const findReportCategory: (id: string) => ReportCategory | undefined;
12
+ /**
13
+ * The request body for a room report. `roomJid` may be the full room JID or
14
+ * the bare room name: the route takes the bare name (JID localpart), like
15
+ * every other /v1/chats/... route. Returns null for an unknown category or
16
+ * an empty room.
17
+ */
18
+ export declare const buildReportRoomPayload: (roomJid: string, categoryId: string, details?: string) => PostReportRoom | null;
@@ -0,0 +1,23 @@
1
+ import { IMessage } from '../types/types';
2
+ import { ScheduledCallMeta } from '../types/models/scheduledCall.model';
3
+ export declare const SCHEDULED_CALL_MESSAGE_TYPE = "scheduledCall";
4
+ /**
5
+ * Reads the scheduled-call fields off a message. Null when the message is not
6
+ * one, or when it lacks what a card cannot do without (a valid slug and a
7
+ * parseable start); such a message falls back to its plain body.
8
+ *
9
+ * `apiBaseUrl` is the API the chat talks to, used to vet the .ics link.
10
+ */
11
+ export declare const parseScheduledCallMeta: (message: unknown, apiBaseUrl?: string | null) => ScheduledCallMeta | null;
12
+ /**
13
+ * createMessageFromXml hook: attaches `scheduledCall` meta to a message that
14
+ * is one. Everything else comes back untouched (same object).
15
+ */
16
+ export declare const attachScheduledCallMeta: (message: IMessage, apiBaseUrl?: string | null) => IMessage;
17
+ /**
18
+ * One card per slug: of all messages that announce the same scheduled call
19
+ * only the newest stays, so an `updated` or `cancelled` message replaces the
20
+ * card instead of stacking under it. Order of everything else is kept, and the
21
+ * input is returned as is when no call is announced twice.
22
+ */
23
+ export declare const collapseScheduledCallMessages: (messages: IMessage[]) => IMessage[];
@@ -3,4 +3,5 @@ export declare const useStoreConsole: () => {
3
3
  rooms: Record<string, any> & import('redux-persist/es/persistReducer').PersistPartial;
4
4
  roomHeapSlice: import('../roomStore/roomHeapSlice').roomHeapSliceState;
5
5
  call: import('immer').WritableDraft<import('../roomStore/callSlice').CallState>;
6
+ scheduledCall: import('immer').WritableDraft<import('../roomStore/scheduledCallSlice').ScheduledCallState>;
6
7
  };
@@ -8,4 +8,5 @@ export declare const useChatSettingState: () => {
8
8
  langSource: any;
9
9
  translateSendEnabled: any;
10
10
  translateMode: any;
11
+ blockedUserIds: any;
11
12
  };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * `Date.now()` that re-renders its component every `intervalMs` while
3
+ * `enabled`. For things that change with the clock (a Join button that opens
4
+ * 15 minutes before the start) without each caller owning a timer.
5
+ */
6
+ export declare const useNow: (intervalMs: number, enabled?: boolean) => number;
@@ -28,6 +28,8 @@ interface UsePushNotificationsOptions {
28
28
  iconPath?: string;
29
29
  /** Custom badge URL/path for browser OS notifications. */
30
30
  badgePath?: string;
31
+ /** Same-origin path a cold-start push tap opens (default: the origin root). */
32
+ clickPath?: string;
31
33
  /**
32
34
  * Custom Firebase configuration object.
33
35
  * If provided, it overrides the environment variables.
@@ -0,0 +1,21 @@
1
+ import { IConfig } from '../types/types';
2
+ import { RemoteConfigRecord } from '../helpers/liveConfig';
3
+ export declare const DEFAULT_REMOTE_APPEARANCE_WAIT_MS = 2500;
4
+ export interface RemoteAppearanceState {
5
+ /** The record to lay over the host config; null until the first read settles. */
6
+ record: RemoteConfigRecord | null;
7
+ /** True while the chat should hold its first paint for the first read. */
8
+ waiting: boolean;
9
+ }
10
+ /**
11
+ * `config.remoteAppearance`: reads the App's chat component config from the
12
+ * server and keeps it current. Reads once on mount (the chat waits for it, at
13
+ * most `initialWaitMs`, so it starts once with its final look), then again
14
+ * every time the server announces a new version with a
15
+ * `chat-component-config-updated` event. The newest read wins, a failed read
16
+ * keeps what is shown, and a version that is already shown is not fetched
17
+ * again.
18
+ *
19
+ * Does nothing (and never waits) when the host did not opt in.
20
+ */
21
+ export declare function useRemoteAppearance(config?: IConfig): RemoteAppearanceState;
@@ -4,5 +4,9 @@ import { TypographyConfig } from '../types/models/config.model';
4
4
  * Wired into the chat root (ReduxWrapper) so the font is in place before the
5
5
  * UI paints. No-op when `typography` is undefined - the default system font
6
6
  * stack is kept, so existing integrations are unaffected.
7
+ *
8
+ * When `typography` goes away on a mounted chat (the operator cleared the
9
+ * font in the admin tab), what this hook applied is removed again and the
10
+ * default stack is back, with no reload.
7
11
  */
8
12
  export declare function useTypography(typography?: TypographyConfig): void;