@ethora/chat-component 26.7.9 → 26.8.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 (38) hide show
  1. package/dist/{ChatProfileModal-D4B6nVkl.js → ChatProfileModal-DJcii-VO.js} +3 -3
  2. package/dist/{FilePreviewModal-DxXBzYVJ.js → FilePreviewModal-CZtgkIHl.js} +37 -37
  3. package/dist/{ManageDataModal-P_5uJrLo.js → ManageDataModal-aOWxvxSs.js} +2 -2
  4. package/dist/{MarkdownBody-DJuU5j5G.js → MarkdownBody-neDkIgJl.js} +1 -1
  5. package/dist/{SideDrawer-CT108Ag1.js → SideDrawer-mSCnYOgy.js} +11 -11
  6. package/dist/UserProfileModal-a_O8hh1O.js +594 -0
  7. package/dist/{UserSettingsModal-CjkqSAhD.js → UserSettingsModal-92nP1add.js} +2 -2
  8. package/dist/{VideoCallOverlay-D2u_n0s-.js → VideoCallOverlay-DYd3pFuD.js} +1 -1
  9. package/dist/{VisibilityModal-BsbvHoF6.js → VisibilityModal-BKI5XKir.js} +2 -2
  10. package/dist/assets/icons.d.ts +8 -0
  11. package/dist/components/MainComponents/AttachmentList.d.ts +5 -0
  12. package/dist/components/styled/MessageImage.d.ts +10 -0
  13. package/dist/e2ee/crypto.d.ts +32 -0
  14. package/dist/e2ee/index.d.ts +53 -0
  15. package/dist/e2ee/omemo.d.ts +130 -0
  16. package/dist/e2ee/protobuf.d.ts +25 -0
  17. package/dist/e2ee/ratchet.d.ts +54 -0
  18. package/dist/e2ee/stanza.d.ts +24 -0
  19. package/dist/e2ee/store.d.ts +12 -0
  20. package/dist/{handleCopyClick-CdTri-Fg.js → handleCopyClick-tizCFAb8.js} +1 -1
  21. package/dist/helpers/findMessagesForFile.d.ts +25 -0
  22. package/dist/helpers/xmppIdShape.d.ts +9 -0
  23. package/dist/helpers/xmppUsername.d.ts +1 -1
  24. package/dist/hooks/useChatWrapperInit.d.ts +5 -1
  25. package/dist/{main-BNdWGLpK.js → main-DkokKp7d.js} +19736 -16252
  26. package/dist/main.d.ts +2 -0
  27. package/dist/main.js +23 -20
  28. package/dist/networking/api-requests/rooms.api.d.ts +6 -4
  29. package/dist/networking/authRefresh.d.ts +6 -0
  30. package/dist/networking/xmpp/sendTextMessage.xmpp.d.ts +1 -1
  31. package/dist/networking/xmpp/sendTextMessageWithTranslateTag.xmpp.d.ts +1 -1
  32. package/dist/networking/xmppClient.d.ts +39 -0
  33. package/dist/roomStore/storage.d.ts +2 -1
  34. package/dist/types/models/config.model.d.ts +14 -0
  35. package/dist/types/models/message.model.d.ts +10 -0
  36. package/dist/types/models/room.model.d.ts +10 -0
  37. package/package.json +4 -1
  38. package/dist/UserProfileModal-BTmSeeuM.js +0 -574
