@sphoro/bugcatch-web-sdk 0.14.2 → 0.14.4
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/dist/bugcatch.es.js +1297 -1233
- package/dist/bugcatch.es.js.map +1 -1
- package/dist/bugcatch.umd.js +124 -82
- package/dist/bugcatch.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/widget.js +103 -5
package/dist/bugcatch.es.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
var
|
|
1
|
+
var Yt = (t) => {
|
|
2
2
|
throw TypeError(t);
|
|
3
3
|
};
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
const
|
|
4
|
+
var Fn = (t, e, n) => e.has(t) || Yt("Cannot " + n);
|
|
5
|
+
var Xt = (t, e, n) => e.has(t) ? Yt("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, n);
|
|
6
|
+
var P = (t, e, n) => (Fn(t, e, "access private method"), n);
|
|
7
|
+
const it = "[REDACTED]", Wn = /* @__PURE__ */ new Set([
|
|
8
8
|
"auth",
|
|
9
9
|
"bearer",
|
|
10
10
|
"session",
|
|
@@ -16,7 +16,7 @@ const rt = "[REDACTED]", Pn = /* @__PURE__ */ new Set([
|
|
|
16
16
|
"pwd",
|
|
17
17
|
"sig",
|
|
18
18
|
"codeverifier"
|
|
19
|
-
]),
|
|
19
|
+
]), Yn = [
|
|
20
20
|
"token",
|
|
21
21
|
"secret",
|
|
22
22
|
"password",
|
|
@@ -28,7 +28,7 @@ const rt = "[REDACTED]", Pn = /* @__PURE__ */ new Set([
|
|
|
28
28
|
"privatekey",
|
|
29
29
|
"accesskey",
|
|
30
30
|
"authorization"
|
|
31
|
-
],
|
|
31
|
+
], Xn = /* @__PURE__ */ new Set(["key", "code", "state", "nonce", "salt", "hash"]), fn = [
|
|
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 rt = "[REDACTED]", Pn = /* @__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
|
+
], Zn = /\bBearer\s+[\w.~+/=-]{8,}/gi, Jn = /^([A-Za-z][A-Za-z0-9+.-]*:\/\/)([^/?#@]+)@/;
|
|
55
|
+
function gn(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 Gn(t) {
|
|
63
|
+
return gn(t).toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
64
64
|
}
|
|
65
|
-
function
|
|
66
|
-
return t.length >= 20 ? !0 :
|
|
65
|
+
function ea(t) {
|
|
66
|
+
return t.length >= 20 ? !0 : fn.some((e) => (e.lastIndex = 0, e.test(t)));
|
|
67
67
|
}
|
|
68
|
-
function
|
|
69
|
-
const n =
|
|
68
|
+
function ta(t, e) {
|
|
69
|
+
const n = Gn(t);
|
|
70
70
|
if (!n) return !1;
|
|
71
|
-
if (
|
|
72
|
-
for (const
|
|
73
|
-
return
|
|
71
|
+
if (Wn.has(n)) return !0;
|
|
72
|
+
for (const a of Yn) if (n.includes(a)) return !0;
|
|
73
|
+
return Xn.has(n) ? ea(gn(e)) : !1;
|
|
74
74
|
}
|
|
75
|
-
function
|
|
75
|
+
function wt(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 i &&
|
|
79
|
+
const a = e.slice(0, n), i = e.slice(n + 1);
|
|
80
|
+
return i && ta(a, i) ? `${a}=${it}` : e;
|
|
81
81
|
}).join("&");
|
|
82
82
|
}
|
|
83
|
-
function
|
|
83
|
+
function mn(t) {
|
|
84
84
|
let e = t;
|
|
85
|
-
for (const n of
|
|
86
|
-
n.lastIndex = 0, e = e.replace(n,
|
|
85
|
+
for (const n of fn)
|
|
86
|
+
n.lastIndex = 0, e = e.replace(n, it);
|
|
87
87
|
return e;
|
|
88
88
|
}
|
|
89
|
-
function
|
|
89
|
+
function bn(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(Jn, `$1${it}@`);
|
|
94
94
|
const n = e.indexOf("#");
|
|
95
|
-
let
|
|
96
|
-
const r =
|
|
97
|
-
if (r !== -1 && (
|
|
95
|
+
let a = n === -1 ? e : e.slice(0, n), i = n === -1 ? "" : e.slice(n);
|
|
96
|
+
const r = a.indexOf("?");
|
|
97
|
+
if (r !== -1 && (a = a.slice(0, r + 1) + wt(a.slice(r + 1))), i.length > 1) {
|
|
98
98
|
const s = i.slice(1), l = s.indexOf("?");
|
|
99
|
-
l !== -1 ? i = `#${s.slice(0, l + 1)}${
|
|
99
|
+
l !== -1 ? i = `#${s.slice(0, l + 1)}${wt(s.slice(l + 1))}` : s.includes("=") && (i = `#${wt(s)}`);
|
|
100
100
|
}
|
|
101
|
-
return
|
|
101
|
+
return mn(a + i);
|
|
102
102
|
}
|
|
103
|
-
function
|
|
103
|
+
function na(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) => bn(n)), e = e.replace(Zn, `Bearer ${it}`), mn(e));
|
|
107
107
|
}
|
|
108
|
-
function
|
|
108
|
+
function We(t) {
|
|
109
109
|
const e = [];
|
|
110
110
|
return {
|
|
111
111
|
push(n) {
|
|
@@ -120,41 +120,41 @@ function Fe(t) {
|
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
const
|
|
124
|
-
function
|
|
123
|
+
const Zt = ["log", "info", "warn", "error", "debug"];
|
|
124
|
+
function aa(t, { levels: e = ["warn", "error", "log", "info"] } = {}) {
|
|
125
125
|
const n = {};
|
|
126
|
-
for (const
|
|
127
|
-
n[
|
|
126
|
+
for (const a of Zt)
|
|
127
|
+
n[a] = console[a], e.includes(a) && (console[a] = (...i) => {
|
|
128
128
|
try {
|
|
129
129
|
t.push({
|
|
130
|
-
level:
|
|
131
|
-
text: i.map(
|
|
130
|
+
level: a,
|
|
131
|
+
text: i.map(wn).join(" ").slice(0, 2e3),
|
|
132
132
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
133
133
|
});
|
|
134
134
|
} catch {
|
|
135
135
|
}
|
|
136
|
-
n[
|
|
136
|
+
n[a].apply(console, i);
|
|
137
137
|
});
|
|
138
138
|
return () => {
|
|
139
|
-
for (const
|
|
139
|
+
for (const a of Zt) console[a] = n[a];
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
|
-
function
|
|
143
|
-
const n = window.fetch,
|
|
142
|
+
function oa(t, { slowMs: e = 2e3 } = {}) {
|
|
143
|
+
const n = window.fetch, a = XMLHttpRequest.prototype.open, i = XMLHttpRequest.prototype.send;
|
|
144
144
|
return n && (window.fetch = async function(...s) {
|
|
145
|
-
var
|
|
146
|
-
const l = performance.now(),
|
|
145
|
+
var y, h, b;
|
|
146
|
+
const l = performance.now(), p = typeof s[0] == "string" ? s[0] : (y = s[0]) == null ? void 0 : y.url, f = ((h = s[1]) == null ? void 0 : h.method) || (typeof s[0] == "object" ? (b = s[0]) == null ? void 0 : b.method : "GET") || "GET";
|
|
147
147
|
try {
|
|
148
|
-
const
|
|
149
|
-
return
|
|
150
|
-
} catch (
|
|
151
|
-
throw
|
|
148
|
+
const g = await n.apply(this, s);
|
|
149
|
+
return vt(t, { url: p, method: f, status: g.status, ms: Math.round(performance.now() - l), slowMs: e }), g;
|
|
150
|
+
} catch (g) {
|
|
151
|
+
throw vt(t, { url: p, method: f, status: 0, error: String((g == null ? void 0 : g.message) || g), ms: Math.round(performance.now() - l), slowMs: e }), g;
|
|
152
152
|
}
|
|
153
|
-
}), XMLHttpRequest.prototype.open = function(s, l, ...
|
|
154
|
-
return this.__bc = { method: s, url: l, started: 0 },
|
|
153
|
+
}), XMLHttpRequest.prototype.open = function(s, l, ...p) {
|
|
154
|
+
return this.__bc = { method: s, url: l, started: 0 }, a.call(this, s, l, ...p);
|
|
155
155
|
}, XMLHttpRequest.prototype.send = function(...s) {
|
|
156
156
|
return this.__bc && (this.__bc.started = performance.now(), this.addEventListener("loadend", () => {
|
|
157
|
-
|
|
157
|
+
vt(t, {
|
|
158
158
|
url: this.__bc.url,
|
|
159
159
|
method: this.__bc.method,
|
|
160
160
|
status: this.status,
|
|
@@ -163,10 +163,10 @@ function to(t, { slowMs: e = 2e3 } = {}) {
|
|
|
163
163
|
});
|
|
164
164
|
})), i.apply(this, s);
|
|
165
165
|
}, () => {
|
|
166
|
-
n && (window.fetch = n), XMLHttpRequest.prototype.open =
|
|
166
|
+
n && (window.fetch = n), XMLHttpRequest.prototype.open = a, XMLHttpRequest.prototype.send = i;
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
|
-
function
|
|
169
|
+
function vt(t, { url: e, method: n, status: a, ms: i, error: r, slowMs: s }) {
|
|
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 wt(t, { url: e, method: n, status: o, ms: i, error: r, slowMs: s }) {
|
|
|
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: bn(String(e)).slice(0, 500),
|
|
179
179
|
method: n,
|
|
180
|
-
status:
|
|
180
|
+
status: a,
|
|
181
181
|
ms: i,
|
|
182
|
-
error: r === void 0 ? void 0 :
|
|
182
|
+
error: r === void 0 ? void 0 : na(r),
|
|
183
183
|
// Flagged so triage can spot the interesting rows without reading everything.
|
|
184
|
-
failed:
|
|
184
|
+
failed: a === 0 || a >= 400,
|
|
185
185
|
slow: i >= s,
|
|
186
186
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
187
187
|
});
|
|
188
188
|
} catch {
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
|
-
function
|
|
192
|
-
const e = (
|
|
193
|
-
const i = String(
|
|
191
|
+
function ra(t) {
|
|
192
|
+
const e = (a) => {
|
|
193
|
+
const i = String(a.message || "Error"), r = a.filename ? ` (${a.filename}:${a.lineno}:${a.colno})` : "";
|
|
194
194
|
t.push({
|
|
195
195
|
level: "error",
|
|
196
196
|
text: (/^uncaught/i.test(i) ? i : `Uncaught ${i}`) + r,
|
|
197
197
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
198
198
|
});
|
|
199
|
-
}, n = (
|
|
199
|
+
}, n = (a) => {
|
|
200
200
|
t.push({
|
|
201
201
|
level: "error",
|
|
202
|
-
text: `Unhandled rejection: ${
|
|
202
|
+
text: `Unhandled rejection: ${wn(a.reason)}`,
|
|
203
203
|
at: (/* @__PURE__ */ new Date()).toISOString()
|
|
204
204
|
});
|
|
205
205
|
};
|
|
@@ -207,8 +207,8 @@ function no(t) {
|
|
|
207
207
|
window.removeEventListener("error", e), window.removeEventListener("unhandledrejection", n);
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
|
-
async function
|
|
211
|
-
const t =
|
|
210
|
+
async function Jt() {
|
|
211
|
+
const t = yn();
|
|
212
212
|
try {
|
|
213
213
|
if (navigator.getBattery) {
|
|
214
214
|
const e = await navigator.getBattery();
|
|
@@ -218,8 +218,8 @@ async function Yt() {
|
|
|
218
218
|
}
|
|
219
219
|
return t;
|
|
220
220
|
}
|
|
221
|
-
function
|
|
222
|
-
var e, n,
|
|
221
|
+
function yn() {
|
|
222
|
+
var e, n, a, i, r, s, l, p, f;
|
|
223
223
|
const t = window.navigator || {};
|
|
224
224
|
return {
|
|
225
225
|
userAgent: t.userAgent,
|
|
@@ -233,7 +233,7 @@ function gn() {
|
|
|
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: (a = window.screen) == null ? void 0 : a.availWidth,
|
|
237
237
|
availHeight: (i = window.screen) == null ? void 0 : i.availHeight,
|
|
238
238
|
colorDepth: (r = window.screen) == null ? void 0 : r.colorDepth,
|
|
239
239
|
orientation: ((l = (s = window.screen) == null ? void 0 : s.orientation) == null ? void 0 : l.type) || null
|
|
@@ -256,11 +256,11 @@ function gn() {
|
|
|
256
256
|
rtt: t.connection.rtt,
|
|
257
257
|
saveData: t.connection.saveData
|
|
258
258
|
} : null,
|
|
259
|
-
prefersColorScheme: (
|
|
260
|
-
prefersReducedMotion: ((
|
|
259
|
+
prefersColorScheme: (p = window.matchMedia) != null && p.call(window, "(prefers-color-scheme: dark)").matches ? "dark" : "light",
|
|
260
|
+
prefersReducedMotion: ((f = window.matchMedia) == null ? void 0 : f.call(window, "(prefers-reduced-motion: reduce)").matches) || !1
|
|
261
261
|
};
|
|
262
262
|
}
|
|
263
|
-
function
|
|
263
|
+
function wn(t) {
|
|
264
264
|
if (typeof t == "string") return t;
|
|
265
265
|
if (t instanceof Error) return `${t.name}: ${t.message}`;
|
|
266
266
|
try {
|
|
@@ -269,7 +269,7 @@ function mn(t) {
|
|
|
269
269
|
return String(t);
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
-
const
|
|
272
|
+
const ia = typeof window < "u" && window.fetch ? window.fetch.bind(window) : null, sa = typeof XMLHttpRequest < "u" ? XMLHttpRequest.prototype.open : null, ca = typeof XMLHttpRequest < "u" ? XMLHttpRequest.prototype.send : null, vn = [
|
|
273
273
|
"image/png",
|
|
274
274
|
"image/jpeg",
|
|
275
275
|
"image/webp",
|
|
@@ -290,27 +290,27 @@ const oo = typeof window < "u" && window.fetch ? window.fetch.bind(window) : nul
|
|
|
290
290
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
291
291
|
"application/vnd.ms-excel",
|
|
292
292
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
293
|
-
],
|
|
293
|
+
], tt = [
|
|
294
294
|
"image/png",
|
|
295
295
|
"image/jpeg",
|
|
296
296
|
"image/webp",
|
|
297
297
|
"video/webm",
|
|
298
298
|
"video/mp4"
|
|
299
|
-
],
|
|
299
|
+
], la = () => {
|
|
300
300
|
var t;
|
|
301
301
|
return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getUserMedia && typeof MediaRecorder < "u");
|
|
302
|
-
},
|
|
302
|
+
}, da = () => {
|
|
303
303
|
var t;
|
|
304
304
|
return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getDisplayMedia && typeof MediaRecorder < "u");
|
|
305
|
-
},
|
|
305
|
+
}, ua = () => {
|
|
306
306
|
var t;
|
|
307
307
|
return !!((t = navigator == null ? void 0 : navigator.mediaDevices) != null && t.getDisplayMedia);
|
|
308
308
|
};
|
|
309
|
-
function
|
|
309
|
+
function nt(t, e = vn) {
|
|
310
310
|
const n = String(t || "").split(";")[0].trim().toLowerCase();
|
|
311
311
|
return e.includes(n) ? n : null;
|
|
312
312
|
}
|
|
313
|
-
async function
|
|
313
|
+
async function pa() {
|
|
314
314
|
const t = await navigator.mediaDevices.getDisplayMedia({
|
|
315
315
|
video: { frameRate: 1 },
|
|
316
316
|
audio: !1
|
|
@@ -318,8 +318,8 @@ async function lo() {
|
|
|
318
318
|
try {
|
|
319
319
|
const e = t.getVideoTracks()[0], n = document.createElement("video");
|
|
320
320
|
n.srcObject = t, n.muted = !0, n.playsInline = !0, await n.play(), await new Promise((l) => requestAnimationFrame(() => requestAnimationFrame(l)));
|
|
321
|
-
const { width:
|
|
322
|
-
r.width =
|
|
321
|
+
const { width: a, height: i } = e.getSettings(), r = document.createElement("canvas");
|
|
322
|
+
r.width = a || n.videoWidth, r.height = i || n.videoHeight, r.getContext("2d").drawImage(n, 0, 0, r.width, r.height);
|
|
323
323
|
const s = await new Promise((l) => r.toBlob(l, "image/png"));
|
|
324
324
|
if (!s) throw new Error("The browser returned an empty screenshot.");
|
|
325
325
|
return { blob: s, mime: "image/png", kind: "SCREENSHOT" };
|
|
@@ -327,46 +327,46 @@ async function lo() {
|
|
|
327
327
|
t.getTracks().forEach((e) => e.stop());
|
|
328
328
|
}
|
|
329
329
|
}
|
|
330
|
-
async function
|
|
331
|
-
const
|
|
330
|
+
async function ha({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
|
|
331
|
+
const a = await navigator.mediaDevices.getDisplayMedia({
|
|
332
332
|
video: { frameRate: 15 },
|
|
333
333
|
audio: !1
|
|
334
|
-
}), i = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"].find((
|
|
335
|
-
r.ondataavailable = (
|
|
336
|
-
|
|
334
|
+
}), i = ["video/webm;codecs=vp9", "video/webm;codecs=vp8", "video/webm"].find((g) => MediaRecorder.isTypeSupported(g)) || "video/webm", r = new MediaRecorder(a, { mimeType: i, videoBitsPerSecond: 25e5 }), s = [];
|
|
335
|
+
r.ondataavailable = (g) => {
|
|
336
|
+
g.data.size && s.push(g.data);
|
|
337
337
|
}, r.start(1e3);
|
|
338
|
-
const l = Date.now(),
|
|
339
|
-
clearInterval(
|
|
340
|
-
},
|
|
338
|
+
const l = Date.now(), p = setInterval(() => e == null ? void 0 : e(Math.floor((Date.now() - l) / 1e3)), 500), f = () => {
|
|
339
|
+
clearInterval(p), clearTimeout(b), a.getTracks().forEach((g) => g.stop());
|
|
340
|
+
}, y = new Promise((g) => {
|
|
341
341
|
r.onstop = () => {
|
|
342
|
-
|
|
342
|
+
f(), g(new Blob(s, { type: i }));
|
|
343
343
|
};
|
|
344
|
-
}),
|
|
344
|
+
}), h = () => {
|
|
345
345
|
r.state !== "inactive" && r.stop(), n == null || n();
|
|
346
346
|
};
|
|
347
|
-
|
|
348
|
-
const b = setTimeout(
|
|
347
|
+
a.getVideoTracks()[0].addEventListener("ended", h);
|
|
348
|
+
const b = setTimeout(h, t);
|
|
349
349
|
return {
|
|
350
350
|
mime: i,
|
|
351
351
|
maxMs: t,
|
|
352
352
|
async stop() {
|
|
353
|
-
return clearTimeout(b), r.state !== "inactive" && r.stop(), { blob: await
|
|
353
|
+
return clearTimeout(b), r.state !== "inactive" && r.stop(), { blob: await y, mime: i, kind: "VIDEO" };
|
|
354
354
|
},
|
|
355
355
|
cancel() {
|
|
356
|
-
|
|
356
|
+
f(), r.state !== "inactive" && r.stop();
|
|
357
357
|
}
|
|
358
358
|
};
|
|
359
359
|
}
|
|
360
|
-
async function
|
|
361
|
-
const
|
|
362
|
-
r.ondataavailable = (
|
|
363
|
-
|
|
360
|
+
async function fa({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
|
|
361
|
+
const a = await navigator.mediaDevices.getUserMedia({ audio: !0 }), i = ["audio/webm;codecs=opus", "audio/webm", "audio/mp4", "audio/ogg"].find((g) => MediaRecorder.isTypeSupported(g)) || "", r = new MediaRecorder(a, i ? { mimeType: i } : void 0), s = [];
|
|
362
|
+
r.ondataavailable = (g) => {
|
|
363
|
+
g.data.size && s.push(g.data);
|
|
364
364
|
}, r.start(1e3);
|
|
365
|
-
const l = Date.now(),
|
|
366
|
-
clearInterval(
|
|
367
|
-
},
|
|
365
|
+
const l = Date.now(), p = setInterval(() => e == null ? void 0 : e(Math.floor((Date.now() - l) / 1e3)), 500), f = () => {
|
|
366
|
+
clearInterval(p), clearTimeout(b), a.getTracks().forEach((g) => g.stop());
|
|
367
|
+
}, y = new Promise((g) => {
|
|
368
368
|
r.onstop = () => {
|
|
369
|
-
|
|
369
|
+
f(), g(new Blob(s, { type: r.mimeType || i }));
|
|
370
370
|
};
|
|
371
371
|
}), b = setTimeout(() => {
|
|
372
372
|
r.state !== "inactive" && r.stop(), n == null || n();
|
|
@@ -376,110 +376,110 @@ async function po({ maxMs: t = 12e4, onTick: e, onAutoStop: n } = {}) {
|
|
|
376
376
|
maxMs: t,
|
|
377
377
|
async stop() {
|
|
378
378
|
clearTimeout(b), r.state !== "inactive" && r.stop();
|
|
379
|
-
const
|
|
380
|
-
return { blob:
|
|
379
|
+
const g = await y;
|
|
380
|
+
return { blob: g, mime: g.type || r.mimeType || i, kind: "AUDIO" };
|
|
381
381
|
},
|
|
382
382
|
cancel() {
|
|
383
|
-
|
|
383
|
+
f(), r.state !== "inactive" && r.stop();
|
|
384
384
|
}
|
|
385
385
|
};
|
|
386
386
|
}
|
|
387
|
-
async function
|
|
388
|
-
const r =
|
|
387
|
+
async function ga({ apiBase: t, apiKey: e, blob: n, mime: a, onProgress: i }) {
|
|
388
|
+
const r = nt(a || n.type);
|
|
389
389
|
if (!r)
|
|
390
|
-
throw new Error(`[BugCatch] ${
|
|
391
|
-
const s = await
|
|
390
|
+
throw new Error(`[BugCatch] ${a || n.type || "that file"} can't be attached.`);
|
|
391
|
+
const s = await ia(`${t}/ingest/presign`, {
|
|
392
392
|
method: "POST",
|
|
393
393
|
headers: { "Content-Type": "application/json", "X-BugCatch-Key": e },
|
|
394
394
|
body: JSON.stringify({ mime: r })
|
|
395
395
|
});
|
|
396
396
|
if (!s.ok) throw new Error(`[BugCatch] could not start the upload (HTTP ${s.status}).`);
|
|
397
|
-
const { key: l, uploadUrl:
|
|
398
|
-
return await
|
|
397
|
+
const { key: l, uploadUrl: p } = await s.json();
|
|
398
|
+
return await ma(p, n, r, i), { storageKey: l, mime: r };
|
|
399
399
|
}
|
|
400
|
-
function
|
|
400
|
+
function ma(t, e, n, a) {
|
|
401
401
|
return new Promise((i, r) => {
|
|
402
402
|
const s = new XMLHttpRequest();
|
|
403
|
-
|
|
404
|
-
l.lengthComputable && (
|
|
403
|
+
sa.call(s, "PUT", t, !0), s.setRequestHeader("Content-Type", n), s.upload.onprogress = (l) => {
|
|
404
|
+
l.lengthComputable && (a == null || a(l.loaded / l.total));
|
|
405
405
|
}, s.onload = () => {
|
|
406
406
|
s.status >= 200 && s.status < 300 ? i() : r(new Error(`[BugCatch] upload failed (HTTP ${s.status}).`));
|
|
407
407
|
}, s.onerror = () => r(new Error(
|
|
408
408
|
"[BugCatch] the browser blocked the upload to storage. If this is a new environment, the media bucket is probably missing its CORS policy."
|
|
409
|
-
)), s.onabort = () => r(new Error("[BugCatch] upload cancelled.")),
|
|
409
|
+
)), s.onabort = () => r(new Error("[BugCatch] upload cancelled.")), ca.call(s, e);
|
|
410
410
|
});
|
|
411
411
|
}
|
|
412
412
|
function je(t) {
|
|
413
413
|
return t < 1024 ? `${t} B` : t < 1024 * 1024 ? `${(t / 1024).toFixed(0)} KB` : `${(t / 1024 / 1024).toFixed(1)} MB`;
|
|
414
414
|
}
|
|
415
|
-
function
|
|
415
|
+
function Ye(t) {
|
|
416
416
|
const e = Math.floor(t / 60), n = t % 60;
|
|
417
417
|
return `${e}:${String(n).padStart(2, "0")}`;
|
|
418
418
|
}
|
|
419
|
-
const
|
|
420
|
-
let
|
|
421
|
-
function
|
|
422
|
-
return
|
|
419
|
+
const ba = 7 * 24 * 60 * 60 * 1e3;
|
|
420
|
+
let Xe;
|
|
421
|
+
function ya() {
|
|
422
|
+
return Xe || (Xe = new Promise((t, e) => {
|
|
423
423
|
const n = indexedDB.open("bugcatch-drafts", 1);
|
|
424
424
|
n.onupgradeneeded = () => n.result.createObjectStore("drafts"), n.onsuccess = () => t(n.result), n.onerror = () => e(n.error), n.onblocked = () => e(new Error("Draft storage is blocked."));
|
|
425
425
|
}).catch((t) => {
|
|
426
|
-
throw
|
|
427
|
-
})),
|
|
426
|
+
throw Xe = null, t;
|
|
427
|
+
})), Xe;
|
|
428
428
|
}
|
|
429
|
-
function
|
|
430
|
-
var n,
|
|
431
|
-
return JSON.stringify([t.apiBase, t.projectId, e || ((n = t.user) == null ? void 0 : n.email) || ((
|
|
429
|
+
function wa(t, e) {
|
|
430
|
+
var n, a;
|
|
431
|
+
return JSON.stringify([t.apiBase, t.projectId, e || ((n = t.user) == null ? void 0 : n.email) || ((a = t.user) == null ? void 0 : a.id) || "anonymous"]);
|
|
432
432
|
}
|
|
433
|
-
async function
|
|
434
|
-
const n = await
|
|
435
|
-
return new Promise((
|
|
433
|
+
async function at(t, e) {
|
|
434
|
+
const n = await ya();
|
|
435
|
+
return new Promise((a, i) => {
|
|
436
436
|
const r = n.transaction("drafts", e === void 0 ? "readonly" : "readwrite"), s = r.objectStore("drafts"), l = e === void 0 ? s.get(t) : e === null ? s.delete(t) : s.put({ ...e, savedAt: Date.now() }, t);
|
|
437
|
-
r.oncomplete = () =>
|
|
437
|
+
r.oncomplete = () => a(l.result), r.onerror = () => i(r.error), r.onabort = () => i(r.error || new Error("Draft was not saved."));
|
|
438
438
|
});
|
|
439
439
|
}
|
|
440
|
-
async function
|
|
441
|
-
const e = await
|
|
442
|
-
return e && Date.now() - e.savedAt >
|
|
440
|
+
async function va(t) {
|
|
441
|
+
const e = await at(t);
|
|
442
|
+
return e && Date.now() - e.savedAt > ba ? (await at(t, null), null) : e || null;
|
|
443
443
|
}
|
|
444
|
-
const
|
|
445
|
-
function
|
|
444
|
+
const xa = "bugcatch.session.", Tt = (t) => `${xa}${t}`, It = /* @__PURE__ */ new Map();
|
|
445
|
+
function he(t) {
|
|
446
446
|
var e;
|
|
447
447
|
if (!t) return null;
|
|
448
448
|
try {
|
|
449
|
-
const n = (e = window.localStorage) == null ? void 0 : e.getItem(
|
|
449
|
+
const n = (e = window.localStorage) == null ? void 0 : e.getItem(Tt(t));
|
|
450
450
|
if (n) {
|
|
451
|
-
const
|
|
452
|
-
if (
|
|
451
|
+
const a = JSON.parse(n);
|
|
452
|
+
if (a != null && a.token) return a;
|
|
453
453
|
}
|
|
454
454
|
} catch {
|
|
455
455
|
}
|
|
456
|
-
return
|
|
456
|
+
return It.get(t) || null;
|
|
457
457
|
}
|
|
458
|
-
function
|
|
459
|
-
var
|
|
458
|
+
function ka(t, e) {
|
|
459
|
+
var a;
|
|
460
460
|
if (!t || !(e != null && e.token)) return;
|
|
461
461
|
const n = {
|
|
462
462
|
token: e.token,
|
|
463
463
|
email: e.email || null,
|
|
464
464
|
name: e.name || null
|
|
465
465
|
};
|
|
466
|
-
|
|
466
|
+
It.set(t, n);
|
|
467
467
|
try {
|
|
468
|
-
(
|
|
468
|
+
(a = window.localStorage) == null || a.setItem(Tt(t), JSON.stringify(n));
|
|
469
469
|
} catch {
|
|
470
470
|
}
|
|
471
471
|
}
|
|
472
|
-
function
|
|
472
|
+
function St(t) {
|
|
473
473
|
var e;
|
|
474
474
|
if (t) {
|
|
475
|
-
|
|
475
|
+
It.delete(t);
|
|
476
476
|
try {
|
|
477
|
-
(e = window.localStorage) == null || e.removeItem(
|
|
477
|
+
(e = window.localStorage) == null || e.removeItem(Tt(t));
|
|
478
478
|
} catch {
|
|
479
479
|
}
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
|
-
function
|
|
482
|
+
function st({ apiKey: t, token: e }) {
|
|
483
483
|
return {
|
|
484
484
|
"Content-Type": "application/json",
|
|
485
485
|
"X-BugCatch-Key": t,
|
|
@@ -489,7 +489,7 @@ function it({ apiKey: t, token: e }) {
|
|
|
489
489
|
...e ? { "X-BugCatch-Session": e } : {}
|
|
490
490
|
};
|
|
491
491
|
}
|
|
492
|
-
async function
|
|
492
|
+
async function xn(t) {
|
|
493
493
|
try {
|
|
494
494
|
const e = await t.json(), n = Array.isArray(e.message) ? e.message.join(", ") : e.message;
|
|
495
495
|
if (n) return n;
|
|
@@ -497,12 +497,12 @@ async function wn(t) {
|
|
|
497
497
|
}
|
|
498
498
|
return `Request failed (HTTP ${t.status})`;
|
|
499
499
|
}
|
|
500
|
-
async function
|
|
500
|
+
async function Sa({ apiBase: t, apiKey: e, projectId: n, token: a }) {
|
|
501
501
|
const i = { mode: "off", signedIn: null, signedOutReason: null };
|
|
502
502
|
try {
|
|
503
503
|
const r = await fetch(
|
|
504
504
|
`${t}/ingest/login?projectId=${encodeURIComponent(n)}`,
|
|
505
|
-
{ headers:
|
|
505
|
+
{ headers: st({ apiKey: e, token: a }) }
|
|
506
506
|
);
|
|
507
507
|
if (!r.ok) return i;
|
|
508
508
|
const s = await r.json();
|
|
@@ -515,104 +515,104 @@ async function xo({ apiBase: t, apiKey: e, projectId: n, token: o }) {
|
|
|
515
515
|
return i;
|
|
516
516
|
}
|
|
517
517
|
}
|
|
518
|
-
async function
|
|
518
|
+
async function Ca({ apiBase: t, apiKey: e, projectId: n, email: a, name: i }) {
|
|
519
519
|
const r = await fetch(`${t}/ingest/login/start`, {
|
|
520
520
|
method: "POST",
|
|
521
|
-
headers:
|
|
522
|
-
body: JSON.stringify({ projectId: n, email:
|
|
521
|
+
headers: st({ apiKey: e }),
|
|
522
|
+
body: JSON.stringify({ projectId: n, email: a, ...i ? { name: i } : {} })
|
|
523
523
|
});
|
|
524
|
-
if (!r.ok) throw new Error(await
|
|
524
|
+
if (!r.ok) throw new Error(await xn(r));
|
|
525
525
|
return r.json();
|
|
526
526
|
}
|
|
527
|
-
async function
|
|
527
|
+
async function $a({ apiBase: t, apiKey: e, projectId: n, email: a, code: i }) {
|
|
528
528
|
const r = await fetch(`${t}/ingest/login`, {
|
|
529
529
|
method: "POST",
|
|
530
|
-
headers:
|
|
531
|
-
body: JSON.stringify({ projectId: n, email:
|
|
530
|
+
headers: st({ apiKey: e }),
|
|
531
|
+
body: JSON.stringify({ projectId: n, email: a, code: i })
|
|
532
532
|
});
|
|
533
|
-
if (!r.ok) throw new Error(await
|
|
533
|
+
if (!r.ok) throw new Error(await xn(r));
|
|
534
534
|
const s = await r.json(), l = { token: s.sessionToken, email: s.email, name: s.name };
|
|
535
|
-
return
|
|
535
|
+
return ka(n, l), l;
|
|
536
536
|
}
|
|
537
|
-
async function
|
|
538
|
-
if (
|
|
537
|
+
async function Ea({ apiBase: t, apiKey: e, projectId: n, token: a }) {
|
|
538
|
+
if (St(n), !a) return { signedOut: !0 };
|
|
539
539
|
try {
|
|
540
540
|
await fetch(`${t}/ingest/logout`, {
|
|
541
541
|
method: "POST",
|
|
542
|
-
headers:
|
|
542
|
+
headers: st({ apiKey: e, token: a }),
|
|
543
543
|
body: JSON.stringify({ projectId: n })
|
|
544
544
|
});
|
|
545
545
|
} catch {
|
|
546
546
|
}
|
|
547
547
|
return { signedOut: !0 };
|
|
548
548
|
}
|
|
549
|
-
const
|
|
549
|
+
const Mt = "bugcatch.watch", Gt = [2e3, 5e3, 15e3, 3e4, 6e4], Ta = 5e3;
|
|
550
550
|
function se() {
|
|
551
551
|
var t;
|
|
552
552
|
try {
|
|
553
|
-
return ((t = window.localStorage) == null ? void 0 : t.getItem(
|
|
553
|
+
return ((t = window.localStorage) == null ? void 0 : t.getItem(Mt)) || null;
|
|
554
554
|
} catch {
|
|
555
555
|
return null;
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
|
-
function
|
|
558
|
+
function Ct(t) {
|
|
559
559
|
var e;
|
|
560
560
|
if (t)
|
|
561
561
|
try {
|
|
562
|
-
(e = window.localStorage) == null || e.setItem(
|
|
562
|
+
(e = window.localStorage) == null || e.setItem(Mt, t);
|
|
563
563
|
} catch {
|
|
564
564
|
}
|
|
565
565
|
}
|
|
566
|
-
function
|
|
566
|
+
function $e() {
|
|
567
567
|
var t;
|
|
568
568
|
try {
|
|
569
|
-
(t = window.localStorage) == null || t.removeItem(
|
|
569
|
+
(t = window.localStorage) == null || t.removeItem(Mt);
|
|
570
570
|
} catch {
|
|
571
571
|
}
|
|
572
|
-
|
|
572
|
+
kn();
|
|
573
573
|
}
|
|
574
574
|
const ot = "bugcatch.unread";
|
|
575
|
-
function
|
|
575
|
+
function Ia(t) {
|
|
576
576
|
return [(t == null ? void 0 : t.bugId) || "report", (t == null ? void 0 : t.kind) || "status", (t == null ? void 0 : t.at) || ""].join("|");
|
|
577
577
|
}
|
|
578
578
|
function Ne() {
|
|
579
579
|
var t;
|
|
580
580
|
try {
|
|
581
581
|
const e = (t = window.localStorage) == null ? void 0 : t.getItem(ot), n = e ? JSON.parse(e) : [];
|
|
582
|
-
return Array.isArray(n) ? n.filter((
|
|
582
|
+
return Array.isArray(n) ? n.filter((a) => a && typeof a.id == "string") : [];
|
|
583
583
|
} catch {
|
|
584
584
|
return [];
|
|
585
585
|
}
|
|
586
586
|
}
|
|
587
|
-
function
|
|
587
|
+
function ct(t) {
|
|
588
588
|
var e, n;
|
|
589
589
|
try {
|
|
590
590
|
t.length ? (e = window.localStorage) == null || e.setItem(ot, JSON.stringify(t)) : (n = window.localStorage) == null || n.removeItem(ot);
|
|
591
591
|
} catch {
|
|
592
592
|
}
|
|
593
593
|
}
|
|
594
|
-
function
|
|
595
|
-
const e = { ...t, id:
|
|
596
|
-
return n.push(e),
|
|
594
|
+
function Ma(t) {
|
|
595
|
+
const e = { ...t, id: Ia(t) }, n = Ne().filter((a) => a.id !== e.id);
|
|
596
|
+
return n.push(e), ct(n.slice(-20)), e;
|
|
597
597
|
}
|
|
598
|
-
function
|
|
598
|
+
function La(t) {
|
|
599
599
|
const e = Ne().filter((n) => n.id !== t);
|
|
600
|
-
return
|
|
600
|
+
return ct(e), e;
|
|
601
601
|
}
|
|
602
|
-
function
|
|
602
|
+
function Ba(t) {
|
|
603
603
|
const e = Ne().filter((n) => n.bugId !== t);
|
|
604
|
-
return
|
|
604
|
+
return ct(e), e;
|
|
605
605
|
}
|
|
606
|
-
function
|
|
607
|
-
return
|
|
606
|
+
function kn() {
|
|
607
|
+
return ct([]), [];
|
|
608
608
|
}
|
|
609
|
-
function
|
|
610
|
-
let n = t,
|
|
609
|
+
function Aa(t, e) {
|
|
610
|
+
let n = t, a = n.indexOf(`
|
|
611
611
|
|
|
612
612
|
`);
|
|
613
|
-
for (;
|
|
614
|
-
const i = n.slice(0,
|
|
615
|
-
n = n.slice(
|
|
613
|
+
for (; a !== -1; ) {
|
|
614
|
+
const i = n.slice(0, a);
|
|
615
|
+
n = n.slice(a + 2);
|
|
616
616
|
const r = i.split(`
|
|
617
617
|
`).filter((s) => s.startsWith("data:")).map((s) => s.slice(5).trim()).join(`
|
|
618
618
|
`);
|
|
@@ -621,36 +621,36 @@ function Lo(t, e) {
|
|
|
621
621
|
e(JSON.parse(r));
|
|
622
622
|
} catch {
|
|
623
623
|
}
|
|
624
|
-
|
|
624
|
+
a = n.indexOf(`
|
|
625
625
|
|
|
626
626
|
`);
|
|
627
627
|
}
|
|
628
628
|
return n;
|
|
629
629
|
}
|
|
630
|
-
async function
|
|
630
|
+
async function Ra({ apiBase: t }) {
|
|
631
631
|
const e = se();
|
|
632
632
|
if (!e) return { reporter: null, reports: [] };
|
|
633
633
|
const n = await fetch(`${t}/ingest/watch/reports`, {
|
|
634
634
|
headers: { Authorization: `Bearer ${e}` }
|
|
635
635
|
});
|
|
636
636
|
if (n.status === 401)
|
|
637
|
-
return
|
|
637
|
+
return $e(), { reporter: null, reports: [] };
|
|
638
638
|
if (!n.ok) throw new Error(`[BugCatch] could not load your reports (HTTP ${n.status})`);
|
|
639
639
|
return n.json();
|
|
640
640
|
}
|
|
641
|
-
async function
|
|
641
|
+
async function Qa({ apiBase: t, bugId: e }) {
|
|
642
642
|
const n = se();
|
|
643
643
|
if (!n) return null;
|
|
644
|
-
const
|
|
644
|
+
const a = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}`, {
|
|
645
645
|
headers: { Authorization: `Bearer ${n}` }
|
|
646
646
|
});
|
|
647
|
-
if (
|
|
648
|
-
return
|
|
649
|
-
if (
|
|
650
|
-
if (!
|
|
651
|
-
return
|
|
647
|
+
if (a.status === 401)
|
|
648
|
+
return $e(), null;
|
|
649
|
+
if (a.status === 404) return null;
|
|
650
|
+
if (!a.ok) throw new Error(`[BugCatch] could not load that report (HTTP ${a.status})`);
|
|
651
|
+
return a.json();
|
|
652
652
|
}
|
|
653
|
-
async function
|
|
653
|
+
async function Sn({ apiBase: t, bugId: e, body: n, attachments: a }) {
|
|
654
654
|
const i = se();
|
|
655
655
|
if (!i) throw new Error("[BugCatch] nothing filed from this browser yet.");
|
|
656
656
|
const r = await fetch(
|
|
@@ -660,12 +660,12 @@ async function vn({ apiBase: t, bugId: e, body: n, attachments: o }) {
|
|
|
660
660
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${i}` },
|
|
661
661
|
body: JSON.stringify({
|
|
662
662
|
...n ? { body: n } : {},
|
|
663
|
-
...
|
|
663
|
+
...a != null && a.length ? { attachments: a } : {}
|
|
664
664
|
})
|
|
665
665
|
}
|
|
666
666
|
);
|
|
667
667
|
if (r.status === 401)
|
|
668
|
-
throw
|
|
668
|
+
throw $e(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
|
|
669
669
|
if (!r.ok) {
|
|
670
670
|
let s = "";
|
|
671
671
|
try {
|
|
@@ -677,21 +677,21 @@ async function vn({ apiBase: t, bugId: e, body: n, attachments: o }) {
|
|
|
677
677
|
}
|
|
678
678
|
return r.json();
|
|
679
679
|
}
|
|
680
|
-
async function
|
|
681
|
-
const
|
|
680
|
+
async function ja({ apiBase: t, apiKey: e, projectId: n }) {
|
|
681
|
+
const a = { agent: !1, live: !1 };
|
|
682
682
|
try {
|
|
683
683
|
const i = await fetch(
|
|
684
684
|
`${t}/ingest/calls?projectId=${encodeURIComponent(n)}`,
|
|
685
685
|
{ headers: { "X-BugCatch-Key": e } }
|
|
686
686
|
);
|
|
687
|
-
if (!i.ok) return
|
|
687
|
+
if (!i.ok) return a;
|
|
688
688
|
const r = await i.json();
|
|
689
|
-
return r != null && r.available ? r.kinds && typeof r.kinds == "object" ? { agent: !1, live: !!r.kinds.live } : { agent: !1, live: r.kind === "live" } :
|
|
689
|
+
return r != null && r.available ? r.kinds && typeof r.kinds == "object" ? { agent: !1, live: !!r.kinds.live } : { agent: !1, live: r.kind === "live" } : a;
|
|
690
690
|
} catch {
|
|
691
|
-
return
|
|
691
|
+
return a;
|
|
692
692
|
}
|
|
693
693
|
}
|
|
694
|
-
async function
|
|
694
|
+
async function za({ apiBase: t, apiKey: e, token: n, payload: a }) {
|
|
695
695
|
const i = await fetch(`${t}/ingest/calls`, {
|
|
696
696
|
method: "POST",
|
|
697
697
|
headers: {
|
|
@@ -703,7 +703,7 @@ async function Qo({ apiBase: t, apiKey: e, token: n, payload: o }) {
|
|
|
703
703
|
// is saying, an inch below the message, who they are signed in as.
|
|
704
704
|
...n ? { "X-BugCatch-Session": n } : {}
|
|
705
705
|
},
|
|
706
|
-
body: JSON.stringify(
|
|
706
|
+
body: JSON.stringify(a)
|
|
707
707
|
});
|
|
708
708
|
if (!i.ok) {
|
|
709
709
|
let r = "";
|
|
@@ -719,61 +719,61 @@ async function Qo({ apiBase: t, apiKey: e, token: n, payload: o }) {
|
|
|
719
719
|
}
|
|
720
720
|
return i.json();
|
|
721
721
|
}
|
|
722
|
-
async function
|
|
722
|
+
async function en({ apiBase: t, bugId: e }) {
|
|
723
723
|
const n = se();
|
|
724
724
|
if (!n) return !1;
|
|
725
725
|
try {
|
|
726
|
-
const
|
|
726
|
+
const a = await fetch(
|
|
727
727
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,
|
|
728
728
|
{ headers: { Authorization: `Bearer ${n}` } }
|
|
729
729
|
);
|
|
730
|
-
if (!
|
|
731
|
-
const i = await
|
|
730
|
+
if (!a.ok) return !1;
|
|
731
|
+
const i = await a.json();
|
|
732
732
|
return !!(i != null && i.offered);
|
|
733
733
|
} catch {
|
|
734
734
|
return !1;
|
|
735
735
|
}
|
|
736
736
|
}
|
|
737
|
-
async function
|
|
737
|
+
async function Oa({ apiBase: t, bugId: e }) {
|
|
738
738
|
const n = se();
|
|
739
739
|
if (!n) throw new Error("[BugCatch] nothing filed from this browser yet.");
|
|
740
|
-
const
|
|
740
|
+
const a = await fetch(
|
|
741
741
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call`,
|
|
742
742
|
{ method: "POST", headers: { Authorization: `Bearer ${n}` } }
|
|
743
743
|
);
|
|
744
|
-
if (
|
|
745
|
-
throw
|
|
746
|
-
if (!
|
|
744
|
+
if (a.status === 401)
|
|
745
|
+
throw $e(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
|
|
746
|
+
if (!a.ok) {
|
|
747
747
|
let i = "";
|
|
748
748
|
try {
|
|
749
|
-
const r = await
|
|
749
|
+
const r = await a.json();
|
|
750
750
|
i = Array.isArray(r.message) ? r.message.join(", ") : r.message || "";
|
|
751
751
|
} catch {
|
|
752
752
|
}
|
|
753
|
-
throw new Error(i || `[BugCatch] the call could not be started (HTTP ${
|
|
753
|
+
throw new Error(i || `[BugCatch] the call could not be started (HTTP ${a.status}).`);
|
|
754
754
|
}
|
|
755
|
-
return
|
|
755
|
+
return a.json();
|
|
756
756
|
}
|
|
757
|
-
async function
|
|
758
|
-
const
|
|
759
|
-
if (
|
|
757
|
+
async function Ha({ apiBase: t, bugId: e, callId: n }) {
|
|
758
|
+
const a = se();
|
|
759
|
+
if (a)
|
|
760
760
|
try {
|
|
761
761
|
await fetch(
|
|
762
762
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/give-up`,
|
|
763
|
-
{ method: "POST", headers: { Authorization: `Bearer ${
|
|
763
|
+
{ method: "POST", headers: { Authorization: `Bearer ${a}` } }
|
|
764
764
|
);
|
|
765
765
|
} catch {
|
|
766
766
|
}
|
|
767
767
|
}
|
|
768
|
-
async function
|
|
769
|
-
const
|
|
770
|
-
if (!
|
|
768
|
+
async function qa({ apiBase: t, bugId: e, callId: n }) {
|
|
769
|
+
const a = se();
|
|
770
|
+
if (!a) throw new Error("[BugCatch] nothing filed from this browser yet.");
|
|
771
771
|
const i = await fetch(
|
|
772
772
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/answer`,
|
|
773
|
-
{ method: "POST", headers: { Authorization: `Bearer ${
|
|
773
|
+
{ method: "POST", headers: { Authorization: `Bearer ${a}` } }
|
|
774
774
|
);
|
|
775
775
|
if (i.status === 401)
|
|
776
|
-
throw
|
|
776
|
+
throw $e(), new Error("[BugCatch] this browser can no longer prove it filed that report.");
|
|
777
777
|
if (i.status === 409)
|
|
778
778
|
throw new Error("[BugCatch] that call is no longer ringing.");
|
|
779
779
|
if (!i.ok) {
|
|
@@ -787,19 +787,19 @@ async function Oo({ apiBase: t, bugId: e, callId: n }) {
|
|
|
787
787
|
}
|
|
788
788
|
return i.json();
|
|
789
789
|
}
|
|
790
|
-
async function
|
|
791
|
-
const
|
|
792
|
-
if (
|
|
790
|
+
async function tn({ apiBase: t, bugId: e, callId: n }) {
|
|
791
|
+
const a = se();
|
|
792
|
+
if (a)
|
|
793
793
|
try {
|
|
794
794
|
await fetch(
|
|
795
795
|
`${t}/ingest/watch/reports/${encodeURIComponent(e)}/live-call/${encodeURIComponent(n)}/decline`,
|
|
796
|
-
{ method: "POST", headers: { Authorization: `Bearer ${
|
|
796
|
+
{ method: "POST", headers: { Authorization: `Bearer ${a}` } }
|
|
797
797
|
);
|
|
798
798
|
} catch {
|
|
799
799
|
}
|
|
800
800
|
}
|
|
801
|
-
function
|
|
802
|
-
let n = !0,
|
|
801
|
+
function Da({ apiBase: t, onUpdate: e }) {
|
|
802
|
+
let n = !0, a = 0, i = null;
|
|
803
803
|
async function r() {
|
|
804
804
|
const s = se();
|
|
805
805
|
if (!s) throw new Error("nothing filed from this browser yet");
|
|
@@ -809,24 +809,24 @@ function Ho({ apiBase: t, onUpdate: e }) {
|
|
|
809
809
|
signal: i.signal
|
|
810
810
|
});
|
|
811
811
|
if (l.status === 401)
|
|
812
|
-
throw n = !1,
|
|
812
|
+
throw n = !1, $e(), new Error("subscription no longer valid");
|
|
813
813
|
if (!l.ok || !l.body) throw new Error(`stream failed (${l.status})`);
|
|
814
|
-
const
|
|
815
|
-
let
|
|
814
|
+
const p = Date.now(), f = l.body.getReader(), y = new TextDecoder();
|
|
815
|
+
let h = "";
|
|
816
816
|
try {
|
|
817
817
|
for (; ; ) {
|
|
818
|
-
const { value: b, done:
|
|
819
|
-
if (
|
|
820
|
-
|
|
821
|
-
if (
|
|
818
|
+
const { value: b, done: g } = await f.read();
|
|
819
|
+
if (g) break;
|
|
820
|
+
h += y.decode(b, { stream: !0 }), h = Aa(h, (S) => {
|
|
821
|
+
if (S.type !== "ping")
|
|
822
822
|
try {
|
|
823
|
-
e(
|
|
823
|
+
e(S);
|
|
824
824
|
} catch {
|
|
825
825
|
}
|
|
826
826
|
});
|
|
827
827
|
}
|
|
828
828
|
} finally {
|
|
829
|
-
Date.now() -
|
|
829
|
+
Date.now() - p >= Ta && (a = 0);
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
832
|
return (async () => {
|
|
@@ -837,66 +837,66 @@ function Ho({ apiBase: t, onUpdate: e }) {
|
|
|
837
837
|
if ((l == null ? void 0 : l.name) === "AbortError") return;
|
|
838
838
|
}
|
|
839
839
|
if (!n) return;
|
|
840
|
-
const s =
|
|
841
|
-
|
|
840
|
+
const s = Gt[Math.min(a, Gt.length - 1)];
|
|
841
|
+
a += 1, await new Promise((l) => setTimeout(l, s));
|
|
842
842
|
}
|
|
843
843
|
})(), () => {
|
|
844
844
|
n = !1, i == null || i.abort(), i = null;
|
|
845
845
|
};
|
|
846
846
|
}
|
|
847
|
-
const
|
|
847
|
+
const Na = {
|
|
848
848
|
OPEN: "is open",
|
|
849
849
|
IN_PROGRESS: "is being worked on",
|
|
850
850
|
RESOLVED: "has been fixed",
|
|
851
851
|
CLOSED: "has been closed"
|
|
852
|
-
},
|
|
852
|
+
}, Ua = {
|
|
853
853
|
status: null,
|
|
854
854
|
// falls back to the host's configured accent
|
|
855
855
|
severity: "#e8912a",
|
|
856
856
|
assignment: "#4da3ff",
|
|
857
857
|
reply: "#35b87f"
|
|
858
858
|
};
|
|
859
|
-
function
|
|
860
|
-
return t != null && t.summary ? t.summary : `Your report ${
|
|
859
|
+
function nn(t) {
|
|
860
|
+
return t != null && t.summary ? t.summary : `Your report ${Na[t == null ? void 0 : t.status] || "was updated"}`;
|
|
861
861
|
}
|
|
862
|
-
function
|
|
862
|
+
function Va(t) {
|
|
863
863
|
var e;
|
|
864
864
|
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) || "";
|
|
865
865
|
}
|
|
866
|
-
function
|
|
866
|
+
function Ka(t) {
|
|
867
867
|
const e = Date.parse(t || "");
|
|
868
868
|
if (!Number.isFinite(e)) return "";
|
|
869
869
|
const n = Math.round((Date.now() - e) / 6e4);
|
|
870
870
|
if (n < 1) return "just now";
|
|
871
871
|
if (n < 60) return `${n}m ago`;
|
|
872
|
-
const
|
|
873
|
-
if (
|
|
874
|
-
const i = Math.round(
|
|
872
|
+
const a = Math.round(n / 60);
|
|
873
|
+
if (a < 24) return `${a}h ago`;
|
|
874
|
+
const i = Math.round(a / 24);
|
|
875
875
|
return i === 1 ? "yesterday" : `${i}d ago`;
|
|
876
876
|
}
|
|
877
|
-
function
|
|
877
|
+
function Pa() {
|
|
878
878
|
var t;
|
|
879
879
|
try {
|
|
880
|
-
const e = document.querySelector('[data-bugcatch="widget"]'), n = (t = e == null ? void 0 : e.shadowRoot) == null ? void 0 : t.querySelector(".dock"),
|
|
881
|
-
return
|
|
880
|
+
const e = document.querySelector('[data-bugcatch="widget"]'), n = (t = e == null ? void 0 : e.shadowRoot) == null ? void 0 : t.querySelector(".dock"), a = (n == null ? void 0 : n.getBoundingClientRect().height) || 0;
|
|
881
|
+
return a ? Math.round(a) + 12 : 0;
|
|
882
882
|
} catch {
|
|
883
883
|
return 0;
|
|
884
884
|
}
|
|
885
885
|
}
|
|
886
|
-
function
|
|
886
|
+
function _a({
|
|
887
887
|
accent: t = "#4F46E5",
|
|
888
888
|
position: e = "bottom-right",
|
|
889
889
|
onRead: n = null,
|
|
890
|
-
onReadAll:
|
|
890
|
+
onReadAll: a = null,
|
|
891
891
|
onCall: i = null
|
|
892
892
|
} = {}) {
|
|
893
|
-
const [r, s] = String(e).split("-"), l = r === "top",
|
|
894
|
-
let
|
|
893
|
+
const [r, s] = String(e).split("-"), l = r === "top", p = s === "left", f = /* @__PURE__ */ new Map();
|
|
894
|
+
let y = null, h = null;
|
|
895
895
|
function b() {
|
|
896
|
-
return
|
|
896
|
+
return y != null && y.isConnected || (y = document.createElement("div"), y.setAttribute("data-bugcatch", "updates"), y.style.cssText = [
|
|
897
897
|
"position:fixed",
|
|
898
|
-
`${l ? "top" : "bottom"}:${20 +
|
|
899
|
-
`${
|
|
898
|
+
`${l ? "top" : "bottom"}:${20 + Pa()}px`,
|
|
899
|
+
`${p ? "left" : "right"}:20px`,
|
|
900
900
|
// Under the widget's dock and its panel scrim, both of which are higher.
|
|
901
901
|
// A notification is worth interrupting a page for, not the report being
|
|
902
902
|
// read on top of it.
|
|
@@ -904,36 +904,36 @@ function Ko({
|
|
|
904
904
|
"display:flex",
|
|
905
905
|
"flex-direction:column",
|
|
906
906
|
"gap:10px",
|
|
907
|
-
`align-items:${
|
|
907
|
+
`align-items:${p ? "flex-start" : "flex-end"}`,
|
|
908
908
|
"width:min(320px,calc(100vw - 40px))",
|
|
909
909
|
// The gaps between cards belong to the page underneath.
|
|
910
910
|
"pointer-events:none"
|
|
911
|
-
].join(";"), document.body.appendChild(
|
|
911
|
+
].join(";"), document.body.appendChild(y)), y;
|
|
912
912
|
}
|
|
913
|
-
function
|
|
914
|
-
if (!
|
|
915
|
-
|
|
913
|
+
function g(C) {
|
|
914
|
+
if (!C._bcShown) {
|
|
915
|
+
C.remove();
|
|
916
916
|
return;
|
|
917
917
|
}
|
|
918
|
-
|
|
918
|
+
C.style.opacity = "0", C.style.transform = `translateY(${l ? -8 : 8}px)`, setTimeout(() => C.remove(), 250);
|
|
919
919
|
}
|
|
920
|
-
function
|
|
920
|
+
function S(C, $) {
|
|
921
921
|
const T = document.createElement("button");
|
|
922
|
-
return T.type = "button", T.textContent =
|
|
922
|
+
return T.type = "button", T.textContent = C, T.style.cssText = [
|
|
923
923
|
"padding:5px 11px",
|
|
924
|
-
`border:${
|
|
924
|
+
`border:${$ ? "0" : "1px solid rgba(236,238,242,.24)"}`,
|
|
925
925
|
"border-radius:6px",
|
|
926
|
-
`background:${
|
|
927
|
-
`color:${
|
|
926
|
+
`background:${$ ? t : "transparent"}`,
|
|
927
|
+
`color:${$ ? "#fff" : "#eceef2"}`,
|
|
928
928
|
"font:600 12px/1.4 inherit",
|
|
929
929
|
"cursor:pointer",
|
|
930
930
|
"white-space:nowrap"
|
|
931
931
|
].join(";"), T;
|
|
932
932
|
}
|
|
933
|
-
function A(
|
|
934
|
-
var
|
|
935
|
-
const
|
|
936
|
-
|
|
933
|
+
function A(C) {
|
|
934
|
+
var U;
|
|
935
|
+
const $ = document.createElement("div");
|
|
936
|
+
$.setAttribute("role", "status"), $.style.cssText = [
|
|
937
937
|
"box-sizing:border-box",
|
|
938
938
|
"width:100%",
|
|
939
939
|
"padding:12px 14px",
|
|
@@ -942,30 +942,30 @@ function Ko({
|
|
|
942
942
|
"color:#eceef2",
|
|
943
943
|
'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',
|
|
944
944
|
"box-shadow:0 12px 30px rgba(0,0,0,0.45)",
|
|
945
|
-
`border-left:3px solid ${
|
|
945
|
+
`border-left:3px solid ${Ua[C == null ? void 0 : C.kind] || t}`,
|
|
946
946
|
"opacity:0",
|
|
947
947
|
`transform:translateY(${l ? -8 : 8}px)`,
|
|
948
948
|
"transition:opacity .2s ease,transform .2s ease",
|
|
949
949
|
"pointer-events:auto"
|
|
950
950
|
].join(";");
|
|
951
951
|
const T = document.createElement("div");
|
|
952
|
-
T.style.cssText = "font-weight:600;margin-bottom:2px", T.textContent =
|
|
952
|
+
T.style.cssText = "font-weight:600;margin-bottom:2px", T.textContent = nn(C);
|
|
953
953
|
const L = document.createElement("div");
|
|
954
|
-
L.style.cssText = (
|
|
954
|
+
L.style.cssText = (C == null ? void 0 : C.kind) === "reply" ? "color:#a4abba;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden" : "color:#a4abba", L.textContent = Va(C);
|
|
955
955
|
const Y = document.createElement("div");
|
|
956
956
|
Y.style.cssText = "display:flex;align-items:center;gap:8px;margin-top:10px;flex-wrap:wrap";
|
|
957
|
-
const
|
|
958
|
-
|
|
959
|
-
const
|
|
960
|
-
if (
|
|
961
|
-
const
|
|
962
|
-
|
|
957
|
+
const N = document.createElement("span");
|
|
958
|
+
N.style.cssText = "color:#7b8394;font-size:11px;margin-right:auto", N.textContent = Ka(C == null ? void 0 : C.at);
|
|
959
|
+
const Q = S("Mark as read", !1);
|
|
960
|
+
if (Q.setAttribute("aria-label", `Mark as read: ${nn(C)}`), Q.addEventListener("click", () => n == null ? void 0 : n(C.id)), Y.append(N, Q), (U = C == null ? void 0 : C.call) != null && U.offered && typeof i == "function") {
|
|
961
|
+
const E = S("Talk it through", !0);
|
|
962
|
+
E.addEventListener("click", () => i(C)), Y.insertBefore(E, Q);
|
|
963
963
|
}
|
|
964
|
-
return
|
|
964
|
+
return $.append(T, L, Y), $;
|
|
965
965
|
}
|
|
966
|
-
function
|
|
967
|
-
const
|
|
968
|
-
|
|
966
|
+
function ae(C) {
|
|
967
|
+
const $ = document.createElement("div");
|
|
968
|
+
$.style.cssText = [
|
|
969
969
|
"box-sizing:border-box",
|
|
970
970
|
"width:100%",
|
|
971
971
|
"display:flex",
|
|
@@ -980,9 +980,9 @@ function Ko({
|
|
|
980
980
|
"pointer-events:auto"
|
|
981
981
|
].join(";");
|
|
982
982
|
const T = document.createElement("span");
|
|
983
|
-
T.style.cssText = "margin-right:auto", T.textContent = `${
|
|
984
|
-
const L =
|
|
985
|
-
return L.style.cssText += ";padding:4px 9px", L.addEventListener("click", () =>
|
|
983
|
+
T.style.cssText = "margin-right:auto", T.textContent = `${C} more update${C === 1 ? "" : "s"}`;
|
|
984
|
+
const L = S("Mark all as read", !1);
|
|
985
|
+
return L.style.cssText += ";padding:4px 9px", L.addEventListener("click", () => a == null ? void 0 : a()), $.append(T, L), $;
|
|
986
986
|
}
|
|
987
987
|
return {
|
|
988
988
|
/**
|
|
@@ -992,40 +992,40 @@ function Ko({
|
|
|
992
992
|
* corner the reporter's eye is already trained on — so the stack grows away
|
|
993
993
|
* from the launcher rather than over it.
|
|
994
994
|
*/
|
|
995
|
-
render(
|
|
996
|
-
const
|
|
997
|
-
if (
|
|
998
|
-
for (const
|
|
999
|
-
|
|
995
|
+
render(C) {
|
|
996
|
+
const $ = Array.isArray(C) ? C : [];
|
|
997
|
+
if (!$.length) {
|
|
998
|
+
for (const E of f.values()) g(E);
|
|
999
|
+
f.clear(), h == null || h.remove(), h = null, y == null || y.remove(), y = null;
|
|
1000
1000
|
return;
|
|
1001
1001
|
}
|
|
1002
|
-
const T =
|
|
1003
|
-
for (const [
|
|
1004
|
-
L.has(
|
|
1005
|
-
const
|
|
1006
|
-
for (const
|
|
1007
|
-
if (
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1002
|
+
const T = $.slice(-3), L = new Set(T.map((E) => E.id)), Y = b();
|
|
1003
|
+
for (const [E, oe] of f)
|
|
1004
|
+
L.has(E) || (g(oe), f.delete(E));
|
|
1005
|
+
const N = [];
|
|
1006
|
+
for (const E of T) {
|
|
1007
|
+
if (f.has(E.id)) continue;
|
|
1008
|
+
const oe = A(E);
|
|
1009
|
+
f.set(E.id, oe), N.push(oe);
|
|
1010
1010
|
}
|
|
1011
|
-
const
|
|
1012
|
-
for (const
|
|
1013
|
-
const
|
|
1014
|
-
|
|
1015
|
-
for (const
|
|
1016
|
-
|
|
1011
|
+
const Q = l ? [...T].reverse() : T;
|
|
1012
|
+
for (const E of Q) Y.appendChild(f.get(E.id));
|
|
1013
|
+
const U = $.length - T.length;
|
|
1014
|
+
U > 0 ? (h == null || h.remove(), h = ae(U), l ? Y.appendChild(h) : Y.insertBefore(h, Y.firstChild)) : (h == null || h.remove(), h = null), requestAnimationFrame(() => {
|
|
1015
|
+
for (const E of N)
|
|
1016
|
+
E.isConnected && (E._bcShown = !0, E.style.opacity = "1", E.style.transform = "translateY(0)");
|
|
1017
1017
|
});
|
|
1018
1018
|
},
|
|
1019
1019
|
destroy() {
|
|
1020
|
-
|
|
1020
|
+
f.clear(), h = null, y == null || y.remove(), y = null;
|
|
1021
1021
|
}
|
|
1022
1022
|
};
|
|
1023
1023
|
}
|
|
1024
|
-
async function
|
|
1024
|
+
async function Fa({ apiBase: t, apiKey: e, projectId: n, sessionToken: a }) {
|
|
1025
1025
|
try {
|
|
1026
1026
|
const i = await fetch(
|
|
1027
1027
|
`${t}/ingest/known-issues?projectId=${encodeURIComponent(n)}`,
|
|
1028
|
-
{ headers:
|
|
1028
|
+
{ headers: Lt(e, a) }
|
|
1029
1029
|
);
|
|
1030
1030
|
if (!i.ok) return [];
|
|
1031
1031
|
const r = await i.json();
|
|
@@ -1034,47 +1034,47 @@ async function Po({ apiBase: t, apiKey: e, projectId: n, sessionToken: o }) {
|
|
|
1034
1034
|
return [];
|
|
1035
1035
|
}
|
|
1036
1036
|
}
|
|
1037
|
-
async function
|
|
1037
|
+
async function Wa({ apiBase: t, apiKey: e, projectId: n, q: a, sessionToken: i, signal: r }) {
|
|
1038
1038
|
try {
|
|
1039
|
-
const s = `${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(
|
|
1039
|
+
const s = `${t}/ingest/known-issues/match?projectId=${encodeURIComponent(n)}&q=${encodeURIComponent(a)}`, l = await fetch(s, { headers: Lt(e, i), signal: r });
|
|
1040
1040
|
if (!l.ok) return [];
|
|
1041
|
-
const
|
|
1042
|
-
return Array.isArray(
|
|
1041
|
+
const p = await l.json();
|
|
1042
|
+
return Array.isArray(p == null ? void 0 : p.issues) ? p.issues : [];
|
|
1043
1043
|
} catch {
|
|
1044
1044
|
return [];
|
|
1045
1045
|
}
|
|
1046
1046
|
}
|
|
1047
|
-
async function
|
|
1047
|
+
async function Ya({
|
|
1048
1048
|
apiBase: t,
|
|
1049
1049
|
apiKey: e,
|
|
1050
1050
|
projectId: n,
|
|
1051
|
-
bugId:
|
|
1051
|
+
bugId: a,
|
|
1052
1052
|
reporterEmail: i,
|
|
1053
1053
|
reporterName: r,
|
|
1054
1054
|
metadata: s,
|
|
1055
1055
|
logs: l,
|
|
1056
|
-
sessionToken:
|
|
1056
|
+
sessionToken: p
|
|
1057
1057
|
}) {
|
|
1058
|
-
const
|
|
1059
|
-
`${t}/ingest/known-issues/${encodeURIComponent(
|
|
1058
|
+
const f = await fetch(
|
|
1059
|
+
`${t}/ingest/known-issues/${encodeURIComponent(a)}/join`,
|
|
1060
1060
|
{
|
|
1061
1061
|
method: "POST",
|
|
1062
|
-
headers:
|
|
1062
|
+
headers: Lt(e, p),
|
|
1063
1063
|
body: JSON.stringify({ projectId: n, reporterEmail: i, reporterName: r, metadata: s, logs: l })
|
|
1064
1064
|
}
|
|
1065
1065
|
);
|
|
1066
|
-
if (!
|
|
1067
|
-
const
|
|
1068
|
-
return
|
|
1066
|
+
if (!f.ok) throw new Error(await Xa(f));
|
|
1067
|
+
const y = await f.json();
|
|
1068
|
+
return y != null && y.watchToken && Ct(y.watchToken), y;
|
|
1069
1069
|
}
|
|
1070
|
-
function
|
|
1070
|
+
function Lt(t, e) {
|
|
1071
1071
|
return {
|
|
1072
1072
|
"Content-Type": "application/json",
|
|
1073
1073
|
"X-BugCatch-Key": t,
|
|
1074
1074
|
...e ? { "X-BugCatch-Session": e } : {}
|
|
1075
1075
|
};
|
|
1076
1076
|
}
|
|
1077
|
-
async function
|
|
1077
|
+
async function Xa(t) {
|
|
1078
1078
|
try {
|
|
1079
1079
|
const e = await t.json(), n = Array.isArray(e.message) ? e.message.join(", ") : e.message;
|
|
1080
1080
|
if (n) return n;
|
|
@@ -1082,19 +1082,19 @@ async function Wo(t) {
|
|
|
1082
1082
|
}
|
|
1083
1083
|
return `Could not add you to this issue (HTTP ${t.status})`;
|
|
1084
1084
|
}
|
|
1085
|
-
async function
|
|
1086
|
-
const
|
|
1087
|
-
if (!
|
|
1085
|
+
async function Za({ apiBase: t, bugId: e, ...n }) {
|
|
1086
|
+
const a = se();
|
|
1087
|
+
if (!a) throw new Error("This browser cannot access that report.");
|
|
1088
1088
|
const i = await fetch(`${t}/ingest/watch/reports/${encodeURIComponent(e)}/verification`, {
|
|
1089
1089
|
method: "POST",
|
|
1090
|
-
headers: { "Content-Type": "application/json", Authorization: `Bearer ${
|
|
1090
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${a}` },
|
|
1091
1091
|
body: JSON.stringify(n)
|
|
1092
1092
|
}), r = await i.json().catch(() => ({}));
|
|
1093
1093
|
if (!i.ok) throw new Error(r.message || "Could not record feedback. Please refresh and try again.");
|
|
1094
1094
|
return r;
|
|
1095
1095
|
}
|
|
1096
|
-
const
|
|
1097
|
-
function
|
|
1096
|
+
const Ja = 2e4, Cn = 120, $n = 200;
|
|
1097
|
+
function En(t) {
|
|
1098
1098
|
if (typeof t != "string" || !t.trim() || t.length > 400) return null;
|
|
1099
1099
|
try {
|
|
1100
1100
|
return new RegExp(t.trim(), "gi");
|
|
@@ -1102,82 +1102,82 @@ function Sn(t) {
|
|
|
1102
1102
|
return null;
|
|
1103
1103
|
}
|
|
1104
1104
|
}
|
|
1105
|
-
const
|
|
1106
|
-
function
|
|
1105
|
+
const Ga = (t) => String(t).replace(/\s+/g, " ").trim().slice(0, Cn);
|
|
1106
|
+
function Tn(t) {
|
|
1107
1107
|
const e = t.length > 1 && t[1] !== void 0 ? t[1] : t[0];
|
|
1108
|
-
return typeof e != "string" || !e.trim() ? null : { value:
|
|
1108
|
+
return typeof e != "string" || !e.trim() ? null : { value: Ga(e), start: t.index, end: t.index + t[0].length };
|
|
1109
1109
|
}
|
|
1110
|
-
function
|
|
1111
|
-
const n = [],
|
|
1110
|
+
function eo(t, e) {
|
|
1111
|
+
const n = [], a = /* @__PURE__ */ new Set();
|
|
1112
1112
|
for (const i of e || []) {
|
|
1113
|
-
const r = typeof i == "string" ? i.slice(0,
|
|
1113
|
+
const r = typeof i == "string" ? i.slice(0, Ja) : "";
|
|
1114
1114
|
if (!r) continue;
|
|
1115
|
-
const s = [], l = (
|
|
1116
|
-
for (const
|
|
1117
|
-
if (!
|
|
1118
|
-
const
|
|
1119
|
-
if (!
|
|
1120
|
-
let
|
|
1121
|
-
for (
|
|
1122
|
-
if (
|
|
1123
|
-
|
|
1115
|
+
const s = [], l = (p, f) => s.some(([y, h]) => p < h && f > y);
|
|
1116
|
+
for (const p of t || []) {
|
|
1117
|
+
if (!p || p.scan === !1) continue;
|
|
1118
|
+
const f = En(p.pattern);
|
|
1119
|
+
if (!f) continue;
|
|
1120
|
+
let y, h = 0;
|
|
1121
|
+
for (f.lastIndex = 0; (y = f.exec(r)) !== null && !(++h > $n); ) {
|
|
1122
|
+
if (y[0] === "") {
|
|
1123
|
+
f.lastIndex += 1;
|
|
1124
1124
|
continue;
|
|
1125
1125
|
}
|
|
1126
|
-
const b =
|
|
1126
|
+
const b = Tn(y);
|
|
1127
1127
|
if (b && !l(b.start, b.end)) {
|
|
1128
1128
|
s.push([b.start, b.end]);
|
|
1129
|
-
const
|
|
1130
|
-
|
|
1129
|
+
const g = `${p.key}:${b.value.toLowerCase()}`;
|
|
1130
|
+
a.has(g) || (a.add(g), n.push({ key: p.key, label: p.label, value: b.value }));
|
|
1131
1131
|
}
|
|
1132
1132
|
}
|
|
1133
1133
|
}
|
|
1134
1134
|
}
|
|
1135
1135
|
return n;
|
|
1136
1136
|
}
|
|
1137
|
-
function
|
|
1137
|
+
function to(t, e) {
|
|
1138
1138
|
const n = typeof e == "string" ? e.trim() : "";
|
|
1139
|
-
if (!n || n.length >
|
|
1140
|
-
const
|
|
1141
|
-
if (!
|
|
1139
|
+
if (!n || n.length > Cn) return null;
|
|
1140
|
+
const a = En(t && (t.valuePattern || t.pattern));
|
|
1141
|
+
if (!a) return null;
|
|
1142
1142
|
let i, r = 0;
|
|
1143
|
-
for (
|
|
1143
|
+
for (a.lastIndex = 0; (i = a.exec(n)) !== null && !(++r > $n); ) {
|
|
1144
1144
|
if (i[0] === "") {
|
|
1145
|
-
|
|
1145
|
+
a.lastIndex += 1;
|
|
1146
1146
|
continue;
|
|
1147
1147
|
}
|
|
1148
1148
|
const s = i.index + i[0].length === n.length, l = i.index === 0 || i.index === 1;
|
|
1149
1149
|
if (s && l) {
|
|
1150
|
-
const
|
|
1151
|
-
if (
|
|
1150
|
+
const p = Tn(i);
|
|
1151
|
+
if (p) return p.value;
|
|
1152
1152
|
}
|
|
1153
1153
|
}
|
|
1154
1154
|
return null;
|
|
1155
1155
|
}
|
|
1156
|
-
async function
|
|
1157
|
-
const
|
|
1156
|
+
async function no({ apiBase: t, apiKey: e, projectId: n }) {
|
|
1157
|
+
const a = { policy: "off", fields: [] };
|
|
1158
1158
|
try {
|
|
1159
1159
|
const i = await fetch(
|
|
1160
1160
|
`${t}/ingest/reference-fields?projectId=${encodeURIComponent(n)}`,
|
|
1161
1161
|
{ headers: { "X-BugCatch-Key": e } }
|
|
1162
1162
|
);
|
|
1163
|
-
if (!i.ok) return
|
|
1163
|
+
if (!i.ok) return a;
|
|
1164
1164
|
const r = await i.json(), s = r.policy === "optional" || r.policy === "required" ? r.policy : "off", l = Array.isArray(r.fields) ? r.fields : [];
|
|
1165
|
-
return l.length ? { policy: s, fields: l } :
|
|
1165
|
+
return l.length ? { policy: s, fields: l } : a;
|
|
1166
1166
|
} catch {
|
|
1167
|
-
return
|
|
1167
|
+
return a;
|
|
1168
1168
|
}
|
|
1169
1169
|
}
|
|
1170
|
-
const
|
|
1170
|
+
const an = {
|
|
1171
1171
|
"bottom-right": "bottom:20px;right:20px;",
|
|
1172
1172
|
"bottom-left": "bottom:20px;left:20px;",
|
|
1173
1173
|
"top-right": "top:20px;right:20px;",
|
|
1174
1174
|
"top-left": "top:20px;left:20px;"
|
|
1175
|
-
},
|
|
1175
|
+
}, on = [
|
|
1176
1176
|
{ value: "LOW", label: "Low" },
|
|
1177
1177
|
{ value: "MEDIUM", label: "Medium" },
|
|
1178
1178
|
{ value: "HIGH", label: "High" },
|
|
1179
1179
|
{ value: "CRITICAL", label: "Critical" }
|
|
1180
|
-
],
|
|
1180
|
+
], O = {
|
|
1181
1181
|
camera: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8.5A1.5 1.5 0 0 1 4.5 7h2.2a1 1 0 0 0 .83-.45l.94-1.4A1 1 0 0 1 9.3 4.7h5.4a1 1 0 0 1 .83.45l.94 1.4a1 1 0 0 0 .83.45h2.2A1.5 1.5 0 0 1 21 8.5v9A1.5 1.5 0 0 1 19.5 19h-15A1.5 1.5 0 0 1 3 17.5z"/><circle cx="12" cy="13" r="3.4"/></svg>',
|
|
1182
1182
|
video: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="6" width="12.5" height="12" rx="2.2"/><path d="M15.5 10.8l4.2-2.6a.6.6 0 0 1 .92.5v6.6a.6.6 0 0 1-.92.5l-4.2-2.6z"/></svg>',
|
|
1183
1183
|
paperclip: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M20 11.5l-7.6 7.6a4.6 4.6 0 0 1-6.5-6.5l8-8a3.2 3.2 0 0 1 4.5 4.5l-8 8a1.8 1.8 0 0 1-2.5-2.5l7.1-7.1"/></svg>',
|
|
@@ -1194,26 +1194,26 @@ const en = {
|
|
|
1194
1194
|
sun: '<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>',
|
|
1195
1195
|
moon: '<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>',
|
|
1196
1196
|
auto: '<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>'
|
|
1197
|
-
},
|
|
1198
|
-
{ value: "light", label: "Light", icon:
|
|
1199
|
-
{ value: "dark", label: "Dark", icon:
|
|
1200
|
-
{ value: "auto", label: "System default", icon:
|
|
1201
|
-
],
|
|
1202
|
-
function
|
|
1197
|
+
}, ao = '<svg class="bc-brand" viewBox="0 0 254 60" fill="none" role="img" aria-label="sphoro BugCatch"><g fill="currentColor"><path transform="translate(0.00 40.00) scale(0.04000 -0.04000)" d="M276.00 -14.00Q179.00 -14.00 117.00 28.00Q55.00 70.00 42.00 148.00L158.00 178.00Q165.00 143.00 181.50 123.00Q198.00 103.00 222.50 94.50Q247.00 86.00 276.00 86.00Q320.00 86.00 341.00 101.50Q362.00 117.00 362.00 140.00Q362.00 163.00 342.00 175.50Q322.00 188.00 278.00 196.00L250.00 201.00Q198.00 211.00 155.00 228.50Q112.00 246.00 86.00 277.00Q60.00 308.00 60.00 357.00Q60.00 431.00 114.00 470.50Q168.00 510.00 256.00 510.00Q339.00 510.00 394.00 473.00Q449.00 436.00 466.00 376.00L349.00 340.00Q341.00 378.00 316.50 394.00Q292.00 410.00 256.00 410.00Q220.00 410.00 201.00 397.50Q182.00 385.00 182.00 363.00Q182.00 339.00 202.00 327.50Q222.00 316.00 256.00 310.00L284.00 305.00Q340.00 295.00 385.50 278.50Q431.00 262.00 457.50 231.50Q484.00 201.00 484.00 149.00Q484.00 71.00 427.50 28.50Q371.00 -14.00 276.00 -14.00Z"/><path transform="translate(19.56 40.00) scale(0.04000 -0.04000)" d="M70.00 -200.00V496.00H194.00V436.00H212.00Q229.00 465.00 265.00 487.50Q301.00 510.00 368.00 510.00Q428.00 510.00 479.00 480.50Q530.00 451.00 561.00 394.00Q592.00 337.00 592.00 256.00V240.00Q592.00 159.00 561.00 102.00Q530.00 45.00 479.00 15.50Q428.00 -14.00 368.00 -14.00Q323.00 -14.00 292.50 -3.50Q262.00 7.00 243.50 23.50Q225.00 40.00 214.00 57.00H196.00V-200.00ZM330.00 96.00Q389.00 96.00 427.50 133.50Q466.00 171.00 466.00 243.00V253.00Q466.00 325.00 427.00 362.50Q388.00 400.00 330.00 400.00Q272.00 400.00 233.00 362.50Q194.00 325.00 194.00 253.00V243.00Q194.00 171.00 233.00 133.50Q272.00 96.00 330.00 96.00Z"/><path transform="translate(43.68 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V700.00H196.00V435.00H214.00Q222.00 451.00 239.00 467.00Q256.00 483.00 284.50 493.50Q313.00 504.00 357.00 504.00Q415.00 504.00 458.50 477.50Q502.00 451.00 526.00 404.50Q550.00 358.00 550.00 296.00V0.00H424.00V286.00Q424.00 342.00 396.50 370.00Q369.00 398.00 318.00 398.00Q260.00 398.00 228.00 359.50Q196.00 321.00 196.00 252.00V0.00Z"/><path transform="translate(66.92 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/><path transform="translate(90.00 40.00) scale(0.04000 -0.04000)" d="M70.00 0.00V496.00H194.00V440.00H212.00Q223.00 470.00 248.50 484.00Q274.00 498.00 308.00 498.00H368.00V386.00H306.00Q258.00 386.00 227.00 360.50Q196.00 335.00 196.00 282.00V0.00Z"/><path transform="translate(104.44 40.00) scale(0.04000 -0.04000)" d="M306.00 -14.00Q232.00 -14.00 173.00 16.00Q114.00 46.00 80.00 103.00Q46.00 160.00 46.00 240.00V256.00Q46.00 336.00 80.00 393.00Q114.00 450.00 173.00 480.00Q232.00 510.00 306.00 510.00Q380.00 510.00 439.00 480.00Q498.00 450.00 532.00 393.00Q566.00 336.00 566.00 256.00V240.00Q566.00 160.00 532.00 103.00Q498.00 46.00 439.00 16.00Q380.00 -14.00 306.00 -14.00ZM306.00 98.00Q364.00 98.00 402.00 135.50Q440.00 173.00 440.00 243.00V253.00Q440.00 323.00 402.50 360.50Q365.00 398.00 306.00 398.00Q248.00 398.00 210.00 360.50Q172.00 323.00 172.00 253.00V243.00Q172.00 173.00 210.00 135.50Q248.00 98.00 306.00 98.00Z"/></g><rect x="139.52" y="16" width="1.6" height="26" rx="0.8" fill="var(--bc-brand-mark, #5647ee)" opacity="0.4"/><g fill="var(--bc-brand-mark, #5647ee)"><path transform="translate(154.52 35.00) scale(0.01400 -0.01400)" d="M46.35 0.00V105.85H139.75V594.15H46.35V700.00H404.08Q467.38 700.00 514.79 678.41Q562.20 656.83 588.70 617.33Q615.20 577.83 615.20 523.35V513.70Q615.20 465.52 597.03 434.76Q578.85 404.00 553.91 387.24Q528.98 370.48 506.28 363.30V346.35Q528.98 340.35 555.24 323.50Q581.50 306.65 600.00 275.48Q618.50 244.30 618.50 194.48V184.48Q618.50 126.65 591.41 85.24Q564.33 43.83 516.83 21.91Q469.33 0.00 406.85 0.00ZM259.85 109.15H392.60Q441.20 109.15 469.80 132.60Q498.40 156.05 498.40 198.55V208.20Q498.40 250.70 470.21 274.15Q442.02 297.60 392.60 297.60H259.85ZM259.85 406.75H391.65Q437.55 406.75 466.32 430.11Q495.10 453.48 495.10 493.80V503.80Q495.10 544.95 466.74 567.90Q438.37 590.85 391.65 590.85H259.85Z"/><path transform="translate(167.00 35.00) scale(0.01400 -0.01400)" d="M335.30 -14.00Q251.22 -14.00 190.60 16.63Q129.97 47.25 97.56 104.96Q65.15 162.68 65.15 243.03V700.00H185.25V239.73Q185.25 170.48 224.03 131.99Q262.80 93.50 335.30 93.50Q407.80 93.50 446.57 131.99Q485.35 170.48 485.35 239.73V700.00H605.45V243.03Q605.45 162.68 573.13 104.96Q540.80 47.25 480.09 16.63Q419.38 -14.00 335.30 -14.00Z"/><path transform="translate(179.60 35.00) scale(0.01400 -0.01400)" d="M311.85 -14.00Q238.45 -14.00 179.69 18.50Q120.92 51.00 86.69 113.67Q52.45 176.35 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.23 645.59Q598.33 577.17 598.33 460.87V456.70H479.87V464.52Q479.87 504.67 463.76 536.86Q447.65 569.05 414.99 587.77Q382.32 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 138.89Q257.63 91.85 334.00 91.85Q410.02 91.85 445.12 132.83Q480.22 173.80 480.22 237.92V249.67H302.85V351.88H598.33V0.00H487.52V69.10H470.57Q462.70 50.87 446.06 31.44Q429.42 12.00 397.64 -1.00Q365.85 -14.00 311.85 -14.00Z"/><path transform="translate(192.05 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(204.25 35.00) scale(0.01400 -0.01400)" d="M19.75 0.00 211.62 700.00H421.33L613.20 0.00H489.27L447.42 159.60H185.53L143.68 0.00ZM214.25 270.40H418.70L324.95 624.87H308.00Z"/><path transform="translate(216.31 35.00) scale(0.01400 -0.01400)" d="M233.95 0.00V590.85H24.70V700.00H563.30V590.85H354.05V0.00Z"/><path transform="translate(227.75 35.00) scale(0.01400 -0.01400)" d="M332.35 -14.00Q203.57 -14.00 128.01 58.50Q52.45 131.00 52.45 266.87V433.13Q52.45 569.00 128.01 641.50Q203.57 714.00 332.35 714.00Q460.13 714.00 529.58 643.85Q599.03 573.70 599.03 451.57V445.75H480.57V455.22Q480.57 521.42 444.15 563.96Q407.72 606.50 332.35 606.50Q257.63 606.50 215.09 560.70Q172.55 514.90 172.55 435.13V264.87Q172.55 185.93 215.09 139.71Q257.63 93.50 332.35 93.50Q407.72 93.50 444.15 136.45Q480.57 179.40 480.57 244.78V262.25H599.03V248.43Q599.03 126.30 529.58 56.15Q460.13 -14.00 332.35 -14.00Z"/><path transform="translate(239.95 35.00) scale(0.01400 -0.01400)" d="M69.50 0.00V700.00H189.60V405.58H466.40V700.00H586.50V0.00H466.40V296.42H189.60V0.00Z"/></g></svg>', In = [
|
|
1198
|
+
{ value: "light", label: "Light", icon: O.sun },
|
|
1199
|
+
{ value: "dark", label: "Dark", icon: O.moon },
|
|
1200
|
+
{ value: "auto", label: "System default", icon: O.auto }
|
|
1201
|
+
], Mn = "bugcatch:theme";
|
|
1202
|
+
function oo() {
|
|
1203
1203
|
try {
|
|
1204
|
-
const t = localStorage.getItem(
|
|
1205
|
-
return
|
|
1204
|
+
const t = localStorage.getItem(Mn);
|
|
1205
|
+
return In.some((e) => e.value === t) ? t : null;
|
|
1206
1206
|
} catch {
|
|
1207
1207
|
return null;
|
|
1208
1208
|
}
|
|
1209
1209
|
}
|
|
1210
|
-
function
|
|
1210
|
+
function ro(t) {
|
|
1211
1211
|
try {
|
|
1212
|
-
localStorage.setItem(
|
|
1212
|
+
localStorage.setItem(Mn, t);
|
|
1213
1213
|
} catch {
|
|
1214
1214
|
}
|
|
1215
1215
|
}
|
|
1216
|
-
const
|
|
1216
|
+
const io = (t) => `
|
|
1217
1217
|
:host { all: initial; }
|
|
1218
1218
|
:host {
|
|
1219
1219
|
--bc-accent: ${t};
|
|
@@ -1747,6 +1747,36 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
1747
1747
|
.att .file .nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1748
1748
|
.att .file .sz { flex: none; color: var(--bc-faint); font-size: 11px; }
|
|
1749
1749
|
|
|
1750
|
+
/* The assistant's live card, above the conversation. */
|
|
1751
|
+
.assistant { margin: 8px 12px 4px; padding: 10px 12px; border-radius: 12px; border: 1px solid var(--bc-border); background: var(--bc-subtle); }
|
|
1752
|
+
.assistant.analyzing, .assistant.confirming, .assistant.needs_info { border-color: color-mix(in srgb, var(--bc-accent) 45%, transparent); }
|
|
1753
|
+
.as-top { display: flex; gap: 10px; align-items: flex-start; }
|
|
1754
|
+
.as-orb { flex: none; width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; color: #fff; font-size: 12px; background: var(--bc-accent); }
|
|
1755
|
+
.as-spin { width: 14px; height: 14px; border-radius: 50%; border: 2px solid rgba(255,255,255,.4); border-top-color: #fff; animation: as-rot .8s linear infinite; }
|
|
1756
|
+
@keyframes as-rot { to { transform: rotate(360deg); } }
|
|
1757
|
+
.as-title { font-weight: 600; font-size: 14px; }
|
|
1758
|
+
.assistant.analyzing .as-title::after { content: ''; animation: as-dots 1.4s steps(4) infinite; }
|
|
1759
|
+
@keyframes as-dots { 0% { content: ''; } 25% { content: '.'; } 50% { content: '..'; } 75% { content: '...'; } }
|
|
1760
|
+
.as-detail { font-size: 12.5px; color: var(--bc-muted); margin-top: 2px; }
|
|
1761
|
+
.as-steps { list-style: none; display: flex; gap: 6px; margin: 10px 0 0; padding: 0; flex-wrap: wrap; font-size: 11.5px; color: var(--bc-muted); }
|
|
1762
|
+
.as-steps li { display: flex; align-items: center; gap: 4px; }
|
|
1763
|
+
.as-steps li span { width: 8px; height: 8px; border-radius: 50%; border: 1.5px solid currentColor; }
|
|
1764
|
+
.as-steps li.done { color: var(--bc-accent); }
|
|
1765
|
+
.as-steps li.done span { background: var(--bc-accent); border-color: var(--bc-accent); }
|
|
1766
|
+
.as-steps li.active { color: var(--bc-fg); font-weight: 600; }
|
|
1767
|
+
.as-steps li.active span { border-color: var(--bc-accent); animation: as-pulse 1s ease-in-out infinite; }
|
|
1768
|
+
@keyframes as-pulse { 50% { box-shadow: 0 0 0 4px color-mix(in srgb, var(--bc-accent) 25%, transparent); } }
|
|
1769
|
+
@media (prefers-reduced-motion: reduce) { .as-spin, .as-steps li.active span, .assistant.analyzing .as-title::after { animation: none; } }
|
|
1770
|
+
|
|
1771
|
+
/* Quick answers under the confirm question — only on the latest message. */
|
|
1772
|
+
.msg-row .quick { display: none; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
|
|
1773
|
+
.msg-row:last-child .quick { display: flex; }
|
|
1774
|
+
.quick button {
|
|
1775
|
+
font: inherit; font-size: 13px; padding: 6px 12px; border-radius: 999px; cursor: pointer;
|
|
1776
|
+
border: 1px solid var(--bc-accent); background: transparent; color: var(--bc-accent);
|
|
1777
|
+
}
|
|
1778
|
+
.quick button:hover { background: color-mix(in srgb, var(--bc-accent) 12%, transparent); }
|
|
1779
|
+
|
|
1750
1780
|
/* ---------- the composer ---------- */
|
|
1751
1781
|
.composer {
|
|
1752
1782
|
position: sticky; bottom: 0; margin-top: auto;
|
|
@@ -1983,63 +2013,63 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
1983
2013
|
.tool:hover, .themer button:hover { border-color: var(--bc-border); }
|
|
1984
2014
|
}
|
|
1985
2015
|
`;
|
|
1986
|
-
function
|
|
2016
|
+
function so(t) {
|
|
1987
2017
|
const e = document.createElement("div");
|
|
1988
2018
|
e.setAttribute("data-bugcatch", "widget");
|
|
1989
|
-
let n =
|
|
1990
|
-
e.className =
|
|
1991
|
-
const
|
|
1992
|
-
i.textContent =
|
|
1993
|
-
const r =
|
|
1994
|
-
s.className = `dock ${r.includes("right") ? "at-right" : "at-left"}` + (r.startsWith("top") ? " at-top" : ""), s.style.cssText =
|
|
2019
|
+
let n = oo() || co(t.config.theme);
|
|
2020
|
+
e.className = rn(n);
|
|
2021
|
+
const a = e.attachShadow({ mode: "open" }), i = document.createElement("style");
|
|
2022
|
+
i.textContent = io(t.config.accent || "#4F46E5"), a.appendChild(i);
|
|
2023
|
+
const r = an[t.config.widgetPosition] ? t.config.widgetPosition : "bottom-right", s = document.createElement("div");
|
|
2024
|
+
s.className = `dock ${r.includes("right") ? "at-right" : "at-left"}` + (r.startsWith("top") ? " at-top" : ""), s.style.cssText = an[r];
|
|
1995
2025
|
const l = document.createElement("div");
|
|
1996
|
-
l.className = "themer", l.setAttribute("role", "group"), l.setAttribute("aria-label", "Report widget theme"), l.innerHTML =
|
|
1997
|
-
const
|
|
1998
|
-
!
|
|
2026
|
+
l.className = "themer", l.setAttribute("role", "group"), l.setAttribute("aria-label", "Report widget theme"), l.innerHTML = In.map((y) => `<button type="button" data-theme="${y.value}" title="${y.label}" aria-label="${y.label}" aria-pressed="${y.value === n}">${y.icon}</button>`).join(""), l.addEventListener("click", (y) => {
|
|
2027
|
+
const h = y.target.closest("button[data-theme]");
|
|
2028
|
+
!h || h.dataset.theme === n || (n = h.dataset.theme, e.className = rn(n), ro(n), l.querySelectorAll("button").forEach((b) => {
|
|
1999
2029
|
b.setAttribute("aria-pressed", String(b.dataset.theme === n));
|
|
2000
2030
|
}));
|
|
2001
2031
|
});
|
|
2002
|
-
const
|
|
2003
|
-
|
|
2004
|
-
let
|
|
2005
|
-
return
|
|
2006
|
-
if (
|
|
2007
|
-
|
|
2032
|
+
const p = document.createElement("button");
|
|
2033
|
+
p.className = "launcher", p.type = "button", p.innerHTML = `${O.bug}<span>Report a bug</span>`, p.setAttribute("aria-haspopup", "dialog"), p.setAttribute("aria-expanded", "false");
|
|
2034
|
+
let f = null;
|
|
2035
|
+
return p.addEventListener("click", () => {
|
|
2036
|
+
if (f) {
|
|
2037
|
+
f.close();
|
|
2008
2038
|
return;
|
|
2009
2039
|
}
|
|
2010
|
-
s.classList.add("over"),
|
|
2011
|
-
root:
|
|
2040
|
+
s.classList.add("over"), p.setAttribute("aria-expanded", "true"), f = lo({
|
|
2041
|
+
root: a,
|
|
2012
2042
|
host: e,
|
|
2013
2043
|
dock: s,
|
|
2014
2044
|
client: t,
|
|
2015
2045
|
onClose: () => {
|
|
2016
|
-
|
|
2046
|
+
f = null, s.classList.remove("over"), p.setAttribute("aria-expanded", "false");
|
|
2017
2047
|
}
|
|
2018
2048
|
});
|
|
2019
|
-
}), s.append(l,
|
|
2020
|
-
|
|
2049
|
+
}), s.append(l, p), a.appendChild(s), document.body.appendChild(e), () => {
|
|
2050
|
+
f == null || f.destroy(), e.remove();
|
|
2021
2051
|
};
|
|
2022
2052
|
}
|
|
2023
|
-
function
|
|
2053
|
+
function co(t) {
|
|
2024
2054
|
return t === "dark" || t === "light" ? t : "auto";
|
|
2025
2055
|
}
|
|
2026
|
-
function
|
|
2056
|
+
function rn(t) {
|
|
2027
2057
|
return t === "dark" ? "bc-dark" : t === "light" ? "bc-light" : "bc-auto";
|
|
2028
2058
|
}
|
|
2029
|
-
function
|
|
2030
|
-
var
|
|
2031
|
-
const r =
|
|
2032
|
-
let
|
|
2033
|
-
const
|
|
2034
|
-
|
|
2059
|
+
function lo({ root: t, host: e, dock: n, client: a, onClose: i }) {
|
|
2060
|
+
var Ut, Vt, Kt, Pt, _t, Ft;
|
|
2061
|
+
const r = a.config, s = r.attachments !== !1, l = s && ua(), p = s && da(), f = [];
|
|
2062
|
+
let y = "MEDIUM", h = null, b = !1;
|
|
2063
|
+
const g = document.createElement("div");
|
|
2064
|
+
g.className = `scrim ${n.classList.contains("at-left") ? "at-left" : "at-right"} ${n.classList.contains("at-top") ? "at-top" : "at-bottom"}`, g.style.setProperty("--bc-dock-h", `${Math.round(n.getBoundingClientRect().height)}px`), g.innerHTML = `
|
|
2035
2065
|
<div class="panel" role="dialog" aria-modal="true" aria-labelledby="bc-h">
|
|
2036
2066
|
<div class="head">
|
|
2037
|
-
<div class="mark">${
|
|
2067
|
+
<div class="mark">${O.bug}</div>
|
|
2038
2068
|
<div class="titles">
|
|
2039
2069
|
<h2 id="bc-h">Report a bug</h2>
|
|
2040
2070
|
<p>We'll attach what the page was doing, so you don't have to explain it.</p>
|
|
2041
2071
|
</div>
|
|
2042
|
-
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${
|
|
2072
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${O.close}</button>
|
|
2043
2073
|
</div>
|
|
2044
2074
|
<div class="body">
|
|
2045
2075
|
<div class="slot"></div>
|
|
@@ -2062,8 +2092,8 @@ function sa({ root: t, host: e, dock: n, client: o, onClose: i }) {
|
|
|
2062
2092
|
<div class="field">
|
|
2063
2093
|
<label id="bc-prio-l">Severity</label>
|
|
2064
2094
|
<div class="seg" role="group" aria-labelledby="bc-prio-l">
|
|
2065
|
-
${
|
|
2066
|
-
<button type="button" data-prio="${
|
|
2095
|
+
${on.map((o) => `
|
|
2096
|
+
<button type="button" data-prio="${o.value}" aria-pressed="${o.value === y}">${o.label}</button>
|
|
2067
2097
|
`).join("")}
|
|
2068
2098
|
</div>
|
|
2069
2099
|
</div>
|
|
@@ -2071,20 +2101,20 @@ function sa({ root: t, host: e, dock: n, client: o, onClose: i }) {
|
|
|
2071
2101
|
<div class="field">
|
|
2072
2102
|
<label>Attach <span style="font-weight:450;color:var(--bc-faint)">(optional)</span></label>
|
|
2073
2103
|
<div class="tools">
|
|
2074
|
-
${l ? `<button class="tool" type="button" data-act="shot">${
|
|
2075
|
-
${
|
|
2076
|
-
<button class="tool" type="button" data-act="file">${
|
|
2104
|
+
${l ? `<button class="tool" type="button" data-act="shot">${O.camera}Screenshot</button>` : ""}
|
|
2105
|
+
${p ? `<button class="tool" type="button" data-act="rec">${O.video}Record</button>` : ""}
|
|
2106
|
+
<button class="tool" type="button" data-act="file">${O.paperclip}File</button>
|
|
2077
2107
|
</div>
|
|
2078
2108
|
<div class="thumbs"></div>
|
|
2079
|
-
<input type="file" accept="${
|
|
2109
|
+
<input type="file" accept="${tt.join(",")}" multiple hidden />
|
|
2080
2110
|
</div>` : ""}
|
|
2081
2111
|
</div>
|
|
2082
2112
|
</div>
|
|
2083
2113
|
<div class="foot">
|
|
2084
|
-
<a class="brand-credit" href="https://bugcatch.sphoro.com" target="_blank" rel="noopener noreferrer" aria-label="BugCatch">${
|
|
2114
|
+
<a class="brand-credit" href="https://bugcatch.sphoro.com" target="_blank" rel="noopener noreferrer" aria-label="BugCatch">${ao}</a>
|
|
2085
2115
|
<span class="note"></span>
|
|
2086
2116
|
<span class="spacer"></span>
|
|
2087
|
-
${
|
|
2117
|
+
${a.hasReports() ? '<button class="ghost" type="button" data-act="history">Your reports</button>' : ""}
|
|
2088
2118
|
<button class="ghost" type="button" data-act="cancel">Cancel</button>
|
|
2089
2119
|
<!-- Hidden until the API confirms this project can take a call, which
|
|
2090
2120
|
most cannot. Drawn here rather than as a second launcher because it
|
|
@@ -2094,40 +2124,40 @@ function sa({ root: t, host: e, dock: n, client: o, onClose: i }) {
|
|
|
2094
2124
|
<button class="primary" type="button" data-act="send">Send report</button>
|
|
2095
2125
|
</div>
|
|
2096
2126
|
</div>`;
|
|
2097
|
-
const
|
|
2098
|
-
ee.setAttribute("role", "status"), ee.className = "note",
|
|
2099
|
-
const ze =
|
|
2100
|
-
let be = r.drafts === !1, Ue = !1,
|
|
2127
|
+
const S = (o) => g.querySelector(o), A = S("#bc-title"), ae = S(".slot"), C = S(".thumbs"), $ = g.querySelector("input[type=file]"), T = S('[data-act="send"]'), L = S('[data-act="call"]'), Y = S(".note"), N = S(".compose"), Q = S(".whoami"), U = S(".refs"), E = S(".known"), oe = S('[data-act="history"]'), ee = document.createElement("div");
|
|
2128
|
+
ee.setAttribute("role", "status"), ee.className = "note", N.prepend(ee);
|
|
2129
|
+
const ze = wa(r, (Ut = he(r.projectId)) == null ? void 0 : Ut.email);
|
|
2130
|
+
let be = r.drafts === !1, Ue = !1, ye = Promise.resolve(), V;
|
|
2101
2131
|
function te() {
|
|
2102
|
-
if (clearTimeout(
|
|
2103
|
-
const
|
|
2132
|
+
if (clearTimeout(V), !be || Ue || r.drafts === !1) return ye;
|
|
2133
|
+
const o = A.value || S("#bc-desc").value || f.length ? {
|
|
2104
2134
|
title: A.value,
|
|
2105
|
-
description:
|
|
2106
|
-
priority:
|
|
2107
|
-
items:
|
|
2135
|
+
description: S("#bc-desc").value,
|
|
2136
|
+
priority: y,
|
|
2137
|
+
items: f.map(({ blob: c, mime: u, kind: d }) => ({ blob: c, mime: u, kind: d }))
|
|
2108
2138
|
} : null;
|
|
2109
|
-
return
|
|
2110
|
-
}).then(() =>
|
|
2111
|
-
ee.textContent =
|
|
2139
|
+
return ye = ye.catch(() => {
|
|
2140
|
+
}).then(() => at(ze, o)).then(() => {
|
|
2141
|
+
ee.textContent = o ? "Draft saved on this device" : "";
|
|
2112
2142
|
}).catch(() => {
|
|
2113
2143
|
ee.textContent = "Draft could not be saved. Keep this tab open.";
|
|
2114
|
-
}),
|
|
2144
|
+
}), ye;
|
|
2115
2145
|
}
|
|
2116
|
-
function
|
|
2117
|
-
clearTimeout(
|
|
2146
|
+
function Ee() {
|
|
2147
|
+
clearTimeout(V), V = setTimeout(te, 250);
|
|
2118
2148
|
}
|
|
2119
|
-
|
|
2149
|
+
N.addEventListener("input", Ee), N.addEventListener("change", Ee);
|
|
2120
2150
|
const Ve = () => {
|
|
2121
2151
|
te();
|
|
2122
2152
|
};
|
|
2123
2153
|
window.addEventListener("pagehide", Ve);
|
|
2124
2154
|
function Oe() {
|
|
2125
|
-
|
|
2155
|
+
f.filter((o) => o.status === "failed").forEach(Le);
|
|
2126
2156
|
}
|
|
2127
|
-
window.addEventListener("online", Oe), r.drafts !== !1 && (
|
|
2128
|
-
Ie || !
|
|
2129
|
-
A.value =
|
|
2130
|
-
for (const c of (
|
|
2157
|
+
window.addEventListener("online", Oe), r.drafts !== !1 && (N.inert = !0, va(ze).then((o) => {
|
|
2158
|
+
Ie || !o || (ee.innerHTML = 'Unfinished report on this device. <button type="button" data-resume>Resume report</button> <button type="button" data-discard>Discard</button>', ee.querySelector("[data-resume]").onclick = () => {
|
|
2159
|
+
A.value = o.title || "", S("#bc-desc").value = o.description || "", y = on.some((c) => c.value === o.priority) ? o.priority : "MEDIUM", g.querySelectorAll("[data-prio]").forEach((c) => c.setAttribute("aria-pressed", String(c.dataset.prio === y)));
|
|
2160
|
+
for (const c of (o.items || []).slice(0, r.maxAttachments ?? 5)) ve(c);
|
|
2131
2161
|
be = !0, te();
|
|
2132
2162
|
}, ee.querySelector("[data-discard]").onclick = () => {
|
|
2133
2163
|
be = !0, te();
|
|
@@ -2135,415 +2165,415 @@ function sa({ root: t, host: e, dock: n, client: o, onClose: i }) {
|
|
|
2135
2165
|
}).catch(() => {
|
|
2136
2166
|
ee.textContent = "Draft storage is unavailable. Keep this tab open.";
|
|
2137
2167
|
}).finally(() => {
|
|
2138
|
-
|
|
2168
|
+
N.inert = !1, ee.querySelector("[data-resume]") || (be = !0);
|
|
2139
2169
|
}));
|
|
2140
|
-
const
|
|
2170
|
+
const fe = document.activeElement, Te = document.documentElement.style, lt = Te.overflow;
|
|
2141
2171
|
Te.overflow = "hidden";
|
|
2142
|
-
let Ie = !1,
|
|
2172
|
+
let Ie = !1, we = null;
|
|
2143
2173
|
function He() {
|
|
2144
|
-
var
|
|
2145
|
-
Ie || (te(), Ie = !0, clearTimeout(
|
|
2174
|
+
var o;
|
|
2175
|
+
Ie || (te(), Ie = !0, clearTimeout(V), window.removeEventListener("pagehide", Ve), window.removeEventListener("online", Oe), h == null || h.cancel(), we == null || we(), f.forEach((c) => c.previewUrl && URL.revokeObjectURL(c.previewUrl)), Te.overflow = lt, document.removeEventListener("keydown", Me, !0), g.remove(), (o = t.querySelector(".recbar")) == null || o.remove(), n.hidden = !1, e.style.opacity = "", i == null || i());
|
|
2146
2176
|
}
|
|
2147
2177
|
function re() {
|
|
2148
|
-
var
|
|
2178
|
+
var o;
|
|
2149
2179
|
if (!Ie) {
|
|
2150
|
-
|
|
2180
|
+
g.classList.add("closing"), setTimeout(He, 160);
|
|
2151
2181
|
try {
|
|
2152
|
-
(
|
|
2182
|
+
(o = fe == null ? void 0 : fe.focus) == null || o.call(fe);
|
|
2153
2183
|
} catch {
|
|
2154
2184
|
}
|
|
2155
2185
|
}
|
|
2156
2186
|
}
|
|
2157
|
-
function Me(
|
|
2158
|
-
if (
|
|
2159
|
-
if (
|
|
2187
|
+
function Me(o) {
|
|
2188
|
+
if (o.key === "Escape") {
|
|
2189
|
+
if (o.stopPropagation(), h) {
|
|
2160
2190
|
Be({ keep: !1 });
|
|
2161
2191
|
return;
|
|
2162
2192
|
}
|
|
2163
2193
|
b || re();
|
|
2164
2194
|
return;
|
|
2165
2195
|
}
|
|
2166
|
-
if (
|
|
2167
|
-
const c = [...
|
|
2196
|
+
if (o.key !== "Tab" || h) return;
|
|
2197
|
+
const c = [...g.querySelectorAll(
|
|
2168
2198
|
"button:not(:disabled), input:not([hidden]), textarea, select, [href]"
|
|
2169
|
-
)].filter((
|
|
2199
|
+
)].filter((w) => w.offsetParent !== null || w === document.activeElement);
|
|
2170
2200
|
if (!c.length) return;
|
|
2171
|
-
const
|
|
2172
|
-
|
|
2173
|
-
}
|
|
2174
|
-
document.addEventListener("keydown", Me, !0),
|
|
2175
|
-
|
|
2176
|
-
}),
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
c.setAttribute("aria-pressed", String(c ===
|
|
2201
|
+
const u = c[0], d = c[c.length - 1], x = g.getRootNode().activeElement;
|
|
2202
|
+
o.shiftKey && x === u ? (o.preventDefault(), d.focus()) : !o.shiftKey && x === d && (o.preventDefault(), u.focus());
|
|
2203
|
+
}
|
|
2204
|
+
document.addEventListener("keydown", Me, !0), g.addEventListener("click", (o) => {
|
|
2205
|
+
o.target === g && !b && re();
|
|
2206
|
+
}), S('[data-act="close"]').addEventListener("click", re), S('[data-act="cancel"]').addEventListener("click", re), g.querySelectorAll("[data-prio]").forEach((o) => {
|
|
2207
|
+
o.addEventListener("click", () => {
|
|
2208
|
+
y = o.dataset.prio, Ee(), g.querySelectorAll("[data-prio]").forEach((c) => {
|
|
2209
|
+
c.setAttribute("aria-pressed", String(c === o));
|
|
2180
2210
|
});
|
|
2181
2211
|
});
|
|
2182
2212
|
});
|
|
2183
|
-
function
|
|
2184
|
-
|
|
2213
|
+
function H(o, c = "err") {
|
|
2214
|
+
ae.innerHTML = o ? `<div class="msg ${c}">${k(o)}</div>` : "";
|
|
2185
2215
|
}
|
|
2186
2216
|
function ce() {
|
|
2187
|
-
const
|
|
2188
|
-
T.disabled = b ||
|
|
2189
|
-
c.disabled = b ||
|
|
2217
|
+
const o = f.some((c) => c.status === "uploading");
|
|
2218
|
+
T.disabled = b || o || f.some((c) => c.status === "failed"), Y.textContent = o ? "Waiting for the upload to finish…" : f.some((c) => c.status === "failed") ? "Retry or remove failed attachments before sending." : "", g.querySelectorAll(".tool").forEach((c) => {
|
|
2219
|
+
c.disabled = b || f.length >= (r.maxAttachments ?? 5);
|
|
2190
2220
|
});
|
|
2191
2221
|
}
|
|
2192
|
-
function Ke(
|
|
2193
|
-
var
|
|
2194
|
-
const c =
|
|
2195
|
-
let
|
|
2196
|
-
|
|
2197
|
-
${
|
|
2198
|
-
<span class="kind">${
|
|
2199
|
-
<button class="drop" type="button" data-act="drop" aria-label="Remove ${
|
|
2200
|
-
${
|
|
2201
|
-
}
|
|
2202
|
-
function
|
|
2203
|
-
const c =
|
|
2204
|
-
c >= 0 &&
|
|
2205
|
-
}
|
|
2206
|
-
async function Le(
|
|
2207
|
-
|
|
2222
|
+
function Ke(o) {
|
|
2223
|
+
var w;
|
|
2224
|
+
const c = o.el, u = o.kind === "VIDEO" ? "Video" : "Shot", d = o.kind === "VIDEO" ? `<video src="${o.previewUrl}" muted playsinline preload="metadata"></video>` : `<img src="${o.previewUrl}" alt="" />`;
|
|
2225
|
+
let x = "";
|
|
2226
|
+
o.status === "uploading" ? x = `<div class="veil"><div class="spinner"></div><div class="bar"><i style="width:${Math.round(o.progress * 100)}%"></i></div></div>` : o.status === "failed" && (x = `<div class="veil err"><button type="button" data-act="retry" aria-label="Retry upload">${O.retry}</button>Failed</div>`), c.innerHTML = `
|
|
2227
|
+
${d}
|
|
2228
|
+
<span class="kind">${u} · ${je(o.size)}</span>
|
|
2229
|
+
<button class="drop" type="button" data-act="drop" aria-label="Remove ${u.toLowerCase()}">${O.close}</button>
|
|
2230
|
+
${x}`, c.querySelector('[data-act="drop"]').addEventListener("click", () => dt(o)), (w = c.querySelector('[data-act="retry"]')) == null || w.addEventListener("click", () => Le(o));
|
|
2231
|
+
}
|
|
2232
|
+
function dt(o) {
|
|
2233
|
+
const c = f.indexOf(o);
|
|
2234
|
+
c >= 0 && f.splice(c, 1), o.previewUrl && URL.revokeObjectURL(o.previewUrl), o.el.remove(), te(), ce();
|
|
2235
|
+
}
|
|
2236
|
+
async function Le(o) {
|
|
2237
|
+
o.status = "uploading", o.progress = 0, Ke(o), ce();
|
|
2208
2238
|
try {
|
|
2209
|
-
const { storageKey: c, mime:
|
|
2210
|
-
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2239
|
+
const { storageKey: c, mime: u } = await a.uploadAttachment(o.blob, o.mime, (d) => {
|
|
2240
|
+
o.progress = d;
|
|
2241
|
+
const x = o.el.querySelector(".bar i");
|
|
2242
|
+
x && (x.style.width = `${Math.round(d * 100)}%`);
|
|
2213
2243
|
});
|
|
2214
|
-
|
|
2244
|
+
o.storageKey = c, o.mime = u, o.status = "ready";
|
|
2215
2245
|
} catch (c) {
|
|
2216
|
-
|
|
2246
|
+
o.status = "failed", H(c.message.replace("[BugCatch] ", ""));
|
|
2217
2247
|
}
|
|
2218
|
-
Ke(
|
|
2248
|
+
Ke(o), ce();
|
|
2219
2249
|
}
|
|
2220
|
-
function ve({ blob:
|
|
2221
|
-
const
|
|
2222
|
-
if (
|
|
2223
|
-
|
|
2250
|
+
function ve({ blob: o, mime: c, kind: u }) {
|
|
2251
|
+
const d = r.maxAttachmentBytes ?? 26214400;
|
|
2252
|
+
if (o.size > d) {
|
|
2253
|
+
H(`That file is ${je(o.size)} — the limit is ${je(d)}.`);
|
|
2224
2254
|
return;
|
|
2225
2255
|
}
|
|
2226
|
-
const
|
|
2227
|
-
if (!
|
|
2228
|
-
|
|
2256
|
+
const x = nt(c || o.type, tt);
|
|
2257
|
+
if (!x) {
|
|
2258
|
+
H("Only PNG, JPEG, WebP, WebM and MP4 files can be attached to a report.");
|
|
2229
2259
|
return;
|
|
2230
2260
|
}
|
|
2231
|
-
const
|
|
2232
|
-
blob:
|
|
2233
|
-
kind:
|
|
2234
|
-
mime:
|
|
2235
|
-
size:
|
|
2236
|
-
previewUrl: URL.createObjectURL(
|
|
2261
|
+
const w = {
|
|
2262
|
+
blob: o,
|
|
2263
|
+
kind: u,
|
|
2264
|
+
mime: x,
|
|
2265
|
+
size: o.size,
|
|
2266
|
+
previewUrl: URL.createObjectURL(o),
|
|
2237
2267
|
status: "uploading",
|
|
2238
2268
|
progress: 0,
|
|
2239
2269
|
storageKey: null,
|
|
2240
2270
|
el: document.createElement("div")
|
|
2241
2271
|
};
|
|
2242
|
-
|
|
2272
|
+
w.el.className = "thumb", f.push(w), C.appendChild(w.el), H(""), te(), Le(w);
|
|
2243
2273
|
}
|
|
2244
|
-
async function
|
|
2274
|
+
async function ut(o) {
|
|
2245
2275
|
e.style.opacity = "0", e.style.pointerEvents = "none", await new Promise((c) => requestAnimationFrame(() => requestAnimationFrame(c)));
|
|
2246
2276
|
try {
|
|
2247
|
-
return await
|
|
2277
|
+
return await o();
|
|
2248
2278
|
} finally {
|
|
2249
2279
|
e.style.opacity = "", e.style.pointerEvents = "";
|
|
2250
2280
|
}
|
|
2251
2281
|
}
|
|
2252
|
-
(
|
|
2282
|
+
(Vt = g.querySelector('[data-act="shot"]')) == null || Vt.addEventListener("click", async () => {
|
|
2253
2283
|
try {
|
|
2254
|
-
const
|
|
2255
|
-
ve(
|
|
2256
|
-
} catch (
|
|
2257
|
-
(
|
|
2284
|
+
const o = await ut(pa);
|
|
2285
|
+
ve(o);
|
|
2286
|
+
} catch (o) {
|
|
2287
|
+
(o == null ? void 0 : o.name) !== "NotAllowedError" && H(`Screenshot failed: ${o.message}`);
|
|
2258
2288
|
}
|
|
2259
|
-
}), (
|
|
2260
|
-
const
|
|
2261
|
-
[
|
|
2289
|
+
}), (Kt = g.querySelector('[data-act="file"]')) == null || Kt.addEventListener("click", () => $.click()), $ == null || $.addEventListener("change", () => {
|
|
2290
|
+
const o = (r.maxAttachments ?? 5) - f.length;
|
|
2291
|
+
[...$.files].slice(0, Math.max(o, 0)).forEach((c) => {
|
|
2262
2292
|
ve({
|
|
2263
2293
|
blob: c,
|
|
2264
2294
|
mime: c.type,
|
|
2265
2295
|
kind: c.type.startsWith("video/") ? "VIDEO" : "SCREENSHOT"
|
|
2266
2296
|
});
|
|
2267
|
-
}),
|
|
2268
|
-
}), (
|
|
2269
|
-
const
|
|
2297
|
+
}), $.value = "";
|
|
2298
|
+
}), (Pt = g.querySelector('[data-act="rec"]')) == null || Pt.addEventListener("click", async () => {
|
|
2299
|
+
const o = r.maxRecordingMs ?? 12e4;
|
|
2270
2300
|
let c;
|
|
2271
2301
|
try {
|
|
2272
|
-
|
|
2273
|
-
maxMs:
|
|
2274
|
-
onTick: (
|
|
2275
|
-
c && (c.querySelector(".time").textContent =
|
|
2302
|
+
h = await ha({
|
|
2303
|
+
maxMs: o,
|
|
2304
|
+
onTick: (u) => {
|
|
2305
|
+
c && (c.querySelector(".time").textContent = Ye(u));
|
|
2276
2306
|
},
|
|
2277
2307
|
onAutoStop: () => {
|
|
2278
|
-
|
|
2308
|
+
h && Be({ keep: !0 });
|
|
2279
2309
|
}
|
|
2280
2310
|
});
|
|
2281
|
-
} catch (
|
|
2282
|
-
(
|
|
2311
|
+
} catch (u) {
|
|
2312
|
+
(u == null ? void 0 : u.name) !== "NotAllowedError" && H(`Recording failed: ${u.message}`);
|
|
2283
2313
|
return;
|
|
2284
2314
|
}
|
|
2285
|
-
|
|
2315
|
+
g.style.display = "none", n.hidden = !0, c = document.createElement("div"), c.className = "recbar", c.innerHTML = `
|
|
2286
2316
|
<span class="dot"></span>
|
|
2287
2317
|
<span class="time">0:00</span>
|
|
2288
|
-
<span class="hint">Recording — up to ${
|
|
2318
|
+
<span class="hint">Recording — up to ${Ye(Math.round(o / 1e3))}</span>
|
|
2289
2319
|
<button class="stop" type="button">Stop</button>
|
|
2290
2320
|
<button class="ghost" type="button">Discard</button>`, c.querySelector(".stop").addEventListener("click", () => Be({ keep: !0 })), c.querySelector(".ghost").addEventListener("click", () => Be({ keep: !1 })), t.appendChild(c), c.querySelector(".stop").focus();
|
|
2291
2321
|
});
|
|
2292
|
-
async function Be({ keep:
|
|
2293
|
-
var
|
|
2294
|
-
const c =
|
|
2322
|
+
async function Be({ keep: o }) {
|
|
2323
|
+
var u;
|
|
2324
|
+
const c = h;
|
|
2295
2325
|
if (c) {
|
|
2296
|
-
if (
|
|
2326
|
+
if (h = null, (u = t.querySelector(".recbar")) == null || u.remove(), g.style.display = "", n.hidden = !1, !o) {
|
|
2297
2327
|
c.cancel(), A.focus();
|
|
2298
2328
|
return;
|
|
2299
2329
|
}
|
|
2300
2330
|
try {
|
|
2301
|
-
const
|
|
2302
|
-
|
|
2303
|
-
} catch (
|
|
2304
|
-
|
|
2331
|
+
const d = await c.stop();
|
|
2332
|
+
d.blob.size ? ve(d) : H("That recording came back empty — nothing was captured.");
|
|
2333
|
+
} catch (d) {
|
|
2334
|
+
H(`Recording failed: ${d.message}`);
|
|
2305
2335
|
}
|
|
2306
2336
|
A.focus();
|
|
2307
2337
|
}
|
|
2308
2338
|
}
|
|
2309
|
-
let m = { policy: "off", fields: [] },
|
|
2310
|
-
|
|
2311
|
-
m =
|
|
2339
|
+
let m = { policy: "off", fields: [] }, v = null, I = "", _ = "", F = !1, xe = !1;
|
|
2340
|
+
a.referenceFields().then((o) => {
|
|
2341
|
+
m = o;
|
|
2312
2342
|
}).catch(() => {
|
|
2313
2343
|
});
|
|
2314
2344
|
function Pe() {
|
|
2315
|
-
return m.policy === "off" || !m.fields.length ? [] :
|
|
2345
|
+
return m.policy === "off" || !m.fields.length ? [] : eo(m.fields, [A.value, S("#bc-desc").value]);
|
|
2316
2346
|
}
|
|
2317
2347
|
function ke() {
|
|
2318
|
-
return !
|
|
2348
|
+
return !v || !I.trim() ? [] : [{ key: v, value: I.trim().slice(0, 120) }];
|
|
2319
2349
|
}
|
|
2320
|
-
function
|
|
2321
|
-
var
|
|
2322
|
-
if (!
|
|
2323
|
-
|
|
2350
|
+
function pe() {
|
|
2351
|
+
var d, x;
|
|
2352
|
+
if (!v) {
|
|
2353
|
+
U.hidden = !0, U.innerHTML = "";
|
|
2324
2354
|
return;
|
|
2325
2355
|
}
|
|
2326
|
-
const
|
|
2327
|
-
|
|
2328
|
-
<p class="why">${
|
|
2356
|
+
const o = m.fields.find((w) => w.key === v) || m.fields[0], c = m.policy !== "required";
|
|
2357
|
+
U.hidden = !1, U.innerHTML = `
|
|
2358
|
+
<p class="why">${k(
|
|
2329
2359
|
c ? "One more thing, so we can find your record — this helps us answer faster." : "We need one of these to look this up."
|
|
2330
2360
|
)}</p>
|
|
2331
2361
|
<div class="row">
|
|
2332
2362
|
${m.fields.length > 1 ? `
|
|
2333
2363
|
<select class="ref-kind" aria-label="Which detail you are giving">
|
|
2334
|
-
${m.fields.map((
|
|
2335
|
-
<option value="${
|
|
2364
|
+
${m.fields.map((w) => `
|
|
2365
|
+
<option value="${k(w.key)}" ${w.key === o.key ? "selected" : ""}>${k(w.label)}</option>
|
|
2336
2366
|
`).join("")}
|
|
2337
2367
|
</select>` : ""}
|
|
2338
|
-
<input class="ref-value" type="${
|
|
2339
|
-
inputmode="${
|
|
2340
|
-
value="${
|
|
2341
|
-
placeholder="${
|
|
2342
|
-
aria-label="${
|
|
2368
|
+
<input class="ref-value" type="${o.inputMode === "email" ? "email" : "text"}"
|
|
2369
|
+
inputmode="${k(o.inputMode === "numeric" || o.inputMode === "tel" ? "numeric" : "text")}"
|
|
2370
|
+
value="${k(I)}"
|
|
2371
|
+
placeholder="${k(o.placeholder || "")}"
|
|
2372
|
+
aria-label="${k(o.label)}" />
|
|
2343
2373
|
</div>
|
|
2344
|
-
${
|
|
2345
|
-
${
|
|
2374
|
+
${o.hint ? `<p class="hint">${k(o.hint)}</p>` : ""}
|
|
2375
|
+
${_ ? `<p class="after err">${k(_)}</p>` : ""}
|
|
2346
2376
|
${c ? `<button type="button" class="link" data-act="ref-skip">I don't have this</button>` : ""}`;
|
|
2347
|
-
const
|
|
2348
|
-
|
|
2349
|
-
I =
|
|
2350
|
-
}),
|
|
2351
|
-
|
|
2352
|
-
}), (
|
|
2353
|
-
var
|
|
2354
|
-
|
|
2355
|
-
}), (
|
|
2356
|
-
|
|
2357
|
-
}),
|
|
2358
|
-
}
|
|
2359
|
-
function
|
|
2360
|
-
return m.policy === "off" || !m.fields.length || Pe().length || ke().length ? !1 : !
|
|
2377
|
+
const u = U.querySelector(".ref-value");
|
|
2378
|
+
u.addEventListener("input", () => {
|
|
2379
|
+
I = u.value, _ = "", xe = !1;
|
|
2380
|
+
}), u.addEventListener("keydown", (w) => {
|
|
2381
|
+
w.key === "Enter" && (w.preventDefault(), T.click());
|
|
2382
|
+
}), (d = U.querySelector(".ref-kind")) == null || d.addEventListener("change", (w) => {
|
|
2383
|
+
var j;
|
|
2384
|
+
v = w.target.value, _ = "", pe(), (j = U.querySelector(".ref-value")) == null || j.focus();
|
|
2385
|
+
}), (x = U.querySelector('[data-act="ref-skip"]')) == null || x.addEventListener("click", () => {
|
|
2386
|
+
F = !0, v = null, I = "", _ = "", xe = !1, pe(), H("");
|
|
2387
|
+
}), u.focus();
|
|
2388
|
+
}
|
|
2389
|
+
function Hn() {
|
|
2390
|
+
return m.policy === "off" || !m.fields.length || Pe().length || ke().length ? !1 : !F || m.policy === "required";
|
|
2361
2391
|
}
|
|
2362
2392
|
T.addEventListener("click", async () => {
|
|
2363
|
-
const
|
|
2364
|
-
if (!
|
|
2365
|
-
|
|
2393
|
+
const o = A.value;
|
|
2394
|
+
if (!o.trim()) {
|
|
2395
|
+
H("Please describe what went wrong."), A.classList.add("invalid"), A.focus(), setTimeout(() => A.classList.remove("invalid"), 500);
|
|
2366
2396
|
return;
|
|
2367
2397
|
}
|
|
2368
|
-
if (
|
|
2369
|
-
|
|
2398
|
+
if (Hn()) {
|
|
2399
|
+
v = v || m.fields[0].key, pe(), H("");
|
|
2370
2400
|
return;
|
|
2371
2401
|
}
|
|
2372
|
-
if (
|
|
2373
|
-
const
|
|
2374
|
-
if (!xe &&
|
|
2375
|
-
|
|
2402
|
+
if (v && I.trim()) {
|
|
2403
|
+
const u = m.fields.find((d) => d.key === v);
|
|
2404
|
+
if (!xe && u && !to(u, I)) {
|
|
2405
|
+
_ = `That does not look like a ${u.label.toLowerCase()}. Press Send again to use it anyway.`, xe = !0, pe();
|
|
2376
2406
|
return;
|
|
2377
2407
|
}
|
|
2378
2408
|
}
|
|
2379
|
-
b = !0,
|
|
2409
|
+
b = !0, H(""), ce();
|
|
2380
2410
|
const c = T.innerHTML;
|
|
2381
2411
|
T.innerHTML = '<span class="spinner"></span>Sending…';
|
|
2382
2412
|
try {
|
|
2383
|
-
const
|
|
2384
|
-
title:
|
|
2385
|
-
description:
|
|
2386
|
-
priority:
|
|
2413
|
+
const u = await a.report({
|
|
2414
|
+
title: o,
|
|
2415
|
+
description: S("#bc-desc").value,
|
|
2416
|
+
priority: y,
|
|
2387
2417
|
references: ke(),
|
|
2388
|
-
attachments:
|
|
2418
|
+
attachments: f.filter((d) => d.status === "ready").map((d) => ({ type: d.kind, storageKey: d.storageKey, mime: d.mime }))
|
|
2389
2419
|
});
|
|
2390
|
-
if (
|
|
2420
|
+
if (u != null && u.cancelled) {
|
|
2391
2421
|
b = !1, T.innerHTML = c, ce();
|
|
2392
2422
|
return;
|
|
2393
2423
|
}
|
|
2394
|
-
Ue = !0, clearTimeout(
|
|
2395
|
-
}),
|
|
2396
|
-
} catch (
|
|
2397
|
-
b = !1, T.innerHTML = c,
|
|
2424
|
+
Ue = !0, clearTimeout(V), await ye, r.drafts !== !1 && await at(ze, null).catch(() => {
|
|
2425
|
+
}), zt(u);
|
|
2426
|
+
} catch (u) {
|
|
2427
|
+
b = !1, T.innerHTML = c, H(u.message.replace("[BugCatch] ", "")), ce(), X.mode !== "off" && gt().catch(() => {
|
|
2398
2428
|
});
|
|
2399
2429
|
}
|
|
2400
|
-
}), (
|
|
2401
|
-
let Ae = [], _e = "",
|
|
2402
|
-
function
|
|
2403
|
-
r.knownIssues !== !1 &&
|
|
2404
|
-
Ae =
|
|
2430
|
+
}), (_t = g.querySelector('[data-act="history"]')) == null || _t.addEventListener("click", Ht);
|
|
2431
|
+
let Ae = [], _e = "", pt = null, qe = null;
|
|
2432
|
+
function Bt() {
|
|
2433
|
+
r.knownIssues !== !1 && a.knownIssues().then((o) => {
|
|
2434
|
+
Ae = o, De();
|
|
2405
2435
|
}).catch(() => {
|
|
2406
2436
|
});
|
|
2407
2437
|
}
|
|
2408
|
-
let
|
|
2409
|
-
function
|
|
2438
|
+
let At = null;
|
|
2439
|
+
function qn(o) {
|
|
2410
2440
|
if (r.knownIssues === !1) return;
|
|
2411
|
-
clearTimeout(
|
|
2412
|
-
const c = (
|
|
2441
|
+
clearTimeout(At), qe == null || qe.abort();
|
|
2442
|
+
const c = (o || "").trim();
|
|
2413
2443
|
if (c.length < 3) {
|
|
2414
|
-
|
|
2444
|
+
Bt();
|
|
2415
2445
|
return;
|
|
2416
2446
|
}
|
|
2417
|
-
|
|
2418
|
-
qe = new AbortController(),
|
|
2419
|
-
|
|
2447
|
+
At = setTimeout(() => {
|
|
2448
|
+
qe = new AbortController(), a.matchKnownIssues(c, { signal: qe.signal }).then((u) => {
|
|
2449
|
+
u.length && (Ae = u, De());
|
|
2420
2450
|
}).catch(() => {
|
|
2421
2451
|
});
|
|
2422
2452
|
}, 250);
|
|
2423
2453
|
}
|
|
2424
2454
|
function De() {
|
|
2425
2455
|
if (!Ae.length) {
|
|
2426
|
-
|
|
2456
|
+
E.hidden = !0, E.innerHTML = "";
|
|
2427
2457
|
return;
|
|
2428
2458
|
}
|
|
2429
|
-
|
|
2459
|
+
E.hidden = !1, E.innerHTML = `
|
|
2430
2460
|
<p class="known-h">Already reported</p>
|
|
2431
|
-
${Ae.map((
|
|
2432
|
-
<div class="issue ${
|
|
2461
|
+
${Ae.map((o) => `
|
|
2462
|
+
<div class="issue ${o.joined ? "is-joined" : ""}">
|
|
2433
2463
|
<span class="who">
|
|
2434
|
-
<span class="t">${
|
|
2435
|
-
<span class="meta">${
|
|
2464
|
+
<span class="t">${k(o.title)}</span>
|
|
2465
|
+
<span class="meta">${k(Dn(o))}</span>
|
|
2436
2466
|
</span>
|
|
2437
|
-
<button class="join" type="button" data-join="${
|
|
2438
|
-
${
|
|
2467
|
+
<button class="join" type="button" data-join="${k(o.id)}"
|
|
2468
|
+
${o.joined ? "disabled" : ""}>${o.joined ? "Following" : "Me too"}</button>
|
|
2439
2469
|
</div>
|
|
2440
|
-
${
|
|
2470
|
+
${pt === o.id ? `
|
|
2441
2471
|
<div class="ask">
|
|
2442
2472
|
<input type="email" class="join-email" placeholder="you@example.com"
|
|
2443
2473
|
aria-label="Your email, so we can tell you when this is fixed" />
|
|
2444
|
-
<button class="ghost" type="button" data-join-confirm="${
|
|
2474
|
+
<button class="ghost" type="button" data-join-confirm="${k(o.id)}">Follow</button>
|
|
2445
2475
|
</div>` : ""}
|
|
2446
2476
|
`).join("")}
|
|
2447
|
-
${_e ? `<p class="err">${
|
|
2477
|
+
${_e ? `<p class="err">${k(_e)}</p>` : ""}`;
|
|
2448
2478
|
}
|
|
2449
|
-
function
|
|
2450
|
-
const c =
|
|
2451
|
-
return `${c} · reported ${
|
|
2479
|
+
function Dn(o) {
|
|
2480
|
+
const c = o.status === "IN_PROGRESS" ? "Being worked on now" : "Not fixed yet", u = o.affectedCount === 0 ? "" : ` · ${o.affectedCount} ${o.affectedCount === 1 ? "person has" : "people have"} said this is happening to them`;
|
|
2481
|
+
return `${c} · reported ${rt(o.since)}${u}`;
|
|
2452
2482
|
}
|
|
2453
|
-
|
|
2454
|
-
var
|
|
2455
|
-
const c =
|
|
2456
|
-
if (!c && !
|
|
2457
|
-
const
|
|
2483
|
+
E.addEventListener("click", async (o) => {
|
|
2484
|
+
var w, j, z, q, G;
|
|
2485
|
+
const c = o.target.closest("[data-join]"), u = o.target.closest("[data-join-confirm]");
|
|
2486
|
+
if (!c && !u) return;
|
|
2487
|
+
const d = (u || c).getAttribute(u ? "data-join-confirm" : "data-join");
|
|
2458
2488
|
_e = "";
|
|
2459
|
-
const
|
|
2460
|
-
if (!
|
|
2461
|
-
|
|
2489
|
+
const x = ((j = (w = E.querySelector(".join-email")) == null ? void 0 : w.value) == null ? void 0 : j.trim()) || ((z = a.signedInAs()) == null ? void 0 : z.email) || ((q = a.config.user) == null ? void 0 : q.email);
|
|
2490
|
+
if (!x) {
|
|
2491
|
+
pt = d, De(), (G = E.querySelector(".join-email")) == null || G.focus();
|
|
2462
2492
|
return;
|
|
2463
2493
|
}
|
|
2464
2494
|
try {
|
|
2465
|
-
const de = await
|
|
2466
|
-
|
|
2495
|
+
const de = await a.meToo(d, { email: x });
|
|
2496
|
+
pt = null, Ae = Ae.map((K) => K.id === d ? { ...K, joined: !0, affectedCount: de.affectedCount ?? K.affectedCount } : K), De();
|
|
2467
2497
|
} catch (de) {
|
|
2468
2498
|
_e = de.message.replace("[BugCatch] ", ""), De();
|
|
2469
2499
|
}
|
|
2470
|
-
}),
|
|
2471
|
-
let
|
|
2472
|
-
function
|
|
2473
|
-
|
|
2474
|
-
|
|
2500
|
+
}), Bt(), A.addEventListener("input", () => qn(A.value));
|
|
2501
|
+
let Rt = !1;
|
|
2502
|
+
function Qt() {
|
|
2503
|
+
a.callKind().then((o) => {
|
|
2504
|
+
o && (Rt = !0, L.hidden = ht());
|
|
2475
2505
|
}).catch(() => {
|
|
2476
2506
|
});
|
|
2477
2507
|
}
|
|
2478
|
-
|
|
2479
|
-
let X = { mode:
|
|
2480
|
-
const
|
|
2481
|
-
function
|
|
2482
|
-
const
|
|
2483
|
-
|
|
2508
|
+
Qt();
|
|
2509
|
+
let X = { mode: a.lastLoginMode || "off", signedIn: null }, Z = "idle", Re = ((Ft = a.config.user) == null ? void 0 : Ft.email) || "", Qe = "", J = !1, le = "";
|
|
2510
|
+
const ht = () => X.mode === "required" && !X.signedIn;
|
|
2511
|
+
function Nn() {
|
|
2512
|
+
const o = ht();
|
|
2513
|
+
N.hidden = o, T.hidden = o, oe && (oe.hidden = o), o ? L.hidden = !0 : Rt && (L.hidden = !1);
|
|
2484
2514
|
}
|
|
2485
|
-
function
|
|
2515
|
+
function Un() {
|
|
2486
2516
|
var c;
|
|
2487
2517
|
if (X.mode === "off") {
|
|
2488
|
-
|
|
2518
|
+
Q.hidden = !0, Q.innerHTML = "";
|
|
2489
2519
|
return;
|
|
2490
2520
|
}
|
|
2491
|
-
|
|
2492
|
-
const
|
|
2521
|
+
Q.hidden = !1, Q.classList.toggle("asking", Z !== "idle");
|
|
2522
|
+
const o = le ? `<div class="after err">${k(le)}</div>` : "";
|
|
2493
2523
|
if (Z === "idle") {
|
|
2494
2524
|
if (X.signedIn) {
|
|
2495
|
-
|
|
2525
|
+
Q.innerHTML = `<span class="who">Signed in as <strong>${k(X.signedIn.email)}</strong></span><button type="button" class="link" data-act="signout">Sign out</button>`;
|
|
2496
2526
|
return;
|
|
2497
2527
|
}
|
|
2498
|
-
const
|
|
2499
|
-
|
|
2528
|
+
const u = (c = a.config.user) == null ? void 0 : c.email;
|
|
2529
|
+
Q.innerHTML = `<span class="who">${X.mode === "required" ? "Sign in to report a bug here." : u ? `Reporting as <strong>${k(u)}</strong>.` : "Reporting anonymously — sign in and we can tell you what happens next."}</span><button type="button" class="link" data-act="signin">Sign in</button>`;
|
|
2500
2530
|
return;
|
|
2501
2531
|
}
|
|
2502
2532
|
if (Z === "email") {
|
|
2503
|
-
|
|
2533
|
+
Q.innerHTML = `
|
|
2504
2534
|
<p class="why">Sign in with any email address — we'll send you a code.
|
|
2505
2535
|
It's how you hear back about this report${X.mode === "required" ? ", and this project asks for it" : ""}.</p>
|
|
2506
2536
|
<div class="row">
|
|
2507
|
-
<input type="email" data-fld="email" value="${
|
|
2537
|
+
<input type="email" data-fld="email" value="${k(Re)}"
|
|
2508
2538
|
placeholder="you@example.com" autocomplete="email" spellcheck="false"
|
|
2509
2539
|
aria-label="Your email address" ${J ? "disabled" : ""} />
|
|
2510
2540
|
<button type="button" class="tool" data-act="code" ${J ? "disabled" : ""}>
|
|
2511
2541
|
${J ? "Sending…" : "Send code"}
|
|
2512
2542
|
</button>
|
|
2513
2543
|
</div>
|
|
2514
|
-
${
|
|
2544
|
+
${o}
|
|
2515
2545
|
${X.mode === "optional" ? '<div class="after"><button type="button" class="link" data-act="skip">Not now</button></div>' : ""}`;
|
|
2516
2546
|
return;
|
|
2517
2547
|
}
|
|
2518
|
-
|
|
2519
|
-
<p class="why">We sent a code to <strong>${
|
|
2548
|
+
Q.innerHTML = `
|
|
2549
|
+
<p class="why">We sent a code to <strong>${k(Re)}</strong>. It expires in ten minutes.</p>
|
|
2520
2550
|
<div class="row">
|
|
2521
|
-
<input type="text" class="code" data-fld="code" value="${
|
|
2551
|
+
<input type="text" class="code" data-fld="code" value="${k(Qe)}"
|
|
2522
2552
|
placeholder="123456" inputmode="numeric" autocomplete="one-time-code"
|
|
2523
2553
|
maxlength="8" aria-label="The code we emailed you" ${J ? "disabled" : ""} />
|
|
2524
2554
|
<button type="button" class="tool" data-act="confirm" ${J ? "disabled" : ""}>
|
|
2525
2555
|
${J ? "Checking…" : "Sign in"}
|
|
2526
2556
|
</button>
|
|
2527
2557
|
</div>
|
|
2528
|
-
${
|
|
2558
|
+
${o}
|
|
2529
2559
|
<div class="after">
|
|
2530
2560
|
<button type="button" class="link" data-act="resend" ${J ? "disabled" : ""}>Send it again</button>
|
|
2531
2561
|
<button type="button" class="link" data-act="signin-back" ${J ? "disabled" : ""}>Use another address</button>
|
|
2532
2562
|
</div>`;
|
|
2533
2563
|
}
|
|
2534
|
-
function ie({ focus:
|
|
2535
|
-
var
|
|
2536
|
-
if (
|
|
2537
|
-
const c =
|
|
2538
|
-
c && (c.focus(), (
|
|
2564
|
+
function ie({ focus: o = !1 } = {}) {
|
|
2565
|
+
var u;
|
|
2566
|
+
if (Un(), Nn(), !o || J) return;
|
|
2567
|
+
const c = Q.querySelector("[data-fld]");
|
|
2568
|
+
c && (c.focus(), (u = c.setSelectionRange) == null || u.call(c, c.value.length, c.value.length));
|
|
2539
2569
|
}
|
|
2540
|
-
|
|
2541
|
-
const c =
|
|
2570
|
+
Q.addEventListener("input", (o) => {
|
|
2571
|
+
const c = o.target.closest("[data-fld]");
|
|
2542
2572
|
c && (c.dataset.fld === "email" ? Re = c.value : Qe = c.value);
|
|
2543
|
-
}),
|
|
2544
|
-
|
|
2573
|
+
}), Q.addEventListener("keydown", (o) => {
|
|
2574
|
+
o.key !== "Enter" || !o.target.closest("[data-fld]") || (o.preventDefault(), Z === "email" ? ft() : jt());
|
|
2545
2575
|
});
|
|
2546
|
-
async function
|
|
2576
|
+
async function ft({ resent: o = !1 } = {}) {
|
|
2547
2577
|
const c = Re.trim();
|
|
2548
2578
|
if (!c) {
|
|
2549
2579
|
le = "Enter the address to send the code to.", ie({ focus: !0 });
|
|
@@ -2551,83 +2581,83 @@ function sa({ root: t, host: e, dock: n, client: o, onClose: i }) {
|
|
|
2551
2581
|
}
|
|
2552
2582
|
J = !0, le = "", ie();
|
|
2553
2583
|
try {
|
|
2554
|
-
await
|
|
2555
|
-
} catch (
|
|
2556
|
-
le =
|
|
2584
|
+
await a.signIn(c), Re = c, o || (Qe = ""), Z = "code";
|
|
2585
|
+
} catch (u) {
|
|
2586
|
+
le = u.message;
|
|
2557
2587
|
} finally {
|
|
2558
2588
|
J = !1, ie({ focus: !0 });
|
|
2559
2589
|
}
|
|
2560
2590
|
}
|
|
2561
|
-
async function
|
|
2562
|
-
const
|
|
2563
|
-
if (!
|
|
2591
|
+
async function jt() {
|
|
2592
|
+
const o = Qe.trim();
|
|
2593
|
+
if (!o) {
|
|
2564
2594
|
le = "Enter the code we emailed you.", ie({ focus: !0 });
|
|
2565
2595
|
return;
|
|
2566
2596
|
}
|
|
2567
2597
|
J = !0, le = "", ie();
|
|
2568
2598
|
try {
|
|
2569
|
-
const c = await
|
|
2570
|
-
X.signedIn = c, Z = "idle", Qe = "",
|
|
2599
|
+
const c = await a.confirmSignIn(Re.trim(), o);
|
|
2600
|
+
X.signedIn = c, Z = "idle", Qe = "", H(""), Qt();
|
|
2571
2601
|
} catch (c) {
|
|
2572
2602
|
le = c.message;
|
|
2573
2603
|
} finally {
|
|
2574
2604
|
J = !1, ie({ focus: Z !== "idle" });
|
|
2575
2605
|
}
|
|
2576
2606
|
}
|
|
2577
|
-
|
|
2578
|
-
const c =
|
|
2607
|
+
Q.addEventListener("click", async (o) => {
|
|
2608
|
+
const c = o.target.closest("button[data-act]");
|
|
2579
2609
|
if (!c) return;
|
|
2580
|
-
const
|
|
2581
|
-
if (
|
|
2610
|
+
const u = c.dataset.act;
|
|
2611
|
+
if (u === "signin") {
|
|
2582
2612
|
Z = "email", le = "", ie({ focus: !0 });
|
|
2583
2613
|
return;
|
|
2584
2614
|
}
|
|
2585
|
-
if (
|
|
2615
|
+
if (u === "skip") {
|
|
2586
2616
|
Z = "idle", le = "", ie();
|
|
2587
2617
|
return;
|
|
2588
2618
|
}
|
|
2589
|
-
if (
|
|
2619
|
+
if (u === "signin-back") {
|
|
2590
2620
|
Z = "email", le = "", Qe = "", ie({ focus: !0 });
|
|
2591
2621
|
return;
|
|
2592
2622
|
}
|
|
2593
|
-
if (
|
|
2594
|
-
|
|
2623
|
+
if (u === "code") {
|
|
2624
|
+
ft();
|
|
2595
2625
|
return;
|
|
2596
2626
|
}
|
|
2597
|
-
if (
|
|
2598
|
-
|
|
2627
|
+
if (u === "resend") {
|
|
2628
|
+
ft({ resent: !0 });
|
|
2599
2629
|
return;
|
|
2600
2630
|
}
|
|
2601
|
-
if (
|
|
2602
|
-
|
|
2631
|
+
if (u === "confirm") {
|
|
2632
|
+
jt();
|
|
2603
2633
|
return;
|
|
2604
2634
|
}
|
|
2605
|
-
if (
|
|
2635
|
+
if (u === "signout") {
|
|
2606
2636
|
J = !0, ie();
|
|
2607
2637
|
try {
|
|
2608
|
-
await
|
|
2638
|
+
await a.signOut();
|
|
2609
2639
|
} finally {
|
|
2610
2640
|
X.signedIn = null, J = !1, Z = X.mode === "required" ? "email" : "idle", ie({ focus: Z !== "idle" });
|
|
2611
2641
|
}
|
|
2612
2642
|
}
|
|
2613
2643
|
});
|
|
2614
|
-
async function
|
|
2615
|
-
const c = await
|
|
2616
|
-
X = { mode: c.mode, signedIn: c.signedIn },
|
|
2644
|
+
async function gt({ announce: o = !1 } = {}) {
|
|
2645
|
+
const c = await a.loginState();
|
|
2646
|
+
X = { mode: c.mode, signedIn: c.signedIn }, a.lastLoginMode = c.mode, ht() && Z === "idle" && (Z = "email"), X.signedIn && (Z = "idle"), o && c.signedOutReason && H(c.signedOutReason, "info"), ie();
|
|
2617
2647
|
}
|
|
2618
|
-
|
|
2648
|
+
gt({ announce: !0 }).catch(() => {
|
|
2619
2649
|
}), L.addEventListener("click", async () => {
|
|
2620
|
-
b = !0,
|
|
2650
|
+
b = !0, H(""), ce(), L.disabled = !0, L.innerHTML = '<span class="spinner"></span>Ringing…';
|
|
2621
2651
|
try {
|
|
2622
|
-
const
|
|
2623
|
-
|
|
2624
|
-
} catch (
|
|
2625
|
-
b = !1, L.disabled = !1, L.textContent = "Talk to the team", ce(),
|
|
2652
|
+
const o = await a.startCall();
|
|
2653
|
+
Vn(o);
|
|
2654
|
+
} catch (o) {
|
|
2655
|
+
b = !1, L.disabled = !1, L.textContent = "Talk to the team", ce(), o.filed ? zt(o.filed, { callFailed: o.reason || "The call could not be started." }) : (H(o.message.replace("[BugCatch] ", "")), X.mode !== "off" && gt().catch(() => {
|
|
2626
2656
|
}));
|
|
2627
2657
|
}
|
|
2628
2658
|
});
|
|
2629
|
-
function
|
|
2630
|
-
const c =
|
|
2659
|
+
function Vn(o) {
|
|
2660
|
+
const c = g.querySelector(".panel"), u = o != null && o.bugId ? String(o.bugId).slice(0, 8) : null;
|
|
2631
2661
|
c.innerHTML = `
|
|
2632
2662
|
<div class="call">
|
|
2633
2663
|
<div class="call-head">
|
|
@@ -2635,349 +2665,383 @@ function sa({ root: t, host: e, dock: n, client: o, onClose: i }) {
|
|
|
2635
2665
|
<strong class="call-state">Ringing…</strong>
|
|
2636
2666
|
</div>
|
|
2637
2667
|
<p class="call-note">
|
|
2638
|
-
We're ringing the team now. Someone will pick up if they're free — your report${
|
|
2668
|
+
We're ringing the team now. Someone will pick up if they're free — your report${u ? ` <code>${k(u)}</code>` : ""} is already filed either way, so nothing is lost if nobody answers.
|
|
2639
2669
|
</p>
|
|
2640
2670
|
<div class="foot">
|
|
2641
2671
|
<span class="spacer"></span>
|
|
2642
2672
|
<button class="primary" type="button" data-act="hangup">Cancel</button>
|
|
2643
2673
|
</div>
|
|
2644
2674
|
</div>`;
|
|
2645
|
-
const
|
|
2675
|
+
const d = c.querySelector(".call-state"), x = c.querySelector(".call-dot"), w = {
|
|
2646
2676
|
ringing: "Ringing the team…",
|
|
2647
2677
|
connecting: "Someone answered — connecting…",
|
|
2648
2678
|
connected: "Connected",
|
|
2649
2679
|
missed: "Nobody was free",
|
|
2650
2680
|
ended: "Call ended",
|
|
2651
2681
|
failed: "The call dropped"
|
|
2652
|
-
},
|
|
2653
|
-
if (
|
|
2682
|
+
}, j = ["ended", "failed", "missed"], z = a.on("call", ({ state: q }) => {
|
|
2683
|
+
if (d.textContent = w[q] || q, x.classList.toggle("off", j.includes(q)), j.includes(q) && (c.querySelector('[data-act="hangup"]').textContent = "Close", q === "missed")) {
|
|
2654
2684
|
const G = c.querySelector(".call-note");
|
|
2655
2685
|
G && (G.textContent = "Nobody was free to pick up just now. Your report is filed and the team will reply in the chat.");
|
|
2656
2686
|
}
|
|
2657
2687
|
});
|
|
2658
2688
|
c.querySelector('[data-act="hangup"]').addEventListener("click", () => {
|
|
2659
|
-
|
|
2689
|
+
z(), a.endCall(), re();
|
|
2660
2690
|
});
|
|
2661
2691
|
}
|
|
2662
|
-
function
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2692
|
+
function zt(o, { callFailed: c = null } = {}) {
|
|
2693
|
+
if (o != null && o.id && !c) {
|
|
2694
|
+
mt(o.id, { fresh: !0 }).then((u) => {
|
|
2695
|
+
u || Ot(o, { callFailed: c });
|
|
2696
|
+
});
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
Ot(o, { callFailed: c });
|
|
2700
|
+
}
|
|
2701
|
+
function Ot(o, { callFailed: c = null } = {}) {
|
|
2702
|
+
var w;
|
|
2703
|
+
const u = o != null && o.id ? String(o.id).slice(0, 8) : null, d = (w = o == null ? void 0 : o.estimate) != null && w.label ? String(o.estimate.label) : null, x = c ? `<p class="eta">${k(c)} Your report is filed, and the team will reply in the chat.</p>` : "";
|
|
2704
|
+
g.querySelector(".panel").innerHTML = `
|
|
2666
2705
|
<div class="done">
|
|
2667
|
-
<div class="tick">${
|
|
2706
|
+
<div class="tick">${O.check}</div>
|
|
2668
2707
|
<h3>Thanks — that's on its way.</h3>
|
|
2669
|
-
<p>${
|
|
2670
|
-
${
|
|
2671
|
-
${
|
|
2672
|
-
</div>`, setTimeout(re,
|
|
2673
|
-
}
|
|
2674
|
-
async function
|
|
2675
|
-
const
|
|
2676
|
-
|
|
2708
|
+
<p>${u ? `Filed as <code>${k(u)}</code>.` : "The team has what they need to reproduce it."}</p>
|
|
2709
|
+
${x}
|
|
2710
|
+
${d ? `<p class="eta">Reports like this usually take <strong>${k(d)}</strong>. We'll let you know when it moves.</p>` : ""}
|
|
2711
|
+
</div>`, setTimeout(re, x ? 6e3 : d ? 4e3 : 2e3);
|
|
2712
|
+
}
|
|
2713
|
+
async function Ht() {
|
|
2714
|
+
const o = g.querySelector(".panel");
|
|
2715
|
+
o.innerHTML = `
|
|
2677
2716
|
<div class="head">
|
|
2678
|
-
<div class="mark">${
|
|
2717
|
+
<div class="mark">${O.bug}</div>
|
|
2679
2718
|
<div class="titles">
|
|
2680
2719
|
<h2>Your reports</h2>
|
|
2681
2720
|
<p>Everything you've reported, and where each one got to.</p>
|
|
2682
2721
|
</div>
|
|
2683
|
-
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${
|
|
2722
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${O.close}</button>
|
|
2684
2723
|
</div>
|
|
2685
|
-
<div class="history"><div class="empty">Loading…</div></div>`,
|
|
2724
|
+
<div class="history"><div class="empty">Loading…</div></div>`, o.querySelector('[data-act="close"]').addEventListener("click", re);
|
|
2686
2725
|
let c = [];
|
|
2687
2726
|
try {
|
|
2688
|
-
({ reports: c } = await
|
|
2727
|
+
({ reports: c } = await a.myReports());
|
|
2689
2728
|
} catch {
|
|
2690
|
-
|
|
2729
|
+
o.querySelector(".history").innerHTML = `<div class="empty">Couldn't load your reports just now.</div>`;
|
|
2691
2730
|
return;
|
|
2692
2731
|
}
|
|
2693
|
-
const
|
|
2694
|
-
if (
|
|
2695
|
-
|
|
2696
|
-
<button class="row" type="button" data-report="${
|
|
2732
|
+
const u = o.querySelector(".history");
|
|
2733
|
+
if (u) {
|
|
2734
|
+
u.innerHTML = c.length ? c.map((d) => `
|
|
2735
|
+
<button class="row" type="button" data-report="${k(d.id)}">
|
|
2697
2736
|
<span class="who">
|
|
2698
|
-
<span class="ttl">${
|
|
2699
|
-
<span class="sub">${
|
|
2737
|
+
<span class="ttl">${k(d.title)}</span>
|
|
2738
|
+
<span class="sub">${k(d.reference)} · ${k(rt(d.createdAt))}</span>
|
|
2700
2739
|
</span>
|
|
2701
|
-
<span class="pill ${
|
|
2740
|
+
<span class="pill ${k(String(d.status).toLowerCase())}">${k(kt(d.status))}</span>
|
|
2702
2741
|
</button>`).join("") : `<div class="empty">You haven't reported anything yet.</div>`;
|
|
2703
|
-
for (const
|
|
2704
|
-
|
|
2742
|
+
for (const d of u.querySelectorAll("[data-report]"))
|
|
2743
|
+
d.addEventListener("click", () => mt(d.dataset.report));
|
|
2705
2744
|
}
|
|
2706
2745
|
}
|
|
2707
|
-
async function
|
|
2708
|
-
var
|
|
2709
|
-
const
|
|
2710
|
-
|
|
2746
|
+
async function mt(o, { fresh: c = !1 } = {}) {
|
|
2747
|
+
var j;
|
|
2748
|
+
const u = g.querySelector(".panel");
|
|
2749
|
+
u.innerHTML = `
|
|
2711
2750
|
<div class="head">
|
|
2712
|
-
<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${
|
|
2751
|
+
<button class="icon-btn back" type="button" data-act="back" aria-label="Back to your reports">${O.back}</button>
|
|
2713
2752
|
<div class="titles">
|
|
2714
|
-
<h2
|
|
2715
|
-
<p
|
|
2753
|
+
<h2>${c ? "Looking into it" : "Your report"}</h2>
|
|
2754
|
+
<p>${c ? "Our assistant is investigating — it may ask you a question." : "Everything that has happened, and a way to answer."}</p>
|
|
2716
2755
|
</div>
|
|
2717
|
-
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${
|
|
2756
|
+
<button class="icon-btn" type="button" data-act="close" aria-label="Close">${O.close}</button>
|
|
2718
2757
|
</div>
|
|
2719
|
-
<div class="history"><div class="empty">Loading…</div></div>`,
|
|
2758
|
+
<div class="history"><div class="empty">Loading…</div></div>`, u.querySelector('[data-act="close"]').addEventListener("click", re), u.querySelector('[data-act="back"]').addEventListener("click", Ht);
|
|
2720
2759
|
let d = null;
|
|
2721
2760
|
try {
|
|
2722
|
-
d = await
|
|
2761
|
+
d = await a.myReport(o);
|
|
2723
2762
|
} catch {
|
|
2724
2763
|
d = null;
|
|
2725
2764
|
}
|
|
2726
|
-
const
|
|
2727
|
-
if (!
|
|
2728
|
-
if (!d)
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
}
|
|
2732
|
-
fe = a, o.markReportRead(a), f.classList.add("chatting"), f.innerHTML = `
|
|
2765
|
+
const x = u.querySelector(".history");
|
|
2766
|
+
if (!x || !u.querySelector('[data-act="back"]')) return !1;
|
|
2767
|
+
if (!d)
|
|
2768
|
+
return c || (x.innerHTML = `<div class="empty">Couldn't load that report just now.</div>`), !1;
|
|
2769
|
+
ge = o, a.markReportRead(o), x.classList.add("chatting"), x.innerHTML = `
|
|
2733
2770
|
<div class="report-head">
|
|
2734
|
-
<span class="ttl">${
|
|
2735
|
-
<span class="sub">${
|
|
2736
|
-
<span class="pill ${
|
|
2737
|
-
${(
|
|
2771
|
+
<span class="ttl">${k(d.title)}</span>
|
|
2772
|
+
<span class="sub">${k(d.reference)} · ${k(d.project || "")}</span>
|
|
2773
|
+
<span class="pill ${k(String(d.status).toLowerCase())}">${k(kt(d.status))}</span>
|
|
2774
|
+
${(j = d.estimate) != null && j.label ? `<span class="eta-line">Usually takes ${k(String(d.estimate.label))}</span>` : ""}
|
|
2738
2775
|
</div>
|
|
2739
|
-
<div class="thread">${
|
|
2740
|
-
const
|
|
2741
|
-
|
|
2742
|
-
}
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2776
|
+
<div class="thread">${sn(d.timeline)}</div>`;
|
|
2777
|
+
const w = x.querySelector(".thread");
|
|
2778
|
+
return xt(w), Nt(x, d), d.canReply && Kn(x, w, o), Dt(x, d, o), !0;
|
|
2779
|
+
}
|
|
2780
|
+
let qt = null;
|
|
2781
|
+
function Dt(o, c, u) {
|
|
2782
|
+
var w, j, z;
|
|
2783
|
+
clearTimeout(qt);
|
|
2784
|
+
const d = c.assistant;
|
|
2785
|
+
if ((w = o.querySelector(".assistant")) == null || w.remove(), !d) return;
|
|
2786
|
+
const x = document.createElement("div");
|
|
2787
|
+
x.className = `assistant ${k(d.phase)}`, x.setAttribute("role", "status"), x.setAttribute("aria-live", "polite"), x.innerHTML = `
|
|
2788
|
+
<div class="as-top">
|
|
2789
|
+
<span class="as-orb" aria-hidden="true">${d.phase === "analyzing" ? '<span class="as-spin"></span>' : "✦"}</span>
|
|
2790
|
+
<div class="as-text">
|
|
2791
|
+
<div class="as-title">${k(d.title)}</div>
|
|
2792
|
+
<div class="as-detail">${k(d.detail)}</div>
|
|
2793
|
+
</div>
|
|
2794
|
+
</div>
|
|
2795
|
+
<ol class="as-steps">${(d.steps || []).map((q) => `<li class="${k(q.state)}"><span></span>${k(q.label)}</li>`).join("")}</ol>`, (j = o.querySelector(".report-head")) == null || j.after(x), d.phase === "analyzing" ? qt = setTimeout(() => Fe(u), 3e3) : d.phase === "needs_info" && ((z = o.querySelector(".composer textarea")) == null || z.focus());
|
|
2796
|
+
}
|
|
2797
|
+
function Nt(o, c) {
|
|
2798
|
+
var d, x;
|
|
2799
|
+
if ((d = o.querySelector(".fix-verification")) == null || d.remove(), !c.resolvedAt || !["RESOLVED", "CLOSED"].includes(c.status)) return;
|
|
2800
|
+
const u = document.createElement("div");
|
|
2801
|
+
u.className = "fix-verification", c.verification ? u.textContent = c.verification === "CONFIRMED" ? "You confirmed that this fix works." : "Your feedback was recorded." : (u.innerHTML = '<p>Does the fix work for you?</p><textarea maxlength="4000" aria-label="Fix feedback" placeholder="What happens when you try again? (optional)"></textarea><button type="button" data-result="CONFIRMED">It works now</button> <button type="button" data-result="STILL_HAPPENING">Still happening</button><p class="feedback-status" role="status"></p>', u.querySelectorAll("[data-result]").forEach((w) => {
|
|
2802
|
+
w.onclick = async () => {
|
|
2803
|
+
u.querySelectorAll("button").forEach((j) => {
|
|
2804
|
+
j.disabled = !0;
|
|
2751
2805
|
});
|
|
2752
2806
|
try {
|
|
2753
|
-
await
|
|
2754
|
-
} catch (
|
|
2755
|
-
|
|
2756
|
-
|
|
2807
|
+
await a.verifyFix(c.id, { result: w.dataset.result, resolvedAt: c.resolvedAt, note: u.querySelector("textarea").value }), await mt(c.id);
|
|
2808
|
+
} catch (j) {
|
|
2809
|
+
u.querySelector(".feedback-status").textContent = j.message, u.querySelectorAll("button").forEach((z) => {
|
|
2810
|
+
z.disabled = !1;
|
|
2757
2811
|
});
|
|
2758
2812
|
}
|
|
2759
2813
|
};
|
|
2760
|
-
})), (
|
|
2814
|
+
})), (x = o.querySelector(".report-head")) == null || x.after(u);
|
|
2761
2815
|
}
|
|
2762
|
-
async function
|
|
2763
|
-
const c =
|
|
2764
|
-
if (!
|
|
2765
|
-
let
|
|
2816
|
+
async function Fe(o) {
|
|
2817
|
+
const c = g.querySelector(".history.chatting"), u = c == null ? void 0 : c.querySelector(".thread");
|
|
2818
|
+
if (!u || ge !== o) return;
|
|
2819
|
+
let d = null;
|
|
2766
2820
|
try {
|
|
2767
|
-
|
|
2821
|
+
d = await a.myReport(o);
|
|
2768
2822
|
} catch {
|
|
2769
2823
|
}
|
|
2770
|
-
if (!
|
|
2771
|
-
|
|
2772
|
-
const
|
|
2773
|
-
|
|
2774
|
-
const
|
|
2775
|
-
|
|
2776
|
-
}
|
|
2777
|
-
function
|
|
2778
|
-
const
|
|
2779
|
-
|
|
2824
|
+
if (!d || ge !== o) return;
|
|
2825
|
+
Nt(c, d), Dt(c, d, o);
|
|
2826
|
+
const x = ho(u);
|
|
2827
|
+
u.innerHTML = sn(d.timeline), x && xt(u);
|
|
2828
|
+
const w = c.querySelector(".report-head .pill");
|
|
2829
|
+
w && (w.className = `pill ${String(d.status).toLowerCase()}`, w.textContent = kt(d.status));
|
|
2830
|
+
}
|
|
2831
|
+
function Kn(o, c, u) {
|
|
2832
|
+
const d = document.createElement("div");
|
|
2833
|
+
d.className = "composer", d.innerHTML = `
|
|
2780
2834
|
<div class="staged" hidden></div>
|
|
2781
2835
|
<div class="row">
|
|
2782
2836
|
<div class="tools">
|
|
2783
|
-
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${
|
|
2784
|
-
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${
|
|
2785
|
-
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${
|
|
2837
|
+
<button class="tool" type="button" data-act="attach" title="Attach a file" aria-label="Attach a file">${O.paperclip}</button>
|
|
2838
|
+
<button class="tool" type="button" data-act="voice" title="Record a voice note" aria-label="Record a voice note">${O.mic}</button>
|
|
2839
|
+
<button class="tool" type="button" data-act="livecall" title="Call the team" aria-label="Call the team" hidden>${O.phone}</button>
|
|
2786
2840
|
</div>
|
|
2787
2841
|
<textarea rows="1" placeholder="Write a reply…" aria-label="Write a reply"></textarea>
|
|
2788
|
-
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${
|
|
2842
|
+
<button class="send" type="button" data-act="send" title="Send" aria-label="Send" disabled>${O.send}</button>
|
|
2789
2843
|
</div>
|
|
2790
2844
|
<div class="note" hidden></div>
|
|
2791
|
-
<input type="file" hidden multiple accept="${
|
|
2792
|
-
const
|
|
2793
|
-
let Se = null,
|
|
2794
|
-
function ne(M,
|
|
2795
|
-
de.hidden = !M, de.className = `note ${
|
|
2845
|
+
<input type="file" hidden multiple accept="${vn.join(",")}">`, o.appendChild(d);
|
|
2846
|
+
const x = d.querySelector(".staged"), w = d.querySelector("textarea"), j = d.querySelector('[data-act="send"]'), z = d.querySelector('[data-act="voice"]'), q = d.querySelector('[data-act="livecall"]'), G = d.querySelector("input[type=file]"), de = d.querySelector(".note"), K = [];
|
|
2847
|
+
let Se = null, W = !1;
|
|
2848
|
+
function ne(M, R = "") {
|
|
2849
|
+
de.hidden = !M, de.className = `note ${R}`, de.textContent = M || "";
|
|
2796
2850
|
}
|
|
2797
2851
|
function Ce() {
|
|
2798
|
-
const M =
|
|
2799
|
-
|
|
2800
|
-
<span class="chip ${
|
|
2801
|
-
<span class="nm">${
|
|
2802
|
-
<span class="sz">${
|
|
2803
|
-
<button type="button" data-drop="${
|
|
2852
|
+
const M = K.filter((R) => R.storageKey);
|
|
2853
|
+
j.disabled = W || !w.value.trim() && !M.length, x.hidden = !K.length, x.innerHTML = K.map((R, ue) => `
|
|
2854
|
+
<span class="chip ${R.storageKey ? "" : "uploading"}">
|
|
2855
|
+
<span class="nm">${k(R.name)}</span>
|
|
2856
|
+
<span class="sz">${R.storageKey ? je(R.size) : "sending…"}</span>
|
|
2857
|
+
<button type="button" data-drop="${ue}" aria-label="Remove ${k(R.name)}">${O.close}</button>
|
|
2804
2858
|
</span>`).join("");
|
|
2805
|
-
for (const
|
|
2806
|
-
|
|
2807
|
-
|
|
2859
|
+
for (const R of x.querySelectorAll("[data-drop]"))
|
|
2860
|
+
R.addEventListener("click", () => {
|
|
2861
|
+
K.splice(Number(R.dataset.drop), 1), Ce();
|
|
2808
2862
|
});
|
|
2809
2863
|
}
|
|
2810
|
-
async function
|
|
2811
|
-
const
|
|
2812
|
-
|
|
2864
|
+
async function Wt(M, R, ue) {
|
|
2865
|
+
const D = { name: ue, size: M.size, storageKey: null };
|
|
2866
|
+
K.push(D), Ce();
|
|
2813
2867
|
try {
|
|
2814
|
-
const { storageKey:
|
|
2815
|
-
|
|
2816
|
-
} catch (
|
|
2817
|
-
|
|
2868
|
+
const { storageKey: yt, mime: _n } = await a.uploadAttachment(M, R);
|
|
2869
|
+
D.storageKey = yt, D.mime = _n;
|
|
2870
|
+
} catch (yt) {
|
|
2871
|
+
K.splice(K.indexOf(D), 1), ne(yt.message || "That file could not be sent.", "err");
|
|
2818
2872
|
}
|
|
2819
2873
|
Ce();
|
|
2820
2874
|
}
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
}),
|
|
2824
|
-
M.key === "Enter" && !M.shiftKey && !M.isComposing && (M.preventDefault(),
|
|
2825
|
-
}),
|
|
2875
|
+
w.addEventListener("input", () => {
|
|
2876
|
+
w.style.height = "auto", w.style.height = `${Math.min(w.scrollHeight, 120)}px`, Ce();
|
|
2877
|
+
}), w.addEventListener("keydown", (M) => {
|
|
2878
|
+
M.key === "Enter" && !M.shiftKey && !M.isComposing && (M.preventDefault(), bt());
|
|
2879
|
+
}), d.querySelector('[data-act="attach"]').addEventListener("click", () => G.click()), G.addEventListener("change", () => {
|
|
2826
2880
|
ne("");
|
|
2827
2881
|
for (const M of G.files) {
|
|
2828
|
-
if (M.size >
|
|
2829
|
-
ne(`${M.name} is larger than ${je(
|
|
2882
|
+
if (M.size > a.config.maxAttachmentBytes) {
|
|
2883
|
+
ne(`${M.name} is larger than ${je(a.config.maxAttachmentBytes)}.`, "err");
|
|
2830
2884
|
continue;
|
|
2831
2885
|
}
|
|
2832
|
-
|
|
2886
|
+
Wt(M, M.type, M.name);
|
|
2833
2887
|
}
|
|
2834
2888
|
G.value = "";
|
|
2835
|
-
}),
|
|
2889
|
+
}), la() || (z.disabled = !0, z.title = "This browser cannot record audio"), z.addEventListener("click", async () => {
|
|
2836
2890
|
if (Se) {
|
|
2837
2891
|
const M = Se;
|
|
2838
|
-
Se = null,
|
|
2839
|
-
const { blob:
|
|
2840
|
-
|
|
2892
|
+
Se = null, z.classList.remove("recording"), z.innerHTML = O.mic, ne("");
|
|
2893
|
+
const { blob: R, mime: ue } = await M.stop();
|
|
2894
|
+
R.size && Wt(R, ue, "Voice note");
|
|
2841
2895
|
return;
|
|
2842
2896
|
}
|
|
2843
2897
|
try {
|
|
2844
|
-
ne(""), Se = await
|
|
2845
|
-
maxMs:
|
|
2846
|
-
onTick: (M) => ne(`Recording — ${
|
|
2847
|
-
onAutoStop: () =>
|
|
2848
|
-
}),
|
|
2898
|
+
ne(""), Se = await fa({
|
|
2899
|
+
maxMs: a.config.maxRecordingMs,
|
|
2900
|
+
onTick: (M) => ne(`Recording — ${Ye(M)}. Tap the mic to stop.`),
|
|
2901
|
+
onAutoStop: () => z.click()
|
|
2902
|
+
}), z.classList.add("recording"), z.innerHTML = O.stopSquare;
|
|
2849
2903
|
} catch {
|
|
2850
2904
|
Se = null, ne("The microphone is not available — check the browser permission.", "err");
|
|
2851
2905
|
}
|
|
2852
|
-
}),
|
|
2853
|
-
M && (
|
|
2906
|
+
}), a.canCallTeam(u).then((M) => {
|
|
2907
|
+
M && (q.hidden = !1);
|
|
2854
2908
|
}).catch(() => {
|
|
2855
|
-
}),
|
|
2856
|
-
|
|
2909
|
+
}), q.addEventListener("click", async () => {
|
|
2910
|
+
q.disabled = !0, ne("");
|
|
2857
2911
|
try {
|
|
2858
|
-
const M = await
|
|
2859
|
-
|
|
2912
|
+
const M = await a.startLiveCall(u);
|
|
2913
|
+
Pn(o, c, M);
|
|
2860
2914
|
} catch (M) {
|
|
2861
2915
|
ne(M.message.replace("[BugCatch] ", ""), "err");
|
|
2862
2916
|
} finally {
|
|
2863
|
-
|
|
2917
|
+
q.disabled = !1;
|
|
2864
2918
|
}
|
|
2865
|
-
}),
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2919
|
+
}), j.addEventListener("click", bt), c.addEventListener("click", (M) => {
|
|
2920
|
+
var ue, D;
|
|
2921
|
+
const R = (D = (ue = M.target).closest) == null ? void 0 : D.call(ue, "[data-quick]");
|
|
2922
|
+
!R || W || (w.value = R.dataset.quick, bt());
|
|
2923
|
+
});
|
|
2924
|
+
async function bt() {
|
|
2925
|
+
var ue;
|
|
2926
|
+
const M = w.value.trim(), R = K.filter((D) => D.storageKey);
|
|
2927
|
+
if (!(W || !M && !R.length)) {
|
|
2928
|
+
W = !0, Ce(), ne(""), c.insertAdjacentHTML("beforeend", Ln({
|
|
2871
2929
|
from: "reporter",
|
|
2872
2930
|
body: M,
|
|
2873
2931
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2874
|
-
attachments:
|
|
2875
|
-
}, "pending")),
|
|
2932
|
+
attachments: R.map((D) => ({ type: "FILE", name: D.name, size: D.size }))
|
|
2933
|
+
}, "pending")), xt(c);
|
|
2876
2934
|
try {
|
|
2877
|
-
await
|
|
2878
|
-
apiBase:
|
|
2879
|
-
bugId:
|
|
2935
|
+
await Sn({
|
|
2936
|
+
apiBase: a.config.apiBase,
|
|
2937
|
+
bugId: u,
|
|
2880
2938
|
body: M,
|
|
2881
|
-
attachments:
|
|
2882
|
-
storageKey:
|
|
2883
|
-
mime:
|
|
2884
|
-
name:
|
|
2885
|
-
size:
|
|
2939
|
+
attachments: R.map((D) => ({
|
|
2940
|
+
storageKey: D.storageKey,
|
|
2941
|
+
mime: D.mime,
|
|
2942
|
+
name: D.name,
|
|
2943
|
+
size: D.size
|
|
2886
2944
|
}))
|
|
2887
|
-
}),
|
|
2888
|
-
} catch (
|
|
2889
|
-
(
|
|
2945
|
+
}), w.value = "", w.style.height = "auto", K.length = 0, await Fe(u);
|
|
2946
|
+
} catch (D) {
|
|
2947
|
+
(ue = c.querySelector(".msg-row.pending")) == null || ue.classList.replace("pending", "failed"), ne(D.message || "That could not be sent — try again.", "err");
|
|
2890
2948
|
} finally {
|
|
2891
|
-
|
|
2949
|
+
W = !1, Ce();
|
|
2892
2950
|
}
|
|
2893
2951
|
}
|
|
2894
2952
|
}
|
|
2895
2953
|
Ce();
|
|
2896
2954
|
}
|
|
2897
|
-
function
|
|
2898
|
-
const
|
|
2899
|
-
|
|
2955
|
+
function Pn(o, c, u) {
|
|
2956
|
+
const d = document.createElement("div");
|
|
2957
|
+
d.className = "livecall", d.innerHTML = `
|
|
2900
2958
|
<span class="call-dot" aria-hidden="true"></span>
|
|
2901
2959
|
<span class="who" role="status" aria-live="polite">Calling the team…</span>
|
|
2902
2960
|
<span class="secs" hidden></span>
|
|
2903
2961
|
<button class="act" type="button" data-act="mute" hidden>Mute</button>
|
|
2904
|
-
<button class="act danger" type="button" data-act="hangup">Cancel</button>`,
|
|
2905
|
-
const
|
|
2962
|
+
<button class="act danger" type="button" data-act="hangup">Cancel</button>`, o.insertBefore(d, c);
|
|
2963
|
+
const x = d.querySelector(".who"), w = d.querySelector(".secs"), j = d.querySelector(".call-dot"), z = d.querySelector('[data-act="mute"]'), q = d.querySelector('[data-act="hangup"]');
|
|
2906
2964
|
let G = null;
|
|
2907
2965
|
const de = () => {
|
|
2908
2966
|
G && (clearInterval(G), G = null);
|
|
2909
|
-
},
|
|
2910
|
-
de(),
|
|
2911
|
-
}, Se =
|
|
2912
|
-
if (
|
|
2913
|
-
|
|
2967
|
+
}, K = (W) => {
|
|
2968
|
+
de(), j.classList.add("off"), d.classList.add("over"), x.textContent = W, w.hidden = !0, z.hidden = !0, q.textContent = "Dismiss", q.classList.remove("danger");
|
|
2969
|
+
}, Se = a.on("call", ({ state: W }) => {
|
|
2970
|
+
if (W === "ringing" && (x.textContent = "Calling the team…"), W === "connecting" && (x.textContent = "Someone answered — connecting…"), W === "connected") {
|
|
2971
|
+
x.textContent = "You're on a call with the team", z.hidden = !1, w.hidden = !1;
|
|
2914
2972
|
const ne = Date.now();
|
|
2915
2973
|
de(), G = setInterval(() => {
|
|
2916
|
-
|
|
2917
|
-
}, 1e3),
|
|
2974
|
+
w.textContent = Ye(Math.floor((Date.now() - ne) / 1e3));
|
|
2975
|
+
}, 1e3), w.textContent = "0s";
|
|
2918
2976
|
}
|
|
2919
|
-
|
|
2977
|
+
W === "missed" && K("Nobody was free. Send a message instead and the team will pick it up."), W === "ended" && K("Call ended."), W === "failed" && K("The call dropped.");
|
|
2920
2978
|
});
|
|
2921
|
-
|
|
2922
|
-
const
|
|
2923
|
-
|
|
2924
|
-
}),
|
|
2925
|
-
Se(), de(),
|
|
2979
|
+
z.addEventListener("click", () => {
|
|
2980
|
+
const W = u.setMuted(!u.isMuted());
|
|
2981
|
+
z.textContent = W ? "Unmute" : "Mute", x.textContent = W ? "You're muted" : "You're on a call with the team";
|
|
2982
|
+
}), q.addEventListener("click", () => {
|
|
2983
|
+
Se(), de(), a.endCall(), d.remove(), Fe(ge);
|
|
2926
2984
|
});
|
|
2927
2985
|
}
|
|
2928
|
-
let
|
|
2929
|
-
return
|
|
2930
|
-
!
|
|
2931
|
-
}), t.appendChild(
|
|
2986
|
+
let ge = null;
|
|
2987
|
+
return we = a.on("update", (o) => {
|
|
2988
|
+
!ge || (o == null ? void 0 : o.bugId) !== ge || (a.markReportRead(ge), Fe(ge));
|
|
2989
|
+
}), t.appendChild(g), ce(), A.focus(), { destroy: He, close: re };
|
|
2932
2990
|
}
|
|
2933
|
-
function
|
|
2991
|
+
function sn(t) {
|
|
2934
2992
|
const e = t || [];
|
|
2935
2993
|
return e.length ? e.map((n) => {
|
|
2936
|
-
var
|
|
2937
|
-
return n.from ?
|
|
2994
|
+
var a, i, r, s;
|
|
2995
|
+
return n.from ? Ln({
|
|
2938
2996
|
from: n.from,
|
|
2939
|
-
author: (
|
|
2997
|
+
author: (a = n.reply) == null ? void 0 : a.author,
|
|
2940
2998
|
automated: (i = n.reply) == null ? void 0 : i.automated,
|
|
2941
2999
|
body: (r = n.reply) == null ? void 0 : r.body,
|
|
2942
3000
|
at: n.at,
|
|
2943
3001
|
attachments: (s = n.reply) == null ? void 0 : s.attachments
|
|
2944
|
-
}) :
|
|
3002
|
+
}) : uo(n);
|
|
2945
3003
|
}).join("") : "";
|
|
2946
3004
|
}
|
|
2947
|
-
function
|
|
3005
|
+
function uo(t) {
|
|
2948
3006
|
return `
|
|
2949
|
-
<div class="sys k-${
|
|
2950
|
-
<span class="dot" aria-hidden="true"></span>${
|
|
2951
|
-
· ${
|
|
3007
|
+
<div class="sys k-${k(t.kind)}">
|
|
3008
|
+
<span class="dot" aria-hidden="true"></span>${k(t.summary || "")}
|
|
3009
|
+
· ${k(rt(t.at))}
|
|
2952
3010
|
</div>`;
|
|
2953
3011
|
}
|
|
2954
|
-
function
|
|
2955
|
-
const n = t.from === "reporter",
|
|
2956
|
-
let
|
|
2957
|
-
|
|
3012
|
+
function Ln(t, e = "") {
|
|
3013
|
+
const n = t.from === "reporter", a = t.body || "", i = t.attachments || [], r = !n && !!t.automated, s = a ? `<span class="msg-text">${k(a)}</span>` : "", l = i.length ? `<div class="att">${i.map(po).join("")}</div>` : "";
|
|
3014
|
+
let p = "";
|
|
3015
|
+
r ? p = '<span class="msg-who auto">Automatic reply</span>' : !n && t.author && (p = `<span class="msg-who">${k(t.author)}</span>`);
|
|
3016
|
+
const f = r && /reply "yes" or "no"/i.test(a) ? `<div class="quick" role="group" aria-label="Answer">
|
|
3017
|
+
<button type="button" data-quick="Yes, this is the problem">Yes, that's it</button>
|
|
3018
|
+
<button type="button" data-quick="No, that is not the problem">No, it's something else</button>
|
|
3019
|
+
</div>` : "";
|
|
3020
|
+
return `
|
|
2958
3021
|
<div class="msg-row ${n ? "mine" : "theirs"} ${r ? "auto" : ""} ${e}">
|
|
2959
|
-
${
|
|
2960
|
-
<div class="bubble ${
|
|
2961
|
-
|
|
3022
|
+
${p}
|
|
3023
|
+
<div class="bubble ${a ? "" : "silent"}">${s}${l}</div>
|
|
3024
|
+
${f}
|
|
3025
|
+
<span class="msg-when">${k(rt(t.at))}</span>
|
|
2962
3026
|
</div>`;
|
|
2963
3027
|
}
|
|
2964
|
-
function
|
|
2965
|
-
const e =
|
|
3028
|
+
function po(t) {
|
|
3029
|
+
const e = k(t.name || "attachment");
|
|
2966
3030
|
if (!t.url) return `<span class="file"><span class="nm">${e}</span></span>`;
|
|
2967
|
-
const n =
|
|
3031
|
+
const n = k(t.url);
|
|
2968
3032
|
return t.type === "SCREENSHOT" ? `<a href="${n}" target="_blank" rel="noopener noreferrer"><img src="${n}" alt="${e}" loading="lazy"></a>` : t.type === "AUDIO" ? `<audio controls preload="metadata" src="${n}"></audio>` : t.type === "VIDEO" ? `<video controls preload="metadata" src="${n}"></video>` : `
|
|
2969
3033
|
<a class="file" href="${n}" target="_blank" rel="noopener noreferrer" download>
|
|
2970
3034
|
<span class="nm">${e}</span>
|
|
2971
|
-
${t.size ? `<span class="sz">${
|
|
3035
|
+
${t.size ? `<span class="sz">${k(je(t.size))}</span>` : ""}
|
|
2972
3036
|
</a>`;
|
|
2973
3037
|
}
|
|
2974
|
-
function
|
|
3038
|
+
function ho(t) {
|
|
2975
3039
|
return t.scrollHeight - t.scrollTop - t.clientHeight < 40;
|
|
2976
3040
|
}
|
|
2977
|
-
function
|
|
3041
|
+
function xt(t) {
|
|
2978
3042
|
t.scrollTop = t.scrollHeight;
|
|
2979
3043
|
}
|
|
2980
|
-
function
|
|
3044
|
+
function kt(t) {
|
|
2981
3045
|
return {
|
|
2982
3046
|
OPEN: "Open",
|
|
2983
3047
|
IN_PROGRESS: "In progress",
|
|
@@ -2985,21 +3049,21 @@ function vt(t) {
|
|
|
2985
3049
|
CLOSED: "Closed"
|
|
2986
3050
|
}[t] || String(t || "").toLowerCase();
|
|
2987
3051
|
}
|
|
2988
|
-
function
|
|
3052
|
+
function rt(t) {
|
|
2989
3053
|
const e = new Date(t).getTime();
|
|
2990
3054
|
if (!Number.isFinite(e)) return "";
|
|
2991
3055
|
const n = Math.floor((Date.now() - e) / 864e5);
|
|
2992
3056
|
if (n <= 0) return "today";
|
|
2993
3057
|
if (n === 1) return "yesterday";
|
|
2994
3058
|
if (n < 30) return `${n} days ago`;
|
|
2995
|
-
const
|
|
2996
|
-
return
|
|
3059
|
+
const a = Math.floor(n / 30);
|
|
3060
|
+
return a === 1 ? "a month ago" : `${a} months ago`;
|
|
2997
3061
|
}
|
|
2998
|
-
function
|
|
3062
|
+
function k(t) {
|
|
2999
3063
|
return String(t).replace(/[&<>"']/g, (e) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[e]);
|
|
3000
3064
|
}
|
|
3001
|
-
const
|
|
3002
|
-
function
|
|
3065
|
+
const Bn = 8e3;
|
|
3066
|
+
function fo(t = Bn) {
|
|
3003
3067
|
const e = window.AudioContext || window.webkitAudioContext;
|
|
3004
3068
|
try {
|
|
3005
3069
|
return new e({ sampleRate: t });
|
|
@@ -3007,44 +3071,44 @@ function ua(t = In) {
|
|
|
3007
3071
|
return new e();
|
|
3008
3072
|
}
|
|
3009
3073
|
}
|
|
3010
|
-
async function
|
|
3074
|
+
async function go(t) {
|
|
3011
3075
|
if (t.state === "suspended")
|
|
3012
3076
|
try {
|
|
3013
3077
|
await t.resume();
|
|
3014
3078
|
} catch {
|
|
3015
3079
|
}
|
|
3016
3080
|
}
|
|
3017
|
-
function
|
|
3018
|
-
const
|
|
3081
|
+
function mo(t, e, n) {
|
|
3082
|
+
const a = e / n, i = new Float32Array(Math.floor(t.length / a));
|
|
3019
3083
|
for (let r = 0; r < i.length; r++) {
|
|
3020
|
-
const s = Math.floor(r *
|
|
3021
|
-
let
|
|
3022
|
-
for (let
|
|
3023
|
-
i[r] = l > s ?
|
|
3084
|
+
const s = Math.floor(r * a), l = Math.min(Math.floor((r + 1) * a), t.length);
|
|
3085
|
+
let p = 0;
|
|
3086
|
+
for (let f = s; f < l; f++) p += t[f];
|
|
3087
|
+
i[r] = l > s ? p / (l - s) : 0;
|
|
3024
3088
|
}
|
|
3025
3089
|
return i;
|
|
3026
3090
|
}
|
|
3027
|
-
const
|
|
3028
|
-
function
|
|
3091
|
+
const bo = 132, cn = 32635;
|
|
3092
|
+
function yo(t) {
|
|
3029
3093
|
const e = new Uint8Array(t.length);
|
|
3030
3094
|
for (let n = 0; n < t.length; n++) {
|
|
3031
|
-
const
|
|
3032
|
-
let i = Math.round(
|
|
3095
|
+
const a = Math.max(-1, Math.min(1, t[n]));
|
|
3096
|
+
let i = Math.round(a * 32767);
|
|
3033
3097
|
const r = i < 0 ? 128 : 0;
|
|
3034
|
-
r && (i = -i), i >
|
|
3098
|
+
r && (i = -i), i > cn && (i = cn), i += bo;
|
|
3035
3099
|
let s = 7;
|
|
3036
|
-
for (let
|
|
3100
|
+
for (let p = 16384; !(i & p) && s > 0; s--, p >>= 1) ;
|
|
3037
3101
|
const l = i >> s + 3 & 15;
|
|
3038
3102
|
e[n] = ~(r | s << 4 | l) & 255;
|
|
3039
3103
|
}
|
|
3040
3104
|
return e;
|
|
3041
3105
|
}
|
|
3042
|
-
const
|
|
3043
|
-
function
|
|
3044
|
-
const i = t.createMediaStreamSource(e), r = t.createScriptProcessor(
|
|
3106
|
+
const wo = 512;
|
|
3107
|
+
function vo(t, e, n, a = Bn) {
|
|
3108
|
+
const i = t.createMediaStreamSource(e), r = t.createScriptProcessor(wo, 1, 1);
|
|
3045
3109
|
r.onaudioprocess = (l) => {
|
|
3046
|
-
const
|
|
3047
|
-
n(
|
|
3110
|
+
const p = l.inputBuffer.getChannelData(0), f = t.sampleRate === a ? p : mo(p, t.sampleRate, a);
|
|
3111
|
+
n(yo(f));
|
|
3048
3112
|
}, i.connect(r);
|
|
3049
3113
|
const s = t.createGain();
|
|
3050
3114
|
return s.gain.value = 0, r.connect(s), s.connect(t.destination), {
|
|
@@ -3065,8 +3129,8 @@ function ba(t, e, n, o = In) {
|
|
|
3065
3129
|
}
|
|
3066
3130
|
};
|
|
3067
3131
|
}
|
|
3068
|
-
const
|
|
3069
|
-
function
|
|
3132
|
+
const xo = "voiceai.realtime.v1", ko = [{ urls: "stun:stun.l.google.com:19302" }];
|
|
3133
|
+
function $t() {
|
|
3070
3134
|
return navigator.mediaDevices.getUserMedia({
|
|
3071
3135
|
audio: {
|
|
3072
3136
|
// Both ends are on speakers as often as not. Without cancellation each
|
|
@@ -3079,21 +3143,21 @@ function St() {
|
|
|
3079
3143
|
}
|
|
3080
3144
|
});
|
|
3081
3145
|
}
|
|
3082
|
-
function
|
|
3146
|
+
function Et() {
|
|
3083
3147
|
var t;
|
|
3084
3148
|
return typeof window < "u" && typeof window.RTCPeerConnection == "function" && !!((t = navigator.mediaDevices) != null && t.getUserMedia);
|
|
3085
3149
|
}
|
|
3086
|
-
async function
|
|
3150
|
+
async function ln({
|
|
3087
3151
|
realtimeUrl: t,
|
|
3088
3152
|
stream: e,
|
|
3089
3153
|
ringsUntil: n,
|
|
3090
|
-
onState:
|
|
3154
|
+
onState: a,
|
|
3091
3155
|
onAudioBlocked: i,
|
|
3092
3156
|
onMicrophone: r
|
|
3093
3157
|
}) {
|
|
3094
|
-
const s = (m,
|
|
3158
|
+
const s = (m, v) => {
|
|
3095
3159
|
try {
|
|
3096
|
-
|
|
3160
|
+
a == null || a(m, v);
|
|
3097
3161
|
} catch {
|
|
3098
3162
|
}
|
|
3099
3163
|
}, l = (m) => {
|
|
@@ -3101,80 +3165,80 @@ async function rn({
|
|
|
3101
3165
|
i == null || i(m);
|
|
3102
3166
|
} catch {
|
|
3103
3167
|
}
|
|
3104
|
-
},
|
|
3168
|
+
}, p = (m) => {
|
|
3105
3169
|
try {
|
|
3106
3170
|
r == null || r(m);
|
|
3107
3171
|
} catch {
|
|
3108
3172
|
}
|
|
3109
3173
|
};
|
|
3110
|
-
if (!
|
|
3174
|
+
if (!Et()) {
|
|
3111
3175
|
const m = new Error("[BugCatch] this browser cannot make live calls.");
|
|
3112
3176
|
throw s("failed", { reason: "unsupported" }), m;
|
|
3113
3177
|
}
|
|
3114
|
-
let
|
|
3115
|
-
if (!
|
|
3178
|
+
let f = e;
|
|
3179
|
+
if (!f)
|
|
3116
3180
|
try {
|
|
3117
|
-
|
|
3181
|
+
f = await $t();
|
|
3118
3182
|
} catch (m) {
|
|
3119
3183
|
throw s("failed", { reason: "microphone", error: String((m == null ? void 0 : m.name) || m) }), m;
|
|
3120
3184
|
}
|
|
3121
|
-
let
|
|
3185
|
+
let y;
|
|
3122
3186
|
try {
|
|
3123
|
-
|
|
3187
|
+
y = await So(t);
|
|
3124
3188
|
} catch (m) {
|
|
3125
|
-
throw
|
|
3189
|
+
throw un(f), s("failed", { reason: "connect" }), m;
|
|
3126
3190
|
}
|
|
3127
|
-
let
|
|
3191
|
+
let h = null, b = null, g = !1, S = null, A = null, ae = null, C = !1, $ = null, T = null, L = !1;
|
|
3128
3192
|
const Y = [];
|
|
3129
|
-
let
|
|
3130
|
-
const ze = 2e3, be = 5e3, Ue = 3e4,
|
|
3131
|
-
if (!
|
|
3132
|
-
|
|
3193
|
+
let N = !1, Q = !1, U = !1, E = null, oe = null, ee = 0;
|
|
3194
|
+
const ze = 2e3, be = 5e3, Ue = 3e4, ye = 4, V = (m, v) => {
|
|
3195
|
+
if (!g) {
|
|
3196
|
+
g = !0, S && (clearTimeout(S), S = null), re(), T == null || T(), T = null, Ve(), $ == null || $(), $ = null;
|
|
3133
3197
|
try {
|
|
3134
|
-
|
|
3198
|
+
h == null || h.close();
|
|
3135
3199
|
} catch {
|
|
3136
3200
|
}
|
|
3137
|
-
|
|
3201
|
+
un(f), b && (b.srcObject = null, b.remove(), b = null);
|
|
3138
3202
|
try {
|
|
3139
|
-
|
|
3203
|
+
y.readyState === WebSocket.OPEN && y.close(1e3, "call over");
|
|
3140
3204
|
} catch {
|
|
3141
3205
|
}
|
|
3142
|
-
s(m,
|
|
3206
|
+
s(m, v);
|
|
3143
3207
|
}
|
|
3144
3208
|
}, te = (m) => {
|
|
3145
|
-
|
|
3146
|
-
},
|
|
3147
|
-
if (L ||
|
|
3209
|
+
y.readyState === WebSocket.OPEN && y.send(JSON.stringify(m));
|
|
3210
|
+
}, Ee = async () => {
|
|
3211
|
+
if (L || ae || g || !A || !A.audio && !A.transcript) return;
|
|
3148
3212
|
L = !0;
|
|
3149
3213
|
const m = A.encoding || "mulaw";
|
|
3150
3214
|
if (m !== "mulaw") {
|
|
3151
|
-
|
|
3215
|
+
dn(`this call is kept as ${m}, which this SDK cannot produce.`);
|
|
3152
3216
|
return;
|
|
3153
3217
|
}
|
|
3154
|
-
const
|
|
3218
|
+
const v = Number(A.sample_rate) || 8e3;
|
|
3155
3219
|
try {
|
|
3156
|
-
const I =
|
|
3157
|
-
if (await
|
|
3220
|
+
const I = fo(v);
|
|
3221
|
+
if (await go(I), g) {
|
|
3158
3222
|
try {
|
|
3159
3223
|
I.close();
|
|
3160
3224
|
} catch {
|
|
3161
3225
|
}
|
|
3162
3226
|
return;
|
|
3163
3227
|
}
|
|
3164
|
-
const
|
|
3165
|
-
|
|
3166
|
-
},
|
|
3167
|
-
|
|
3228
|
+
const _ = vo(I, f, (F) => {
|
|
3229
|
+
y.readyState === WebSocket.OPEN && y.send(F);
|
|
3230
|
+
}, v);
|
|
3231
|
+
ae = { context: I, tap: _ };
|
|
3168
3232
|
} catch (I) {
|
|
3169
|
-
|
|
3233
|
+
dn(`could not send the copy this call is keeping: ${String((I == null ? void 0 : I.message) || I)}`);
|
|
3170
3234
|
}
|
|
3171
3235
|
};
|
|
3172
3236
|
function Ve() {
|
|
3173
|
-
if (L = !1, !
|
|
3174
|
-
const { context: m, tap:
|
|
3175
|
-
|
|
3237
|
+
if (L = !1, !ae) return;
|
|
3238
|
+
const { context: m, tap: v } = ae;
|
|
3239
|
+
ae = null;
|
|
3176
3240
|
try {
|
|
3177
|
-
|
|
3241
|
+
v.stop();
|
|
3178
3242
|
} catch {
|
|
3179
3243
|
}
|
|
3180
3244
|
try {
|
|
@@ -3183,34 +3247,34 @@ async function rn({
|
|
|
3183
3247
|
}
|
|
3184
3248
|
}
|
|
3185
3249
|
function Oe() {
|
|
3186
|
-
var
|
|
3187
|
-
if (!b ||
|
|
3250
|
+
var v;
|
|
3251
|
+
if (!b || g) return;
|
|
3188
3252
|
let m;
|
|
3189
3253
|
try {
|
|
3190
|
-
m = (
|
|
3254
|
+
m = (v = b.play) == null ? void 0 : v.call(b);
|
|
3191
3255
|
} catch {
|
|
3192
3256
|
Te();
|
|
3193
3257
|
return;
|
|
3194
3258
|
}
|
|
3195
3259
|
if (!m || typeof m.then != "function") {
|
|
3196
|
-
|
|
3260
|
+
fe();
|
|
3197
3261
|
return;
|
|
3198
3262
|
}
|
|
3199
|
-
m.then(
|
|
3263
|
+
m.then(fe, Te);
|
|
3200
3264
|
}
|
|
3201
|
-
function
|
|
3202
|
-
|
|
3265
|
+
function fe() {
|
|
3266
|
+
$ == null || $(), $ = null, C && (C = !1, l(!1));
|
|
3203
3267
|
}
|
|
3204
3268
|
function Te() {
|
|
3205
|
-
|
|
3269
|
+
g || (C || (C = !0, l(!0)), lt());
|
|
3206
3270
|
}
|
|
3207
|
-
function
|
|
3208
|
-
if (
|
|
3209
|
-
const m = () => Oe(),
|
|
3210
|
-
for (const I of
|
|
3271
|
+
function lt() {
|
|
3272
|
+
if ($ || typeof window > "u" || typeof window.addEventListener != "function") return;
|
|
3273
|
+
const m = () => Oe(), v = ["pointerdown", "keydown", "touchstart"];
|
|
3274
|
+
for (const I of v)
|
|
3211
3275
|
window.addEventListener(I, m, { capture: !0, passive: !0 });
|
|
3212
|
-
|
|
3213
|
-
for (const I of
|
|
3276
|
+
$ = () => {
|
|
3277
|
+
for (const I of v)
|
|
3214
3278
|
try {
|
|
3215
3279
|
window.removeEventListener(I, m, { capture: !0 });
|
|
3216
3280
|
} catch {
|
|
@@ -3218,209 +3282,209 @@ async function rn({
|
|
|
3218
3282
|
};
|
|
3219
3283
|
}
|
|
3220
3284
|
const Ie = (m) => {
|
|
3221
|
-
|
|
3222
|
-
for (const
|
|
3223
|
-
T = ce(),
|
|
3224
|
-
|
|
3225
|
-
},
|
|
3226
|
-
var
|
|
3227
|
-
const [I] =
|
|
3228
|
-
I && (b || (b = document.createElement("audio"), b.autoplay = !0, b.playsInline = !0, (
|
|
3229
|
-
},
|
|
3285
|
+
h = new RTCPeerConnection({ iceServers: m != null && m.length ? m : ko });
|
|
3286
|
+
for (const v of f.getAudioTracks()) h.addTrack(v, f);
|
|
3287
|
+
T = ce(), h.onicecandidate = (v) => {
|
|
3288
|
+
v.candidate && te({ type: "signal", signal: { kind: "candidate", payload: v.candidate.toJSON() } });
|
|
3289
|
+
}, h.ontrack = (v) => {
|
|
3290
|
+
var _;
|
|
3291
|
+
const [I] = v.streams;
|
|
3292
|
+
I && (b || (b = document.createElement("audio"), b.autoplay = !0, b.playsInline = !0, (_ = b.setAttribute) == null || _.call(b, "playsinline", ""), b.style.cssText = "position:fixed;width:0;height:0;opacity:0;pointer-events:none", document.body.appendChild(b)), b.srcObject = I, Oe());
|
|
3293
|
+
}, h.onconnectionstatechange = we, h.oniceconnectionstatechange = we;
|
|
3230
3294
|
};
|
|
3231
|
-
function
|
|
3232
|
-
if (!
|
|
3233
|
-
const m =
|
|
3295
|
+
function we() {
|
|
3296
|
+
if (!h || g) return;
|
|
3297
|
+
const m = h.connectionState || h.iceConnectionState;
|
|
3234
3298
|
if (m === "connected" || m === "completed") {
|
|
3235
|
-
|
|
3299
|
+
Q = !0, ee = 0, re(), U = !1, s("connected");
|
|
3236
3300
|
return;
|
|
3237
3301
|
}
|
|
3238
3302
|
if (m === "disconnected") {
|
|
3239
|
-
if (!
|
|
3303
|
+
if (!Q) return;
|
|
3240
3304
|
He(ze);
|
|
3241
3305
|
return;
|
|
3242
3306
|
}
|
|
3243
3307
|
if (m === "failed") {
|
|
3244
|
-
if (!
|
|
3245
|
-
|
|
3308
|
+
if (!Q) {
|
|
3309
|
+
V("failed", { reason: "ice" });
|
|
3246
3310
|
return;
|
|
3247
3311
|
}
|
|
3248
3312
|
He(0);
|
|
3249
3313
|
}
|
|
3250
3314
|
}
|
|
3251
3315
|
function He(m) {
|
|
3252
|
-
|
|
3316
|
+
g || (U || (U = !0, s("reconnecting"), oe = setTimeout(() => V("failed", { reason: "network" }), Ue)), !E && (E = setTimeout(Me, m)));
|
|
3253
3317
|
}
|
|
3254
3318
|
function re() {
|
|
3255
|
-
|
|
3319
|
+
E && (clearTimeout(E), E = null), oe && (clearTimeout(oe), oe = null);
|
|
3256
3320
|
}
|
|
3257
3321
|
async function Me() {
|
|
3258
|
-
if (
|
|
3259
|
-
const m =
|
|
3322
|
+
if (E = null, g || !h) return;
|
|
3323
|
+
const m = h.connectionState || h.iceConnectionState;
|
|
3260
3324
|
if (!(m === "connected" || m === "completed")) {
|
|
3261
|
-
if (!
|
|
3262
|
-
te({ type: "signal", signal: { kind: "restart", payload: {} } }),
|
|
3325
|
+
if (!N) {
|
|
3326
|
+
te({ type: "signal", signal: { kind: "restart", payload: {} } }), E = setTimeout(Me, be);
|
|
3263
3327
|
return;
|
|
3264
3328
|
}
|
|
3265
|
-
ee >=
|
|
3329
|
+
ee >= ye || (ee += 1, await H(), E = setTimeout(Me, be));
|
|
3266
3330
|
}
|
|
3267
3331
|
}
|
|
3268
|
-
async function
|
|
3269
|
-
if (!(
|
|
3332
|
+
async function H() {
|
|
3333
|
+
if (!(g || !h))
|
|
3270
3334
|
try {
|
|
3271
|
-
const m = await
|
|
3272
|
-
await
|
|
3335
|
+
const m = await h.createOffer({ iceRestart: !0 });
|
|
3336
|
+
await h.setLocalDescription(m), te({ type: "signal", signal: { kind: "offer", payload: h.localDescription.toJSON() } });
|
|
3273
3337
|
} catch {
|
|
3274
3338
|
}
|
|
3275
3339
|
}
|
|
3276
3340
|
function ce() {
|
|
3277
|
-
let
|
|
3278
|
-
const
|
|
3279
|
-
if (
|
|
3341
|
+
let v = null, I = !1;
|
|
3342
|
+
const _ = (F) => {
|
|
3343
|
+
if (v && (clearTimeout(v), v = null), F) {
|
|
3280
3344
|
if (!I) return;
|
|
3281
|
-
I = !1,
|
|
3345
|
+
I = !1, p(!0);
|
|
3282
3346
|
return;
|
|
3283
3347
|
}
|
|
3284
|
-
I || (
|
|
3285
|
-
|
|
3348
|
+
I || (v = setTimeout(() => {
|
|
3349
|
+
v = null, !g && (I = !0, p(!1));
|
|
3286
3350
|
}, 600));
|
|
3287
3351
|
};
|
|
3288
|
-
for (const
|
|
3289
|
-
|
|
3290
|
-
|
|
3352
|
+
for (const F of f.getAudioTracks())
|
|
3353
|
+
F.onmute = () => _(!1), F.onunmute = () => _(!0), F.onended = () => {
|
|
3354
|
+
v && (clearTimeout(v), v = null), !I && (I = !0, p(!1));
|
|
3291
3355
|
};
|
|
3292
3356
|
return () => {
|
|
3293
|
-
|
|
3294
|
-
for (const
|
|
3295
|
-
|
|
3357
|
+
v && (clearTimeout(v), v = null);
|
|
3358
|
+
for (const F of f.getAudioTracks())
|
|
3359
|
+
F.onmute = null, F.onunmute = null, F.onended = null;
|
|
3296
3360
|
};
|
|
3297
3361
|
}
|
|
3298
3362
|
const Ke = async () => {
|
|
3299
3363
|
try {
|
|
3300
|
-
const m = await
|
|
3301
|
-
await
|
|
3364
|
+
const m = await h.createOffer();
|
|
3365
|
+
await h.setLocalDescription(m), te({ type: "signal", signal: { kind: "offer", payload: h.localDescription.toJSON() } });
|
|
3302
3366
|
} catch {
|
|
3303
|
-
|
|
3367
|
+
V("failed", { reason: "negotiation" });
|
|
3304
3368
|
}
|
|
3305
|
-
},
|
|
3369
|
+
}, dt = async (m) => {
|
|
3306
3370
|
try {
|
|
3307
|
-
await
|
|
3308
|
-
const
|
|
3309
|
-
await
|
|
3371
|
+
await h.setRemoteDescription(new RTCSessionDescription(m));
|
|
3372
|
+
const v = await h.createAnswer();
|
|
3373
|
+
await h.setLocalDescription(v), te({ type: "signal", signal: { kind: "answer", payload: h.localDescription.toJSON() } }), await Le();
|
|
3310
3374
|
} catch {
|
|
3311
|
-
|
|
3375
|
+
V("failed", { reason: "negotiation" });
|
|
3312
3376
|
}
|
|
3313
3377
|
}, Le = async () => {
|
|
3314
3378
|
for (; Y.length; ) {
|
|
3315
3379
|
const m = Y.shift();
|
|
3316
3380
|
try {
|
|
3317
|
-
await
|
|
3381
|
+
await h.addIceCandidate(new RTCIceCandidate(m));
|
|
3318
3382
|
} catch {
|
|
3319
3383
|
}
|
|
3320
3384
|
}
|
|
3321
3385
|
};
|
|
3322
3386
|
let ve = Promise.resolve();
|
|
3323
|
-
|
|
3324
|
-
ve = ve.then(() =>
|
|
3387
|
+
y.onmessage = (m) => {
|
|
3388
|
+
ve = ve.then(() => ut(m)).catch(() => {
|
|
3325
3389
|
});
|
|
3326
3390
|
};
|
|
3327
|
-
const
|
|
3328
|
-
var I,
|
|
3391
|
+
const ut = async (m) => {
|
|
3392
|
+
var I, _, F, xe, Pe;
|
|
3329
3393
|
if (typeof m.data != "string") return;
|
|
3330
|
-
let
|
|
3394
|
+
let v;
|
|
3331
3395
|
try {
|
|
3332
|
-
|
|
3396
|
+
v = JSON.parse(m.data);
|
|
3333
3397
|
} catch {
|
|
3334
3398
|
return;
|
|
3335
3399
|
}
|
|
3336
|
-
switch (
|
|
3400
|
+
switch (v.type) {
|
|
3337
3401
|
case "session.created": {
|
|
3338
|
-
if (Ie((I =
|
|
3339
|
-
s("connecting"),
|
|
3402
|
+
if (Ie((I = v.data) == null ? void 0 : I.ice_servers), A = ((_ = v.data) == null ? void 0 : _.capture) || null, (F = v.data) != null && F.peer_present) {
|
|
3403
|
+
s("connecting"), Ee();
|
|
3340
3404
|
break;
|
|
3341
3405
|
}
|
|
3342
3406
|
s("ringing"), Be();
|
|
3343
3407
|
break;
|
|
3344
3408
|
}
|
|
3345
3409
|
case "peer.joined": {
|
|
3346
|
-
|
|
3410
|
+
S && (clearTimeout(S), S = null), s("connecting"), N = !!((xe = v.data) != null && xe.should_offer), N && await Ke(), Ee();
|
|
3347
3411
|
break;
|
|
3348
3412
|
}
|
|
3349
3413
|
case "signal": {
|
|
3350
|
-
if (!
|
|
3351
|
-
const { kind: ke, payload:
|
|
3414
|
+
if (!h) break;
|
|
3415
|
+
const { kind: ke, payload: pe } = v.data || {};
|
|
3352
3416
|
if (ke === "offer")
|
|
3353
|
-
await
|
|
3417
|
+
await dt(pe);
|
|
3354
3418
|
else if (ke === "answer")
|
|
3355
3419
|
try {
|
|
3356
|
-
await
|
|
3420
|
+
await h.setRemoteDescription(new RTCSessionDescription(pe)), await Le();
|
|
3357
3421
|
} catch {
|
|
3358
|
-
|
|
3422
|
+
V("failed", { reason: "negotiation" });
|
|
3359
3423
|
}
|
|
3360
3424
|
else if (ke === "candidate")
|
|
3361
|
-
if (
|
|
3425
|
+
if (h.remoteDescription)
|
|
3362
3426
|
try {
|
|
3363
|
-
await
|
|
3427
|
+
await h.addIceCandidate(new RTCIceCandidate(pe));
|
|
3364
3428
|
} catch {
|
|
3365
3429
|
}
|
|
3366
3430
|
else
|
|
3367
|
-
Y.push(
|
|
3368
|
-
else ke === "restart" &&
|
|
3431
|
+
Y.push(pe);
|
|
3432
|
+
else ke === "restart" && N && await H();
|
|
3369
3433
|
break;
|
|
3370
3434
|
}
|
|
3371
3435
|
case "peer.left":
|
|
3372
|
-
|
|
3436
|
+
V("ended", { reason: "peer_left" });
|
|
3373
3437
|
break;
|
|
3374
3438
|
case "error":
|
|
3375
|
-
|
|
3439
|
+
V("failed", { reason: "server", detail: (Pe = v.error) == null ? void 0 : Pe.detail });
|
|
3376
3440
|
break;
|
|
3377
3441
|
case "session.ended":
|
|
3378
|
-
|
|
3442
|
+
V("ended", { reason: "server" });
|
|
3379
3443
|
break;
|
|
3380
3444
|
}
|
|
3381
3445
|
};
|
|
3382
|
-
|
|
3446
|
+
y.onclose = () => V("ended", { reason: "disconnected" }), y.onerror = () => V("failed", { reason: "socket" });
|
|
3383
3447
|
function Be() {
|
|
3384
3448
|
if (!n) return;
|
|
3385
3449
|
const m = new Date(n).getTime() - Date.now();
|
|
3386
|
-
Number.isFinite(m) && (
|
|
3450
|
+
Number.isFinite(m) && (S = setTimeout(() => V("missed"), Math.max(0, m)));
|
|
3387
3451
|
}
|
|
3388
3452
|
return {
|
|
3389
3453
|
hangUp() {
|
|
3390
|
-
te({ type: "session.end" }),
|
|
3454
|
+
te({ type: "session.end" }), V("ended", { reason: "hung_up" });
|
|
3391
3455
|
},
|
|
3392
3456
|
setMuted(m) {
|
|
3393
|
-
for (const
|
|
3457
|
+
for (const v of f.getAudioTracks()) v.enabled = !m;
|
|
3394
3458
|
return m;
|
|
3395
3459
|
},
|
|
3396
3460
|
isMuted() {
|
|
3397
|
-
return
|
|
3461
|
+
return f.getAudioTracks().every((m) => !m.enabled);
|
|
3398
3462
|
}
|
|
3399
3463
|
};
|
|
3400
3464
|
}
|
|
3401
|
-
function
|
|
3465
|
+
function So(t) {
|
|
3402
3466
|
return new Promise((e, n) => {
|
|
3403
|
-
let
|
|
3467
|
+
let a;
|
|
3404
3468
|
try {
|
|
3405
|
-
|
|
3469
|
+
a = new WebSocket(t, xo);
|
|
3406
3470
|
} catch (i) {
|
|
3407
3471
|
n(i);
|
|
3408
3472
|
return;
|
|
3409
3473
|
}
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
},
|
|
3413
|
-
|
|
3474
|
+
a.onopen = () => {
|
|
3475
|
+
a.onopen = null, a.onerror = null, e(a);
|
|
3476
|
+
}, a.onerror = () => {
|
|
3477
|
+
a.onopen = null, a.onerror = null, n(new Error("[BugCatch] could not connect the call."));
|
|
3414
3478
|
};
|
|
3415
3479
|
});
|
|
3416
3480
|
}
|
|
3417
|
-
function
|
|
3481
|
+
function dn(t) {
|
|
3418
3482
|
try {
|
|
3419
3483
|
console.warn(`[BugCatch] ${t}`);
|
|
3420
3484
|
} catch {
|
|
3421
3485
|
}
|
|
3422
3486
|
}
|
|
3423
|
-
function
|
|
3487
|
+
function un(t) {
|
|
3424
3488
|
var e;
|
|
3425
3489
|
for (const n of ((e = t == null ? void 0 : t.getTracks) == null ? void 0 : e.call(t)) ?? [])
|
|
3426
3490
|
try {
|
|
@@ -3428,7 +3492,7 @@ function cn(t) {
|
|
|
3428
3492
|
} catch {
|
|
3429
3493
|
}
|
|
3430
3494
|
}
|
|
3431
|
-
const
|
|
3495
|
+
const Ze = {
|
|
3432
3496
|
cycleMs: 3e3,
|
|
3433
3497
|
peak: 0.045,
|
|
3434
3498
|
bursts: [
|
|
@@ -3436,17 +3500,17 @@ const Xe = {
|
|
|
3436
3500
|
{ at: 0.55, seconds: 0.4, hz: [440, 660] }
|
|
3437
3501
|
]
|
|
3438
3502
|
};
|
|
3439
|
-
let
|
|
3503
|
+
let An = !1;
|
|
3440
3504
|
if (typeof window < "u" && window.addEventListener)
|
|
3441
3505
|
for (const t of ["pointerdown", "keydown", "touchstart"])
|
|
3442
3506
|
window.addEventListener(t, () => {
|
|
3443
|
-
|
|
3507
|
+
An = !0;
|
|
3444
3508
|
}, {
|
|
3445
3509
|
once: !0,
|
|
3446
3510
|
capture: !0,
|
|
3447
3511
|
passive: !0
|
|
3448
3512
|
});
|
|
3449
|
-
function
|
|
3513
|
+
function Co() {
|
|
3450
3514
|
var t;
|
|
3451
3515
|
try {
|
|
3452
3516
|
return !!((t = navigator.userActivation) != null && t.hasBeenActive);
|
|
@@ -3454,8 +3518,8 @@ function xa() {
|
|
|
3454
3518
|
return !1;
|
|
3455
3519
|
}
|
|
3456
3520
|
}
|
|
3457
|
-
function
|
|
3458
|
-
if (!
|
|
3521
|
+
function $o() {
|
|
3522
|
+
if (!An && !Co()) return () => {
|
|
3459
3523
|
};
|
|
3460
3524
|
const t = typeof window < "u" && (window.AudioContext || window.webkitAudioContext);
|
|
3461
3525
|
if (!t) return () => {
|
|
@@ -3467,29 +3531,29 @@ function ka() {
|
|
|
3467
3531
|
return () => {
|
|
3468
3532
|
};
|
|
3469
3533
|
}
|
|
3470
|
-
let n = !1,
|
|
3471
|
-
const i = [], r = ({ at:
|
|
3472
|
-
const
|
|
3473
|
-
b.connect(e.destination), b.gain.setValueAtTime(0,
|
|
3474
|
-
for (const
|
|
3475
|
-
const
|
|
3476
|
-
|
|
3534
|
+
let n = !1, a = null;
|
|
3535
|
+
const i = [], r = ({ at: p, seconds: f, hz: y }) => {
|
|
3536
|
+
const h = e.currentTime + p, b = e.createGain();
|
|
3537
|
+
b.connect(e.destination), b.gain.setValueAtTime(0, h), b.gain.linearRampToValueAtTime(Ze.peak, h + 0.02), b.gain.setValueAtTime(Ze.peak, h + f - 0.06), b.gain.linearRampToValueAtTime(0, h + f);
|
|
3538
|
+
for (const g of y) {
|
|
3539
|
+
const S = e.createOscillator();
|
|
3540
|
+
S.type = "sine", S.frequency.value = g, S.connect(b), S.start(h), S.stop(h + f + 0.02), i.push(S);
|
|
3477
3541
|
}
|
|
3478
3542
|
}, s = () => {
|
|
3479
3543
|
if (!n)
|
|
3480
3544
|
try {
|
|
3481
|
-
|
|
3545
|
+
Ze.bursts.forEach(r);
|
|
3482
3546
|
} catch {
|
|
3483
3547
|
}
|
|
3484
3548
|
}, l = () => {
|
|
3485
|
-
n || (s(),
|
|
3549
|
+
n || (s(), a = setInterval(s, Ze.cycleMs));
|
|
3486
3550
|
};
|
|
3487
3551
|
return e.state === "running" ? l() : e.resume().then(l).catch(() => {
|
|
3488
3552
|
}), () => {
|
|
3489
|
-
n = !0,
|
|
3490
|
-
for (const
|
|
3553
|
+
n = !0, a && clearInterval(a);
|
|
3554
|
+
for (const p of i)
|
|
3491
3555
|
try {
|
|
3492
|
-
|
|
3556
|
+
p.stop();
|
|
3493
3557
|
} catch {
|
|
3494
3558
|
}
|
|
3495
3559
|
try {
|
|
@@ -3498,11 +3562,11 @@ function ka() {
|
|
|
3498
3562
|
}
|
|
3499
3563
|
};
|
|
3500
3564
|
}
|
|
3501
|
-
function
|
|
3565
|
+
function Eo(t) {
|
|
3502
3566
|
const e = Date.parse(t || "");
|
|
3503
3567
|
return Number.isNaN(e) ? 0 : Math.max(0, Math.round((e - Date.now()) / 1e3));
|
|
3504
3568
|
}
|
|
3505
|
-
const
|
|
3569
|
+
const pn = [
|
|
3506
3570
|
"flex:1",
|
|
3507
3571
|
"padding:9px 12px",
|
|
3508
3572
|
"border:0",
|
|
@@ -3510,18 +3574,18 @@ const ln = [
|
|
|
3510
3574
|
"font:600 13px/1.4 inherit",
|
|
3511
3575
|
"cursor:pointer"
|
|
3512
3576
|
].join(";");
|
|
3513
|
-
function
|
|
3577
|
+
function To({
|
|
3514
3578
|
call: t,
|
|
3515
3579
|
accent: e = "#5b6ef5",
|
|
3516
3580
|
position: n = "bottom-right",
|
|
3517
|
-
onAnswer:
|
|
3581
|
+
onAnswer: a,
|
|
3518
3582
|
onDecline: i,
|
|
3519
3583
|
onExpire: r
|
|
3520
3584
|
}) {
|
|
3521
3585
|
if (typeof document > "u" || !document.body) return () => {
|
|
3522
3586
|
};
|
|
3523
|
-
const [s, l] = String(n).split("-"),
|
|
3524
|
-
|
|
3587
|
+
const [s, l] = String(n).split("-"), p = document.createElement("div");
|
|
3588
|
+
p.setAttribute("role", "alertdialog"), p.setAttribute("aria-live", "assertive"), p.setAttribute("aria-label", `${t.from || "Support"} is calling about ${t.reference}`), p.style.cssText = [
|
|
3525
3589
|
"position:fixed",
|
|
3526
3590
|
`${s === "top" ? "top" : "bottom"}:20px`,
|
|
3527
3591
|
`${l === "left" ? "left" : "right"}:20px`,
|
|
@@ -3541,56 +3605,56 @@ function Ca({
|
|
|
3541
3605
|
"transform:translateY(8px)",
|
|
3542
3606
|
"transition:opacity .2s ease,transform .2s ease"
|
|
3543
3607
|
].join(";");
|
|
3544
|
-
const
|
|
3545
|
-
|
|
3546
|
-
const
|
|
3547
|
-
|
|
3548
|
-
const
|
|
3549
|
-
|
|
3608
|
+
const f = document.createElement("div");
|
|
3609
|
+
f.style.cssText = "font-weight:600;font-size:14px;margin-bottom:2px", f.textContent = `${t.from || "Support"} is calling`;
|
|
3610
|
+
const y = document.createElement("div");
|
|
3611
|
+
y.style.cssText = "color:#a4abba;margin-bottom:10px", y.textContent = t.project ? `About your report ${t.reference} · ${t.project}` : `About your report ${t.reference}`;
|
|
3612
|
+
const h = document.createElement("div");
|
|
3613
|
+
h.style.cssText = "color:#7d8598;font-size:12px;margin-bottom:10px";
|
|
3550
3614
|
const b = document.createElement("button");
|
|
3551
|
-
b.type = "button", b.textContent = "Answer", b.style.cssText = `${
|
|
3552
|
-
const
|
|
3553
|
-
|
|
3554
|
-
const
|
|
3555
|
-
if (
|
|
3615
|
+
b.type = "button", b.textContent = "Answer", b.style.cssText = `${pn};background:${e};color:#fff`;
|
|
3616
|
+
const g = document.createElement("button");
|
|
3617
|
+
g.type = "button", g.textContent = "Not now", g.style.cssText = `${pn};background:#2b2f3a;color:#c8cedb`;
|
|
3618
|
+
const S = document.createElement("div");
|
|
3619
|
+
if (S.style.cssText = "display:flex;gap:8px", S.append(b, g), p.append(f, y, h), t.recorded) {
|
|
3556
3620
|
const L = document.createElement("div");
|
|
3557
|
-
L.style.cssText = "color:#7d8598;font-size:12px;margin-bottom:10px", L.textContent = "This call will be recorded.",
|
|
3621
|
+
L.style.cssText = "color:#7d8598;font-size:12px;margin-bottom:10px", L.textContent = "This call will be recorded.", p.append(L);
|
|
3558
3622
|
}
|
|
3559
|
-
|
|
3560
|
-
const A =
|
|
3561
|
-
let
|
|
3562
|
-
const
|
|
3563
|
-
|
|
3623
|
+
p.append(S), document.body.appendChild(p);
|
|
3624
|
+
const A = $o();
|
|
3625
|
+
let ae = !1, C = null;
|
|
3626
|
+
const $ = () => {
|
|
3627
|
+
ae || (ae = !0, C && clearInterval(C), A(), p.style.opacity = "0", p.style.transform = "translateY(8px)", setTimeout(() => p.remove(), 250));
|
|
3564
3628
|
}, T = () => {
|
|
3565
|
-
const L =
|
|
3566
|
-
if (
|
|
3567
|
-
|
|
3629
|
+
const L = Eo(t.ringsUntil);
|
|
3630
|
+
if (h.textContent = L ? `Ringing — ${L}s` : "The call has stopped ringing.", !L) {
|
|
3631
|
+
$();
|
|
3568
3632
|
try {
|
|
3569
3633
|
r == null || r();
|
|
3570
3634
|
} catch {
|
|
3571
3635
|
}
|
|
3572
3636
|
}
|
|
3573
3637
|
};
|
|
3574
|
-
return T(),
|
|
3575
|
-
|
|
3638
|
+
return T(), C = setInterval(T, 1e3), b.addEventListener("click", () => {
|
|
3639
|
+
$();
|
|
3576
3640
|
try {
|
|
3577
|
-
|
|
3641
|
+
a == null || a();
|
|
3578
3642
|
} catch {
|
|
3579
3643
|
}
|
|
3580
|
-
}),
|
|
3581
|
-
|
|
3644
|
+
}), g.addEventListener("click", () => {
|
|
3645
|
+
$();
|
|
3582
3646
|
try {
|
|
3583
3647
|
i == null || i();
|
|
3584
3648
|
} catch {
|
|
3585
3649
|
}
|
|
3586
3650
|
}), requestAnimationFrame(() => {
|
|
3587
|
-
|
|
3588
|
-
}),
|
|
3651
|
+
p.style.opacity = "1", p.style.transform = "translateY(0)";
|
|
3652
|
+
}), $;
|
|
3589
3653
|
}
|
|
3590
|
-
const
|
|
3654
|
+
const hn = {
|
|
3591
3655
|
name: "@sphoro/bugcatch-web-sdk",
|
|
3592
|
-
version: "0.14.
|
|
3593
|
-
},
|
|
3656
|
+
version: "0.14.4"
|
|
3657
|
+
}, Je = {
|
|
3594
3658
|
apiBase: "http://localhost:3000",
|
|
3595
3659
|
apiKey: null,
|
|
3596
3660
|
projectId: null,
|
|
@@ -3642,18 +3706,18 @@ const dn = {
|
|
|
3642
3706
|
// switch the whole thing off.
|
|
3643
3707
|
onIncomingCall: null
|
|
3644
3708
|
};
|
|
3645
|
-
var B, me,
|
|
3646
|
-
class
|
|
3709
|
+
var B, me, Ge, Qn, jn, zn, et, On;
|
|
3710
|
+
class Rn {
|
|
3647
3711
|
constructor() {
|
|
3648
|
-
|
|
3649
|
-
this.config = { ...
|
|
3712
|
+
Xt(this, B);
|
|
3713
|
+
this.config = { ...Je }, this.started = !1, this.teardown = [], this.consoleBuffer = We(Je.consoleLimit), this.networkBuffer = We(Je.networkLimit), this.stopWatching = null, this.notifier = null, this.call = null, this.callStarting = !1, this.ringing = null, this.listeners = /* @__PURE__ */ new Map();
|
|
3650
3714
|
}
|
|
3651
3715
|
init(e = {}) {
|
|
3652
3716
|
if (this.started)
|
|
3653
3717
|
return console.warn("[BugCatch] init() called twice — ignoring the second call."), this;
|
|
3654
|
-
if (this.config = { ...
|
|
3718
|
+
if (this.config = { ...Je, ...e }, !this.config.apiKey) throw new Error("[BugCatch] apiKey is required.");
|
|
3655
3719
|
if (!this.config.projectId) throw new Error("[BugCatch] projectId is required.");
|
|
3656
|
-
return this.consoleBuffer =
|
|
3720
|
+
return this.consoleBuffer = We(this.config.consoleLimit), this.networkBuffer = We(this.config.networkLimit), this.config.captureConsole && this.teardown.push(aa(this.consoleBuffer)), this.config.captureNetwork && this.teardown.push(oa(this.networkBuffer)), this.config.captureErrors && this.teardown.push(ra(this.consoleBuffer)), this.config.widget && this.teardown.push(so(this)), this.config.updates && se() && (this.startWatching(), queueMicrotask(() => P(this, B, me).call(this))), this.started = !0, this;
|
|
3657
3721
|
}
|
|
3658
3722
|
/**
|
|
3659
3723
|
* Open the update stream. Idempotent — init() and a first report both reach
|
|
@@ -3661,26 +3725,26 @@ class Ln {
|
|
|
3661
3725
|
*/
|
|
3662
3726
|
startWatching() {
|
|
3663
3727
|
if (this.stopWatching) return this;
|
|
3664
|
-
this.stopWatching =
|
|
3728
|
+
this.stopWatching = Da({
|
|
3665
3729
|
apiBase: this.config.apiBase,
|
|
3666
3730
|
onUpdate: (n) => {
|
|
3667
3731
|
if (n != null && n.incomingCall) {
|
|
3668
|
-
|
|
3732
|
+
P(this, B, zn).call(this, n);
|
|
3669
3733
|
return;
|
|
3670
3734
|
}
|
|
3671
3735
|
if (n != null && n.callWithdrawn) {
|
|
3672
|
-
|
|
3736
|
+
P(this, B, et).call(this, n.callWithdrawn.callId);
|
|
3673
3737
|
return;
|
|
3674
3738
|
}
|
|
3675
|
-
const
|
|
3676
|
-
typeof this.config.onUpdate == "function" && this.config.onUpdate(
|
|
3739
|
+
const a = Ma(n);
|
|
3740
|
+
typeof this.config.onUpdate == "function" && this.config.onUpdate(a), this.emit("update", a), P(this, B, me).call(this);
|
|
3677
3741
|
}
|
|
3678
3742
|
}), this.teardown.push(() => {
|
|
3679
3743
|
var n;
|
|
3680
3744
|
return (n = this.stopWatching) == null ? void 0 : n.call(this);
|
|
3681
|
-
}), this.teardown.push(() =>
|
|
3745
|
+
}), this.teardown.push(() => P(this, B, et).call(this));
|
|
3682
3746
|
const e = (n) => {
|
|
3683
|
-
(n.key === ot || n.key === null) &&
|
|
3747
|
+
(n.key === ot || n.key === null) && P(this, B, me).call(this);
|
|
3684
3748
|
};
|
|
3685
3749
|
return window.addEventListener("storage", e), this.teardown.push(() => window.removeEventListener("storage", e)), this;
|
|
3686
3750
|
}
|
|
@@ -3697,18 +3761,18 @@ class Ln {
|
|
|
3697
3761
|
on(e, n) {
|
|
3698
3762
|
if (typeof n != "function") return () => {
|
|
3699
3763
|
};
|
|
3700
|
-
const
|
|
3701
|
-
return
|
|
3764
|
+
const a = this.listeners.get(e) || /* @__PURE__ */ new Set();
|
|
3765
|
+
return a.add(n), this.listeners.set(e, a), () => this.off(e, n);
|
|
3702
3766
|
}
|
|
3703
3767
|
off(e, n) {
|
|
3704
|
-
var
|
|
3705
|
-
return (
|
|
3768
|
+
var a;
|
|
3769
|
+
return (a = this.listeners.get(e)) == null || a.delete(n), this;
|
|
3706
3770
|
}
|
|
3707
3771
|
/** Notify listeners; one that throws must not stop the rest. */
|
|
3708
3772
|
emit(e, n) {
|
|
3709
|
-
for (const
|
|
3773
|
+
for (const a of this.listeners.get(e) || [])
|
|
3710
3774
|
try {
|
|
3711
|
-
|
|
3775
|
+
a(n);
|
|
3712
3776
|
} catch (i) {
|
|
3713
3777
|
console.error("[BugCatch] an update listener threw:", i);
|
|
3714
3778
|
}
|
|
@@ -3737,7 +3801,7 @@ class Ln {
|
|
|
3737
3801
|
* knows when its reader has seen one, so it has to say.
|
|
3738
3802
|
*/
|
|
3739
3803
|
markUpdateRead(e) {
|
|
3740
|
-
return
|
|
3804
|
+
return La(e), P(this, B, me).call(this), this;
|
|
3741
3805
|
}
|
|
3742
3806
|
/**
|
|
3743
3807
|
* Mark everything about one report read.
|
|
@@ -3746,11 +3810,11 @@ class Ln {
|
|
|
3746
3810
|
* the thread opens; an integration with its own report view should too.
|
|
3747
3811
|
*/
|
|
3748
3812
|
markReportRead(e) {
|
|
3749
|
-
return
|
|
3813
|
+
return Ba(e), P(this, B, me).call(this), this;
|
|
3750
3814
|
}
|
|
3751
3815
|
/** Mark everything read. The "clear all" behind your own notification list. */
|
|
3752
3816
|
markUpdatesRead() {
|
|
3753
|
-
return
|
|
3817
|
+
return kn(), P(this, B, me).call(this), this;
|
|
3754
3818
|
}
|
|
3755
3819
|
/**
|
|
3756
3820
|
* One report in full, with its timeline — every step from filing to now.
|
|
@@ -3760,12 +3824,12 @@ class Ln {
|
|
|
3760
3824
|
*
|
|
3761
3825
|
* Resolves to null when this browser cannot prove it filed that report.
|
|
3762
3826
|
*/
|
|
3763
|
-
async verifyFix(e, { result: n, resolvedAt:
|
|
3764
|
-
const r = n === "STILL_HAPPENING" ? await
|
|
3765
|
-
return
|
|
3827
|
+
async verifyFix(e, { result: n, resolvedAt: a, note: i }) {
|
|
3828
|
+
const r = n === "STILL_HAPPENING" ? await P(this, B, Ge).call(this, {}) : {};
|
|
3829
|
+
return Za({ apiBase: this.config.apiBase, bugId: e, result: n, resolvedAt: a, note: i, metadata: r.metadata, logs: r.logs });
|
|
3766
3830
|
}
|
|
3767
3831
|
myReport(e) {
|
|
3768
|
-
return
|
|
3832
|
+
return Qa({ apiBase: this.config.apiBase, bugId: e });
|
|
3769
3833
|
}
|
|
3770
3834
|
/**
|
|
3771
3835
|
* Write back on a report this browser filed.
|
|
@@ -3780,8 +3844,8 @@ class Ln {
|
|
|
3780
3844
|
* integration rendering its own can too. Resolves to the stored message, so
|
|
3781
3845
|
* the caller renders what the server kept rather than what it hoped it sent.
|
|
3782
3846
|
*/
|
|
3783
|
-
replyToReport(e, { body: n, attachments:
|
|
3784
|
-
return
|
|
3847
|
+
replyToReport(e, { body: n, attachments: a } = {}) {
|
|
3848
|
+
return Sn({ apiBase: this.config.apiBase, bugId: e, body: n, attachments: a });
|
|
3785
3849
|
}
|
|
3786
3850
|
/**
|
|
3787
3851
|
* Whether this visitor can report something by talking about it instead.
|
|
@@ -3834,7 +3898,7 @@ class Ln {
|
|
|
3834
3898
|
async callKinds() {
|
|
3835
3899
|
var n;
|
|
3836
3900
|
const e = { agent: !1, live: !1 };
|
|
3837
|
-
return !this.config.voice || !((n = this.config.user) != null && n.email) ? e : this.kinds !== void 0 ? this.kinds : (this.kinds = await
|
|
3901
|
+
return !this.config.voice || !((n = this.config.user) != null && n.email) ? e : this.kinds !== void 0 ? this.kinds : (this.kinds = await ja({
|
|
3838
3902
|
apiBase: this.config.apiBase,
|
|
3839
3903
|
apiKey: this.config.apiKey,
|
|
3840
3904
|
projectId: this.config.projectId
|
|
@@ -3855,7 +3919,7 @@ class Ln {
|
|
|
3855
3919
|
* for either of them to be asking about.
|
|
3856
3920
|
*/
|
|
3857
3921
|
canCall(e) {
|
|
3858
|
-
return this.config.voice ?
|
|
3922
|
+
return this.config.voice ? en({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
|
|
3859
3923
|
}
|
|
3860
3924
|
/**
|
|
3861
3925
|
* Ring the team.
|
|
@@ -3898,7 +3962,7 @@ class Ln {
|
|
|
3898
3962
|
try {
|
|
3899
3963
|
if (!await this.callKind())
|
|
3900
3964
|
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.");
|
|
3901
|
-
return await
|
|
3965
|
+
return await P(this, B, jn).call(this, e);
|
|
3902
3966
|
} finally {
|
|
3903
3967
|
this.callStarting = !1;
|
|
3904
3968
|
}
|
|
@@ -3921,7 +3985,7 @@ class Ln {
|
|
|
3921
3985
|
* For a host application drawing its own button. The widget asks this itself.
|
|
3922
3986
|
*/
|
|
3923
3987
|
canCallTeam(e) {
|
|
3924
|
-
return this.config.voice ?
|
|
3988
|
+
return this.config.voice ? en({ apiBase: this.config.apiBase, bugId: e }) : Promise.resolve(!1);
|
|
3925
3989
|
}
|
|
3926
3990
|
/**
|
|
3927
3991
|
* End the call in progress, of either kind. Does nothing when there is not
|
|
@@ -3943,7 +4007,7 @@ class Ln {
|
|
|
3943
4007
|
* nothing to look up in either case.
|
|
3944
4008
|
*/
|
|
3945
4009
|
myReports() {
|
|
3946
|
-
return
|
|
4010
|
+
return Ra({ apiBase: this.config.apiBase });
|
|
3947
4011
|
}
|
|
3948
4012
|
/** True when this browser has filed something, so a "your reports" entry
|
|
3949
4013
|
* point can be hidden until it would show anything. */
|
|
@@ -3956,7 +4020,7 @@ class Ln {
|
|
|
3956
4020
|
*/
|
|
3957
4021
|
forgetReports() {
|
|
3958
4022
|
var e;
|
|
3959
|
-
return (e = this.stopWatching) == null || e.call(this), this.stopWatching = null, this.endCall(),
|
|
4023
|
+
return (e = this.stopWatching) == null || e.call(this), this.stopWatching = null, this.endCall(), $e(), P(this, B, me).call(this), this;
|
|
3960
4024
|
}
|
|
3961
4025
|
/**
|
|
3962
4026
|
* Attach the signed-in user so reports say who hit the bug.
|
|
@@ -3983,46 +4047,46 @@ class Ln {
|
|
|
3983
4047
|
* through the API — so this is also what you call when you drive the SDK
|
|
3984
4048
|
* yourself with `widget: false`.
|
|
3985
4049
|
*/
|
|
3986
|
-
async uploadAttachment(e, n,
|
|
4050
|
+
async uploadAttachment(e, n, a) {
|
|
3987
4051
|
if (!this.started) throw new Error("[BugCatch] call init() first.");
|
|
3988
|
-
return
|
|
4052
|
+
return ga({
|
|
3989
4053
|
apiBase: this.config.apiBase,
|
|
3990
4054
|
apiKey: this.config.apiKey,
|
|
3991
4055
|
blob: e,
|
|
3992
4056
|
mime: n || (e == null ? void 0 : e.type),
|
|
3993
|
-
onProgress:
|
|
4057
|
+
onProgress: a
|
|
3994
4058
|
});
|
|
3995
4059
|
}
|
|
3996
4060
|
/** File a bug with everything captured so far. */
|
|
3997
4061
|
async report({
|
|
3998
4062
|
title: e,
|
|
3999
4063
|
description: n = "",
|
|
4000
|
-
priority:
|
|
4064
|
+
priority: a = "MEDIUM",
|
|
4001
4065
|
metadata: i = {},
|
|
4002
4066
|
attachments: r = [],
|
|
4003
4067
|
references: s = []
|
|
4004
4068
|
} = {}) {
|
|
4005
4069
|
if (!this.started) throw new Error("[BugCatch] call init() first.");
|
|
4006
4070
|
if (!e || !e.trim()) throw new Error("[BugCatch] a title is required.");
|
|
4007
|
-
const l = (r || []).filter((b) => (b == null ? void 0 : b.storageKey) &&
|
|
4071
|
+
const l = (r || []).filter((b) => (b == null ? void 0 : b.storageKey) && nt(b.mime, tt)).map((b) => ({
|
|
4008
4072
|
type: b.type === "VIDEO" ? "VIDEO" : "SCREENSHOT",
|
|
4009
4073
|
storageKey: b.storageKey,
|
|
4010
|
-
mime:
|
|
4074
|
+
mime: nt(b.mime, tt)
|
|
4011
4075
|
}));
|
|
4012
|
-
let
|
|
4076
|
+
let p = await P(this, B, Ge).call(this, {
|
|
4013
4077
|
title: e.trim(),
|
|
4014
4078
|
description: n,
|
|
4015
|
-
priority:
|
|
4079
|
+
priority: a,
|
|
4016
4080
|
metadata: i,
|
|
4017
4081
|
media: l,
|
|
4018
4082
|
references: s
|
|
4019
4083
|
});
|
|
4020
4084
|
if (typeof this.config.beforeSend == "function") {
|
|
4021
|
-
const b = this.config.beforeSend(
|
|
4085
|
+
const b = this.config.beforeSend(p);
|
|
4022
4086
|
if (b === !1) return { cancelled: !0 };
|
|
4023
|
-
b && typeof b == "object" && (
|
|
4087
|
+
b && typeof b == "object" && (p = b);
|
|
4024
4088
|
}
|
|
4025
|
-
const
|
|
4089
|
+
const f = he(this.config.projectId), y = await fetch(`${this.config.apiBase}/ingest/bugs`, {
|
|
4026
4090
|
method: "POST",
|
|
4027
4091
|
headers: {
|
|
4028
4092
|
"Content-Type": "application/json",
|
|
@@ -4031,21 +4095,21 @@ class Ln {
|
|
|
4031
4095
|
// address from here rather than from the payload when it is — on a
|
|
4032
4096
|
// project that requires sign-in, letting the page name a different
|
|
4033
4097
|
// reporter would undo the requirement.
|
|
4034
|
-
...
|
|
4098
|
+
...f != null && f.token ? { "X-BugCatch-Session": f.token } : {}
|
|
4035
4099
|
},
|
|
4036
|
-
body: JSON.stringify(
|
|
4100
|
+
body: JSON.stringify(p)
|
|
4037
4101
|
});
|
|
4038
|
-
if (
|
|
4102
|
+
if (y.status === 401 && f && St(this.config.projectId), !y.ok) {
|
|
4039
4103
|
let b = "";
|
|
4040
4104
|
try {
|
|
4041
|
-
const
|
|
4042
|
-
b = Array.isArray(
|
|
4105
|
+
const g = await y.json();
|
|
4106
|
+
b = Array.isArray(g.message) ? g.message.join(", ") : g.message || "";
|
|
4043
4107
|
} catch {
|
|
4044
4108
|
}
|
|
4045
|
-
throw new Error(`[BugCatch] report failed (HTTP ${
|
|
4109
|
+
throw new Error(`[BugCatch] report failed (HTTP ${y.status})${b ? ": " + b : ""}`);
|
|
4046
4110
|
}
|
|
4047
|
-
const
|
|
4048
|
-
return
|
|
4111
|
+
const h = await y.json();
|
|
4112
|
+
return h.watchToken && (Ct(h.watchToken), this.config.updates && this.startWatching()), h;
|
|
4049
4113
|
}
|
|
4050
4114
|
/**
|
|
4051
4115
|
* What this project asks of the person reporting, and who this browser is
|
|
@@ -4064,11 +4128,11 @@ class Ln {
|
|
|
4064
4128
|
*/
|
|
4065
4129
|
loginState() {
|
|
4066
4130
|
var e;
|
|
4067
|
-
return
|
|
4131
|
+
return Sa({
|
|
4068
4132
|
apiBase: this.config.apiBase,
|
|
4069
4133
|
apiKey: this.config.apiKey,
|
|
4070
4134
|
projectId: this.config.projectId,
|
|
4071
|
-
token: (e =
|
|
4135
|
+
token: (e = he(this.config.projectId)) == null ? void 0 : e.token
|
|
4072
4136
|
});
|
|
4073
4137
|
}
|
|
4074
4138
|
/**
|
|
@@ -4087,7 +4151,7 @@ class Ln {
|
|
|
4087
4151
|
* whether that form should have an identifier box on it.
|
|
4088
4152
|
*/
|
|
4089
4153
|
referenceFields() {
|
|
4090
|
-
return this.refFields ? this.refFields : (this.refFields =
|
|
4154
|
+
return this.refFields ? this.refFields : (this.refFields = no({
|
|
4091
4155
|
apiBase: this.config.apiBase,
|
|
4092
4156
|
apiKey: this.config.apiKey,
|
|
4093
4157
|
projectId: this.config.projectId
|
|
@@ -4103,7 +4167,7 @@ class Ln {
|
|
|
4103
4167
|
* the server. Use loginState() where that matters.
|
|
4104
4168
|
*/
|
|
4105
4169
|
signedInAs() {
|
|
4106
|
-
const e =
|
|
4170
|
+
const e = he(this.config.projectId);
|
|
4107
4171
|
return e ? { email: e.email, name: e.name } : null;
|
|
4108
4172
|
}
|
|
4109
4173
|
/**
|
|
@@ -4118,14 +4182,14 @@ class Ln {
|
|
|
4118
4182
|
* address, which is all a reply-to has ever needed to be worth.
|
|
4119
4183
|
*/
|
|
4120
4184
|
signIn(e, { name: n } = {}) {
|
|
4121
|
-
var
|
|
4122
|
-
return
|
|
4185
|
+
var a;
|
|
4186
|
+
return Ca({
|
|
4123
4187
|
apiBase: this.config.apiBase,
|
|
4124
4188
|
apiKey: this.config.apiKey,
|
|
4125
4189
|
projectId: this.config.projectId,
|
|
4126
4190
|
email: e,
|
|
4127
4191
|
// The name the host app already knows beats asking for one again.
|
|
4128
|
-
name: n ?? ((
|
|
4192
|
+
name: n ?? ((a = this.config.user) == null ? void 0 : a.name) ?? null
|
|
4129
4193
|
});
|
|
4130
4194
|
}
|
|
4131
4195
|
/**
|
|
@@ -4137,14 +4201,14 @@ class Ln {
|
|
|
4137
4201
|
*/
|
|
4138
4202
|
async confirmSignIn(e, n) {
|
|
4139
4203
|
var i;
|
|
4140
|
-
const
|
|
4204
|
+
const a = await $a({
|
|
4141
4205
|
apiBase: this.config.apiBase,
|
|
4142
4206
|
apiKey: this.config.apiKey,
|
|
4143
4207
|
projectId: this.config.projectId,
|
|
4144
4208
|
email: e,
|
|
4145
4209
|
code: n
|
|
4146
4210
|
});
|
|
4147
|
-
return (i = this.config.user) != null && i.email || (this.config.user = { email:
|
|
4211
|
+
return (i = this.config.user) != null && i.email || (this.config.user = { email: a.email, name: a.name || void 0 }), this.emit("signin", { email: a.email, name: a.name }), { email: a.email, name: a.name };
|
|
4148
4212
|
}
|
|
4149
4213
|
/**
|
|
4150
4214
|
* Sign out of this project.
|
|
@@ -4154,14 +4218,14 @@ class Ln {
|
|
|
4154
4218
|
* says — sign-out on a shared machine has to mean signed out on it.
|
|
4155
4219
|
*/
|
|
4156
4220
|
async signOut() {
|
|
4157
|
-
var
|
|
4158
|
-
const e =
|
|
4221
|
+
var a;
|
|
4222
|
+
const e = he(this.config.projectId), n = await Ea({
|
|
4159
4223
|
apiBase: this.config.apiBase,
|
|
4160
4224
|
apiKey: this.config.apiKey,
|
|
4161
4225
|
projectId: this.config.projectId,
|
|
4162
4226
|
token: e == null ? void 0 : e.token
|
|
4163
4227
|
});
|
|
4164
|
-
return e != null && e.email && ((
|
|
4228
|
+
return e != null && e.email && ((a = this.config.user) == null ? void 0 : a.email) === e.email && (this.config.user = null), this.emit("signout", { email: (e == null ? void 0 : e.email) || null }), n;
|
|
4165
4229
|
}
|
|
4166
4230
|
/** What would be sent right now — useful for debugging integrations. */
|
|
4167
4231
|
/**
|
|
@@ -4174,11 +4238,11 @@ class Ln {
|
|
|
4174
4238
|
*/
|
|
4175
4239
|
knownIssues() {
|
|
4176
4240
|
var e;
|
|
4177
|
-
return
|
|
4241
|
+
return Fa({
|
|
4178
4242
|
apiBase: this.config.apiBase,
|
|
4179
4243
|
apiKey: this.config.apiKey,
|
|
4180
4244
|
projectId: this.config.projectId,
|
|
4181
|
-
sessionToken: (e =
|
|
4245
|
+
sessionToken: (e = he(this.config.projectId)) == null ? void 0 : e.token
|
|
4182
4246
|
});
|
|
4183
4247
|
}
|
|
4184
4248
|
/**
|
|
@@ -4188,13 +4252,13 @@ class Ln {
|
|
|
4188
4252
|
* the results of whichever request happens to return last.
|
|
4189
4253
|
*/
|
|
4190
4254
|
matchKnownIssues(e, { signal: n } = {}) {
|
|
4191
|
-
var
|
|
4192
|
-
return
|
|
4255
|
+
var a;
|
|
4256
|
+
return Wa({
|
|
4193
4257
|
apiBase: this.config.apiBase,
|
|
4194
4258
|
apiKey: this.config.apiKey,
|
|
4195
4259
|
projectId: this.config.projectId,
|
|
4196
4260
|
q: e || "",
|
|
4197
|
-
sessionToken: (
|
|
4261
|
+
sessionToken: (a = he(this.config.projectId)) == null ? void 0 : a.token,
|
|
4198
4262
|
signal: n
|
|
4199
4263
|
});
|
|
4200
4264
|
}
|
|
@@ -4211,17 +4275,17 @@ class Ln {
|
|
|
4211
4275
|
* me when this is fixed", and there is no way to keep that promise to
|
|
4212
4276
|
* somebody anonymous.
|
|
4213
4277
|
*/
|
|
4214
|
-
async meToo(e, { email: n, name:
|
|
4278
|
+
async meToo(e, { email: n, name: a } = {}) {
|
|
4215
4279
|
var s, l;
|
|
4216
|
-
const i =
|
|
4217
|
-
return
|
|
4280
|
+
const i = he(this.config.projectId), r = await Jt();
|
|
4281
|
+
return Ya({
|
|
4218
4282
|
apiBase: this.config.apiBase,
|
|
4219
4283
|
apiKey: this.config.apiKey,
|
|
4220
4284
|
projectId: this.config.projectId,
|
|
4221
4285
|
bugId: e,
|
|
4222
4286
|
reporterEmail: n || ((s = this.config.user) == null ? void 0 : s.email),
|
|
4223
|
-
reporterName:
|
|
4224
|
-
metadata: { ...r, user: this.config.user || void 0, sdk:
|
|
4287
|
+
reporterName: a || ((l = this.config.user) == null ? void 0 : l.name),
|
|
4288
|
+
metadata: { ...r, user: this.config.user || void 0, sdk: hn },
|
|
4225
4289
|
logs: {
|
|
4226
4290
|
console: { entries: this.consoleBuffer.all() },
|
|
4227
4291
|
network: { entries: this.networkBuffer.all() }
|
|
@@ -4233,7 +4297,7 @@ class Ln {
|
|
|
4233
4297
|
return {
|
|
4234
4298
|
console: this.consoleBuffer.all(),
|
|
4235
4299
|
network: this.networkBuffer.all(),
|
|
4236
|
-
environment:
|
|
4300
|
+
environment: yn()
|
|
4237
4301
|
};
|
|
4238
4302
|
}
|
|
4239
4303
|
clear() {
|
|
@@ -4261,7 +4325,7 @@ me = function() {
|
|
|
4261
4325
|
if (this.emit("unread", { count: e.length, updates: e }), !!this.config.updateToast) {
|
|
4262
4326
|
if (!this.notifier) {
|
|
4263
4327
|
if (!e.length) return;
|
|
4264
|
-
this.notifier =
|
|
4328
|
+
this.notifier = _a({
|
|
4265
4329
|
accent: this.config.accent,
|
|
4266
4330
|
position: this.config.widgetPosition,
|
|
4267
4331
|
onRead: (n) => this.markUpdateRead(n),
|
|
@@ -4280,26 +4344,26 @@ me = function() {
|
|
|
4280
4344
|
}
|
|
4281
4345
|
this.notifier.render(e);
|
|
4282
4346
|
}
|
|
4283
|
-
},
|
|
4284
|
-
var l,
|
|
4347
|
+
}, Ge = async function({ title: e, description: n = "", priority: a = "MEDIUM", metadata: i = {}, media: r = [], references: s = [] }) {
|
|
4348
|
+
var l, p;
|
|
4285
4349
|
return {
|
|
4286
4350
|
projectId: this.config.projectId,
|
|
4287
4351
|
...e ? { title: e } : {},
|
|
4288
4352
|
description: n,
|
|
4289
|
-
priority:
|
|
4353
|
+
priority: a,
|
|
4290
4354
|
url: window.location.href,
|
|
4291
4355
|
reporterEmail: (l = this.config.user) == null ? void 0 : l.email,
|
|
4292
4356
|
// Sent alongside the address so the dashboard can show a person rather
|
|
4293
4357
|
// than a mailbox, and so the resolution email can open with their name.
|
|
4294
|
-
reporterName: (
|
|
4358
|
+
reporterName: (p = this.config.user) == null ? void 0 : p.name,
|
|
4295
4359
|
metadata: {
|
|
4296
|
-
...await
|
|
4360
|
+
...await Jt(),
|
|
4297
4361
|
release: this.config.release,
|
|
4298
4362
|
environment: this.config.environment,
|
|
4299
4363
|
buildId: this.config.buildId,
|
|
4300
4364
|
...i,
|
|
4301
4365
|
user: this.config.user || void 0,
|
|
4302
|
-
sdk:
|
|
4366
|
+
sdk: hn
|
|
4303
4367
|
},
|
|
4304
4368
|
logs: {
|
|
4305
4369
|
console: { entries: this.consoleBuffer.all() },
|
|
@@ -4315,29 +4379,29 @@ me = function() {
|
|
|
4315
4379
|
// no reason to make the join key one when the source text is right here.
|
|
4316
4380
|
...s.length ? { references: s } : {}
|
|
4317
4381
|
};
|
|
4318
|
-
},
|
|
4319
|
-
const e =
|
|
4382
|
+
}, Qn = async function() {
|
|
4383
|
+
const e = he(this.config.projectId);
|
|
4320
4384
|
let n;
|
|
4321
4385
|
try {
|
|
4322
|
-
n = await
|
|
4386
|
+
n = await za({
|
|
4323
4387
|
apiBase: this.config.apiBase,
|
|
4324
4388
|
apiKey: this.config.apiKey,
|
|
4325
4389
|
token: e == null ? void 0 : e.token,
|
|
4326
|
-
payload: await
|
|
4390
|
+
payload: await P(this, B, Ge).call(this, {})
|
|
4327
4391
|
});
|
|
4328
|
-
} catch (
|
|
4329
|
-
throw
|
|
4392
|
+
} catch (a) {
|
|
4393
|
+
throw a.status === 401 && e && St(this.config.projectId), a;
|
|
4330
4394
|
}
|
|
4331
|
-
return n.watchToken && (
|
|
4332
|
-
},
|
|
4333
|
-
if (!
|
|
4395
|
+
return n.watchToken && (Ct(n.watchToken), this.config.updates && this.startWatching()), n;
|
|
4396
|
+
}, jn = async function(e) {
|
|
4397
|
+
if (!Et())
|
|
4334
4398
|
throw new Error("[BugCatch] this browser cannot make live calls.");
|
|
4335
|
-
const n = await
|
|
4336
|
-
let
|
|
4399
|
+
const n = await $t();
|
|
4400
|
+
let a, i = null;
|
|
4337
4401
|
try {
|
|
4338
4402
|
if (e)
|
|
4339
|
-
|
|
4340
|
-
else if (i = await
|
|
4403
|
+
a = await Oa({ apiBase: this.config.apiBase, bugId: e });
|
|
4404
|
+
else if (i = await P(this, B, Qn).call(this), e = i.id, a = i.live_call, !(a != null && a.realtime_url)) {
|
|
4341
4405
|
const s = new Error(`[BugCatch] the report was filed, but the team could not be rung${i.call_error ? `: ${i.call_error}` : "."}`);
|
|
4342
4406
|
throw s.filed = i, s.reason = i.call_error || null, s;
|
|
4343
4407
|
}
|
|
@@ -4345,15 +4409,15 @@ me = function() {
|
|
|
4345
4409
|
for (const l of n.getTracks()) l.stop();
|
|
4346
4410
|
throw s;
|
|
4347
4411
|
}
|
|
4348
|
-
const r = await
|
|
4349
|
-
realtimeUrl:
|
|
4412
|
+
const r = await ln({
|
|
4413
|
+
realtimeUrl: a.realtime_url,
|
|
4350
4414
|
stream: n,
|
|
4351
|
-
ringsUntil:
|
|
4415
|
+
ringsUntil: a.rings_until,
|
|
4352
4416
|
onState: (s, l) => {
|
|
4353
|
-
(s === "ended" || s === "failed" || s === "missed") && (this.call = null), s === "missed" &&
|
|
4417
|
+
(s === "ended" || s === "failed" || s === "missed") && (this.call = null), s === "missed" && Ha({ apiBase: this.config.apiBase, bugId: e, callId: a.call_id }), typeof this.config.onCallState == "function" && this.config.onCallState(s, { bugId: e, live: !0, ...l }), this.emit("call", { bugId: e, live: !0, state: s, ...l });
|
|
4354
4418
|
}
|
|
4355
4419
|
});
|
|
4356
|
-
return this.call = r, Object.assign(r, { bugId: e, callId:
|
|
4420
|
+
return this.call = r, Object.assign(r, { bugId: e, callId: a.call_id, live: !0, filed: i });
|
|
4357
4421
|
}, // --- being called ------------------------------------------------------------
|
|
4358
4422
|
/**
|
|
4359
4423
|
* Somebody on the team is ringing this page.
|
|
@@ -4369,20 +4433,20 @@ me = function() {
|
|
|
4369
4433
|
* said `voice: false` has said its customers are not to be rung, and a card
|
|
4370
4434
|
* offering a call this page could not join would be worse than none.
|
|
4371
4435
|
*/
|
|
4372
|
-
|
|
4436
|
+
zn = function(e) {
|
|
4373
4437
|
var i;
|
|
4374
4438
|
const n = e.incomingCall;
|
|
4375
|
-
if (!this.config.voice || !
|
|
4376
|
-
|
|
4377
|
-
const
|
|
4439
|
+
if (!this.config.voice || !Et() || ((i = this.ringing) == null ? void 0 : i.callId) === n.callId || this.call || this.callStarting) return;
|
|
4440
|
+
P(this, B, et).call(this);
|
|
4441
|
+
const a = To({
|
|
4378
4442
|
call: n,
|
|
4379
4443
|
accent: this.config.accent,
|
|
4380
4444
|
position: this.config.widgetPosition,
|
|
4381
4445
|
onAnswer: () => {
|
|
4382
|
-
|
|
4446
|
+
P(this, B, On).call(this, e.bugId, n);
|
|
4383
4447
|
},
|
|
4384
4448
|
onDecline: () => {
|
|
4385
|
-
this.ringing = null,
|
|
4449
|
+
this.ringing = null, tn({
|
|
4386
4450
|
apiBase: this.config.apiBase,
|
|
4387
4451
|
bugId: e.bugId,
|
|
4388
4452
|
callId: n.callId
|
|
@@ -4396,14 +4460,14 @@ Rn = function(e) {
|
|
|
4396
4460
|
this.ringing = null, this.emit("incoming-call", { bugId: e.bugId, callId: n.callId, state: "missed" });
|
|
4397
4461
|
}
|
|
4398
4462
|
});
|
|
4399
|
-
if (this.ringing = { callId: n.callId, dismiss:
|
|
4463
|
+
if (this.ringing = { callId: n.callId, dismiss: a }, typeof this.config.onIncomingCall == "function")
|
|
4400
4464
|
try {
|
|
4401
4465
|
this.config.onIncomingCall({ bugId: e.bugId, ...n });
|
|
4402
4466
|
} catch {
|
|
4403
4467
|
}
|
|
4404
4468
|
this.emit("incoming-call", { bugId: e.bugId, callId: n.callId, state: "ringing" });
|
|
4405
4469
|
}, /** Take the card away, whatever it is showing. */
|
|
4406
|
-
|
|
4470
|
+
et = function(e) {
|
|
4407
4471
|
if (this.ringing && !(e && this.ringing.callId !== e)) {
|
|
4408
4472
|
try {
|
|
4409
4473
|
this.ringing.dismiss();
|
|
@@ -4411,32 +4475,32 @@ Ge = function(e) {
|
|
|
4411
4475
|
}
|
|
4412
4476
|
this.ringing = null;
|
|
4413
4477
|
}
|
|
4414
|
-
},
|
|
4478
|
+
}, On = async function(e, n) {
|
|
4415
4479
|
if (this.ringing = null, this.call || this.callStarting) return;
|
|
4416
4480
|
this.callStarting = !0;
|
|
4417
|
-
let
|
|
4481
|
+
let a;
|
|
4418
4482
|
try {
|
|
4419
|
-
|
|
4483
|
+
a = await $t();
|
|
4420
4484
|
} catch (r) {
|
|
4421
|
-
this.callStarting = !1,
|
|
4485
|
+
this.callStarting = !1, tn({ apiBase: this.config.apiBase, bugId: e, callId: n.callId }), this.emit("incoming-call", { bugId: e, callId: n.callId, state: "failed", error: r });
|
|
4422
4486
|
return;
|
|
4423
4487
|
}
|
|
4424
4488
|
let i;
|
|
4425
4489
|
try {
|
|
4426
|
-
i = await
|
|
4490
|
+
i = await qa({
|
|
4427
4491
|
apiBase: this.config.apiBase,
|
|
4428
4492
|
bugId: e,
|
|
4429
4493
|
callId: n.callId
|
|
4430
4494
|
});
|
|
4431
4495
|
} catch (r) {
|
|
4432
|
-
for (const s of
|
|
4496
|
+
for (const s of a.getTracks()) s.stop();
|
|
4433
4497
|
this.callStarting = !1, this.emit("incoming-call", { bugId: e, callId: n.callId, state: "missed", error: r });
|
|
4434
4498
|
return;
|
|
4435
4499
|
}
|
|
4436
4500
|
try {
|
|
4437
|
-
const r = await
|
|
4501
|
+
const r = await ln({
|
|
4438
4502
|
realtimeUrl: i.realtime_url,
|
|
4439
|
-
stream:
|
|
4503
|
+
stream: a,
|
|
4440
4504
|
// No deadline on this side. The ringing is over — it ended when this
|
|
4441
4505
|
// browser claimed the call — and a countdown here would hang up on a
|
|
4442
4506
|
// conversation that has already started.
|
|
@@ -4446,15 +4510,15 @@ Ge = function(e) {
|
|
|
4446
4510
|
});
|
|
4447
4511
|
this.call = r, this.emit("incoming-call", { bugId: e, callId: n.callId, state: "answered" });
|
|
4448
4512
|
} catch (r) {
|
|
4449
|
-
for (const s of
|
|
4513
|
+
for (const s of a.getTracks()) s.stop();
|
|
4450
4514
|
this.emit("incoming-call", { bugId: e, callId: n.callId, state: "failed", error: r });
|
|
4451
4515
|
} finally {
|
|
4452
4516
|
this.callStarting = !1;
|
|
4453
4517
|
}
|
|
4454
4518
|
};
|
|
4455
|
-
const
|
|
4456
|
-
|
|
4519
|
+
const Io = new Rn();
|
|
4520
|
+
Io.Client = Rn;
|
|
4457
4521
|
export {
|
|
4458
|
-
|
|
4522
|
+
Io as default
|
|
4459
4523
|
};
|
|
4460
4524
|
//# sourceMappingURL=bugcatch.es.js.map
|