@sphoro/bugcatch-web-sdk 0.18.0 → 0.20.0
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 +51 -3
- package/dist/bugcatch-call.es.js +201 -200
- package/dist/bugcatch-call.es.js.map +1 -1
- package/dist/bugcatch-call.umd.js +1 -1
- package/dist/bugcatch-call.umd.js.map +1 -1
- package/dist/bugcatch-core.es.js +1085 -1007
- package/dist/bugcatch-core.es.js.map +1 -1
- package/dist/bugcatch-panel.es.js +1337 -1067
- package/dist/bugcatch-panel.es.js.map +1 -1
- package/dist/bugcatch-panel.umd.js +427 -315
- package/dist/bugcatch-panel.umd.js.map +1 -1
- package/dist/bugcatch.standalone.umd.js +553 -429
- package/dist/bugcatch.standalone.umd.js.map +1 -1
- package/dist/bugcatch.umd.js +132 -120
- package/dist/bugcatch.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/accent.js +38 -0
- package/src/incoming-call.js +17 -15
- package/src/index.d.ts +52 -2
- package/src/index.js +26 -7
- package/src/panel/call.js +3 -2
- package/src/panel/compose.js +7 -3
- package/src/panel/icons.js +2 -0
- package/src/panel/index.js +26 -3
- package/src/panel/messages.js +2 -2
- package/src/panel/picks.js +6 -2
- package/src/panel/rate-due.js +155 -0
- package/src/panel/rating.js +87 -0
- package/src/panel/refs.js +1 -1
- package/src/panel/render.js +11 -3
- package/src/panel/signin.js +1 -1
- package/src/panel/styles.js +270 -186
- package/src/panel/thread.js +48 -7
- package/src/updates.js +77 -27
- package/src/widget.js +160 -141
package/dist/bugcatch-core.es.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
1
|
+
var be = (t) => {
|
|
2
2
|
throw TypeError(t);
|
|
3
3
|
};
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var x = (t, e, n) => (
|
|
7
|
-
const
|
|
4
|
+
var xt = (t, e, n) => e.has(t) || be("Cannot " + n);
|
|
5
|
+
var xe = (t, e, n) => e.has(t) ? be("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, n);
|
|
6
|
+
var x = (t, e, n) => (xt(t, e, "access private method"), n);
|
|
7
|
+
const Q = "[REDACTED]", kt = /* @__PURE__ */ new Set([
|
|
8
8
|
"auth",
|
|
9
9
|
"bearer",
|
|
10
10
|
"session",
|
|
@@ -16,7 +16,7 @@ const Y = "[REDACTED]", ft = /* @__PURE__ */ new Set([
|
|
|
16
16
|
"pwd",
|
|
17
17
|
"sig",
|
|
18
18
|
"codeverifier"
|
|
19
|
-
]),
|
|
19
|
+
]), vt = [
|
|
20
20
|
"token",
|
|
21
21
|
"secret",
|
|
22
22
|
"password",
|
|
@@ -28,7 +28,7 @@ const Y = "[REDACTED]", ft = /* @__PURE__ */ new Set([
|
|
|
28
28
|
"privatekey",
|
|
29
29
|
"accesskey",
|
|
30
30
|
"authorization"
|
|
31
|
-
],
|
|
31
|
+
], It = /* @__PURE__ */ new Set(["key", "code", "state", "nonce", "salt", "hash"]), Ne = [
|
|
32
32
|
/eyJ[\w-]{8,}\.[\w-]{8,}\.[\w-]+/g,
|
|
33
33
|
// JWT
|
|
34
34
|
/(?:AKIA|ASIA|AROA|AIDA|AGPA|ANPA|ANVA|APKA)[0-9A-Z]{16}/g,
|
|
@@ -51,61 +51,61 @@ const Y = "[REDACTED]", ft = /* @__PURE__ */ new Set([
|
|
|
51
51
|
// GitLab
|
|
52
52
|
/shp(?:at|ss|ca|pa)_[A-Za-z0-9]{32}/g
|
|
53
53
|
// Shopify
|
|
54
|
-
],
|
|
55
|
-
function
|
|
54
|
+
], Ct = /\bBearer\s+[\w.~+/=-]{8,}/gi, St = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;
|
|
55
|
+
function Ue(t) {
|
|
56
56
|
try {
|
|
57
57
|
return decodeURIComponent(t.replace(/\+/g, " "));
|
|
58
58
|
} catch {
|
|
59
59
|
return t;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
function
|
|
63
|
-
return
|
|
62
|
+
function Bt(t) {
|
|
63
|
+
return Ue(t).toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
64
64
|
}
|
|
65
|
-
function
|
|
66
|
-
return t.length >= 20 ? !0 :
|
|
65
|
+
function Et(t) {
|
|
66
|
+
return t.length >= 20 ? !0 : Ne.some((e) => (e.lastIndex = 0, e.test(t)));
|
|
67
67
|
}
|
|
68
|
-
function
|
|
69
|
-
const n =
|
|
68
|
+
function $t(t, e) {
|
|
69
|
+
const n = Bt(t);
|
|
70
70
|
if (!n) return !1;
|
|
71
|
-
if (
|
|
72
|
-
for (const
|
|
73
|
-
return
|
|
71
|
+
if (kt.has(n)) return !0;
|
|
72
|
+
for (const i of vt) if (n.includes(i)) return !0;
|
|
73
|
+
return It.has(n) ? Et(Ue(e)) : !1;
|
|
74
74
|
}
|
|
75
|
-
function
|
|
75
|
+
function ie(t) {
|
|
76
76
|
return t.split("&").map((e) => {
|
|
77
77
|
const n = e.indexOf("=");
|
|
78
78
|
if (n === -1) return e;
|
|
79
|
-
const
|
|
80
|
-
return r &&
|
|
79
|
+
const i = e.slice(0, n), r = e.slice(n + 1);
|
|
80
|
+
return r && $t(i, r) ? `${i}=${Q}` : e;
|
|
81
81
|
}).join("&");
|
|
82
82
|
}
|
|
83
|
-
function
|
|
83
|
+
function Pe(t) {
|
|
84
84
|
let e = t;
|
|
85
|
-
for (const n of
|
|
86
|
-
n.lastIndex = 0, e = e.replace(n,
|
|
85
|
+
for (const n of Ne)
|
|
86
|
+
n.lastIndex = 0, e = e.replace(n, Q);
|
|
87
87
|
return e;
|
|
88
88
|
}
|
|
89
|
-
function
|
|
89
|
+
function De(t) {
|
|
90
90
|
if (t == null) return t;
|
|
91
91
|
let e = String(t);
|
|
92
92
|
if (!e) return e;
|
|
93
|
-
e = e.replace(
|
|
93
|
+
e = e.replace(St, `$1${Q}@`);
|
|
94
94
|
const n = e.indexOf("#");
|
|
95
|
-
let
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
95
|
+
let i = n === -1 ? e : e.slice(0, n), r = n === -1 ? "" : e.slice(n);
|
|
96
|
+
const o = i.indexOf("?");
|
|
97
|
+
if (o !== -1 && (i = i.slice(0, o + 1) + ie(i.slice(o + 1))), r.length > 1) {
|
|
98
98
|
const a = r.slice(1), s = a.indexOf("?");
|
|
99
|
-
s !== -1 ? r = `#${a.slice(0, s + 1)}${
|
|
99
|
+
s !== -1 ? r = `#${a.slice(0, s + 1)}${ie(a.slice(s + 1))}` : a.includes("=") && (r = `#${ie(a)}`);
|
|
100
100
|
}
|
|
101
|
-
return
|
|
101
|
+
return Pe(i + r);
|
|
102
102
|
}
|
|
103
|
-
function
|
|
103
|
+
function Tt(t) {
|
|
104
104
|
if (t == null) return t;
|
|
105
105
|
let e = String(t);
|
|
106
|
-
return e && (e = e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g, (n) =>
|
|
106
|
+
return e && (e = e.replace(/[A-Za-z][A-Za-z0-9+.-]{0,30}:\/\/[^\s"'<>)\]]+/g, (n) => De(n)), e = e.replace(Ct, `Bearer ${Q}`), Pe(e));
|
|
107
107
|
}
|
|
108
|
-
function
|
|
108
|
+
function z(t) {
|
|
109
109
|
const e = [];
|
|
110
110
|
return {
|
|
111
111
|
push(n) {
|
|
@@ -120,41 +120,41 @@ function D(t) {
|
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
const
|
|
124
|
-
function
|
|
123
|
+
const ke = ["log", "info", "warn", "error", "debug"];
|
|
124
|
+
function At(t, { levels: e = ["warn", "error", "log", "info"] } = {}) {
|
|
125
125
|
const n = {};
|
|
126
|
-
for (const
|
|
127
|
-
n[
|
|
126
|
+
for (const i of ke)
|
|
127
|
+
n[i] = console[i], e.includes(i) && (console[i] = (...r) => {
|
|
128
128
|
try {
|
|
129
129
|
t.push({
|
|
130
|
-
level:
|
|
131
|
-
text: r.map(
|
|
130
|
+
level: i,
|
|
131
|
+
text: r.map(He).join(" ").slice(0, 2e3),
|
|
132
132
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
133
133
|
});
|
|
134
134
|
} catch {
|
|
135
135
|
}
|
|
136
|
-
n[
|
|
136
|
+
n[i].apply(console, r);
|
|
137
137
|
});
|
|
138
138
|
return () => {
|
|
139
|
-
for (const
|
|
139
|
+
for (const i of ke) console[i] = n[i];
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
|
-
function
|
|
143
|
-
const n = window.fetch,
|
|
142
|
+
function jt(t, { slowMs: e = 2e3 } = {}) {
|
|
143
|
+
const n = window.fetch, i = XMLHttpRequest.prototype.open, r = XMLHttpRequest.prototype.send;
|
|
144
144
|
return n && (window.fetch = async function(...a) {
|
|
145
|
-
var
|
|
146
|
-
const s = performance.now(), c = typeof a[0] == "string" ? a[0] : (
|
|
145
|
+
var h, f, d;
|
|
146
|
+
const s = performance.now(), c = typeof a[0] == "string" ? a[0] : (h = a[0]) == null ? void 0 : h.url, l = ((f = a[1]) == null ? void 0 : f.method) || (typeof a[0] == "object" ? (d = a[0]) == null ? void 0 : d.method : "GET") || "GET";
|
|
147
147
|
try {
|
|
148
148
|
const u = await n.apply(this, a);
|
|
149
|
-
return
|
|
149
|
+
return oe(t, { url: c, method: l, status: u.status, ms: Math.round(performance.now() - s), slowMs: e }), u;
|
|
150
150
|
} catch (u) {
|
|
151
|
-
throw
|
|
151
|
+
throw oe(t, { url: c, method: l, status: 0, error: String((u == null ? void 0 : u.message) || u), ms: Math.round(performance.now() - s), slowMs: e }), u;
|
|
152
152
|
}
|
|
153
153
|
}), XMLHttpRequest.prototype.open = function(a, s, ...c) {
|
|
154
|
-
return this.__bc = { method: a, url: s, started: 0 },
|
|
154
|
+
return this.__bc = { method: a, url: s, started: 0 }, i.call(this, a, s, ...c);
|
|
155
155
|
}, XMLHttpRequest.prototype.send = function(...a) {
|
|
156
156
|
return this.__bc && (this.__bc.started = performance.now(), this.addEventListener("loadend", () => {
|
|
157
|
-
|
|
157
|
+
oe(t, {
|
|
158
158
|
url: this.__bc.url,
|
|
159
159
|
method: this.__bc.method,
|
|
160
160
|
status: this.status,
|
|
@@ -163,10 +163,10 @@ function It(t, { slowMs: e = 2e3 } = {}) {
|
|
|
163
163
|
});
|
|
164
164
|
})), r.apply(this, a);
|
|
165
165
|
}, () => {
|
|
166
|
-
n && (window.fetch = n), XMLHttpRequest.prototype.open =
|
|
166
|
+
n && (window.fetch = n), XMLHttpRequest.prototype.open = i, XMLHttpRequest.prototype.send = r;
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
|
-
function
|
|
169
|
+
function oe(t, { url: e, method: n, status: i, ms: r, error: o, slowMs: a }) {
|
|
170
170
|
try {
|
|
171
171
|
t.push({
|
|
172
172
|
// Scrubbed before it is buffered, not before it is sent: a credential
|
|
@@ -175,31 +175,31 @@ function Q(t, { url: e, method: n, status: o, ms: r, error: i, slowMs: a }) {
|
|
|
175
175
|
// then truncate — truncating first would split a token into something
|
|
176
176
|
// no pattern recognises, and the fragment would still be a fragment of
|
|
177
177
|
// a live credential.
|
|
178
|
-
url:
|
|
178
|
+
url: De(String(e)).slice(0, 500),
|
|
179
179
|
method: n,
|
|
180
|
-
status:
|
|
180
|
+
status: i,
|
|
181
181
|
ms: r,
|
|
182
|
-
error:
|
|
182
|
+
error: o === void 0 ? void 0 : Tt(o),
|
|
183
183
|
// Flagged so triage can spot the interesting rows without reading everything.
|
|
184
|
-
failed:
|
|
184
|
+
failed: i === 0 || i >= 400,
|
|
185
185
|
slow: r >= a,
|
|
186
186
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
187
187
|
});
|
|
188
188
|
} catch {
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
function
|
|
192
|
-
const e = (
|
|
193
|
-
const r = String(
|
|
191
|
+
function Ot(t) {
|
|
192
|
+
const e = (i) => {
|
|
193
|
+
const r = String(i.message || "Error"), o = i.filename ? ` (${i.filename}:${i.lineno}:${i.colno})` : "";
|
|
194
194
|
t.push({
|
|
195
195
|
level: "error",
|
|
196
|
-
text: (/^uncaught/i.test(r) ? r : `Uncaught ${r}`) +
|
|
196
|
+
text: (/^uncaught/i.test(r) ? r : `Uncaught ${r}`) + o,
|
|
197
197
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
198
198
|
});
|
|
199
|
-
}, n = (
|
|
199
|
+
}, n = (i) => {
|
|
200
200
|
t.push({
|
|
201
201
|
level: "error",
|
|
202
|
-
text: `Unhandled rejection: ${
|
|
202
|
+
text: `Unhandled rejection: ${He(i.reason)}`,
|
|
203
203
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
204
204
|
});
|
|
205
205
|
};
|
|
@@ -207,8 +207,8 @@ function St(t) {
|
|
|
207
207
|
window.removeEventListener("error", e), window.removeEventListener("unhandledrejection", n);
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
|
-
async function
|
|
211
|
-
const t =
|
|
210
|
+
async function ve() {
|
|
211
|
+
const t = _e();
|
|
212
212
|
try {
|
|
213
213
|
if (navigator.getBattery) {
|
|
214
214
|
const e = await navigator.getBattery();
|
|
@@ -218,8 +218,8 @@ async function me() {
|
|
|
218
218
|
}
|
|
219
219
|
return t;
|
|
220
220
|
}
|
|
221
|
-
function
|
|
222
|
-
var e, n,
|
|
221
|
+
function _e() {
|
|
222
|
+
var e, n, i, r, o, a, s, c, l;
|
|
223
223
|
const t = window.navigator || {};
|
|
224
224
|
return {
|
|
225
225
|
userAgent: t.userAgent,
|
|
@@ -233,9 +233,9 @@ function Le() {
|
|
|
233
233
|
screen: {
|
|
234
234
|
width: (e = window.screen) == null ? void 0 : e.width,
|
|
235
235
|
height: (n = window.screen) == null ? void 0 : n.height,
|
|
236
|
-
availWidth: (
|
|
236
|
+
availWidth: (i = window.screen) == null ? void 0 : i.availWidth,
|
|
237
237
|
availHeight: (r = window.screen) == null ? void 0 : r.availHeight,
|
|
238
|
-
colorDepth: (
|
|
238
|
+
colorDepth: (o = window.screen) == null ? void 0 : o.colorDepth,
|
|
239
239
|
orientation: ((s = (a = window.screen) == null ? void 0 : a.orientation) == null ? void 0 : s.type) || null
|
|
240
240
|
},
|
|
241
241
|
devicePixelRatio: window.devicePixelRatio,
|
|
@@ -260,7 +260,7 @@ function Le() {
|
|
|
260
260
|
prefersReducedMotion: ((l = window.matchMedia) == null ? void 0 : l.call(window, "(prefers-reduced-motion: reduce)").matches) || !1
|
|
261
261
|
};
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function He(t) {
|
|
264
264
|
if (typeof t == "string") return t;
|
|
265
265
|
if (t instanceof Error) return `${t.name}: ${t.message}`;
|
|
266
266
|
try {
|
|
@@ -269,152 +269,192 @@ function Re(t) {
|
|
|
269
269
|
return String(t);
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
-
const
|
|
273
|
-
function
|
|
272
|
+
const hi = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11.5a7.5 7 0 0 1 7.5-7h1a7.5 7 0 0 1 0 14H9l-4.2 2.6a.5.5 0 0 1-.76-.5l.5-3.1A7 7 0 0 1 4 11.5z"/><path d="M8.5 11.5h.01M12 11.5h.01M15.5 11.5h.01" stroke-width="2.6"/></svg>', Mt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9.5l6 6 6-6"/></svg>', Rt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4.2"/><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.4 5.4l1.6 1.6M17 17l1.6 1.6M18.6 5.4L17 7M7 17l-1.6 1.6"/></svg>', Lt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><path d="M20 13.4A8.2 8.2 0 1 1 10.6 4a6.6 6.6 0 0 0 9.4 9.4z"/></svg>', Kt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="2.8" y="4.4" width="18.4" height="12.6" rx="2.2"/><path d="M8.6 20.2h6.8"/><path d="M12 4.4v12.6"/><path d="M12 7.2a3.6 3.6 0 0 1 0 7.2z" fill="currentColor" stroke="none"/></svg>', ze = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 7.5v5.2M12 16.3h.01"/></svg>', qe = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 6l12 12M18 6L6 18"/></svg>', Nt = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12.8l4.6 4.4L19 7"/></svg>', Fe = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M12 11v5.5M12 7.7h.01"/></svg>', Ut = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.3 4.2a2 2 0 0 1 3.4 0l7.6 13.1a2 2 0 0 1-1.7 3H4.4a2 2 0 0 1-1.7-3z"/><path d="M12 9.5v4.2M12 17h.01"/></svg>';
|
|
273
|
+
function Xe(t, e) {
|
|
274
274
|
console.warn(`[BugCatch] ${t}`, ...e ? [e] : []);
|
|
275
275
|
const n = new Error("[BugCatch] part of the widget could not be loaded — check the connection and try again.");
|
|
276
276
|
return e && (n.cause = e), n;
|
|
277
277
|
}
|
|
278
|
-
function
|
|
278
|
+
function We(t) {
|
|
279
279
|
let e = null;
|
|
280
|
-
return (...n) => (e || (e = t(...n).catch((
|
|
281
|
-
throw e = null,
|
|
280
|
+
return (...n) => (e || (e = t(...n).catch((i) => {
|
|
281
|
+
throw e = null, i;
|
|
282
282
|
})), e);
|
|
283
283
|
}
|
|
284
|
-
const
|
|
285
|
-
throw
|
|
286
|
-
})),
|
|
287
|
-
throw
|
|
288
|
-
})),
|
|
289
|
-
info:
|
|
290
|
-
success:
|
|
291
|
-
warning:
|
|
292
|
-
critical:
|
|
284
|
+
const Ie = We(() => import("./bugcatch-panel.es.js").catch((t) => {
|
|
285
|
+
throw Xe("the report panel could not be loaded.", t);
|
|
286
|
+
})), q = We(() => import("./bugcatch-call.es.js").catch((t) => {
|
|
287
|
+
throw Xe("the calling code could not be loaded.", t);
|
|
288
|
+
})), Pt = {
|
|
289
|
+
info: Fe,
|
|
290
|
+
success: Nt,
|
|
291
|
+
warning: Ut,
|
|
292
|
+
critical: ze
|
|
293
293
|
};
|
|
294
|
-
function
|
|
295
|
-
const o = document.createElement("div");
|
|
296
|
-
o.className = `notice tone-${t.tone} at-${e}`, o.setAttribute("role", "status");
|
|
297
|
-
const r = document.createElement("span");
|
|
298
|
-
r.className = "notice-ico", r.setAttribute("aria-hidden", "true"), r.innerHTML = Ot[t.tone] || Ne;
|
|
294
|
+
function Dt(t, { where: e, onDismiss: n }) {
|
|
299
295
|
const i = document.createElement("div");
|
|
300
|
-
i.className =
|
|
296
|
+
i.className = `notice tone-${t.tone} at-${e}`, i.setAttribute("role", "status");
|
|
297
|
+
const r = document.createElement("span");
|
|
298
|
+
r.className = "notice-ico", r.setAttribute("aria-hidden", "true"), r.innerHTML = Pt[t.tone] || Fe;
|
|
299
|
+
const o = document.createElement("div");
|
|
300
|
+
o.className = "notice-text";
|
|
301
301
|
const a = document.createElement("strong");
|
|
302
|
-
if (a.textContent = t.title,
|
|
302
|
+
if (a.textContent = t.title, o.append(a), t.body) {
|
|
303
303
|
const s = document.createElement("p");
|
|
304
|
-
s.textContent = t.body,
|
|
304
|
+
s.textContent = t.body, o.append(s);
|
|
305
305
|
}
|
|
306
306
|
if (t.ctaHref && t.ctaLabel) {
|
|
307
307
|
const s = document.createElement("a");
|
|
308
|
-
s.className = "notice-cta", s.href = t.ctaHref, s.textContent = t.ctaLabel, /^https?:/i.test(t.ctaHref) && (s.target = "_blank", s.rel = "noopener noreferrer"),
|
|
308
|
+
s.className = "notice-cta", s.href = t.ctaHref, s.textContent = t.ctaLabel, /^https?:/i.test(t.ctaHref) && (s.target = "_blank", s.rel = "noopener noreferrer"), o.append(s);
|
|
309
309
|
}
|
|
310
|
-
if (
|
|
310
|
+
if (i.append(r, o), t.dismissible && n) {
|
|
311
311
|
const s = document.createElement("button");
|
|
312
|
-
s.type = "button", s.className = "notice-x", s.setAttribute("aria-label", "Dismiss this notice"), s.innerHTML =
|
|
312
|
+
s.type = "button", s.className = "notice-x", s.setAttribute("aria-label", "Dismiss this notice"), s.innerHTML = qe, s.addEventListener("click", () => n(t)), i.append(s);
|
|
313
313
|
}
|
|
314
|
-
return
|
|
314
|
+
return i;
|
|
315
|
+
}
|
|
316
|
+
const Je = "#0e0e10", re = "#ffffff";
|
|
317
|
+
function Ye(t) {
|
|
318
|
+
const e = _t(t);
|
|
319
|
+
if (!e) return re;
|
|
320
|
+
const [n, i, r] = e.map((a) => {
|
|
321
|
+
const s = a / 255;
|
|
322
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
323
|
+
});
|
|
324
|
+
return 0.2126 * n + 0.7152 * i + 0.0722 * r > 0.179 ? Je : re;
|
|
325
|
+
}
|
|
326
|
+
function _t(t) {
|
|
327
|
+
const e = String(t || "").trim();
|
|
328
|
+
let n = /^#([0-9a-f]{3})$/i.exec(e);
|
|
329
|
+
return n ? [...n[1]].map((i) => parseInt(i + i, 16)) : (n = /^#([0-9a-f]{6})$/i.exec(e), n ? [0, 2, 4].map((i) => parseInt(n[1].slice(i, i + 2), 16)) : (n = /^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/i.exec(e), n ? [n[1], n[2], n[3]].map(Number) : null));
|
|
315
330
|
}
|
|
316
|
-
const
|
|
331
|
+
const Ce = {
|
|
317
332
|
"bottom-right": "bottom:20px;right:20px;",
|
|
318
333
|
"bottom-left": "bottom:20px;left:20px;",
|
|
319
334
|
"top-right": "top:20px;right:20px;",
|
|
320
335
|
"top-left": "top:20px;left:20px;"
|
|
321
|
-
},
|
|
322
|
-
{ value: "light", label: "Light", icon:
|
|
323
|
-
{ value: "dark", label: "Dark", icon:
|
|
324
|
-
{ value: "auto", label: "System default", icon:
|
|
325
|
-
],
|
|
326
|
-
function
|
|
336
|
+
}, P = [
|
|
337
|
+
{ value: "light", label: "Light", icon: Rt },
|
|
338
|
+
{ value: "dark", label: "Dark", icon: Lt },
|
|
339
|
+
{ value: "auto", label: "System default", icon: Kt }
|
|
340
|
+
], Ve = "bugcatch:theme";
|
|
341
|
+
function Ht() {
|
|
327
342
|
try {
|
|
328
|
-
const t = localStorage.getItem(
|
|
329
|
-
return
|
|
343
|
+
const t = localStorage.getItem(Ve);
|
|
344
|
+
return P.some((e) => e.value === t) ? t : null;
|
|
330
345
|
} catch {
|
|
331
346
|
return null;
|
|
332
347
|
}
|
|
333
348
|
}
|
|
334
|
-
function
|
|
349
|
+
function zt(t) {
|
|
335
350
|
try {
|
|
336
|
-
localStorage.setItem(
|
|
351
|
+
localStorage.setItem(Ve, t);
|
|
337
352
|
} catch {
|
|
338
353
|
}
|
|
339
354
|
}
|
|
340
|
-
const
|
|
355
|
+
const Se = `
|
|
356
|
+
--bc-bg: #151517;
|
|
357
|
+
--bc-elevated: #1c1c1f;
|
|
358
|
+
--bc-fg: #f3f2ef;
|
|
359
|
+
--bc-muted: #b3b0aa;
|
|
360
|
+
--bc-faint: #8f8c86;
|
|
361
|
+
--bc-border: #2c2c30;
|
|
362
|
+
--bc-subtle: #1f1f22;
|
|
363
|
+
--bc-stone: #26262a;
|
|
364
|
+
--bc-raised: #303035;
|
|
365
|
+
--bc-danger: #ff6b81;
|
|
366
|
+
--bc-ok: #4fd19a;
|
|
367
|
+
--bc-warn: #f2a54a;
|
|
368
|
+
--bc-info: #79a8ff;
|
|
369
|
+
--bc-brand-ink: #b3b0aa;
|
|
370
|
+
--bc-brand-mark: #a59cff;
|
|
371
|
+
--bc-shadow: 0 0 0 1px rgba(255,255,255,.08), 0 30px 70px -20px rgba(0,0,0,.8), 0 8px 20px -8px rgba(0,0,0,.5);
|
|
372
|
+
--bc-shadow-sm: 0 0 0 1px rgba(255,255,255,.07), 0 1px 2px rgba(0,0,0,.4);
|
|
373
|
+
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 14%, var(--bc-bg));`, qt = (t) => `
|
|
341
374
|
:host { all: initial; }
|
|
342
375
|
:host {
|
|
343
|
-
--bc-accent: ${t};
|
|
344
|
-
--bc-on-accent:
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
--bc-
|
|
348
|
-
--bc-
|
|
349
|
-
--bc-
|
|
350
|
-
--bc-
|
|
351
|
-
--bc-
|
|
352
|
-
--bc-
|
|
353
|
-
--bc-
|
|
354
|
-
--bc-
|
|
355
|
-
--bc-
|
|
376
|
+
--bc-accent: ${t || "var(--bc-fg)"};
|
|
377
|
+
--bc-on-accent: ${t ? Ye(t) : "var(--bc-bg)"};
|
|
378
|
+
/* The assistant's orb: BugCatch's own three colours, or the host's accent
|
|
379
|
+
with two lighter cuts of it, so the orb on their site is in their colour. */
|
|
380
|
+
--bc-o1: ${t ? `color-mix(in srgb, ${t} 32%, #fff)` : "#ffb3c9"};
|
|
381
|
+
--bc-o2: ${t || "#6a5cff"};
|
|
382
|
+
--bc-o3: ${t ? `color-mix(in srgb, ${t} 22%, #ffe7d1)` : "#ffd6a0"};
|
|
383
|
+
--bc-bg: #ffffff;
|
|
384
|
+
--bc-elevated: #ffffff;
|
|
385
|
+
--bc-fg: #0e0e10;
|
|
386
|
+
--bc-muted: #57544e;
|
|
387
|
+
--bc-faint: #75726c;
|
|
388
|
+
--bc-border: #e9e7e3;
|
|
389
|
+
--bc-subtle: #f6f5f3;
|
|
390
|
+
/* Warm stone: fields, chips and the selected track. */
|
|
391
|
+
--bc-stone: #f0efec;
|
|
392
|
+
--bc-raised: #ffffff;
|
|
393
|
+
--bc-danger: #c8233d;
|
|
394
|
+
--bc-ok: #0b7a55;
|
|
395
|
+
--bc-warn: #a4570a;
|
|
396
|
+
--bc-info: #2459d1;
|
|
356
397
|
/* The lockup's own two colours, kept off --bc-accent on purpose: that one is
|
|
357
398
|
the customer's brand, and this mark is ours. Values are the light cut of
|
|
358
399
|
brand/sphoro-bugcatch-primary.svg, pulled up from near-black so the mark
|
|
359
400
|
identifies itself without out-shouting the host's page. */
|
|
360
|
-
--bc-brand-ink: #
|
|
401
|
+
--bc-brand-ink: #57544e;
|
|
361
402
|
--bc-brand-mark: #5647ee;
|
|
362
|
-
--bc-shadow: 0
|
|
363
|
-
--bc-shadow-sm: 0 1px
|
|
364
|
-
--bc-dur:
|
|
403
|
+
--bc-shadow: 0 0 0 1px rgba(20,18,14,.06), 0 30px 70px -24px rgba(20,18,14,.30), 0 8px 20px -8px rgba(20,18,14,.10);
|
|
404
|
+
--bc-shadow-sm: 0 0 0 1px rgba(20,18,14,.06), 0 1px 2px rgba(20,18,14,.05);
|
|
405
|
+
--bc-dur: 220ms;
|
|
365
406
|
--bc-ease: cubic-bezier(.22,1,.36,1);
|
|
407
|
+
/* Film grain over the orb, so it reads as light rather than a gradient. */
|
|
408
|
+
--bc-grain: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .6 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
|
|
366
409
|
/* The system everything below is drawn from. Derived tokens are written in
|
|
367
410
|
terms of the ones above, so a host that overrides --bc-accent or the
|
|
368
411
|
palette gets a coherent result without touching these. */
|
|
369
|
-
--bc-accent-soft: color-mix(in srgb, var(--bc-accent)
|
|
370
|
-
--bc-accent-line: color-mix(in srgb, var(--bc-accent)
|
|
371
|
-
--bc-ring: 0 0 0 3px color-mix(in srgb, var(--bc-accent)
|
|
412
|
+
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 7%, var(--bc-bg));
|
|
413
|
+
--bc-accent-line: color-mix(in srgb, var(--bc-accent) 30%, var(--bc-border));
|
|
414
|
+
--bc-ring: 0 0 0 3px color-mix(in srgb, var(--bc-accent) 16%, transparent);
|
|
372
415
|
--bc-r-sm: 8px;
|
|
373
416
|
--bc-r-md: 12px;
|
|
374
|
-
--bc-r-lg:
|
|
375
|
-
--bc-r-xl:
|
|
417
|
+
--bc-r-lg: 16px;
|
|
418
|
+
--bc-r-xl: 20px;
|
|
376
419
|
--bc-fs-xs: 11.5px;
|
|
377
420
|
--bc-fs-sm: 12.5px;
|
|
378
421
|
--bc-fs-md: 14px;
|
|
379
|
-
--bc-fs-lg:
|
|
422
|
+
--bc-fs-lg: 15px;
|
|
380
423
|
--bc-pad: 18px;
|
|
381
424
|
}
|
|
382
|
-
:host(.bc-dark) {
|
|
383
|
-
--bc-bg: #14161c;
|
|
384
|
-
--bc-elevated: #1c1f27;
|
|
385
|
-
--bc-fg: #eef0f4;
|
|
386
|
-
--bc-muted: #a3aab6;
|
|
387
|
-
--bc-faint: #6f7682;
|
|
388
|
-
--bc-border: #2a2e38;
|
|
389
|
-
--bc-subtle: #1f222a;
|
|
390
|
-
--bc-raised: #363d4b;
|
|
391
|
-
--bc-warn: #f59e0b;
|
|
392
|
-
--bc-brand-ink: #9aa1ad;
|
|
393
|
-
--bc-brand-mark: #9b8fff;
|
|
394
|
-
--bc-shadow: 0 24px 64px rgba(0,0,0,.6), 0 4px 14px rgba(0,0,0,.4);
|
|
395
|
-
--bc-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
|
|
396
|
-
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 18%, var(--bc-bg));
|
|
425
|
+
:host(.bc-dark) {${Se}
|
|
397
426
|
}
|
|
398
427
|
@media (prefers-color-scheme: dark) {
|
|
399
|
-
:host(.bc-auto) {
|
|
400
|
-
--bc-bg: #14161c;
|
|
401
|
-
--bc-elevated: #1c1f27;
|
|
402
|
-
--bc-fg: #eef0f4;
|
|
403
|
-
--bc-muted: #a3aab6;
|
|
404
|
-
--bc-faint: #6f7682;
|
|
405
|
-
--bc-border: #2a2e38;
|
|
406
|
-
--bc-subtle: #1f222a;
|
|
407
|
-
--bc-raised: #363d4b;
|
|
408
|
-
--bc-warn: #f59e0b;
|
|
409
|
-
--bc-brand-ink: #9aa1ad;
|
|
410
|
-
--bc-brand-mark: #9b8fff;
|
|
411
|
-
--bc-shadow: 0 24px 64px rgba(0,0,0,.6), 0 4px 14px rgba(0,0,0,.4);
|
|
412
|
-
--bc-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
|
|
413
|
-
--bc-accent-soft: color-mix(in srgb, var(--bc-accent) 18%, var(--bc-bg));
|
|
428
|
+
:host(.bc-auto) {${Se}
|
|
414
429
|
}
|
|
415
430
|
}
|
|
416
431
|
|
|
417
432
|
* { box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif; }
|
|
433
|
+
|
|
434
|
+
/* ---------- the orb ----------
|
|
435
|
+
The assistant's face, on the launcher and at the top of every screen: three
|
|
436
|
+
blurred colour blobs turning slowly under a highlight and grain. Hue from
|
|
437
|
+
--bc-o1..3. Sized by whoever places it. */
|
|
438
|
+
.orb {
|
|
439
|
+
position: relative; display: block; flex: none; aspect-ratio: 1; border-radius: 50%;
|
|
440
|
+
background: var(--bc-o2); overflow: hidden; isolation: isolate;
|
|
441
|
+
box-shadow: inset -3px -5px 10px rgba(0,0,0,.22), inset 2px 3px 7px rgba(255,255,255,.35);
|
|
442
|
+
}
|
|
443
|
+
.orb::before {
|
|
444
|
+
content: ''; position: absolute; inset: -20%; border-radius: 50%; z-index: -1;
|
|
445
|
+
background:
|
|
446
|
+
radial-gradient(circle at 70% 72%, var(--bc-o3) 0%, transparent 44%),
|
|
447
|
+
radial-gradient(circle at 26% 66%, var(--bc-o1) 0%, transparent 48%),
|
|
448
|
+
radial-gradient(circle at 58% 30%, var(--bc-o2) 0%, transparent 62%);
|
|
449
|
+
filter: blur(3px);
|
|
450
|
+
animation: bc-orb-turn 18s linear infinite;
|
|
451
|
+
}
|
|
452
|
+
.orb::after {
|
|
453
|
+
content: ''; position: absolute; inset: 0; border-radius: 50%;
|
|
454
|
+
background: radial-gradient(circle at 34% 26%, rgba(255,255,255,.85) 0 5%, rgba(255,255,255,0) 30%), var(--bc-grain);
|
|
455
|
+
mix-blend-mode: soft-light;
|
|
456
|
+
}
|
|
457
|
+
@keyframes bc-orb-turn { to { transform: rotate(360deg); } }
|
|
418
458
|
svg { width: 1em; height: 1em; display: block; }
|
|
419
459
|
/* The hidden attribute has to actually hide. Nearly every element in here is given a
|
|
420
460
|
display by a rule below, and any of them beats the attribute's own UA style
|
|
@@ -445,65 +485,50 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
445
485
|
@keyframes bc-launcher-in { from { opacity: 0; transform: translateY(12px) scale(.86) } to { opacity: 1; transform: none } }
|
|
446
486
|
@keyframes bc-item-in { from { opacity: 0; transform: translateY(8px) scale(.96) } to { opacity: 1; transform: none } }
|
|
447
487
|
|
|
448
|
-
/* ---------- dock:
|
|
488
|
+
/* ---------- dock: the launcher, and what is said beside it ---------- */
|
|
449
489
|
.dock {
|
|
450
490
|
position: fixed; z-index: 2147483000;
|
|
451
491
|
display: flex; flex-direction: column; gap: 10px;
|
|
452
492
|
}
|
|
453
493
|
.dock[hidden] { display: none; }
|
|
454
|
-
/* While the panel is open the
|
|
455
|
-
|
|
494
|
+
/* While the panel is open the launcher rises above the scrim, so the button
|
|
495
|
+
that opened it is the button that closes it. */
|
|
456
496
|
.dock.over { z-index: 2147483002; }
|
|
457
497
|
.dock.at-right { align-items: flex-end; }
|
|
458
498
|
.dock.at-left { align-items: flex-start; }
|
|
459
|
-
/* Anchored to the top, "above the launcher" would be off-screen, so
|
|
460
|
-
|
|
499
|
+
/* Anchored to the top, "above the launcher" would be off-screen, so cards go
|
|
500
|
+
under it and the launcher stays the outermost thing. */
|
|
461
501
|
.dock.at-top { flex-direction: column-reverse; }
|
|
462
502
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
box-shadow: 0 6px 18px rgba(10,12,16,.14), 0 1px 3px rgba(10,12,16,.08);
|
|
468
|
-
animation: bc-launcher-in 420ms var(--bc-ease) both;
|
|
469
|
-
}
|
|
470
|
-
.themer button {
|
|
471
|
-
display: grid; place-items: center;
|
|
472
|
-
width: 28px; height: 28px; padding: 0;
|
|
473
|
-
border: none; border-radius: 999px; background: transparent;
|
|
474
|
-
color: var(--bc-muted); cursor: pointer;
|
|
475
|
-
transition: background var(--bc-dur) var(--bc-ease), color var(--bc-dur) var(--bc-ease), transform 140ms var(--bc-ease);
|
|
476
|
-
}
|
|
477
|
-
.themer button svg { font-size: 15px; }
|
|
478
|
-
.themer button:hover { background: var(--bc-subtle); color: var(--bc-fg); }
|
|
479
|
-
.themer button:active { transform: scale(.92); }
|
|
480
|
-
.themer button[aria-pressed="true"] { background: var(--bc-accent); color: var(--bc-on-accent); }
|
|
481
|
-
.themer button[aria-pressed="true"]:hover { background: var(--bc-accent); filter: brightness(1.06); }
|
|
482
|
-
|
|
483
|
-
/* ---------- launcher ---------- */
|
|
503
|
+
/* ---------- launcher ----------
|
|
504
|
+
A pill with the assistant's orb in it: ink by default, the host's colour when
|
|
505
|
+
they set one. The shadow is neutral, never tinted, so a bright brand colour
|
|
506
|
+
does not glow on somebody's checkout. */
|
|
484
507
|
.launcher {
|
|
485
508
|
position: relative;
|
|
486
|
-
display: inline-flex; align-items: center; gap:
|
|
487
|
-
height:
|
|
509
|
+
display: inline-flex; align-items: center; gap: 10px;
|
|
510
|
+
height: 46px; padding: 0 18px 0 7px; border: none; border-radius: 999px;
|
|
488
511
|
background: var(--bc-accent); color: var(--bc-on-accent);
|
|
489
|
-
font-size: var(--bc-fs-md); font-weight:
|
|
512
|
+
font-size: var(--bc-fs-md); font-weight: 560; line-height: 1; letter-spacing: -.01em;
|
|
490
513
|
cursor: pointer;
|
|
491
|
-
box-shadow: 0
|
|
492
|
-
transition: transform var(--bc-dur) var(--bc-ease), box-shadow var(--bc-dur) var(--bc-ease), filter 160ms linear
|
|
514
|
+
box-shadow: 0 1px 2px rgba(0,0,0,.18), 0 10px 26px -8px rgba(0,0,0,.36);
|
|
515
|
+
transition: transform var(--bc-dur) var(--bc-ease), box-shadow var(--bc-dur) var(--bc-ease), filter 160ms linear;
|
|
493
516
|
animation: bc-launcher-in 420ms var(--bc-ease) both;
|
|
494
517
|
}
|
|
495
|
-
/* Two
|
|
518
|
+
/* Two faces in one circle: the orb when closed, a chevron when open, turned
|
|
496
519
|
into each other so the button reads as the panel's own handle. */
|
|
497
|
-
.launcher .ico { position: relative; width:
|
|
520
|
+
.launcher .ico { position: relative; width: 32px; height: 32px; flex: none; }
|
|
498
521
|
.launcher .ico > span {
|
|
499
|
-
position: absolute; inset: 0;
|
|
522
|
+
position: absolute; inset: 0; display: grid; place-items: center; border-radius: 50%;
|
|
500
523
|
transition: transform 320ms var(--bc-ease), opacity 200ms ease;
|
|
501
524
|
}
|
|
502
|
-
.launcher .ico
|
|
525
|
+
.launcher .ico .orb { width: 32px; }
|
|
526
|
+
.launcher .ico .when-open { background: color-mix(in srgb, var(--bc-on-accent) 14%, transparent); }
|
|
527
|
+
.launcher .ico svg { width: 18px; height: 18px; }
|
|
503
528
|
.launcher .ico .when-open { opacity: 0; transform: rotate(-90deg) scale(.6); }
|
|
504
529
|
.launcher[aria-expanded="true"] .ico .when-closed { opacity: 0; transform: rotate(90deg) scale(.6); }
|
|
505
530
|
.launcher[aria-expanded="true"] .ico .when-open { opacity: 1; transform: none; }
|
|
506
|
-
.launcher:hover { transform: translateY(-
|
|
531
|
+
.launcher:hover { transform: translateY(-1px); box-shadow: 0 1px 2px rgba(0,0,0,.18), 0 14px 30px -8px rgba(0,0,0,.42); }
|
|
507
532
|
.launcher:active { transform: translateY(0) scale(.97); transition-duration: 90ms; }
|
|
508
533
|
.launcher:focus-visible { outline-offset: 3px; }
|
|
509
534
|
.launcher[hidden] { display: none; }
|
|
@@ -526,11 +551,11 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
526
551
|
In this sheet because the card beside the button exists before the panel's
|
|
527
552
|
does. The tone is a colour and an icon; the site's accent is the info one. */
|
|
528
553
|
.notice {
|
|
529
|
-
--tone: var(--bc-
|
|
554
|
+
--tone: var(--bc-info);
|
|
530
555
|
display: flex; align-items: flex-start; gap: 10px;
|
|
531
|
-
padding:
|
|
532
|
-
background:
|
|
533
|
-
border: 1px solid
|
|
556
|
+
padding: 11px 10px 11px 12px; border-radius: var(--bc-r-md);
|
|
557
|
+
background: var(--bc-subtle);
|
|
558
|
+
border: 1px solid var(--bc-border);
|
|
534
559
|
color: var(--bc-fg);
|
|
535
560
|
font-size: var(--bc-fs-sm); line-height: 1.45; text-align: left;
|
|
536
561
|
animation: bc-item-in 240ms var(--bc-ease) both;
|
|
@@ -538,33 +563,48 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
538
563
|
.notice.tone-success { --tone: var(--bc-ok); }
|
|
539
564
|
.notice.tone-warning { --tone: var(--bc-warn); }
|
|
540
565
|
.notice.tone-critical { --tone: var(--bc-danger); }
|
|
541
|
-
|
|
566
|
+
/* The tone is the icon's colour and a wash behind it — enough to tell a delay
|
|
567
|
+
from a fix at a glance, without a coloured card shouting over the form. */
|
|
568
|
+
.notice-ico {
|
|
569
|
+
flex: none; display: grid; place-items: center; width: 22px; height: 22px; margin-top: -1px;
|
|
570
|
+
border-radius: 7px; font-size: 14px;
|
|
571
|
+
color: var(--tone); background: color-mix(in srgb, var(--tone) 13%, transparent);
|
|
572
|
+
}
|
|
542
573
|
.notice-text { flex: 1; min-width: 0; overflow-wrap: anywhere; }
|
|
543
|
-
.notice-text strong { display: block; font-weight:
|
|
574
|
+
.notice-text strong { display: block; font-weight: 600; letter-spacing: -.005em; }
|
|
544
575
|
.notice-text p { margin: 2px 0 0; color: var(--bc-muted); white-space: pre-line; }
|
|
545
576
|
.notice-cta {
|
|
546
|
-
display: inline-
|
|
547
|
-
color: var(--
|
|
577
|
+
display: inline-flex; align-items: center; gap: 4px; margin-top: 6px;
|
|
578
|
+
color: var(--bc-fg); font-weight: 600; text-decoration: underline;
|
|
579
|
+
text-decoration-color: color-mix(in srgb, var(--bc-fg) 30%, transparent); text-underline-offset: 3px;
|
|
548
580
|
}
|
|
549
|
-
.notice-cta:hover { text-decoration
|
|
581
|
+
.notice-cta:hover { text-decoration-color: currentColor; }
|
|
550
582
|
.notice-x {
|
|
551
583
|
flex: none; display: grid; place-items: center;
|
|
552
|
-
width:
|
|
584
|
+
width: 24px; height: 24px; margin: -2px -2px 0 0; padding: 0;
|
|
553
585
|
border: 0; border-radius: 999px; background: transparent;
|
|
554
|
-
color: var(--bc-
|
|
586
|
+
color: var(--bc-faint); cursor: pointer;
|
|
555
587
|
}
|
|
556
|
-
.notice-x:hover { background: color-mix(in srgb, var(--
|
|
557
|
-
.notice-x svg { font-size:
|
|
588
|
+
.notice-x:hover { background: color-mix(in srgb, var(--bc-fg) 7%, transparent); color: var(--bc-fg); }
|
|
589
|
+
.notice-x svg { font-size: 13px; }
|
|
558
590
|
/* Beside the button it floats over somebody else's page: opaque, lifted, and
|
|
559
591
|
never taller than a glance. The whole text is in the panel. */
|
|
560
592
|
.notice.at-launcher {
|
|
561
593
|
width: min(320px, calc(100vw - 40px));
|
|
562
|
-
|
|
594
|
+
background: var(--bc-elevated); border-color: transparent;
|
|
595
|
+
box-shadow: var(--bc-shadow);
|
|
596
|
+
padding: 13px 12px 13px 13px;
|
|
563
597
|
}
|
|
564
598
|
.notice.at-launcher .notice-text p {
|
|
565
599
|
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
|
|
566
600
|
}
|
|
567
|
-
|
|
601
|
+
/* In the panel they are a stack of short lines above the form, not a wall:
|
|
602
|
+
the body is held to two lines, and the whole of it was beside the button. */
|
|
603
|
+
.notice.at-panel { margin-bottom: 8px; padding: 9px 8px 9px 10px; }
|
|
604
|
+
.notice.at-panel .notice-text p {
|
|
605
|
+
display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
|
|
606
|
+
}
|
|
607
|
+
.notice.at-panel .notice-cta { margin-top: 3px; }
|
|
568
608
|
|
|
569
609
|
/* The dock sits in a corner of a page the widget does not own. On a notched
|
|
570
610
|
phone that corner is under the home indicator, and in landscape it is under
|
|
@@ -584,25 +624,12 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
584
624
|
.dock.over { display: none; }
|
|
585
625
|
}
|
|
586
626
|
@media (pointer: coarse) {
|
|
587
|
-
/* The theme switch's buttons are small glyphs whose boxes cannot grow without
|
|
588
|
-
moving the launcher under them, so each keeps its size and gets an
|
|
589
|
-
invisible target drawn around it instead. */
|
|
590
|
-
.themer button { position: relative; }
|
|
591
|
-
.themer button::after {
|
|
592
|
-
content: '';
|
|
593
|
-
position: absolute;
|
|
594
|
-
inset: -8px;
|
|
595
|
-
}
|
|
596
|
-
/* The themer's three buttons sit side by side, so their expanders would
|
|
597
|
-
overlap each other without a gap to grow into. */
|
|
598
|
-
.themer { gap: 4px; }
|
|
599
627
|
.notice-x { width: 36px; height: 36px; margin: -9px -8px -6px 0; }
|
|
600
628
|
}
|
|
601
629
|
/* Hover is a lie on a touchscreen: it latches on tap and stays. The launcher's
|
|
602
630
|
lift in particular was left applied after the panel closed. */
|
|
603
631
|
@media (hover: none) {
|
|
604
632
|
.launcher:hover { transform: none; filter: none; }
|
|
605
|
-
.themer button:hover { transform: none; }
|
|
606
633
|
}
|
|
607
634
|
|
|
608
635
|
/* ---------- while the panel's code is on its way ----------
|
|
@@ -628,99 +655,100 @@ button:focus-visible, a:focus-visible, select:focus-visible, [tabindex]:focus-vi
|
|
|
628
655
|
.loadfail button[data-act="retry"] { text-decoration: underline; text-underline-offset: 2px; }
|
|
629
656
|
.loadfail button svg { font-size: 13px; margin: 0; }
|
|
630
657
|
`;
|
|
631
|
-
function
|
|
658
|
+
function Ft(t) {
|
|
632
659
|
const e = document.createElement("div");
|
|
633
660
|
e.setAttribute("data-bugcatch", "widget");
|
|
634
|
-
let n =
|
|
635
|
-
e.className =
|
|
636
|
-
const
|
|
637
|
-
r.textContent =
|
|
638
|
-
const
|
|
639
|
-
a.className = `dock ${
|
|
640
|
-
const s =
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
c.className = "launcher", c.type = "button", c.innerHTML = `<span class="ico" aria-hidden="true"><span class="when-closed"
|
|
661
|
+
let n = Ht() || Xt(t.config.theme);
|
|
662
|
+
e.className = Be(n);
|
|
663
|
+
const i = e.attachShadow({ mode: "open" }), r = document.createElement("style");
|
|
664
|
+
r.textContent = qt(t.config.accent || null), i.appendChild(r);
|
|
665
|
+
const o = Ce[t.config.widgetPosition] ? t.config.widgetPosition : "bottom-right", a = document.createElement("div");
|
|
666
|
+
a.className = `dock ${o.includes("right") ? "at-right" : "at-left"}` + (o.startsWith("top") ? " at-top" : ""), a.style.cssText = Ce[o];
|
|
667
|
+
const s = {
|
|
668
|
+
current: () => n,
|
|
669
|
+
label: () => P.find((g) => g.value === n).label,
|
|
670
|
+
cycle() {
|
|
671
|
+
const g = P[(P.findIndex((b) => b.value === n) + 1) % P.length];
|
|
672
|
+
return n = g.value, e.className = Be(n), zt(n), g;
|
|
673
|
+
}
|
|
674
|
+
}, c = document.createElement("button");
|
|
675
|
+
c.className = "launcher", c.type = "button", c.innerHTML = `<span class="ico" aria-hidden="true"><span class="when-closed"><span class="orb"></span></span><span class="when-open">${Mt}</span></span><span>Report a bug</span>`, c.setAttribute("aria-haspopup", "dialog"), c.setAttribute("aria-expanded", "false");
|
|
649
676
|
let l = null;
|
|
650
677
|
c.addEventListener("click", () => {
|
|
651
678
|
if (l) {
|
|
652
679
|
l.close();
|
|
653
680
|
return;
|
|
654
681
|
}
|
|
655
|
-
l =
|
|
682
|
+
l = h();
|
|
656
683
|
});
|
|
657
|
-
function
|
|
658
|
-
|
|
659
|
-
let
|
|
684
|
+
function h() {
|
|
685
|
+
I(), p();
|
|
686
|
+
let g = null, b = !1;
|
|
660
687
|
const B = () => {
|
|
661
|
-
|
|
662
|
-
},
|
|
663
|
-
close: () =>
|
|
664
|
-
destroy: () =>
|
|
688
|
+
b = !0, c.removeAttribute("aria-busy"), l = null;
|
|
689
|
+
}, y = {
|
|
690
|
+
close: () => g ? g.close() : B(),
|
|
691
|
+
destroy: () => g ? g.destroy() : B()
|
|
665
692
|
};
|
|
666
|
-
return c.setAttribute("aria-busy", "true"),
|
|
667
|
-
|
|
668
|
-
root:
|
|
693
|
+
return c.setAttribute("aria-busy", "true"), Ie(t.config.chunkBase).then(({ openPanel: C }) => {
|
|
694
|
+
b || (c.removeAttribute("aria-busy"), a.classList.add("over"), c.setAttribute("aria-expanded", "true"), g = C({
|
|
695
|
+
root: i,
|
|
669
696
|
host: e,
|
|
670
697
|
dock: a,
|
|
671
698
|
client: t,
|
|
672
699
|
preloadCall: u,
|
|
700
|
+
themeControls: s,
|
|
673
701
|
onClose: () => {
|
|
674
702
|
l = null, a.classList.remove("over"), c.setAttribute("aria-expanded", "false");
|
|
675
703
|
}
|
|
676
704
|
}));
|
|
677
705
|
}, () => {
|
|
678
|
-
|
|
679
|
-
}),
|
|
706
|
+
b || (B(), $());
|
|
707
|
+
}), y;
|
|
680
708
|
}
|
|
681
|
-
const
|
|
682
|
-
|
|
709
|
+
const f = () => {
|
|
710
|
+
Ie(t.config.chunkBase).catch(() => {
|
|
683
711
|
});
|
|
684
712
|
};
|
|
685
|
-
for (const
|
|
686
|
-
c.addEventListener(
|
|
687
|
-
const d =
|
|
713
|
+
for (const g of ["pointerenter", "touchstart", "focus"])
|
|
714
|
+
c.addEventListener(g, f, { once: !0, passive: !0 });
|
|
715
|
+
const d = Ee(f);
|
|
688
716
|
function u() {
|
|
689
|
-
|
|
717
|
+
q(t.config.chunkBase).catch(() => {
|
|
690
718
|
});
|
|
691
719
|
}
|
|
692
|
-
let
|
|
720
|
+
let m = null;
|
|
693
721
|
function $() {
|
|
694
|
-
|
|
695
|
-
c.focus(), l || (l =
|
|
696
|
-
}),
|
|
697
|
-
c.focus(),
|
|
698
|
-
}), a.prepend(
|
|
699
|
-
}
|
|
700
|
-
function
|
|
701
|
-
|
|
702
|
-
}
|
|
703
|
-
let
|
|
704
|
-
function
|
|
705
|
-
|
|
722
|
+
I(), m = document.createElement("div"), m.className = "msg err loadfail", m.setAttribute("role", "alert"), m.innerHTML = `${ze}<span>The report form didn't load. Check your connection and try again.</span><button type="button" data-act="retry">Try again</button><button type="button" data-act="dismiss" aria-label="Dismiss">${qe}</button>`, m.querySelector('[data-act="retry"]').addEventListener("click", () => {
|
|
723
|
+
c.focus(), l || (l = h());
|
|
724
|
+
}), m.querySelector('[data-act="dismiss"]').addEventListener("click", () => {
|
|
725
|
+
c.focus(), I();
|
|
726
|
+
}), a.prepend(m);
|
|
727
|
+
}
|
|
728
|
+
function I() {
|
|
729
|
+
m == null || m.remove(), m = null;
|
|
730
|
+
}
|
|
731
|
+
let v = null;
|
|
732
|
+
function T(g) {
|
|
733
|
+
p(), v = Dt(g, {
|
|
706
734
|
where: "launcher",
|
|
707
|
-
onDismiss: (
|
|
708
|
-
t.dismissAnnouncement(
|
|
735
|
+
onDismiss: (b) => {
|
|
736
|
+
t.dismissAnnouncement(b), c.focus(), p();
|
|
709
737
|
}
|
|
710
|
-
}),
|
|
738
|
+
}), m ? m.after(v) : a.prepend(v);
|
|
711
739
|
}
|
|
712
|
-
function
|
|
713
|
-
|
|
740
|
+
function p() {
|
|
741
|
+
v == null || v.remove(), v = null;
|
|
714
742
|
}
|
|
715
|
-
const
|
|
716
|
-
} :
|
|
717
|
-
t.announcements().then((
|
|
718
|
-
const
|
|
719
|
-
|
|
743
|
+
const k = t.config.announcements === !1 ? () => {
|
|
744
|
+
} : Ee(() => {
|
|
745
|
+
t.announcements().then((g) => {
|
|
746
|
+
const b = g.find((B) => B.placement === "launcher");
|
|
747
|
+
b && !l && e.isConnected && T(b);
|
|
720
748
|
}).catch(() => {
|
|
721
749
|
});
|
|
722
750
|
});
|
|
723
|
-
return a.append(
|
|
751
|
+
return a.append(c), i.appendChild(a), document.body.appendChild(e), t.widgetControls = {
|
|
724
752
|
open: () => {
|
|
725
753
|
l || c.click();
|
|
726
754
|
},
|
|
@@ -729,34 +757,34 @@ function Ut(t) {
|
|
|
729
757
|
},
|
|
730
758
|
isOpen: () => !!l
|
|
731
759
|
}, () => {
|
|
732
|
-
d(),
|
|
760
|
+
d(), k(), l == null || l.destroy(), e.remove(), t.widgetControls = null;
|
|
733
761
|
};
|
|
734
762
|
}
|
|
735
|
-
function
|
|
763
|
+
function Xt(t) {
|
|
736
764
|
return t === "dark" || t === "light" ? t : "auto";
|
|
737
765
|
}
|
|
738
|
-
function
|
|
766
|
+
function Be(t) {
|
|
739
767
|
return t === "dark" ? "bc-dark" : t === "light" ? "bc-light" : "bc-auto";
|
|
740
768
|
}
|
|
741
|
-
function
|
|
769
|
+
function Ee(t) {
|
|
742
770
|
let e = () => {
|
|
743
771
|
};
|
|
744
772
|
const n = () => {
|
|
745
773
|
if (typeof requestIdleCallback == "function") {
|
|
746
|
-
const
|
|
747
|
-
e = () => cancelIdleCallback(
|
|
774
|
+
const i = requestIdleCallback(t, { timeout: 5e3 });
|
|
775
|
+
e = () => cancelIdleCallback(i);
|
|
748
776
|
} else {
|
|
749
|
-
const
|
|
750
|
-
e = () => clearTimeout(
|
|
777
|
+
const i = setTimeout(t, 1500);
|
|
778
|
+
e = () => clearTimeout(i);
|
|
751
779
|
}
|
|
752
780
|
};
|
|
753
781
|
return document.readyState === "complete" ? n() : (window.addEventListener("load", n, { once: !0 }), e = () => window.removeEventListener("load", n)), () => e();
|
|
754
782
|
}
|
|
755
|
-
const
|
|
756
|
-
function
|
|
757
|
-
return t ||
|
|
783
|
+
const Wt = "Too many requests are being sent from here at the moment. Please try again in a minute.";
|
|
784
|
+
function N(t) {
|
|
785
|
+
return t || Wt;
|
|
758
786
|
}
|
|
759
|
-
const
|
|
787
|
+
const Jt = typeof window < "u" && window.fetch ? window.fetch.bind(window) : null, Yt = typeof XMLHttpRequest < "u" ? XMLHttpRequest.prototype.open : null, Vt = typeof XMLHttpRequest < "u" ? XMLHttpRequest.prototype.send : null, Zt = [
|
|
760
788
|
"image/png",
|
|
761
789
|
"image/jpeg",
|
|
762
790
|
"image/webp",
|
|
@@ -777,27 +805,27 @@ const _t = typeof window < "u" && window.fetch ? window.fetch.bind(window) : nul
|
|
|
777
805
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
778
806
|
"application/vnd.ms-excel",
|
|
779
807
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
780
|
-
],
|
|
808
|
+
], $e = [
|
|
781
809
|
"image/png",
|
|
782
810
|
"image/jpeg",
|
|
783
811
|
"image/webp",
|
|
784
812
|
"video/webm",
|
|
785
813
|
"video/mp4"
|
|
786
|
-
],
|
|
814
|
+
], fi = () => {
|
|
787
815
|
var t;
|
|
788
816
|
return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getUserMedia && typeof MediaRecorder < "u");
|
|
789
|
-
},
|
|
817
|
+
}, pi = () => {
|
|
790
818
|
var t;
|
|
791
819
|
return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getDisplayMedia && typeof MediaRecorder < "u");
|
|
792
|
-
},
|
|
820
|
+
}, gi = () => {
|
|
793
821
|
var t;
|
|
794
822
|
return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getDisplayMedia);
|
|
795
823
|
};
|
|
796
|
-
function
|
|
824
|
+
function ae(t, e = Zt) {
|
|
797
825
|
const n = String(t || "").split(";")[0].trim().toLowerCase();
|
|
798
826
|
return e.includes(n) ? n : null;
|
|
799
827
|
}
|
|
800
|
-
async function
|
|
828
|
+
async function mi() {
|
|
801
829
|
const t = await navigator.mediaDevices.getDisplayMedia({
|
|
802
830
|
video: { frameRate: 1 },
|
|
803
831
|
audio: !1
|
|
@@ -805,268 +833,268 @@ async function ao() {
|
|
|
805
833
|
try {
|
|
806
834
|
const e = t.getVideoTracks()[0], n = document.createElement("video");
|
|
807
835
|
n.srcObject = t, n.muted = !0, n.playsInline = !0, await n.play(), await new Promise((s) => requestAnimationFrame(() => requestAnimationFrame(s)));
|
|
808
|
-
const { width:
|
|
809
|
-
|
|
810
|
-
const a = await new Promise((s) =>
|
|
836
|
+
const { width: i, height: r } = e.getSettings(), o = document.createElement("canvas");
|
|
837
|
+
o.width = i || n.videoWidth, o.height = r || n.videoHeight, o.getContext("2d").drawImage(n, 0, 0, o.width, o.height);
|
|
838
|
+
const a = await new Promise((s) => o.toBlob(s, "image/png"));
|
|
811
839
|
if (!a) throw new Error("The browser returned an empty screenshot.");
|
|
812
840
|
return { blob: a, mime: "image/png", kind: "SCREENSHOT" };
|
|
813
841
|
} finally {
|
|
814
842
|
t.getTracks().forEach((e) => e.stop());
|
|
815
843
|
}
|
|
816
844
|
}
|
|
817
|
-
async function
|
|
818
|
-
const
|
|
845
|
+
async function wi({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
|
|
846
|
+
const i = await navigator.mediaDevices.getDisplayMedia({
|
|
819
847
|
video: { frameRate: 15 },
|
|
820
848
|
audio: !1
|
|
821
|
-
}), r = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"].find((u) => MediaRecorder.isTypeSupported(u)) || "video/webm",
|
|
822
|
-
|
|
849
|
+
}), r = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"].find((u) => MediaRecorder.isTypeSupported(u)) || "video/webm", o = new MediaRecorder(i, { mimeType: r, videoBitsPerSecond: 25e5 }), a = [];
|
|
850
|
+
o.ondataavailable = (u) => {
|
|
823
851
|
u.data.size && a.push(u.data);
|
|
824
|
-
},
|
|
852
|
+
}, o.start(1e3);
|
|
825
853
|
const s = Date.now(), c = setInterval(() => e == null ? void 0 : e(Math.floor((Date.now() - s) / 1e3)), 500), l = () => {
|
|
826
|
-
clearInterval(c), clearTimeout(d),
|
|
827
|
-
},
|
|
828
|
-
|
|
854
|
+
clearInterval(c), clearTimeout(d), i.getTracks().forEach((u) => u.stop());
|
|
855
|
+
}, h = new Promise((u) => {
|
|
856
|
+
o.onstop = () => {
|
|
829
857
|
l(), u(new Blob(a, { type: r }));
|
|
830
858
|
};
|
|
831
|
-
}),
|
|
832
|
-
|
|
859
|
+
}), f = () => {
|
|
860
|
+
o.state !== "inactive" && o.stop(), n == null || n();
|
|
833
861
|
};
|
|
834
|
-
|
|
835
|
-
const d = setTimeout(
|
|
862
|
+
i.getVideoTracks()[0].addEventListener("ended", f);
|
|
863
|
+
const d = setTimeout(f, t);
|
|
836
864
|
return {
|
|
837
865
|
mime: r,
|
|
838
866
|
maxMs: t,
|
|
839
867
|
async stop() {
|
|
840
|
-
return clearTimeout(d),
|
|
868
|
+
return clearTimeout(d), o.state !== "inactive" && o.stop(), { blob: await h, mime: r, kind: "VIDEO" };
|
|
841
869
|
},
|
|
842
870
|
cancel() {
|
|
843
|
-
l(),
|
|
871
|
+
l(), o.state !== "inactive" && o.stop();
|
|
844
872
|
}
|
|
845
873
|
};
|
|
846
874
|
}
|
|
847
|
-
async function
|
|
848
|
-
const
|
|
849
|
-
|
|
875
|
+
async function yi({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
|
|
876
|
+
const i = await navigator.mediaDevices.getUserMedia({ audio: !0 }), r = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4", "audio/ogg"].find((u) => MediaRecorder.isTypeSupported(u)) || "", o = new MediaRecorder(i, r ? { mimeType: r } : void 0), a = [];
|
|
877
|
+
o.ondataavailable = (u) => {
|
|
850
878
|
u.data.size && a.push(u.data);
|
|
851
|
-
},
|
|
879
|
+
}, o.start(1e3);
|
|
852
880
|
const s = Date.now(), c = setInterval(() => e == null ? void 0 : e(Math.floor((Date.now() - s) / 1e3)), 500), l = () => {
|
|
853
|
-
clearInterval(c), clearTimeout(d),
|
|
854
|
-
},
|
|
855
|
-
|
|
856
|
-
l(), u(new Blob(a, { type:
|
|
881
|
+
clearInterval(c), clearTimeout(d), i.getTracks().forEach((u) => u.stop());
|
|
882
|
+
}, h = new Promise((u) => {
|
|
883
|
+
o.onstop = () => {
|
|
884
|
+
l(), u(new Blob(a, { type: o.mimeType || r }));
|
|
857
885
|
};
|
|
858
886
|
}), d = setTimeout(() => {
|
|
859
|
-
|
|
887
|
+
o.state !== "inactive" && o.stop(), n == null || n();
|
|
860
888
|
}, t);
|
|
861
889
|
return {
|
|
862
|
-
mime:
|
|
890
|
+
mime: o.mimeType || r,
|
|
863
891
|
maxMs: t,
|
|
864
892
|
async stop() {
|
|
865
|
-
clearTimeout(d),
|
|
866
|
-
const u = await
|
|
867
|
-
return { blob: u, mime: u.type ||
|
|
893
|
+
clearTimeout(d), o.state !== "inactive" && o.stop();
|
|
894
|
+
const u = await h;
|
|
895
|
+
return { blob: u, mime: u.type || o.mimeType || r, kind: "AUDIO" };
|
|
868
896
|
},
|
|
869
897
|
cancel() {
|
|
870
|
-
l(),
|
|
898
|
+
l(), o.state !== "inactive" && o.stop();
|
|
871
899
|
}
|
|
872
900
|
};
|
|
873
901
|
}
|
|
874
|
-
async function
|
|
902
|
+
async function Gt({ apiBase: t, apiKey: e, blob: n, mime: i, onProgress: r }) {
|
|
875
903
|
var l;
|
|
876
|
-
const
|
|
877
|
-
if (!
|
|
878
|
-
throw new Error(`[BugCatch] ${
|
|
879
|
-
const a = await
|
|
904
|
+
const o = ae(i || n.type);
|
|
905
|
+
if (!o)
|
|
906
|
+
throw new Error(`[BugCatch] ${i || n.type || "that file"} can't be attached.`);
|
|
907
|
+
const a = await Jt(`${t}/ingest/presign`, {
|
|
880
908
|
method: "POST",
|
|
881
909
|
headers: { "Content-Type": "application/json", "X-BugCatch-Key": e },
|
|
882
|
-
body: JSON.stringify({ mime:
|
|
910
|
+
body: JSON.stringify({ mime: o })
|
|
883
911
|
});
|
|
884
912
|
if (a.status === 429) {
|
|
885
|
-
let
|
|
913
|
+
let h = "";
|
|
886
914
|
try {
|
|
887
|
-
|
|
915
|
+
h = ((l = await a.json()) == null ? void 0 : l.message) || "";
|
|
888
916
|
} catch {
|
|
889
917
|
}
|
|
890
|
-
throw new Error(`[BugCatch] ${
|
|
918
|
+
throw new Error(`[BugCatch] ${N(typeof h == "string" ? h : "")}`);
|
|
891
919
|
}
|
|
892
920
|
if (!a.ok) throw new Error(`[BugCatch] could not start the upload (HTTP ${a.status}).`);
|
|
893
921
|
const { key: s, uploadUrl: c } = await a.json();
|
|
894
|
-
return await
|
|
922
|
+
return await Qt(c, n, o, r), { storageKey: s, mime: o };
|
|
895
923
|
}
|
|
896
|
-
function
|
|
897
|
-
return new Promise((r,
|
|
924
|
+
function Qt(t, e, n, i) {
|
|
925
|
+
return new Promise((r, o) => {
|
|
898
926
|
const a = new XMLHttpRequest();
|
|
899
|
-
|
|
900
|
-
s.lengthComputable && (
|
|
927
|
+
Yt.call(a, "PUT", t, !0), a.setRequestHeader("Content-Type", n), a.upload.onprogress = (s) => {
|
|
928
|
+
s.lengthComputable && (i == null || i(s.loaded / s.total));
|
|
901
929
|
}, a.onload = () => {
|
|
902
|
-
a.status >= 200 && a.status < 300 ? r() :
|
|
903
|
-
}, a.onerror = () =>
|
|
930
|
+
a.status >= 200 && a.status < 300 ? r() : o(new Error(`[BugCatch] upload failed (HTTP ${a.status}).`));
|
|
931
|
+
}, a.onerror = () => o(new Error(
|
|
904
932
|
"[BugCatch] the browser blocked the upload to storage. If this is a new environment, the media bucket is probably missing its CORS policy."
|
|
905
|
-
)), a.onabort = () =>
|
|
933
|
+
)), a.onabort = () => o(new Error("[BugCatch] upload cancelled.")), Vt.call(a, e);
|
|
906
934
|
});
|
|
907
935
|
}
|
|
908
|
-
function
|
|
936
|
+
function bi(t) {
|
|
909
937
|
return t < 1024 ? `${t} B` : t < 1024 * 1024 ? `${(t / 1024).toFixed(0)} KB` : `${(t / 1024 / 1024).toFixed(1)} MB`;
|
|
910
938
|
}
|
|
911
|
-
function
|
|
939
|
+
function xi(t) {
|
|
912
940
|
const e = Math.floor(t / 60), n = t % 60;
|
|
913
941
|
return `${e}:${String(n).padStart(2, "0")}`;
|
|
914
942
|
}
|
|
915
|
-
const
|
|
916
|
-
let
|
|
917
|
-
function
|
|
918
|
-
|
|
943
|
+
const Y = "bugcatch.watch", Te = [2e3, 5e3, 15e3, 3e4, 6e4], en = 5e3;
|
|
944
|
+
let _ = null;
|
|
945
|
+
function tn(t) {
|
|
946
|
+
_ = t || null;
|
|
919
947
|
}
|
|
920
|
-
const
|
|
921
|
-
function
|
|
922
|
-
return
|
|
948
|
+
const fe = () => _ ? `${Y}:${_}` : Y;
|
|
949
|
+
function ee() {
|
|
950
|
+
return _ ? `?projectId=${encodeURIComponent(_)}` : "";
|
|
923
951
|
}
|
|
924
952
|
function E() {
|
|
925
953
|
try {
|
|
926
954
|
const t = window.localStorage;
|
|
927
|
-
return (t == null ? void 0 : t.getItem(
|
|
955
|
+
return (t == null ? void 0 : t.getItem(fe())) || (t == null ? void 0 : t.getItem(Y)) || null;
|
|
928
956
|
} catch {
|
|
929
957
|
return null;
|
|
930
958
|
}
|
|
931
959
|
}
|
|
932
|
-
function
|
|
960
|
+
function se(t) {
|
|
933
961
|
var e;
|
|
934
962
|
if (t)
|
|
935
963
|
try {
|
|
936
|
-
(e = window.localStorage) == null || e.setItem(
|
|
964
|
+
(e = window.localStorage) == null || e.setItem(fe(), t);
|
|
937
965
|
} catch {
|
|
938
966
|
}
|
|
939
967
|
}
|
|
940
|
-
function
|
|
968
|
+
function K() {
|
|
941
969
|
var t, e;
|
|
942
970
|
try {
|
|
943
|
-
(t = window.localStorage) == null || t.removeItem(
|
|
971
|
+
(t = window.localStorage) == null || t.removeItem(fe()), (e = window.localStorage) == null || e.removeItem(Y);
|
|
944
972
|
} catch {
|
|
945
973
|
}
|
|
946
|
-
|
|
974
|
+
Ze();
|
|
947
975
|
}
|
|
948
|
-
const
|
|
949
|
-
function
|
|
976
|
+
const V = "bugcatch.unread";
|
|
977
|
+
function nn(t) {
|
|
950
978
|
return [(t == null ? void 0 : t.bugId) || "report", (t == null ? void 0 : t.kind) || "status", (t == null ? void 0 : t.at) || ""].join("|");
|
|
951
979
|
}
|
|
952
|
-
function
|
|
980
|
+
function H() {
|
|
953
981
|
var t;
|
|
954
982
|
try {
|
|
955
|
-
const e = (t = window.localStorage) == null ? void 0 : t.getItem(
|
|
956
|
-
return Array.isArray(n) ? n.filter((
|
|
983
|
+
const e = (t = window.localStorage) == null ? void 0 : t.getItem(V), n = e ? JSON.parse(e) : [];
|
|
984
|
+
return Array.isArray(n) ? n.filter((i) => i && typeof i.id == "string") : [];
|
|
957
985
|
} catch {
|
|
958
986
|
return [];
|
|
959
987
|
}
|
|
960
988
|
}
|
|
961
|
-
function
|
|
989
|
+
function te(t) {
|
|
962
990
|
var e, n;
|
|
963
991
|
try {
|
|
964
|
-
t.length ? (e = window.localStorage) == null || e.setItem(
|
|
992
|
+
t.length ? (e = window.localStorage) == null || e.setItem(V, JSON.stringify(t)) : (n = window.localStorage) == null || n.removeItem(V);
|
|
965
993
|
} catch {
|
|
966
994
|
}
|
|
967
995
|
}
|
|
968
|
-
function
|
|
969
|
-
const e = { ...t, id:
|
|
970
|
-
return n.push(e),
|
|
996
|
+
function on(t) {
|
|
997
|
+
const e = { ...t, id: nn(t) }, n = H().filter((i) => i.id !== e.id);
|
|
998
|
+
return n.push(e), te(n.slice(-20)), e;
|
|
971
999
|
}
|
|
972
|
-
function
|
|
973
|
-
const e =
|
|
974
|
-
return
|
|
1000
|
+
function rn(t) {
|
|
1001
|
+
const e = H().filter((n) => n.id !== t);
|
|
1002
|
+
return te(e), e;
|
|
975
1003
|
}
|
|
976
|
-
function
|
|
977
|
-
const e =
|
|
978
|
-
return
|
|
1004
|
+
function an(t) {
|
|
1005
|
+
const e = H().filter((n) => n.bugId !== t);
|
|
1006
|
+
return te(e), e;
|
|
979
1007
|
}
|
|
980
|
-
function
|
|
981
|
-
return
|
|
1008
|
+
function Ze() {
|
|
1009
|
+
return te([]), [];
|
|
982
1010
|
}
|
|
983
|
-
function
|
|
984
|
-
let n = t,
|
|
1011
|
+
function sn(t, e) {
|
|
1012
|
+
let n = t, i = n.indexOf(`
|
|
985
1013
|
|
|
986
1014
|
`);
|
|
987
|
-
for (;
|
|
988
|
-
const r = n.slice(0,
|
|
989
|
-
n = n.slice(
|
|
990
|
-
const
|
|
1015
|
+
for (; i !== -1; ) {
|
|
1016
|
+
const r = n.slice(0, i);
|
|
1017
|
+
n = n.slice(i + 2);
|
|
1018
|
+
const o = r.split(`
|
|
991
1019
|
`).filter((a) => a.startsWith("data:")).map((a) => a.slice(5).trim()).join(`
|
|
992
1020
|
`);
|
|
993
|
-
if (
|
|
1021
|
+
if (o)
|
|
994
1022
|
try {
|
|
995
|
-
e(JSON.parse(
|
|
1023
|
+
e(JSON.parse(o));
|
|
996
1024
|
} catch {
|
|
997
1025
|
}
|
|
998
|
-
|
|
1026
|
+
i = n.indexOf(`
|
|
999
1027
|
|
|
1000
1028
|
`);
|
|
1001
1029
|
}
|
|
1002
1030
|
return n;
|
|
1003
1031
|
}
|
|
1004
|
-
async function
|
|
1032
|
+
async function cn({ apiBase: t }) {
|
|
1005
1033
|
const e = E();
|
|
1006
1034
|
if (!e) return { reporter: null, reports: [] };
|
|
1007
|
-
const n = await fetch(`${t}/ingest/watch/reports${
|
|
1035
|
+
const n = await fetch(`${t}/ingest/watch/reports${ee()}`, {
|
|
1008
1036
|
headers: { Authorization: `Bearer ${e}` }
|
|
1009
1037
|
});
|
|
1010
1038
|
if (n.status === 401)
|
|
1011
|
-
return
|
|
1039
|
+
return K(), { reporter: null, reports: [] };
|
|
1012
1040
|
if (!n.ok) throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);
|
|
1013
1041
|
return n.json();
|
|
1014
1042
|
}
|
|
1015
|
-
async function
|
|
1043
|
+
async function ln({ apiBase: t, bugId: e }) {
|
|
1016
1044
|
const n = E();
|
|
1017
1045
|
if (!n) return null;
|
|
1018
|
-
const
|
|
1046
|
+
const i = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}${ee()}`, {
|
|
1019
1047
|
headers: { Authorization: `Bearer ${n}` }
|
|
1020
1048
|
});
|
|
1021
|
-
if (
|
|
1022
|
-
return
|
|
1023
|
-
if (
|
|
1024
|
-
if (!
|
|
1025
|
-
return
|
|
1049
|
+
if (i.status === 401)
|
|
1050
|
+
return K(), null;
|
|
1051
|
+
if (i.status === 404) return null;
|
|
1052
|
+
if (!i.ok) throw new Error(`[BugCatch] could not load that report (HTTP ${i.status})`);
|
|
1053
|
+
return i.json();
|
|
1026
1054
|
}
|
|
1027
|
-
async function
|
|
1055
|
+
async function un({ apiBase: t, bugId: e, body: n, attachments: i }) {
|
|
1028
1056
|
const r = E();
|
|
1029
1057
|
if (!r) throw new Error("[BugCatch] nothing filed from this browser yet.");
|
|
1030
|
-
const
|
|
1058
|
+
const o = await fetch(
|
|
1031
1059
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/messages`,
|
|
1032
1060
|
{
|
|
1033
1061
|
method: "POST",
|
|
1034
1062
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${r}` },
|
|
1035
1063
|
body: JSON.stringify({
|
|
1036
1064
|
...n ? { body: n } : {},
|
|
1037
|
-
...
|
|
1065
|
+
...i != null && i.length ? { attachments: i } : {}
|
|
1038
1066
|
})
|
|
1039
1067
|
}
|
|
1040
1068
|
);
|
|
1041
|
-
if (
|
|
1042
|
-
throw
|
|
1043
|
-
if (!
|
|
1069
|
+
if (o.status === 401)
|
|
1070
|
+
throw K(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
|
|
1071
|
+
if (!o.ok) {
|
|
1044
1072
|
let a = "";
|
|
1045
1073
|
try {
|
|
1046
|
-
const s = await
|
|
1074
|
+
const s = await o.json();
|
|
1047
1075
|
a = Array.isArray(s.message) ? s.message.join(", ") : s.message || "";
|
|
1048
1076
|
} catch {
|
|
1049
1077
|
}
|
|
1050
|
-
throw
|
|
1078
|
+
throw o.status === 429 ? new Error(N(a)) : new Error(a || `[BugCatch] could not send that (HTTP ${o.status}).`);
|
|
1051
1079
|
}
|
|
1052
|
-
return
|
|
1080
|
+
return o.json();
|
|
1053
1081
|
}
|
|
1054
|
-
async function
|
|
1055
|
-
const
|
|
1082
|
+
async function dn({ apiBase: t, apiKey: e, projectId: n }) {
|
|
1083
|
+
const i = { agent: !1, live: !1 };
|
|
1056
1084
|
try {
|
|
1057
1085
|
const r = await fetch(
|
|
1058
1086
|
`${t}/ingest/calls?projectId=${encodeURIComponent(n)}`,
|
|
1059
1087
|
{ headers: { "X-BugCatch-Key": e } }
|
|
1060
1088
|
);
|
|
1061
|
-
if (!r.ok) return
|
|
1062
|
-
const
|
|
1063
|
-
return
|
|
1089
|
+
if (!r.ok) return i;
|
|
1090
|
+
const o = await r.json();
|
|
1091
|
+
return o != null && o.available ? o.kinds && typeof o.kinds == "object" ? { agent: !1, live: !!o.kinds.live } : { agent: !1, live: o.kind === "live" } : i;
|
|
1064
1092
|
} catch {
|
|
1065
|
-
return
|
|
1093
|
+
return i;
|
|
1066
1094
|
}
|
|
1067
1095
|
}
|
|
1068
|
-
async function
|
|
1069
|
-
const
|
|
1096
|
+
async function hn({ apiBase: t, apiKey: e, token: n, payload: i, watchToken: r }) {
|
|
1097
|
+
const o = await fetch(`${t}/ingest/calls`, {
|
|
1070
1098
|
method: "POST",
|
|
1071
1099
|
headers: {
|
|
1072
1100
|
"Content-Type": "application/json",
|
|
@@ -1079,199 +1107,206 @@ async function on({ apiBase: t, apiKey: e, token: n, payload: o, watchToken: r }
|
|
|
1079
1107
|
},
|
|
1080
1108
|
// The watch token this browser holds, so the one filing hands back covers
|
|
1081
1109
|
// the reports it already could — see withHeldToken in index.js.
|
|
1082
|
-
body: JSON.stringify(r ? { ...
|
|
1110
|
+
body: JSON.stringify(r ? { ...i, watchToken: r } : i)
|
|
1083
1111
|
});
|
|
1084
|
-
if (!
|
|
1112
|
+
if (!o.ok) {
|
|
1085
1113
|
let a = "";
|
|
1086
1114
|
try {
|
|
1087
|
-
const c = await
|
|
1115
|
+
const c = await o.json();
|
|
1088
1116
|
a = Array.isArray(c.message) ? c.message.join(", ") : c.message || "";
|
|
1089
1117
|
} catch {
|
|
1090
1118
|
}
|
|
1091
1119
|
const s = new Error(
|
|
1092
|
-
|
|
1120
|
+
o.status === 429 ? N(a) : a || `[BugCatch] the call could not be started (HTTP ${o.status}).`
|
|
1093
1121
|
);
|
|
1094
|
-
throw s.status =
|
|
1122
|
+
throw s.status = o.status, s;
|
|
1095
1123
|
}
|
|
1096
|
-
return
|
|
1124
|
+
return o.json();
|
|
1097
1125
|
}
|
|
1098
|
-
async function
|
|
1126
|
+
async function Ae({ apiBase: t, bugId: e }) {
|
|
1099
1127
|
const n = E();
|
|
1100
1128
|
if (!n) return !1;
|
|
1101
1129
|
try {
|
|
1102
|
-
const
|
|
1130
|
+
const i = await fetch(
|
|
1103
1131
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,
|
|
1104
1132
|
{ headers: { Authorization: `Bearer ${n}` } }
|
|
1105
1133
|
);
|
|
1106
|
-
if (!
|
|
1107
|
-
const r = await
|
|
1134
|
+
if (!i.ok) return !1;
|
|
1135
|
+
const r = await i.json();
|
|
1108
1136
|
return !!(r != null && r.offered);
|
|
1109
1137
|
} catch {
|
|
1110
1138
|
return !1;
|
|
1111
1139
|
}
|
|
1112
1140
|
}
|
|
1113
|
-
async function
|
|
1141
|
+
async function fn({ apiBase: t, bugId: e }) {
|
|
1114
1142
|
const n = E();
|
|
1115
1143
|
if (!n) throw new Error("[BugCatch] nothing filed from this browser yet.");
|
|
1116
|
-
const
|
|
1144
|
+
const i = await fetch(
|
|
1117
1145
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,
|
|
1118
1146
|
{ method: "POST", headers: { Authorization: `Bearer ${n}` } }
|
|
1119
1147
|
);
|
|
1120
|
-
if (
|
|
1121
|
-
throw
|
|
1122
|
-
if (!
|
|
1148
|
+
if (i.status === 401)
|
|
1149
|
+
throw K(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
|
|
1150
|
+
if (!i.ok) {
|
|
1123
1151
|
let r = "";
|
|
1124
1152
|
try {
|
|
1125
|
-
const
|
|
1126
|
-
r = Array.isArray(
|
|
1153
|
+
const o = await i.json();
|
|
1154
|
+
r = Array.isArray(o.message) ? o.message.join(", ") : o.message || "";
|
|
1127
1155
|
} catch {
|
|
1128
1156
|
}
|
|
1129
|
-
throw new Error(r || `[BugCatch] the call could not be started (HTTP ${
|
|
1157
|
+
throw new Error(r || `[BugCatch] the call could not be started (HTTP ${i.status}).`);
|
|
1130
1158
|
}
|
|
1131
|
-
return
|
|
1159
|
+
return i.json();
|
|
1132
1160
|
}
|
|
1133
|
-
async function
|
|
1134
|
-
const
|
|
1135
|
-
if (
|
|
1161
|
+
async function pn({ apiBase: t, bugId: e, callId: n }) {
|
|
1162
|
+
const i = E();
|
|
1163
|
+
if (i)
|
|
1136
1164
|
try {
|
|
1137
1165
|
await fetch(
|
|
1138
1166
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/give-up`,
|
|
1139
|
-
{ method: "POST", headers: { Authorization: `Bearer ${
|
|
1167
|
+
{ method: "POST", headers: { Authorization: `Bearer ${i}` } }
|
|
1140
1168
|
);
|
|
1141
1169
|
} catch {
|
|
1142
1170
|
}
|
|
1143
1171
|
}
|
|
1144
|
-
async function
|
|
1145
|
-
const
|
|
1146
|
-
if (!
|
|
1172
|
+
async function gn({ apiBase: t, bugId: e, callId: n }) {
|
|
1173
|
+
const i = E();
|
|
1174
|
+
if (!i) throw new Error("[BugCatch] nothing filed from this browser yet.");
|
|
1147
1175
|
const r = await fetch(
|
|
1148
1176
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/answer`,
|
|
1149
|
-
{ method: "POST", headers: { Authorization: `Bearer ${
|
|
1177
|
+
{ method: "POST", headers: { Authorization: `Bearer ${i}` } }
|
|
1150
1178
|
);
|
|
1151
1179
|
if (r.status === 401)
|
|
1152
|
-
throw
|
|
1180
|
+
throw K(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
|
|
1153
1181
|
if (r.status === 409)
|
|
1154
1182
|
throw new Error("[BugCatch] that call is no longer ringing.");
|
|
1155
1183
|
if (!r.ok) {
|
|
1156
|
-
let
|
|
1184
|
+
let o = "";
|
|
1157
1185
|
try {
|
|
1158
1186
|
const a = await r.json();
|
|
1159
|
-
|
|
1187
|
+
o = Array.isArray(a.message) ? a.message.join(", ") : a.message || "";
|
|
1160
1188
|
} catch {
|
|
1161
1189
|
}
|
|
1162
|
-
throw new Error(
|
|
1190
|
+
throw new Error(o || `[BugCatch] the call could not be answered (HTTP ${r.status}).`);
|
|
1163
1191
|
}
|
|
1164
1192
|
return r.json();
|
|
1165
1193
|
}
|
|
1166
|
-
async function
|
|
1167
|
-
const
|
|
1168
|
-
if (
|
|
1194
|
+
async function je({ apiBase: t, bugId: e, callId: n }) {
|
|
1195
|
+
const i = E();
|
|
1196
|
+
if (i)
|
|
1169
1197
|
try {
|
|
1170
1198
|
await fetch(
|
|
1171
1199
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/decline`,
|
|
1172
|
-
{ method: "POST", headers: { Authorization: `Bearer ${
|
|
1200
|
+
{ method: "POST", headers: { Authorization: `Bearer ${i}` } }
|
|
1173
1201
|
);
|
|
1174
1202
|
} catch {
|
|
1175
1203
|
}
|
|
1176
1204
|
}
|
|
1177
|
-
function
|
|
1178
|
-
let n = !0,
|
|
1179
|
-
async function
|
|
1205
|
+
function mn({ apiBase: t, onUpdate: e }) {
|
|
1206
|
+
let n = !0, i = 0, r = null;
|
|
1207
|
+
async function o() {
|
|
1180
1208
|
const a = E();
|
|
1181
1209
|
if (!a) throw new Error("nothing filed from this browser yet");
|
|
1182
1210
|
r = new AbortController();
|
|
1183
|
-
const s = await fetch(`${t}/ingest/watch/stream${
|
|
1211
|
+
const s = await fetch(`${t}/ingest/watch/stream${ee()}`, {
|
|
1184
1212
|
headers: { Authorization: `Bearer ${a}`, Accept: "text/event-stream" },
|
|
1185
1213
|
signal: r.signal
|
|
1186
1214
|
});
|
|
1187
1215
|
if (s.status === 401)
|
|
1188
|
-
throw n = !1,
|
|
1216
|
+
throw n = !1, K(), new Error("subscription no longer valid");
|
|
1189
1217
|
if (!s.ok || !s.body) throw new Error(`stream failed (${s.status})`);
|
|
1190
|
-
const c = Date.now(), l = s.body.getReader(),
|
|
1191
|
-
let
|
|
1218
|
+
const c = Date.now(), l = s.body.getReader(), h = new TextDecoder();
|
|
1219
|
+
let f = "";
|
|
1192
1220
|
try {
|
|
1193
1221
|
for (; ; ) {
|
|
1194
1222
|
const { value: d, done: u } = await l.read();
|
|
1195
1223
|
if (u) break;
|
|
1196
|
-
|
|
1197
|
-
if (
|
|
1224
|
+
f += h.decode(d, { stream: !0 }), f = sn(f, (m) => {
|
|
1225
|
+
if (m.type !== "ping")
|
|
1198
1226
|
try {
|
|
1199
|
-
e(
|
|
1227
|
+
e(m);
|
|
1200
1228
|
} catch {
|
|
1201
1229
|
}
|
|
1202
1230
|
});
|
|
1203
1231
|
}
|
|
1204
1232
|
} finally {
|
|
1205
|
-
Date.now() - c >=
|
|
1233
|
+
Date.now() - c >= en && (i = 0);
|
|
1206
1234
|
}
|
|
1207
1235
|
}
|
|
1208
1236
|
return (async () => {
|
|
1209
1237
|
for (; n; ) {
|
|
1210
1238
|
try {
|
|
1211
|
-
await
|
|
1239
|
+
await o();
|
|
1212
1240
|
} catch (s) {
|
|
1213
1241
|
if ((s == null ? void 0 : s.name) === "AbortError") return;
|
|
1214
1242
|
}
|
|
1215
1243
|
if (!n) return;
|
|
1216
|
-
const a =
|
|
1217
|
-
|
|
1244
|
+
const a = Te[Math.min(i, Te.length - 1)];
|
|
1245
|
+
i += 1, await new Promise((s) => setTimeout(s, a));
|
|
1218
1246
|
}
|
|
1219
1247
|
})(), () => {
|
|
1220
1248
|
n = !1, r == null || r.abort(), r = null;
|
|
1221
1249
|
};
|
|
1222
1250
|
}
|
|
1223
|
-
const
|
|
1251
|
+
const wn = {
|
|
1224
1252
|
OPEN: "is open",
|
|
1225
1253
|
IN_PROGRESS: "is being worked on",
|
|
1226
1254
|
RESOLVED: "has been fixed",
|
|
1227
1255
|
CLOSED: "has been closed"
|
|
1228
|
-
},
|
|
1256
|
+
}, yn = {
|
|
1229
1257
|
status: null,
|
|
1230
1258
|
// falls back to the host's configured accent
|
|
1231
|
-
severity: "#
|
|
1232
|
-
assignment: "#
|
|
1233
|
-
reply: "#
|
|
1259
|
+
severity: "#f2a54a",
|
|
1260
|
+
assignment: "#79a8ff",
|
|
1261
|
+
reply: "#4fd19a"
|
|
1262
|
+
}, j = {
|
|
1263
|
+
bg: "#111113",
|
|
1264
|
+
fg: "#f3f2ef",
|
|
1265
|
+
muted: "#b3b0aa",
|
|
1266
|
+
faint: "#8f8c86",
|
|
1267
|
+
ring: "rgba(255,255,255,.09)",
|
|
1268
|
+
brand: "#a59cff"
|
|
1234
1269
|
};
|
|
1235
|
-
function
|
|
1236
|
-
return t != null && t.summary ? t.summary : `Your report ${
|
|
1270
|
+
function Oe(t) {
|
|
1271
|
+
return t != null && t.summary ? t.summary : `Your report ${wn[t == null ? void 0 : t.status] || "was updated"}`;
|
|
1237
1272
|
}
|
|
1238
|
-
function
|
|
1273
|
+
function bn(t) {
|
|
1239
1274
|
var e;
|
|
1240
1275
|
return (t == null ? void 0 : t.kind) === "reply" && ((e = t.reply) != null && e.body) ? `${t.reply.author ? `${t.reply.author}: ` : ""}${t.reply.body}` : (t == null ? void 0 : t.title) || "";
|
|
1241
1276
|
}
|
|
1242
|
-
function
|
|
1277
|
+
function xn(t) {
|
|
1243
1278
|
const e = Date.parse(t || "");
|
|
1244
1279
|
if (!Number.isFinite(e)) return "";
|
|
1245
1280
|
const n = Math.round((Date.now() - e) / 6e4);
|
|
1246
1281
|
if (n < 1) return "just now";
|
|
1247
1282
|
if (n < 60) return `${n}m ago`;
|
|
1248
|
-
const
|
|
1249
|
-
if (
|
|
1250
|
-
const r = Math.round(
|
|
1283
|
+
const i = Math.round(n / 60);
|
|
1284
|
+
if (i < 24) return `${i}h ago`;
|
|
1285
|
+
const r = Math.round(i / 24);
|
|
1251
1286
|
return r === 1 ? "yesterday" : `${r}d ago`;
|
|
1252
1287
|
}
|
|
1253
|
-
function
|
|
1288
|
+
function kn() {
|
|
1254
1289
|
var t;
|
|
1255
1290
|
try {
|
|
1256
|
-
const e = document.querySelector('[data-bugcatch="widget"]'), n = (t = e == null ? void 0 : e.shadowRoot) == null ? void 0 : t.querySelector(".dock"),
|
|
1257
|
-
return
|
|
1291
|
+
const e = document.querySelector('[data-bugcatch="widget"]'), n = (t = e == null ? void 0 : e.shadowRoot) == null ? void 0 : t.querySelector(".dock"), i = (n == null ? void 0 : n.getBoundingClientRect().height) || 0;
|
|
1292
|
+
return i ? Math.round(i) + 12 : 0;
|
|
1258
1293
|
} catch {
|
|
1259
1294
|
return 0;
|
|
1260
1295
|
}
|
|
1261
1296
|
}
|
|
1262
|
-
function
|
|
1263
|
-
accent: t =
|
|
1297
|
+
function vn({
|
|
1298
|
+
accent: t = null,
|
|
1264
1299
|
position: e = "bottom-right",
|
|
1265
1300
|
onRead: n = null,
|
|
1266
|
-
onReadAll:
|
|
1301
|
+
onReadAll: i = null,
|
|
1267
1302
|
onCall: r = null
|
|
1268
1303
|
} = {}) {
|
|
1269
|
-
const [
|
|
1270
|
-
let
|
|
1304
|
+
const [o, a] = String(e).split("-"), s = o === "top", c = a === "left", l = /* @__PURE__ */ new Map();
|
|
1305
|
+
let h = null, f = null;
|
|
1271
1306
|
function d() {
|
|
1272
|
-
return
|
|
1307
|
+
return h != null && h.isConnected || (h = document.createElement("div"), h.setAttribute("data-bugcatch", "updates"), h.style.cssText = [
|
|
1273
1308
|
"position:fixed",
|
|
1274
|
-
`${s ? "top" : "bottom"}:${20 +
|
|
1309
|
+
`${s ? "top" : "bottom"}:${20 + kn()}px`,
|
|
1275
1310
|
`${c ? "left" : "right"}:20px`,
|
|
1276
1311
|
// Under the widget's dock and its panel scrim, both of which are higher.
|
|
1277
1312
|
// A notification is worth interrupting a page for, not the report being
|
|
@@ -1284,81 +1319,86 @@ function pn({
|
|
|
1284
1319
|
"width:min(320px,calc(100vw - 40px))",
|
|
1285
1320
|
// The gaps between cards belong to the page underneath.
|
|
1286
1321
|
"pointer-events:none"
|
|
1287
|
-
].join(";"), document.body.appendChild(
|
|
1322
|
+
].join(";"), document.body.appendChild(h)), h;
|
|
1288
1323
|
}
|
|
1289
|
-
function u(
|
|
1290
|
-
if (!
|
|
1291
|
-
|
|
1324
|
+
function u(p) {
|
|
1325
|
+
if (!p._bcShown) {
|
|
1326
|
+
p.remove();
|
|
1292
1327
|
return;
|
|
1293
1328
|
}
|
|
1294
|
-
|
|
1295
|
-
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
"border
|
|
1302
|
-
`
|
|
1303
|
-
|
|
1304
|
-
|
|
1329
|
+
p.style.opacity = "0", p.style.transform = `translateY(${s ? -8 : 8}px)`, setTimeout(() => p.remove(), 250);
|
|
1330
|
+
}
|
|
1331
|
+
const m = t || re, $ = t ? Ye(t) : Je;
|
|
1332
|
+
function I(p, k) {
|
|
1333
|
+
const g = document.createElement("button");
|
|
1334
|
+
return g.type = "button", g.textContent = p, g.style.cssText = [
|
|
1335
|
+
"padding:6px 12px",
|
|
1336
|
+
"border:0",
|
|
1337
|
+
`box-shadow:${k ? "none" : `inset 0 0 0 1px ${j.ring}`}`,
|
|
1338
|
+
"border-radius:999px",
|
|
1339
|
+
`background:${k ? m : "rgba(255,255,255,.06)"}`,
|
|
1340
|
+
`color:${k ? $ : j.fg}`,
|
|
1341
|
+
"font:560 12px/1.4 inherit",
|
|
1305
1342
|
"cursor:pointer",
|
|
1306
1343
|
"white-space:nowrap"
|
|
1307
|
-
].join(";"),
|
|
1344
|
+
].join(";"), g;
|
|
1308
1345
|
}
|
|
1309
|
-
function
|
|
1310
|
-
var
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1346
|
+
function v(p) {
|
|
1347
|
+
var L;
|
|
1348
|
+
const k = document.createElement("div");
|
|
1349
|
+
k.setAttribute("role", "status"), k.style.cssText = [
|
|
1313
1350
|
"box-sizing:border-box",
|
|
1314
1351
|
"width:100%",
|
|
1315
|
-
"padding:
|
|
1316
|
-
"border-radius:
|
|
1317
|
-
|
|
1318
|
-
|
|
1352
|
+
"padding:13px 14px",
|
|
1353
|
+
"border-radius:14px",
|
|
1354
|
+
`background:${j.bg}`,
|
|
1355
|
+
`color:${j.fg}`,
|
|
1319
1356
|
'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',
|
|
1320
|
-
|
|
1321
|
-
`border-left:3px solid ${un[h == null ? void 0 : h.kind] || t}`,
|
|
1357
|
+
`box-shadow:0 0 0 1px ${j.ring},0 20px 44px -12px rgba(0,0,0,.55),0 4px 12px rgba(0,0,0,.25)`,
|
|
1322
1358
|
"opacity:0",
|
|
1323
1359
|
`transform:translateY(${s ? -8 : 8}px)`,
|
|
1324
1360
|
"transition:opacity .2s ease,transform .2s ease",
|
|
1325
1361
|
"pointer-events:auto"
|
|
1326
1362
|
].join(";");
|
|
1327
|
-
const
|
|
1328
|
-
|
|
1363
|
+
const g = document.createElement("div");
|
|
1364
|
+
g.style.cssText = "display:flex;align-items:baseline;gap:8px;font-weight:600;margin-bottom:2px";
|
|
1365
|
+
const b = document.createElement("span");
|
|
1366
|
+
b.setAttribute("aria-hidden", "true"), b.style.cssText = `flex:none;width:7px;height:7px;border-radius:50%;transform:translateY(-1px);background:${yn[p == null ? void 0 : p.kind] || t || j.brand}`;
|
|
1367
|
+
const B = document.createElement("span");
|
|
1368
|
+
B.textContent = Oe(p), g.append(b, B);
|
|
1369
|
+
const y = document.createElement("div");
|
|
1370
|
+
y.style.cssText = (p == null ? void 0 : p.kind) === "reply" ? `color:${j.muted};padding-left:15px;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden` : `color:${j.muted};padding-left:15px`, y.textContent = bn(p);
|
|
1329
1371
|
const C = document.createElement("div");
|
|
1330
|
-
C.style.cssText =
|
|
1331
|
-
const
|
|
1332
|
-
|
|
1333
|
-
const
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
const y = g("Talk it through", !0);
|
|
1338
|
-
y.addEventListener("click", () => r(h)), w.insertBefore(y, B);
|
|
1372
|
+
C.style.cssText = "display:flex;align-items:center;gap:8px;margin-top:10px;padding-left:15px;flex-wrap:wrap";
|
|
1373
|
+
const A = document.createElement("span");
|
|
1374
|
+
A.style.cssText = `color:${j.faint};font-size:11px;margin-right:auto`, A.textContent = xn(p == null ? void 0 : p.at);
|
|
1375
|
+
const S = I("Mark as read", !1);
|
|
1376
|
+
if (S.setAttribute("aria-label", `Mark as read: ${Oe(p)}`), S.addEventListener("click", () => n == null ? void 0 : n(p.id)), C.append(A, S), (L = p == null ? void 0 : p.call) != null && L.offered && typeof r == "function") {
|
|
1377
|
+
const ye = I("Talk it through", !0);
|
|
1378
|
+
ye.addEventListener("click", () => r(p)), C.insertBefore(ye, S);
|
|
1339
1379
|
}
|
|
1340
|
-
return
|
|
1380
|
+
return k.append(g, y, C), k;
|
|
1341
1381
|
}
|
|
1342
|
-
function
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1382
|
+
function T(p) {
|
|
1383
|
+
const k = document.createElement("div");
|
|
1384
|
+
k.style.cssText = [
|
|
1345
1385
|
"box-sizing:border-box",
|
|
1346
1386
|
"width:100%",
|
|
1347
1387
|
"display:flex",
|
|
1348
1388
|
"align-items:center",
|
|
1349
1389
|
"gap:8px",
|
|
1350
|
-
"padding:8px
|
|
1351
|
-
"border-radius:
|
|
1352
|
-
|
|
1353
|
-
|
|
1390
|
+
"padding:8px 10px 8px 14px",
|
|
1391
|
+
"border-radius:999px",
|
|
1392
|
+
`background:${j.bg}`,
|
|
1393
|
+
`color:${j.muted}`,
|
|
1354
1394
|
'font:12px/1.4 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',
|
|
1355
|
-
|
|
1395
|
+
`box-shadow:0 0 0 1px ${j.ring},0 12px 30px -10px rgba(0,0,0,.5)`,
|
|
1356
1396
|
"pointer-events:auto"
|
|
1357
1397
|
].join(";");
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
const
|
|
1361
|
-
return
|
|
1398
|
+
const g = document.createElement("span");
|
|
1399
|
+
g.style.cssText = "margin-right:auto", g.textContent = `${p} more update${p === 1 ? "" : "s"}`;
|
|
1400
|
+
const b = I("Mark all as read", !1);
|
|
1401
|
+
return b.style.cssText += ";padding:4px 9px", b.addEventListener("click", () => i == null ? void 0 : i()), k.append(g, b), k;
|
|
1362
1402
|
}
|
|
1363
1403
|
return {
|
|
1364
1404
|
/**
|
|
@@ -1368,51 +1408,51 @@ function pn({
|
|
|
1368
1408
|
* corner the reporter's eye is already trained on — so the stack grows away
|
|
1369
1409
|
* from the launcher rather than over it.
|
|
1370
1410
|
*/
|
|
1371
|
-
render(
|
|
1372
|
-
const
|
|
1373
|
-
if (!
|
|
1374
|
-
for (const
|
|
1375
|
-
l.clear(),
|
|
1411
|
+
render(p) {
|
|
1412
|
+
const k = Array.isArray(p) ? p : [];
|
|
1413
|
+
if (!k.length) {
|
|
1414
|
+
for (const S of l.values()) u(S);
|
|
1415
|
+
l.clear(), f == null || f.remove(), f = null, h == null || h.remove(), h = null;
|
|
1376
1416
|
return;
|
|
1377
1417
|
}
|
|
1378
|
-
const
|
|
1379
|
-
for (const [
|
|
1380
|
-
|
|
1381
|
-
const
|
|
1382
|
-
for (const
|
|
1383
|
-
if (l.has(
|
|
1384
|
-
const
|
|
1385
|
-
l.set(
|
|
1418
|
+
const g = k.slice(-3), b = new Set(g.map((S) => S.id)), B = d();
|
|
1419
|
+
for (const [S, L] of l)
|
|
1420
|
+
b.has(S) || (u(L), l.delete(S));
|
|
1421
|
+
const y = [];
|
|
1422
|
+
for (const S of g) {
|
|
1423
|
+
if (l.has(S.id)) continue;
|
|
1424
|
+
const L = v(S);
|
|
1425
|
+
l.set(S.id, L), y.push(L);
|
|
1386
1426
|
}
|
|
1387
|
-
const
|
|
1388
|
-
for (const
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
for (const
|
|
1392
|
-
|
|
1427
|
+
const C = s ? [...g].reverse() : g;
|
|
1428
|
+
for (const S of C) B.appendChild(l.get(S.id));
|
|
1429
|
+
const A = k.length - g.length;
|
|
1430
|
+
A > 0 ? (f == null || f.remove(), f = T(A), s ? B.appendChild(f) : B.insertBefore(f, B.firstChild)) : (f == null || f.remove(), f = null), requestAnimationFrame(() => {
|
|
1431
|
+
for (const S of y)
|
|
1432
|
+
S.isConnected && (S._bcShown = !0, S.style.opacity = "1", S.style.transform = "translateY(0)");
|
|
1393
1433
|
});
|
|
1394
1434
|
},
|
|
1395
1435
|
destroy() {
|
|
1396
|
-
l.clear(),
|
|
1436
|
+
l.clear(), f = null, h == null || h.remove(), h = null;
|
|
1397
1437
|
}
|
|
1398
1438
|
};
|
|
1399
1439
|
}
|
|
1400
|
-
async function
|
|
1440
|
+
async function In({ apiBase: t, apiKey: e, projectId: n, sessionToken: i }) {
|
|
1401
1441
|
try {
|
|
1402
1442
|
const r = await fetch(
|
|
1403
1443
|
`${t}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,
|
|
1404
|
-
{ headers:
|
|
1444
|
+
{ headers: pe(e, i) }
|
|
1405
1445
|
);
|
|
1406
1446
|
if (!r.ok) return [];
|
|
1407
|
-
const
|
|
1408
|
-
return Array.isArray(
|
|
1447
|
+
const o = await r.json();
|
|
1448
|
+
return Array.isArray(o == null ? void 0 : o.issues) ? o.issues : [];
|
|
1409
1449
|
} catch {
|
|
1410
1450
|
return [];
|
|
1411
1451
|
}
|
|
1412
1452
|
}
|
|
1413
|
-
async function
|
|
1453
|
+
async function Cn({ apiBase: t, apiKey: e, projectId: n, q: i, sessionToken: r, signal: o }) {
|
|
1414
1454
|
try {
|
|
1415
|
-
const a = `${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(
|
|
1455
|
+
const a = `${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(i)}`, s = await fetch(a, { headers: pe(e, r), signal: o });
|
|
1416
1456
|
if (!s.ok) return [];
|
|
1417
1457
|
const c = await s.json();
|
|
1418
1458
|
return Array.isArray(c == null ? void 0 : c.issues) ? c.issues : [];
|
|
@@ -1420,102 +1460,116 @@ async function mn({ apiBase: t, apiKey: e, projectId: n, q: o, sessionToken: r,
|
|
|
1420
1460
|
return [];
|
|
1421
1461
|
}
|
|
1422
1462
|
}
|
|
1423
|
-
async function
|
|
1463
|
+
async function Sn({
|
|
1424
1464
|
apiBase: t,
|
|
1425
1465
|
apiKey: e,
|
|
1426
1466
|
projectId: n,
|
|
1427
|
-
bugId:
|
|
1467
|
+
bugId: i,
|
|
1428
1468
|
reporterEmail: r,
|
|
1429
|
-
reporterName:
|
|
1469
|
+
reporterName: o,
|
|
1430
1470
|
metadata: a,
|
|
1431
1471
|
logs: s,
|
|
1432
1472
|
sessionToken: c
|
|
1433
1473
|
}) {
|
|
1434
|
-
const l = E(),
|
|
1435
|
-
`${t}/ingest/known-issues/${encodeURIComponent(
|
|
1474
|
+
const l = E(), h = await fetch(
|
|
1475
|
+
`${t}/ingest/known-issues/${encodeURIComponent(i)}/join`,
|
|
1436
1476
|
{
|
|
1437
1477
|
method: "POST",
|
|
1438
|
-
headers:
|
|
1478
|
+
headers: pe(e, c),
|
|
1439
1479
|
body: JSON.stringify({
|
|
1440
1480
|
projectId: n,
|
|
1441
1481
|
reporterEmail: r,
|
|
1442
|
-
reporterName:
|
|
1482
|
+
reporterName: o,
|
|
1443
1483
|
metadata: a,
|
|
1444
1484
|
logs: s,
|
|
1445
1485
|
...l ? { watchToken: l } : {}
|
|
1446
1486
|
})
|
|
1447
1487
|
}
|
|
1448
1488
|
);
|
|
1449
|
-
if (!
|
|
1450
|
-
const
|
|
1451
|
-
return
|
|
1489
|
+
if (!h.ok) throw new Error(await Bn(h));
|
|
1490
|
+
const f = await h.json();
|
|
1491
|
+
return f != null && f.watchToken && se(f.watchToken), f;
|
|
1452
1492
|
}
|
|
1453
|
-
function
|
|
1493
|
+
function pe(t, e) {
|
|
1454
1494
|
return {
|
|
1455
1495
|
"Content-Type": "application/json",
|
|
1456
1496
|
"X-BugCatch-Key": t,
|
|
1457
1497
|
...e ? { "X-BugCatch-Session": e } : {}
|
|
1458
1498
|
};
|
|
1459
1499
|
}
|
|
1460
|
-
async function
|
|
1500
|
+
async function Bn(t) {
|
|
1461
1501
|
let e = "";
|
|
1462
1502
|
try {
|
|
1463
1503
|
const n = await t.json();
|
|
1464
1504
|
e = Array.isArray(n.message) ? n.message.join(", ") : n.message || "";
|
|
1465
1505
|
} catch {
|
|
1466
1506
|
}
|
|
1467
|
-
return t.status === 429 ?
|
|
1507
|
+
return t.status === 429 ? N(e) : e || `Could not add you to this issue (HTTP ${t.status})`;
|
|
1508
|
+
}
|
|
1509
|
+
async function En({ apiBase: t, bugId: e, score: n, comment: i }) {
|
|
1510
|
+
const r = E();
|
|
1511
|
+
if (!r) throw new Error("This browser cannot access that report.");
|
|
1512
|
+
const o = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/rating${ee()}`, {
|
|
1513
|
+
method: "POST",
|
|
1514
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${r}` },
|
|
1515
|
+
body: JSON.stringify({ score: n, ...i ? { comment: i } : {} })
|
|
1516
|
+
}), a = await o.json().catch(() => ({}));
|
|
1517
|
+
if (!o.ok) {
|
|
1518
|
+
const s = Array.isArray(a.message) ? a.message.join(", ") : a.message;
|
|
1519
|
+
throw new Error(s || "Could not send your rating. Please try again.");
|
|
1520
|
+
}
|
|
1521
|
+
return a;
|
|
1468
1522
|
}
|
|
1469
|
-
async function
|
|
1470
|
-
const
|
|
1471
|
-
if (!
|
|
1523
|
+
async function $n({ apiBase: t, bugId: e, ...n }) {
|
|
1524
|
+
const i = E();
|
|
1525
|
+
if (!i) throw new Error("This browser cannot access that report.");
|
|
1472
1526
|
const r = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/verification`, {
|
|
1473
1527
|
method: "POST",
|
|
1474
|
-
headers: { "Content-Type": "application/json", Authorization: `Bearer ${
|
|
1528
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${i}` },
|
|
1475
1529
|
body: JSON.stringify(n)
|
|
1476
|
-
}),
|
|
1477
|
-
if (!r.ok) throw new Error(
|
|
1478
|
-
return
|
|
1530
|
+
}), o = await r.json().catch(() => ({}));
|
|
1531
|
+
if (!r.ok) throw new Error(o.message || "Could not record feedback. Please refresh and try again.");
|
|
1532
|
+
return o;
|
|
1479
1533
|
}
|
|
1480
|
-
const
|
|
1481
|
-
function
|
|
1534
|
+
const Tn = "bugcatch.session.", ge = (t) => `${Tn}${t}`, me = /* @__PURE__ */ new Map();
|
|
1535
|
+
function M(t) {
|
|
1482
1536
|
var e;
|
|
1483
1537
|
if (!t) return null;
|
|
1484
1538
|
try {
|
|
1485
|
-
const n = (e = window.localStorage) == null ? void 0 : e.getItem(
|
|
1539
|
+
const n = (e = window.localStorage) == null ? void 0 : e.getItem(ge(t));
|
|
1486
1540
|
if (n) {
|
|
1487
|
-
const
|
|
1488
|
-
if (
|
|
1541
|
+
const i = JSON.parse(n);
|
|
1542
|
+
if (i != null && i.token) return i;
|
|
1489
1543
|
}
|
|
1490
1544
|
} catch {
|
|
1491
1545
|
}
|
|
1492
|
-
return
|
|
1546
|
+
return me.get(t) || null;
|
|
1493
1547
|
}
|
|
1494
|
-
function
|
|
1495
|
-
var
|
|
1548
|
+
function An(t, e) {
|
|
1549
|
+
var i;
|
|
1496
1550
|
if (!t || !(e != null && e.token)) return;
|
|
1497
1551
|
const n = {
|
|
1498
1552
|
token: e.token,
|
|
1499
1553
|
email: e.email || null,
|
|
1500
1554
|
name: e.name || null
|
|
1501
1555
|
};
|
|
1502
|
-
|
|
1556
|
+
me.set(t, n);
|
|
1503
1557
|
try {
|
|
1504
|
-
(
|
|
1558
|
+
(i = window.localStorage) == null || i.setItem(ge(t), JSON.stringify(n));
|
|
1505
1559
|
} catch {
|
|
1506
1560
|
}
|
|
1507
1561
|
}
|
|
1508
|
-
function
|
|
1562
|
+
function ce(t) {
|
|
1509
1563
|
var e;
|
|
1510
1564
|
if (t) {
|
|
1511
|
-
|
|
1565
|
+
me.delete(t);
|
|
1512
1566
|
try {
|
|
1513
|
-
(e = window.localStorage) == null || e.removeItem(
|
|
1567
|
+
(e = window.localStorage) == null || e.removeItem(ge(t));
|
|
1514
1568
|
} catch {
|
|
1515
1569
|
}
|
|
1516
1570
|
}
|
|
1517
1571
|
}
|
|
1518
|
-
function
|
|
1572
|
+
function ne({ apiKey: t, token: e }) {
|
|
1519
1573
|
return {
|
|
1520
1574
|
"Content-Type": "application/json",
|
|
1521
1575
|
"X-BugCatch-Key": t,
|
|
@@ -1525,24 +1579,24 @@ function Z({ apiKey: t, token: e }) {
|
|
|
1525
1579
|
...e ? { "X-BugCatch-Session": e } : {}
|
|
1526
1580
|
};
|
|
1527
1581
|
}
|
|
1528
|
-
async function
|
|
1582
|
+
async function Ge(t) {
|
|
1529
1583
|
let e = "";
|
|
1530
1584
|
try {
|
|
1531
1585
|
const n = await t.json();
|
|
1532
1586
|
e = Array.isArray(n.message) ? n.message.join(", ") : n.message || "";
|
|
1533
1587
|
} catch {
|
|
1534
1588
|
}
|
|
1535
|
-
return t.status === 429 ?
|
|
1589
|
+
return t.status === 429 ? N(e) : e || `Request failed (HTTP ${t.status})`;
|
|
1536
1590
|
}
|
|
1537
|
-
async function
|
|
1591
|
+
async function jn({ apiBase: t, apiKey: e, projectId: n, token: i }) {
|
|
1538
1592
|
const r = { mode: "off", signedIn: null, signedOutReason: null };
|
|
1539
1593
|
try {
|
|
1540
|
-
const
|
|
1594
|
+
const o = await fetch(
|
|
1541
1595
|
`${t}/ingest/login?projectId=${encodeURIComponent(n)}`,
|
|
1542
|
-
{ headers:
|
|
1596
|
+
{ headers: ne({ apiKey: e, token: i }) }
|
|
1543
1597
|
);
|
|
1544
|
-
if (!
|
|
1545
|
-
const a = await
|
|
1598
|
+
if (!o.ok) return r;
|
|
1599
|
+
const a = await o.json();
|
|
1546
1600
|
return {
|
|
1547
1601
|
mode: a.mode === "optional" || a.mode === "required" ? a.mode : "off",
|
|
1548
1602
|
signedIn: a.signedIn || null,
|
|
@@ -1552,52 +1606,52 @@ async function xn({ apiBase: t, apiKey: e, projectId: n, token: o }) {
|
|
|
1552
1606
|
return r;
|
|
1553
1607
|
}
|
|
1554
1608
|
}
|
|
1555
|
-
async function
|
|
1556
|
-
const
|
|
1609
|
+
async function On({ apiBase: t, apiKey: e, projectId: n, email: i, name: r }) {
|
|
1610
|
+
const o = await fetch(`${t}/ingest/login/start`, {
|
|
1557
1611
|
method: "POST",
|
|
1558
|
-
headers:
|
|
1559
|
-
body: JSON.stringify({ projectId: n, email:
|
|
1612
|
+
headers: ne({ apiKey: e }),
|
|
1613
|
+
body: JSON.stringify({ projectId: n, email: i, ...r ? { name: r } : {} })
|
|
1560
1614
|
});
|
|
1561
|
-
if (!
|
|
1562
|
-
return
|
|
1615
|
+
if (!o.ok) throw new Error(await Ge(o));
|
|
1616
|
+
return o.json();
|
|
1563
1617
|
}
|
|
1564
|
-
async function
|
|
1565
|
-
const
|
|
1618
|
+
async function Mn({ apiBase: t, apiKey: e, projectId: n, email: i, code: r }) {
|
|
1619
|
+
const o = await fetch(`${t}/ingest/login`, {
|
|
1566
1620
|
method: "POST",
|
|
1567
|
-
headers:
|
|
1568
|
-
body: JSON.stringify({ projectId: n, email:
|
|
1621
|
+
headers: ne({ apiKey: e }),
|
|
1622
|
+
body: JSON.stringify({ projectId: n, email: i, code: r })
|
|
1569
1623
|
});
|
|
1570
|
-
if (!
|
|
1571
|
-
const a = await
|
|
1572
|
-
return
|
|
1624
|
+
if (!o.ok) throw new Error(await Ge(o));
|
|
1625
|
+
const a = await o.json(), s = { token: a.sessionToken, email: a.email, name: a.name };
|
|
1626
|
+
return An(n, s), s;
|
|
1573
1627
|
}
|
|
1574
|
-
async function
|
|
1575
|
-
if (
|
|
1628
|
+
async function Rn({ apiBase: t, apiKey: e, projectId: n, token: i }) {
|
|
1629
|
+
if (ce(n), !i) return { signedOut: !0 };
|
|
1576
1630
|
try {
|
|
1577
1631
|
await fetch(`${t}/ingest/logout`, {
|
|
1578
1632
|
method: "POST",
|
|
1579
|
-
headers:
|
|
1633
|
+
headers: ne({ apiKey: e, token: i }),
|
|
1580
1634
|
body: JSON.stringify({ projectId: n })
|
|
1581
1635
|
});
|
|
1582
1636
|
} catch {
|
|
1583
1637
|
}
|
|
1584
1638
|
return { signedOut: !0 };
|
|
1585
1639
|
}
|
|
1586
|
-
let
|
|
1640
|
+
let Qe = !1;
|
|
1587
1641
|
if (typeof window < "u" && window.addEventListener)
|
|
1588
1642
|
for (const t of ["pointerdown", "keydown", "touchstart"])
|
|
1589
1643
|
window.addEventListener(t, () => {
|
|
1590
|
-
|
|
1644
|
+
Qe = !0;
|
|
1591
1645
|
}, {
|
|
1592
1646
|
once: !0,
|
|
1593
1647
|
capture: !0,
|
|
1594
1648
|
passive: !0
|
|
1595
1649
|
});
|
|
1596
|
-
function
|
|
1597
|
-
return
|
|
1650
|
+
function Ln() {
|
|
1651
|
+
return Qe;
|
|
1598
1652
|
}
|
|
1599
|
-
const
|
|
1600
|
-
function
|
|
1653
|
+
const Kn = 2e4, et = 120, le = 200;
|
|
1654
|
+
function tt(t) {
|
|
1601
1655
|
if (typeof t != "string" || !t.trim() || t.length > 400) return null;
|
|
1602
1656
|
try {
|
|
1603
1657
|
return new RegExp(t.trim(), "gi");
|
|
@@ -1605,194 +1659,194 @@ function We(t) {
|
|
|
1605
1659
|
return null;
|
|
1606
1660
|
}
|
|
1607
1661
|
}
|
|
1608
|
-
const
|
|
1609
|
-
function
|
|
1662
|
+
const nt = (t) => String(t).replace(/\s+/g, " ").trim().slice(0, et);
|
|
1663
|
+
function it(t, e) {
|
|
1610
1664
|
const n = t && t.normalize;
|
|
1611
1665
|
if (n === "phone") {
|
|
1612
|
-
const
|
|
1613
|
-
return
|
|
1666
|
+
const i = e.replace(/\D/g, "");
|
|
1667
|
+
return i.length === 10 ? i : i.length === 12 && i.startsWith("91") ? i.slice(2) : i.length === 11 && i.startsWith("0") ? i.slice(1) : e;
|
|
1614
1668
|
}
|
|
1615
1669
|
return n === "upper" ? e.toUpperCase() : e;
|
|
1616
1670
|
}
|
|
1617
|
-
function
|
|
1671
|
+
function ot(t) {
|
|
1618
1672
|
const e = t.length > 1 && t[1] !== void 0 ? t[1] : t[0];
|
|
1619
|
-
return typeof e != "string" || !e.trim() ? null : { value:
|
|
1673
|
+
return typeof e != "string" || !e.trim() ? null : { value: nt(e), start: t.index, end: t.index + t[0].length };
|
|
1620
1674
|
}
|
|
1621
|
-
function
|
|
1675
|
+
function Nn(t, e) {
|
|
1622
1676
|
return ((t.slice(e.start, e.valueStart) + t.slice(e.valueEnd, e.end)).match(/[a-z]/gi) || []).length;
|
|
1623
1677
|
}
|
|
1624
|
-
const
|
|
1625
|
-
function
|
|
1626
|
-
const n = (t || []).filter((d) => d && d.scan !== !1 && d.pattern),
|
|
1627
|
-
|
|
1628
|
-
d && n.forEach((
|
|
1629
|
-
const
|
|
1630
|
-
if (!
|
|
1631
|
-
let
|
|
1632
|
-
for (
|
|
1633
|
-
if (
|
|
1634
|
-
|
|
1678
|
+
const Un = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[A-Za-z0-9][\w-]{5,40}/gi, Me = /[\w-]/;
|
|
1679
|
+
function ki(t, e) {
|
|
1680
|
+
const n = (t || []).filter((d) => d && d.scan !== !1 && d.pattern), i = [], r = [], o = (e || []).map((d) => typeof d == "string" ? d.slice(0, Kn) : "");
|
|
1681
|
+
o.forEach((d, u) => {
|
|
1682
|
+
d && n.forEach((m, $) => {
|
|
1683
|
+
const I = tt(m.pattern);
|
|
1684
|
+
if (!I) return;
|
|
1685
|
+
let v, T = 0;
|
|
1686
|
+
for (I.lastIndex = 0; (v = I.exec(d)) !== null && !(++T > le); ) {
|
|
1687
|
+
if (v[0] === "") {
|
|
1688
|
+
I.lastIndex += 1;
|
|
1635
1689
|
continue;
|
|
1636
1690
|
}
|
|
1637
|
-
const
|
|
1638
|
-
if (!
|
|
1639
|
-
const
|
|
1691
|
+
const p = ot(v);
|
|
1692
|
+
if (!p) continue;
|
|
1693
|
+
const k = v.length > 1 && v[1] !== void 0 ? v[1] : v[0], g = v.index + Math.max(0, v[0].indexOf(k)), b = {
|
|
1640
1694
|
block: u,
|
|
1641
1695
|
order: $,
|
|
1642
|
-
key:
|
|
1643
|
-
label:
|
|
1644
|
-
value:
|
|
1645
|
-
start:
|
|
1646
|
-
end:
|
|
1647
|
-
valueStart:
|
|
1648
|
-
valueEnd:
|
|
1696
|
+
key: m.key,
|
|
1697
|
+
label: m.label,
|
|
1698
|
+
value: it(m, p.value),
|
|
1699
|
+
start: p.start,
|
|
1700
|
+
end: p.end,
|
|
1701
|
+
valueStart: g,
|
|
1702
|
+
valueEnd: g + k.length
|
|
1649
1703
|
};
|
|
1650
|
-
|
|
1704
|
+
b.weight = Nn(d, b), i.push(b);
|
|
1651
1705
|
}
|
|
1652
1706
|
});
|
|
1653
1707
|
});
|
|
1654
|
-
const a =
|
|
1708
|
+
const a = i.filter((d) => !i.some((u) => u !== d && u.block === d.block && u.key !== d.key && u.valueStart <= d.valueStart && u.valueEnd >= d.valueEnd && u.weight > d.weight)), s = /* @__PURE__ */ new Map();
|
|
1655
1709
|
for (const d of a) {
|
|
1656
1710
|
const u = d.value.toLowerCase();
|
|
1657
1711
|
s.has(u) || s.set(u, { value: d.value, keys: /* @__PURE__ */ new Map() });
|
|
1658
|
-
const
|
|
1659
|
-
|
|
1712
|
+
const m = s.get(u);
|
|
1713
|
+
m.keys.has(d.key) || m.keys.set(d.key, { key: d.key, label: d.label, order: d.order });
|
|
1660
1714
|
}
|
|
1661
|
-
const c = [], l = [],
|
|
1715
|
+
const c = [], l = [], h = /* @__PURE__ */ new Map();
|
|
1662
1716
|
for (const d of s.values()) {
|
|
1663
|
-
const u = [...d.keys.values()].sort((
|
|
1717
|
+
const u = [...d.keys.values()].sort((I, v) => I.order - v.order);
|
|
1664
1718
|
if (u.length > 1) {
|
|
1665
|
-
l.push({ value: d.value, kinds: u.map(({ key:
|
|
1719
|
+
l.push({ value: d.value, kinds: u.map(({ key: I, label: v }) => ({ key: I, label: v })) });
|
|
1666
1720
|
continue;
|
|
1667
1721
|
}
|
|
1668
|
-
const [{ key:
|
|
1669
|
-
|
|
1722
|
+
const [{ key: m, label: $ }] = u;
|
|
1723
|
+
h.has(m) || h.set(m, []), h.get(m).push({ key: m, label: $, value: d.value });
|
|
1670
1724
|
}
|
|
1671
|
-
for (const d of
|
|
1725
|
+
for (const d of h.values())
|
|
1672
1726
|
if (d.length === 1) c.push(d[0]);
|
|
1673
1727
|
else for (const u of d) l.push({ value: u.value, kinds: [{ key: u.key, label: u.label }] });
|
|
1674
|
-
const
|
|
1675
|
-
return
|
|
1728
|
+
const f = new Set(s.keys());
|
|
1729
|
+
return o.forEach((d, u) => {
|
|
1676
1730
|
if (!d) return;
|
|
1677
|
-
const
|
|
1678
|
-
let
|
|
1679
|
-
for (; (
|
|
1680
|
-
const
|
|
1681
|
-
if (
|
|
1682
|
-
const
|
|
1683
|
-
if (
|
|
1684
|
-
const
|
|
1685
|
-
if (
|
|
1686
|
-
const
|
|
1687
|
-
|
|
1731
|
+
const m = i.filter((T) => T.block === u), $ = new RegExp(Un.source, "gi");
|
|
1732
|
+
let I, v = 0;
|
|
1733
|
+
for (; (I = $.exec(d)) !== null && ++v <= le; ) {
|
|
1734
|
+
const T = I.index, p = T + I[0].length;
|
|
1735
|
+
if (m.some((C) => T < C.end && p > C.start)) continue;
|
|
1736
|
+
const k = d[T - 1] || "", g = d[p] || "";
|
|
1737
|
+
if (Me.test(k) || Me.test(g) || k === "/" || k === "@" || g === "@" || k === "." || g === "." && /\w/.test(d[p + 1] || "") || !/\d/.test(I[0])) continue;
|
|
1738
|
+
const b = nt(I[0]), B = b.toLowerCase();
|
|
1739
|
+
if (f.has(B)) continue;
|
|
1740
|
+
const y = (t || []).filter((C) => C && Pn(C, b)).map(({ key: C, label: A }) => ({ key: C, label: A }));
|
|
1741
|
+
y.length && (f.add(B), r.push({ value: b, kinds: y }));
|
|
1688
1742
|
}
|
|
1689
1743
|
}), { found: c, conflicts: l, loose: r };
|
|
1690
1744
|
}
|
|
1691
|
-
function
|
|
1745
|
+
function Pn(t, e) {
|
|
1692
1746
|
const n = typeof e == "string" ? e.trim() : "";
|
|
1693
|
-
if (!n || n.length >
|
|
1694
|
-
const
|
|
1695
|
-
if (!
|
|
1696
|
-
let r,
|
|
1697
|
-
for (
|
|
1747
|
+
if (!n || n.length > et) return null;
|
|
1748
|
+
const i = tt(t && (t.valuePattern || t.pattern));
|
|
1749
|
+
if (!i) return null;
|
|
1750
|
+
let r, o = 0;
|
|
1751
|
+
for (i.lastIndex = 0; (r = i.exec(n)) !== null && !(++o > le); ) {
|
|
1698
1752
|
if (r[0] === "") {
|
|
1699
|
-
|
|
1753
|
+
i.lastIndex += 1;
|
|
1700
1754
|
continue;
|
|
1701
1755
|
}
|
|
1702
1756
|
const a = r.index + r[0].length === n.length, s = r.index === 0 || r.index === 1;
|
|
1703
1757
|
if (a && s) {
|
|
1704
|
-
const c =
|
|
1705
|
-
if (c) return
|
|
1758
|
+
const c = ot(r);
|
|
1759
|
+
if (c) return it(t, c.value);
|
|
1706
1760
|
}
|
|
1707
1761
|
}
|
|
1708
1762
|
return null;
|
|
1709
1763
|
}
|
|
1710
|
-
async function
|
|
1711
|
-
const
|
|
1764
|
+
async function Dn({ apiBase: t, apiKey: e, projectId: n }) {
|
|
1765
|
+
const i = { policy: "off", fields: [] };
|
|
1712
1766
|
try {
|
|
1713
1767
|
const r = await fetch(
|
|
1714
1768
|
`${t}/ingest/reference-fields?projectId=${encodeURIComponent(n)}`,
|
|
1715
1769
|
{ headers: { "X-BugCatch-Key": e } }
|
|
1716
1770
|
);
|
|
1717
|
-
if (!r.ok) return
|
|
1718
|
-
const
|
|
1719
|
-
return s.length ? { policy: a, fields: s } :
|
|
1771
|
+
if (!r.ok) return i;
|
|
1772
|
+
const o = await r.json(), a = o.policy === "optional" || o.policy === "required" ? o.policy : "off", s = Array.isArray(o.fields) ? o.fields : [];
|
|
1773
|
+
return s.length ? { policy: a, fields: s } : i;
|
|
1720
1774
|
} catch {
|
|
1721
|
-
return
|
|
1775
|
+
return i;
|
|
1722
1776
|
}
|
|
1723
1777
|
}
|
|
1724
|
-
const
|
|
1725
|
-
async function
|
|
1778
|
+
const vi = /Did this answer your question\?/i;
|
|
1779
|
+
async function _n({ apiBase: t, apiKey: e, projectId: n }) {
|
|
1726
1780
|
try {
|
|
1727
|
-
const
|
|
1781
|
+
const i = await fetch(
|
|
1728
1782
|
`${t}/ingest/agent-issues?projectId=${encodeURIComponent(n)}`,
|
|
1729
1783
|
{ headers: { "X-BugCatch-Key": e } }
|
|
1730
1784
|
);
|
|
1731
|
-
if (!
|
|
1732
|
-
const r = await
|
|
1733
|
-
return (Array.isArray(r == null ? void 0 : r.issues) ? r.issues : []).filter((
|
|
1785
|
+
if (!i.ok) return [];
|
|
1786
|
+
const r = await i.json();
|
|
1787
|
+
return (Array.isArray(r == null ? void 0 : r.issues) ? r.issues : []).filter((o) => o && typeof o.key == "string" && typeof o.title == "string").map((o) => ({ key: o.key, title: o.title, hint: typeof o.hint == "string" ? o.hint : "" }));
|
|
1734
1788
|
} catch {
|
|
1735
1789
|
return [];
|
|
1736
1790
|
}
|
|
1737
1791
|
}
|
|
1738
|
-
const
|
|
1739
|
-
async function
|
|
1792
|
+
const Hn = 5 * 6e4, rt = "bugcatch:announcements:seen", zn = 40, qn = ["info", "success", "warning", "critical"], at = (t) => `bugcatch:announcements:${t}`;
|
|
1793
|
+
async function Fn({
|
|
1740
1794
|
apiBase: t,
|
|
1741
1795
|
apiKey: e,
|
|
1742
1796
|
projectId: n,
|
|
1743
|
-
fresh:
|
|
1797
|
+
fresh: i = !1
|
|
1744
1798
|
}) {
|
|
1745
1799
|
var r;
|
|
1746
|
-
if (!
|
|
1747
|
-
const
|
|
1748
|
-
if (
|
|
1800
|
+
if (!i) {
|
|
1801
|
+
const o = Gn(n);
|
|
1802
|
+
if (o) return o;
|
|
1749
1803
|
}
|
|
1750
1804
|
try {
|
|
1751
|
-
const
|
|
1805
|
+
const o = await fetch(
|
|
1752
1806
|
`${t}/ingest/announcements?projectId=${encodeURIComponent(n)}`,
|
|
1753
1807
|
{ headers: { "X-BugCatch-Key": e } }
|
|
1754
|
-
), a =
|
|
1755
|
-
return
|
|
1808
|
+
), a = o.ok ? Zn((r = await o.json()) == null ? void 0 : r.announcements) : [];
|
|
1809
|
+
return Qn(n, a), a;
|
|
1756
1810
|
} catch {
|
|
1757
1811
|
return [];
|
|
1758
1812
|
}
|
|
1759
1813
|
}
|
|
1760
|
-
function
|
|
1761
|
-
return (t || []).filter((
|
|
1814
|
+
function Xn(t, { on: e = Yn(), seen: n = ct() } = {}) {
|
|
1815
|
+
return (t || []).filter((i) => Vn(i, e) && !(i.dismissible && n.includes(st(i))));
|
|
1762
1816
|
}
|
|
1763
|
-
function
|
|
1817
|
+
function Wn(t) {
|
|
1764
1818
|
if (!(!(t != null && t.id) || !t.dismissible))
|
|
1765
1819
|
try {
|
|
1766
|
-
const e =
|
|
1767
|
-
localStorage.setItem(
|
|
1820
|
+
const e = st(t), n = [...ct().filter((i) => i !== e), e];
|
|
1821
|
+
localStorage.setItem(rt, JSON.stringify(n.slice(-zn)));
|
|
1768
1822
|
} catch {
|
|
1769
1823
|
}
|
|
1770
1824
|
}
|
|
1771
|
-
function
|
|
1825
|
+
function Jn(t) {
|
|
1772
1826
|
return typeof t != "string" || !t || t.startsWith("//") ? null : t.startsWith("/") || /^(https?:\/\/|mailto:)./i.test(t) ? t : null;
|
|
1773
1827
|
}
|
|
1774
|
-
function
|
|
1828
|
+
function Yn(t = /* @__PURE__ */ new Date()) {
|
|
1775
1829
|
const e = (n) => String(n).padStart(2, "0");
|
|
1776
1830
|
return `${t.getFullYear()}-${e(t.getMonth() + 1)}-${e(t.getDate())}`;
|
|
1777
1831
|
}
|
|
1778
|
-
function
|
|
1832
|
+
function Vn(t, e) {
|
|
1779
1833
|
return !(t.startsOn && e < t.startsOn || t.endsOn && e > t.endsOn);
|
|
1780
1834
|
}
|
|
1781
|
-
function
|
|
1835
|
+
function st(t) {
|
|
1782
1836
|
return `${t.id}#${t.revision || 0}`;
|
|
1783
1837
|
}
|
|
1784
|
-
function
|
|
1838
|
+
function Zn(t) {
|
|
1785
1839
|
return (Array.isArray(t) ? t : []).filter((e) => e && typeof e.id == "string" && typeof e.title == "string" && e.title.trim()).map((e) => {
|
|
1786
|
-
const n = e.placement === "launcher" ? "launcher" : "panel",
|
|
1840
|
+
const n = e.placement === "launcher" ? "launcher" : "panel", i = Jn(e.ctaHref);
|
|
1787
1841
|
return {
|
|
1788
1842
|
id: e.id,
|
|
1789
1843
|
revision: Number.isInteger(e.revision) ? e.revision : 0,
|
|
1790
1844
|
title: e.title,
|
|
1791
1845
|
body: typeof e.body == "string" ? e.body : "",
|
|
1792
|
-
tone:
|
|
1846
|
+
tone: qn.includes(e.tone) ? e.tone : "info",
|
|
1793
1847
|
// Both halves, or neither, as the API saves them.
|
|
1794
|
-
ctaLabel:
|
|
1795
|
-
ctaHref:
|
|
1848
|
+
ctaLabel: i && typeof e.ctaLabel == "string" ? e.ctaLabel : "",
|
|
1849
|
+
ctaHref: i && typeof e.ctaLabel == "string" ? i : "",
|
|
1796
1850
|
placement: n,
|
|
1797
1851
|
dismissible: n === "launcher" || e.dismissible !== !1,
|
|
1798
1852
|
startsOn: typeof e.startsOn == "string" ? e.startsOn : "",
|
|
@@ -1800,150 +1854,150 @@ function Hn(t) {
|
|
|
1800
1854
|
};
|
|
1801
1855
|
});
|
|
1802
1856
|
}
|
|
1803
|
-
function
|
|
1857
|
+
function ct() {
|
|
1804
1858
|
try {
|
|
1805
|
-
const t = JSON.parse(localStorage.getItem(
|
|
1859
|
+
const t = JSON.parse(localStorage.getItem(rt) || "[]");
|
|
1806
1860
|
return Array.isArray(t) ? t.filter((e) => typeof e == "string") : [];
|
|
1807
1861
|
} catch {
|
|
1808
1862
|
return [];
|
|
1809
1863
|
}
|
|
1810
1864
|
}
|
|
1811
|
-
function
|
|
1865
|
+
function Gn(t) {
|
|
1812
1866
|
try {
|
|
1813
|
-
const e = JSON.parse(localStorage.getItem(
|
|
1867
|
+
const e = JSON.parse(localStorage.getItem(at(t)) || "null");
|
|
1814
1868
|
if (!e || !Array.isArray(e.list) || typeof e.at != "number") return null;
|
|
1815
1869
|
const n = Date.now() - e.at;
|
|
1816
|
-
return n >= 0 && n <
|
|
1870
|
+
return n >= 0 && n < Hn ? e.list : null;
|
|
1817
1871
|
} catch {
|
|
1818
1872
|
return null;
|
|
1819
1873
|
}
|
|
1820
1874
|
}
|
|
1821
|
-
function
|
|
1875
|
+
function Qn(t, e) {
|
|
1822
1876
|
try {
|
|
1823
|
-
localStorage.setItem(
|
|
1877
|
+
localStorage.setItem(at(t), JSON.stringify({ at: Date.now(), list: e }));
|
|
1824
1878
|
} catch {
|
|
1825
1879
|
}
|
|
1826
1880
|
}
|
|
1827
|
-
const
|
|
1881
|
+
const Z = 120, ei = 500, G = 30, ti = 1e3, we = {
|
|
1828
1882
|
loanId: ["loanId", "loanNumber"],
|
|
1829
1883
|
applicationId: ["applicationId"],
|
|
1830
1884
|
customerNumber: ["customerNumber", "customerId"]
|
|
1831
|
-
},
|
|
1832
|
-
function
|
|
1885
|
+
}, ni = /[\u0000-\u001f\u007f]/;
|
|
1886
|
+
function ii(t) {
|
|
1833
1887
|
if (typeof t == "number") return Number.isFinite(t) ? String(t) : null;
|
|
1834
1888
|
if (typeof t != "string") return null;
|
|
1835
1889
|
const e = t.trim();
|
|
1836
|
-
return !e || e.length >
|
|
1890
|
+
return !e || e.length > Z || ni.test(e) ? null : e;
|
|
1837
1891
|
}
|
|
1838
|
-
function
|
|
1892
|
+
function O(t) {
|
|
1839
1893
|
return t === null ? "null" : Array.isArray(t) ? "an array" : typeof t == "object" ? "an object" : `a ${typeof t}`;
|
|
1840
1894
|
}
|
|
1841
|
-
function
|
|
1842
|
-
for (const
|
|
1843
|
-
if (!(
|
|
1844
|
-
const a =
|
|
1895
|
+
function ue(t, e, n, i, r) {
|
|
1896
|
+
for (const o of n) {
|
|
1897
|
+
if (!(o in t) || t[o] === void 0 || t[o] === null || t[o] === "") continue;
|
|
1898
|
+
const a = ii(t[o]);
|
|
1845
1899
|
if (a) return a;
|
|
1846
|
-
const s = t[
|
|
1847
|
-
r(typeof s == "string" && s.trim().length >
|
|
1900
|
+
const s = t[o];
|
|
1901
|
+
r(typeof s == "string" && s.trim().length > Z ? `${i}.${o} is longer than ${Z} characters and was dropped — pass the identifier itself, not a sentence or a URL.` : `${i}.${o} should be a string or number, got ${O(s)} — it was dropped.`);
|
|
1848
1902
|
}
|
|
1849
1903
|
return null;
|
|
1850
1904
|
}
|
|
1851
|
-
function
|
|
1905
|
+
function lt(t) {
|
|
1852
1906
|
if (t === null || typeof t == "boolean") return { ok: !0, value: t };
|
|
1853
1907
|
if (typeof t == "number") return Number.isFinite(t) ? { ok: !0, value: t } : { ok: !1 };
|
|
1854
|
-
if (typeof t == "string") return { ok: !0, value: t.slice(0,
|
|
1908
|
+
if (typeof t == "string") return { ok: !0, value: t.slice(0, ei) };
|
|
1855
1909
|
if (typeof t == "object")
|
|
1856
1910
|
try {
|
|
1857
1911
|
const e = JSON.stringify(t);
|
|
1858
|
-
if (e && e.length <=
|
|
1912
|
+
if (e && e.length <= ti) return { ok: !0, value: JSON.parse(e) };
|
|
1859
1913
|
} catch {
|
|
1860
1914
|
}
|
|
1861
1915
|
return { ok: !1 };
|
|
1862
1916
|
}
|
|
1863
|
-
const
|
|
1864
|
-
function
|
|
1917
|
+
const ut = ["email", "name", "phone"], oi = /* @__PURE__ */ new Set(["id", "userId", ...ut, ...Object.values(we).flat()]);
|
|
1918
|
+
function Re(t, e = () => {
|
|
1865
1919
|
}) {
|
|
1866
1920
|
if (t == null) return null;
|
|
1867
1921
|
if (typeof t != "object" || Array.isArray(t))
|
|
1868
|
-
return e(`identify() takes an object like { id, email, name } or null, got ${
|
|
1922
|
+
return e(`identify() takes an object like { id, email, name } or null, got ${O(t)} — ignored.`), null;
|
|
1869
1923
|
const n = {};
|
|
1870
1924
|
try {
|
|
1871
|
-
const
|
|
1872
|
-
|
|
1873
|
-
for (const
|
|
1874
|
-
const a = t[
|
|
1925
|
+
const i = ue(t, "id", ["id", "userId"], "identify()", e);
|
|
1926
|
+
i && (n.id = i);
|
|
1927
|
+
for (const o of ut) {
|
|
1928
|
+
const a = t[o];
|
|
1875
1929
|
if (a == null || a === "") continue;
|
|
1876
|
-
if (
|
|
1930
|
+
if (o === "phone" && typeof a == "number" && Number.isFinite(a)) {
|
|
1877
1931
|
n.phone = String(a);
|
|
1878
1932
|
continue;
|
|
1879
1933
|
}
|
|
1880
1934
|
if (typeof a != "string") {
|
|
1881
|
-
e(`identify().${
|
|
1935
|
+
e(`identify().${o} should be a string, got ${O(a)} — it was dropped.`);
|
|
1882
1936
|
continue;
|
|
1883
1937
|
}
|
|
1884
|
-
const s = a.trim().slice(0,
|
|
1885
|
-
s && (
|
|
1938
|
+
const s = a.trim().slice(0, o === "name" ? 200 : Z);
|
|
1939
|
+
s && (o === "email" && !s.includes("@") && e(`identify().email "${s}" does not look like an email address — reports cannot be threaded or followed up without one.`), n[o] = s);
|
|
1886
1940
|
}
|
|
1887
|
-
for (const [
|
|
1888
|
-
const s =
|
|
1889
|
-
s && (n[
|
|
1941
|
+
for (const [o, a] of Object.entries(we)) {
|
|
1942
|
+
const s = ue(t, o, a, "identify()", e);
|
|
1943
|
+
s && (n[o] = s);
|
|
1890
1944
|
}
|
|
1891
1945
|
let r = 0;
|
|
1892
|
-
for (const [
|
|
1893
|
-
if (
|
|
1894
|
-
if (r >=
|
|
1895
|
-
e(`identify() was given more than ${
|
|
1946
|
+
for (const [o, a] of Object.entries(t)) {
|
|
1947
|
+
if (oi.has(o) || a === void 0 || typeof a == "function") continue;
|
|
1948
|
+
if (r >= G) {
|
|
1949
|
+
e(`identify() was given more than ${G} extra fields; the rest were dropped.`);
|
|
1896
1950
|
break;
|
|
1897
1951
|
}
|
|
1898
|
-
const s =
|
|
1952
|
+
const s = lt(a);
|
|
1899
1953
|
if (!s.ok) {
|
|
1900
|
-
e(`identify().${
|
|
1954
|
+
e(`identify().${o} could not be sent (${O(a)} too large or not serialisable) — dropped.`);
|
|
1901
1955
|
continue;
|
|
1902
1956
|
}
|
|
1903
|
-
n[
|
|
1957
|
+
n[o] = s.value, r += 1;
|
|
1904
1958
|
}
|
|
1905
1959
|
} catch {
|
|
1906
1960
|
}
|
|
1907
1961
|
return !n.id && !n.email && e("identify() was called without an id or email — reports will not be attributed to anyone, and nothing can be looked up by user."), n;
|
|
1908
1962
|
}
|
|
1909
|
-
function
|
|
1963
|
+
function Le(t, e, n = () => {
|
|
1910
1964
|
}) {
|
|
1911
1965
|
if (e === null) return {};
|
|
1912
|
-
const
|
|
1913
|
-
if (e === void 0) return
|
|
1966
|
+
const i = { ...t || {} };
|
|
1967
|
+
if (e === void 0) return i;
|
|
1914
1968
|
if (typeof e != "object" || Array.isArray(e))
|
|
1915
|
-
return n(`setContext() takes an object like { loanId, screen } or null, got ${
|
|
1969
|
+
return n(`setContext() takes an object like { loanId, screen } or null, got ${O(e)} — ignored.`), i;
|
|
1916
1970
|
try {
|
|
1917
1971
|
const r = /* @__PURE__ */ new Map();
|
|
1918
|
-
for (const [
|
|
1919
|
-
for (const [
|
|
1920
|
-
const s = r.get(
|
|
1972
|
+
for (const [o, a] of Object.entries(we)) for (const s of a) r.set(s, o);
|
|
1973
|
+
for (const [o, a] of Object.entries(e)) {
|
|
1974
|
+
const s = r.get(o);
|
|
1921
1975
|
if (a == null) {
|
|
1922
|
-
delete
|
|
1976
|
+
delete i[s || o];
|
|
1923
1977
|
continue;
|
|
1924
1978
|
}
|
|
1925
1979
|
if (s) {
|
|
1926
|
-
const l =
|
|
1927
|
-
l ?
|
|
1980
|
+
const l = ue({ [o]: a }, s, [o], "setContext()", n);
|
|
1981
|
+
l ? i[s] = l : delete i[s];
|
|
1928
1982
|
continue;
|
|
1929
1983
|
}
|
|
1930
1984
|
if (typeof a == "function") continue;
|
|
1931
|
-
if (!(
|
|
1932
|
-
n(`setContext() holds at most ${
|
|
1985
|
+
if (!(o in i) && Object.keys(i).length >= G) {
|
|
1986
|
+
n(`setContext() holds at most ${G} keys; "${o}" was dropped.`);
|
|
1933
1987
|
continue;
|
|
1934
1988
|
}
|
|
1935
|
-
const c =
|
|
1989
|
+
const c = lt(a);
|
|
1936
1990
|
if (!c.ok) {
|
|
1937
|
-
n(`setContext().${
|
|
1991
|
+
n(`setContext().${o} could not be sent (${O(a)} too large or not serialisable) — dropped.`);
|
|
1938
1992
|
continue;
|
|
1939
1993
|
}
|
|
1940
|
-
o
|
|
1994
|
+
i[o] = c.value;
|
|
1941
1995
|
}
|
|
1942
1996
|
} catch {
|
|
1943
1997
|
}
|
|
1944
|
-
return
|
|
1998
|
+
return i;
|
|
1945
1999
|
}
|
|
1946
|
-
const
|
|
2000
|
+
const dt = [
|
|
1947
2001
|
"apiBase",
|
|
1948
2002
|
"apiKey",
|
|
1949
2003
|
"projectId",
|
|
@@ -1981,7 +2035,7 @@ const ot = [
|
|
|
1981
2035
|
"buildId",
|
|
1982
2036
|
"chunkBase",
|
|
1983
2037
|
"announcements"
|
|
1984
|
-
],
|
|
2038
|
+
], ri = [
|
|
1985
2039
|
"beforeSend",
|
|
1986
2040
|
"onUpdate",
|
|
1987
2041
|
"onCallState",
|
|
@@ -1990,35 +2044,35 @@ const ot = [
|
|
|
1990
2044
|
"onAssistantPhase",
|
|
1991
2045
|
"onError"
|
|
1992
2046
|
];
|
|
1993
|
-
function
|
|
2047
|
+
function ai(t) {
|
|
1994
2048
|
const e = t.toLowerCase().replace(/[-_]/g, "");
|
|
1995
|
-
return
|
|
2049
|
+
return dt.find((n) => n.toLowerCase() === e) || null;
|
|
1996
2050
|
}
|
|
1997
|
-
const
|
|
1998
|
-
function
|
|
1999
|
-
const n = [],
|
|
2051
|
+
const Ke = /^(your[_-]|<|xxx|todo|changeme)/i, si = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2052
|
+
function ci(t, { pageHost: e = "" } = {}) {
|
|
2053
|
+
const n = [], i = [];
|
|
2000
2054
|
if (!t || typeof t != "object")
|
|
2001
|
-
return n.push("init() takes an options object: BugCatch.init({ apiBase, apiKey, projectId })."), { errors: n, warnings:
|
|
2002
|
-
const { apiKey: r, projectId:
|
|
2003
|
-
r ? typeof r != "string" ? n.push(`apiKey must be a string, got ${
|
|
2055
|
+
return n.push("init() takes an options object: BugCatch.init({ apiBase, apiKey, projectId })."), { errors: n, warnings: i };
|
|
2056
|
+
const { apiKey: r, projectId: o, apiBase: a } = t;
|
|
2057
|
+
r ? typeof r != "string" ? n.push(`apiKey must be a string, got ${O(r)}.`) : Ke.test(r) ? n.push(`apiKey is still the placeholder "${r}" — paste the key you saved when you created it.`) : si.test(r) ? i.push("apiKey looks like a project id — did you swap apiKey and projectId?") : r.startsWith("bc_") || i.push('apiKey does not look like a BugCatch key (they start with "bc_live_") — reports will be refused with HTTP 401.') : n.push("apiKey is required — create one under Workspace Settings → API Keys."), o ? typeof o != "string" ? n.push(`projectId must be a string, got ${O(o)}.`) : Ke.test(o) ? n.push(`projectId is still the placeholder "${o}".`) : o.startsWith("bc_") ? i.push("projectId looks like an API key — did you swap apiKey and projectId?") : /\s/.test(o) && i.push("projectId contains whitespace — check it was copied cleanly.") : n.push("projectId is required — copy it from Project Settings → Web SDK."), a == null ? !e || /^(localhost|127\.|0\.0\.0\.0|\[::1\])/.test(e) || i.push("apiBase is not set, so reports go to http://localhost:3000 — set apiBase to your BugCatch API URL.") : (typeof a != "string" || !/^https?:\/\//.test(a)) && i.push(`apiBase should be an absolute http(s) URL, got ${JSON.stringify(a)}.`);
|
|
2004
2058
|
for (const s of Object.keys(t)) {
|
|
2005
|
-
if (
|
|
2006
|
-
const c =
|
|
2007
|
-
|
|
2059
|
+
if (dt.includes(s)) continue;
|
|
2060
|
+
const c = ai(s);
|
|
2061
|
+
i.push(c ? `unknown option "${s}" — did you mean "${c}"?` : `unknown option "${s}" is ignored.`);
|
|
2008
2062
|
}
|
|
2009
|
-
for (const s of
|
|
2063
|
+
for (const s of ri) {
|
|
2010
2064
|
const c = t[s];
|
|
2011
|
-
c != null && typeof c != "function" &&
|
|
2065
|
+
c != null && typeof c != "function" && i.push(`${s} should be a function, got ${O(c)} — it will not be called.`);
|
|
2012
2066
|
}
|
|
2013
|
-
return { errors: n, warnings:
|
|
2067
|
+
return { errors: n, warnings: i };
|
|
2014
2068
|
}
|
|
2015
|
-
function
|
|
2069
|
+
function li(t) {
|
|
2016
2070
|
return typeof t == "string" ? t.replace(/\/+$/, "") : t;
|
|
2017
2071
|
}
|
|
2018
|
-
const
|
|
2072
|
+
const D = {
|
|
2019
2073
|
name: "@sphoro/bugcatch-web-sdk",
|
|
2020
|
-
version: "0.
|
|
2021
|
-
},
|
|
2074
|
+
version: "0.20.0"
|
|
2075
|
+
}, U = {
|
|
2022
2076
|
apiBase: "http://localhost:3000",
|
|
2023
2077
|
apiKey: null,
|
|
2024
2078
|
projectId: null,
|
|
@@ -2032,7 +2086,9 @@ const K = {
|
|
|
2032
2086
|
widgetPosition: "bottom-right",
|
|
2033
2087
|
// 'auto' follows the visitor's system setting; 'light' / 'dark' pin it.
|
|
2034
2088
|
theme: "auto",
|
|
2035
|
-
|
|
2089
|
+
// null is ink: black buttons on light, white on dark (accent.js). Any CSS
|
|
2090
|
+
// colour makes the buttons, the launcher and the assistant's orb that colour.
|
|
2091
|
+
accent: null,
|
|
2036
2092
|
// Draw what the project's team is telling visitors — written on the Widget
|
|
2037
2093
|
// announcements settings page — in the panel, and beside the button for the
|
|
2038
2094
|
// ones written for that. false draws nothing; announcements() still answers,
|
|
@@ -2100,15 +2156,15 @@ const K = {
|
|
|
2100
2156
|
// printed either way.
|
|
2101
2157
|
debug: !1
|
|
2102
2158
|
};
|
|
2103
|
-
function
|
|
2159
|
+
function ui(t) {
|
|
2104
2160
|
const e = E();
|
|
2105
2161
|
return e ? { ...t, watchToken: e } : t;
|
|
2106
2162
|
}
|
|
2107
|
-
var
|
|
2108
|
-
class
|
|
2163
|
+
var w, F, ft, R, pt, de, X, W, he, gt, mt, wt, J, yt;
|
|
2164
|
+
class ht {
|
|
2109
2165
|
constructor() {
|
|
2110
|
-
|
|
2111
|
-
this.config = { ...
|
|
2166
|
+
xe(this, w);
|
|
2167
|
+
this.config = { ...U }, this.started = !1, this.teardown = [], this.consoleBuffer = z(U.consoleLimit), this.networkBuffer = z(U.networkLimit), this.stopWatching = null, this.notifier = null, this.call = null, this.callStarting = !1, this.ringing = null, this.listeners = /* @__PURE__ */ new Map(), this.context = {}, this.warned = /* @__PURE__ */ new Set(), this.phases = /* @__PURE__ */ new Map();
|
|
2112
2168
|
}
|
|
2113
2169
|
/** A misconfiguration, said once. Always printed — it is what saves a day of guessing. */
|
|
2114
2170
|
warn(e) {
|
|
@@ -2121,14 +2177,14 @@ class it {
|
|
|
2121
2177
|
init(e = {}) {
|
|
2122
2178
|
if (this.started)
|
|
2123
2179
|
return console.warn("[BugCatch] init() called twice — ignoring the second call."), this;
|
|
2124
|
-
const { errors: n, warnings:
|
|
2180
|
+
const { errors: n, warnings: i } = ci(e, {
|
|
2125
2181
|
pageHost: typeof location < "u" ? location.hostname : ""
|
|
2126
2182
|
});
|
|
2127
2183
|
if (n.length) throw new Error(`[BugCatch] ${n[0]}`);
|
|
2128
|
-
for (const
|
|
2184
|
+
for (const o of i) this.warn(o);
|
|
2129
2185
|
const r = this.config.user;
|
|
2130
|
-
return this.config = { ...
|
|
2131
|
-
version:
|
|
2186
|
+
return this.config = { ...U, ...e, apiBase: li(e.apiBase ?? U.apiBase) }, this.config.user = e.user !== void 0 ? Re(e.user, (o) => this.warn(o.replace("identify()", "init({ user })"))) : r || null, e.context && this.setContext(e.context), this.consoleBuffer = z(this.config.consoleLimit), this.networkBuffer = z(this.config.networkLimit), this.config.captureConsole && this.teardown.push(At(this.consoleBuffer)), this.config.captureNetwork && this.teardown.push(jt(this.networkBuffer)), this.config.captureErrors && this.teardown.push(Ot(this.consoleBuffer)), tn(this.config.projectId), this.config.widget && this.teardown.push(Ft(this)), this.config.updates && E() && (this.startWatching(), queueMicrotask(() => x(this, w, R).call(this))), this.started = !0, x(this, w, ft).call(this), this.debugLog("initialised", {
|
|
2187
|
+
version: D.version,
|
|
2132
2188
|
apiBase: this.config.apiBase,
|
|
2133
2189
|
projectId: this.config.projectId,
|
|
2134
2190
|
user: this.config.user,
|
|
@@ -2141,26 +2197,26 @@ class it {
|
|
|
2141
2197
|
*/
|
|
2142
2198
|
startWatching() {
|
|
2143
2199
|
if (this.stopWatching) return this;
|
|
2144
|
-
this.stopWatching =
|
|
2200
|
+
this.stopWatching = mn({
|
|
2145
2201
|
apiBase: this.config.apiBase,
|
|
2146
2202
|
onUpdate: (n) => {
|
|
2147
2203
|
if (n != null && n.incomingCall) {
|
|
2148
|
-
x(this,
|
|
2204
|
+
x(this, w, wt).call(this, n);
|
|
2149
2205
|
return;
|
|
2150
2206
|
}
|
|
2151
2207
|
if (n != null && n.callWithdrawn) {
|
|
2152
|
-
x(this,
|
|
2208
|
+
x(this, w, J).call(this, n.callWithdrawn.callId);
|
|
2153
2209
|
return;
|
|
2154
2210
|
}
|
|
2155
|
-
const
|
|
2156
|
-
typeof this.config.onUpdate == "function" && this.config.onUpdate(
|
|
2211
|
+
const i = on(n);
|
|
2212
|
+
typeof this.config.onUpdate == "function" && this.config.onUpdate(i), this.emit("update", i), x(this, w, R).call(this);
|
|
2157
2213
|
}
|
|
2158
2214
|
}), this.teardown.push(() => {
|
|
2159
2215
|
var n;
|
|
2160
2216
|
return (n = this.stopWatching) == null ? void 0 : n.call(this);
|
|
2161
|
-
}), this.teardown.push(() => x(this,
|
|
2217
|
+
}), this.teardown.push(() => x(this, w, J).call(this));
|
|
2162
2218
|
const e = (n) => {
|
|
2163
|
-
(n.key ===
|
|
2219
|
+
(n.key === V || n.key === null) && x(this, w, R).call(this);
|
|
2164
2220
|
};
|
|
2165
2221
|
return window.addEventListener("storage", e), this.teardown.push(() => window.removeEventListener("storage", e)), this;
|
|
2166
2222
|
}
|
|
@@ -2177,18 +2233,18 @@ class it {
|
|
|
2177
2233
|
on(e, n) {
|
|
2178
2234
|
if (typeof n != "function") return () => {
|
|
2179
2235
|
};
|
|
2180
|
-
const
|
|
2181
|
-
return
|
|
2236
|
+
const i = this.listeners.get(e) || /* @__PURE__ */ new Set();
|
|
2237
|
+
return i.add(n), this.listeners.set(e, i), () => this.off(e, n);
|
|
2182
2238
|
}
|
|
2183
2239
|
off(e, n) {
|
|
2184
|
-
var
|
|
2185
|
-
return (
|
|
2240
|
+
var i;
|
|
2241
|
+
return (i = this.listeners.get(e)) == null || i.delete(n), this;
|
|
2186
2242
|
}
|
|
2187
2243
|
/** Notify listeners; one that throws must not stop the rest. */
|
|
2188
2244
|
emit(e, n) {
|
|
2189
|
-
for (const
|
|
2245
|
+
for (const i of this.listeners.get(e) || [])
|
|
2190
2246
|
try {
|
|
2191
|
-
|
|
2247
|
+
i(n);
|
|
2192
2248
|
} catch (r) {
|
|
2193
2249
|
console.error(`[BugCatch] a '${e}' listener threw:`, r);
|
|
2194
2250
|
}
|
|
@@ -2204,7 +2260,7 @@ class it {
|
|
|
2204
2260
|
* Each carries the `id` the mark-read calls take.
|
|
2205
2261
|
*/
|
|
2206
2262
|
unreadUpdates() {
|
|
2207
|
-
return
|
|
2263
|
+
return H();
|
|
2208
2264
|
}
|
|
2209
2265
|
/**
|
|
2210
2266
|
* Mark one update read. It stops being shown, here and on the next load.
|
|
@@ -2217,7 +2273,7 @@ class it {
|
|
|
2217
2273
|
* knows when its reader has seen one, so it has to say.
|
|
2218
2274
|
*/
|
|
2219
2275
|
markUpdateRead(e) {
|
|
2220
|
-
return
|
|
2276
|
+
return rn(e), x(this, w, R).call(this), this;
|
|
2221
2277
|
}
|
|
2222
2278
|
/**
|
|
2223
2279
|
* Mark everything about one report read.
|
|
@@ -2226,11 +2282,31 @@ class it {
|
|
|
2226
2282
|
* the thread opens; an integration with its own report view should too.
|
|
2227
2283
|
*/
|
|
2228
2284
|
markReportRead(e) {
|
|
2229
|
-
return
|
|
2285
|
+
return an(e), x(this, w, R).call(this), this;
|
|
2230
2286
|
}
|
|
2231
2287
|
/** Mark everything read. The "clear all" behind your own notification list. */
|
|
2232
2288
|
markUpdatesRead() {
|
|
2233
|
-
return
|
|
2289
|
+
return Ze(), x(this, w, R).call(this), this;
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Tell the team whether their fix worked. STILL_HAPPENING reopens the report
|
|
2293
|
+
* and re-sends this browser's context with it.
|
|
2294
|
+
*/
|
|
2295
|
+
async verifyFix(e, { result: n, resolvedAt: i, note: r }) {
|
|
2296
|
+
const o = n === "STILL_HAPPENING" ? await x(this, w, W).call(this, {}) : {};
|
|
2297
|
+
return $n({ apiBase: this.config.apiBase, bugId: e, result: n, resolvedAt: i, note: r, metadata: o.metadata, logs: o.logs });
|
|
2298
|
+
}
|
|
2299
|
+
/**
|
|
2300
|
+
* Rate how a settled report was handled, 1 to 5, five best.
|
|
2301
|
+
*
|
|
2302
|
+
* await BugCatch.rate(report.id, { score: 4, comment: 'Quick, thanks' });
|
|
2303
|
+
*
|
|
2304
|
+
* Only once the report is RESOLVED or CLOSED, on a project that asks for
|
|
2305
|
+
* ratings — `myReport(id).ratingAsked` says whether it does. Rating again
|
|
2306
|
+
* replaces the earlier score rather than adding a second one.
|
|
2307
|
+
*/
|
|
2308
|
+
async rate(e, { score: n, comment: i } = {}) {
|
|
2309
|
+
return En({ apiBase: this.config.apiBase, bugId: e, score: n, comment: i });
|
|
2234
2310
|
}
|
|
2235
2311
|
/**
|
|
2236
2312
|
* One report in full, with its timeline — every step from filing to now.
|
|
@@ -2240,13 +2316,9 @@ class it {
|
|
|
2240
2316
|
*
|
|
2241
2317
|
* Resolves to null when this browser cannot prove it filed that report.
|
|
2242
2318
|
*/
|
|
2243
|
-
async verifyFix(e, { result: n, resolvedAt: o, note: r }) {
|
|
2244
|
-
const i = n === "STILL_HAPPENING" ? await x(this, m, z).call(this, {}) : {};
|
|
2245
|
-
return yn({ apiBase: this.config.apiBase, bugId: e, result: n, resolvedAt: o, note: r, metadata: i.metadata, logs: i.logs });
|
|
2246
|
-
}
|
|
2247
2319
|
async myReport(e) {
|
|
2248
|
-
const n = await
|
|
2249
|
-
return x(this,
|
|
2320
|
+
const n = await ln({ apiBase: this.config.apiBase, bugId: e });
|
|
2321
|
+
return x(this, w, pt).call(this, e, n == null ? void 0 : n.assistant), n;
|
|
2250
2322
|
}
|
|
2251
2323
|
/**
|
|
2252
2324
|
* Write back on a report this browser filed.
|
|
@@ -2261,8 +2333,8 @@ class it {
|
|
|
2261
2333
|
* integration rendering its own can too. Resolves to the stored message, so
|
|
2262
2334
|
* the caller renders what the server kept rather than what it hoped it sent.
|
|
2263
2335
|
*/
|
|
2264
|
-
replyToReport(e, { body: n, attachments:
|
|
2265
|
-
return
|
|
2336
|
+
replyToReport(e, { body: n, attachments: i } = {}) {
|
|
2337
|
+
return un({ apiBase: this.config.apiBase, bugId: e, body: n, attachments: i });
|
|
2266
2338
|
}
|
|
2267
2339
|
/**
|
|
2268
2340
|
* Whether this visitor can report something by talking about it instead.
|
|
@@ -2315,7 +2387,7 @@ class it {
|
|
|
2315
2387
|
async callKinds() {
|
|
2316
2388
|
var n;
|
|
2317
2389
|
const e = { agent: !1, live: !1 };
|
|
2318
|
-
return !this.config.voice || !((n = this.config.user) != null && n.email) ? e : this.kinds !== void 0 ? this.kinds : (this.kinds = await
|
|
2390
|
+
return !this.config.voice || !((n = this.config.user) != null && n.email) ? e : this.kinds !== void 0 ? this.kinds : (this.kinds = await dn({
|
|
2319
2391
|
apiBase: this.config.apiBase,
|
|
2320
2392
|
apiKey: this.config.apiKey,
|
|
2321
2393
|
projectId: this.config.projectId
|
|
@@ -2336,7 +2408,7 @@ class it {
|
|
|
2336
2408
|
* for either of them to be asking about.
|
|
2337
2409
|
*/
|
|
2338
2410
|
canCall(e) {
|
|
2339
|
-
return this.config.voice ?
|
|
2411
|
+
return this.config.voice ? Ae({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
|
|
2340
2412
|
}
|
|
2341
2413
|
/**
|
|
2342
2414
|
* Ring the team.
|
|
@@ -2379,7 +2451,7 @@ class it {
|
|
|
2379
2451
|
try {
|
|
2380
2452
|
if (!await this.callKind())
|
|
2381
2453
|
throw new Error((n = this.config.user) != null && n.email ? "[BugCatch] calling is not available on this project." : "[BugCatch] a call needs to know who is calling — call identify() with an email first.");
|
|
2382
|
-
return await x(this,
|
|
2454
|
+
return await x(this, w, mt).call(this, e);
|
|
2383
2455
|
} finally {
|
|
2384
2456
|
this.callStarting = !1;
|
|
2385
2457
|
}
|
|
@@ -2402,7 +2474,7 @@ class it {
|
|
|
2402
2474
|
* For a host application drawing its own button. The widget asks this itself.
|
|
2403
2475
|
*/
|
|
2404
2476
|
canCallTeam(e) {
|
|
2405
|
-
return this.config.voice ?
|
|
2477
|
+
return this.config.voice ? Ae({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
|
|
2406
2478
|
}
|
|
2407
2479
|
/**
|
|
2408
2480
|
* End the call in progress, of either kind. Does nothing when there is not
|
|
@@ -2424,7 +2496,7 @@ class it {
|
|
|
2424
2496
|
* nothing to look up in either case.
|
|
2425
2497
|
*/
|
|
2426
2498
|
myReports() {
|
|
2427
|
-
return
|
|
2499
|
+
return cn({ apiBase: this.config.apiBase });
|
|
2428
2500
|
}
|
|
2429
2501
|
/** True when this browser has filed something, so a "your reports" entry
|
|
2430
2502
|
* point can be hidden until it would show anything. */
|
|
@@ -2437,7 +2509,7 @@ class it {
|
|
|
2437
2509
|
*/
|
|
2438
2510
|
forgetReports() {
|
|
2439
2511
|
var e;
|
|
2440
|
-
return (e = this.stopWatching) == null || e.call(this), this.stopWatching = null, this.endCall(),
|
|
2512
|
+
return (e = this.stopWatching) == null || e.call(this), this.stopWatching = null, this.endCall(), K(), x(this, w, R).call(this), this;
|
|
2441
2513
|
}
|
|
2442
2514
|
/**
|
|
2443
2515
|
* Attach the signed-in user so reports say who hit the bug.
|
|
@@ -2454,7 +2526,7 @@ class it {
|
|
|
2454
2526
|
* Pass null to forget them again on sign-out.
|
|
2455
2527
|
*/
|
|
2456
2528
|
identify(e) {
|
|
2457
|
-
const n =
|
|
2529
|
+
const n = Re(e, (i) => this.warn(i));
|
|
2458
2530
|
return e != null && !n ? this : (this.config.user = n, this.debugLog("identify", n), this);
|
|
2459
2531
|
}
|
|
2460
2532
|
/**
|
|
@@ -2471,7 +2543,7 @@ class it {
|
|
|
2471
2543
|
* outrank the same field on identify(); anything else is readable metadata.
|
|
2472
2544
|
*/
|
|
2473
2545
|
setContext(e) {
|
|
2474
|
-
return this.context =
|
|
2546
|
+
return this.context = Le(this.context, e, (n) => this.warn(n)), this.debugLog("context", this.context), this;
|
|
2475
2547
|
}
|
|
2476
2548
|
/** What setContext() currently holds (a copy). */
|
|
2477
2549
|
getContext() {
|
|
@@ -2505,61 +2577,61 @@ class it {
|
|
|
2505
2577
|
* through the API — so this is also what you call when you drive the SDK
|
|
2506
2578
|
* yourself with `widget: false`.
|
|
2507
2579
|
*/
|
|
2508
|
-
async uploadAttachment(e, n,
|
|
2580
|
+
async uploadAttachment(e, n, i) {
|
|
2509
2581
|
if (!this.started) throw new Error("[BugCatch] call init() first.");
|
|
2510
|
-
return
|
|
2582
|
+
return Gt({
|
|
2511
2583
|
apiBase: this.config.apiBase,
|
|
2512
2584
|
apiKey: this.config.apiKey,
|
|
2513
2585
|
blob: e,
|
|
2514
2586
|
mime: n || (e == null ? void 0 : e.type),
|
|
2515
|
-
onProgress:
|
|
2587
|
+
onProgress: i
|
|
2516
2588
|
});
|
|
2517
2589
|
}
|
|
2518
2590
|
/** File a bug with everything captured so far. */
|
|
2519
2591
|
async report({
|
|
2520
2592
|
title: e,
|
|
2521
2593
|
description: n = "",
|
|
2522
|
-
priority:
|
|
2594
|
+
priority: i = "MEDIUM",
|
|
2523
2595
|
metadata: r = {},
|
|
2524
|
-
attachments:
|
|
2596
|
+
attachments: o = [],
|
|
2525
2597
|
references: a = [],
|
|
2526
2598
|
context: s = null,
|
|
2527
2599
|
issue: c = null
|
|
2528
2600
|
} = {}) {
|
|
2529
|
-
var
|
|
2601
|
+
var I, v, T, p, k, g, b, B;
|
|
2530
2602
|
if (!this.started) throw new Error("[BugCatch] call init() first.");
|
|
2531
2603
|
if (typeof e != "string" || !e.trim()) throw new Error("[BugCatch] a title is required.");
|
|
2532
|
-
["LOW", "MEDIUM", "HIGH", "CRITICAL"].includes(String(
|
|
2533
|
-
const l = (
|
|
2534
|
-
type:
|
|
2535
|
-
storageKey:
|
|
2536
|
-
mime:
|
|
2537
|
-
})),
|
|
2538
|
-
Array.isArray(a) &&
|
|
2539
|
-
let
|
|
2604
|
+
["LOW", "MEDIUM", "HIGH", "CRITICAL"].includes(String(i).toUpperCase()) || (this.warn(`priority "${i}" is not one of LOW, MEDIUM, HIGH, CRITICAL — sent as MEDIUM.`), i = "MEDIUM");
|
|
2605
|
+
const l = (o || []).filter((y) => (y == null ? void 0 : y.storageKey) && ae(y.mime, $e)).map((y) => ({
|
|
2606
|
+
type: y.type === "VIDEO" ? "VIDEO" : "SCREENSHOT",
|
|
2607
|
+
storageKey: y.storageKey,
|
|
2608
|
+
mime: ae(y.mime, $e)
|
|
2609
|
+
})), h = (Array.isArray(a) ? a : []).filter((y) => y && typeof y.key == "string" && y.key && (typeof y.value == "string" || typeof y.value == "number")).map((y) => ({ key: y.key.slice(0, 64), value: String(y.value).trim().slice(0, 120) })).filter((y) => y.value);
|
|
2610
|
+
Array.isArray(a) && h.length < a.length && this.warn("report({ references }) takes [{ key, value }] with string values; malformed entries were dropped.");
|
|
2611
|
+
let f = await x(this, w, W).call(this, {
|
|
2540
2612
|
title: e.trim(),
|
|
2541
2613
|
description: typeof n == "string" ? n : String(n ?? ""),
|
|
2542
|
-
priority: String(
|
|
2614
|
+
priority: String(i).toUpperCase(),
|
|
2543
2615
|
metadata: r,
|
|
2544
2616
|
media: l,
|
|
2545
|
-
references:
|
|
2617
|
+
references: h,
|
|
2546
2618
|
context: s,
|
|
2547
2619
|
issue: typeof c == "string" && c ? c.slice(0, 32) : null
|
|
2548
2620
|
});
|
|
2549
|
-
const d = x(this,
|
|
2621
|
+
const d = x(this, w, he).call(this, f);
|
|
2550
2622
|
if (d === !1) return { cancelled: !0 };
|
|
2551
|
-
|
|
2552
|
-
title:
|
|
2553
|
-
user: (
|
|
2554
|
-
context: (
|
|
2555
|
-
references:
|
|
2556
|
-
console: (
|
|
2557
|
-
network: (B = (
|
|
2623
|
+
f = d, this.debugLog("sending report", {
|
|
2624
|
+
title: f.title,
|
|
2625
|
+
user: (I = f.metadata) == null ? void 0 : I.user,
|
|
2626
|
+
context: (v = f.metadata) == null ? void 0 : v.context,
|
|
2627
|
+
references: f.references,
|
|
2628
|
+
console: (k = (p = (T = f.logs) == null ? void 0 : T.console) == null ? void 0 : p.entries) == null ? void 0 : k.length,
|
|
2629
|
+
network: (B = (b = (g = f.logs) == null ? void 0 : g.network) == null ? void 0 : b.entries) == null ? void 0 : B.length
|
|
2558
2630
|
});
|
|
2559
|
-
const u =
|
|
2560
|
-
let
|
|
2631
|
+
const u = M(this.config.projectId);
|
|
2632
|
+
let m;
|
|
2561
2633
|
try {
|
|
2562
|
-
|
|
2634
|
+
m = await fetch(`${this.config.apiBase}/ingest/bugs`, {
|
|
2563
2635
|
method: "POST",
|
|
2564
2636
|
headers: {
|
|
2565
2637
|
"Content-Type": "application/json",
|
|
@@ -2570,25 +2642,25 @@ class it {
|
|
|
2570
2642
|
// reporter would undo the requirement.
|
|
2571
2643
|
...u != null && u.token ? { "X-BugCatch-Session": u.token } : {}
|
|
2572
2644
|
},
|
|
2573
|
-
body: JSON.stringify(
|
|
2645
|
+
body: JSON.stringify(ui(f))
|
|
2574
2646
|
});
|
|
2575
|
-
} catch (
|
|
2576
|
-
const
|
|
2577
|
-
throw
|
|
2647
|
+
} catch (y) {
|
|
2648
|
+
const C = new Error(`[BugCatch] could not reach ${this.config.apiBase} — check apiBase, and that this site's origin is allowed by the API.`);
|
|
2649
|
+
throw C.cause = y, x(this, w, X).call(this, "report", C), C;
|
|
2578
2650
|
}
|
|
2579
|
-
if (
|
|
2580
|
-
let
|
|
2651
|
+
if (m.status === 401 && u && ce(this.config.projectId), !m.ok) {
|
|
2652
|
+
let y = "";
|
|
2581
2653
|
try {
|
|
2582
|
-
const
|
|
2583
|
-
|
|
2654
|
+
const A = await m.json();
|
|
2655
|
+
y = Array.isArray(A.message) ? A.message.join(", ") : A.message || "";
|
|
2584
2656
|
} catch {
|
|
2585
2657
|
}
|
|
2586
|
-
|
|
2587
|
-
const
|
|
2588
|
-
throw
|
|
2658
|
+
m.status === 401 && !u && (y || (y = "the apiKey was not accepted")), m.status === 403 && (y || (y = "the apiKey is not allowed to report to this projectId"));
|
|
2659
|
+
const C = m.status === 429 ? new Error(`[BugCatch] ${N(y)}`) : new Error(`[BugCatch] report failed (HTTP ${m.status})${y ? ": " + y : ""}`);
|
|
2660
|
+
throw C.status = m.status, x(this, w, X).call(this, "report", C), C;
|
|
2589
2661
|
}
|
|
2590
|
-
const $ = await
|
|
2591
|
-
return x(this,
|
|
2662
|
+
const $ = await m.json();
|
|
2663
|
+
return x(this, w, de).call(this, $, { title: f.title ?? e.trim(), via: "form" }), $.watchToken && (se($.watchToken), this.config.updates && this.startWatching()), $;
|
|
2592
2664
|
}
|
|
2593
2665
|
/**
|
|
2594
2666
|
* What this project asks of the person reporting, and who this browser is
|
|
@@ -2607,11 +2679,11 @@ class it {
|
|
|
2607
2679
|
*/
|
|
2608
2680
|
loginState() {
|
|
2609
2681
|
var e;
|
|
2610
|
-
return
|
|
2682
|
+
return jn({
|
|
2611
2683
|
apiBase: this.config.apiBase,
|
|
2612
2684
|
apiKey: this.config.apiKey,
|
|
2613
2685
|
projectId: this.config.projectId,
|
|
2614
|
-
token: (e =
|
|
2686
|
+
token: (e = M(this.config.projectId)) == null ? void 0 : e.token
|
|
2615
2687
|
});
|
|
2616
2688
|
}
|
|
2617
2689
|
/**
|
|
@@ -2630,7 +2702,7 @@ class it {
|
|
|
2630
2702
|
* whether that form should have an identifier box on it.
|
|
2631
2703
|
*/
|
|
2632
2704
|
referenceFields() {
|
|
2633
|
-
return this.refFields ? this.refFields : (this.refFields =
|
|
2705
|
+
return this.refFields ? this.refFields : (this.refFields = Dn({
|
|
2634
2706
|
apiBase: this.config.apiBase,
|
|
2635
2707
|
apiKey: this.config.apiKey,
|
|
2636
2708
|
projectId: this.config.projectId
|
|
@@ -2652,7 +2724,7 @@ class it {
|
|
|
2652
2724
|
* itself; cached for the life of the page.
|
|
2653
2725
|
*/
|
|
2654
2726
|
agentIssues() {
|
|
2655
|
-
return this.agentIssueList ? this.agentIssueList : (this.agentIssueList =
|
|
2727
|
+
return this.agentIssueList ? this.agentIssueList : (this.agentIssueList = _n({
|
|
2656
2728
|
apiBase: this.config.apiBase,
|
|
2657
2729
|
apiKey: this.config.apiKey,
|
|
2658
2730
|
projectId: this.config.projectId
|
|
@@ -2673,12 +2745,12 @@ class it {
|
|
|
2673
2745
|
* `widget: false` or `announcements: false`. Empty on every failure.
|
|
2674
2746
|
*/
|
|
2675
2747
|
async announcements() {
|
|
2676
|
-
const e = await
|
|
2748
|
+
const e = await Fn({
|
|
2677
2749
|
apiBase: this.config.apiBase,
|
|
2678
2750
|
apiKey: this.config.apiKey,
|
|
2679
2751
|
projectId: this.config.projectId
|
|
2680
2752
|
});
|
|
2681
|
-
return
|
|
2753
|
+
return Xn(e);
|
|
2682
2754
|
}
|
|
2683
2755
|
/**
|
|
2684
2756
|
* Stop showing an announcement in this browser, until the team uses "Show it
|
|
@@ -2686,7 +2758,7 @@ class it {
|
|
|
2686
2758
|
* is left alone.
|
|
2687
2759
|
*/
|
|
2688
2760
|
dismissAnnouncement(e) {
|
|
2689
|
-
|
|
2761
|
+
Wn(e);
|
|
2690
2762
|
}
|
|
2691
2763
|
/**
|
|
2692
2764
|
* Who this browser is signed in as on this project, from storage alone.
|
|
@@ -2698,7 +2770,7 @@ class it {
|
|
|
2698
2770
|
* the server. Use loginState() where that matters.
|
|
2699
2771
|
*/
|
|
2700
2772
|
signedInAs() {
|
|
2701
|
-
const e =
|
|
2773
|
+
const e = M(this.config.projectId);
|
|
2702
2774
|
return e ? { email: e.email, name: e.name } : null;
|
|
2703
2775
|
}
|
|
2704
2776
|
/**
|
|
@@ -2713,14 +2785,14 @@ class it {
|
|
|
2713
2785
|
* address, which is all a reply-to has ever needed to be worth.
|
|
2714
2786
|
*/
|
|
2715
2787
|
signIn(e, { name: n } = {}) {
|
|
2716
|
-
var
|
|
2717
|
-
return
|
|
2788
|
+
var i;
|
|
2789
|
+
return On({
|
|
2718
2790
|
apiBase: this.config.apiBase,
|
|
2719
2791
|
apiKey: this.config.apiKey,
|
|
2720
2792
|
projectId: this.config.projectId,
|
|
2721
2793
|
email: e,
|
|
2722
2794
|
// The name the host app already knows beats asking for one again.
|
|
2723
|
-
name: n ?? ((
|
|
2795
|
+
name: n ?? ((i = this.config.user) == null ? void 0 : i.name) ?? null
|
|
2724
2796
|
});
|
|
2725
2797
|
}
|
|
2726
2798
|
/**
|
|
@@ -2732,14 +2804,14 @@ class it {
|
|
|
2732
2804
|
*/
|
|
2733
2805
|
async confirmSignIn(e, n) {
|
|
2734
2806
|
var r;
|
|
2735
|
-
const
|
|
2807
|
+
const i = await Mn({
|
|
2736
2808
|
apiBase: this.config.apiBase,
|
|
2737
2809
|
apiKey: this.config.apiKey,
|
|
2738
2810
|
projectId: this.config.projectId,
|
|
2739
2811
|
email: e,
|
|
2740
2812
|
code: n
|
|
2741
2813
|
});
|
|
2742
|
-
return (r = this.config.user) != null && r.email || (this.config.user = { email:
|
|
2814
|
+
return (r = this.config.user) != null && r.email || (this.config.user = { email: i.email, name: i.name || void 0 }), this.emit("signin", { email: i.email, name: i.name }), { email: i.email, name: i.name };
|
|
2743
2815
|
}
|
|
2744
2816
|
/**
|
|
2745
2817
|
* Sign out of this project.
|
|
@@ -2749,14 +2821,14 @@ class it {
|
|
|
2749
2821
|
* says — sign-out on a shared machine has to mean signed out on it.
|
|
2750
2822
|
*/
|
|
2751
2823
|
async signOut() {
|
|
2752
|
-
var
|
|
2753
|
-
const e =
|
|
2824
|
+
var i;
|
|
2825
|
+
const e = M(this.config.projectId), n = await Rn({
|
|
2754
2826
|
apiBase: this.config.apiBase,
|
|
2755
2827
|
apiKey: this.config.apiKey,
|
|
2756
2828
|
projectId: this.config.projectId,
|
|
2757
2829
|
token: e == null ? void 0 : e.token
|
|
2758
2830
|
});
|
|
2759
|
-
return e != null && e.email && ((
|
|
2831
|
+
return e != null && e.email && ((i = this.config.user) == null ? void 0 : i.email) === e.email && (this.config.user = null), this.emit("signout", { email: (e == null ? void 0 : e.email) || null }), n;
|
|
2760
2832
|
}
|
|
2761
2833
|
/**
|
|
2762
2834
|
* What this project is already known to be having trouble with.
|
|
@@ -2768,11 +2840,11 @@ class it {
|
|
|
2768
2840
|
*/
|
|
2769
2841
|
knownIssues() {
|
|
2770
2842
|
var e;
|
|
2771
|
-
return
|
|
2843
|
+
return In({
|
|
2772
2844
|
apiBase: this.config.apiBase,
|
|
2773
2845
|
apiKey: this.config.apiKey,
|
|
2774
2846
|
projectId: this.config.projectId,
|
|
2775
|
-
sessionToken: (e =
|
|
2847
|
+
sessionToken: (e = M(this.config.projectId)) == null ? void 0 : e.token
|
|
2776
2848
|
});
|
|
2777
2849
|
}
|
|
2778
2850
|
/**
|
|
@@ -2782,13 +2854,13 @@ class it {
|
|
|
2782
2854
|
* the results of whichever request happens to return last.
|
|
2783
2855
|
*/
|
|
2784
2856
|
matchKnownIssues(e, { signal: n } = {}) {
|
|
2785
|
-
var
|
|
2786
|
-
return
|
|
2857
|
+
var i;
|
|
2858
|
+
return Cn({
|
|
2787
2859
|
apiBase: this.config.apiBase,
|
|
2788
2860
|
apiKey: this.config.apiKey,
|
|
2789
2861
|
projectId: this.config.projectId,
|
|
2790
2862
|
q: e || "",
|
|
2791
|
-
sessionToken: (
|
|
2863
|
+
sessionToken: (i = M(this.config.projectId)) == null ? void 0 : i.token,
|
|
2792
2864
|
signal: n
|
|
2793
2865
|
});
|
|
2794
2866
|
}
|
|
@@ -2805,21 +2877,21 @@ class it {
|
|
|
2805
2877
|
* me when this is fixed", and there is no way to keep that promise to
|
|
2806
2878
|
* somebody anonymous.
|
|
2807
2879
|
*/
|
|
2808
|
-
async meToo(e, { email: n, name:
|
|
2880
|
+
async meToo(e, { email: n, name: i } = {}) {
|
|
2809
2881
|
var a, s;
|
|
2810
|
-
const r =
|
|
2811
|
-
return
|
|
2882
|
+
const r = M(this.config.projectId), o = await ve();
|
|
2883
|
+
return Sn({
|
|
2812
2884
|
apiBase: this.config.apiBase,
|
|
2813
2885
|
apiKey: this.config.apiKey,
|
|
2814
2886
|
projectId: this.config.projectId,
|
|
2815
2887
|
bugId: e,
|
|
2816
2888
|
reporterEmail: n || ((a = this.config.user) == null ? void 0 : a.email),
|
|
2817
|
-
reporterName:
|
|
2889
|
+
reporterName: i || ((s = this.config.user) == null ? void 0 : s.name),
|
|
2818
2890
|
metadata: {
|
|
2819
|
-
...
|
|
2891
|
+
...o,
|
|
2820
2892
|
user: this.config.user || void 0,
|
|
2821
2893
|
...Object.keys(this.context).length ? { context: this.context } : {},
|
|
2822
|
-
sdk:
|
|
2894
|
+
sdk: D
|
|
2823
2895
|
},
|
|
2824
2896
|
logs: {
|
|
2825
2897
|
console: { entries: this.consoleBuffer.all() },
|
|
@@ -2835,7 +2907,7 @@ class it {
|
|
|
2835
2907
|
context: { ...this.context },
|
|
2836
2908
|
console: this.consoleBuffer.all(),
|
|
2837
2909
|
network: this.networkBuffer.all(),
|
|
2838
|
-
environment:
|
|
2910
|
+
environment: _e()
|
|
2839
2911
|
};
|
|
2840
2912
|
}
|
|
2841
2913
|
clear() {
|
|
@@ -2851,12 +2923,12 @@ class it {
|
|
|
2851
2923
|
}), this.teardown = [], this.notifier = null, this.started = !1;
|
|
2852
2924
|
}
|
|
2853
2925
|
}
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
const
|
|
2857
|
-
if (typeof
|
|
2926
|
+
w = new WeakSet(), /** Call a host callback without letting it break the SDK. */
|
|
2927
|
+
F = function(e, n) {
|
|
2928
|
+
const i = this.config[e];
|
|
2929
|
+
if (typeof i == "function")
|
|
2858
2930
|
try {
|
|
2859
|
-
|
|
2931
|
+
i(n);
|
|
2860
2932
|
} catch (r) {
|
|
2861
2933
|
console.error(`[BugCatch] your ${e} callback threw:`, r);
|
|
2862
2934
|
}
|
|
@@ -2870,14 +2942,14 @@ P = function(e, n) {
|
|
|
2870
2942
|
* version string and four booleans. Every failure is silent — this must
|
|
2871
2943
|
* never cost a page anything but one small request a day.
|
|
2872
2944
|
*/
|
|
2873
|
-
|
|
2945
|
+
ft = function() {
|
|
2874
2946
|
if (typeof window > "u" || typeof fetch != "function") return;
|
|
2875
2947
|
const e = `bugcatch:hello:${this.config.projectId}`, n = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2876
2948
|
try {
|
|
2877
2949
|
if (window.localStorage.getItem(e) === n) return;
|
|
2878
2950
|
} catch {
|
|
2879
2951
|
}
|
|
2880
|
-
const
|
|
2952
|
+
const i = setTimeout(() => {
|
|
2881
2953
|
try {
|
|
2882
2954
|
window.localStorage.setItem(e, n);
|
|
2883
2955
|
} catch {
|
|
@@ -2888,7 +2960,7 @@ rt = function() {
|
|
|
2888
2960
|
headers: { "Content-Type": "application/json", "X-BugCatch-Key": this.config.apiKey },
|
|
2889
2961
|
body: JSON.stringify({
|
|
2890
2962
|
projectId: this.config.projectId,
|
|
2891
|
-
version:
|
|
2963
|
+
version: D.version,
|
|
2892
2964
|
identify: !!this.config.user,
|
|
2893
2965
|
context: !!(this.context && Object.keys(this.context).length),
|
|
2894
2966
|
widget: !!this.config.widget,
|
|
@@ -2898,7 +2970,7 @@ rt = function() {
|
|
|
2898
2970
|
}).catch(() => {
|
|
2899
2971
|
});
|
|
2900
2972
|
}, 5e3);
|
|
2901
|
-
this.teardown.push(() => clearTimeout(
|
|
2973
|
+
this.teardown.push(() => clearTimeout(i));
|
|
2902
2974
|
}, /**
|
|
2903
2975
|
* Redraw the built-in notifications, and tell anyone counting.
|
|
2904
2976
|
*
|
|
@@ -2906,12 +2978,12 @@ rt = function() {
|
|
|
2906
2978
|
* here, so the cards on screen and a host app's own badge cannot disagree
|
|
2907
2979
|
* about what is outstanding.
|
|
2908
2980
|
*/
|
|
2909
|
-
|
|
2910
|
-
const e =
|
|
2981
|
+
R = function() {
|
|
2982
|
+
const e = H();
|
|
2911
2983
|
if (this.emit("unread", { count: e.length, updates: e }), !!this.config.updateToast) {
|
|
2912
2984
|
if (!this.notifier) {
|
|
2913
2985
|
if (!e.length) return;
|
|
2914
|
-
this.notifier =
|
|
2986
|
+
this.notifier = vn({
|
|
2915
2987
|
accent: this.config.accent,
|
|
2916
2988
|
position: this.config.widgetPosition,
|
|
2917
2989
|
onRead: (n) => this.markUpdateRead(n),
|
|
@@ -2938,35 +3010,35 @@ O = function() {
|
|
|
2938
3010
|
* myReport(). The first sighting counts as a change: a host that has just
|
|
2939
3011
|
* opened a report wants to know it is being analysed.
|
|
2940
3012
|
*/
|
|
2941
|
-
|
|
2942
|
-
const
|
|
2943
|
-
if (!e || typeof
|
|
2944
|
-
this.phases.set(e,
|
|
2945
|
-
const r = { bugId: e, phase:
|
|
2946
|
-
this.debugLog("assistant", r), x(this,
|
|
3013
|
+
pt = function(e, n) {
|
|
3014
|
+
const i = n == null ? void 0 : n.phase;
|
|
3015
|
+
if (!e || typeof i != "string" || this.phases.get(e) === i) return;
|
|
3016
|
+
this.phases.set(e, i);
|
|
3017
|
+
const r = { bugId: e, phase: i, title: n.title ?? null, detail: n.detail ?? null };
|
|
3018
|
+
this.debugLog("assistant", r), x(this, w, F).call(this, "onAssistantPhase", r), this.emit("assistant", r);
|
|
2947
3019
|
}, /** A report was accepted: tell the host app, however it was filed. */
|
|
2948
|
-
|
|
3020
|
+
de = function(e, { title: n, via: i }) {
|
|
2949
3021
|
if (!(e != null && e.id)) return;
|
|
2950
|
-
const r = { bugId: e.id, title: n ?? null, via:
|
|
2951
|
-
this.debugLog("report accepted", r), x(this,
|
|
3022
|
+
const r = { bugId: e.id, title: n ?? null, via: i, result: e };
|
|
3023
|
+
this.debugLog("report accepted", r), x(this, w, F).call(this, "onReportSubmitted", r), this.emit("report", r);
|
|
2952
3024
|
}, /** Something done on the page's behalf failed. */
|
|
2953
|
-
|
|
2954
|
-
x(this,
|
|
2955
|
-
},
|
|
2956
|
-
var
|
|
2957
|
-
const l = s ?
|
|
3025
|
+
X = function(e, n) {
|
|
3026
|
+
x(this, w, F).call(this, "onError", { action: e, error: n }), this.emit("error", { action: e, error: n });
|
|
3027
|
+
}, W = async function({ title: e, description: n = "", priority: i = "MEDIUM", metadata: r = {}, media: o = [], references: a = [], context: s = null, issue: c = null }) {
|
|
3028
|
+
var h, f;
|
|
3029
|
+
const l = s ? Le(this.context, s, (d) => this.warn(d.replace("setContext()", "report({ context })"))) : this.context;
|
|
2958
3030
|
return {
|
|
2959
3031
|
projectId: this.config.projectId,
|
|
2960
3032
|
...e ? { title: e } : {},
|
|
2961
3033
|
description: n,
|
|
2962
|
-
priority:
|
|
3034
|
+
priority: i,
|
|
2963
3035
|
url: window.location.href,
|
|
2964
|
-
reporterEmail: (
|
|
3036
|
+
reporterEmail: (h = this.config.user) == null ? void 0 : h.email,
|
|
2965
3037
|
// Sent alongside the address so the dashboard can show a person rather
|
|
2966
3038
|
// than a mailbox, and so the resolution email can open with their name.
|
|
2967
|
-
reporterName: (
|
|
3039
|
+
reporterName: (f = this.config.user) == null ? void 0 : f.name,
|
|
2968
3040
|
metadata: {
|
|
2969
|
-
...await
|
|
3041
|
+
...await ve(),
|
|
2970
3042
|
release: this.config.release,
|
|
2971
3043
|
environment: this.config.environment,
|
|
2972
3044
|
buildId: this.config.buildId,
|
|
@@ -2978,7 +3050,7 @@ H = function(e, n) {
|
|
|
2978
3050
|
// The screen the report came from — setContext(). Its identifiers
|
|
2979
3051
|
// outrank the same kind on `user`.
|
|
2980
3052
|
...Object.keys(l).length ? { context: l } : {},
|
|
2981
|
-
sdk:
|
|
3053
|
+
sdk: D
|
|
2982
3054
|
},
|
|
2983
3055
|
logs: {
|
|
2984
3056
|
console: { entries: this.consoleBuffer.all() },
|
|
@@ -2986,7 +3058,7 @@ H = function(e, n) {
|
|
|
2986
3058
|
},
|
|
2987
3059
|
// Omitted rather than sent empty: the field is optional server-side, and
|
|
2988
3060
|
// an empty array in every payload makes beforeSend hooks harder to read.
|
|
2989
|
-
...
|
|
3061
|
+
...o.length ? { attachments: o } : {},
|
|
2990
3062
|
// What the reporter answered when asked which record this is about. Only
|
|
2991
3063
|
// ever what they typed into the box — never what this browser matched in
|
|
2992
3064
|
// their own text, which the API reads for itself out of the title and
|
|
@@ -3017,22 +3089,22 @@ H = function(e, n) {
|
|
|
3017
3089
|
*
|
|
3018
3090
|
* Returns the payload to send, or false when the host cancelled.
|
|
3019
3091
|
*/
|
|
3020
|
-
|
|
3092
|
+
he = function(e) {
|
|
3021
3093
|
if (typeof this.config.beforeSend != "function") return e;
|
|
3022
3094
|
let n;
|
|
3023
3095
|
try {
|
|
3024
3096
|
n = this.config.beforeSend(e);
|
|
3025
|
-
} catch (
|
|
3026
|
-
return this.warn(`beforeSend threw, so nothing was sent: ${(
|
|
3097
|
+
} catch (i) {
|
|
3098
|
+
return this.warn(`beforeSend threw, so nothing was sent: ${(i == null ? void 0 : i.message) || i}`), !1;
|
|
3027
3099
|
}
|
|
3028
3100
|
return n === !1 ? !1 : n && typeof n == "object" ? n : e;
|
|
3029
|
-
},
|
|
3030
|
-
const e =
|
|
3101
|
+
}, gt = async function() {
|
|
3102
|
+
const e = M(this.config.projectId), n = x(this, w, he).call(this, await x(this, w, W).call(this, {}));
|
|
3031
3103
|
if (n === !1)
|
|
3032
3104
|
return this.debugLog("call cancelled by beforeSend"), { cancelled: !0 };
|
|
3033
|
-
let
|
|
3105
|
+
let i;
|
|
3034
3106
|
try {
|
|
3035
|
-
|
|
3107
|
+
i = await hn({
|
|
3036
3108
|
apiBase: this.config.apiBase,
|
|
3037
3109
|
apiKey: this.config.apiKey,
|
|
3038
3110
|
token: e == null ? void 0 : e.token,
|
|
@@ -3042,32 +3114,32 @@ ae = function(e) {
|
|
|
3042
3114
|
watchToken: E()
|
|
3043
3115
|
});
|
|
3044
3116
|
} catch (r) {
|
|
3045
|
-
throw r.status === 401 && e &&
|
|
3117
|
+
throw r.status === 401 && e && ce(this.config.projectId), x(this, w, X).call(this, "call", r), r;
|
|
3046
3118
|
}
|
|
3047
|
-
return x(this,
|
|
3048
|
-
},
|
|
3049
|
-
const { joinLiveCall: n, liveCallSupported:
|
|
3050
|
-
if (!
|
|
3119
|
+
return x(this, w, de).call(this, i, { title: null, via: "call" }), i.watchToken && (se(i.watchToken), this.config.updates && this.startWatching()), i;
|
|
3120
|
+
}, mt = async function(e) {
|
|
3121
|
+
const { joinLiveCall: n, liveCallSupported: i, openMicrophone: r } = await q(this.config.chunkBase);
|
|
3122
|
+
if (!i())
|
|
3051
3123
|
throw new Error("[BugCatch] this browser cannot make live calls.");
|
|
3052
|
-
const
|
|
3124
|
+
const o = await r();
|
|
3053
3125
|
let a, s = null;
|
|
3054
3126
|
try {
|
|
3055
3127
|
if (e)
|
|
3056
|
-
a = await
|
|
3057
|
-
else if (s = await x(this,
|
|
3128
|
+
a = await fn({ apiBase: this.config.apiBase, bugId: e });
|
|
3129
|
+
else if (s = await x(this, w, gt).call(this), e = s.id, a = s.live_call, !(a != null && a.realtime_url)) {
|
|
3058
3130
|
const l = new Error(`[BugCatch] the report was filed, but the team could not be rung${s.call_error ? `: ${s.call_error}` : "."}`);
|
|
3059
3131
|
throw l.filed = s, l.reason = s.call_error || null, l;
|
|
3060
3132
|
}
|
|
3061
3133
|
} catch (l) {
|
|
3062
|
-
for (const
|
|
3134
|
+
for (const h of o.getTracks()) h.stop();
|
|
3063
3135
|
throw l;
|
|
3064
3136
|
}
|
|
3065
3137
|
const c = await n({
|
|
3066
3138
|
realtimeUrl: a.realtime_url,
|
|
3067
|
-
stream:
|
|
3139
|
+
stream: o,
|
|
3068
3140
|
ringsUntil: a.rings_until,
|
|
3069
|
-
onState: (l,
|
|
3070
|
-
(l === "ended" || l === "failed" || l === "missed") && (this.call = null), l === "missed" &&
|
|
3141
|
+
onState: (l, h) => {
|
|
3142
|
+
(l === "ended" || l === "failed" || l === "missed") && (this.call = null), l === "missed" && pn({ apiBase: this.config.apiBase, bugId: e, callId: a.call_id }), typeof this.config.onCallState == "function" && this.config.onCallState(l, { bugId: e, live: !0, ...h }), this.emit("call", { bugId: e, live: !0, state: l, ...h });
|
|
3071
3143
|
}
|
|
3072
3144
|
});
|
|
3073
3145
|
return this.call = c, Object.assign(c, {
|
|
@@ -3092,27 +3164,27 @@ ae = function(e) {
|
|
|
3092
3164
|
* said `voice: false` has said its customers are not to be rung, and a card
|
|
3093
3165
|
* offering a call this page could not join would be worse than none.
|
|
3094
3166
|
*/
|
|
3095
|
-
|
|
3167
|
+
wt = function(e) {
|
|
3096
3168
|
var r;
|
|
3097
3169
|
const n = e.incomingCall;
|
|
3098
3170
|
if (!this.config.voice || ((r = this.ringing) == null ? void 0 : r.callId) === n.callId || this.call || this.callStarting) return;
|
|
3099
|
-
x(this,
|
|
3100
|
-
const
|
|
3171
|
+
x(this, w, J).call(this);
|
|
3172
|
+
const i = { callId: n.callId, dismiss: () => {
|
|
3101
3173
|
} };
|
|
3102
|
-
this.ringing =
|
|
3103
|
-
if (this.ringing !==
|
|
3174
|
+
this.ringing = i, q(this.config.chunkBase).then(({ liveCallSupported: o, showIncomingCall: a }) => {
|
|
3175
|
+
if (this.ringing !== i || (this.ringing = null, !o()) || this.call || this.callStarting) return;
|
|
3104
3176
|
const s = a({
|
|
3105
3177
|
call: n,
|
|
3106
3178
|
accent: this.config.accent,
|
|
3107
3179
|
position: this.config.widgetPosition,
|
|
3108
3180
|
// Whether the page has been touched, which is when the card may ring
|
|
3109
3181
|
// out loud — tracked since load, which the card's own code cannot be.
|
|
3110
|
-
touched:
|
|
3182
|
+
touched: Ln,
|
|
3111
3183
|
onAnswer: () => {
|
|
3112
|
-
x(this,
|
|
3184
|
+
x(this, w, yt).call(this, e.bugId, n);
|
|
3113
3185
|
},
|
|
3114
3186
|
onDecline: () => {
|
|
3115
|
-
this.ringing = null,
|
|
3187
|
+
this.ringing = null, je({
|
|
3116
3188
|
apiBase: this.config.apiBase,
|
|
3117
3189
|
bugId: e.bugId,
|
|
3118
3190
|
callId: n.callId
|
|
@@ -3133,10 +3205,10 @@ lt = function(e) {
|
|
|
3133
3205
|
}
|
|
3134
3206
|
this.emit("incoming-call", { bugId: e.bugId, callId: n.callId, state: "ringing" });
|
|
3135
3207
|
}, () => {
|
|
3136
|
-
this.ringing ===
|
|
3208
|
+
this.ringing === i && (this.ringing = null);
|
|
3137
3209
|
});
|
|
3138
3210
|
}, /** Take the card away, whatever it is showing. */
|
|
3139
|
-
|
|
3211
|
+
J = function(e) {
|
|
3140
3212
|
if (this.ringing && !(e && this.ringing.callId !== e)) {
|
|
3141
3213
|
try {
|
|
3142
3214
|
this.ringing.dismiss();
|
|
@@ -3144,33 +3216,33 @@ F = function(e) {
|
|
|
3144
3216
|
}
|
|
3145
3217
|
this.ringing = null;
|
|
3146
3218
|
}
|
|
3147
|
-
},
|
|
3219
|
+
}, yt = async function(e, n) {
|
|
3148
3220
|
if (this.ringing = null, this.call || this.callStarting) return;
|
|
3149
3221
|
this.callStarting = !0;
|
|
3150
|
-
let
|
|
3222
|
+
let i, r;
|
|
3151
3223
|
try {
|
|
3152
|
-
const a = await
|
|
3153
|
-
r = a.joinLiveCall,
|
|
3224
|
+
const a = await q(this.config.chunkBase);
|
|
3225
|
+
r = a.joinLiveCall, i = await a.openMicrophone();
|
|
3154
3226
|
} catch (a) {
|
|
3155
|
-
this.callStarting = !1,
|
|
3227
|
+
this.callStarting = !1, je({ apiBase: this.config.apiBase, bugId: e, callId: n.callId }), this.emit("incoming-call", { bugId: e, callId: n.callId, state: "failed", error: a });
|
|
3156
3228
|
return;
|
|
3157
3229
|
}
|
|
3158
|
-
let
|
|
3230
|
+
let o;
|
|
3159
3231
|
try {
|
|
3160
|
-
|
|
3232
|
+
o = await gn({
|
|
3161
3233
|
apiBase: this.config.apiBase,
|
|
3162
3234
|
bugId: e,
|
|
3163
3235
|
callId: n.callId
|
|
3164
3236
|
});
|
|
3165
3237
|
} catch (a) {
|
|
3166
|
-
for (const s of
|
|
3238
|
+
for (const s of i.getTracks()) s.stop();
|
|
3167
3239
|
this.callStarting = !1, this.emit("incoming-call", { bugId: e, callId: n.callId, state: "missed", error: a });
|
|
3168
3240
|
return;
|
|
3169
3241
|
}
|
|
3170
3242
|
try {
|
|
3171
3243
|
const a = await r({
|
|
3172
|
-
realtimeUrl:
|
|
3173
|
-
stream:
|
|
3244
|
+
realtimeUrl: o.realtime_url,
|
|
3245
|
+
stream: i,
|
|
3174
3246
|
// No deadline on this side. The ringing is over — it ended when this
|
|
3175
3247
|
// browser claimed the call — and a countdown here would hang up on a
|
|
3176
3248
|
// conversation that has already started.
|
|
@@ -3180,35 +3252,41 @@ F = function(e) {
|
|
|
3180
3252
|
});
|
|
3181
3253
|
this.call = a, this.emit("incoming-call", { bugId: e, callId: n.callId, state: "answered" });
|
|
3182
3254
|
} catch (a) {
|
|
3183
|
-
for (const s of
|
|
3255
|
+
for (const s of i.getTracks()) s.stop();
|
|
3184
3256
|
this.emit("incoming-call", { bugId: e, callId: n.callId, state: "failed", error: a });
|
|
3185
3257
|
} finally {
|
|
3186
3258
|
this.callStarting = !1;
|
|
3187
3259
|
}
|
|
3188
3260
|
};
|
|
3189
|
-
const
|
|
3190
|
-
|
|
3191
|
-
|
|
3261
|
+
const bt = new ht();
|
|
3262
|
+
bt.Client = ht;
|
|
3263
|
+
bt.version = D.version;
|
|
3192
3264
|
export {
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3265
|
+
bt as B,
|
|
3266
|
+
Je as I,
|
|
3267
|
+
re as P,
|
|
3268
|
+
$e as R,
|
|
3269
|
+
vi as S,
|
|
3270
|
+
Zt as U,
|
|
3271
|
+
Kt as a,
|
|
3272
|
+
gi as b,
|
|
3273
|
+
qe as c,
|
|
3274
|
+
pi as d,
|
|
3275
|
+
mi as e,
|
|
3276
|
+
wi as f,
|
|
3277
|
+
xi as g,
|
|
3278
|
+
bi as h,
|
|
3279
|
+
ze as i,
|
|
3280
|
+
Nt as j,
|
|
3281
|
+
Dt as k,
|
|
3282
|
+
fi as l,
|
|
3283
|
+
Lt as m,
|
|
3284
|
+
ae as n,
|
|
3285
|
+
yi as o,
|
|
3286
|
+
hi as p,
|
|
3287
|
+
Ye as q,
|
|
3288
|
+
ki as r,
|
|
3289
|
+
Rt as s,
|
|
3290
|
+
Pn as v
|
|
3213
3291
|
};
|
|
3214
3292
|
//# sourceMappingURL=bugcatch-core.es.js.map
|