glitchgrab 1.44.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/dist/index.js +382 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +414 -82
- package/dist/index.mjs.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -770,7 +770,9 @@ async function assistTurn(params, token, baseUrl) {
|
|
|
770
770
|
conversationId: null,
|
|
771
771
|
question: null,
|
|
772
772
|
report: null,
|
|
773
|
-
degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded
|
|
773
|
+
degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded,
|
|
774
|
+
// An hourly limit, not a cap: the dialog keeps the assistant button.
|
|
775
|
+
retryable: (envelope == null ? void 0 : envelope.retryable) === true
|
|
774
776
|
};
|
|
775
777
|
}
|
|
776
778
|
return {
|
|
@@ -1367,6 +1369,59 @@ var SEVERITY_LABELS = {
|
|
|
1367
1369
|
};
|
|
1368
1370
|
var MAX_ASSIST_IMAGES = 3;
|
|
1369
1371
|
var MAX_ASSIST_IMAGE_CHARS = 35e5;
|
|
1372
|
+
var MAX_ASSIST_FILES = 3;
|
|
1373
|
+
var MAX_ASSIST_FILE_CHARS = 3e5;
|
|
1374
|
+
var MAX_ASSIST_FILE_CHARS_EACH = 2e5;
|
|
1375
|
+
var TEXT_ATTACHMENT_EXTENSIONS = [
|
|
1376
|
+
".html",
|
|
1377
|
+
".htm",
|
|
1378
|
+
".txt",
|
|
1379
|
+
".md",
|
|
1380
|
+
".json",
|
|
1381
|
+
".xml",
|
|
1382
|
+
".log",
|
|
1383
|
+
".yml",
|
|
1384
|
+
".yaml",
|
|
1385
|
+
".csv",
|
|
1386
|
+
".har",
|
|
1387
|
+
".js",
|
|
1388
|
+
".mjs",
|
|
1389
|
+
".cjs",
|
|
1390
|
+
".ts",
|
|
1391
|
+
".tsx",
|
|
1392
|
+
".jsx",
|
|
1393
|
+
".css",
|
|
1394
|
+
".scss",
|
|
1395
|
+
".py",
|
|
1396
|
+
".sh"
|
|
1397
|
+
];
|
|
1398
|
+
var BINARY_ATTACHMENT_EXTENSIONS = [".pdf", ".doc", ".docx", ".xls", ".xlsx", ".zip"];
|
|
1399
|
+
var ATTACHMENT_ACCEPT = [
|
|
1400
|
+
"image/*",
|
|
1401
|
+
...TEXT_ATTACHMENT_EXTENSIONS,
|
|
1402
|
+
...BINARY_ATTACHMENT_EXTENSIONS
|
|
1403
|
+
].join(",");
|
|
1404
|
+
var ASSIST_ATTACHMENT_ACCEPT = ["image/*", ...TEXT_ATTACHMENT_EXTENSIONS].join(",");
|
|
1405
|
+
function isAssistReadableFile(name) {
|
|
1406
|
+
const lower = name.toLowerCase();
|
|
1407
|
+
return TEXT_ATTACHMENT_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
1408
|
+
}
|
|
1409
|
+
function decodeTextDataUrl(dataUrl) {
|
|
1410
|
+
try {
|
|
1411
|
+
if (!dataUrl.startsWith("data:")) return null;
|
|
1412
|
+
const comma = dataUrl.indexOf(",");
|
|
1413
|
+
if (comma < 0) return null;
|
|
1414
|
+
const meta = dataUrl.slice(5, comma);
|
|
1415
|
+
const payload = dataUrl.slice(comma + 1);
|
|
1416
|
+
if (!meta.endsWith(";base64")) return decodeURIComponent(payload);
|
|
1417
|
+
const binary = atob(payload);
|
|
1418
|
+
const bytes = new Uint8Array(binary.length);
|
|
1419
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1420
|
+
return new TextDecoder("utf-8").decode(bytes);
|
|
1421
|
+
} catch (e) {
|
|
1422
|
+
return null;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1370
1425
|
function getTypeLabel(type) {
|
|
1371
1426
|
switch (type) {
|
|
1372
1427
|
case "RATING":
|
|
@@ -1398,6 +1453,22 @@ function pickAssistImages(all) {
|
|
|
1398
1453
|
}
|
|
1399
1454
|
return picked;
|
|
1400
1455
|
}
|
|
1456
|
+
var NO_FILES = [];
|
|
1457
|
+
function pickAssistFiles(files) {
|
|
1458
|
+
const picked = [];
|
|
1459
|
+
let total = 0;
|
|
1460
|
+
for (let i = files.length - 1; i >= 0 && picked.length < MAX_ASSIST_FILES; i--) {
|
|
1461
|
+
const attached = files[i];
|
|
1462
|
+
if (!isAssistReadableFile(attached.name)) continue;
|
|
1463
|
+
const text = decodeTextDataUrl(attached.dataUrl);
|
|
1464
|
+
if (!text || !text.trim()) continue;
|
|
1465
|
+
const content = text.slice(0, MAX_ASSIST_FILE_CHARS_EACH);
|
|
1466
|
+
if (total + content.length > MAX_ASSIST_FILE_CHARS) continue;
|
|
1467
|
+
picked.unshift({ index: i, file: { name: attached.name, content } });
|
|
1468
|
+
total += content.length;
|
|
1469
|
+
}
|
|
1470
|
+
return picked;
|
|
1471
|
+
}
|
|
1401
1472
|
var STARTERS = [
|
|
1402
1473
|
"Something on this page is broken",
|
|
1403
1474
|
"It did the wrong thing",
|
|
@@ -1474,7 +1545,9 @@ function AssistSheet({
|
|
|
1474
1545
|
theme: t2,
|
|
1475
1546
|
screenshots,
|
|
1476
1547
|
pageShot = null,
|
|
1477
|
-
|
|
1548
|
+
onAddFiles,
|
|
1549
|
+
files = NO_FILES,
|
|
1550
|
+
onRemoveFile,
|
|
1478
1551
|
onRemoveImage,
|
|
1479
1552
|
attachmentCount,
|
|
1480
1553
|
context,
|
|
@@ -1545,6 +1618,8 @@ function AssistSheet({
|
|
|
1545
1618
|
}
|
|
1546
1619
|
}
|
|
1547
1620
|
const readShots = new Set(pickAssistImages(screenshots));
|
|
1621
|
+
const sentFiles = (0, import_react3.useMemo)(() => pickAssistFiles(files), [files]);
|
|
1622
|
+
const readFiles = new Set(sentFiles.map((f) => f.index));
|
|
1548
1623
|
function leave(type, detail) {
|
|
1549
1624
|
logEvent(type, detail);
|
|
1550
1625
|
flushEvents();
|
|
@@ -1558,10 +1633,10 @@ function AssistSheet({
|
|
|
1558
1633
|
var _a;
|
|
1559
1634
|
if (phase === "draft") (_a = draftRef.current) == null ? void 0 : _a.focus();
|
|
1560
1635
|
}, [phase]);
|
|
1561
|
-
function degradeKeepingEvents(events, message) {
|
|
1636
|
+
function degradeKeepingEvents(events, message, retryable) {
|
|
1562
1637
|
if (events) eventsRef.current = [...events, ...eventsRef.current];
|
|
1563
1638
|
flushEvents();
|
|
1564
|
-
onDegrade(message);
|
|
1639
|
+
onDegrade(message, retryable);
|
|
1565
1640
|
}
|
|
1566
1641
|
async function runTurn(history2) {
|
|
1567
1642
|
var _a, _b, _c, _d;
|
|
@@ -1579,6 +1654,9 @@ function AssistSheet({
|
|
|
1579
1654
|
),
|
|
1580
1655
|
conversationId,
|
|
1581
1656
|
screenshots: sent,
|
|
1657
|
+
// Only when there is something: an older server then sees the body
|
|
1658
|
+
// it always did.
|
|
1659
|
+
...sentFiles.length > 0 ? { files: sentFiles.map((f) => f.file) } : {},
|
|
1582
1660
|
context: {
|
|
1583
1661
|
...context != null ? context : {},
|
|
1584
1662
|
imageSources: sent.map((shot) => pageShot && shot === pageShot ? "page" : "attached"),
|
|
@@ -1598,7 +1676,7 @@ function AssistSheet({
|
|
|
1598
1676
|
setBusy(false);
|
|
1599
1677
|
}
|
|
1600
1678
|
if (result.degraded) {
|
|
1601
|
-
degradeKeepingEvents(events, result.degraded);
|
|
1679
|
+
degradeKeepingEvents(events, result.degraded, result.retryable === true);
|
|
1602
1680
|
return;
|
|
1603
1681
|
}
|
|
1604
1682
|
if (result.conversationId) {
|
|
@@ -2586,7 +2664,7 @@ function AssistSheet({
|
|
|
2586
2664
|
// instead of remounting, and a draft is something you can
|
|
2587
2665
|
// still reply to (#360), not a form that replaced the chat.
|
|
2588
2666
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
2589
|
-
(screenshots.length > 0 ||
|
|
2667
|
+
(screenshots.length > 0 || files.length > 0 || onAddFiles) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2590
2668
|
"div",
|
|
2591
2669
|
{
|
|
2592
2670
|
style: {
|
|
@@ -2690,11 +2768,118 @@ function AssistSheet({
|
|
|
2690
2768
|
`${i}-${shot.slice(-16)}`
|
|
2691
2769
|
);
|
|
2692
2770
|
}),
|
|
2693
|
-
|
|
2771
|
+
files.map((file, i) => {
|
|
2772
|
+
const read = readFiles.has(i);
|
|
2773
|
+
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";
|
|
2774
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2775
|
+
"div",
|
|
2776
|
+
{
|
|
2777
|
+
"data-gg-assist-file": "",
|
|
2778
|
+
"data-gg-assist-file-read": read ? "" : void 0,
|
|
2779
|
+
title: `${file.name} \u2014 ${why}`,
|
|
2780
|
+
style: {
|
|
2781
|
+
position: "relative",
|
|
2782
|
+
height: "40px",
|
|
2783
|
+
maxWidth: "170px",
|
|
2784
|
+
display: "flex",
|
|
2785
|
+
alignItems: "center",
|
|
2786
|
+
gap: "6px",
|
|
2787
|
+
padding: "0 10px",
|
|
2788
|
+
borderRadius: "8px",
|
|
2789
|
+
border: `1px solid ${read ? t2.accent : t2.inputBorder}`,
|
|
2790
|
+
opacity: read ? 1 : 0.55,
|
|
2791
|
+
boxSizing: "border-box",
|
|
2792
|
+
flexShrink: 0
|
|
2793
|
+
},
|
|
2794
|
+
children: [
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2796
|
+
"path",
|
|
2797
|
+
{
|
|
2798
|
+
d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z M14 2v6h6",
|
|
2799
|
+
stroke: t2.textMuted,
|
|
2800
|
+
strokeWidth: "1.5",
|
|
2801
|
+
strokeLinecap: "round",
|
|
2802
|
+
strokeLinejoin: "round"
|
|
2803
|
+
}
|
|
2804
|
+
) }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2806
|
+
"span",
|
|
2807
|
+
{
|
|
2808
|
+
style: {
|
|
2809
|
+
fontSize: "11.5px",
|
|
2810
|
+
color: t2.text,
|
|
2811
|
+
overflow: "hidden",
|
|
2812
|
+
textOverflow: "ellipsis",
|
|
2813
|
+
whiteSpace: "nowrap"
|
|
2814
|
+
},
|
|
2815
|
+
children: file.name
|
|
2816
|
+
}
|
|
2817
|
+
),
|
|
2818
|
+
onRemoveFile && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2819
|
+
"button",
|
|
2820
|
+
{
|
|
2821
|
+
type: "button",
|
|
2822
|
+
"data-gg-assist-remove-file": "",
|
|
2823
|
+
"aria-label": `Remove file ${file.name}`,
|
|
2824
|
+
title: "Remove this file",
|
|
2825
|
+
onClick: () => {
|
|
2826
|
+
logEvent("file_removed", read ? "read" : "not read");
|
|
2827
|
+
onRemoveFile(i);
|
|
2828
|
+
},
|
|
2829
|
+
style: {
|
|
2830
|
+
position: "absolute",
|
|
2831
|
+
top: "-13px",
|
|
2832
|
+
right: "-13px",
|
|
2833
|
+
width: "32px",
|
|
2834
|
+
height: "32px",
|
|
2835
|
+
border: "none",
|
|
2836
|
+
background: "transparent",
|
|
2837
|
+
padding: 0,
|
|
2838
|
+
cursor: "pointer",
|
|
2839
|
+
display: "flex",
|
|
2840
|
+
alignItems: "center",
|
|
2841
|
+
justifyContent: "center",
|
|
2842
|
+
borderRadius: "50%"
|
|
2843
|
+
},
|
|
2844
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2845
|
+
"span",
|
|
2846
|
+
{
|
|
2847
|
+
"aria-hidden": "true",
|
|
2848
|
+
style: {
|
|
2849
|
+
width: "20px",
|
|
2850
|
+
height: "20px",
|
|
2851
|
+
boxSizing: "border-box",
|
|
2852
|
+
borderRadius: "50%",
|
|
2853
|
+
border: `2px solid ${t2.bg}`,
|
|
2854
|
+
background: "#ef4444",
|
|
2855
|
+
color: "#fff",
|
|
2856
|
+
display: "flex",
|
|
2857
|
+
alignItems: "center",
|
|
2858
|
+
justifyContent: "center"
|
|
2859
|
+
},
|
|
2860
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
2861
|
+
"path",
|
|
2862
|
+
{
|
|
2863
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
2864
|
+
stroke: "currentColor",
|
|
2865
|
+
strokeWidth: "1.6",
|
|
2866
|
+
strokeLinecap: "round"
|
|
2867
|
+
}
|
|
2868
|
+
) })
|
|
2869
|
+
}
|
|
2870
|
+
)
|
|
2871
|
+
}
|
|
2872
|
+
)
|
|
2873
|
+
]
|
|
2874
|
+
},
|
|
2875
|
+
`file-${i}-${file.name}`
|
|
2876
|
+
);
|
|
2877
|
+
}),
|
|
2878
|
+
onAddFiles && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
2694
2879
|
"label",
|
|
2695
2880
|
{
|
|
2696
2881
|
"data-gg-assist-attach": "",
|
|
2697
|
-
title: "Attach an image \u2014 or
|
|
2882
|
+
title: "Attach an image or a file (html, json, log\u2026) \u2014 or paste one",
|
|
2698
2883
|
style: {
|
|
2699
2884
|
width: "40px",
|
|
2700
2885
|
height: "40px",
|
|
@@ -2714,14 +2899,18 @@ function AssistSheet({
|
|
|
2714
2899
|
"input",
|
|
2715
2900
|
{
|
|
2716
2901
|
type: "file",
|
|
2717
|
-
accept:
|
|
2902
|
+
accept: ASSIST_ATTACHMENT_ACCEPT,
|
|
2718
2903
|
multiple: true,
|
|
2719
2904
|
onChange: (e) => {
|
|
2720
2905
|
var _a;
|
|
2721
|
-
const
|
|
2722
|
-
if (
|
|
2723
|
-
|
|
2724
|
-
|
|
2906
|
+
const picked = Array.from((_a = e.target.files) != null ? _a : []);
|
|
2907
|
+
if (picked.length) {
|
|
2908
|
+
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
2909
|
+
if (images) logEvent("image_added", String(images));
|
|
2910
|
+
if (picked.length > images) {
|
|
2911
|
+
logEvent("file_added", String(picked.length - images));
|
|
2912
|
+
}
|
|
2913
|
+
onAddFiles(picked);
|
|
2725
2914
|
}
|
|
2726
2915
|
e.target.value = "";
|
|
2727
2916
|
},
|
|
@@ -2902,6 +3091,7 @@ function AssistSheet({
|
|
|
2902
3091
|
}
|
|
2903
3092
|
var FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2904
3093
|
var FAILED = "Couldn't send it. Try again in a moment.";
|
|
3094
|
+
var MAX_SELF_REPORT_IMAGES = 5;
|
|
2905
3095
|
function describeSentAlong(hasChat, screenshotCount) {
|
|
2906
3096
|
const parts = [
|
|
2907
3097
|
...hasChat ? ["your AI chat"] : [],
|
|
@@ -2925,11 +3115,49 @@ function GlitchgrabProblemPanel({
|
|
|
2925
3115
|
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
2926
3116
|
const [sent, setSent] = (0, import_react4.useState)(false);
|
|
2927
3117
|
const [error, setError] = (0, import_react4.useState)(null);
|
|
3118
|
+
const [images, setImages] = (0, import_react4.useState)(
|
|
3119
|
+
() => screenshots.slice(0, MAX_SELF_REPORT_IMAGES)
|
|
3120
|
+
);
|
|
2928
3121
|
const inputRef = (0, import_react4.useRef)(null);
|
|
3122
|
+
const fileRef = (0, import_react4.useRef)(null);
|
|
2929
3123
|
(0, import_react4.useEffect)(() => {
|
|
2930
3124
|
var _a;
|
|
2931
3125
|
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
2932
3126
|
}, []);
|
|
3127
|
+
const addImages = (0, import_react4.useCallback)((files) => {
|
|
3128
|
+
const picked = files.filter((file) => file.type.startsWith("image/"));
|
|
3129
|
+
if (!picked.length) return;
|
|
3130
|
+
void Promise.all(picked.map((file) => encodeImageFile(file).catch(() => null))).then(
|
|
3131
|
+
(encoded) => {
|
|
3132
|
+
const added = encoded.filter((url) => !!url);
|
|
3133
|
+
if (added.length) {
|
|
3134
|
+
setImages((prev) => [...prev, ...added].slice(0, MAX_SELF_REPORT_IMAGES));
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
);
|
|
3138
|
+
}, []);
|
|
3139
|
+
(0, import_react4.useEffect)(() => {
|
|
3140
|
+
const onPaste = (e) => {
|
|
3141
|
+
var _a;
|
|
3142
|
+
try {
|
|
3143
|
+
const items = (_a = e.clipboardData) == null ? void 0 : _a.items;
|
|
3144
|
+
if (!items) return;
|
|
3145
|
+
const files = [];
|
|
3146
|
+
for (let i = 0; i < items.length; i++) {
|
|
3147
|
+
if (items[i].kind !== "file") continue;
|
|
3148
|
+
const file = items[i].getAsFile();
|
|
3149
|
+
if (file) files.push(file);
|
|
3150
|
+
}
|
|
3151
|
+
if (!files.length) return;
|
|
3152
|
+
e.preventDefault();
|
|
3153
|
+
e.stopImmediatePropagation();
|
|
3154
|
+
addImages(files);
|
|
3155
|
+
} catch (e2) {
|
|
3156
|
+
}
|
|
3157
|
+
};
|
|
3158
|
+
window.addEventListener("paste", onPaste, true);
|
|
3159
|
+
return () => window.removeEventListener("paste", onPaste, true);
|
|
3160
|
+
}, [addImages]);
|
|
2933
3161
|
(0, import_react4.useEffect)(() => {
|
|
2934
3162
|
const onKey = (e) => {
|
|
2935
3163
|
if (e.key !== "Escape") return;
|
|
@@ -2945,7 +3173,13 @@ function GlitchgrabProblemPanel({
|
|
|
2945
3173
|
setBusy(true);
|
|
2946
3174
|
setError(null);
|
|
2947
3175
|
try {
|
|
2948
|
-
const result = await send({
|
|
3176
|
+
const result = await send({
|
|
3177
|
+
description,
|
|
3178
|
+
surface,
|
|
3179
|
+
conversationId,
|
|
3180
|
+
reportType,
|
|
3181
|
+
screenshots: images
|
|
3182
|
+
});
|
|
2949
3183
|
if (result == null ? void 0 : result.success) setSent(true);
|
|
2950
3184
|
else setError((result == null ? void 0 : result.message) || FAILED);
|
|
2951
3185
|
} catch (e) {
|
|
@@ -3098,6 +3332,134 @@ function GlitchgrabProblemPanel({
|
|
|
3098
3332
|
}
|
|
3099
3333
|
}
|
|
3100
3334
|
),
|
|
3335
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3336
|
+
"div",
|
|
3337
|
+
{
|
|
3338
|
+
"data-gg-self-report-images": "",
|
|
3339
|
+
style: {
|
|
3340
|
+
display: "flex",
|
|
3341
|
+
flexWrap: "wrap",
|
|
3342
|
+
alignItems: "center",
|
|
3343
|
+
gap: "8px",
|
|
3344
|
+
marginTop: "10px"
|
|
3345
|
+
},
|
|
3346
|
+
children: [
|
|
3347
|
+
images.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative", width: "48px", height: "48px" }, children: [
|
|
3348
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3349
|
+
"img",
|
|
3350
|
+
{
|
|
3351
|
+
src,
|
|
3352
|
+
alt: `Screenshot ${i + 1}`,
|
|
3353
|
+
style: {
|
|
3354
|
+
width: "100%",
|
|
3355
|
+
height: "100%",
|
|
3356
|
+
objectFit: "cover",
|
|
3357
|
+
display: "block",
|
|
3358
|
+
boxSizing: "border-box",
|
|
3359
|
+
borderRadius: "8px",
|
|
3360
|
+
border: `1px solid ${t2.inputBorder}`
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
),
|
|
3364
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3365
|
+
"button",
|
|
3366
|
+
{
|
|
3367
|
+
type: "button",
|
|
3368
|
+
"data-gg-self-report-remove-image": "",
|
|
3369
|
+
"aria-label": `Remove screenshot ${i + 1}`,
|
|
3370
|
+
title: "Don't send this one",
|
|
3371
|
+
onClick: () => setImages((prev) => prev.filter((_, j) => j !== i)),
|
|
3372
|
+
style: {
|
|
3373
|
+
position: "absolute",
|
|
3374
|
+
top: "-13px",
|
|
3375
|
+
right: "-13px",
|
|
3376
|
+
width: "32px",
|
|
3377
|
+
height: "32px",
|
|
3378
|
+
border: "none",
|
|
3379
|
+
background: "transparent",
|
|
3380
|
+
padding: 0,
|
|
3381
|
+
cursor: "pointer",
|
|
3382
|
+
display: "flex",
|
|
3383
|
+
alignItems: "center",
|
|
3384
|
+
justifyContent: "center",
|
|
3385
|
+
borderRadius: "50%"
|
|
3386
|
+
},
|
|
3387
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3388
|
+
"span",
|
|
3389
|
+
{
|
|
3390
|
+
"aria-hidden": "true",
|
|
3391
|
+
style: {
|
|
3392
|
+
width: "20px",
|
|
3393
|
+
height: "20px",
|
|
3394
|
+
boxSizing: "border-box",
|
|
3395
|
+
borderRadius: "50%",
|
|
3396
|
+
border: `2px solid ${t2.bg}`,
|
|
3397
|
+
background: "#ef4444",
|
|
3398
|
+
color: "#fff",
|
|
3399
|
+
display: "flex",
|
|
3400
|
+
alignItems: "center",
|
|
3401
|
+
justifyContent: "center"
|
|
3402
|
+
},
|
|
3403
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3404
|
+
"path",
|
|
3405
|
+
{
|
|
3406
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
3407
|
+
stroke: "currentColor",
|
|
3408
|
+
strokeWidth: "1.6",
|
|
3409
|
+
strokeLinecap: "round"
|
|
3410
|
+
}
|
|
3411
|
+
) })
|
|
3412
|
+
}
|
|
3413
|
+
)
|
|
3414
|
+
}
|
|
3415
|
+
)
|
|
3416
|
+
] }, i)),
|
|
3417
|
+
images.length < MAX_SELF_REPORT_IMAGES && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3418
|
+
"button",
|
|
3419
|
+
{
|
|
3420
|
+
type: "button",
|
|
3421
|
+
"data-gg-self-report-attach": "",
|
|
3422
|
+
"aria-label": "Add screenshot",
|
|
3423
|
+
title: "Add a screenshot \u2014 or paste one",
|
|
3424
|
+
onClick: () => {
|
|
3425
|
+
var _a;
|
|
3426
|
+
return (_a = fileRef.current) == null ? void 0 : _a.click();
|
|
3427
|
+
},
|
|
3428
|
+
style: {
|
|
3429
|
+
height: "48px",
|
|
3430
|
+
padding: "0 12px",
|
|
3431
|
+
boxSizing: "border-box",
|
|
3432
|
+
borderRadius: "8px",
|
|
3433
|
+
border: `1px dashed ${t2.inputBorder}`,
|
|
3434
|
+
background: "transparent",
|
|
3435
|
+
color: t2.textMuted,
|
|
3436
|
+
fontSize: "12.5px",
|
|
3437
|
+
fontWeight: 600,
|
|
3438
|
+
fontFamily: "inherit",
|
|
3439
|
+
cursor: "pointer"
|
|
3440
|
+
},
|
|
3441
|
+
children: images.length >= 3 ? "+ Add" : "+ Add screenshot"
|
|
3442
|
+
}
|
|
3443
|
+
),
|
|
3444
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3445
|
+
"input",
|
|
3446
|
+
{
|
|
3447
|
+
ref: fileRef,
|
|
3448
|
+
type: "file",
|
|
3449
|
+
accept: "image/*",
|
|
3450
|
+
multiple: true,
|
|
3451
|
+
"data-gg-self-report-file": "",
|
|
3452
|
+
onChange: (e) => {
|
|
3453
|
+
var _a;
|
|
3454
|
+
addImages(Array.from((_a = e.target.files) != null ? _a : []));
|
|
3455
|
+
e.target.value = "";
|
|
3456
|
+
},
|
|
3457
|
+
style: { display: "none" }
|
|
3458
|
+
}
|
|
3459
|
+
)
|
|
3460
|
+
]
|
|
3461
|
+
}
|
|
3462
|
+
),
|
|
3101
3463
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3102
3464
|
"p",
|
|
3103
3465
|
{
|
|
@@ -3106,7 +3468,7 @@ function GlitchgrabProblemPanel({
|
|
|
3106
3468
|
children: [
|
|
3107
3469
|
"Also sent, so we can see what happened:",
|
|
3108
3470
|
" ",
|
|
3109
|
-
describeSentAlong(conversationId !== null,
|
|
3471
|
+
describeSentAlong(conversationId !== null, images.length),
|
|
3110
3472
|
"."
|
|
3111
3473
|
]
|
|
3112
3474
|
}
|
|
@@ -3147,38 +3509,6 @@ function isMac() {
|
|
|
3147
3509
|
function getShortcutLabel() {
|
|
3148
3510
|
return isMac() ? GLITCHGRAB_SHORTCUT_MAC : GLITCHGRAB_SHORTCUT;
|
|
3149
3511
|
}
|
|
3150
|
-
var ATTACHMENT_ACCEPT = [
|
|
3151
|
-
"image/*",
|
|
3152
|
-
// text — inlined into the issue body
|
|
3153
|
-
".html",
|
|
3154
|
-
".htm",
|
|
3155
|
-
".txt",
|
|
3156
|
-
".md",
|
|
3157
|
-
".json",
|
|
3158
|
-
".xml",
|
|
3159
|
-
".log",
|
|
3160
|
-
".yml",
|
|
3161
|
-
".yaml",
|
|
3162
|
-
".csv",
|
|
3163
|
-
".har",
|
|
3164
|
-
".js",
|
|
3165
|
-
".mjs",
|
|
3166
|
-
".cjs",
|
|
3167
|
-
".ts",
|
|
3168
|
-
".tsx",
|
|
3169
|
-
".jsx",
|
|
3170
|
-
".css",
|
|
3171
|
-
".scss",
|
|
3172
|
-
".py",
|
|
3173
|
-
".sh",
|
|
3174
|
-
// binary documents
|
|
3175
|
-
".pdf",
|
|
3176
|
-
".doc",
|
|
3177
|
-
".docx",
|
|
3178
|
-
".xls",
|
|
3179
|
-
".xlsx",
|
|
3180
|
-
".zip"
|
|
3181
|
-
].join(",");
|
|
3182
3512
|
var MAX_SCALE = 2;
|
|
3183
3513
|
var FRAME_TIMEOUT_MS = 3e3;
|
|
3184
3514
|
var GRAB_TIMEOUT_MS = FRAME_TIMEOUT_MS + 2e3;
|
|
@@ -6408,8 +6738,10 @@ function ReportDialog({
|
|
|
6408
6738
|
theme: layerTheme,
|
|
6409
6739
|
screenshots,
|
|
6410
6740
|
pageShot,
|
|
6411
|
-
|
|
6741
|
+
onAddFiles: addFiles,
|
|
6412
6742
|
onRemoveImage: (index) => setScreenshots((prev) => prev.filter((_, i) => i !== index)),
|
|
6743
|
+
files: attachments,
|
|
6744
|
+
onRemoveFile: (index) => setAttachments((prev) => prev.filter((_, i) => i !== index)),
|
|
6413
6745
|
attachmentCount: screenshots.length + attachments.length,
|
|
6414
6746
|
context: { ...assistContext != null ? assistContext : {}, reportType },
|
|
6415
6747
|
reportTypeLabel: getTypeLabel(reportType),
|
|
@@ -6451,9 +6783,9 @@ function ReportDialog({
|
|
|
6451
6783
|
setSelfReportPrefill(prefill != null ? prefill : "");
|
|
6452
6784
|
setSelfReportFrom("assist");
|
|
6453
6785
|
} : void 0,
|
|
6454
|
-
onDegrade: (message) => {
|
|
6786
|
+
onDegrade: (message, retryable) => {
|
|
6455
6787
|
setAssistOpen(false);
|
|
6456
|
-
setAssistUsed(true);
|
|
6788
|
+
if (!retryable) setAssistUsed(true);
|
|
6457
6789
|
setAssistNotice(message);
|
|
6458
6790
|
},
|
|
6459
6791
|
onClose: () => {
|