glitchgrab 1.43.0 → 1.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -0
- package/dist/index.d.mts +15 -3
- package/dist/index.d.ts +15 -3
- package/dist/index.js +701 -74
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +731 -104
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +29 -22
- package/dist/server.d.ts +29 -22
- package/dist/server.js +26 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +26 -1
- package/dist/server.mjs.map +1 -1
- package/dist/{types-YpA_jHFp.d.mts → types-Lldp5noh.d.mts} +7 -0
- package/dist/{types-YpA_jHFp.d.ts → types-Lldp5noh.d.ts} +7 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
useContext,
|
|
7
7
|
useRef as useRef5,
|
|
8
8
|
useEffect as useEffect6,
|
|
9
|
-
useCallback as
|
|
10
|
-
useMemo as
|
|
9
|
+
useCallback as useCallback3,
|
|
10
|
+
useMemo as useMemo4,
|
|
11
11
|
useState as useState6
|
|
12
12
|
} from "react";
|
|
13
13
|
|
|
@@ -634,7 +634,11 @@ async function sendFeedback(payload, baseUrl) {
|
|
|
634
634
|
return null;
|
|
635
635
|
}
|
|
636
636
|
}
|
|
637
|
-
|
|
637
|
+
function signedFields(identity) {
|
|
638
|
+
if (!(identity == null ? void 0 : identity.signature) || !identity.userId) return {};
|
|
639
|
+
return { userId: identity.userId, signature: identity.signature };
|
|
640
|
+
}
|
|
641
|
+
async function enhanceText(text, token, baseUrl, screenshot, context, identity) {
|
|
638
642
|
var _a;
|
|
639
643
|
try {
|
|
640
644
|
const trimmed = text.trim();
|
|
@@ -649,7 +653,8 @@ async function enhanceText(text, token, baseUrl, screenshot, context) {
|
|
|
649
653
|
body: JSON.stringify({
|
|
650
654
|
text: trimmed,
|
|
651
655
|
...screenshot ? { screenshot } : {},
|
|
652
|
-
...context ? { context } : {}
|
|
656
|
+
...context ? { context } : {},
|
|
657
|
+
...signedFields(identity)
|
|
653
658
|
})
|
|
654
659
|
});
|
|
655
660
|
if (!response.ok) return text;
|
|
@@ -662,6 +667,26 @@ async function enhanceText(text, token, baseUrl, screenshot, context) {
|
|
|
662
667
|
return text;
|
|
663
668
|
}
|
|
664
669
|
}
|
|
670
|
+
async function findSimilarIssues(description, token, baseUrl, identity) {
|
|
671
|
+
var _a;
|
|
672
|
+
try {
|
|
673
|
+
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/reports/similar`;
|
|
674
|
+
const response = await fetch(url, {
|
|
675
|
+
method: "POST",
|
|
676
|
+
headers: {
|
|
677
|
+
"Content-Type": "application/json",
|
|
678
|
+
Authorization: `Bearer ${token}`
|
|
679
|
+
},
|
|
680
|
+
body: JSON.stringify({ text: description, ...signedFields(identity) })
|
|
681
|
+
});
|
|
682
|
+
const envelope = await response.json().catch(() => null);
|
|
683
|
+
if (!response.ok || !(envelope == null ? void 0 : envelope.success)) return null;
|
|
684
|
+
if (!((_a = envelope.data) == null ? void 0 : _a.enabled)) return [];
|
|
685
|
+
return Array.isArray(envelope.data.matches) ? envelope.data.matches : [];
|
|
686
|
+
} catch (e) {
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
665
690
|
async function assistTurn(params, token, baseUrl) {
|
|
666
691
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
667
692
|
const offline = {
|
|
@@ -686,7 +711,9 @@ async function assistTurn(params, token, baseUrl) {
|
|
|
686
711
|
conversationId: null,
|
|
687
712
|
question: null,
|
|
688
713
|
report: null,
|
|
689
|
-
degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded
|
|
714
|
+
degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded,
|
|
715
|
+
// An hourly limit, not a cap: the dialog keeps the assistant button.
|
|
716
|
+
retryable: (envelope == null ? void 0 : envelope.retryable) === true
|
|
690
717
|
};
|
|
691
718
|
}
|
|
692
719
|
return {
|
|
@@ -703,13 +730,18 @@ async function assistTurn(params, token, baseUrl) {
|
|
|
703
730
|
return offline;
|
|
704
731
|
}
|
|
705
732
|
}
|
|
706
|
-
async function transcribeAudio(blob, token, baseUrl) {
|
|
733
|
+
async function transcribeAudio(blob, token, baseUrl, identity) {
|
|
707
734
|
var _a;
|
|
708
735
|
try {
|
|
709
736
|
if (blob.size === 0) return "";
|
|
710
737
|
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/sdk/stt`;
|
|
711
738
|
const form = new FormData();
|
|
712
739
|
form.append("file", blob, "audio.webm");
|
|
740
|
+
const signed = signedFields(identity);
|
|
741
|
+
if (signed.userId && signed.signature) {
|
|
742
|
+
form.append("userId", signed.userId);
|
|
743
|
+
form.append("signature", signed.signature);
|
|
744
|
+
}
|
|
713
745
|
const response = await fetch(url, {
|
|
714
746
|
method: "POST",
|
|
715
747
|
headers: { Authorization: `Bearer ${token}` },
|
|
@@ -914,15 +946,15 @@ import {
|
|
|
914
946
|
useState as useState4,
|
|
915
947
|
useRef as useRef4,
|
|
916
948
|
useEffect as useEffect4,
|
|
917
|
-
useMemo
|
|
949
|
+
useMemo as useMemo2
|
|
918
950
|
} from "react";
|
|
919
951
|
import { createPortal as createPortal3 } from "react-dom";
|
|
920
952
|
import { useEffect, useRef, useState } from "react";
|
|
921
953
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
922
|
-
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
954
|
+
import { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
923
955
|
import { createPortal } from "react-dom";
|
|
924
956
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
925
|
-
import { useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
957
|
+
import { useCallback, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
|
|
926
958
|
import { createPortal as createPortal2 } from "react-dom";
|
|
927
959
|
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
928
960
|
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -1283,6 +1315,59 @@ var SEVERITY_LABELS = {
|
|
|
1283
1315
|
};
|
|
1284
1316
|
var MAX_ASSIST_IMAGES = 3;
|
|
1285
1317
|
var MAX_ASSIST_IMAGE_CHARS = 35e5;
|
|
1318
|
+
var MAX_ASSIST_FILES = 3;
|
|
1319
|
+
var MAX_ASSIST_FILE_CHARS = 3e5;
|
|
1320
|
+
var MAX_ASSIST_FILE_CHARS_EACH = 2e5;
|
|
1321
|
+
var TEXT_ATTACHMENT_EXTENSIONS = [
|
|
1322
|
+
".html",
|
|
1323
|
+
".htm",
|
|
1324
|
+
".txt",
|
|
1325
|
+
".md",
|
|
1326
|
+
".json",
|
|
1327
|
+
".xml",
|
|
1328
|
+
".log",
|
|
1329
|
+
".yml",
|
|
1330
|
+
".yaml",
|
|
1331
|
+
".csv",
|
|
1332
|
+
".har",
|
|
1333
|
+
".js",
|
|
1334
|
+
".mjs",
|
|
1335
|
+
".cjs",
|
|
1336
|
+
".ts",
|
|
1337
|
+
".tsx",
|
|
1338
|
+
".jsx",
|
|
1339
|
+
".css",
|
|
1340
|
+
".scss",
|
|
1341
|
+
".py",
|
|
1342
|
+
".sh"
|
|
1343
|
+
];
|
|
1344
|
+
var BINARY_ATTACHMENT_EXTENSIONS = [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".zip"];
|
|
1345
|
+
var ATTACHMENT_ACCEPT = [
|
|
1346
|
+
"image/*",
|
|
1347
|
+
...TEXT_ATTACHMENT_EXTENSIONS,
|
|
1348
|
+
...BINARY_ATTACHMENT_EXTENSIONS
|
|
1349
|
+
].join(",");
|
|
1350
|
+
var ASSIST_ATTACHMENT_ACCEPT = ["image/*", ...TEXT_ATTACHMENT_EXTENSIONS].join(",");
|
|
1351
|
+
function isAssistReadableFile(name) {
|
|
1352
|
+
const lower = name.toLowerCase();
|
|
1353
|
+
return TEXT_ATTACHMENT_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
1354
|
+
}
|
|
1355
|
+
function decodeTextDataUrl(dataUrl) {
|
|
1356
|
+
try {
|
|
1357
|
+
if (!dataUrl.startsWith("data:")) return null;
|
|
1358
|
+
const comma = dataUrl.indexOf(",");
|
|
1359
|
+
if (comma < 0) return null;
|
|
1360
|
+
const meta = dataUrl.slice(5, comma);
|
|
1361
|
+
const payload = dataUrl.slice(comma + 1);
|
|
1362
|
+
if (!meta.endsWith(";base64")) return decodeURIComponent(payload);
|
|
1363
|
+
const binary = atob(payload);
|
|
1364
|
+
const bytes = new Uint8Array(binary.length);
|
|
1365
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1366
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
1367
|
+
} catch (e) {
|
|
1368
|
+
return null;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1286
1371
|
function getTypeLabel(type) {
|
|
1287
1372
|
switch (type) {
|
|
1288
1373
|
case "RATING":
|
|
@@ -1314,6 +1399,22 @@ function pickAssistImages(all) {
|
|
|
1314
1399
|
}
|
|
1315
1400
|
return picked;
|
|
1316
1401
|
}
|
|
1402
|
+
var NO_FILES = [];
|
|
1403
|
+
function pickAssistFiles(files) {
|
|
1404
|
+
const picked = [];
|
|
1405
|
+
let total = 0;
|
|
1406
|
+
for (let i = files.length - 1; i >= 0 && picked.length < MAX_ASSIST_FILES; i--) {
|
|
1407
|
+
const attached = files[i];
|
|
1408
|
+
if (!isAssistReadableFile(attached.name)) continue;
|
|
1409
|
+
const text = decodeTextDataUrl(attached.dataUrl);
|
|
1410
|
+
if (!text || !text.trim()) continue;
|
|
1411
|
+
const content = text.slice(0, MAX_ASSIST_FILE_CHARS_EACH);
|
|
1412
|
+
if (total + content.length > MAX_ASSIST_FILE_CHARS) continue;
|
|
1413
|
+
picked.unshift({ index: i, file: { name: attached.name, content } });
|
|
1414
|
+
total += content.length;
|
|
1415
|
+
}
|
|
1416
|
+
return picked;
|
|
1417
|
+
}
|
|
1317
1418
|
var STARTERS = [
|
|
1318
1419
|
"Something on this page is broken",
|
|
1319
1420
|
"It did the wrong thing",
|
|
@@ -1390,7 +1491,9 @@ function AssistSheet({
|
|
|
1390
1491
|
theme: t2,
|
|
1391
1492
|
screenshots,
|
|
1392
1493
|
pageShot = null,
|
|
1393
|
-
|
|
1494
|
+
onAddFiles,
|
|
1495
|
+
files = NO_FILES,
|
|
1496
|
+
onRemoveFile,
|
|
1394
1497
|
onRemoveImage,
|
|
1395
1498
|
attachmentCount,
|
|
1396
1499
|
context,
|
|
@@ -1461,6 +1564,8 @@ function AssistSheet({
|
|
|
1461
1564
|
}
|
|
1462
1565
|
}
|
|
1463
1566
|
const readShots = new Set(pickAssistImages(screenshots));
|
|
1567
|
+
const sentFiles = useMemo(() => pickAssistFiles(files), [files]);
|
|
1568
|
+
const readFiles = new Set(sentFiles.map((f) => f.index));
|
|
1464
1569
|
function leave(type, detail) {
|
|
1465
1570
|
logEvent(type, detail);
|
|
1466
1571
|
flushEvents();
|
|
@@ -1474,10 +1579,10 @@ function AssistSheet({
|
|
|
1474
1579
|
var _a;
|
|
1475
1580
|
if (phase === "draft") (_a = draftRef.current) == null ? void 0 : _a.focus();
|
|
1476
1581
|
}, [phase]);
|
|
1477
|
-
function degradeKeepingEvents(events, message) {
|
|
1582
|
+
function degradeKeepingEvents(events, message, retryable) {
|
|
1478
1583
|
if (events) eventsRef.current = [...events, ...eventsRef.current];
|
|
1479
1584
|
flushEvents();
|
|
1480
|
-
onDegrade(message);
|
|
1585
|
+
onDegrade(message, retryable);
|
|
1481
1586
|
}
|
|
1482
1587
|
async function runTurn(history2) {
|
|
1483
1588
|
var _a, _b, _c, _d;
|
|
@@ -1495,6 +1600,9 @@ function AssistSheet({
|
|
|
1495
1600
|
),
|
|
1496
1601
|
conversationId,
|
|
1497
1602
|
screenshots: sent,
|
|
1603
|
+
// Only when there is something: an older server then sees the body
|
|
1604
|
+
// it always did.
|
|
1605
|
+
...sentFiles.length > 0 ? { files: sentFiles.map((f) => f.file) } : {},
|
|
1498
1606
|
context: {
|
|
1499
1607
|
...context != null ? context : {},
|
|
1500
1608
|
imageSources: sent.map((shot) => pageShot && shot === pageShot ? "page" : "attached"),
|
|
@@ -1514,7 +1622,7 @@ function AssistSheet({
|
|
|
1514
1622
|
setBusy(false);
|
|
1515
1623
|
}
|
|
1516
1624
|
if (result.degraded) {
|
|
1517
|
-
degradeKeepingEvents(events, result.degraded);
|
|
1625
|
+
degradeKeepingEvents(events, result.degraded, result.retryable === true);
|
|
1518
1626
|
return;
|
|
1519
1627
|
}
|
|
1520
1628
|
if (result.conversationId) {
|
|
@@ -1614,7 +1722,7 @@ function AssistSheet({
|
|
|
1614
1722
|
minWidth: 0
|
|
1615
1723
|
},
|
|
1616
1724
|
children: [
|
|
1617
|
-
/* @__PURE__ */ jsx2("span", { style: { color:
|
|
1725
|
+
/* @__PURE__ */ jsx2("span", { style: { color: t2.text, fontWeight: 600 }, children: title ? "Our team is already on this" : `Our team is already on #${duplicate.number}` }),
|
|
1618
1726
|
title && /* @__PURE__ */ jsxs2("span", { style: { color: t2.textMuted, wordBreak: "break-word" }, children: [
|
|
1619
1727
|
"#",
|
|
1620
1728
|
duplicate.number,
|
|
@@ -2502,7 +2610,7 @@ function AssistSheet({
|
|
|
2502
2610
|
// instead of remounting, and a draft is something you can
|
|
2503
2611
|
// still reply to (#360), not a form that replaced the chat.
|
|
2504
2612
|
/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2505
|
-
(screenshots.length > 0 ||
|
|
2613
|
+
(screenshots.length > 0 || files.length > 0 || onAddFiles) && /* @__PURE__ */ jsxs2(
|
|
2506
2614
|
"div",
|
|
2507
2615
|
{
|
|
2508
2616
|
style: {
|
|
@@ -2606,11 +2714,118 @@ function AssistSheet({
|
|
|
2606
2714
|
`${i}-${shot.slice(-16)}`
|
|
2607
2715
|
);
|
|
2608
2716
|
}),
|
|
2609
|
-
|
|
2717
|
+
files.map((file, i) => {
|
|
2718
|
+
const read = readFiles.has(i);
|
|
2719
|
+
const why = read ? "the assistant reads this file" : isAssistReadableFile(file.name) ? "attached, but more than one message can carry, so the assistant is not reading it" : "attached to the report \u2014 the assistant can't read this kind of file";
|
|
2720
|
+
return /* @__PURE__ */ jsxs2(
|
|
2721
|
+
"div",
|
|
2722
|
+
{
|
|
2723
|
+
"data-gg-assist-file": "",
|
|
2724
|
+
"data-gg-assist-file-read": read ? "" : void 0,
|
|
2725
|
+
title: `${file.name} \u2014 ${why}`,
|
|
2726
|
+
style: {
|
|
2727
|
+
position: "relative",
|
|
2728
|
+
height: "40px",
|
|
2729
|
+
maxWidth: "170px",
|
|
2730
|
+
display: "flex",
|
|
2731
|
+
alignItems: "center",
|
|
2732
|
+
gap: "6px",
|
|
2733
|
+
padding: "0 10px",
|
|
2734
|
+
borderRadius: "8px",
|
|
2735
|
+
border: `1px solid ${read ? t2.accent : t2.inputBorder}`,
|
|
2736
|
+
opacity: read ? 1 : 0.55,
|
|
2737
|
+
boxSizing: "border-box",
|
|
2738
|
+
flexShrink: 0
|
|
2739
|
+
},
|
|
2740
|
+
children: [
|
|
2741
|
+
/* @__PURE__ */ jsx2("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsx2(
|
|
2742
|
+
"path",
|
|
2743
|
+
{
|
|
2744
|
+
d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z M14 2v6h6",
|
|
2745
|
+
stroke: t2.textMuted,
|
|
2746
|
+
strokeWidth: "1.5",
|
|
2747
|
+
strokeLinecap: "round",
|
|
2748
|
+
strokeLinejoin: "round"
|
|
2749
|
+
}
|
|
2750
|
+
) }),
|
|
2751
|
+
/* @__PURE__ */ jsx2(
|
|
2752
|
+
"span",
|
|
2753
|
+
{
|
|
2754
|
+
style: {
|
|
2755
|
+
fontSize: "11.5px",
|
|
2756
|
+
color: t2.text,
|
|
2757
|
+
overflow: "hidden",
|
|
2758
|
+
textOverflow: "ellipsis",
|
|
2759
|
+
whiteSpace: "nowrap"
|
|
2760
|
+
},
|
|
2761
|
+
children: file.name
|
|
2762
|
+
}
|
|
2763
|
+
),
|
|
2764
|
+
onRemoveFile && /* @__PURE__ */ jsx2(
|
|
2765
|
+
"button",
|
|
2766
|
+
{
|
|
2767
|
+
type: "button",
|
|
2768
|
+
"data-gg-assist-remove-file": "",
|
|
2769
|
+
"aria-label": `Remove file ${file.name}`,
|
|
2770
|
+
title: "Remove this file",
|
|
2771
|
+
onClick: () => {
|
|
2772
|
+
logEvent("file_removed", read ? "read" : "not read");
|
|
2773
|
+
onRemoveFile(i);
|
|
2774
|
+
},
|
|
2775
|
+
style: {
|
|
2776
|
+
position: "absolute",
|
|
2777
|
+
top: "-13px",
|
|
2778
|
+
right: "-13px",
|
|
2779
|
+
width: "32px",
|
|
2780
|
+
height: "32px",
|
|
2781
|
+
border: "none",
|
|
2782
|
+
background: "transparent",
|
|
2783
|
+
padding: 0,
|
|
2784
|
+
cursor: "pointer",
|
|
2785
|
+
display: "flex",
|
|
2786
|
+
alignItems: "center",
|
|
2787
|
+
justifyContent: "center",
|
|
2788
|
+
borderRadius: "50%"
|
|
2789
|
+
},
|
|
2790
|
+
children: /* @__PURE__ */ jsx2(
|
|
2791
|
+
"span",
|
|
2792
|
+
{
|
|
2793
|
+
"aria-hidden": "true",
|
|
2794
|
+
style: {
|
|
2795
|
+
width: "20px",
|
|
2796
|
+
height: "20px",
|
|
2797
|
+
boxSizing: "border-box",
|
|
2798
|
+
borderRadius: "50%",
|
|
2799
|
+
border: `2px solid ${t2.bg}`,
|
|
2800
|
+
background: "#ef4444",
|
|
2801
|
+
color: "#fff",
|
|
2802
|
+
display: "flex",
|
|
2803
|
+
alignItems: "center",
|
|
2804
|
+
justifyContent: "center"
|
|
2805
|
+
},
|
|
2806
|
+
children: /* @__PURE__ */ jsx2("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx2(
|
|
2807
|
+
"path",
|
|
2808
|
+
{
|
|
2809
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
2810
|
+
stroke: "currentColor",
|
|
2811
|
+
strokeWidth: "1.6",
|
|
2812
|
+
strokeLinecap: "round"
|
|
2813
|
+
}
|
|
2814
|
+
) })
|
|
2815
|
+
}
|
|
2816
|
+
)
|
|
2817
|
+
}
|
|
2818
|
+
)
|
|
2819
|
+
]
|
|
2820
|
+
},
|
|
2821
|
+
`file-${i}-${file.name}`
|
|
2822
|
+
);
|
|
2823
|
+
}),
|
|
2824
|
+
onAddFiles && /* @__PURE__ */ jsxs2(
|
|
2610
2825
|
"label",
|
|
2611
2826
|
{
|
|
2612
2827
|
"data-gg-assist-attach": "",
|
|
2613
|
-
title: "Attach an image \u2014 or
|
|
2828
|
+
title: "Attach an image or a file (html, json, log\u2026) \u2014 or paste one",
|
|
2614
2829
|
style: {
|
|
2615
2830
|
width: "40px",
|
|
2616
2831
|
height: "40px",
|
|
@@ -2630,14 +2845,18 @@ function AssistSheet({
|
|
|
2630
2845
|
"input",
|
|
2631
2846
|
{
|
|
2632
2847
|
type: "file",
|
|
2633
|
-
accept:
|
|
2848
|
+
accept: ASSIST_ATTACHMENT_ACCEPT,
|
|
2634
2849
|
multiple: true,
|
|
2635
2850
|
onChange: (e) => {
|
|
2636
2851
|
var _a;
|
|
2637
|
-
const
|
|
2638
|
-
if (
|
|
2639
|
-
|
|
2640
|
-
|
|
2852
|
+
const picked = Array.from((_a = e.target.files) != null ? _a : []);
|
|
2853
|
+
if (picked.length) {
|
|
2854
|
+
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
2855
|
+
if (images) logEvent("image_added", String(images));
|
|
2856
|
+
if (picked.length > images) {
|
|
2857
|
+
logEvent("file_added", String(picked.length - images));
|
|
2858
|
+
}
|
|
2859
|
+
onAddFiles(picked);
|
|
2641
2860
|
}
|
|
2642
2861
|
e.target.value = "";
|
|
2643
2862
|
},
|
|
@@ -2818,6 +3037,7 @@ function AssistSheet({
|
|
|
2818
3037
|
}
|
|
2819
3038
|
var FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2820
3039
|
var FAILED = "Couldn't send it. Try again in a moment.";
|
|
3040
|
+
var MAX_SELF_REPORT_IMAGES = 5;
|
|
2821
3041
|
function describeSentAlong(hasChat, screenshotCount) {
|
|
2822
3042
|
const parts = [
|
|
2823
3043
|
...hasChat ? ["your AI chat"] : [],
|
|
@@ -2841,11 +3061,49 @@ function GlitchgrabProblemPanel({
|
|
|
2841
3061
|
const [busy, setBusy] = useState3(false);
|
|
2842
3062
|
const [sent, setSent] = useState3(false);
|
|
2843
3063
|
const [error, setError] = useState3(null);
|
|
3064
|
+
const [images, setImages] = useState3(
|
|
3065
|
+
() => screenshots.slice(0, MAX_SELF_REPORT_IMAGES)
|
|
3066
|
+
);
|
|
2844
3067
|
const inputRef = useRef3(null);
|
|
3068
|
+
const fileRef = useRef3(null);
|
|
2845
3069
|
useEffect3(() => {
|
|
2846
3070
|
var _a;
|
|
2847
3071
|
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
2848
3072
|
}, []);
|
|
3073
|
+
const addImages = useCallback((files) => {
|
|
3074
|
+
const picked = files.filter((file) => file.type.startsWith("image/"));
|
|
3075
|
+
if (!picked.length) return;
|
|
3076
|
+
void Promise.all(picked.map((file) => encodeImageFile(file).catch(() => null))).then(
|
|
3077
|
+
(encoded) => {
|
|
3078
|
+
const added = encoded.filter((url) => !!url);
|
|
3079
|
+
if (added.length) {
|
|
3080
|
+
setImages((prev) => [...prev, ...added].slice(0, MAX_SELF_REPORT_IMAGES));
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
);
|
|
3084
|
+
}, []);
|
|
3085
|
+
useEffect3(() => {
|
|
3086
|
+
const onPaste = (e) => {
|
|
3087
|
+
var _a;
|
|
3088
|
+
try {
|
|
3089
|
+
const items = (_a = e.clipboardData) == null ? void 0 : _a.items;
|
|
3090
|
+
if (!items) return;
|
|
3091
|
+
const files = [];
|
|
3092
|
+
for (let i = 0; i < items.length; i++) {
|
|
3093
|
+
if (items[i].kind !== "file") continue;
|
|
3094
|
+
const file = items[i].getAsFile();
|
|
3095
|
+
if (file) files.push(file);
|
|
3096
|
+
}
|
|
3097
|
+
if (!files.length) return;
|
|
3098
|
+
e.preventDefault();
|
|
3099
|
+
e.stopImmediatePropagation();
|
|
3100
|
+
addImages(files);
|
|
3101
|
+
} catch (e2) {
|
|
3102
|
+
}
|
|
3103
|
+
};
|
|
3104
|
+
window.addEventListener("paste", onPaste, true);
|
|
3105
|
+
return () => window.removeEventListener("paste", onPaste, true);
|
|
3106
|
+
}, [addImages]);
|
|
2849
3107
|
useEffect3(() => {
|
|
2850
3108
|
const onKey = (e) => {
|
|
2851
3109
|
if (e.key !== "Escape") return;
|
|
@@ -2861,7 +3119,13 @@ function GlitchgrabProblemPanel({
|
|
|
2861
3119
|
setBusy(true);
|
|
2862
3120
|
setError(null);
|
|
2863
3121
|
try {
|
|
2864
|
-
const result = await send({
|
|
3122
|
+
const result = await send({
|
|
3123
|
+
description,
|
|
3124
|
+
surface,
|
|
3125
|
+
conversationId,
|
|
3126
|
+
reportType,
|
|
3127
|
+
screenshots: images
|
|
3128
|
+
});
|
|
2865
3129
|
if (result == null ? void 0 : result.success) setSent(true);
|
|
2866
3130
|
else setError((result == null ? void 0 : result.message) || FAILED);
|
|
2867
3131
|
} catch (e) {
|
|
@@ -3014,6 +3278,134 @@ function GlitchgrabProblemPanel({
|
|
|
3014
3278
|
}
|
|
3015
3279
|
}
|
|
3016
3280
|
),
|
|
3281
|
+
/* @__PURE__ */ jsxs3(
|
|
3282
|
+
"div",
|
|
3283
|
+
{
|
|
3284
|
+
"data-gg-self-report-images": "",
|
|
3285
|
+
style: {
|
|
3286
|
+
display: "flex",
|
|
3287
|
+
flexWrap: "wrap",
|
|
3288
|
+
alignItems: "center",
|
|
3289
|
+
gap: "8px",
|
|
3290
|
+
marginTop: "10px"
|
|
3291
|
+
},
|
|
3292
|
+
children: [
|
|
3293
|
+
images.map((src, i) => /* @__PURE__ */ jsxs3("div", { style: { position: "relative", width: "48px", height: "48px" }, children: [
|
|
3294
|
+
/* @__PURE__ */ jsx3(
|
|
3295
|
+
"img",
|
|
3296
|
+
{
|
|
3297
|
+
src,
|
|
3298
|
+
alt: `Screenshot ${i + 1}`,
|
|
3299
|
+
style: {
|
|
3300
|
+
width: "100%",
|
|
3301
|
+
height: "100%",
|
|
3302
|
+
objectFit: "cover",
|
|
3303
|
+
display: "block",
|
|
3304
|
+
boxSizing: "border-box",
|
|
3305
|
+
borderRadius: "8px",
|
|
3306
|
+
border: `1px solid ${t2.inputBorder}`
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
),
|
|
3310
|
+
/* @__PURE__ */ jsx3(
|
|
3311
|
+
"button",
|
|
3312
|
+
{
|
|
3313
|
+
type: "button",
|
|
3314
|
+
"data-gg-self-report-remove-image": "",
|
|
3315
|
+
"aria-label": `Remove screenshot ${i + 1}`,
|
|
3316
|
+
title: "Don't send this one",
|
|
3317
|
+
onClick: () => setImages((prev) => prev.filter((_, j) => j !== i)),
|
|
3318
|
+
style: {
|
|
3319
|
+
position: "absolute",
|
|
3320
|
+
top: "-13px",
|
|
3321
|
+
right: "-13px",
|
|
3322
|
+
width: "32px",
|
|
3323
|
+
height: "32px",
|
|
3324
|
+
border: "none",
|
|
3325
|
+
background: "transparent",
|
|
3326
|
+
padding: 0,
|
|
3327
|
+
cursor: "pointer",
|
|
3328
|
+
display: "flex",
|
|
3329
|
+
alignItems: "center",
|
|
3330
|
+
justifyContent: "center",
|
|
3331
|
+
borderRadius: "50%"
|
|
3332
|
+
},
|
|
3333
|
+
children: /* @__PURE__ */ jsx3(
|
|
3334
|
+
"span",
|
|
3335
|
+
{
|
|
3336
|
+
"aria-hidden": "true",
|
|
3337
|
+
style: {
|
|
3338
|
+
width: "20px",
|
|
3339
|
+
height: "20px",
|
|
3340
|
+
boxSizing: "border-box",
|
|
3341
|
+
borderRadius: "50%",
|
|
3342
|
+
border: `2px solid ${t2.bg}`,
|
|
3343
|
+
background: "#ef4444",
|
|
3344
|
+
color: "#fff",
|
|
3345
|
+
display: "flex",
|
|
3346
|
+
alignItems: "center",
|
|
3347
|
+
justifyContent: "center"
|
|
3348
|
+
},
|
|
3349
|
+
children: /* @__PURE__ */ jsx3("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx3(
|
|
3350
|
+
"path",
|
|
3351
|
+
{
|
|
3352
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
3353
|
+
stroke: "currentColor",
|
|
3354
|
+
strokeWidth: "1.6",
|
|
3355
|
+
strokeLinecap: "round"
|
|
3356
|
+
}
|
|
3357
|
+
) })
|
|
3358
|
+
}
|
|
3359
|
+
)
|
|
3360
|
+
}
|
|
3361
|
+
)
|
|
3362
|
+
] }, i)),
|
|
3363
|
+
images.length < MAX_SELF_REPORT_IMAGES && /* @__PURE__ */ jsx3(
|
|
3364
|
+
"button",
|
|
3365
|
+
{
|
|
3366
|
+
type: "button",
|
|
3367
|
+
"data-gg-self-report-attach": "",
|
|
3368
|
+
"aria-label": "Add screenshot",
|
|
3369
|
+
title: "Add a screenshot \u2014 or paste one",
|
|
3370
|
+
onClick: () => {
|
|
3371
|
+
var _a;
|
|
3372
|
+
return (_a = fileRef.current) == null ? void 0 : _a.click();
|
|
3373
|
+
},
|
|
3374
|
+
style: {
|
|
3375
|
+
height: "48px",
|
|
3376
|
+
padding: "0 12px",
|
|
3377
|
+
boxSizing: "border-box",
|
|
3378
|
+
borderRadius: "8px",
|
|
3379
|
+
border: `1px dashed ${t2.inputBorder}`,
|
|
3380
|
+
background: "transparent",
|
|
3381
|
+
color: t2.textMuted,
|
|
3382
|
+
fontSize: "12.5px",
|
|
3383
|
+
fontWeight: 600,
|
|
3384
|
+
fontFamily: "inherit",
|
|
3385
|
+
cursor: "pointer"
|
|
3386
|
+
},
|
|
3387
|
+
children: images.length >= 3 ? "+ Add" : "+ Add screenshot"
|
|
3388
|
+
}
|
|
3389
|
+
),
|
|
3390
|
+
/* @__PURE__ */ jsx3(
|
|
3391
|
+
"input",
|
|
3392
|
+
{
|
|
3393
|
+
ref: fileRef,
|
|
3394
|
+
type: "file",
|
|
3395
|
+
accept: "image/*",
|
|
3396
|
+
multiple: true,
|
|
3397
|
+
"data-gg-self-report-file": "",
|
|
3398
|
+
onChange: (e) => {
|
|
3399
|
+
var _a;
|
|
3400
|
+
addImages(Array.from((_a = e.target.files) != null ? _a : []));
|
|
3401
|
+
e.target.value = "";
|
|
3402
|
+
},
|
|
3403
|
+
style: { display: "none" }
|
|
3404
|
+
}
|
|
3405
|
+
)
|
|
3406
|
+
]
|
|
3407
|
+
}
|
|
3408
|
+
),
|
|
3017
3409
|
/* @__PURE__ */ jsxs3(
|
|
3018
3410
|
"p",
|
|
3019
3411
|
{
|
|
@@ -3022,7 +3414,7 @@ function GlitchgrabProblemPanel({
|
|
|
3022
3414
|
children: [
|
|
3023
3415
|
"Also sent, so we can see what happened:",
|
|
3024
3416
|
" ",
|
|
3025
|
-
describeSentAlong(conversationId !== null,
|
|
3417
|
+
describeSentAlong(conversationId !== null, images.length),
|
|
3026
3418
|
"."
|
|
3027
3419
|
]
|
|
3028
3420
|
}
|
|
@@ -3063,38 +3455,6 @@ function isMac() {
|
|
|
3063
3455
|
function getShortcutLabel() {
|
|
3064
3456
|
return isMac() ? GLITCHGRAB_SHORTCUT_MAC : GLITCHGRAB_SHORTCUT;
|
|
3065
3457
|
}
|
|
3066
|
-
var ATTACHMENT_ACCEPT = [
|
|
3067
|
-
"image/*",
|
|
3068
|
-
// text — inlined into the issue body
|
|
3069
|
-
".html",
|
|
3070
|
-
".htm",
|
|
3071
|
-
".txt",
|
|
3072
|
-
".md",
|
|
3073
|
-
".json",
|
|
3074
|
-
".xml",
|
|
3075
|
-
".log",
|
|
3076
|
-
".yml",
|
|
3077
|
-
".yaml",
|
|
3078
|
-
".csv",
|
|
3079
|
-
".har",
|
|
3080
|
-
".js",
|
|
3081
|
-
".mjs",
|
|
3082
|
-
".cjs",
|
|
3083
|
-
".ts",
|
|
3084
|
-
".tsx",
|
|
3085
|
-
".jsx",
|
|
3086
|
-
".css",
|
|
3087
|
-
".scss",
|
|
3088
|
-
".py",
|
|
3089
|
-
".sh",
|
|
3090
|
-
// binary documents
|
|
3091
|
-
".pdf",
|
|
3092
|
-
".doc",
|
|
3093
|
-
".docx",
|
|
3094
|
-
".xls",
|
|
3095
|
-
".xlsx",
|
|
3096
|
-
".zip"
|
|
3097
|
-
].join(",");
|
|
3098
3458
|
var MAX_SCALE = 2;
|
|
3099
3459
|
var FRAME_TIMEOUT_MS = 3e3;
|
|
3100
3460
|
var GRAB_TIMEOUT_MS = FRAME_TIMEOUT_MS + 2e3;
|
|
@@ -3238,6 +3598,27 @@ function captureDefaultScreenshot(options) {
|
|
|
3238
3598
|
}
|
|
3239
3599
|
var SEVERITY_REQUIRED = "Pick how bad it is before sending.";
|
|
3240
3600
|
var SHOT_WAIT_MS = 3e3;
|
|
3601
|
+
var SIMILAR_WAIT_MS = 2500;
|
|
3602
|
+
var MAX_SIMILAR_SHOWN = 3;
|
|
3603
|
+
function ButtonSpinner() {
|
|
3604
|
+
return /* @__PURE__ */ jsx4(
|
|
3605
|
+
"span",
|
|
3606
|
+
{
|
|
3607
|
+
"aria-hidden": "true",
|
|
3608
|
+
style: {
|
|
3609
|
+
display: "inline-block",
|
|
3610
|
+
width: "11px",
|
|
3611
|
+
height: "11px",
|
|
3612
|
+
marginRight: "6px",
|
|
3613
|
+
verticalAlign: "-1px",
|
|
3614
|
+
border: "2px solid currentColor",
|
|
3615
|
+
borderRightColor: "transparent",
|
|
3616
|
+
borderRadius: "50%",
|
|
3617
|
+
animation: "gg-spin .7s linear infinite"
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
);
|
|
3621
|
+
}
|
|
3241
3622
|
function detectDark() {
|
|
3242
3623
|
if (typeof window === "undefined") return true;
|
|
3243
3624
|
try {
|
|
@@ -3544,6 +3925,7 @@ function ReportDialog({
|
|
|
3544
3925
|
sendFeedback: sendFeedback2,
|
|
3545
3926
|
enhanceText: enhanceText2,
|
|
3546
3927
|
assist,
|
|
3928
|
+
findSimilarIssues: findSimilarIssues2,
|
|
3547
3929
|
assistContext = null,
|
|
3548
3930
|
transcribeAudio: transcribeAudio2,
|
|
3549
3931
|
types,
|
|
@@ -3563,6 +3945,11 @@ function ReportDialog({
|
|
|
3563
3945
|
const [selfReportPrefill, setSelfReportPrefill] = useState4("");
|
|
3564
3946
|
const [typeChosen, setTypeChosen] = useState4(false);
|
|
3565
3947
|
const [duplicateIssueNumber, setDuplicateIssueNumber] = useState4(null);
|
|
3948
|
+
const [similarIssues, setSimilarIssues] = useState4(null);
|
|
3949
|
+
const [checkingSimilar, setCheckingSimilar] = useState4(false);
|
|
3950
|
+
const [attachingTo, setAttachingTo] = useState4(null);
|
|
3951
|
+
const [pickedSimilar, setPickedSimilar] = useState4(null);
|
|
3952
|
+
const [addedToIssue, setAddedToIssue] = useState4(null);
|
|
3566
3953
|
const [aiConversationId, setAiConversationId] = useState4(null);
|
|
3567
3954
|
const [isEnhanced, setIsEnhanced] = useState4(false);
|
|
3568
3955
|
const [originalDescription, setOriginalDescription] = useState4(
|
|
@@ -3713,7 +4100,7 @@ function ReportDialog({
|
|
|
3713
4100
|
const next = current === -1 ? 0 : Math.min(Math.max(current + delta, 0), tiles.length - 1);
|
|
3714
4101
|
(_c = tiles[next]) == null ? void 0 : _c.focus();
|
|
3715
4102
|
};
|
|
3716
|
-
const isDark =
|
|
4103
|
+
const isDark = useMemo2(() => isOpen ? detectDark() : true, [isOpen]);
|
|
3717
4104
|
const t2 = getTheme(isDark);
|
|
3718
4105
|
const layerTheme = {
|
|
3719
4106
|
bg: t2.bg,
|
|
@@ -3993,6 +4380,10 @@ function ReportDialog({
|
|
|
3993
4380
|
setReportType("BUG");
|
|
3994
4381
|
setTypeChosen(false);
|
|
3995
4382
|
setDuplicateIssueNumber(null);
|
|
4383
|
+
setSimilarIssues(null);
|
|
4384
|
+
setPickedSimilar(null);
|
|
4385
|
+
setCheckingSimilar(false);
|
|
4386
|
+
setAttachingTo(null);
|
|
3996
4387
|
setSeverity(null);
|
|
3997
4388
|
setValidationError(null);
|
|
3998
4389
|
setSelfReportFrom(null);
|
|
@@ -4180,7 +4571,8 @@ function ReportDialog({
|
|
|
4180
4571
|
stopListeningAndTranscribe();
|
|
4181
4572
|
}
|
|
4182
4573
|
};
|
|
4183
|
-
const handleSubmit = async () => {
|
|
4574
|
+
const handleSubmit = async (opts) => {
|
|
4575
|
+
var _a2;
|
|
4184
4576
|
try {
|
|
4185
4577
|
if (isSubmitting) return;
|
|
4186
4578
|
if (isRating) {
|
|
@@ -4217,6 +4609,22 @@ function ReportDialog({
|
|
|
4217
4609
|
setStep(2);
|
|
4218
4610
|
return;
|
|
4219
4611
|
}
|
|
4612
|
+
const duplicateOf = (_a2 = opts == null ? void 0 : opts.duplicateOf) != null ? _a2 : duplicateIssueNumber;
|
|
4613
|
+
if (findSimilarIssues2 && !(opts == null ? void 0 : opts.skipSimilar) && !duplicateOf && !aiConversationId) {
|
|
4614
|
+
setIsSubmitting(true);
|
|
4615
|
+
setCheckingSimilar(true);
|
|
4616
|
+
const matches = await Promise.race([
|
|
4617
|
+
findSimilarIssues2(description.trim()).catch(() => null),
|
|
4618
|
+
new Promise((resolve) => setTimeout(() => resolve(null), SIMILAR_WAIT_MS))
|
|
4619
|
+
]);
|
|
4620
|
+
setCheckingSimilar(false);
|
|
4621
|
+
if (matches && matches.length > 0) {
|
|
4622
|
+
setSimilarIssues(matches.slice(0, MAX_SIMILAR_SHOWN));
|
|
4623
|
+
setPickedSimilar(null);
|
|
4624
|
+
setIsSubmitting(false);
|
|
4625
|
+
return;
|
|
4626
|
+
}
|
|
4627
|
+
}
|
|
4220
4628
|
setIsSubmitting(true);
|
|
4221
4629
|
let shots = screenshots;
|
|
4222
4630
|
const pending = pendingShotRef.current;
|
|
@@ -4235,8 +4643,8 @@ function ReportDialog({
|
|
|
4235
4643
|
if (showSeverity && reportType === "BUG" && severity) {
|
|
4236
4644
|
metadata.severity = severity;
|
|
4237
4645
|
}
|
|
4238
|
-
if (
|
|
4239
|
-
metadata.duplicateIssueNumber = String(
|
|
4646
|
+
if (duplicateOf) {
|
|
4647
|
+
metadata.duplicateIssueNumber = String(duplicateOf);
|
|
4240
4648
|
}
|
|
4241
4649
|
if (aiConversationId) {
|
|
4242
4650
|
metadata.aiConversationId = aiConversationId;
|
|
@@ -4249,20 +4657,26 @@ function ReportDialog({
|
|
|
4249
4657
|
Object.keys(metadata).length > 0 ? metadata : void 0
|
|
4250
4658
|
);
|
|
4251
4659
|
if (result) {
|
|
4660
|
+
setAddedToIssue(duplicateOf && result.issueNumber === duplicateOf ? duplicateOf : null);
|
|
4252
4661
|
setSubmitted(true);
|
|
4253
4662
|
setDescription("");
|
|
4254
4663
|
setScreenshots([]);
|
|
4255
4664
|
setAttachments([]);
|
|
4256
4665
|
setAiConversationId(null);
|
|
4257
4666
|
setDuplicateIssueNumber(null);
|
|
4667
|
+
setSimilarIssues(null);
|
|
4668
|
+
setPickedSimilar(null);
|
|
4258
4669
|
setTimeout(() => {
|
|
4259
4670
|
setSubmitted(false);
|
|
4260
4671
|
handleClose();
|
|
4261
4672
|
}, 2e3);
|
|
4262
4673
|
}
|
|
4263
4674
|
setIsSubmitting(false);
|
|
4675
|
+
setAttachingTo(null);
|
|
4264
4676
|
} catch (e) {
|
|
4265
4677
|
setIsSubmitting(false);
|
|
4678
|
+
setCheckingSimilar(false);
|
|
4679
|
+
setAttachingTo(null);
|
|
4266
4680
|
}
|
|
4267
4681
|
};
|
|
4268
4682
|
if (!mounted) return null;
|
|
@@ -4270,6 +4684,7 @@ function ReportDialog({
|
|
|
4270
4684
|
isOpen && createPortal3(
|
|
4271
4685
|
/* @__PURE__ */ jsx4("style", { children: `
|
|
4272
4686
|
@keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
|
|
4687
|
+
@keyframes gg-spin{to{transform:rotate(360deg)}}
|
|
4273
4688
|
@keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
|
|
4274
4689
|
@keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
|
|
4275
4690
|
@keyframes gg-b3{0%,100%{height:4px}30%{height:14px}70%{height:5px}}
|
|
@@ -4554,7 +4969,7 @@ function ReportDialog({
|
|
|
4554
4969
|
flex: "1 1 auto",
|
|
4555
4970
|
minHeight: 0
|
|
4556
4971
|
},
|
|
4557
|
-
children: submitted ? /* @__PURE__ */
|
|
4972
|
+
children: submitted ? /* @__PURE__ */ jsx4(
|
|
4558
4973
|
"div",
|
|
4559
4974
|
{
|
|
4560
4975
|
style: {
|
|
@@ -4564,10 +4979,7 @@ function ReportDialog({
|
|
|
4564
4979
|
fontSize: "14px",
|
|
4565
4980
|
fontWeight: 500
|
|
4566
4981
|
},
|
|
4567
|
-
children:
|
|
4568
|
-
getTypeLabel(reportType),
|
|
4569
|
-
" sent. Thank you!"
|
|
4570
|
-
]
|
|
4982
|
+
children: addedToIssue ? `Added to #${addedToIssue}. Thank you!` : `${getTypeLabel(reportType)} sent. Thank you!`
|
|
4571
4983
|
}
|
|
4572
4984
|
) : /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
4573
4985
|
step === 1 && headerSlot ? /* @__PURE__ */ jsx4("div", { style: { marginBottom: "14px" }, children: headerSlot }) : null,
|
|
@@ -5792,11 +6204,194 @@ function ReportDialog({
|
|
|
5792
6204
|
children: validationError
|
|
5793
6205
|
}
|
|
5794
6206
|
),
|
|
5795
|
-
|
|
6207
|
+
similarIssues ? (
|
|
6208
|
+
// Same visual language as the assistant's "Our team is
|
|
6209
|
+
// already on this" card, so both routes to a duplicate
|
|
6210
|
+
// read as one feature.
|
|
6211
|
+
/* @__PURE__ */ jsxs4(
|
|
6212
|
+
"div",
|
|
6213
|
+
{
|
|
6214
|
+
"data-gg-similar": "",
|
|
6215
|
+
style: {
|
|
6216
|
+
marginTop: "12px",
|
|
6217
|
+
display: "flex",
|
|
6218
|
+
flexDirection: "column",
|
|
6219
|
+
gap: "10px",
|
|
6220
|
+
padding: "12px",
|
|
6221
|
+
borderRadius: "10px",
|
|
6222
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
6223
|
+
backgroundColor: "rgba(245,158,11,0.08)"
|
|
6224
|
+
},
|
|
6225
|
+
children: [
|
|
6226
|
+
/* @__PURE__ */ jsxs4("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
|
|
6227
|
+
/* @__PURE__ */ jsx4("span", { style: { color: t2.text, fontWeight: 600, fontSize: "13px" }, children: "Our team may already have this" }),
|
|
6228
|
+
/* @__PURE__ */ jsx4("span", { style: { color: t2.textMuted, fontSize: "12px", lineHeight: 1.5 }, children: similarIssues.length > 1 ? "Pick the one that matches \u2014 your report is added to it, so the team sees everyone hitting it in one place." : "If it's the same problem, pick it \u2014 your report is added to it, so the team sees everyone hitting it in one place." })
|
|
6229
|
+
] }),
|
|
6230
|
+
/* @__PURE__ */ jsx4(
|
|
6231
|
+
"div",
|
|
6232
|
+
{
|
|
6233
|
+
role: "radiogroup",
|
|
6234
|
+
"aria-label": "Existing issues",
|
|
6235
|
+
style: { display: "flex", flexDirection: "column", gap: "6px" },
|
|
6236
|
+
children: similarIssues.map((issue) => {
|
|
6237
|
+
const picked = pickedSimilar === issue.number;
|
|
6238
|
+
return /* @__PURE__ */ jsxs4(
|
|
6239
|
+
"button",
|
|
6240
|
+
{
|
|
6241
|
+
type: "button",
|
|
6242
|
+
role: "radio",
|
|
6243
|
+
"aria-checked": picked,
|
|
6244
|
+
disabled: isSubmitting,
|
|
6245
|
+
onClick: () => setPickedSimilar(issue.number),
|
|
6246
|
+
style: {
|
|
6247
|
+
display: "flex",
|
|
6248
|
+
alignItems: "flex-start",
|
|
6249
|
+
gap: "10px",
|
|
6250
|
+
width: "100%",
|
|
6251
|
+
minHeight: "44px",
|
|
6252
|
+
padding: "9px 10px",
|
|
6253
|
+
borderRadius: "8px",
|
|
6254
|
+
border: `1px solid ${picked ? t2.accent : t2.border}`,
|
|
6255
|
+
boxShadow: picked ? `0 0 0 1px ${t2.accent}` : "none",
|
|
6256
|
+
backgroundColor: t2.bg,
|
|
6257
|
+
color: t2.text,
|
|
6258
|
+
textAlign: "left",
|
|
6259
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
6260
|
+
fontFamily: "inherit"
|
|
6261
|
+
},
|
|
6262
|
+
children: [
|
|
6263
|
+
/* @__PURE__ */ jsx4(
|
|
6264
|
+
"span",
|
|
6265
|
+
{
|
|
6266
|
+
"aria-hidden": "true",
|
|
6267
|
+
style: {
|
|
6268
|
+
flexShrink: 0,
|
|
6269
|
+
marginTop: "2px",
|
|
6270
|
+
width: "14px",
|
|
6271
|
+
height: "14px",
|
|
6272
|
+
boxSizing: "border-box",
|
|
6273
|
+
borderRadius: "50%",
|
|
6274
|
+
border: `2px solid ${picked ? t2.accent : t2.textMuted}`,
|
|
6275
|
+
backgroundColor: picked ? t2.accent : "transparent",
|
|
6276
|
+
boxShadow: picked ? `inset 0 0 0 2px ${t2.bg}` : "none"
|
|
6277
|
+
}
|
|
6278
|
+
}
|
|
6279
|
+
),
|
|
6280
|
+
/* @__PURE__ */ jsxs4(
|
|
6281
|
+
"span",
|
|
6282
|
+
{
|
|
6283
|
+
style: {
|
|
6284
|
+
display: "flex",
|
|
6285
|
+
flexDirection: "column",
|
|
6286
|
+
gap: "3px",
|
|
6287
|
+
minWidth: 0
|
|
6288
|
+
},
|
|
6289
|
+
children: [
|
|
6290
|
+
/* @__PURE__ */ jsxs4(
|
|
6291
|
+
"span",
|
|
6292
|
+
{
|
|
6293
|
+
title: issue.title,
|
|
6294
|
+
style: {
|
|
6295
|
+
fontSize: "12.5px",
|
|
6296
|
+
lineHeight: 1.45,
|
|
6297
|
+
wordBreak: "break-word",
|
|
6298
|
+
overflow: "hidden",
|
|
6299
|
+
display: "-webkit-box",
|
|
6300
|
+
WebkitLineClamp: 3,
|
|
6301
|
+
WebkitBoxOrient: "vertical"
|
|
6302
|
+
},
|
|
6303
|
+
children: [
|
|
6304
|
+
/* @__PURE__ */ jsxs4("span", { style: { color: t2.textMuted, fontWeight: 600 }, children: [
|
|
6305
|
+
"#",
|
|
6306
|
+
issue.number
|
|
6307
|
+
] }),
|
|
6308
|
+
" ",
|
|
6309
|
+
issue.title
|
|
6310
|
+
]
|
|
6311
|
+
}
|
|
6312
|
+
),
|
|
6313
|
+
issue.status && /* @__PURE__ */ jsx4("span", { style: { fontSize: "11.5px", color: t2.textMuted }, children: issue.status })
|
|
6314
|
+
]
|
|
6315
|
+
}
|
|
6316
|
+
)
|
|
6317
|
+
]
|
|
6318
|
+
},
|
|
6319
|
+
issue.number
|
|
6320
|
+
);
|
|
6321
|
+
})
|
|
6322
|
+
}
|
|
6323
|
+
),
|
|
6324
|
+
/* @__PURE__ */ jsx4(
|
|
6325
|
+
"button",
|
|
6326
|
+
{
|
|
6327
|
+
type: "button",
|
|
6328
|
+
disabled: isSubmitting || !pickedSimilar,
|
|
6329
|
+
onClick: () => {
|
|
6330
|
+
if (!pickedSimilar) return;
|
|
6331
|
+
setAttachingTo(pickedSimilar);
|
|
6332
|
+
setDuplicateIssueNumber(pickedSimilar);
|
|
6333
|
+
void handleSubmit({ duplicateOf: pickedSimilar });
|
|
6334
|
+
},
|
|
6335
|
+
style: {
|
|
6336
|
+
width: "100%",
|
|
6337
|
+
minHeight: "40px",
|
|
6338
|
+
padding: "10px",
|
|
6339
|
+
borderRadius: "8px",
|
|
6340
|
+
border: "none",
|
|
6341
|
+
backgroundColor: isSubmitting || !pickedSimilar ? t2.bgSecondary : t2.accent,
|
|
6342
|
+
color: isSubmitting || !pickedSimilar ? t2.textMuted : t2.accentText,
|
|
6343
|
+
fontSize: "14px",
|
|
6344
|
+
fontWeight: 600,
|
|
6345
|
+
cursor: isSubmitting || !pickedSimilar ? "not-allowed" : "pointer",
|
|
6346
|
+
fontFamily: "inherit"
|
|
6347
|
+
},
|
|
6348
|
+
children: typeof attachingTo === "number" ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
6349
|
+
/* @__PURE__ */ jsx4(ButtonSpinner, {}),
|
|
6350
|
+
"Adding to #",
|
|
6351
|
+
attachingTo,
|
|
6352
|
+
"\u2026"
|
|
6353
|
+
] }) : pickedSimilar ? `Add to #${pickedSimilar}` : "Pick the matching issue"
|
|
6354
|
+
}
|
|
6355
|
+
),
|
|
6356
|
+
/* @__PURE__ */ jsx4(
|
|
6357
|
+
"button",
|
|
6358
|
+
{
|
|
6359
|
+
type: "button",
|
|
6360
|
+
disabled: isSubmitting,
|
|
6361
|
+
onClick: () => {
|
|
6362
|
+
setAttachingTo("new");
|
|
6363
|
+
void handleSubmit({ skipSimilar: true });
|
|
6364
|
+
},
|
|
6365
|
+
style: {
|
|
6366
|
+
width: "100%",
|
|
6367
|
+
minHeight: "40px",
|
|
6368
|
+
marginTop: "-4px",
|
|
6369
|
+
padding: "8px",
|
|
6370
|
+
borderRadius: "8px",
|
|
6371
|
+
border: "none",
|
|
6372
|
+
backgroundColor: "transparent",
|
|
6373
|
+
color: isSubmitting ? t2.textMuted : t2.text,
|
|
6374
|
+
fontSize: "13px",
|
|
6375
|
+
fontWeight: 500,
|
|
6376
|
+
textDecoration: "underline",
|
|
6377
|
+
textUnderlineOffset: "3px",
|
|
6378
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
6379
|
+
fontFamily: "inherit"
|
|
6380
|
+
},
|
|
6381
|
+
children: attachingTo === "new" ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
6382
|
+
/* @__PURE__ */ jsx4(ButtonSpinner, {}),
|
|
6383
|
+
"Sending as new\u2026"
|
|
6384
|
+
] }) : "No, mine is different \u2014 send as new"
|
|
6385
|
+
}
|
|
6386
|
+
)
|
|
6387
|
+
]
|
|
6388
|
+
}
|
|
6389
|
+
)
|
|
6390
|
+
) : /* @__PURE__ */ jsx4(
|
|
5796
6391
|
"button",
|
|
5797
6392
|
{
|
|
5798
6393
|
type: "button",
|
|
5799
|
-
onClick: handleSubmit,
|
|
6394
|
+
onClick: () => void handleSubmit(),
|
|
5800
6395
|
disabled: submitDisabled,
|
|
5801
6396
|
style: {
|
|
5802
6397
|
marginTop: "12px",
|
|
@@ -5812,7 +6407,10 @@ function ReportDialog({
|
|
|
5812
6407
|
fontFamily: "inherit",
|
|
5813
6408
|
transition: "background-color 0.15s ease"
|
|
5814
6409
|
},
|
|
5815
|
-
children:
|
|
6410
|
+
children: checkingSimilar ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
6411
|
+
/* @__PURE__ */ jsx4(ButtonSpinner, {}),
|
|
6412
|
+
"Checking for existing reports\u2026"
|
|
6413
|
+
] }) : isSubmitting ? shotPending && !isRating ? "Attaching screenshot\u2026" : "Sending..." : isRating ? "Send Rating" : "Send Report"
|
|
5816
6414
|
}
|
|
5817
6415
|
)
|
|
5818
6416
|
] })
|
|
@@ -6086,8 +6684,10 @@ function ReportDialog({
|
|
|
6086
6684
|
theme: layerTheme,
|
|
6087
6685
|
screenshots,
|
|
6088
6686
|
pageShot,
|
|
6089
|
-
|
|
6687
|
+
onAddFiles: addFiles,
|
|
6090
6688
|
onRemoveImage: (index) => setScreenshots((prev) => prev.filter((_, i) => i !== index)),
|
|
6689
|
+
files: attachments,
|
|
6690
|
+
onRemoveFile: (index) => setAttachments((prev) => prev.filter((_, i) => i !== index)),
|
|
6091
6691
|
attachmentCount: screenshots.length + attachments.length,
|
|
6092
6692
|
context: { ...assistContext != null ? assistContext : {}, reportType },
|
|
6093
6693
|
reportTypeLabel: getTypeLabel(reportType),
|
|
@@ -6124,14 +6724,14 @@ function ReportDialog({
|
|
|
6124
6724
|
severityRefused: needsSeverity,
|
|
6125
6725
|
isSubmitting,
|
|
6126
6726
|
submitted,
|
|
6127
|
-
onSend: () => void handleSubmit(),
|
|
6727
|
+
onSend: () => void handleSubmit({ skipSimilar: true }),
|
|
6128
6728
|
onReportGlitchgrabProblem: reportGlitchgrabProblem ? (prefill) => {
|
|
6129
6729
|
setSelfReportPrefill(prefill != null ? prefill : "");
|
|
6130
6730
|
setSelfReportFrom("assist");
|
|
6131
6731
|
} : void 0,
|
|
6132
|
-
onDegrade: (message) => {
|
|
6732
|
+
onDegrade: (message, retryable) => {
|
|
6133
6733
|
setAssistOpen(false);
|
|
6134
|
-
setAssistUsed(true);
|
|
6734
|
+
if (!retryable) setAssistUsed(true);
|
|
6135
6735
|
setAssistNotice(message);
|
|
6136
6736
|
},
|
|
6137
6737
|
onClose: () => {
|
|
@@ -6277,7 +6877,7 @@ function getTypeIcon(type, color, size = 24) {
|
|
|
6277
6877
|
}
|
|
6278
6878
|
|
|
6279
6879
|
// src/booking-dialog.tsx
|
|
6280
|
-
import { useCallback, useEffect as useEffect5, useMemo as
|
|
6880
|
+
import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo3, useState as useState5 } from "react";
|
|
6281
6881
|
import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
6282
6882
|
var t = {
|
|
6283
6883
|
bg: "#141414",
|
|
@@ -6332,11 +6932,11 @@ function BookingDialog({
|
|
|
6332
6932
|
const [meetUrl, setMeetUrl] = useState5(null);
|
|
6333
6933
|
const [busy, setBusy] = useState5(false);
|
|
6334
6934
|
const [error, setError] = useState5(null);
|
|
6335
|
-
const headers =
|
|
6935
|
+
const headers = useMemo3(
|
|
6336
6936
|
() => ({ Authorization: `Bearer ${token}`, "Content-Type": "application/json" }),
|
|
6337
6937
|
[token]
|
|
6338
6938
|
);
|
|
6339
|
-
const loadSlots =
|
|
6939
|
+
const loadSlots = useCallback2(async () => {
|
|
6340
6940
|
var _a2, _b, _c;
|
|
6341
6941
|
setError(null);
|
|
6342
6942
|
setSlots(null);
|
|
@@ -6843,7 +7443,7 @@ function GlitchgrabProviderInner({
|
|
|
6843
7443
|
sessionProp.avatarUrl,
|
|
6844
7444
|
sessionProp.image
|
|
6845
7445
|
].map((v) => v == null ? "" : String(v)).join("\0") : "";
|
|
6846
|
-
const session =
|
|
7446
|
+
const session = useMemo4(() => sessionProp, [sessionKey]);
|
|
6847
7447
|
setRelease(release2);
|
|
6848
7448
|
if (appContext2) setContexts(appContext2);
|
|
6849
7449
|
registerCaptureConfig({
|
|
@@ -7024,7 +7624,7 @@ function GlitchgrabProviderInner({
|
|
|
7024
7624
|
} catch (e) {
|
|
7025
7625
|
}
|
|
7026
7626
|
}, [token, baseUrl, onError, onReportSent, session, ignoreErrors]);
|
|
7027
|
-
const report =
|
|
7627
|
+
const report = useCallback3(
|
|
7028
7628
|
async (type, description, metadata) => {
|
|
7029
7629
|
var _a;
|
|
7030
7630
|
try {
|
|
@@ -7058,11 +7658,11 @@ function GlitchgrabProviderInner({
|
|
|
7058
7658
|
},
|
|
7059
7659
|
[token, baseUrl, onReportSent, session]
|
|
7060
7660
|
);
|
|
7061
|
-
const reportBug =
|
|
7661
|
+
const reportBug = useCallback3(
|
|
7062
7662
|
(description, metadata) => report("BUG", description, metadata),
|
|
7063
7663
|
[report]
|
|
7064
7664
|
);
|
|
7065
|
-
const reportGlitchgrabProblem =
|
|
7665
|
+
const reportGlitchgrabProblem = useCallback3(
|
|
7066
7666
|
async (params) => {
|
|
7067
7667
|
var _a, _b;
|
|
7068
7668
|
try {
|
|
@@ -7096,7 +7696,7 @@ function GlitchgrabProviderInner({
|
|
|
7096
7696
|
},
|
|
7097
7697
|
[token, baseUrl, session]
|
|
7098
7698
|
);
|
|
7099
|
-
const feedback =
|
|
7699
|
+
const feedback = useCallback3(
|
|
7100
7700
|
async (rating, message, metadata) => {
|
|
7101
7701
|
try {
|
|
7102
7702
|
const context = captureContext(visitedPagesRef.current);
|
|
@@ -7124,32 +7724,38 @@ function GlitchgrabProviderInner({
|
|
|
7124
7724
|
},
|
|
7125
7725
|
[token, baseUrl, session]
|
|
7126
7726
|
);
|
|
7127
|
-
const openFeedbackDialog =
|
|
7727
|
+
const openFeedbackDialog = useCallback3(() => {
|
|
7128
7728
|
if (typeof window !== "undefined") {
|
|
7129
7729
|
window.dispatchEvent(
|
|
7130
7730
|
new CustomEvent("glitchgrab:open-report", { detail: { type: "RATING" } })
|
|
7131
7731
|
);
|
|
7132
7732
|
}
|
|
7133
7733
|
}, []);
|
|
7134
|
-
const captureError2 =
|
|
7734
|
+
const captureError2 = useCallback3(
|
|
7135
7735
|
(error, options) => {
|
|
7136
7736
|
captureError(error, options);
|
|
7137
7737
|
},
|
|
7138
7738
|
[]
|
|
7139
7739
|
);
|
|
7140
|
-
const setContext2 =
|
|
7740
|
+
const setContext2 = useCallback3((key, value) => {
|
|
7141
7741
|
setContext(key, value);
|
|
7142
7742
|
}, []);
|
|
7143
|
-
const setContexts2 =
|
|
7743
|
+
const setContexts2 = useCallback3((values) => {
|
|
7144
7744
|
setContexts(values);
|
|
7145
7745
|
}, []);
|
|
7146
|
-
const addBreadcrumb2 =
|
|
7746
|
+
const addBreadcrumb2 = useCallback3(
|
|
7147
7747
|
(message, data) => {
|
|
7148
7748
|
addBreadcrumb("custom", message, data);
|
|
7149
7749
|
},
|
|
7150
7750
|
[]
|
|
7151
7751
|
);
|
|
7152
|
-
const
|
|
7752
|
+
const signedUserId = session == null ? void 0 : session.userId;
|
|
7753
|
+
const signature = typeof (session == null ? void 0 : session.signature) === "string" ? session.signature : null;
|
|
7754
|
+
const identity = useMemo4(
|
|
7755
|
+
() => ({ userId: signedUserId != null ? signedUserId : null, signature }),
|
|
7756
|
+
[signedUserId, signature]
|
|
7757
|
+
);
|
|
7758
|
+
const enhance = useCallback3(
|
|
7153
7759
|
async (text, screenshot) => {
|
|
7154
7760
|
try {
|
|
7155
7761
|
const ctx = captureContext(visitedPagesRef.current);
|
|
@@ -7158,14 +7764,14 @@ function GlitchgrabProviderInner({
|
|
|
7158
7764
|
visitedPages: ctx.visitedPages.slice(-5),
|
|
7159
7765
|
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
7160
7766
|
};
|
|
7161
|
-
return await enhanceText(text, token, baseUrl, screenshot, context);
|
|
7767
|
+
return await enhanceText(text, token, baseUrl, screenshot, context, identity);
|
|
7162
7768
|
} catch (e) {
|
|
7163
7769
|
return text;
|
|
7164
7770
|
}
|
|
7165
7771
|
},
|
|
7166
|
-
[token, baseUrl]
|
|
7772
|
+
[token, baseUrl, identity]
|
|
7167
7773
|
);
|
|
7168
|
-
const assist =
|
|
7774
|
+
const assist = useCallback3(
|
|
7169
7775
|
async (params) => {
|
|
7170
7776
|
var _a;
|
|
7171
7777
|
const ctx = captureContext(visitedPagesRef.current);
|
|
@@ -7176,7 +7782,8 @@ function GlitchgrabProviderInner({
|
|
|
7176
7782
|
reporter: session ? {
|
|
7177
7783
|
key: session.userId,
|
|
7178
7784
|
name: session.name ? String(session.name) : null,
|
|
7179
|
-
email: session.email ? String(session.email) : null
|
|
7785
|
+
email: session.email ? String(session.email) : null,
|
|
7786
|
+
...signature ? { signature } : {}
|
|
7180
7787
|
} : void 0,
|
|
7181
7788
|
context: {
|
|
7182
7789
|
...(_a = params.context) != null ? _a : {},
|
|
@@ -7191,17 +7798,21 @@ function GlitchgrabProviderInner({
|
|
|
7191
7798
|
},
|
|
7192
7799
|
[token, baseUrl, session]
|
|
7193
7800
|
);
|
|
7194
|
-
const
|
|
7801
|
+
const findSimilar = useCallback3(
|
|
7802
|
+
(description) => findSimilarIssues(description, token, baseUrl, identity),
|
|
7803
|
+
[token, baseUrl, identity]
|
|
7804
|
+
);
|
|
7805
|
+
const transcribe = useCallback3(
|
|
7195
7806
|
async (blob) => {
|
|
7196
7807
|
try {
|
|
7197
|
-
return await transcribeAudio(blob, token, baseUrl);
|
|
7808
|
+
return await transcribeAudio(blob, token, baseUrl, identity);
|
|
7198
7809
|
} catch (e) {
|
|
7199
7810
|
return "";
|
|
7200
7811
|
}
|
|
7201
7812
|
},
|
|
7202
|
-
[token, baseUrl]
|
|
7813
|
+
[token, baseUrl, identity]
|
|
7203
7814
|
);
|
|
7204
|
-
const openReportDialog =
|
|
7815
|
+
const openReportDialog = useCallback3((options) => {
|
|
7205
7816
|
if (typeof window !== "undefined") {
|
|
7206
7817
|
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
7207
7818
|
}
|
|
@@ -7217,8 +7828,10 @@ function GlitchgrabProviderInner({
|
|
|
7217
7828
|
const [projectName, setProjectName] = useState6(null);
|
|
7218
7829
|
const [aiAssist, setAiAssist] = useState6(false);
|
|
7219
7830
|
const [glitchgrabReport, setGlitchgrabReport] = useState6(false);
|
|
7831
|
+
const [signedUsers, setSignedUsers] = useState6("OFF");
|
|
7832
|
+
const aiBlockedUnsigned = signedUsers === "ENFORCE" && !signature;
|
|
7220
7833
|
const [bookingOpen, setBookingOpen] = useState6(false);
|
|
7221
|
-
const openBookingDialog =
|
|
7834
|
+
const openBookingDialog = useCallback3(() => setBookingOpen(true), []);
|
|
7222
7835
|
useEffect6(() => {
|
|
7223
7836
|
let cancelled = false;
|
|
7224
7837
|
fetch(`${baseUrl}/api/v1/sdk/project`, {
|
|
@@ -7229,12 +7842,25 @@ function GlitchgrabProviderInner({
|
|
|
7229
7842
|
setProjectName(json.data.name);
|
|
7230
7843
|
setAiAssist(json.data.aiAssist === true);
|
|
7231
7844
|
setGlitchgrabReport(json.data.glitchgrabReport === true);
|
|
7845
|
+
const mode = json.data.signedUsers;
|
|
7846
|
+
setSignedUsers(mode === "WARN" || mode === "ENFORCE" ? mode : "OFF");
|
|
7232
7847
|
}).catch(() => {
|
|
7233
7848
|
});
|
|
7234
7849
|
return () => {
|
|
7235
7850
|
cancelled = true;
|
|
7236
7851
|
};
|
|
7237
7852
|
}, [baseUrl, token]);
|
|
7853
|
+
useEffect6(() => {
|
|
7854
|
+
var _a;
|
|
7855
|
+
try {
|
|
7856
|
+
if (signedUsers === "OFF" || signature || !session) return;
|
|
7857
|
+
if (typeof process === "undefined" || ((_a = process.env) == null ? void 0 : _a.NODE_ENV) !== "development") return;
|
|
7858
|
+
console.warn(
|
|
7859
|
+
signedUsers === "ENFORCE" ? '[glitchgrab] This project enforces signed users and `session.signature` is missing \u2014 AI features are hidden. Sign it on your server with signSession() from "glitchgrab/server".' : '[glitchgrab] This project warns on unsigned users and `session.signature` is missing. Sign it on your server with signSession() from "glitchgrab/server" before the owner switches to Enforce.'
|
|
7860
|
+
);
|
|
7861
|
+
} catch (e) {
|
|
7862
|
+
}
|
|
7863
|
+
}, [signedUsers, signature, session]);
|
|
7238
7864
|
useEffect6(() => {
|
|
7239
7865
|
try {
|
|
7240
7866
|
if (typeof window === "undefined") return;
|
|
@@ -7249,7 +7875,7 @@ function GlitchgrabProviderInner({
|
|
|
7249
7875
|
} catch (e) {
|
|
7250
7876
|
}
|
|
7251
7877
|
}, [openReportDialog]);
|
|
7252
|
-
const reporter =
|
|
7878
|
+
const reporter = useMemo4(() => {
|
|
7253
7879
|
var _a;
|
|
7254
7880
|
if (!session) return null;
|
|
7255
7881
|
const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
|
|
@@ -7309,10 +7935,11 @@ function GlitchgrabProviderInner({
|
|
|
7309
7935
|
{
|
|
7310
7936
|
report,
|
|
7311
7937
|
sendFeedback: feedback,
|
|
7312
|
-
enhanceText: enhance,
|
|
7313
|
-
assist: aiAssist ? assist : void 0,
|
|
7938
|
+
enhanceText: aiAssist && !aiBlockedUnsigned ? enhance : void 0,
|
|
7939
|
+
assist: aiAssist && !aiBlockedUnsigned ? assist : void 0,
|
|
7940
|
+
findSimilarIssues: aiAssist && !aiBlockedUnsigned ? findSimilar : void 0,
|
|
7314
7941
|
reportGlitchgrabProblem: glitchgrabReport ? reportGlitchgrabProblem : void 0,
|
|
7315
|
-
transcribeAudio: transcribe,
|
|
7942
|
+
transcribeAudio: aiBlockedUnsigned ? void 0 : transcribe,
|
|
7316
7943
|
types,
|
|
7317
7944
|
showSeverity,
|
|
7318
7945
|
reporter,
|
|
@@ -7547,7 +8174,7 @@ function FeedbackButton({
|
|
|
7547
8174
|
}
|
|
7548
8175
|
|
|
7549
8176
|
// src/use-reports.ts
|
|
7550
|
-
import { useState as useState8, useEffect as useEffect7, useCallback as
|
|
8177
|
+
import { useState as useState8, useEffect as useEffect7, useCallback as useCallback4 } from "react";
|
|
7551
8178
|
var BASE_URL = "https://glitchgrab.dev";
|
|
7552
8179
|
function useGlitchgrabReports({
|
|
7553
8180
|
token,
|
|
@@ -7558,7 +8185,7 @@ function useGlitchgrabReports({
|
|
|
7558
8185
|
const [isLoading, setIsLoading] = useState8(true);
|
|
7559
8186
|
const [isFetching, setIsFetching] = useState8(false);
|
|
7560
8187
|
const [error, setError] = useState8(null);
|
|
7561
|
-
const fetchReports =
|
|
8188
|
+
const fetchReports = useCallback4(async () => {
|
|
7562
8189
|
var _a, _b;
|
|
7563
8190
|
if (!token || !userId) {
|
|
7564
8191
|
setIsLoading(false);
|
|
@@ -7623,7 +8250,7 @@ function useGlitchgrabActions({
|
|
|
7623
8250
|
}) {
|
|
7624
8251
|
const [isPending, setIsPending] = useState8(false);
|
|
7625
8252
|
const [error, setError] = useState8(null);
|
|
7626
|
-
const run =
|
|
8253
|
+
const run = useCallback4(
|
|
7627
8254
|
async (reportId, body) => {
|
|
7628
8255
|
setIsPending(true);
|
|
7629
8256
|
setError(null);
|
|
@@ -7653,7 +8280,7 @@ function useGlitchgrabActions({
|
|
|
7653
8280
|
}
|
|
7654
8281
|
|
|
7655
8282
|
// src/use-feedback.ts
|
|
7656
|
-
import { useState as useState9, useEffect as useEffect8, useCallback as
|
|
8283
|
+
import { useState as useState9, useEffect as useEffect8, useCallback as useCallback5 } from "react";
|
|
7657
8284
|
var DEFAULT_BASE_URL3 = "https://glitchgrab.dev";
|
|
7658
8285
|
function buildUrl({
|
|
7659
8286
|
approvedOnly,
|
|
@@ -7683,7 +8310,7 @@ function useGlitchgrabFeedback(query) {
|
|
|
7683
8310
|
const [isLoading, setIsLoading] = useState9(true);
|
|
7684
8311
|
const [isFetching, setIsFetching] = useState9(false);
|
|
7685
8312
|
const [error, setError] = useState9(null);
|
|
7686
|
-
const load =
|
|
8313
|
+
const load = useCallback5(async () => {
|
|
7687
8314
|
if (!token) {
|
|
7688
8315
|
setIsLoading(false);
|
|
7689
8316
|
return;
|