@ethora/chat-component 26.8.2 → 26.9.2

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 (27) hide show
  1. package/README.md +1 -0
  2. package/dist/{ChatProfileModal-DJcii-VO.js → ChatProfileModal-DJu41Pd7.js} +6 -3
  3. package/dist/{FilePreviewModal-CZtgkIHl.js → FilePreviewModal-C9LtTRwf.js} +63 -63
  4. package/dist/{ManageDataModal-aOWxvxSs.js → ManageDataModal-W7YjmIsd.js} +3 -3
  5. package/dist/{MarkdownBody-neDkIgJl.js → MarkdownBody-k4RvO7v6.js} +3 -3
  6. package/dist/{SideDrawer-mSCnYOgy.js → SideDrawer-DTXPBfJl.js} +25 -25
  7. package/dist/{UserProfileModal-a_O8hh1O.js → UserProfileModal-CyUJ-rFm.js} +3 -3
  8. package/dist/{UserSettingsModal-92nP1add.js → UserSettingsModal-DJYdx8X3.js} +9 -9
  9. package/dist/{VideoCallOverlay-DYd3pFuD.js → VideoCallOverlay-C7flkkQ5.js} +2673 -2662
  10. package/dist/VisibilityModal-Dq_1oMwl.js +138 -0
  11. package/dist/components/MainComponents/SealedAttachmentList.d.ts +14 -0
  12. package/dist/components/RoomComponents/styled/LastMessageSealed.d.ts +14 -0
  13. package/dist/components/RoomComponents/styled/StyledRoomComponents.d.ts +4 -2
  14. package/dist/components/styled/AudioMessage.d.ts +38 -0
  15. package/dist/e2ee/fileEnvelope.d.ts +48 -0
  16. package/dist/{handleCopyClick-tizCFAb8.js → handleCopyClick-Cv8OCQA-.js} +2 -2
  17. package/dist/helpers/sealedAttachments.d.ts +25 -0
  18. package/dist/{main-DkokKp7d.js → main-DaxJ3rMp.js} +9701 -8964
  19. package/dist/main.js +5 -5
  20. package/dist/networking/api-requests/auth.api.d.ts +10 -1
  21. package/dist/networking/xmpp/sendMediaMessage.xmpp.d.ts +12 -1
  22. package/dist/styles/tokens.d.ts +26 -4
  23. package/dist/types/models/config.model.d.ts +19 -0
  24. package/dist/types/models/message.model.d.ts +17 -0
  25. package/dist/version.d.ts +1 -1
  26. package/package.json +1 -1
  27. package/dist/VisibilityModal-BKI5XKir.js +0 -132
