@paramms/chat-widget 1.0.39 → 1.0.41
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.
- package/README.md +164 -2
- package/dist/embed.d.ts +110 -10
- package/dist/embed.js +44 -10
- package/dist/embed.js.map +1 -1
- package/dist/index.js +314 -323
- package/dist/index.js.map +1 -1
- package/dist/outbox.js +5 -5
- package/dist/outbox.js.map +1 -1
- package/dist/renderer.d.ts +1 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var y = (t, e, i) =>
|
|
4
|
-
import { p as
|
|
1
|
+
var Le = Object.defineProperty;
|
|
2
|
+
var je = (t, e, i) => e in t ? Le(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i;
|
|
3
|
+
var y = (t, e, i) => je(t, typeof e != "symbol" ? e + "" : e, i);
|
|
4
|
+
import { p as Pe, r as Ae, a as Be } from "./codec.js";
|
|
5
5
|
import { h as st } from "./codec.js";
|
|
6
|
-
import { P as
|
|
7
|
-
import { e as
|
|
8
|
-
import { E2ESession as qe, extractX3DHInit as
|
|
6
|
+
import { P as $e, C as Me, b as Re } from "./outbox.js";
|
|
7
|
+
import { e as rt } from "./outbox.js";
|
|
8
|
+
import { E2ESession as qe, extractX3DHInit as Ne } from "./e2e.js";
|
|
9
9
|
const xe = "http://www.w3.org/2000/svg", De = 8e3;
|
|
10
|
-
class
|
|
10
|
+
class Oe {
|
|
11
11
|
constructor() {
|
|
12
12
|
y(this, "svg", null);
|
|
13
13
|
y(this, "timers", /* @__PURE__ */ new Set());
|
|
@@ -32,16 +32,16 @@ class He {
|
|
|
32
32
|
draw(e) {
|
|
33
33
|
var b;
|
|
34
34
|
if (typeof document > "u" || !((b = e.points) != null && b.length)) return;
|
|
35
|
-
const i = this.ensureSvg(), s = window.innerWidth,
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
35
|
+
const i = this.ensureSvg(), s = window.innerWidth, a = window.innerHeight, c = document.createElementNS(xe, "polyline");
|
|
36
|
+
c.setAttribute("points", e.points.map((d) => `${(d.x * s).toFixed(1)},${(d.y * a).toFixed(1)}`).join(" ")), c.setAttribute("fill", "none"), c.setAttribute("stroke", e.color || "#ff3b30"), c.setAttribute("stroke-width", String(e.width || 3)), c.setAttribute("stroke-linecap", "round"), c.setAttribute("stroke-linejoin", "round"), c.setAttribute("data-stroke-id", e.id), i.append(c);
|
|
37
|
+
const w = setTimeout(() => {
|
|
38
|
+
c.style.transition = "opacity 600ms", c.style.opacity = "0";
|
|
39
39
|
const d = setTimeout(() => {
|
|
40
|
-
|
|
40
|
+
c.remove(), this.timers.delete(d);
|
|
41
41
|
}, 650);
|
|
42
|
-
this.timers.add(d), this.timers.delete(
|
|
42
|
+
this.timers.add(d), this.timers.delete(w);
|
|
43
43
|
}, De);
|
|
44
|
-
this.timers.add(
|
|
44
|
+
this.timers.add(w);
|
|
45
45
|
}
|
|
46
46
|
clear() {
|
|
47
47
|
var e;
|
|
@@ -53,7 +53,7 @@ class He {
|
|
|
53
53
|
this.timers.clear(), (e = this.svg) == null || e.remove(), this.svg = null;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
const
|
|
56
|
+
const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "😢", "🙏"], _e = 400, Fe = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', Ue = `
|
|
57
57
|
.ocw { --ocw-accent:#4F63F5; --ocw-bg:#f3efe9; --ocw-card:#fff; --ocw-line:#ececec; --ocw-ink:#1c1b1a; --ocw-mut:#9b9690;
|
|
58
58
|
position:relative;
|
|
59
59
|
display:flex; flex-direction:column; height:100%; min-height:320px; background:var(--ocw-bg);
|
|
@@ -152,15 +152,13 @@ const me = "objectchat-widget-styles", Ne = ["👍", "❤️", "😂", "😮", "
|
|
|
152
152
|
.ocw-conn-status.err { color:#c0392b; font-weight:600; }
|
|
153
153
|
.ocw-load-more { display:block; width:100%; background:none; border:1px solid #e3ded7; border-radius:10px; padding:6px 0; font-size:12px; color:var(--ocw-mut); cursor:pointer; margin-bottom:8px; }
|
|
154
154
|
.ocw-load-more:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
|
|
155
|
-
.ocw-
|
|
156
|
-
.ocw-
|
|
157
|
-
|
|
158
|
-
.ocw-offline-msg { font-size:13px; color:var(--ocw-mut); margin-bottom:16px; }
|
|
155
|
+
.ocw-away { margin:0 14px 8px; padding:9px 12px; background:#fff8e6; border:1px solid #f0e2bd; border-radius:10px; font-size:12px; color:#7a5c17; display:flex; gap:7px; align-items:flex-start; line-height:1.45; }
|
|
156
|
+
.ocw-away-icon { flex:none; }
|
|
157
|
+
/* Shared form styles (used by the pre-chat panel; named for the retired offline form). */
|
|
159
158
|
.ocw-offline-form { display:flex; flex-direction:column; gap:8px; text-align:left; }
|
|
160
159
|
.ocw-offline-input { border:1px solid #e3ded7; border-radius:10px; padding:10px 12px; font-size:13px; font-family:inherit; }
|
|
161
160
|
.ocw-offline-input:focus { outline:none; border-color:var(--ocw-accent); }
|
|
162
161
|
.ocw-offline-submit { background:var(--ocw-accent); color:#fff; border:none; border-radius:10px; padding:11px; font-size:14px; font-weight:600; cursor:pointer; }
|
|
163
|
-
.ocw-offline-thanks { font-size:14px; color:#15803d; font-weight:600; }
|
|
164
162
|
.ocw-prechat { margin:20px 14px; padding:20px; background:#fff; border:1px solid #e3ded7; border-radius:16px; }
|
|
165
163
|
.ocw-prechat-title { font-weight:700; font-size:15px; margin-bottom:12px; }
|
|
166
164
|
.ocw-prechat select { border:1px solid #e3ded7; border-radius:10px; padding:10px 12px; font:inherit; font-size:13px; background:#fff; }
|
|
@@ -245,9 +243,9 @@ const me = "objectchat-widget-styles", Ne = ["👍", "❤️", "😂", "😮", "
|
|
|
245
243
|
.ocw-translated-tag { font-size:10px; color:var(--ocw-mut); margin-top:2px; }
|
|
246
244
|
`;
|
|
247
245
|
function We() {
|
|
248
|
-
if (typeof document > "u" || document.getElementById(
|
|
246
|
+
if (typeof document > "u" || document.getElementById(ge)) return;
|
|
249
247
|
const t = document.createElement("style");
|
|
250
|
-
t.id =
|
|
248
|
+
t.id = ge, t.textContent = Ue, document.head.appendChild(t);
|
|
251
249
|
}
|
|
252
250
|
function o(t, e, i) {
|
|
253
251
|
const s = document.createElement(t);
|
|
@@ -277,16 +275,16 @@ function ie(t) {
|
|
|
277
275
|
return `📅 ${t.title} — ${new Date(t.startIso).toLocaleString()}`;
|
|
278
276
|
}
|
|
279
277
|
}
|
|
280
|
-
class
|
|
278
|
+
class Ke {
|
|
281
279
|
/** Last seq the guest has seen per conversationId — used to compute unread badges. */
|
|
282
|
-
constructor(e, i, s,
|
|
280
|
+
constructor(e, i, s, a = {}) {
|
|
283
281
|
y(this, "scroll");
|
|
284
282
|
y(this, "chips");
|
|
285
283
|
y(this, "typing");
|
|
286
284
|
y(this, "quick");
|
|
287
285
|
y(this, "formHost");
|
|
288
286
|
y(this, "csatPanel");
|
|
289
|
-
y(this, "
|
|
287
|
+
y(this, "awayNotice");
|
|
290
288
|
y(this, "preChatPanel");
|
|
291
289
|
y(this, "deflectPanel");
|
|
292
290
|
y(this, "preChatBuilt", !1);
|
|
@@ -319,73 +317,73 @@ class Ye {
|
|
|
319
317
|
/** Whether the subject card (server Subject entity, mount config fallback)
|
|
320
318
|
* has been built — built once when data first arrives. */
|
|
321
319
|
y(this, "subjectBuilt", !1);
|
|
322
|
-
var k, I,
|
|
323
|
-
this.root = e, this.me = i, this.h = s, this.cfg =
|
|
324
|
-
const
|
|
320
|
+
var k, I, P, C, R, A, N, U, T, $;
|
|
321
|
+
this.root = e, this.me = i, this.h = s, this.cfg = a, We(), e.replaceChildren(), e.classList.add("ocw"), a.accent && e.style.setProperty("--ocw-accent", a.accent);
|
|
322
|
+
const c = o("div", "ocw-head");
|
|
325
323
|
if (this.h.onBack) {
|
|
326
|
-
const
|
|
327
|
-
|
|
324
|
+
const g = o("button", "ocw-back", "‹");
|
|
325
|
+
g.type = "button", g.setAttribute("aria-label", "Back"), g.addEventListener("click", () => this.h.onBack()), c.append(g);
|
|
328
326
|
}
|
|
329
|
-
const
|
|
330
|
-
if ((k =
|
|
331
|
-
const
|
|
332
|
-
|
|
327
|
+
const w = o("div", "ocw-avatar");
|
|
328
|
+
if ((k = a.userInfo) != null && k.avatar) {
|
|
329
|
+
const g = document.createElement("img");
|
|
330
|
+
g.src = a.userInfo.avatar, g.alt = a.userInfo.name ?? "You", g.style.cssText = "width:100%;height:100%;border-radius:50%;object-fit:cover", w.append(g);
|
|
333
331
|
} else
|
|
334
|
-
|
|
335
|
-
|
|
332
|
+
w.textContent = (I = a.userInfo) != null && I.name ? a.userInfo.name[0].toUpperCase() : "🧑";
|
|
333
|
+
c.append(w);
|
|
336
334
|
const b = o("div", "ocw-head-main");
|
|
337
|
-
this.headerName = o("div", "ocw-head-name", ((
|
|
335
|
+
this.headerName = o("div", "ocw-head-name", ((P = a.subject) == null ? void 0 : P.ownerLabel) ?? ((C = a.subject) == null ? void 0 : C.title) ?? ""), b.append(this.headerName), (R = a.subject) != null && R.subtitle && b.append(o("div", "ocw-head-meta", a.subject.subtitle)), c.append(b), this.statusBadge = o("span", "ocw-badge", ((A = a.subject) == null ? void 0 : A.status) ?? ""), (N = a.subject) != null && N.status || (this.statusBadge.style.display = "none"), c.append(this.statusBadge), this.e2eBadge = o("span", "ocw-e2e", "🔒 E2E"), this.e2eBadge.style.display = "none", c.append(this.e2eBadge), this.connStatus = o("span", "ocw-conn-status"), this.connStatus.style.display = "none", c.append(this.connStatus), this.cobrowseBtn = o("button", "ocw-menu ocw-cobrowse-btn", "🖍"), this.cobrowseBtn.title = "Shared whiteboard — draw to point things out together", this.cobrowseBtn.addEventListener("click", () => {
|
|
338
336
|
this.cobrowseActive = !this.cobrowseActive, this.updateCobrowseUI();
|
|
339
|
-
}),
|
|
337
|
+
}), c.append(this.cobrowseBtn), c.append(o("button", "ocw-menu", "⋯")), this.chips = o("div", "ocw-chiprow"), this.scroll = o("div", "ocw-scroll"), this.subjectCard = o("div", "ocw-subject"), this.typing = o("div", "ocw-typing");
|
|
340
338
|
const d = o("div", "ocw-typing-bubble");
|
|
341
339
|
d.append(o("div", "ocw-typing-dot"), o("div", "ocw-typing-dot"), o("div", "ocw-typing-dot")), this.typing.append(o("div", "ocw-dot", "🧑"), d), this.quick = o("div", "ocw-quick");
|
|
342
|
-
for (const
|
|
343
|
-
const S = o("button", void 0,
|
|
340
|
+
for (const g of a.quickReplies ?? []) {
|
|
341
|
+
const S = o("button", void 0, g);
|
|
344
342
|
S.addEventListener("click", () => {
|
|
345
|
-
this.h.onSend(
|
|
343
|
+
this.h.onSend(g), this.quick.style.display = "none";
|
|
346
344
|
}), this.quick.append(S);
|
|
347
345
|
}
|
|
348
|
-
this.formHost = o("div", "ocw-form-host"), this.csatPanel = o("div", "ocw-csat"), this.csatPanel.style.display = "none", this.
|
|
346
|
+
this.formHost = o("div", "ocw-form-host"), this.csatPanel = o("div", "ocw-csat"), this.csatPanel.style.display = "none", this.awayNotice = o("div", "ocw-away"), this.awayNotice.style.display = "none", this.preChatPanel = o("div", "ocw-prechat"), this.preChatPanel.style.display = "none", this.deflectPanel = o("div", "ocw-deflect"), this.deflectPanel.style.display = "none", this.input = o("textarea", void 0), this.input.rows = 1, this.input.placeholder = ((U = a.i18n) == null ? void 0 : U.placeholder) ?? "Message…";
|
|
349
347
|
const h = o("button", "ocw-sendbtn");
|
|
350
348
|
h.type = "button";
|
|
351
|
-
const v = (T =
|
|
349
|
+
const v = (T = a.i18n) == null ? void 0 : T.send;
|
|
352
350
|
v ? (h.textContent = v, h.classList.add("ocw-sendbtn-label"), h.setAttribute("aria-label", v)) : (h.innerHTML = Fe, h.setAttribute("aria-label", "Send message")), h.disabled = !0, this.sendBtn = h, h.addEventListener("click", () => this.flushSend()), this.input.addEventListener("input", () => {
|
|
353
|
-
var
|
|
354
|
-
this.sendBtn.disabled = this.input.value.trim().length === 0, this.autoGrowInput(), this.storeRef && !this.storeRef.messages().some((q) => q.senderRole === "guest") ? (S = (
|
|
355
|
-
}), this.input.addEventListener("keydown", (
|
|
356
|
-
|
|
351
|
+
var g, S;
|
|
352
|
+
this.sendBtn.disabled = this.input.value.trim().length === 0, this.autoGrowInput(), this.storeRef && !this.storeRef.messages().some((q) => q.senderRole === "guest") ? (S = (g = this.h).onDeflectQuery) == null || S.call(g, this.input.value) : this.hideDeflection();
|
|
353
|
+
}), this.input.addEventListener("keydown", (g) => {
|
|
354
|
+
g.isComposing || g.keyCode === 229 || (g.key === "Enter" && !g.shiftKey ? (g.preventDefault(), this.flushSend()) : this.signalTyping());
|
|
357
355
|
});
|
|
358
|
-
const
|
|
359
|
-
|
|
356
|
+
const r = o("button", "ocw-attach", "📎");
|
|
357
|
+
r.title = "Attach image or file";
|
|
360
358
|
const u = document.createElement("input");
|
|
361
|
-
u.type = "file", u.accept = "image/*,.pdf,.txt,.doc,.docx", u.style.display = "none",
|
|
362
|
-
var
|
|
363
|
-
(
|
|
359
|
+
u.type = "file", u.accept = "image/*,.pdf,.txt,.doc,.docx", u.style.display = "none", r.addEventListener("click", () => u.click()), u.addEventListener("change", () => {
|
|
360
|
+
var g;
|
|
361
|
+
(g = u.files) != null && g[0] && this.h.onAttach && this.h.onAttach(u.files[0]), u.value = "";
|
|
364
362
|
});
|
|
365
363
|
const l = o("div", "ocw-input");
|
|
366
|
-
l.append(
|
|
364
|
+
l.append(r, u, this.input, h);
|
|
367
365
|
const E = o("div", "ocw-footer");
|
|
368
|
-
((
|
|
369
|
-
for (const
|
|
366
|
+
(($ = a.i18n) == null ? void 0 : $.poweredBy) !== void 0 ? E.textContent = a.i18n.poweredBy : E.innerHTML = 'Powered by <a href="https://relay.paramms.com" target="_blank" rel="noopener">Relay</a>', this.footer = E, e.append(c, this.chips, this.scroll, this.typing, this.quick, this.formHost, this.csatPanel, this.preChatPanel, this.deflectPanel, this.awayNotice, l, this.footer), this.cobrowseCanvas = o("canvas", "ocw-cobrowse-canvas"), this.cobrowseToolbar = o("div", "ocw-cobrowse-toolbar");
|
|
367
|
+
for (const g of ["#f5713c", "#1c1b1a", "#2563eb", "#16a34a", "#dc2626"]) {
|
|
370
368
|
const S = o("button", "ocw-cobrowse-swatch");
|
|
371
|
-
S.style.background =
|
|
372
|
-
this.cobrowseColor =
|
|
369
|
+
S.style.background = g, S.type = "button", g === this.cobrowseColor && S.classList.add("sel"), S.addEventListener("click", () => {
|
|
370
|
+
this.cobrowseColor = g;
|
|
373
371
|
for (const q of this.cobrowseToolbar.querySelectorAll(".ocw-cobrowse-swatch")) q.classList.remove("sel");
|
|
374
372
|
S.classList.add("sel");
|
|
375
373
|
}), this.cobrowseToolbar.append(S);
|
|
376
374
|
}
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
var
|
|
380
|
-
return (S = (
|
|
381
|
-
}), this.cobrowseToolbar.append(
|
|
382
|
-
const
|
|
383
|
-
e.classList.toggle("ocw-compact",
|
|
375
|
+
const m = o("button", "ocw-cobrowse-clear", "Clear");
|
|
376
|
+
m.addEventListener("click", () => {
|
|
377
|
+
var g, S;
|
|
378
|
+
return (S = (g = this.h).onAnnotateClear) == null ? void 0 : S.call(g);
|
|
379
|
+
}), this.cobrowseToolbar.append(m), this.cobrowseHint = o("div", "ocw-cobrowse-hint", "🖍 Draw to point things out — visible to both sides"), e.append(this.cobrowseCanvas, this.cobrowseToolbar, this.cobrowseHint), this.bindCobrowsePointerEvents();
|
|
380
|
+
const f = (g) => {
|
|
381
|
+
e.classList.toggle("ocw-compact", g > 0 && g < _e);
|
|
384
382
|
};
|
|
385
|
-
|
|
383
|
+
f(e.clientWidth), typeof ResizeObserver < "u" && (this.compactObserver = new ResizeObserver((g) => {
|
|
386
384
|
var q;
|
|
387
|
-
const S = ((q =
|
|
388
|
-
|
|
385
|
+
const S = ((q = g[0]) == null ? void 0 : q.contentRect.width) ?? e.clientWidth;
|
|
386
|
+
f(S);
|
|
389
387
|
}), this.compactObserver.observe(e));
|
|
390
388
|
}
|
|
391
389
|
/** Returns the scroll container so history.ts can attach scroll listeners. */
|
|
@@ -420,30 +418,40 @@ class Ye {
|
|
|
420
418
|
this.h.onTyping(!0, e), this.typingTimer && clearTimeout(this.typingTimer), this.typingTimer = setTimeout(() => this.h.onTyping(!1), 2e3);
|
|
421
419
|
}
|
|
422
420
|
render(e) {
|
|
423
|
-
var
|
|
421
|
+
var r, u, l, E, m;
|
|
424
422
|
if (this.storeRef = e, this.cobrowseBtn.classList.toggle("show", !!e.subject), !e.subject && this.cobrowseActive && (this.cobrowseActive = !1, this.updateCobrowseUI()), this.cobrowseActive && e.annotationVersion !== this.lastAnnotationVersion && (this.lastAnnotationVersion = e.annotationVersion, this.resizeCobrowseCanvas(), this.redrawCobrowse()), e.accent && this.root.style.setProperty("--ocw-accent", e.accent), this.e2eBadge.style.display = e.e2e ? "inline-flex" : "none", this.buildSubjectCard(e), e.subject) {
|
|
425
|
-
const
|
|
426
|
-
|
|
423
|
+
const f = (r = this.cfg.subject) == null ? void 0 : r.ownerLabel;
|
|
424
|
+
f && (this.headerName.textContent = f);
|
|
427
425
|
}
|
|
428
426
|
this.quick.style.display = e.messages().length === 0 ? "flex" : "none", this.chips.replaceChildren();
|
|
429
427
|
const i = e.visibleActions();
|
|
430
428
|
this.chips.style.display = i.length ? "flex" : "none";
|
|
431
|
-
for (const
|
|
432
|
-
const s = this.scroll.scrollHeight,
|
|
429
|
+
for (const f of i) this.chips.append(this.chipEl(f));
|
|
430
|
+
const s = this.scroll.scrollHeight, a = this.scroll.scrollTop;
|
|
433
431
|
if (this.scroll.replaceChildren(), this.subjectCard.childNodes.length && this.scroll.append(this.subjectCard), e.hasMoreHistory) {
|
|
434
|
-
const
|
|
435
|
-
|
|
432
|
+
const f = o("div", "ocw-load-more");
|
|
433
|
+
f.textContent = "↑ Loading earlier messages…", f.style.pointerEvents = "none", this.scroll.append(f);
|
|
436
434
|
}
|
|
437
|
-
let
|
|
438
|
-
for (const
|
|
439
|
-
this.scroll.append(this.messageEl(
|
|
440
|
-
|
|
441
|
-
const
|
|
442
|
-
this.typing.classList.toggle("active",
|
|
435
|
+
let c = 0;
|
|
436
|
+
for (const f of e.messages())
|
|
437
|
+
this.scroll.append(this.messageEl(f, e)), f.senderId !== this.me && f.seq > c && (c = f.seq);
|
|
438
|
+
a > 20 ? this.scroll.scrollTop = this.scroll.scrollHeight - s + a : this.scroll.scrollTop = this.scroll.scrollHeight, c > 0 && this.h.onReadUpTo(c);
|
|
439
|
+
const w = [...e.typing];
|
|
440
|
+
this.typing.classList.toggle("active", w.length > 0);
|
|
443
441
|
const b = this.typing.querySelector(".ocw-typing-bubble");
|
|
444
|
-
b && b.setAttribute("aria-label",
|
|
445
|
-
const d = e.messages().some((
|
|
446
|
-
!!((u = e.preChat) != null && u.enabled) && !this.preChatDone && !d && (e.preChat.showWhen !== "offline" || e.offline)
|
|
442
|
+
b && b.setAttribute("aria-label", w.length ? "typing" : ""), this.footer.style.display = e.whiteLabel ? "none" : "block";
|
|
443
|
+
const d = e.messages().some((f) => f.senderRole === "guest");
|
|
444
|
+
if (!!((u = e.preChat) != null && u.enabled) && !this.preChatDone && !d && (e.preChat.showWhen !== "offline" || e.offline))
|
|
445
|
+
this.preChatBuilt || this.buildPreChatPanel(e.preChat), this.preChatPanel.style.display = "block", this.awayNotice.style.display = "none", (l = this.root.querySelector(".ocw-input")) == null || l.style.setProperty("display", "none");
|
|
446
|
+
else {
|
|
447
|
+
if (this.preChatPanel.style.display = "none", e.offline) {
|
|
448
|
+
this.awayNotice.firstChild || this.awayNotice.append(o("span", "ocw-away-icon", "🌙"), o("span", "", ""));
|
|
449
|
+
const f = this.awayNotice.lastChild;
|
|
450
|
+
f.textContent = e.offlineMessage || ((E = this.cfg.i18n) == null ? void 0 : E.offline) || "We're away right now — send your message and we'll reply as soon as we're back.", this.awayNotice.style.display = "flex";
|
|
451
|
+
} else
|
|
452
|
+
this.awayNotice.style.display = "none";
|
|
453
|
+
(m = this.root.querySelector(".ocw-input")) == null || m.style.removeProperty("display");
|
|
454
|
+
}
|
|
447
455
|
const v = ["resolved", "closed", "sold", "issued", "checked_out"];
|
|
448
456
|
this.h.onCsat && !this.csatSubmitted && v.includes(e.state) && e.messages().length > 0 && (this.csatPanel.style.display === "none" && this.buildCsatPanel(), this.csatPanel.style.display = "block");
|
|
449
457
|
}
|
|
@@ -456,23 +464,6 @@ class Ye {
|
|
|
456
464
|
const s = e === "error";
|
|
457
465
|
this.connStatus.className = `ocw-conn-status${s ? " err" : e === "reconnecting" ? " warn" : ""}`, this.connStatus.textContent = s ? `⚠ ${i ?? "Chat unavailable"}` : e === "reconnecting" ? i ?? "↻ reconnecting…" : "● connecting…";
|
|
458
466
|
}
|
|
459
|
-
buildOfflinePanel(e) {
|
|
460
|
-
var b;
|
|
461
|
-
this.offlinePanel.replaceChildren(), this.offlinePanel.append(o("div", "ocw-offline-icon", "🌙")), this.offlinePanel.append(o("div", "ocw-offline-title", ((b = this.cfg.i18n) == null ? void 0 : b.offline) ?? "We're offline right now")), this.offlinePanel.append(o("div", "ocw-offline-msg", e || "Leave your details and we'll get back to you soon."));
|
|
462
|
-
const i = o("div", "ocw-offline-form"), s = o("input", "ocw-offline-input");
|
|
463
|
-
s.placeholder = "Your name", s.type = "text";
|
|
464
|
-
const r = o("input", "ocw-offline-input");
|
|
465
|
-
r.placeholder = "Your email", r.type = "email";
|
|
466
|
-
const a = o("textarea", "ocw-offline-input");
|
|
467
|
-
a.placeholder = "Your message", a.rows = 3;
|
|
468
|
-
const f = o("button", "ocw-offline-submit", "Send message");
|
|
469
|
-
f.type = "button", f.addEventListener("click", () => {
|
|
470
|
-
!r.value.trim() || !a.value.trim() || (f.disabled = !0, this.h.onSend(`[Offline form]
|
|
471
|
-
Name: ${s.value || "Anonymous"}
|
|
472
|
-
Email: ${r.value}
|
|
473
|
-
Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-thanks", "✓ Message sent! We'll reply to your email.")));
|
|
474
|
-
}), i.append(s, r, a, f), this.offlinePanel.append(i);
|
|
475
|
-
}
|
|
476
467
|
buildPreChatPanel(e) {
|
|
477
468
|
var d;
|
|
478
469
|
this.preChatBuilt = !0, this.preChatPanel.replaceChildren(), this.preChatPanel.append(o("div", "ocw-prechat-title", e.title ?? "Before we start…"));
|
|
@@ -481,44 +472,44 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
481
472
|
const v = o("input", "ocw-offline-input");
|
|
482
473
|
v.type = h === "email" ? "email" : h === "phone" ? "tel" : "text", v.placeholder = h === "name" ? "Your name" : h === "email" ? "Your email" : "Your phone number", s[h] = v, i.append(v);
|
|
483
474
|
}
|
|
484
|
-
let
|
|
475
|
+
let a = null;
|
|
485
476
|
if ((d = e.topics) != null && d.length) {
|
|
486
|
-
|
|
477
|
+
a = o("select", void 0);
|
|
487
478
|
const h = document.createElement("option");
|
|
488
|
-
h.value = "", h.textContent = "What is this about?",
|
|
479
|
+
h.value = "", h.textContent = "What is this about?", a.append(h);
|
|
489
480
|
for (const v of e.topics) {
|
|
490
|
-
const
|
|
491
|
-
|
|
481
|
+
const r = document.createElement("option");
|
|
482
|
+
r.value = v, r.textContent = v, a.append(r);
|
|
492
483
|
}
|
|
493
|
-
i.append(
|
|
484
|
+
i.append(a);
|
|
494
485
|
}
|
|
495
|
-
let
|
|
486
|
+
let c = null, w = null;
|
|
496
487
|
if (e.callbackOption) {
|
|
497
488
|
const h = o("label", "ocw-prechat-cb");
|
|
498
|
-
|
|
489
|
+
c = document.createElement("input"), c.type = "checkbox", h.append(c, document.createTextNode("📞 Request a call back")), i.append(h), s.phone || (w = o("input", "ocw-offline-input"), w.type = "tel", w.placeholder = "Phone number for the call", w.style.display = "none", c.addEventListener("change", () => w.style.setProperty("display", c.checked ? "block" : "none")), i.append(w));
|
|
499
490
|
}
|
|
500
491
|
const b = o("button", "ocw-offline-submit", "Start chat");
|
|
501
492
|
b.type = "button", b.addEventListener("click", () => {
|
|
502
|
-
var u, l, E,
|
|
493
|
+
var u, l, E, m, f, k, I;
|
|
503
494
|
const h = (u = s.email) == null ? void 0 : u.value.trim();
|
|
504
495
|
if (s.email && (!h || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(h))) {
|
|
505
496
|
s.email.focus();
|
|
506
497
|
return;
|
|
507
498
|
}
|
|
508
|
-
const v = !!(
|
|
509
|
-
if (v && !
|
|
510
|
-
(E = s.phone ??
|
|
499
|
+
const v = !!(c != null && c.checked), r = (((l = s.phone) == null ? void 0 : l.value) ?? (w == null ? void 0 : w.value) ?? "").trim();
|
|
500
|
+
if (v && !r) {
|
|
501
|
+
(E = s.phone ?? w) == null || E.focus();
|
|
511
502
|
return;
|
|
512
503
|
}
|
|
513
|
-
if (
|
|
514
|
-
|
|
504
|
+
if (a && ((m = e.topics) != null && m.length) && !a.value) {
|
|
505
|
+
a.focus();
|
|
515
506
|
return;
|
|
516
507
|
}
|
|
517
508
|
b.disabled = !0, this.completePreChat(), (I = (k = this.h).onPreChat) == null || I.call(k, {
|
|
518
|
-
...(
|
|
509
|
+
...(f = s.name) != null && f.value.trim() ? { name: s.name.value.trim() } : {},
|
|
519
510
|
...h ? { email: h } : {},
|
|
520
|
-
...
|
|
521
|
-
...
|
|
511
|
+
...r ? { phone: r } : {},
|
|
512
|
+
...a != null && a.value ? { topic: a.value } : {},
|
|
522
513
|
...v ? { callback: !0 } : {}
|
|
523
514
|
});
|
|
524
515
|
}), i.append(b), this.preChatPanel.append(i);
|
|
@@ -544,11 +535,11 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
544
535
|
this.csatPanel.replaceChildren(), this.csatPanel.append(o("div", "ocw-csat-title", "How did we do?"));
|
|
545
536
|
const e = o("div", "ocw-csat-stars"), i = [];
|
|
546
537
|
for (let s = 1; s <= 5; s++) {
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
var
|
|
550
|
-
this.csatSubmitted = !0, this.csatPanel.replaceChildren(o("div", "ocw-csat-done", `Thanks for your ${s}★ rating!`)), (
|
|
551
|
-
}), i.push(
|
|
538
|
+
const a = o("button", "ocw-csat-star", "★");
|
|
539
|
+
a.dataset.score = String(s), a.addEventListener("mouseenter", () => i.forEach((c, w) => c.classList.toggle("lit", w < s))), a.addEventListener("mouseleave", () => i.forEach((c) => c.classList.remove("lit"))), a.addEventListener("click", () => {
|
|
540
|
+
var c, w;
|
|
541
|
+
this.csatSubmitted = !0, this.csatPanel.replaceChildren(o("div", "ocw-csat-done", `Thanks for your ${s}★ rating!`)), (w = (c = this.h).onCsat) == null || w.call(c, s);
|
|
542
|
+
}), i.push(a), e.append(a);
|
|
552
543
|
}
|
|
553
544
|
this.csatPanel.append(e);
|
|
554
545
|
}
|
|
@@ -564,9 +555,9 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
564
555
|
drawStroke(e) {
|
|
565
556
|
const i = this.cobrowseCanvas.getContext("2d");
|
|
566
557
|
if (!i || e.points.length < 2) return;
|
|
567
|
-
const s = this.cobrowseCanvas.width,
|
|
568
|
-
i.strokeStyle = e.color, i.lineWidth = Math.max(1, e.width * Math.min(s,
|
|
569
|
-
for (const
|
|
558
|
+
const s = this.cobrowseCanvas.width, a = this.cobrowseCanvas.height;
|
|
559
|
+
i.strokeStyle = e.color, i.lineWidth = Math.max(1, e.width * Math.min(s, a)), i.lineJoin = "round", i.lineCap = "round", i.beginPath(), i.moveTo(e.points[0].x * s, e.points[0].y * a);
|
|
560
|
+
for (const c of e.points.slice(1)) i.lineTo(c.x * s, c.y * a);
|
|
570
561
|
i.stroke();
|
|
571
562
|
}
|
|
572
563
|
redrawCobrowse() {
|
|
@@ -579,38 +570,38 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
579
570
|
}
|
|
580
571
|
bindCobrowsePointerEvents() {
|
|
581
572
|
let e = !1, i = [];
|
|
582
|
-
const s = (
|
|
583
|
-
const b = this.cobrowseCanvas.getBoundingClientRect(), d = b.width > 0 ? (
|
|
573
|
+
const s = (w) => {
|
|
574
|
+
const b = this.cobrowseCanvas.getBoundingClientRect(), d = b.width > 0 ? (w.clientX - b.left) / b.width : 0, h = b.height > 0 ? (w.clientY - b.top) / b.height : 0;
|
|
584
575
|
return { x: Math.min(1, Math.max(0, d)), y: Math.min(1, Math.max(0, h)) };
|
|
585
|
-
},
|
|
586
|
-
this.cobrowseCanvas.addEventListener("pointerdown", (
|
|
587
|
-
this.cobrowseActive && (e = !0, i = [s(
|
|
588
|
-
}), this.cobrowseCanvas.addEventListener("pointermove", (
|
|
589
|
-
e && (i.push(s(
|
|
576
|
+
}, a = 6e-3;
|
|
577
|
+
this.cobrowseCanvas.addEventListener("pointerdown", (w) => {
|
|
578
|
+
this.cobrowseActive && (e = !0, i = [s(w)], this.cobrowseCanvas.setPointerCapture(w.pointerId));
|
|
579
|
+
}), this.cobrowseCanvas.addEventListener("pointermove", (w) => {
|
|
580
|
+
e && (i.push(s(w)), this.redrawCobrowse(), this.drawStroke({ points: i, color: this.cobrowseColor, width: a }));
|
|
590
581
|
});
|
|
591
|
-
const
|
|
582
|
+
const c = (w) => {
|
|
592
583
|
var b, d;
|
|
593
584
|
if (e) {
|
|
594
|
-
e = !1, i.length > 1 && ((d = (b = this.h).onAnnotate) == null || d.call(b, { id: `an_${Date.now()}_${Math.random().toString(36).slice(2)}`, points: i, color: this.cobrowseColor, width:
|
|
585
|
+
e = !1, i.length > 1 && ((d = (b = this.h).onAnnotate) == null || d.call(b, { id: `an_${Date.now()}_${Math.random().toString(36).slice(2)}`, points: i, color: this.cobrowseColor, width: a })), i = [];
|
|
595
586
|
try {
|
|
596
|
-
this.cobrowseCanvas.releasePointerCapture(
|
|
587
|
+
this.cobrowseCanvas.releasePointerCapture(w.pointerId);
|
|
597
588
|
} catch {
|
|
598
589
|
}
|
|
599
590
|
}
|
|
600
591
|
};
|
|
601
|
-
this.cobrowseCanvas.addEventListener("pointerup",
|
|
592
|
+
this.cobrowseCanvas.addEventListener("pointerup", c), this.cobrowseCanvas.addEventListener("pointercancel", c);
|
|
602
593
|
}
|
|
603
594
|
buildSubjectCard(e) {
|
|
604
595
|
if (this.subjectBuilt) return;
|
|
605
|
-
const i = e.subject, s = this.cfg.subject,
|
|
606
|
-
if (!
|
|
607
|
-
this.subjectBuilt = !0, this.subjectCard.replaceChildren(), this.subjectCard.append(o("div", "ocw-subject-title",
|
|
608
|
-
const
|
|
609
|
-
if (i) for (const [b, d] of Object.entries(i.fields))
|
|
610
|
-
else for (const b of (s == null ? void 0 : s.tags) ?? [])
|
|
611
|
-
|
|
612
|
-
const
|
|
613
|
-
|
|
596
|
+
const i = e.subject, s = this.cfg.subject, a = (i == null ? void 0 : i.title) ?? (s == null ? void 0 : s.title);
|
|
597
|
+
if (!a) return;
|
|
598
|
+
this.subjectBuilt = !0, this.subjectCard.replaceChildren(), this.subjectCard.append(o("div", "ocw-subject-title", a)), s != null && s.subtitle && this.subjectCard.append(o("div", "ocw-subject-sub", s.subtitle));
|
|
599
|
+
const c = o("div", "ocw-tags");
|
|
600
|
+
if (i) for (const [b, d] of Object.entries(i.fields)) c.append(o("span", "ocw-tag", `${b}: ${d}`));
|
|
601
|
+
else for (const b of (s == null ? void 0 : s.tags) ?? []) c.append(o("span", "ocw-tag", b));
|
|
602
|
+
c.childNodes.length && this.subjectCard.append(c);
|
|
603
|
+
const w = (i == null ? void 0 : i.state) ?? (s == null ? void 0 : s.status);
|
|
604
|
+
w && (this.statusBadge.textContent = w, this.statusBadge.style.display = "inline-flex");
|
|
614
605
|
}
|
|
615
606
|
chipEl(e) {
|
|
616
607
|
const i = o("button", "ocw-chip", e.icon ? `${e.icon} ${e.label}` : e.label);
|
|
@@ -622,14 +613,14 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
622
613
|
/** In-widget confirmation modal (replaces window.confirm). */
|
|
623
614
|
confirm(e) {
|
|
624
615
|
return new Promise((i) => {
|
|
625
|
-
const s = o("div", "ocw-modal"),
|
|
626
|
-
|
|
627
|
-
const
|
|
616
|
+
const s = o("div", "ocw-modal"), a = o("div", "ocw-modal-card");
|
|
617
|
+
a.append(o("div", "ocw-modal-title", e)), a.append(o("div", "ocw-modal-body", `Confirm “${e}”?`));
|
|
618
|
+
const c = o("div", "ocw-modal-actions"), w = o("button", "ocw-modal-cancel", "Cancel"), b = o("button", "ocw-modal-ok", "Confirm"), d = (h) => {
|
|
628
619
|
s.remove(), i(h);
|
|
629
620
|
};
|
|
630
|
-
|
|
621
|
+
w.addEventListener("click", () => d(!1)), b.addEventListener("click", () => d(!0)), s.addEventListener("click", (h) => {
|
|
631
622
|
h.target === s && d(!1);
|
|
632
|
-
}),
|
|
623
|
+
}), c.append(w, b), a.append(c), s.append(a), this.root.append(s), b.focus();
|
|
633
624
|
});
|
|
634
625
|
}
|
|
635
626
|
/** Inline form for a form-effect action: typed inputs (date picker, number,
|
|
@@ -643,51 +634,51 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
643
634
|
for (const h of e.input ?? []) {
|
|
644
635
|
const v = o("label", "ocw-form-row");
|
|
645
636
|
if (v.append(o("span", "ocw-form-lbl", h.label)), h.type === "select" && ((b = h.options) != null && b.length)) {
|
|
646
|
-
const
|
|
647
|
-
h.required ||
|
|
637
|
+
const r = o("select", "ocw-form-input");
|
|
638
|
+
h.required || r.append(o("option", void 0, "— select —"));
|
|
648
639
|
for (const u of h.options) {
|
|
649
640
|
const l = o("option");
|
|
650
|
-
l.value = u, l.textContent = u,
|
|
641
|
+
l.value = u, l.textContent = u, r.append(l);
|
|
651
642
|
}
|
|
652
|
-
h.required && (
|
|
643
|
+
h.required && (r.required = !0), v.append(r), s.set(h.name, r);
|
|
653
644
|
} else {
|
|
654
|
-
const
|
|
655
|
-
|
|
645
|
+
const r = o("input", "ocw-form-input");
|
|
646
|
+
r.type = h.type === "number" ? "number" : h.type === "date" ? "datetime-local" : "text", h.required && (r.required = !0), v.append(r), s.set(h.name, r);
|
|
656
647
|
}
|
|
657
648
|
i.append(v);
|
|
658
649
|
}
|
|
659
|
-
const
|
|
660
|
-
|
|
650
|
+
const a = o("div", "ocw-form-actions"), c = o("button", "ocw-form-cancel", "Cancel"), w = o("button", "ocw-form-submit", "Send");
|
|
651
|
+
c.addEventListener("click", () => this.formHost.replaceChildren()), w.addEventListener("click", () => {
|
|
661
652
|
const h = {};
|
|
662
|
-
for (const [v,
|
|
663
|
-
if (
|
|
664
|
-
|
|
653
|
+
for (const [v, r] of s) {
|
|
654
|
+
if (r.required && !r.value) {
|
|
655
|
+
r.style.borderColor = "#e5484d";
|
|
665
656
|
return;
|
|
666
657
|
}
|
|
667
|
-
h[v] =
|
|
658
|
+
h[v] = r.type === "number" ? Number(r.value) : r.value;
|
|
668
659
|
}
|
|
669
660
|
this.formHost.replaceChildren(), this.h.onInvoke(e.id, h);
|
|
670
|
-
}),
|
|
661
|
+
}), a.append(c, w), i.append(a), this.formHost.append(i), (d = s.values().next().value) == null || d.focus();
|
|
671
662
|
}
|
|
672
663
|
messageEl(e, i) {
|
|
673
|
-
var
|
|
664
|
+
var r;
|
|
674
665
|
if (e.senderRole === "system") {
|
|
675
666
|
const u = o("div", "ocw-sys");
|
|
676
667
|
return u.textContent = e.deletedAt ? "message deleted" : ie(e.content), u;
|
|
677
668
|
}
|
|
678
|
-
const s = e.senderId === this.me,
|
|
679
|
-
!s && !
|
|
680
|
-
const
|
|
669
|
+
const s = e.senderId === this.me, a = !!e.internal, c = o("div", `ocw-row ${a ? "ocw-note mine" : s ? "mine" : "theirs"} ${e.senderRole === "bot" ? "ocw-bot" : ""}`);
|
|
670
|
+
!s && !a && c.append(o("div", "ocw-dot", e.senderRole === "bot" ? "🤖" : "🧑"));
|
|
671
|
+
const w = o("div"), b = o("div", "ocw-bubble-wrap");
|
|
681
672
|
if (e.replyToId) {
|
|
682
673
|
const u = o("div", "ocw-reply-to", "↩ replying to a message");
|
|
683
|
-
u.style.cssText = "font-size:11px;color:var(--ocw-mut);margin-bottom:2px;font-style:italic",
|
|
674
|
+
u.style.cssText = "font-size:11px;color:var(--ocw-mut);margin-bottom:2px;font-style:italic", w.append(u);
|
|
684
675
|
}
|
|
685
676
|
const d = o("div", "ocw-bubble");
|
|
686
677
|
let h = null;
|
|
687
678
|
if (e.deletedAt) d.append(o("span", "ocw-deleted", "message deleted"));
|
|
688
679
|
else if (e.content.kind === "attachment") {
|
|
689
680
|
const u = e.content;
|
|
690
|
-
if ((
|
|
681
|
+
if ((r = u.mime) != null && r.startsWith("image/")) {
|
|
691
682
|
const l = document.createElement("img");
|
|
692
683
|
l.src = u.url, l.alt = u.name ?? "image", l.style.cssText = "max-width:220px;max-height:160px;border-radius:10px;display:block;cursor:pointer", l.addEventListener("click", () => window.open(u.url, "_blank")), d.append(l);
|
|
693
684
|
} else {
|
|
@@ -697,13 +688,13 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
697
688
|
} else if (e.content.kind === "appointment") {
|
|
698
689
|
const u = e.content, l = o("div", "ocw-appt");
|
|
699
690
|
l.append(o("div", "ocw-appt-title", `📅 ${u.title}`)), l.append(o("div", "ocw-appt-time", new Date(u.startIso).toLocaleString() + " – " + new Date(u.endIso).toLocaleTimeString())), u.location && l.append(o("div", "ocw-appt-loc", `📍 ${u.location}`)), u.description && l.append(o("div", "ocw-appt-desc", u.description));
|
|
700
|
-
const E = o("div", "ocw-appt-links"),
|
|
701
|
-
|
|
702
|
-
const
|
|
703
|
-
|
|
691
|
+
const E = o("div", "ocw-appt-links"), m = document.createElement("a");
|
|
692
|
+
m.href = u.googleUrl, m.target = "_blank", m.rel = "noopener", m.className = "ocw-appt-btn", m.textContent = "📅 Add to Google Calendar";
|
|
693
|
+
const f = document.createElement("a");
|
|
694
|
+
f.href = u.icalUrl, f.download = `${u.title}.ics`, f.className = "ocw-appt-btn ocw-appt-btn-sec", f.textContent = "🍎 Apple / iCal", E.append(m, f), l.append(E), d.append(l);
|
|
704
695
|
} else
|
|
705
696
|
h = document.createTextNode(ie(e.content)), d.append(h), e.editedAt && d.append(o("span", "ocw-edited", "(edited)"));
|
|
706
|
-
if (b.append(d), !s && !
|
|
697
|
+
if (b.append(d), !s && !a && this.h.onTranslate && e.content.kind === "text" && !e.deletedAt && e.seq > 0 && h) {
|
|
707
698
|
const u = e.content.text;
|
|
708
699
|
if (u.trim()) {
|
|
709
700
|
const l = o("button", "ocw-translate-btn", "🌐");
|
|
@@ -712,19 +703,19 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
712
703
|
this.showingTranslation.delete(e.id), h.textContent = u, l.textContent = "🌐", l.title = "Translate";
|
|
713
704
|
return;
|
|
714
705
|
}
|
|
715
|
-
const
|
|
716
|
-
if (
|
|
717
|
-
this.showingTranslation.add(e.id), h.textContent =
|
|
706
|
+
const m = this.translationCache.get(e.id);
|
|
707
|
+
if (m !== void 0) {
|
|
708
|
+
this.showingTranslation.add(e.id), h.textContent = m, l.textContent = "↩", l.title = "Show original";
|
|
718
709
|
return;
|
|
719
710
|
}
|
|
720
|
-
l.textContent = "⏳", this.h.onTranslate(u).then((
|
|
721
|
-
if (
|
|
711
|
+
l.textContent = "⏳", this.h.onTranslate(u).then((f) => {
|
|
712
|
+
if (f === null) {
|
|
722
713
|
l.textContent = "⚠️", l.title = "Translation unavailable", setTimeout(() => {
|
|
723
714
|
l.textContent = "🌐", l.title = "Translate";
|
|
724
715
|
}, 1500);
|
|
725
716
|
return;
|
|
726
717
|
}
|
|
727
|
-
this.translationCache.set(e.id,
|
|
718
|
+
this.translationCache.set(e.id, f), this.showingTranslation.add(e.id), h.textContent = f, l.textContent = "↩", l.title = "Show original";
|
|
728
719
|
});
|
|
729
720
|
}), b.append(l);
|
|
730
721
|
}
|
|
@@ -735,21 +726,21 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
735
726
|
const l = o("button", void 0, "✏️");
|
|
736
727
|
l.title = "Edit", l.addEventListener("click", (E) => {
|
|
737
728
|
E.stopPropagation();
|
|
738
|
-
const
|
|
739
|
-
|
|
729
|
+
const m = ie(e.content), f = document.createElement("textarea");
|
|
730
|
+
f.value = m, f.rows = Math.min(4, Math.ceil(m.length / 40) + 1), f.style.cssText = "width:100%;resize:vertical;border:1px solid var(--ocw-accent);border-radius:8px;padding:6px 10px;font:inherit;font-size:14px;background:#fff;color:#1c1b1a;box-sizing:border-box";
|
|
740
731
|
const k = o("button", "ocw-form-submit", "Save");
|
|
741
732
|
k.style.cssText = "margin-top:6px;padding:5px 14px;font-size:13px";
|
|
742
733
|
const I = o("button", "ocw-form-cancel", "Cancel");
|
|
743
734
|
I.style.cssText = "margin-top:6px;padding:5px 10px;font-size:13px";
|
|
744
|
-
const
|
|
745
|
-
|
|
735
|
+
const P = o("div");
|
|
736
|
+
P.style.cssText = "display:flex;gap:6px;justify-content:flex-end", P.append(I, k);
|
|
746
737
|
const C = o("div");
|
|
747
|
-
C.append(
|
|
748
|
-
const R = () => d.replaceChildren(h ?? document.createTextNode(
|
|
738
|
+
C.append(f, P), d.replaceChildren(C), f.focus(), f.select();
|
|
739
|
+
const R = () => d.replaceChildren(h ?? document.createTextNode(m));
|
|
749
740
|
I.addEventListener("click", R), k.addEventListener("click", () => {
|
|
750
|
-
const A =
|
|
751
|
-
A && A !==
|
|
752
|
-
}),
|
|
741
|
+
const A = f.value.trim();
|
|
742
|
+
A && A !== m && this.h.onEdit(e.id, A), R();
|
|
743
|
+
}), f.addEventListener("keydown", (A) => {
|
|
753
744
|
A.key === "Enter" && !A.shiftKey && (A.preventDefault(), k.click()), A.key === "Escape" && R();
|
|
754
745
|
});
|
|
755
746
|
}), u.append(l);
|
|
@@ -762,43 +753,43 @@ Message: ${a.value}`), this.offlinePanel.replaceChildren(o("div", "ocw-offline-t
|
|
|
762
753
|
}
|
|
763
754
|
b.append(u);
|
|
764
755
|
}
|
|
765
|
-
if (
|
|
756
|
+
if (w.append(b), this.h.onReact && !e.deletedAt && e.seq > 0) {
|
|
766
757
|
const u = o("div", "ocw-react-wrap"), l = o("div", "ocw-react");
|
|
767
758
|
if (e.reactions && Object.keys(e.reactions).length)
|
|
768
|
-
for (const [
|
|
769
|
-
const I = o("button", `ocw-react-pill${k.includes(this.me) ? " mine" : ""}`, `${
|
|
759
|
+
for (const [f, k] of Object.entries(e.reactions)) {
|
|
760
|
+
const I = o("button", `ocw-react-pill${k.includes(this.me) ? " mine" : ""}`, `${f} ${k.length}`);
|
|
770
761
|
I.addEventListener("click", () => {
|
|
771
|
-
var
|
|
772
|
-
return (C = (
|
|
762
|
+
var P, C;
|
|
763
|
+
return (C = (P = this.h).onReact) == null ? void 0 : C.call(P, e.id, f, k.includes(this.me));
|
|
773
764
|
}), l.append(I);
|
|
774
765
|
}
|
|
775
|
-
const E = o("button", "ocw-react-btn", "+"),
|
|
776
|
-
for (const
|
|
777
|
-
const k = o("button", void 0,
|
|
766
|
+
const E = o("button", "ocw-react-btn", "+"), m = o("div", "ocw-react-picker");
|
|
767
|
+
for (const f of He) {
|
|
768
|
+
const k = o("button", void 0, f);
|
|
778
769
|
k.addEventListener("click", (I) => {
|
|
779
|
-
var C, R, A,
|
|
770
|
+
var C, R, A, N;
|
|
780
771
|
I.stopPropagation();
|
|
781
|
-
const
|
|
782
|
-
(
|
|
783
|
-
}),
|
|
772
|
+
const P = (R = (C = e.reactions) == null ? void 0 : C[f]) == null ? void 0 : R.includes(this.me);
|
|
773
|
+
(N = (A = this.h).onReact) == null || N.call(A, e.id, f, !!P), m.style.display = "none";
|
|
774
|
+
}), m.append(k);
|
|
784
775
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const k =
|
|
788
|
-
|
|
789
|
-
|
|
776
|
+
m.style.display = "none", E.addEventListener("click", (f) => {
|
|
777
|
+
f.stopPropagation();
|
|
778
|
+
const k = m.style.display === "none";
|
|
779
|
+
m.style.display = k ? "flex" : "none", k && document.addEventListener("click", () => {
|
|
780
|
+
m.style.display = "none";
|
|
790
781
|
}, { once: !0 });
|
|
791
|
-
}), l.append(E), u.append(l,
|
|
792
|
-
} else e.reactions && Object.keys(e.reactions).length &&
|
|
782
|
+
}), l.append(E), u.append(l, m), w.append(u);
|
|
783
|
+
} else e.reactions && Object.keys(e.reactions).length && w.append(o("div", "ocw-react", Object.entries(e.reactions).map(([u, l]) => `${u}${l.length}`).join(" ")));
|
|
793
784
|
const v = o("div", "ocw-time ocw-meta", Ve(e.ts));
|
|
794
785
|
if (s && e.status) {
|
|
795
|
-
const u = o("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`,
|
|
786
|
+
const u = o("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`, Ge(e.status));
|
|
796
787
|
v.append(u);
|
|
797
788
|
}
|
|
798
|
-
return s && e.seq > 0 && i.lastReadByOthers >= e.seq && v.append(o("span", "ocw-seen", " · Seen")),
|
|
789
|
+
return s && e.seq > 0 && i.lastReadByOthers >= e.seq && v.append(o("span", "ocw-seen", " · Seen")), w.append(v), c.append(w), c;
|
|
799
790
|
}
|
|
800
791
|
}
|
|
801
|
-
function
|
|
792
|
+
function Ge(t) {
|
|
802
793
|
switch (t) {
|
|
803
794
|
case "read":
|
|
804
795
|
return "✓✓";
|
|
@@ -810,12 +801,12 @@ function Ke(t) {
|
|
|
810
801
|
return "🕓";
|
|
811
802
|
}
|
|
812
803
|
}
|
|
813
|
-
const
|
|
814
|
-
function
|
|
804
|
+
const O = /* @__PURE__ */ new WeakMap(), X = /* @__PURE__ */ new Map();
|
|
805
|
+
function me(t) {
|
|
815
806
|
return `relay-launcher::${t.profileId}::${t.subjectId ?? ""}`;
|
|
816
807
|
}
|
|
817
808
|
let F = null;
|
|
818
|
-
function
|
|
809
|
+
function Ye() {
|
|
819
810
|
if (F && F.state !== "closed") return F;
|
|
820
811
|
try {
|
|
821
812
|
return F = new AudioContext(), F;
|
|
@@ -825,25 +816,25 @@ function Ge() {
|
|
|
825
816
|
}
|
|
826
817
|
function tt(t) {
|
|
827
818
|
var e;
|
|
828
|
-
(e =
|
|
819
|
+
(e = O.get(t)) == null || e.close(), O.delete(t);
|
|
829
820
|
}
|
|
830
821
|
function ot(t) {
|
|
831
822
|
var le, de, pe, he, ue;
|
|
832
|
-
|
|
833
|
-
const e =
|
|
823
|
+
O.has(t.el) && (O.get(t.el).close(), O.delete(t.el)), t.launcher && ((le = X.get(me(t))) == null || le.close());
|
|
824
|
+
const e = Pe();
|
|
834
825
|
let i, s = !1;
|
|
835
|
-
const
|
|
836
|
-
let d = new Me(
|
|
837
|
-
const h = t.subjectId ? `${
|
|
838
|
-
let
|
|
826
|
+
const a = t.token ?? t.userId ?? e, c = a !== e ? e : void 0, { wsUrl: w, httpBase: b } = Ae(t.url, t.apiUrl);
|
|
827
|
+
let d = new Me(a);
|
|
828
|
+
const h = t.subjectId ? `${a}::${t.subjectId}` : a, v = new $e(h);
|
|
829
|
+
let r, u = !1, l = null, E = null, m = null, f = null;
|
|
839
830
|
!t.launcher && !t.el.style.height && t.el.clientHeight === 0 && (t.el.style.width = t.el.style.width || "100%", t.el.style.height = "600px");
|
|
840
831
|
for (const n of v.load()) d.addOptimistic(n.clientMsgId, n.content);
|
|
841
|
-
let k = null, I = null,
|
|
832
|
+
let k = null, I = null, P = 0, C = !t.launcher;
|
|
842
833
|
if (t.launcher) {
|
|
843
834
|
const p = (t.position ?? "bottom-right").includes("right");
|
|
844
835
|
k = document.createElement("div"), k.style.cssText = `position:fixed;${p ? "right:20px" : "left:20px"};bottom:20px;z-index:9999;display:flex;flex-direction:column;align-items:${p ? "flex-end" : "flex-start"};gap:12px`;
|
|
845
|
-
const x = document.createElement("div"),
|
|
846
|
-
t.el.classList.toggle("ocw-fs",
|
|
836
|
+
const x = document.createElement("div"), j = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(max-width: 479px)") : null, V = (L) => {
|
|
837
|
+
t.el.classList.toggle("ocw-fs", L), x.style.cssText = L ? [
|
|
847
838
|
"position:fixed",
|
|
848
839
|
"inset:0",
|
|
849
840
|
"width:100%",
|
|
@@ -872,9 +863,9 @@ function ot(t) {
|
|
|
872
863
|
"transform:scale(.95)"
|
|
873
864
|
].join(";");
|
|
874
865
|
};
|
|
875
|
-
V((
|
|
876
|
-
const
|
|
877
|
-
|
|
866
|
+
V((j == null ? void 0 : j.matches) ?? !1);
|
|
867
|
+
const K = (L) => V(L.matches);
|
|
868
|
+
j == null || j.addEventListener("change", K), l = j, E = K, t.el.style.cssText = "width:100%;height:100%;overflow:hidden", x.append(t.el);
|
|
878
869
|
const Q = '<svg viewBox="0 0 24 24" width="26" height="26" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', Z = '<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>', M = document.createElement("button");
|
|
879
870
|
M.type = "button", M.style.cssText = [
|
|
880
871
|
"width:56px;height:56px;border-radius:50%",
|
|
@@ -889,11 +880,11 @@ function ot(t) {
|
|
|
889
880
|
}, M.onmouseleave = () => {
|
|
890
881
|
M.style.transform = "scale(1)";
|
|
891
882
|
}, I = document.createElement("span"), I.style.cssText = "position:absolute;top:-4px;right:-4px;background:#ef4444;color:#fff;border-radius:50%;width:20px;height:20px;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center";
|
|
892
|
-
const
|
|
883
|
+
const G = () => {
|
|
893
884
|
M.innerHTML = C ? Z : Q, M.setAttribute("aria-label", C ? "Close chat" : "Open chat"), M.setAttribute("aria-expanded", String(C)), M.append(I);
|
|
894
885
|
};
|
|
895
|
-
|
|
896
|
-
const ee = `ocw-teaser-dismissed::${t.profileId}`,
|
|
886
|
+
G(), k.append(x, M), document.body.append(k);
|
|
887
|
+
const ee = `ocw-teaser-dismissed::${t.profileId}`, Y = typeof t.launcherMessage == "string" ? { title: t.launcherMessage } : t.launcherMessage;
|
|
897
888
|
let z = null;
|
|
898
889
|
const Se = () => {
|
|
899
890
|
try {
|
|
@@ -902,13 +893,13 @@ function ot(t) {
|
|
|
902
893
|
return !1;
|
|
903
894
|
}
|
|
904
895
|
}, ze = '<svg viewBox="0 0 24 24" width="15" height="15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', fe = () => {
|
|
905
|
-
const
|
|
906
|
-
if (!(!!(
|
|
896
|
+
const L = Y != null && Y.title ? Y : d.launcherMessage ?? void 0;
|
|
897
|
+
if (!(!!(L != null && L.title) && !C && !Se())) {
|
|
907
898
|
z && (z.remove(), z = null);
|
|
908
899
|
return;
|
|
909
900
|
}
|
|
910
901
|
if (z) return;
|
|
911
|
-
z = document.createElement("div"), z.setAttribute("role", "button"), z.setAttribute("tabindex", "0"), z.setAttribute("aria-label",
|
|
902
|
+
z = document.createElement("div"), z.setAttribute("role", "button"), z.setAttribute("tabindex", "0"), z.setAttribute("aria-label", L.title), z.style.cssText = [
|
|
912
903
|
"max-width:280px",
|
|
913
904
|
"background:#fff",
|
|
914
905
|
"border-radius:14px",
|
|
@@ -921,60 +912,60 @@ function ot(t) {
|
|
|
921
912
|
"animation:ocw-teaser-in .22s ease-out"
|
|
922
913
|
].join(";");
|
|
923
914
|
const oe = document.createElement("div");
|
|
924
|
-
if (oe.textContent =
|
|
915
|
+
if (oe.textContent = L.title, oe.style.cssText = "font-size:15px;font-weight:600;color:#111;line-height:1.35", z.append(oe), L.subtitle) {
|
|
925
916
|
const D = document.createElement("div");
|
|
926
917
|
D.style.cssText = "display:flex;align-items:center;gap:6px;margin-top:6px;font-size:13px;color:#6b7280";
|
|
927
918
|
const ne = document.createElement("span");
|
|
928
919
|
ne.innerHTML = ze, ne.style.cssText = `color:${t.accent ?? "#4F63F5"};display:inline-flex`;
|
|
929
920
|
const be = document.createElement("span");
|
|
930
|
-
be.textContent =
|
|
921
|
+
be.textContent = L.subtitle, D.append(ne, be), z.append(D);
|
|
931
922
|
}
|
|
932
|
-
const
|
|
933
|
-
|
|
923
|
+
const H = document.createElement("button");
|
|
924
|
+
H.type = "button", H.setAttribute("aria-label", "Dismiss"), H.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>', H.style.cssText = "position:absolute;top:8px;right:8px;width:24px;height:24px;border:none;border-radius:50%;background:#f3f4f6;color:#6b7280;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0", H.addEventListener("click", (D) => {
|
|
934
925
|
D.stopPropagation();
|
|
935
926
|
try {
|
|
936
927
|
sessionStorage.setItem(ee, "1");
|
|
937
928
|
} catch {
|
|
938
929
|
}
|
|
939
930
|
z && (z.remove(), z = null);
|
|
940
|
-
}), z.append(
|
|
931
|
+
}), z.append(H);
|
|
941
932
|
const we = () => {
|
|
942
|
-
C || (C = !0, te(!0),
|
|
933
|
+
C || (C = !0, te(!0), G(), P = 0, I && (I.style.display = "none"), z && (z.remove(), z = null));
|
|
943
934
|
};
|
|
944
935
|
z.addEventListener("click", we), z.addEventListener("keydown", (D) => {
|
|
945
936
|
(D.key === "Enter" || D.key === " ") && (D.preventDefault(), we());
|
|
946
937
|
}), k.insertBefore(z, M);
|
|
947
938
|
};
|
|
948
939
|
if (!document.getElementById("ocw-teaser-style")) {
|
|
949
|
-
const
|
|
950
|
-
|
|
940
|
+
const L = document.createElement("style");
|
|
941
|
+
L.id = "ocw-teaser-style", L.textContent = "@keyframes ocw-teaser-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}", document.head.append(L);
|
|
951
942
|
}
|
|
952
|
-
|
|
953
|
-
const te = (
|
|
954
|
-
|
|
943
|
+
f = fe, fe();
|
|
944
|
+
const te = (L) => {
|
|
945
|
+
L ? (x.style.display = "flex", requestAnimationFrame(() => {
|
|
955
946
|
x.style.opacity = "1", x.style.transform = "scale(1)";
|
|
956
947
|
})) : (x.style.opacity = "0", x.style.transform = "scale(.95)", setTimeout(() => {
|
|
957
948
|
C || (x.style.display = "none");
|
|
958
949
|
}, 180));
|
|
959
950
|
};
|
|
960
951
|
M.addEventListener("click", () => {
|
|
961
|
-
if (C = !C, te(C),
|
|
962
|
-
|
|
952
|
+
if (C = !C, te(C), G(), C) {
|
|
953
|
+
P = 0, I && (I.style.display = "none");
|
|
963
954
|
try {
|
|
964
955
|
sessionStorage.setItem(ee, "1");
|
|
965
956
|
} catch {
|
|
966
957
|
}
|
|
967
958
|
}
|
|
968
|
-
|
|
969
|
-
}),
|
|
970
|
-
|
|
971
|
-
}, document.addEventListener("keydown",
|
|
959
|
+
f == null || f();
|
|
960
|
+
}), m = (L) => {
|
|
961
|
+
L.key === "Escape" && C && (C = !1, te(!1), G());
|
|
962
|
+
}, document.addEventListener("keydown", m);
|
|
972
963
|
}
|
|
973
964
|
const R = () => {
|
|
974
|
-
C || (
|
|
965
|
+
C || (P++, I && (I.textContent = String(P), I.style.display = "flex"));
|
|
975
966
|
}, A = () => {
|
|
976
967
|
try {
|
|
977
|
-
const n =
|
|
968
|
+
const n = Ye();
|
|
978
969
|
if (!n) return;
|
|
979
970
|
n.state === "suspended" && n.resume().catch(() => {
|
|
980
971
|
});
|
|
@@ -982,24 +973,24 @@ function ot(t) {
|
|
|
982
973
|
p.connect(x), x.connect(n.destination), p.frequency.setValueAtTime(880, n.currentTime), p.frequency.exponentialRampToValueAtTime(440, n.currentTime + 0.15), x.gain.setValueAtTime(0.3, n.currentTime), x.gain.exponentialRampToValueAtTime(1e-3, n.currentTime + 0.3), p.start(), p.stop(n.currentTime + 0.3);
|
|
983
974
|
} catch {
|
|
984
975
|
}
|
|
985
|
-
},
|
|
986
|
-
for (;
|
|
987
|
-
const p =
|
|
976
|
+
}, N = [], U = (n) => {
|
|
977
|
+
for (; N.length; ) {
|
|
978
|
+
const p = N.shift();
|
|
988
979
|
v.add({ clientMsgId: p.clientMsgId, content: p.content, ts: Date.now() }), T.send({ type: "send", conversationId: n, clientMsgId: p.clientMsgId, content: p.content });
|
|
989
980
|
}
|
|
990
981
|
};
|
|
991
982
|
let T;
|
|
992
|
-
const
|
|
993
|
-
let
|
|
983
|
+
const $ = new qe(`ocw-e2e-${t.profileId}`);
|
|
984
|
+
let g = !1;
|
|
994
985
|
const S = [], q = [];
|
|
995
986
|
let se = !1;
|
|
996
987
|
const J = (n, p) => {
|
|
997
|
-
|
|
998
|
-
|
|
988
|
+
$.sealText(p).then((x) => {
|
|
989
|
+
r && T.send({ type: "send", conversationId: r, clientMsgId: n, content: x });
|
|
999
990
|
});
|
|
1000
991
|
}, ye = (n, p, x) => {
|
|
1001
|
-
|
|
1002
|
-
|
|
992
|
+
$.sealText(p, x).then((j) => {
|
|
993
|
+
r && T.send({ type: "send", conversationId: r, clientMsgId: n, content: j });
|
|
1003
994
|
});
|
|
1004
995
|
}, ve = () => {
|
|
1005
996
|
for (; S.length; ) {
|
|
@@ -1014,42 +1005,42 @@ function ot(t) {
|
|
|
1014
1005
|
T.send({ type: "fetchPrekey", targetUserId: n });
|
|
1015
1006
|
}, Ce = t.i18n ?? {}, Te = ["ar", "he", "fa", "ur"], Ee = typeof navigator < "u" ? (navigator.language ?? "").slice(0, 2).toLowerCase() : "";
|
|
1016
1007
|
Te.includes(Ee) && !t.el.dir && (t.el.dir = "rtl", t.el.style.fontFamily = t.el.style.fontFamily || "Tahoma,Arial,system-ui,sans-serif");
|
|
1017
|
-
const
|
|
1008
|
+
const ae = new Oe(), re = `oc_prechat_${t.profileId}_${a.slice(-8)}`, B = new Ke(t.el, a, {
|
|
1018
1009
|
onSend(n) {
|
|
1019
1010
|
const p = `cm_${Math.random().toString(36).slice(2)}`, x = { kind: "text", text: n };
|
|
1020
|
-
d.addOptimistic(p, x),
|
|
1011
|
+
d.addOptimistic(p, x), B.render(d), d.e2e ? $.ready ? J(p, n) : se ? q.push({ clientMsgId: p, text: n }) : (S.push({ clientMsgId: p, text: n }), d.assignedAgentId && ke(d.assignedAgentId)) : r ? (v.add({ clientMsgId: p, content: x, ts: Date.now() }), T.send({ type: "send", conversationId: r, clientMsgId: p, content: x })) : N.push({ clientMsgId: p, content: x });
|
|
1021
1012
|
},
|
|
1022
1013
|
async onAttach(n) {
|
|
1023
|
-
if (!
|
|
1014
|
+
if (!r) return;
|
|
1024
1015
|
const p = `${b}/upload?name=${encodeURIComponent(n.name)}`, x = `cm_${Math.random().toString(36).slice(2)}`;
|
|
1025
|
-
d.addOptimistic(x, { kind: "text", text: `📎 Uploading ${n.name}…` }),
|
|
1016
|
+
d.addOptimistic(x, { kind: "text", text: `📎 Uploading ${n.name}…` }), B.render(d);
|
|
1026
1017
|
try {
|
|
1027
|
-
const
|
|
1018
|
+
const j = await fetch(p, {
|
|
1028
1019
|
method: "POST",
|
|
1029
1020
|
// Use the resolved connection token (a signed JWT, an explicit userId,
|
|
1030
1021
|
// or the anonymous persistent uid) — NOT just opts.token. The server
|
|
1031
1022
|
// requires an Authorization header, and the verifier accepts an
|
|
1032
1023
|
// anonymous id as a guest; keying off opts.token alone meant anonymous
|
|
1033
1024
|
// visitors (the common case) sent no auth and every upload 401'd.
|
|
1034
|
-
headers: { "content-type": n.type, authorization: `Bearer ${
|
|
1025
|
+
headers: { "content-type": n.type, authorization: `Bearer ${a}` },
|
|
1035
1026
|
body: n
|
|
1036
1027
|
});
|
|
1037
|
-
if (!
|
|
1038
|
-
const { url: V, name:
|
|
1039
|
-
T.send({ type: "send", conversationId:
|
|
1040
|
-
} catch (
|
|
1041
|
-
d.addOptimistic(x, { kind: "text", text: `⚠️ Upload failed: ${
|
|
1028
|
+
if (!j.ok) throw new Error(`Upload failed: ${j.status}`);
|
|
1029
|
+
const { url: V, name: K, mime: Q, size: Z } = await j.json();
|
|
1030
|
+
T.send({ type: "send", conversationId: r, clientMsgId: x, content: { kind: "attachment", url: V, name: K, mime: Q, size: Z } });
|
|
1031
|
+
} catch (j) {
|
|
1032
|
+
d.addOptimistic(x, { kind: "text", text: `⚠️ Upload failed: ${j.message}` }), B.render(d);
|
|
1042
1033
|
}
|
|
1043
1034
|
},
|
|
1044
1035
|
onInvoke(n, p) {
|
|
1045
|
-
|
|
1036
|
+
r && T.send({ type: "invoke", conversationId: r, actionId: n, clientInvokeId: `iv_${Math.random().toString(36).slice(2)}`, ...p ? { inputs: p } : {} });
|
|
1046
1037
|
},
|
|
1047
1038
|
onTyping(n, p) {
|
|
1048
|
-
|
|
1039
|
+
r && T.send({ type: "typing", conversationId: r, isTyping: n, ...p ? { preview: p } : {} });
|
|
1049
1040
|
},
|
|
1050
1041
|
onPreChat(n) {
|
|
1051
1042
|
try {
|
|
1052
|
-
localStorage.setItem(
|
|
1043
|
+
localStorage.setItem(re, "1");
|
|
1053
1044
|
} catch {
|
|
1054
1045
|
}
|
|
1055
1046
|
T.send({
|
|
@@ -1066,57 +1057,57 @@ function ot(t) {
|
|
|
1066
1057
|
}
|
|
1067
1058
|
});
|
|
1068
1059
|
const p = n.callback ? `📞 Call-back requested${n.phone ? `: ${n.phone}` : ""}${n.topic ? ` — ${n.topic}` : ""}` : n.topic ? `Topic: ${n.topic}` : "";
|
|
1069
|
-
p &&
|
|
1060
|
+
p && r && !d.e2e && T.send({ type: "send", conversationId: r, clientMsgId: `pc_${Math.random().toString(36).slice(2, 12)}`, content: { kind: "text", text: p } });
|
|
1070
1061
|
},
|
|
1071
1062
|
onDeflectQuery(n) {
|
|
1072
1063
|
if (s) return;
|
|
1073
1064
|
clearTimeout(i);
|
|
1074
1065
|
const p = n.trim();
|
|
1075
1066
|
if (p.length < 3) {
|
|
1076
|
-
|
|
1067
|
+
B.hideDeflection();
|
|
1077
1068
|
return;
|
|
1078
1069
|
}
|
|
1079
1070
|
i = setTimeout(() => {
|
|
1080
|
-
fetch(`${b}/kb/search?profileId=${encodeURIComponent(t.profileId)}&q=${encodeURIComponent(p.slice(0, 200))}`).then((x) => x.ok ? x.json() : { articles: [] }).then((x) =>
|
|
1071
|
+
fetch(`${b}/kb/search?profileId=${encodeURIComponent(t.profileId)}&q=${encodeURIComponent(p.slice(0, 200))}`).then((x) => x.ok ? x.json() : { articles: [] }).then((x) => B.showDeflection(x.articles ?? [])).catch(() => B.hideDeflection());
|
|
1081
1072
|
}, 350);
|
|
1082
1073
|
},
|
|
1083
1074
|
onReadUpTo(n) {
|
|
1084
|
-
|
|
1075
|
+
r && T.send({ type: "read", conversationId: r, seq: n });
|
|
1085
1076
|
},
|
|
1086
1077
|
onLoadMore() {
|
|
1087
|
-
if (!
|
|
1078
|
+
if (!r || !d.e2e) return;
|
|
1088
1079
|
const n = d.messages()[0];
|
|
1089
|
-
n && T.send({ type: "history", conversationId:
|
|
1080
|
+
n && T.send({ type: "history", conversationId: r, beforeSeq: n.seq, limit: 20 });
|
|
1090
1081
|
},
|
|
1091
1082
|
onEdit(n, p) {
|
|
1092
|
-
|
|
1083
|
+
r && T.send({ type: "edit", conversationId: r, messageId: n, content: { kind: "text", text: p } });
|
|
1093
1084
|
},
|
|
1094
1085
|
onDelete(n) {
|
|
1095
|
-
|
|
1086
|
+
r && T.send({ type: "delete", conversationId: r, messageId: n });
|
|
1096
1087
|
},
|
|
1097
1088
|
onReact(n, p, x) {
|
|
1098
|
-
|
|
1089
|
+
r && T.send({ type: "react", conversationId: r, messageId: n, emoji: p, remove: x });
|
|
1099
1090
|
},
|
|
1100
1091
|
onCsat(n) {
|
|
1101
|
-
|
|
1092
|
+
r && fetch(`${b}/conversations/${r}/csat`, {
|
|
1102
1093
|
method: "POST",
|
|
1103
|
-
headers: { "Content-Type": "application/json", Authorization: `Bearer ${
|
|
1094
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${a}` },
|
|
1104
1095
|
body: JSON.stringify({ score: n })
|
|
1105
1096
|
}).catch(() => {
|
|
1106
1097
|
});
|
|
1107
1098
|
},
|
|
1108
1099
|
onAnnotate(n) {
|
|
1109
|
-
|
|
1100
|
+
r && T.send({ type: "annotate", conversationId: r, stroke: n });
|
|
1110
1101
|
},
|
|
1111
1102
|
onAnnotateClear() {
|
|
1112
|
-
|
|
1103
|
+
r && T.send({ type: "annotate_clear", conversationId: r });
|
|
1113
1104
|
},
|
|
1114
1105
|
...t.translateLang ? {
|
|
1115
1106
|
async onTranslate(n) {
|
|
1116
1107
|
try {
|
|
1117
1108
|
const p = await fetch(`${b}/translate`, {
|
|
1118
1109
|
method: "POST",
|
|
1119
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${
|
|
1110
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${a}` },
|
|
1120
1111
|
body: JSON.stringify({ text: n, targetLang: t.translateLang })
|
|
1121
1112
|
});
|
|
1122
1113
|
if (!p.ok) return null;
|
|
@@ -1136,7 +1127,7 @@ function ot(t) {
|
|
|
1136
1127
|
i18n: Ce
|
|
1137
1128
|
});
|
|
1138
1129
|
try {
|
|
1139
|
-
localStorage.getItem(
|
|
1130
|
+
localStorage.getItem(re) && B.completePreChat();
|
|
1140
1131
|
} catch {
|
|
1141
1132
|
}
|
|
1142
1133
|
const ce = t.user && (t.user.name || t.user.email || t.user.avatar || t.user.meta) ? {
|
|
@@ -1151,7 +1142,7 @@ function ot(t) {
|
|
|
1151
1142
|
// server-derived and owner-keyed, so passing it as subjectId from the
|
|
1152
1143
|
// NON-owner side would find-or-create a junk duplicate thread.
|
|
1153
1144
|
...t.kind === "direct" && t.peerId ? { kind: "direct", peerId: t.peerId } : t.subjectId ? { subjectId: t.subjectId } : {},
|
|
1154
|
-
...
|
|
1145
|
+
...c ? { linkFrom: c } : {},
|
|
1155
1146
|
...ce ? { userInfo: ce } : {},
|
|
1156
1147
|
...typeof location < "u" ? { pageUrl: location.href } : {},
|
|
1157
1148
|
...typeof document < "u" && document.title ? { pageTitle: document.title } : {},
|
|
@@ -1162,72 +1153,72 @@ function ot(t) {
|
|
|
1162
1153
|
};
|
|
1163
1154
|
T = new Re({
|
|
1164
1155
|
...t.refreshToken ? { refreshToken: t.refreshToken } : {},
|
|
1165
|
-
url:
|
|
1166
|
-
token:
|
|
1156
|
+
url: w,
|
|
1157
|
+
token: a,
|
|
1167
1158
|
open: Ie,
|
|
1168
1159
|
getCursor: () => d.highestSeq(),
|
|
1169
|
-
onStatusChange: (n, p) =>
|
|
1160
|
+
onStatusChange: (n, p) => B.setConnStatus(n, p),
|
|
1170
1161
|
onFrame(n) {
|
|
1171
|
-
if (
|
|
1172
|
-
if (
|
|
1162
|
+
if (ae.apply(n), n.type === "opened") {
|
|
1163
|
+
if (r = n.conversation.id, !u) {
|
|
1173
1164
|
u = !0;
|
|
1174
1165
|
for (const p of v.load())
|
|
1175
|
-
T.send({ type: "send", conversationId:
|
|
1166
|
+
T.send({ type: "send", conversationId: r, clientMsgId: p.clientMsgId, content: p.content });
|
|
1176
1167
|
}
|
|
1177
|
-
|
|
1168
|
+
Be(w, a, r, d, B, b), N.length && U(r);
|
|
1178
1169
|
}
|
|
1179
1170
|
if (n.type === "ack" && v.remove(n.clientMsgId), n.type === "prekeyBundle") {
|
|
1180
|
-
n.bundle && (se = !0,
|
|
1171
|
+
n.bundle && (se = !0, $.x3dhSendTo(n.bundle).then((p) => {
|
|
1181
1172
|
const x = [...S.splice(0), ...q.splice(0)];
|
|
1182
|
-
for (const
|
|
1183
|
-
|
|
1173
|
+
for (const j of x) ye(j.clientMsgId, j.text, p);
|
|
1174
|
+
B.render(d);
|
|
1184
1175
|
}));
|
|
1185
1176
|
return;
|
|
1186
1177
|
}
|
|
1187
1178
|
if (n.type === "message" && d.e2e) {
|
|
1188
|
-
const p =
|
|
1189
|
-
if (p &&
|
|
1190
|
-
|
|
1191
|
-
await
|
|
1179
|
+
const p = Ne(n.message.content);
|
|
1180
|
+
if (p && !$.ready) {
|
|
1181
|
+
$.x3dhReceiveFrom(p.x3dhIK, p.x3dhEK, p.x3dhSPK).then(async () => {
|
|
1182
|
+
await $.openFrame(n), d.apply(n), B.render(d);
|
|
1192
1183
|
});
|
|
1193
1184
|
return;
|
|
1194
1185
|
}
|
|
1195
1186
|
}
|
|
1196
1187
|
if (n.type === "peerkey") {
|
|
1197
|
-
|
|
1198
|
-
ve(),
|
|
1188
|
+
$.onPeerKey(n.key).then(() => {
|
|
1189
|
+
ve(), B.render(d);
|
|
1199
1190
|
});
|
|
1200
1191
|
return;
|
|
1201
1192
|
}
|
|
1202
1193
|
(async () => {
|
|
1203
|
-
if (d.e2e && await
|
|
1204
|
-
|
|
1205
|
-
const p = await
|
|
1194
|
+
if (d.e2e && await $.openFrame(n), d.apply(n), n.type === "manifest" && (f == null || f()), n.type === "message" && n.message.senderId !== a && !n.message.internal && (R(), A()), d.e2e && r && !g) {
|
|
1195
|
+
g = !0;
|
|
1196
|
+
const p = await $.initX3DH();
|
|
1206
1197
|
T.send({ type: "uploadPrekeys", ...p });
|
|
1207
|
-
const x = await
|
|
1208
|
-
T.send({ type: "pubkey", conversationId:
|
|
1198
|
+
const x = await $.begin();
|
|
1199
|
+
T.send({ type: "pubkey", conversationId: r, key: x });
|
|
1209
1200
|
}
|
|
1210
|
-
|
|
1201
|
+
B.render(d);
|
|
1211
1202
|
})();
|
|
1212
1203
|
}
|
|
1213
|
-
}), T.connect(),
|
|
1214
|
-
const _ = t.launcher ?
|
|
1215
|
-
s = !0, clearTimeout(i), T.close(), k == null || k.remove(),
|
|
1204
|
+
}), T.connect(), B.render(d);
|
|
1205
|
+
const _ = t.launcher ? me(t) : null, W = { close: () => {
|
|
1206
|
+
s = !0, clearTimeout(i), T.close(), k == null || k.remove(), B.destroy(), ae.destroy(), l && E && l.removeEventListener("change", E), m && (document.removeEventListener("keydown", m), m = null), O.delete(t.el), _ && X.get(_) === W && X.delete(_);
|
|
1216
1207
|
} };
|
|
1217
|
-
return
|
|
1208
|
+
return O.set(t.el, W), _ && X.set(_, W), W;
|
|
1218
1209
|
}
|
|
1219
1210
|
export {
|
|
1220
1211
|
Me as ChatStore,
|
|
1221
1212
|
Re as ConnectionManager,
|
|
1222
1213
|
qe as E2ESession,
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1214
|
+
$e as PersistentOutbox,
|
|
1215
|
+
Ke as Renderer,
|
|
1216
|
+
rt as asConversationId,
|
|
1217
|
+
Ne as extractX3DHInit,
|
|
1227
1218
|
st as httpBaseFromWsUrl,
|
|
1228
1219
|
ot as mount,
|
|
1229
1220
|
Ae as resolveRelayUrls,
|
|
1230
|
-
|
|
1221
|
+
Be as restoreHistory,
|
|
1231
1222
|
tt as unmount
|
|
1232
1223
|
};
|
|
1233
1224
|
//# sourceMappingURL=index.js.map
|