@@ -0,0 +1,594 @@
1
+ import { jsxs as u, Fragment as $, jsx as o } from "react/jsx-runtime";
2
+ import { forwardRef as ge, useState as I, useCallback as y, useImperativeHandle as ve, useRef as ae, useMemo as M } from "react";
3
+ import { a as be, n as J, p as ye, q as xe, t as we, P as re, I as H, v as D, w as Ce, x as Se, y as Ie, z as te, C as De, D as Ne, E as ke, F as Ue, u as Q, G as Fe, J as Pe, L as Ae, K as Re, N as Y, o as Z, O as ze, Q as je, R as Be, s as $e, B as X, S as Ee, T as Oe, U as Te, W as ee, X as R, Y as Le, Z as Me, V as He, A as Xe, _ as We, $ as Je, a0 as Ke, a1 as Ve } from "./main-DkokKp7d.js";
4
+ import { D as E, a as W, b as Ge, e as qe, f as _e, S as Qe } from "./SideDrawer-mSCnYOgy.js";
5
+ import { P as ne, a as Ye, D as Ze, b as eo, h as oo } from "./handleCopyClick-tizCFAb8.js";
6
+ const ao = (c, i) => {
7
+ const l = atob(c.split(",")[1]), g = new ArrayBuffer(l.length), e = new Uint8Array(g);
8
+ for (let r = 0; r < l.length; r++)
9
+ e[r] = l.charCodeAt(r);
10
+ const n = new Blob([e], { type: "image/jpeg" });
11
+ return new File([n], i, { type: "image/jpeg" });
12
+ }, ro = D.div`
13
+ display: flex;
14
+ flex-direction: column;
15
+ gap: var(--ethora-space-4, 16px);
16
+ width: 100%;
17
+ `, se = ge(
18
+ ({ setIsEditing: c, modalUser: i, config: l }, g) => {
19
+ const e = be(), n = J(), [r, t] = I(i?.firstName || ""), [f, U] = I(i?.lastName || ""), [b, w] = I(i?.description || ""), [v, x] = I(
20
+ i?.profileImage
21
+ ), C = y(async () => {
22
+ try {
23
+ let s = new FormData();
24
+ if (typeof v == "string" && v.startsWith("data:image/")) {
25
+ const F = ao(v, "profileImage.jpg");
26
+ s.append("file", F);
27
+ } else v instanceof File && s.append("file", v);
28
+ s.append("firstName", r), s.append("lastName", f), s.append("description", b);
29
+ const { user: N } = await ye(s);
30
+ e(
31
+ xe({
32
+ updates: {
33
+ firstName: r,
34
+ lastName: f,
35
+ description: b,
36
+ profileImage: N?.profileImage
37
+ }
38
+ })
39
+ ), c(!1);
40
+ } catch (s) {
41
+ we.log("error", s);
42
+ }
43
+ }, [
44
+ e,
45
+ b,
46
+ r,
47
+ f,
48
+ v,
49
+ c
50
+ ]);
51
+ ve(g, () => ({ save: C }), [C]);
52
+ const S = (s) => {
53
+ x(s);
54
+ };
55
+ return /* @__PURE__ */ u($, { children: [
56
+ /* @__PURE__ */ o(ne, { children: /* @__PURE__ */ o(
57
+ re,
58
+ {
59
+ icon: v,
60
+ name: `${r} ${f}`,
61
+ size: 96,
62
+ upload: {
63
+ onUpload: S,
64
+ active: !0
65
+ }
66
+ }
67
+ ) }),
68
+ /* @__PURE__ */ o(E, { children: /* @__PURE__ */ u(ro, { children: [
69
+ /* @__PURE__ */ o(
70
+ H,
71
+ {
72
+ color: l?.colors?.primary,
73
+ colorBg: l?.colors?.colorInput,
74
+ placeholder: n("field.firstName"),
75
+ label: n("field.firstName"),
76
+ value: r,
77
+ onChange: (s) => t(s.target.value)
78
+ }
79
+ ),
80
+ /* @__PURE__ */ o(
81
+ H,
82
+ {
83
+ color: l?.colors?.primary,
84
+ colorBg: l?.colors?.colorInput,
85
+ placeholder: n("field.lastName"),
86
+ label: n("field.lastName"),
87
+ value: f,
88
+ onChange: (s) => U(s.target.value)
89
+ }
90
+ ),
91
+ /* @__PURE__ */ o(
92
+ H,
93
+ {
94
+ color: l?.colors?.primary,
95
+ colorBg: l?.colors?.colorInput,
96
+ placeholder: n("modal.profile.about"),
97
+ label: n("modal.profile.about"),
98
+ value: b,
99
+ onChange: (s) => w(s.target.value)
100
+ }
101
+ )
102
+ ] }) })
103
+ ] });
104
+ }
105
+ );
106
+ se.displayName = "EditUserModal";
107
+ const to = te`
108
+ from {
109
+ transform: rotate(0deg);
110
+ }
111
+ to {
112
+ transform: rotate(180deg);
113
+ }
114
+ `, no = te`
115
+ from {
116
+ transform: rotate(180deg);
117
+ }
118
+ to {
119
+ transform: rotate(0deg);
120
+ }
121
+ `, so = D.div`
122
+ position: relative;
123
+ width: 100%;
124
+ `, io = D.div`
125
+ border: 1px solid
126
+ ${({ $borderColor: c, $isOpen: i }) => i ? c || "var(--ethora-color-primary, #0052cd)" : c || "var(--ethora-color-border, #e6e8ec)"};
127
+ padding: 0 16px;
128
+ height: 48px;
129
+ box-sizing: border-box;
130
+ display: flex;
131
+ justify-content: space-between;
132
+ align-items: center;
133
+ cursor: pointer;
134
+ background-color: var(--ethora-color-bg, #fff);
135
+ color: var(--ethora-color-text, #141414);
136
+ font-size: var(--ethora-font-size, 16px);
137
+ border-radius: var(--ethora-radius-md, 16px);
138
+ transition:
139
+ border-color var(--ethora-motion-fast, 150ms) var(--ethora-motion-ease, ease),
140
+ box-shadow var(--ethora-motion-fast, 150ms) var(--ethora-motion-ease, ease);
141
+
142
+ ${({ $isOpen: c }) => c && Se`
143
+ outline: 2px solid var(--ethora-color-primary, #0052cd);
144
+ outline-offset: 1px;
145
+ `}
146
+
147
+ &:focus-visible {
148
+ outline: 2px solid var(--ethora-color-primary, #0052cd);
149
+ outline-offset: 1px;
150
+ }
151
+ `, lo = D.span`
152
+ color: var(--ethora-color-text-muted, #8c8c8c);
153
+ `, co = D.span`
154
+ margin-left: 10px;
155
+ display: inline-block;
156
+ color: var(--ethora-color-text-muted, #8c8c8c);
157
+ font-size: 12px;
158
+ animation: ${(c) => c.$isOpen ? to : no} 0.3s ease
159
+ forwards;
160
+ `, po = D.div`
161
+ position: absolute;
162
+ top: 100%;
163
+ left: 0;
164
+ right: 0;
165
+ border: 1px solid var(--ethora-color-border, #e6e8ec);
166
+ background-color: var(--ethora-color-bg, #fff);
167
+ max-height: 200px;
168
+ overflow-y: auto;
169
+ margin-top: 4px;
170
+ border-radius: var(--ethora-radius-md, 16px);
171
+ box-shadow: var(--ethora-shadow-md, 0 4px 12px rgba(16, 24, 40, 0.1));
172
+ z-index: 100;
173
+ ${Ie}
174
+ `, mo = D.input`
175
+ width: 100%;
176
+ padding: 12px 16px;
177
+ border: none;
178
+ border-bottom: 1px solid var(--ethora-color-border, #e6e8ec);
179
+ outline: none;
180
+ box-sizing: border-box;
181
+ font-size: var(--ethora-font-size-sm, 14px);
182
+ background: transparent;
183
+ color: var(--ethora-color-text, #141414);
184
+
185
+ &::placeholder {
186
+ color: var(--ethora-color-text-muted, #8c8c8c);
187
+ }
188
+ `, oe = D.div`
189
+ padding: 12px 16px;
190
+ cursor: pointer;
191
+ font-size: var(--ethora-font-size-sm, 14px);
192
+ color: var(--ethora-color-text, #141414);
193
+ background-color: ${({ $selected: c }) => c ? "var(--ethora-color-primary-soft, #e7edf9)" : "transparent"};
194
+ transition: background-color var(--ethora-motion-fast, 150ms);
195
+
196
+ &:hover {
197
+ background-color: ${({ $selected: c }) => c ? "var(--ethora-color-primary-soft, #e7edf9)" : "var(--ethora-color-bg-hover, #f0f2f5)"};
198
+ }
199
+ `, ho = ({
200
+ options: c,
201
+ placeholder: i,
202
+ onSelect: l,
203
+ accentColor: g,
204
+ selectedValue: e
205
+ }) => {
206
+ const n = J(), [r, t] = I(!1), [f, U] = I(
207
+ e
208
+ ), [b, w] = I(""), v = ae(null), x = () => t((a) => !a), C = (a) => {
209
+ U(a), l(a), t(!1), w("");
210
+ }, S = c.filter(
211
+ (a) => a.name.toLowerCase().includes(b.toLowerCase())
212
+ ), s = y(() => t(!1), []);
213
+ Ce({
214
+ enabled: r,
215
+ onClose: s,
216
+ kind: "menu",
217
+ insideRefs: [v],
218
+ closeOnOutsidePress: !0
219
+ });
220
+ const N = (a) => {
221
+ a.key === "Enter" || a.key === " " ? (a.preventDefault(), x()) : a.key === "Escape" && r && t(!1);
222
+ }, F = (a, P) => {
223
+ (a.key === "Enter" || a.key === " ") && (a.preventDefault(), C(P));
224
+ };
225
+ return /* @__PURE__ */ u(so, { ref: v, children: [
226
+ /* @__PURE__ */ u(
227
+ io,
228
+ {
229
+ $isOpen: r,
230
+ onClick: x,
231
+ onKeyDown: N,
232
+ $borderColor: g,
233
+ role: "button",
234
+ tabIndex: 0,
235
+ "aria-haspopup": "listbox",
236
+ "aria-expanded": r,
237
+ children: [
238
+ f ? /* @__PURE__ */ o("span", { children: f.name }) : /* @__PURE__ */ o(lo, { children: i }),
239
+ /* @__PURE__ */ o(co, { style: { color: g }, $isOpen: r, children: "▼" })
240
+ ]
241
+ }
242
+ ),
243
+ r && /* @__PURE__ */ u(po, { role: "listbox", children: [
244
+ /* @__PURE__ */ o(
245
+ mo,
246
+ {
247
+ type: "text",
248
+ placeholder: n("search.placeholder"),
249
+ value: b,
250
+ onChange: (a) => w(a.target.value)
251
+ }
252
+ ),
253
+ S.length > 0 ? S.map((a) => /* @__PURE__ */ o(
254
+ oe,
255
+ {
256
+ onClick: () => C(a),
257
+ onKeyDown: (P) => F(P, a),
258
+ role: "option",
259
+ tabIndex: 0,
260
+ "aria-selected": f?.id === a.id,
261
+ $selected: f?.id === a.id,
262
+ children: a.name
263
+ },
264
+ a.id
265
+ )) : /* @__PURE__ */ o(oe, { children: n("select.noOptions") })
266
+ ] })
267
+ ] });
268
+ }, yo = ({
269
+ handleCloseModal: c
270
+ }) => {
271
+ const i = De(), { client: l } = Ne();
272
+ ke();
273
+ const { showToast: g } = Ue(), e = J(), { config: n, user: r, selectedUser: t, langSource: f } = Q(
274
+ (d) => d.chatSettingStore
275
+ ), U = Q((d) => d.call.phase), [b, w] = I(!1), v = ae(null), x = n?.videoCalls, C = n?.e2ee?.enabled === !0, S = x?.enabled === !0 && !!x?.livekitUrl?.trim() && (x?.allowedRoomTypes || ["private"]).includes("private"), s = S && x?.enableAudioCalls === !0, N = U !== "idle", F = y(() => {
276
+ i(Fe()), c();
277
+ }, []), a = y(() => {
278
+ Pe.performLogout();
279
+ }, []), P = M(
280
+ () => [
281
+ {
282
+ label: e("action.logOut"),
283
+ icon: /* @__PURE__ */ o(Ae, {}),
284
+ onClick: () => {
285
+ a();
286
+ },
287
+ styles: { color: "var(--ethora-color-danger, #D92D20)" }
288
+ }
289
+ ],
290
+ [a, e]
291
+ ), ie = (d) => {
292
+ i(Ve(d.id));
293
+ }, le = y(() => {
294
+ w(!0);
295
+ }, []), ce = async (d, h) => {
296
+ try {
297
+ const p = We(
298
+ d,
299
+ n?.xmppSettings?.conference,
300
+ h
301
+ );
302
+ if (!p || !p.jid)
303
+ return console.error(
304
+ "handleRoomCreation: failed to normalize new private room",
305
+ d
306
+ ), g({
307
+ id: Date.now().toString(),
308
+ title: e("toast.error"),
309
+ message: e("toast.couldNotOpenPrivateChat"),
310
+ type: "error",
311
+ duration: 4e3
312
+ }), null;
313
+ if (i(
314
+ Je({
315
+ room: p,
316
+ xmpp: l
317
+ })
318
+ ), l && p.jid) {
319
+ try {
320
+ await l.presenceInRoomStanza(p.jid);
321
+ } catch (k) {
322
+ console.warn("presenceInRoomStanza failed (non-fatal):", k);
323
+ }
324
+ try {
325
+ l.getHistoryStanza(p.jid, 10);
326
+ } catch (k) {
327
+ console.warn("getHistoryStanza failed (non-fatal):", k);
328
+ }
329
+ }
330
+ return i(Ke({ roomJID: p.jid })), g({
331
+ id: Date.now().toString(),
332
+ title: e("toast.success"),
333
+ message: e("toast.roomCreatedSuccess"),
334
+ type: "success",
335
+ duration: 3e3
336
+ }), { jid: p.jid };
337
+ } catch (p) {
338
+ return console.error("Error handling room creation:", p), null;
339
+ }
340
+ }, z = y(async (d = !1) => {
341
+ const h = String(
342
+ t?.name || `${t?.firstName || ""} ${t?.lastName || ""}`
343
+ ).trim() || "";
344
+ if (n?.newArch !== !1) {
345
+ const T = t?.xmppUsername || t?.userJID || t?.id;
346
+ if (!T)
347
+ return g({
348
+ id: Date.now().toString(),
349
+ title: e("toast.error"),
350
+ message: e("toast.couldNotResolveRecipient"),
351
+ type: "error",
352
+ duration: 4e3
353
+ }), null;
354
+ try {
355
+ const B = await Re(T, d), L = await ce(B, 2);
356
+ return L?.jid ? {
357
+ jid: L.jid,
358
+ bareName: L.jid.split("@")[0],
359
+ peerXmppUsername: String(T).split("@")[0],
360
+ peerDisplay: h
361
+ } : null;
362
+ } catch (B) {
363
+ return console.error("postPrivateRoom failed:", B), g({
364
+ id: Date.now().toString(),
365
+ title: e("toast.error"),
366
+ message: B?.message || e("toast.failedToCreatePrivateChat"),
367
+ type: "error",
368
+ duration: 4e3
369
+ }), null;
370
+ }
371
+ }
372
+ const p = Y(t.id), ue = [Y(r.defaultWallet.walletAddress), p].sort().join(".").toLowerCase(), _ = [r.firstName, t.name?.split(" ")?.[0]].sort().join(" and "), A = await l.createPrivateRoomStanza(
373
+ _,
374
+ `Private chat ${_}`,
375
+ ue
376
+ );
377
+ return A && (await l.inviteRoomRequestStanza(p, A), await l.getRoomsStanza()), A ? {
378
+ jid: A,
379
+ bareName: String(A).split("@")[0],
380
+ peerXmppUsername: p,
381
+ peerDisplay: h
382
+ } : null;
383
+ }, [t, n?.newArch, l, r]), j = y(
384
+ async (d) => {
385
+ g({
386
+ id: Date.now().toString(),
387
+ title: e("toast.roomCreationTitle"),
388
+ message: e("toast.roomCreating"),
389
+ type: "info",
390
+ duration: 3e3
391
+ }), await z(d), i(Z());
392
+ },
393
+ [z, i, g, e]
394
+ ), K = y(
395
+ () => j(!1),
396
+ [j]
397
+ ), V = y(
398
+ () => j(!0),
399
+ [j]
400
+ ), O = y(
401
+ async (d) => {
402
+ const h = await z();
403
+ if (!h) return;
404
+ const p = h.peerDisplay || h.bareName;
405
+ i(
406
+ ze({
407
+ roomJid: h.jid,
408
+ roomName: p,
409
+ roomBareName: h.bareName,
410
+ kind: d,
411
+ peerXmppUsername: h.peerXmppUsername || null
412
+ })
413
+ ), h.peerXmppUsername && je(d, {
414
+ peerXmppUsername: h.peerXmppUsername,
415
+ roomBareName: h.bareName
416
+ }), i(Z());
417
+ try {
418
+ await Be(h.bareName, { kind: d });
419
+ } catch (k) {
420
+ const q = k instanceof Error ? k.message : e("toast.failedToCreateCall");
421
+ i($e(q));
422
+ }
423
+ },
424
+ [z, i, e]
425
+ ), m = t ?? r, de = () => {
426
+ if (f)
427
+ return ee.find((d) => d.id === f);
428
+ }, pe = t ? void 0 : /* @__PURE__ */ u($, { children: [
429
+ /* @__PURE__ */ o(X, { onClick: le, "aria-label": e("action.editProfile"), children: /* @__PURE__ */ o(Ee, { color: "var(--ethora-color-text-muted, #8C8C8C)" }) }),
430
+ /* @__PURE__ */ o(
431
+ Oe,
432
+ {
433
+ options: P,
434
+ position: "left",
435
+ menuIcon: /* @__PURE__ */ o(Te, {})
436
+ }
437
+ )
438
+ ] }), me = /* @__PURE__ */ u($, { children: [
439
+ /* @__PURE__ */ o(
440
+ X,
441
+ {
442
+ variant: "ghost",
443
+ onClick: () => w(!1),
444
+ style: { width: "auto", padding: "0 var(--ethora-space-3, 12px)" },
445
+ children: e("action.cancel")
446
+ }
447
+ ),
448
+ /* @__PURE__ */ o(
449
+ X,
450
+ {
451
+ variant: "filled",
452
+ onClick: () => {
453
+ v.current?.save();
454
+ },
455
+ style: { width: "auto", padding: "0 var(--ethora-space-4, 16px)" },
456
+ children: e("action.save")
457
+ }
458
+ )
459
+ ] }), G = t && t.xmppUsername !== r.xmppUsername && !n?.disableProfilesInteractions, he = M(
460
+ () => /* @__PURE__ */ u($, { children: [
461
+ /* @__PURE__ */ u(ne, { children: [
462
+ /* @__PURE__ */ o(
463
+ re,
464
+ {
465
+ icon: m?.profileImage ?? null,
466
+ name: m?.name ?? m?.firstName,
467
+ size: 96
468
+ }
469
+ ),
470
+ /* @__PURE__ */ o(Ye, { children: m?.name ? `${m?.name}` : `${m?.firstName} ${m?.lastName}` })
471
+ ] }),
472
+ /* @__PURE__ */ u(E, { children: [
473
+ /* @__PURE__ */ o(W, { children: e("modal.profile.about") }),
474
+ /* @__PURE__ */ o(
475
+ Ze,
476
+ {
477
+ $empty: !(m?.description && m?.description?.length > 4),
478
+ children: m?.description && m?.description?.length > 4 ? m.description : e("modal.profile.noDescription")
479
+ }
480
+ )
481
+ ] }),
482
+ !t && n?.translates?.enabled && /* @__PURE__ */ u(E, { children: [
483
+ /* @__PURE__ */ o(W, { children: e("modal.profile.preferences") }),
484
+ /* @__PURE__ */ o(Ge, { children: /* @__PURE__ */ u(qe, { children: [
485
+ /* @__PURE__ */ o(_e, { children: e("modal.profile.languageHint") }),
486
+ /* @__PURE__ */ o(
487
+ ho,
488
+ {
489
+ options: ee,
490
+ placeholder: e("language.select"),
491
+ onSelect: ie,
492
+ accentColor: n?.colors?.primary,
493
+ selectedValue: de()
494
+ }
495
+ )
496
+ ] }) })
497
+ ] }),
498
+ G && /* @__PURE__ */ u(E, { children: [
499
+ /* @__PURE__ */ o(W, { children: e("modal.profile.actions") }),
500
+ /* @__PURE__ */ u(eo, { children: [
501
+ /* @__PURE__ */ o(
502
+ R,
503
+ {
504
+ StartIcon: /* @__PURE__ */ o(Le, {}),
505
+ onClick: K,
506
+ variant: "filled",
507
+ children: e("action.message")
508
+ }
509
+ ),
510
+ C && /* @__PURE__ */ o(
511
+ R,
512
+ {
513
+ StartIcon: /* @__PURE__ */ o(Me, { color: "var(--ethora-color-text-on-primary, #FFFFFF)" }),
514
+ onClick: V,
515
+ variant: "filled",
516
+ children: e("action.encryptedMessage")
517
+ }
518
+ ),
519
+ S && /* @__PURE__ */ o(
520
+ R,
521
+ {
522
+ StartIcon: /* @__PURE__ */ o(He, { color: "var(--ethora-color-text-on-primary, #FFFFFF)" }),
523
+ onClick: () => {
524
+ O("video");
525
+ },
526
+ disabled: N,
527
+ variant: "filled",
528
+ children: e(s ? "action.videoCall" : "action.call")
529
+ }
530
+ ),
531
+ s && /* @__PURE__ */ o(
532
+ R,
533
+ {
534
+ StartIcon: /* @__PURE__ */ o(Xe, { color: "var(--ethora-color-text-on-primary, #FFFFFF)" }),
535
+ onClick: () => {
536
+ O("audio");
537
+ },
538
+ disabled: N,
539
+ variant: "filled",
540
+ children: e("action.audioCall")
541
+ }
542
+ ),
543
+ /* @__PURE__ */ o(
544
+ R,
545
+ {
546
+ onClick: () => oo(t.id),
547
+ variant: "outlined",
548
+ children: e("action.copyUserId")
549
+ }
550
+ )
551
+ ] })
552
+ ] })
553
+ ] }),
554
+ [
555
+ m,
556
+ S,
557
+ s,
558
+ N,
559
+ O,
560
+ K,
561
+ V,
562
+ C,
563
+ t,
564
+ G,
565
+ r,
566
+ n,
567
+ f,
568
+ e
569
+ ]
570
+ ), fe = M(
571
+ () => /* @__PURE__ */ o(
572
+ se,
573
+ {
574
+ ref: v,
575
+ setIsEditing: w,
576
+ modalUser: m,
577
+ config: n
578
+ }
579
+ ),
580
+ [m]
581
+ );
582
+ return /* @__PURE__ */ o(
583
+ Qe,
584
+ {
585
+ title: e("modal.profile.title"),
586
+ onClose: F,
587
+ headerActions: b ? me : pe,
588
+ children: b ? fe : he
589
+ }
590
+ );
591
+ };
592
+ export {
593
+ yo as default
594
+ };
@@ -1,7 +1,7 @@
1
1
  import { jsx as i, jsxs as n } from "react/jsx-runtime";
2
2
  import m, { useCallback as D, useMemo as h } from "react";
3
- import { n as g, a as p, o as w, M as r } from "./main-BNdWGLpK.js";
4
- import { S as b, D as u, a as k, b as y, c as S, d as f } from "./SideDrawer-CT108Ag1.js";
3
+ import { n as g, a as p, o as w, M as r } from "./main-DkokKp7d.js";
4
+ import { S as b, D as u, a as k, b as y, c as S, d as f } from "./SideDrawer-mSCnYOgy.js";
5
5
  const T = ({
6
6
  handleCloseModal: l
7
7
  }) => {
@@ -1,7 +1,7 @@
1
1
  import { jsxs as z, jsx as M, Fragment as xi } from "react/jsx-runtime";
2
2
  import * as F from "react";
3
3
  import { useState as zt, useRef as be, useEffect as ge, useMemo as ln, useCallback as mi } from "react";
4
- import { u as Qi, P as Kn, H as Oi, a as Hd, b as zd, s as po, c as Kd, d as Gd, e as fo, f as Jd, g as Yd, h as mo, i as $d, j as Xd, r as go, k as Qd, l as Zd, A as vo, V as bo, B as eu } from "./main-BNdWGLpK.js";
4
+ import { u as Qi, P as Kn, H as Oi, a as Hd, b as zd, s as po, c as Kd, d as Gd, e as fo, f as Jd, g as Yd, h as mo, i as $d, j as Xd, r as go, k as Qd, l as Zd, A as vo, V as bo, B as eu } from "./main-DkokKp7d.js";
5
5
  function tu(n, e) {
6
6
  return e.forEach(function(t) {
7
7
  t && typeof t != "string" && !Array.isArray(t) && Object.keys(t).forEach(function(i) {
@@ -1,7 +1,7 @@
1
1
  import { jsxs as r, jsx as e } from "react/jsx-runtime";
2
2
  import { useState as b, useEffect as x } from "react";
3
- import { v as o, a as L, n as P, u as z, aD as D, aE as I } from "./main-BNdWGLpK.js";
4
- import { S as N, D as C, a as w, b as O, e as S, f as p } from "./SideDrawer-CT108Ag1.js";
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
5
  o.div``;
6
6
  o.div`
7
7
  font-size: 16px;
@@ -172,3 +172,11 @@ export declare const ZoomResetIcon: ({ color, ...props }: {
172
172
  [x: string]: any;
173
173
  color?: string;
174
174
  }) => import("react/jsx-runtime").JSX.Element;
175
+ export declare const LockIcon: ({ color, ...props }: {
176
+ [x: string]: any;
177
+ color?: string;
178
+ }) => import("react/jsx-runtime").JSX.Element;
179
+ export declare const LockOffIcon: ({ color, ...props }: {
180
+ [x: string]: any;
181
+ color?: string;
182
+ }) => import("react/jsx-runtime").JSX.Element;
@@ -2,6 +2,11 @@ import { default as React } from 'react';
2
2
  import { IAttachment } from '../../types/types';
3
3
  interface AttachmentListProps {
4
4
  attachments: IAttachment[];
5
+ /** See CustomMessageImage's `onUnavailable` - only wired to the full-width
6
+ * single-image renderer (AttachmentRow), not the multi-file grid tiles,
7
+ * since one dead thumbnail there shouldn't tombstone a message that still
8
+ * has other live attachments. */
9
+ onUnavailable?: () => void;
5
10
  }
6
11
  declare const AttachmentList: React.FC<AttachmentListProps>;
7
12
  export default AttachmentList;
@@ -4,6 +4,16 @@ interface CustomMessageImageProps {
4
4
  fileName: string;
5
5
  mimetype: string;
6
6
  locationPreview?: string;
7
+ /**
8
+ * Called only once the server itself says the file is gone (404/410),
9
+ * not merely when the <img> failed to load. The only known cause in
10
+ * practice is the file having been deleted from the Files panel without
11
+ * a matching message found locally to tombstone up front (see
12
+ * FilesPanel.tsx's handleDelete) - the caller uses this to flip the
13
+ * message to the normal "deleted" placeholder instead of leaving this
14
+ * broken-image card on screen.
15
+ */
16
+ onUnavailable?: () => void;
7
17
  }
8
18
  declare const CustomMessageImage: React.FC<CustomMessageImageProps>;
9
19
  export default CustomMessageImage;
@@ -0,0 +1,32 @@
1
+ import { concatBytes, randomBytes } from '@noble/hashes/utils.js';
2
+ export { concatBytes, randomBytes };
3
+ export interface KeyPair {
4
+ priv: Uint8Array;
5
+ pub: Uint8Array;
6
+ }
7
+ /** Ed25519 identity key; `seed` is the 32-byte Ed25519 secret key. */
8
+ export interface IdentityKey {
9
+ seed: Uint8Array;
10
+ pub: Uint8Array;
11
+ }
12
+ export declare function hkdfSha256(ikm: Uint8Array, salt: Uint8Array | undefined, info: string, length: number): Uint8Array<ArrayBufferLike> & Uint8Array<ArrayBuffer>;
13
+ export declare function hmacSha256(key: Uint8Array, data: Uint8Array): Uint8Array;
14
+ /** AES-256-CBC with PKCS#7 padding. */
15
+ export declare function aesEncrypt(key: Uint8Array, iv: Uint8Array, data: Uint8Array): Uint8Array;
16
+ export declare function aesDecrypt(key: Uint8Array, iv: Uint8Array, data: Uint8Array): Uint8Array;
17
+ export declare function generateKeyPair(): KeyPair;
18
+ export declare function generateIdentity(): IdentityKey;
19
+ /** X25519; throws on low-order public keys. */
20
+ export declare function dh(priv: Uint8Array, pub: Uint8Array): Uint8Array;
21
+ /** The X25519 form of an identity key, for X3DH. */
22
+ export declare function identityDhPrivate(identity: IdentityKey): Uint8Array;
23
+ export declare function identityDhPublic(identityPub: Uint8Array): Uint8Array;
24
+ export declare function sign(identity: IdentityKey, message: Uint8Array): Uint8Array;
25
+ export declare function verify(signature: Uint8Array, message: Uint8Array, identityPub: Uint8Array): boolean;
26
+ /** Constant-time comparison. */
27
+ export declare function bytesEqual(a: Uint8Array, b: Uint8Array): boolean;
28
+ export declare function toBase64(bytes: Uint8Array): string;
29
+ export declare function fromBase64(text: string): Uint8Array;
30
+ export declare function toHex(bytes: Uint8Array): string;
31
+ /** Random integer in [min, max]. */
32
+ export declare function randomInt(min: number, max: number): number;