package/dist/main.js CHANGED
@@ -1,4 +1,4 @@
1
- import { b3 as a, b4 as r, b5 as b, b6 as o, b7 as t, b8 as i, b9 as p, ba as u, bb as h, bc as n, bd as d, be as l, bf as f, J as m, bg as T, bh as g, bi as y, bj as I, bk as R, bl as c, bm as C, bn as k, bo as A, ai as E, aj as Q, bp as F, bq as M } from "./main-DkokKp7d.js";
1
+ import { b5 as a, b6 as r, b7 as b, b8 as o, b9 as t, ba as i, bb as p, bc as u, bd as h, be as n, bf as l, bg as d, bh as f, L as m, bi as T, bj as g, bk as y, bl as I, bm as R, bn as c, bo as k, bp as C, bq as A, ak as E, al as Q, br as F, bs as M } from "./main-DaxJ3rMp.js";
2
2
  export {
3
3
  a as AuthTestIds,
4
4
  r as Chat,
@@ -10,8 +10,8 @@ export {
10
10
  u as applyTypography,
11
11
  h as clearTypography,
12
12
  n as formatFingerprint,
13
- d as handleQRChatId,
14
- l as isE2eeEnabled,
13
+ l as handleQRChatId,
14
+ d as isE2eeEnabled,
15
15
  f as isRefreshFatalError,
16
16
  m as logoutService,
17
17
  T as omemo,
@@ -20,8 +20,8 @@ export {
20
20
  I as refreshAuthTokensQuietly,
21
21
  R as resendMessage,
22
22
  c as useInAppNotifications,
23
- C as useIsUserOnline,
24
- k as usePushNotifications,
23
+ k as useIsUserOnline,
24
+ C as usePushNotifications,
25
25
  A as useQRCodeChat,
26
26
  E as useRoomMute,
27
27
  Q as useRoomPresence,
@@ -19,5 +19,14 @@ export declare const signInWithGoogle: () => Promise<{
19
19
  idToken: string;
20
20
  credential: import('firebase/auth').OAuthCredential;
21
21
  }>;
22
- export declare function uploadFile(formData: FormData, activeRoomJID: string): Promise<import('axios').AxiosResponse<any, any, {}>>;
22
+ export interface UploadFileOptions {
23
+ /**
24
+ * The payload is ciphertext the caller sealed (e2ee rooms). Tells the
25
+ * backend to store it verbatim: no thumbnail, no duration/page probe, and
26
+ * `mimetype` recorded as declared rather than inferred. Set on the form
27
+ * BEFORE the secure/legacy split so both routes carry it.
28
+ */
29
+ clientEncrypted?: boolean;
30
+ }
31
+ export declare function uploadFile(formData: FormData, activeRoomJID: string, options?: UploadFileOptions): Promise<import('axios').AxiosResponse<any, any, {}>>;
23
32
  export declare function ensureUserFromMy(user: User | null | undefined): Promise<User | null>;
@@ -1,2 +1,13 @@
1
1
  import { Client } from '@xmpp/client';
2
- export declare function sendMediaMessage(client: Client, roomJID: string, data: any, id: string): void;
2
+ /**
3
+ * What <body> carries in an e2ee room: the key material for each sealed
4
+ * attachment, in the same order as `attachments` / the flat fields on <data>.
5
+ * The real mimetype and filename are not here - they are inside each sealed
6
+ * payload (see e2ee/fileEnvelope.ts), so they survive exactly as long as the
7
+ * bytes do and cannot be stripped off in transit.
8
+ */
9
+ export interface E2eeMediaBody {
10
+ v: 1;
11
+ keys: string[];
12
+ }
13
+ export declare function sendMediaMessage(client: Client, roomJID: string, data: any, id: string): Promise<void>;
@@ -1,15 +1,19 @@
1
1
  import { CSSProperties } from 'react';
2
- import { IConfig, TypographyConfig } from '../types/types';
2
+ import { ChatColorScheme, IConfig, TypographyConfig } from '../types/types';
3
3
  /** Mix `hex` toward white by `amount` (0-1). Used for soft tints. */
4
4
  export declare const tintColor: (hex: string, amount: number) => string;
5
5
  /** Mix `hex` toward black by `amount` (0-1). Used for hover/pressed shades. */
6
6
  export declare const shadeColor: (hex: string, amount: number) => string;
7
+ /** Mix `a` toward `b` by `amount` (0-1). Used for dark-scheme tints. */
8
+ export declare const mixColor: (a: string, b: string, amount: number) => string;
9
+ /** The scheme actually rendered: `'system'` resolved against the OS. */
10
+ export type ResolvedColorScheme = 'light' | 'dark';
7
11
  export type ThemeTokenMap = Record<string, string>;
8
12
  /**
9
13
  * Build the full `--ethora-*` CSS variable map from the host's config.
10
14
  * Pure function - safe to call outside the browser (SSR, tests).
11
15
  */
12
- export declare function buildThemeTokens(colors?: IConfig['colors'], typography?: TypographyConfig): ThemeTokenMap;
16
+ export declare function buildThemeTokens(colors?: IConfig['colors'], typography?: TypographyConfig, scheme?: ResolvedColorScheme): ThemeTokenMap;
13
17
  /**
14
18
  * The class the chat's root element carries; useful for scoping global CSS.
15
19
  * Re-exported from `styles/classNames`, which owns every class name this
@@ -21,7 +25,25 @@ export { CHAT_ROOT_CLASS } from './classNames';
21
25
  * the chat root element's inline `style` so the variables are scoped to the
22
26
  * chat subtree wherever the root can carry them.
23
27
  */
24
- export declare function useThemeTokenStyle(colors?: IConfig['colors'], typography?: TypographyConfig): CSSProperties;
28
+ export declare function useThemeTokenStyle(colors?: IConfig['colors'], typography?: TypographyConfig, scheme?: ResolvedColorScheme): CSSProperties;
25
29
  export declare function ThemeTokens({ config, }: {
26
- config?: Pick<IConfig, 'colors' | 'typography'>;
30
+ config?: Pick<IConfig, 'colors' | 'typography' | 'colorScheme'>;
27
31
  }): null;
32
+ /**
33
+ * The config the HOST passed as a prop, published so the inner roots can
34
+ * theme themselves from it on the very first frame.
35
+ *
36
+ * The store copy of the config only exists after ConfigEnabler has
37
+ * dispatched it, which is a render later. Until then a component reading
38
+ * the store sees the slice default - light - and paints light tokens over
39
+ * the dark ones it inherits, which is the white flash a dark-mode chat
40
+ * showed while it started up.
41
+ */
42
+ export declare const HostConfigContext: import('react').Context<Pick<IConfig, "colorScheme" | "colors" | "typography">>;
43
+ export declare const useHostConfig: () => Pick<IConfig, "colorScheme" | "colors" | "typography">;
44
+ /**
45
+ * Resolve `config.colorScheme` to the scheme to render. `'system'` tracks the
46
+ * OS setting live; anything else (including unset) is taken as given, with
47
+ * `'light'` as the default so existing integrations are unchanged.
48
+ */
49
+ export declare function useResolvedColorScheme(scheme?: ChatColorScheme): ResolvedColorScheme;
@@ -133,6 +133,7 @@ export interface ChatErrorInfo {
133
133
  export type ChatErrorFallbackRenderer = (context: ChatErrorInfo & {
134
134
  reset: () => void;
135
135
  }) => React.ReactNode;
136
+ export type ChatColorScheme = 'light' | 'dark' | 'system';
136
137
  export interface IConfig {
137
138
  appId?: string;
138
139
  /**
@@ -176,6 +177,24 @@ export interface IConfig {
176
177
  /** Documents above this are not auto-rendered. Default 25. */
177
178
  maxFileSizeMb?: number;
178
179
  };
180
+ /**
181
+ * Light or dark UI. `'system'` follows the viewer's OS / browser setting
182
+ * (`prefers-color-scheme`) and updates live when it changes.
183
+ *
184
+ * Defaults to `'light'`, which is exactly the chat as it looked before
185
+ * this option existed. Surfaces, text, borders and bubbles switch to a
186
+ * dark palette; `colors.icons`, `colors.iconsBg`, the bubble/input
187
+ * colours and `backgroundChat` are used as given in both schemes.
188
+ * `colors.primary` is the exception: in dark it is lightened slightly so
189
+ * primary-coloured text and icons stay legible on the dark surface while
190
+ * buttons keep white text on them (see `--ethora-color-primary-text` for
191
+ * the text-only variant). Pass an already-dark-suitable `primary` if the
192
+ * exact brand value matters more. The
193
+ * scheme is scoped to the chat's own elements - the host page is not
194
+ * touched, so a host with its own dark mode should pass its resolved
195
+ * choice here.
196
+ */
197
+ colorScheme?: ChatColorScheme;
179
198
  colors?: {
180
199
  primary: string;
181
200
  secondary: string;
@@ -29,6 +29,23 @@ export interface IMessage {
29
29
  * mistakes the room's badge for a guarantee about this message.
30
30
  */
31
31
  unencrypted?: boolean;
32
+ /**
33
+ * Attachments on this message are sealed; `clientEncrypted` is set on the
34
+ * stanza and these open them, one key per attachment, in attachment order.
35
+ *
36
+ * Lifted by getDataFromXml out of the OMEMO-decrypted <body>, which is the
37
+ * only part of a media stanza that is encrypted - so an undecryptable
38
+ * message has the ciphertext URLs and no keys, and stays unopenable.
39
+ */
40
+ e2eeKeys?: string[];
41
+ /**
42
+ * Set by the sender when this message's attachments are sealed. Stamped on
43
+ * <data>, which rides in the clear, so it survives a body that could not be
44
+ * decrypted - which is exactly when a renderer most needs to know the bytes
45
+ * are ciphertext rather than a corrupt file. A string, because it comes off
46
+ * an XML attribute.
47
+ */
48
+ clientEncrypted?: string;
32
49
  timestamp?: number;
33
50
  showInChannel?: string;
34
51
  activeMessage?: boolean;
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.7.4";
1
+ export declare const ETHORA_CHAT_COMPONENT_VERSION = "26.9.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethora/chat-component",
3
- "version": "26.8.2",
3
+ "version": "26.9.2",
4
4
  "type": "module",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
@@ -1,132 +0,0 @@
1
- import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
- import { useState as b, useEffect as x } from "react";
3
- import { v as o, a as L, n as P, u as z, aE as D, aF as I } from "./main-DkokKp7d.js";
4
- import { S as N, D as C, a as w, b as O, e as S, f as p } from "./SideDrawer-mSCnYOgy.js";
5
- o.div``;
6
- o.div`
7
- font-size: 16px;
8
- font-weight: bold;
9
- color: var(--ethora-color-text, #141414);
10
- `;
11
- o.p`
12
- font-size: 14px;
13
- color: var(--ethora-color-text-muted, #6b7280);
14
- margin-bottom: 32px;
15
- `;
16
- const $ = o.div`
17
- display: flex;
18
- flex-direction: column;
19
- gap: 6px;
20
- `, h = o.label`
21
- display: flex;
22
- align-items: center;
23
- font-size: 14px;
24
- gap: 8px;
25
- `, f = o.input`
26
- accent-color: ${({ $radioColor: t }) => t || "var(--ethora-color-primary, #0052CD)"};
27
- margin: 0px;
28
- `, R = o.div`
29
- padding: 10px 15px;
30
- margin-top: 16px;
31
- color: ${({ type: t }) => t === "success" ? "#10b981" : "#ef4444"};
32
- background: ${({ type: t }) => t === "success" ? "#d1fae5" : "#fee2e2"};
33
- border: 1px solid
34
- ${({ type: t }) => t === "success" ? "#10b981" : "#ef4444"};
35
- border-radius: 4px;
36
- `, M = ({
37
- handleCloseModal: t
38
- }) => {
39
- const k = L(), i = P(), { user: c, config: l } = z(
40
- (s) => s.chatSettingStore
41
- ), y = (s) => k(I(s)), [n, m] = b(c?.isProfileOpen), [a, g] = b(c?.isAssetsOpen), [u, v] = b(null), d = (s, A) => {
42
- v({ message: s, type: A }), setTimeout(() => v(null), 3e3);
43
- };
44
- return x(() => {
45
- n !== c.isProfileOpen && D({ isProfileOpen: n }).then(({ data: s }) => {
46
- y(s.user), d(i("notification.saved"), "success");
47
- }).catch(() => d(i("toast.error"), "error"));
48
- }, [n]), x(() => {
49
- a !== c?.isAssetsOpen && D({ isAssetsOpen: a }).then(({ data: s }) => {
50
- y(s.user), d(i("notification.saved"), "success");
51
- }).catch(() => d(i("toast.error"), "error"));
52
- }, [a]), /* @__PURE__ */ r(
53
- N,
54
- {
55
- title: i("settings.visibility.title"),
56
- onClose: t,
57
- backLabel: i("action.back"),
58
- children: [
59
- /* @__PURE__ */ r(C, { children: [
60
- /* @__PURE__ */ e(w, { children: i("settings.visibility.profileLabel") }),
61
- /* @__PURE__ */ e(O, { children: /* @__PURE__ */ e(S, { children: /* @__PURE__ */ r($, { children: [
62
- /* @__PURE__ */ r(h, { children: [
63
- /* @__PURE__ */ e(
64
- f,
65
- {
66
- $radioColor: l?.colors?.primary,
67
- type: "radio",
68
- name: "ethora-profile-visibility",
69
- checked: n === !0,
70
- onChange: () => m(!0)
71
- }
72
- ),
73
- i("settings.visibility.open")
74
- ] }),
75
- /* @__PURE__ */ e(p, { children: i("settings.visibility.openDescription") }),
76
- /* @__PURE__ */ r(h, { children: [
77
- /* @__PURE__ */ e(
78
- f,
79
- {
80
- $radioColor: l?.colors?.primary,
81
- type: "radio",
82
- name: "ethora-profile-visibility",
83
- checked: n === !1,
84
- onChange: () => m(!1)
85
- }
86
- ),
87
- i("settings.visibility.restricted")
88
- ] }),
89
- /* @__PURE__ */ e(p, { children: i("settings.visibility.restrictedDescription") })
90
- ] }) }) })
91
- ] }),
92
- /* @__PURE__ */ r(C, { children: [
93
- /* @__PURE__ */ e(w, { children: i("settings.visibility.documentsLabel") }),
94
- /* @__PURE__ */ e(O, { children: /* @__PURE__ */ e(S, { children: /* @__PURE__ */ r($, { children: [
95
- /* @__PURE__ */ r(h, { children: [
96
- /* @__PURE__ */ e(
97
- f,
98
- {
99
- $radioColor: l?.colors?.primary,
100
- type: "radio",
101
- name: "ethora-documents-visibility",
102
- checked: a === !0,
103
- onChange: () => g(!0)
104
- }
105
- ),
106
- i("settings.visibility.full")
107
- ] }),
108
- /* @__PURE__ */ e(p, { children: i("settings.visibility.fullDescription") }),
109
- /* @__PURE__ */ r(h, { children: [
110
- /* @__PURE__ */ e(
111
- f,
112
- {
113
- $radioColor: l?.colors?.primary,
114
- type: "radio",
115
- name: "ethora-documents-visibility",
116
- checked: a === !1,
117
- onChange: () => g(!1)
118
- }
119
- ),
120
- i("settings.visibility.individual")
121
- ] }),
122
- /* @__PURE__ */ e(p, { children: i("settings.visibility.individualDescription") })
123
- ] }) }) })
124
- ] }),
125
- u && /* @__PURE__ */ e(R, { type: u.type, children: u.message })
126
- ]
127
- }
128
- );
129
- };
130
- export {
131
- M as default
132
- };