glitchgrab 1.58.2 → 1.59.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 +40 -0
- package/dist/index.d.mts +77 -1
- package/dist/index.d.ts +77 -1
- package/dist/index.js +1630 -737
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1627 -737
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +11 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +7 -2
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +7 -2
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -49,12 +49,14 @@ __export(index_exports, {
|
|
|
49
49
|
computeSignature: () => computeSignature,
|
|
50
50
|
enhanceText: () => enhanceText,
|
|
51
51
|
fetchGlitchgrabFeedback: () => fetchGlitchgrabFeedback,
|
|
52
|
+
fetchGlitchgrabReportThread: () => fetchGlitchgrabReportThread,
|
|
52
53
|
fetchGlitchgrabReports: () => fetchGlitchgrabReports,
|
|
53
54
|
getAppContext: () => getAppContext,
|
|
54
55
|
getBreadcrumbs: () => getBreadcrumbs,
|
|
55
56
|
getShortcutLabel: () => getShortcutLabel2,
|
|
56
57
|
initBreadcrumbs: () => initBreadcrumbs,
|
|
57
58
|
matchesShortcut: () => matchesShortcut,
|
|
59
|
+
postGlitchgrabReportComment: () => postGlitchgrabReportComment,
|
|
58
60
|
sanitizeUrl: () => sanitizeUrl,
|
|
59
61
|
sendFeedback: () => sendFeedback,
|
|
60
62
|
sendLead: () => sendLead,
|
|
@@ -65,6 +67,7 @@ __export(index_exports, {
|
|
|
65
67
|
useGlitchgrab: () => useGlitchgrab,
|
|
66
68
|
useGlitchgrabActions: () => useGlitchgrabActions,
|
|
67
69
|
useGlitchgrabFeedback: () => useGlitchgrabFeedback,
|
|
70
|
+
useGlitchgrabReportThread: () => useGlitchgrabReportThread,
|
|
68
71
|
useGlitchgrabReports: () => useGlitchgrabReports
|
|
69
72
|
});
|
|
70
73
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -239,7 +242,7 @@ function argsToString(args) {
|
|
|
239
242
|
function previewJson(value, max) {
|
|
240
243
|
let out = "";
|
|
241
244
|
const path = /* @__PURE__ */ new WeakSet();
|
|
242
|
-
const
|
|
245
|
+
const write2 = (input, inArray) => {
|
|
243
246
|
if (out.length > max) return;
|
|
244
247
|
let v = input;
|
|
245
248
|
if (v !== null && typeof v === "object" && typeof v.toJSON === "function") {
|
|
@@ -276,7 +279,7 @@ function previewJson(value, max) {
|
|
|
276
279
|
out += "[";
|
|
277
280
|
for (let i = 0; i < obj.length && out.length <= max; i++) {
|
|
278
281
|
if (i > 0) out += ",";
|
|
279
|
-
|
|
282
|
+
write2(obj[i], true);
|
|
280
283
|
}
|
|
281
284
|
out += "]";
|
|
282
285
|
} else {
|
|
@@ -289,13 +292,13 @@ function previewJson(value, max) {
|
|
|
289
292
|
if (child === void 0 || typeof child === "function" || typeof child === "symbol") continue;
|
|
290
293
|
out += `${first ? "" : ","}${JSON.stringify(key)}:`;
|
|
291
294
|
first = false;
|
|
292
|
-
|
|
295
|
+
write2(child, false);
|
|
293
296
|
}
|
|
294
297
|
out += "}";
|
|
295
298
|
}
|
|
296
299
|
path.delete(obj);
|
|
297
300
|
};
|
|
298
|
-
|
|
301
|
+
write2(value, false);
|
|
299
302
|
return out;
|
|
300
303
|
}
|
|
301
304
|
async function readErrorBody(response, url) {
|
|
@@ -772,12 +775,21 @@ function signedFields(identity) {
|
|
|
772
775
|
return { userId: identity.userId, signature: identity.signature };
|
|
773
776
|
}
|
|
774
777
|
async function enhanceText(text, token, baseUrl, screenshot, context, identity) {
|
|
778
|
+
try {
|
|
779
|
+
return await enhanceTextOrThrow(text, token, baseUrl, screenshot, context, identity);
|
|
780
|
+
} catch (e) {
|
|
781
|
+
return text;
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
async function enhanceTextOrThrow(text, token, baseUrl, screenshot, context, identity) {
|
|
775
785
|
var _a;
|
|
786
|
+
const trimmed = text.trim();
|
|
787
|
+
if (!trimmed) return text;
|
|
788
|
+
const unavailable = "AI enhance isn't available right now \u2014 send your report as written.";
|
|
789
|
+
let response;
|
|
776
790
|
try {
|
|
777
|
-
const trimmed = text.trim();
|
|
778
|
-
if (!trimmed) return text;
|
|
779
791
|
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/enhance-text`;
|
|
780
|
-
|
|
792
|
+
response = await fetch(url, {
|
|
781
793
|
method: "POST",
|
|
782
794
|
headers: {
|
|
783
795
|
"Content-Type": "application/json",
|
|
@@ -790,15 +802,20 @@ async function enhanceText(text, token, baseUrl, screenshot, context, identity)
|
|
|
790
802
|
...signedFields(identity)
|
|
791
803
|
})
|
|
792
804
|
});
|
|
793
|
-
if (!response.ok) return text;
|
|
794
|
-
const envelope = await response.json();
|
|
795
|
-
if ((envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.text) === "string") {
|
|
796
|
-
return envelope.data.text;
|
|
797
|
-
}
|
|
798
|
-
return text;
|
|
799
805
|
} catch (e) {
|
|
800
|
-
|
|
806
|
+
throw new Error(unavailable);
|
|
807
|
+
}
|
|
808
|
+
if (response.status === 429) {
|
|
809
|
+
throw new Error("Too many AI enhance tries \u2014 wait a while, or send your report as written.");
|
|
801
810
|
}
|
|
811
|
+
const envelope = await response.json().catch(() => null);
|
|
812
|
+
if (response.ok && (envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.text) === "string") {
|
|
813
|
+
return envelope.data.text;
|
|
814
|
+
}
|
|
815
|
+
if (response.status === 400 && typeof (envelope == null ? void 0 : envelope.error) === "string") {
|
|
816
|
+
throw new Error(envelope.error);
|
|
817
|
+
}
|
|
818
|
+
throw new Error(unavailable);
|
|
802
819
|
}
|
|
803
820
|
async function findSimilarIssues(description, token, baseUrl, identity, files) {
|
|
804
821
|
var _a;
|
|
@@ -956,6 +973,292 @@ function clearDedupCache() {
|
|
|
956
973
|
seen.clear();
|
|
957
974
|
}
|
|
958
975
|
|
|
976
|
+
// src/hydration.ts
|
|
977
|
+
var HYDRATION_CODE_RE = /Minified React error #(418|419|422|423|425)\b/;
|
|
978
|
+
var HYDRATION_DEV_RE = /Hydration failed|hydration mismatch|Text content does not match|did not match\. Server|There was an error while hydrating|error occurred during hydration|server rendered HTML didn't match/i;
|
|
979
|
+
var BAILOUT_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
|
980
|
+
var DOM_SNIPPET_MAX = 3e3;
|
|
981
|
+
var STACK_FRAMES_MAX = 40;
|
|
982
|
+
function messageOf(error) {
|
|
983
|
+
if (error && typeof error === "object" && typeof error.message === "string") {
|
|
984
|
+
return error.message;
|
|
985
|
+
}
|
|
986
|
+
return typeof error === "string" ? error : "";
|
|
987
|
+
}
|
|
988
|
+
function hydrationCode(message) {
|
|
989
|
+
if (!message) return null;
|
|
990
|
+
const m = HYDRATION_CODE_RE.exec(message);
|
|
991
|
+
if (m) return m[1];
|
|
992
|
+
return HYDRATION_DEV_RE.test(message) ? "dev" : null;
|
|
993
|
+
}
|
|
994
|
+
function isHydrationError(error) {
|
|
995
|
+
if (hydrationCode(messageOf(error))) return true;
|
|
996
|
+
const cause = error && typeof error === "object" ? error.cause : void 0;
|
|
997
|
+
return cause !== void 0 && cause !== error && hydrationCode(messageOf(cause)) !== null;
|
|
998
|
+
}
|
|
999
|
+
function isBailout(error) {
|
|
1000
|
+
const e = error;
|
|
1001
|
+
if (!e || typeof e !== "object") return false;
|
|
1002
|
+
if (e.digest === BAILOUT_DIGEST) return true;
|
|
1003
|
+
const c = e.cause;
|
|
1004
|
+
return !!c && typeof c === "object" && c.digest === BAILOUT_DIGEST;
|
|
1005
|
+
}
|
|
1006
|
+
function componentStackNames(stack) {
|
|
1007
|
+
if (!stack) return [];
|
|
1008
|
+
const names = [];
|
|
1009
|
+
for (const raw of stack.split("\n")) {
|
|
1010
|
+
const line = raw.trim();
|
|
1011
|
+
if (!line) continue;
|
|
1012
|
+
let name = "";
|
|
1013
|
+
if (line.startsWith("at ")) {
|
|
1014
|
+
name = line.slice(3).split(" (")[0].trim();
|
|
1015
|
+
} else if (line.includes("@")) {
|
|
1016
|
+
name = line.slice(0, line.indexOf("@")).trim();
|
|
1017
|
+
} else {
|
|
1018
|
+
name = line;
|
|
1019
|
+
}
|
|
1020
|
+
if (name) names.push(name);
|
|
1021
|
+
if (names.length >= STACK_FRAMES_MAX) break;
|
|
1022
|
+
}
|
|
1023
|
+
return names;
|
|
1024
|
+
}
|
|
1025
|
+
function componentStackKey(stack) {
|
|
1026
|
+
return componentStackNames(stack).join(">");
|
|
1027
|
+
}
|
|
1028
|
+
var observer = null;
|
|
1029
|
+
var observerStarted = false;
|
|
1030
|
+
var observerStopAt = 0;
|
|
1031
|
+
var OBSERVE_MS = 3e4;
|
|
1032
|
+
function startObserver() {
|
|
1033
|
+
if (observerStarted || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
observerStarted = true;
|
|
1037
|
+
try {
|
|
1038
|
+
observer = new MutationObserver(() => {
|
|
1039
|
+
if (Date.now() > observerStopAt) stopObserver();
|
|
1040
|
+
});
|
|
1041
|
+
observer.observe(document, { childList: true, subtree: true });
|
|
1042
|
+
observerStopAt = Date.now() + OBSERVE_MS;
|
|
1043
|
+
setTimeout(stopObserver, OBSERVE_MS);
|
|
1044
|
+
} catch (e) {
|
|
1045
|
+
observer = null;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
function stopObserver() {
|
|
1049
|
+
try {
|
|
1050
|
+
observer == null ? void 0 : observer.disconnect();
|
|
1051
|
+
} catch (e) {
|
|
1052
|
+
}
|
|
1053
|
+
observer = null;
|
|
1054
|
+
}
|
|
1055
|
+
function describeNode(node) {
|
|
1056
|
+
if (!node) return "";
|
|
1057
|
+
if (node.nodeType === 9) return "#document";
|
|
1058
|
+
const el = node;
|
|
1059
|
+
if (!el.tagName) return node.nodeName;
|
|
1060
|
+
const id = el.id ? `#${el.id}` : "";
|
|
1061
|
+
const cls = typeof el.className === "string" && el.className.trim() ? "." + el.className.trim().split(/\s+/).slice(0, 3).join(".") : "";
|
|
1062
|
+
return `${el.tagName.toLowerCase()}${id}${cls}`;
|
|
1063
|
+
}
|
|
1064
|
+
function pathOf(node) {
|
|
1065
|
+
const parts = [];
|
|
1066
|
+
let cur = node;
|
|
1067
|
+
while (cur && parts.length < 6) {
|
|
1068
|
+
parts.unshift(describeNode(cur));
|
|
1069
|
+
if (cur.nodeType === 9) break;
|
|
1070
|
+
cur = cur.parentNode;
|
|
1071
|
+
}
|
|
1072
|
+
return parts.join(" > ");
|
|
1073
|
+
}
|
|
1074
|
+
var NON_CONTENT_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "LINK", "META", "NOSCRIPT", "TEMPLATE", "TITLE", "HEAD"]);
|
|
1075
|
+
function isInHead(node) {
|
|
1076
|
+
for (let cur = node; cur; cur = cur.parentNode) {
|
|
1077
|
+
if (cur.nodeName === "HEAD") return true;
|
|
1078
|
+
if (cur.nodeName === "BODY") return false;
|
|
1079
|
+
}
|
|
1080
|
+
return false;
|
|
1081
|
+
}
|
|
1082
|
+
var GSTIN_RE = /\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z0-9]Z[A-Z0-9]\b/g;
|
|
1083
|
+
var PAN_RE = /\b[A-Z]{5}\d{4}[A-Z]\b/g;
|
|
1084
|
+
function scrubHtml(html) {
|
|
1085
|
+
return redactString(
|
|
1086
|
+
html.replace(/\svalue="[^"]*"/gi, ' value="[REDACTED]"').replace(GSTIN_RE, "[REDACTED_GSTIN]").replace(PAN_RE, "[REDACTED_PAN]").replace(/\d{6,}/g, (m) => "#".repeat(Math.min(m.length, 6)))
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
function takeRemovedServerHtml() {
|
|
1090
|
+
var _a, _b;
|
|
1091
|
+
if (!observer) return { html: "", where: "" };
|
|
1092
|
+
try {
|
|
1093
|
+
const records = observer.takeRecords();
|
|
1094
|
+
let html = "";
|
|
1095
|
+
let where = "";
|
|
1096
|
+
for (const rec of records) {
|
|
1097
|
+
if (rec.type !== "childList" || rec.removedNodes.length === 0) continue;
|
|
1098
|
+
if (isInHead(rec.target)) continue;
|
|
1099
|
+
if (!where) where = pathOf(rec.target);
|
|
1100
|
+
for (const node of Array.from(rec.removedNodes)) {
|
|
1101
|
+
if (node.nodeType === 1 && NON_CONTENT_TAGS.has(node.tagName)) continue;
|
|
1102
|
+
if (node.nodeType === 3 && !((_a = node.textContent) != null ? _a : "").trim()) continue;
|
|
1103
|
+
const piece = node.nodeType === 1 ? node.outerHTML : node.nodeType === 3 ? `#text "${(_b = node.textContent) != null ? _b : ""}"` : "";
|
|
1104
|
+
if (!piece) continue;
|
|
1105
|
+
html += (html ? "\n" : "") + piece;
|
|
1106
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1107
|
+
}
|
|
1108
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1109
|
+
}
|
|
1110
|
+
const scrubbed = scrubHtml(html);
|
|
1111
|
+
return {
|
|
1112
|
+
html: scrubbed.length > DOM_SNIPPET_MAX ? `${scrubbed.slice(0, DOM_SNIPPET_MAX)}\u2026[truncated]` : scrubbed,
|
|
1113
|
+
where
|
|
1114
|
+
};
|
|
1115
|
+
} catch (e) {
|
|
1116
|
+
return { html: "", where: "" };
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
function detectForeignNodes(doc = document) {
|
|
1120
|
+
var _a;
|
|
1121
|
+
const found = [];
|
|
1122
|
+
try {
|
|
1123
|
+
const html = doc.documentElement;
|
|
1124
|
+
if ((html == null ? void 0 : html.classList.contains("translated-ltr")) || (html == null ? void 0 : html.classList.contains("translated-rtl"))) {
|
|
1125
|
+
found.push("Google Translate is active (html.translated-*)");
|
|
1126
|
+
}
|
|
1127
|
+
const fonts = doc.getElementsByTagName("font").length;
|
|
1128
|
+
if (fonts > 0) found.push(`<font> \xD7 ${fonts} (Google Translate or a translation extension)`);
|
|
1129
|
+
const detectors = doc.querySelectorAll("a[x-apple-data-detectors]").length;
|
|
1130
|
+
if (detectors > 0) {
|
|
1131
|
+
found.push(`<a x-apple-data-detectors> \xD7 ${detectors} (iOS format detection turned text into links)`);
|
|
1132
|
+
}
|
|
1133
|
+
if (doc.querySelector("[data-gr-ext-installed],[data-new-gr-c-s-check-loaded],grammarly-desktop-integration")) {
|
|
1134
|
+
found.push("Grammarly extension attributes");
|
|
1135
|
+
}
|
|
1136
|
+
if (doc.querySelector("[data-lt-installed]")) found.push("LanguageTool extension attributes");
|
|
1137
|
+
if ((_a = doc.body) == null ? void 0 : _a.hasAttribute("cz-shortcut-listen")) found.push("ColorZilla extension attribute on <body>");
|
|
1138
|
+
const custom = /* @__PURE__ */ new Set();
|
|
1139
|
+
for (const parent of [html, doc.body]) {
|
|
1140
|
+
if (!parent) continue;
|
|
1141
|
+
for (const child of Array.from(parent.children)) {
|
|
1142
|
+
const tag = child.tagName.toLowerCase();
|
|
1143
|
+
if (tag.includes("-")) custom.add(tag);
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
if (custom.size > 0) {
|
|
1147
|
+
found.push(`custom elements at top level: ${Array.from(custom).slice(0, 5).join(", ")} (often an extension)`);
|
|
1148
|
+
}
|
|
1149
|
+
} catch (e) {
|
|
1150
|
+
}
|
|
1151
|
+
return found;
|
|
1152
|
+
}
|
|
1153
|
+
function hydrationTiming() {
|
|
1154
|
+
var _a, _b, _c, _d;
|
|
1155
|
+
try {
|
|
1156
|
+
if (typeof performance === "undefined") return "";
|
|
1157
|
+
const at2 = Math.round(performance.now());
|
|
1158
|
+
const parts = [`error at ${at2}ms after navigation start`];
|
|
1159
|
+
const nav = (_b = (_a = performance.getEntriesByType) == null ? void 0 : _a.call(performance, "navigation")) == null ? void 0 : _b[0];
|
|
1160
|
+
if (nav == null ? void 0 : nav.domContentLoadedEventEnd) {
|
|
1161
|
+
parts.push(`DOMContentLoaded ${Math.round(nav.domContentLoadedEventEnd)}ms`);
|
|
1162
|
+
}
|
|
1163
|
+
const fetches = ((_d = (_c = performance.getEntriesByType) == null ? void 0 : _c.call(performance, "resource")) != null ? _d : []).filter((e) => {
|
|
1164
|
+
const t = e.initiatorType;
|
|
1165
|
+
return t === "fetch" || t === "xmlhttprequest";
|
|
1166
|
+
}).sort((a, b) => a.responseEnd - b.responseEnd).slice(0, 8).map((e) => {
|
|
1167
|
+
let path = e.name;
|
|
1168
|
+
try {
|
|
1169
|
+
const u = new URL(e.name);
|
|
1170
|
+
path = u.origin === window.location.origin ? u.pathname : `${u.host}${u.pathname}`;
|
|
1171
|
+
} catch (e2) {
|
|
1172
|
+
}
|
|
1173
|
+
return `${path} ${Math.round(e.responseEnd)}ms`;
|
|
1174
|
+
});
|
|
1175
|
+
if (fetches.length > 0) parts.push(`fetches finished before it: ${fetches.join(", ")}`);
|
|
1176
|
+
else parts.push("no fetch had finished yet");
|
|
1177
|
+
return parts.join("; ");
|
|
1178
|
+
} catch (e) {
|
|
1179
|
+
return "";
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
function hydrationMetadata(error, extra) {
|
|
1183
|
+
var _a, _b, _c;
|
|
1184
|
+
const code = (_a = hydrationCode(messageOf(error))) != null ? _a : hydrationCode(messageOf(error == null ? void 0 : error.cause));
|
|
1185
|
+
const meta = { errorKind: "hydration" };
|
|
1186
|
+
if (code) meta.hydrationCode = code;
|
|
1187
|
+
const cause = error == null ? void 0 : error.cause;
|
|
1188
|
+
if (cause && cause !== error && messageOf(cause)) {
|
|
1189
|
+
meta.hydrationCause = messageOf(cause).slice(0, 500);
|
|
1190
|
+
}
|
|
1191
|
+
if ((_b = extra == null ? void 0 : extra.removed) == null ? void 0 : _b.html) meta.hydrationServerHtml = extra.removed.html;
|
|
1192
|
+
if ((_c = extra == null ? void 0 : extra.removed) == null ? void 0 : _c.where) meta.hydrationReplacedIn = extra.removed.where;
|
|
1193
|
+
const foreign = detectForeignNodes();
|
|
1194
|
+
if (foreign.length > 0) meta.hydrationForeignNodes = foreign.join("\n");
|
|
1195
|
+
const timing = hydrationTiming();
|
|
1196
|
+
if (timing) meta.hydrationTiming = timing;
|
|
1197
|
+
return meta;
|
|
1198
|
+
}
|
|
1199
|
+
var handled = /* @__PURE__ */ new WeakSet();
|
|
1200
|
+
function isHandledHydrationError(error) {
|
|
1201
|
+
return !!error && typeof error === "object" && handled.has(error);
|
|
1202
|
+
}
|
|
1203
|
+
function markHandled(error) {
|
|
1204
|
+
if (error && typeof error === "object") {
|
|
1205
|
+
handled.add(error);
|
|
1206
|
+
const cause = error.cause;
|
|
1207
|
+
if (cause && typeof cause === "object") handled.add(cause);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
var reporter = null;
|
|
1211
|
+
var PATCHED = "__glitchgrabHydrationPatched";
|
|
1212
|
+
function findFiberRoot(container) {
|
|
1213
|
+
if (!container || typeof container !== "object") return null;
|
|
1214
|
+
try {
|
|
1215
|
+
const key = Object.keys(container).find((k) => k.startsWith("__reactContainer$"));
|
|
1216
|
+
if (!key) return null;
|
|
1217
|
+
const hostRoot = container[key];
|
|
1218
|
+
const root = hostRoot == null ? void 0 : hostRoot.stateNode;
|
|
1219
|
+
return root && typeof root === "object" ? root : null;
|
|
1220
|
+
} catch (e) {
|
|
1221
|
+
return null;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
function patchRoot(root) {
|
|
1225
|
+
if (root[PATCHED]) return true;
|
|
1226
|
+
const original = root.onRecoverableError;
|
|
1227
|
+
if (typeof original !== "function") return false;
|
|
1228
|
+
root.onRecoverableError = function glitchgrabOnRecoverableError(error, info) {
|
|
1229
|
+
var _a;
|
|
1230
|
+
try {
|
|
1231
|
+
if (reporter && isHydrationError(error) && !isBailout(error)) {
|
|
1232
|
+
const removed = takeRemovedServerHtml();
|
|
1233
|
+
markHandled(error);
|
|
1234
|
+
reporter(error, (_a = info == null ? void 0 : info.componentStack) != null ? _a : "", hydrationMetadata(error, { removed }));
|
|
1235
|
+
}
|
|
1236
|
+
} catch (e) {
|
|
1237
|
+
}
|
|
1238
|
+
return original.call(this, error, info);
|
|
1239
|
+
};
|
|
1240
|
+
root[PATCHED] = true;
|
|
1241
|
+
return true;
|
|
1242
|
+
}
|
|
1243
|
+
function patchKnownRoots() {
|
|
1244
|
+
if (typeof document === "undefined") return false;
|
|
1245
|
+
let patched = false;
|
|
1246
|
+
for (const container of [document, document.getElementById("__next"), document.getElementById("root")]) {
|
|
1247
|
+
const root = findFiberRoot(container);
|
|
1248
|
+
if (root && patchRoot(root)) patched = true;
|
|
1249
|
+
}
|
|
1250
|
+
return patched;
|
|
1251
|
+
}
|
|
1252
|
+
function installHydrationCapture(report) {
|
|
1253
|
+
try {
|
|
1254
|
+
if (typeof window === "undefined") return;
|
|
1255
|
+
reporter = report;
|
|
1256
|
+
startObserver();
|
|
1257
|
+
patchKnownRoots();
|
|
1258
|
+
} catch (e) {
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
959
1262
|
// src/capture.ts
|
|
960
1263
|
var config = null;
|
|
961
1264
|
function registerCaptureConfig(next) {
|
|
@@ -975,7 +1278,7 @@ function sessionMetadata(session) {
|
|
|
975
1278
|
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {}
|
|
976
1279
|
};
|
|
977
1280
|
}
|
|
978
|
-
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError") {
|
|
1281
|
+
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError", dedupKey) {
|
|
979
1282
|
var _a, _b, _c;
|
|
980
1283
|
const err = error instanceof Error ? error : void 0;
|
|
981
1284
|
const errorMessage = err ? err.message : String(error);
|
|
@@ -987,7 +1290,7 @@ function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureErr
|
|
|
987
1290
|
const sig = computeSignature({
|
|
988
1291
|
errorMessage,
|
|
989
1292
|
pageUrl: context.url,
|
|
990
|
-
errorStack: err == null ? void 0 : err.stack,
|
|
1293
|
+
errorStack: dedupKey ? `at ${dedupKey}` : err == null ? void 0 : err.stack,
|
|
991
1294
|
digest
|
|
992
1295
|
});
|
|
993
1296
|
if (shouldSkipDuplicate(sig)) return null;
|
|
@@ -1027,6 +1330,25 @@ function captureError(error, options) {
|
|
|
1027
1330
|
} catch (e) {
|
|
1028
1331
|
}
|
|
1029
1332
|
}
|
|
1333
|
+
function reportHydrationError(error, componentStack, metadata) {
|
|
1334
|
+
try {
|
|
1335
|
+
const cfg = config;
|
|
1336
|
+
if (!(cfg == null ? void 0 : cfg.token)) return;
|
|
1337
|
+
const payload = buildCapturedErrorPayload(
|
|
1338
|
+
error,
|
|
1339
|
+
{ componentStack: componentStack || void 0, metadata },
|
|
1340
|
+
cfg,
|
|
1341
|
+
"onRecoverableError",
|
|
1342
|
+
componentStackKey(componentStack) || void 0
|
|
1343
|
+
);
|
|
1344
|
+
if (!payload) return;
|
|
1345
|
+
void sendReport(payload, cfg.baseUrl).then((result) => {
|
|
1346
|
+
if (result && cfg.onReportSent) cfg.onReportSent(result);
|
|
1347
|
+
});
|
|
1348
|
+
if (cfg.onError && error instanceof Error) cfg.onError(error);
|
|
1349
|
+
} catch (e) {
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1030
1352
|
|
|
1031
1353
|
// src/error-boundary.tsx
|
|
1032
1354
|
var GlitchgrabErrorBoundary = class extends React.Component {
|
|
@@ -1948,6 +2270,79 @@ function renderBlocks(lines, theme, key) {
|
|
|
1948
2270
|
function ChatMarkdown({ text, theme }) {
|
|
1949
2271
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: STACK, children: renderBlocks(text.replace(/\r\n?/g, "\n").split("\n"), theme, "md") });
|
|
1950
2272
|
}
|
|
2273
|
+
var MAX_SAVED_CHATS = 20;
|
|
2274
|
+
var SAVED_CHAT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
2275
|
+
var TITLE_CHARS = 80;
|
|
2276
|
+
var PREFIX = "glitchgrab:ai-chats:";
|
|
2277
|
+
function chatHistoryKey(...parts) {
|
|
2278
|
+
const input = parts.map((p) => p != null ? p : "").join("\0");
|
|
2279
|
+
let hash = 2166136261;
|
|
2280
|
+
for (let i = 0; i < input.length; i++) {
|
|
2281
|
+
hash ^= input.charCodeAt(i);
|
|
2282
|
+
hash = Math.imul(hash, 16777619);
|
|
2283
|
+
}
|
|
2284
|
+
return (hash >>> 0).toString(36);
|
|
2285
|
+
}
|
|
2286
|
+
function chatTitle(messages) {
|
|
2287
|
+
var _a, _b;
|
|
2288
|
+
const first = (_b = (_a = messages.find((m) => m.role === "user")) == null ? void 0 : _a.content.trim()) != null ? _b : "";
|
|
2289
|
+
const line = first.replace(/\s+/g, " ");
|
|
2290
|
+
return line.length > TITLE_CHARS ? `${line.slice(0, TITLE_CHARS - 1)}\u2026` : line;
|
|
2291
|
+
}
|
|
2292
|
+
function storage() {
|
|
2293
|
+
try {
|
|
2294
|
+
return typeof window !== "undefined" && window.localStorage ? window.localStorage : null;
|
|
2295
|
+
} catch (e) {
|
|
2296
|
+
return null;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
function isSavedChat(value) {
|
|
2300
|
+
if (!value || typeof value !== "object") return false;
|
|
2301
|
+
const c = value;
|
|
2302
|
+
return typeof c.id === "string" && typeof c.title === "string" && typeof c.updatedAt === "number" && (c.status === "open" || c.status === "filed") && Array.isArray(c.messages);
|
|
2303
|
+
}
|
|
2304
|
+
function loadChats(key, now = Date.now()) {
|
|
2305
|
+
const store = storage();
|
|
2306
|
+
if (!store) return [];
|
|
2307
|
+
try {
|
|
2308
|
+
const raw = store.getItem(PREFIX + key);
|
|
2309
|
+
if (!raw) return [];
|
|
2310
|
+
const parsed = JSON.parse(raw);
|
|
2311
|
+
if (!Array.isArray(parsed)) return [];
|
|
2312
|
+
return parsed.filter(isSavedChat).filter((c) => now - c.updatedAt < SAVED_CHAT_MAX_AGE_MS).sort((a, b) => b.updatedAt - a.updatedAt).slice(0, MAX_SAVED_CHATS);
|
|
2313
|
+
} catch (e) {
|
|
2314
|
+
return [];
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
function write(key, chats) {
|
|
2318
|
+
const store = storage();
|
|
2319
|
+
if (!store) return;
|
|
2320
|
+
try {
|
|
2321
|
+
if (chats.length === 0) store.removeItem(PREFIX + key);
|
|
2322
|
+
else store.setItem(PREFIX + key, JSON.stringify(chats));
|
|
2323
|
+
} catch (e) {
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
function saveChat(key, chat, now = Date.now()) {
|
|
2327
|
+
const rest = loadChats(key, now).filter((c) => c.id !== chat.id);
|
|
2328
|
+
const next = [chat, ...rest].slice(0, MAX_SAVED_CHATS);
|
|
2329
|
+
write(key, next);
|
|
2330
|
+
return next;
|
|
2331
|
+
}
|
|
2332
|
+
function markChatFiled(key, conversationId, label, now = Date.now()) {
|
|
2333
|
+
const chats = loadChats(key, now);
|
|
2334
|
+
const hit = chats.find((c) => c.conversationId === conversationId);
|
|
2335
|
+
if (!hit || hit.status === "filed") return;
|
|
2336
|
+
write(
|
|
2337
|
+
key,
|
|
2338
|
+
chats.map((c) => c === hit ? { ...c, status: "filed", filedLabel: label, updatedAt: now } : c)
|
|
2339
|
+
);
|
|
2340
|
+
}
|
|
2341
|
+
function removeChat(key, id, now = Date.now()) {
|
|
2342
|
+
const next = loadChats(key, now).filter((c) => c.id !== id);
|
|
2343
|
+
write(key, next);
|
|
2344
|
+
return next;
|
|
2345
|
+
}
|
|
1951
2346
|
function pickAssistImages(all) {
|
|
1952
2347
|
const picked = [];
|
|
1953
2348
|
let total = 0;
|
|
@@ -1974,6 +2369,18 @@ function pickAssistFiles(files) {
|
|
|
1974
2369
|
}
|
|
1975
2370
|
return picked;
|
|
1976
2371
|
}
|
|
2372
|
+
function newChatId() {
|
|
2373
|
+
return `local-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
|
2374
|
+
}
|
|
2375
|
+
function chatAge(at2, now = Date.now()) {
|
|
2376
|
+
const min = Math.round((now - at2) / 6e4);
|
|
2377
|
+
if (min < 1) return "just now";
|
|
2378
|
+
if (min < 60) return `${min} min ago`;
|
|
2379
|
+
const hours = Math.round(min / 60);
|
|
2380
|
+
if (hours < 24) return `${hours} h ago`;
|
|
2381
|
+
if (hours < 48) return "yesterday";
|
|
2382
|
+
return new Date(at2).toLocaleDateString(void 0, { day: "numeric", month: "short" });
|
|
2383
|
+
}
|
|
1977
2384
|
var STARTERS = [
|
|
1978
2385
|
"Something on this page is broken",
|
|
1979
2386
|
"It did the wrong thing",
|
|
@@ -2056,6 +2463,33 @@ function Avatar({
|
|
|
2056
2463
|
}
|
|
2057
2464
|
);
|
|
2058
2465
|
}
|
|
2466
|
+
var THINKING_SLOW_SECONDS = 20;
|
|
2467
|
+
function ThinkingClock({ color }) {
|
|
2468
|
+
const [seconds, setSeconds] = (0, import_react3.useState)(0);
|
|
2469
|
+
(0, import_react3.useEffect)(() => {
|
|
2470
|
+
const started = Date.now();
|
|
2471
|
+
const id = setInterval(() => setSeconds(Math.floor((Date.now() - started) / 1e3)), 1e3);
|
|
2472
|
+
return () => clearInterval(id);
|
|
2473
|
+
}, []);
|
|
2474
|
+
return (
|
|
2475
|
+
// Hidden from screen readers: the bubble already says "Thinking", and a
|
|
2476
|
+
// number changing every second would be read out every second.
|
|
2477
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2478
|
+
"span",
|
|
2479
|
+
{
|
|
2480
|
+
"data-gg-thinking-clock": "",
|
|
2481
|
+
"aria-hidden": "true",
|
|
2482
|
+
style: { marginLeft: "6px", fontSize: "12px", color, fontVariantNumeric: "tabular-nums" },
|
|
2483
|
+
children: [
|
|
2484
|
+
"Thinking\u2026 ",
|
|
2485
|
+
seconds,
|
|
2486
|
+
"s",
|
|
2487
|
+
seconds >= THINKING_SLOW_SECONDS ? " \xB7 taking longer than usual, still working" : ""
|
|
2488
|
+
]
|
|
2489
|
+
}
|
|
2490
|
+
)
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2059
2493
|
function AssistSheet({
|
|
2060
2494
|
assist,
|
|
2061
2495
|
theme: t,
|
|
@@ -2096,14 +2530,22 @@ function AssistSheet({
|
|
|
2096
2530
|
onDegrade,
|
|
2097
2531
|
onClose,
|
|
2098
2532
|
onFinish,
|
|
2099
|
-
onReportGlitchgrabProblem
|
|
2533
|
+
onReportGlitchgrabProblem,
|
|
2534
|
+
historyKey = null
|
|
2100
2535
|
}) {
|
|
2536
|
+
var _a;
|
|
2101
2537
|
const narrow = useIsNarrow();
|
|
2102
2538
|
const severityAsked = showSeverity && currentTile === "BUG";
|
|
2103
2539
|
const [messages, setMessages] = (0, import_react3.useState)([]);
|
|
2104
2540
|
const [input, setInput] = (0, import_react3.useState)("");
|
|
2105
2541
|
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
2106
2542
|
const [conversationId, setConversationId] = (0, import_react3.useState)(null);
|
|
2543
|
+
const chatIdRef = (0, import_react3.useRef)(newChatId());
|
|
2544
|
+
const [savedChats, setSavedChats] = (0, import_react3.useState)(
|
|
2545
|
+
() => historyKey ? loadChats(historyKey) : []
|
|
2546
|
+
);
|
|
2547
|
+
const [showChats, setShowChats] = (0, import_react3.useState)(false);
|
|
2548
|
+
const [viewingChat, setViewingChat] = (0, import_react3.useState)(null);
|
|
2107
2549
|
const [hoveredStar, setHoveredStar] = (0, import_react3.useState)(0);
|
|
2108
2550
|
const [options, setOptions] = (0, import_react3.useState)([]);
|
|
2109
2551
|
const [duplicate, setDuplicate] = (0, import_react3.useState)(null);
|
|
@@ -2155,8 +2597,8 @@ function AssistSheet({
|
|
|
2155
2597
|
if (el) el.scrollTop = el.scrollHeight;
|
|
2156
2598
|
}, [messages, busy, phase]);
|
|
2157
2599
|
(0, import_react3.useEffect)(() => {
|
|
2158
|
-
var
|
|
2159
|
-
if (phase === "draft") (
|
|
2600
|
+
var _a2;
|
|
2601
|
+
if (phase === "draft") (_a2 = draftRef.current) == null ? void 0 : _a2.focus();
|
|
2160
2602
|
}, [phase]);
|
|
2161
2603
|
(0, import_react3.useEffect)(() => {
|
|
2162
2604
|
const el = composerRef.current;
|
|
@@ -2188,7 +2630,8 @@ function AssistSheet({
|
|
|
2188
2630
|
onDegrade(message, retryable);
|
|
2189
2631
|
}
|
|
2190
2632
|
async function runTurn(history2, autoFile = false) {
|
|
2191
|
-
var
|
|
2633
|
+
var _a2, _b, _c;
|
|
2634
|
+
const turnChat = chatIdRef.current;
|
|
2192
2635
|
setBusy(true);
|
|
2193
2636
|
setAutoFileLeft(null);
|
|
2194
2637
|
let result;
|
|
@@ -2225,6 +2668,7 @@ function AssistSheet({
|
|
|
2225
2668
|
} finally {
|
|
2226
2669
|
setBusy(false);
|
|
2227
2670
|
}
|
|
2671
|
+
if (chatIdRef.current !== turnChat) return;
|
|
2228
2672
|
if (result.degraded) {
|
|
2229
2673
|
degradeKeepingEvents(events, result.degraded, result.retryable === true);
|
|
2230
2674
|
return;
|
|
@@ -2235,7 +2679,7 @@ function AssistSheet({
|
|
|
2235
2679
|
}
|
|
2236
2680
|
const attach = result.duplicate ? { ...result.duplicate, kind: "duplicate" } : result.related ? { ...result.related, kind: "related" } : null;
|
|
2237
2681
|
setDuplicate(attach);
|
|
2238
|
-
onDuplicateChange == null ? void 0 : onDuplicateChange((
|
|
2682
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange((_a2 = attach == null ? void 0 : attach.number) != null ? _a2 : null, attach == null ? void 0 : attach.kind);
|
|
2239
2683
|
setGlitchgrabOffer(!!result.aboutGlitchgrab && !!onReportGlitchgrabProblem && !!result.question);
|
|
2240
2684
|
if (result.solved) {
|
|
2241
2685
|
setSolved(result.solved);
|
|
@@ -2289,9 +2733,9 @@ function AssistSheet({
|
|
|
2289
2733
|
}
|
|
2290
2734
|
}
|
|
2291
2735
|
function sendTyped(text) {
|
|
2292
|
-
var
|
|
2736
|
+
var _a2;
|
|
2293
2737
|
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
|
2294
|
-
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((
|
|
2738
|
+
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((_a2 = lastAssistant == null ? void 0 : lastAssistant.content) != null ? _a2 : "");
|
|
2295
2739
|
send(text, checkingBack && isAffirmativeReply(text));
|
|
2296
2740
|
}
|
|
2297
2741
|
function send(text, autoFile = false) {
|
|
@@ -2333,7 +2777,215 @@ function AssistSheet({
|
|
|
2333
2777
|
flushEvents();
|
|
2334
2778
|
onSend();
|
|
2335
2779
|
}
|
|
2780
|
+
(0, import_react3.useEffect)(() => {
|
|
2781
|
+
if (!historyKey || !messages.some((m) => m.role === "user")) return;
|
|
2782
|
+
const done = submitted || phase === "solved";
|
|
2783
|
+
const kept = submitted || phase === "draft" ? withCurrentDraft(messages) : messages;
|
|
2784
|
+
setSavedChats(
|
|
2785
|
+
saveChat(historyKey, {
|
|
2786
|
+
id: chatIdRef.current,
|
|
2787
|
+
conversationId,
|
|
2788
|
+
title: chatTitle(kept),
|
|
2789
|
+
tile: currentTile,
|
|
2790
|
+
messages: kept,
|
|
2791
|
+
...issueTitle ? { issueTitle } : {},
|
|
2792
|
+
status: done ? "filed" : "open",
|
|
2793
|
+
...done ? {
|
|
2794
|
+
filedLabel: submitted ? submittedText != null ? submittedText : `${reportTypeLabel} sent` : "Answered \u2014 nothing was filed"
|
|
2795
|
+
} : {},
|
|
2796
|
+
updatedAt: Date.now()
|
|
2797
|
+
})
|
|
2798
|
+
);
|
|
2799
|
+
}, [
|
|
2800
|
+
historyKey,
|
|
2801
|
+
messages,
|
|
2802
|
+
conversationId,
|
|
2803
|
+
submitted,
|
|
2804
|
+
phase === "solved",
|
|
2805
|
+
issueTitle,
|
|
2806
|
+
phase === "draft" ? description : null
|
|
2807
|
+
]);
|
|
2808
|
+
function resumeChat(chat) {
|
|
2809
|
+
var _a2;
|
|
2810
|
+
flushEvents();
|
|
2811
|
+
chatIdRef.current = chat.id;
|
|
2812
|
+
setMessages(chat.messages);
|
|
2813
|
+
setConversationId(chat.conversationId);
|
|
2814
|
+
onConversationChange == null ? void 0 : onConversationChange(chat.conversationId);
|
|
2815
|
+
setOptions([]);
|
|
2816
|
+
setDuplicate(null);
|
|
2817
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2818
|
+
setGlitchgrabOffer(false);
|
|
2819
|
+
setAutoFileLeft(null);
|
|
2820
|
+
setInput("");
|
|
2821
|
+
if (chat.tile !== currentTile && tiles.includes(chat.tile)) {
|
|
2822
|
+
onPickType(chat.tile);
|
|
2823
|
+
}
|
|
2824
|
+
const last = chat.messages[chat.messages.length - 1];
|
|
2825
|
+
if ((last == null ? void 0 : last.kind) === "report") {
|
|
2826
|
+
onDescriptionChange(last.content);
|
|
2827
|
+
onIssueTitleChange((_a2 = chat.issueTitle) != null ? _a2 : "");
|
|
2828
|
+
aiDraftRef.current = last.content;
|
|
2829
|
+
setPhase("draft");
|
|
2830
|
+
} else {
|
|
2831
|
+
setPhase("chat");
|
|
2832
|
+
}
|
|
2833
|
+
setShowChats(false);
|
|
2834
|
+
setViewingChat(null);
|
|
2835
|
+
}
|
|
2836
|
+
function startNewChat() {
|
|
2837
|
+
flushEvents();
|
|
2838
|
+
chatIdRef.current = newChatId();
|
|
2839
|
+
setMessages([]);
|
|
2840
|
+
setConversationId(null);
|
|
2841
|
+
onConversationChange == null ? void 0 : onConversationChange(null);
|
|
2842
|
+
setOptions([]);
|
|
2843
|
+
setDuplicate(null);
|
|
2844
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2845
|
+
setGlitchgrabOffer(false);
|
|
2846
|
+
setAutoFileLeft(null);
|
|
2847
|
+
setInput("");
|
|
2848
|
+
onDescriptionChange("");
|
|
2849
|
+
onIssueTitleChange("");
|
|
2850
|
+
aiDraftRef.current = null;
|
|
2851
|
+
setPhase("chat");
|
|
2852
|
+
setShowChats(false);
|
|
2853
|
+
setViewingChat(null);
|
|
2854
|
+
}
|
|
2855
|
+
function forgetChat(id) {
|
|
2856
|
+
if (!historyKey) return;
|
|
2857
|
+
setSavedChats(removeChat(historyKey, id));
|
|
2858
|
+
if (viewingChat === id) setViewingChat(null);
|
|
2859
|
+
}
|
|
2860
|
+
const otherChats = savedChats.filter((c) => c.id !== chatIdRef.current);
|
|
2861
|
+
const resumable = (_a = otherChats.find((c) => c.status === "open" && c.messages.length > 0)) != null ? _a : null;
|
|
2336
2862
|
const empty = phase === "chat" && messages.length === 0 && !busy;
|
|
2863
|
+
function renderChatList() {
|
|
2864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { "data-gg-chat-list": "", style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
2865
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
2866
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: "Your chats" }),
|
|
2867
|
+
messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2868
|
+
"button",
|
|
2869
|
+
{
|
|
2870
|
+
type: "button",
|
|
2871
|
+
"data-gg-new-chat": "",
|
|
2872
|
+
onClick: startNewChat,
|
|
2873
|
+
style: {
|
|
2874
|
+
border: `1px solid ${t.inputBorder}`,
|
|
2875
|
+
borderRadius: "999px",
|
|
2876
|
+
background: "transparent",
|
|
2877
|
+
color: t.text,
|
|
2878
|
+
padding: "7px 12px",
|
|
2879
|
+
fontSize: "12px",
|
|
2880
|
+
fontFamily: "inherit",
|
|
2881
|
+
cursor: "pointer"
|
|
2882
|
+
},
|
|
2883
|
+
children: "+ New chat"
|
|
2884
|
+
}
|
|
2885
|
+
)
|
|
2886
|
+
] }),
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "11.5px", color: t.textMuted, lineHeight: 1.5 }, children: "Kept in this browser only, for 30 days." }),
|
|
2888
|
+
otherChats.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "12.5px", color: t.textMuted, padding: "12px 0" }, children: "No other chats yet." }),
|
|
2889
|
+
otherChats.map((chat) => {
|
|
2890
|
+
var _a2;
|
|
2891
|
+
const filed = chat.status === "filed";
|
|
2892
|
+
const open = viewingChat === chat.id;
|
|
2893
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2894
|
+
"div",
|
|
2895
|
+
{
|
|
2896
|
+
"data-gg-saved-chat": chat.status,
|
|
2897
|
+
style: {
|
|
2898
|
+
border: `1px solid ${t.border}`,
|
|
2899
|
+
borderRadius: "10px",
|
|
2900
|
+
padding: "10px 12px",
|
|
2901
|
+
display: "flex",
|
|
2902
|
+
flexDirection: "column",
|
|
2903
|
+
gap: "6px",
|
|
2904
|
+
minWidth: 0
|
|
2905
|
+
},
|
|
2906
|
+
children: [
|
|
2907
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-start", minWidth: 0 }, children: [
|
|
2908
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2909
|
+
"button",
|
|
2910
|
+
{
|
|
2911
|
+
type: "button",
|
|
2912
|
+
onClick: () => filed ? setViewingChat(open ? null : chat.id) : resumeChat(chat),
|
|
2913
|
+
style: {
|
|
2914
|
+
flex: 1,
|
|
2915
|
+
minWidth: 0,
|
|
2916
|
+
textAlign: "left",
|
|
2917
|
+
border: "none",
|
|
2918
|
+
background: "transparent",
|
|
2919
|
+
color: t.text,
|
|
2920
|
+
padding: 0,
|
|
2921
|
+
fontFamily: "inherit",
|
|
2922
|
+
cursor: "pointer",
|
|
2923
|
+
display: "flex",
|
|
2924
|
+
flexDirection: "column",
|
|
2925
|
+
gap: "4px"
|
|
2926
|
+
},
|
|
2927
|
+
children: [
|
|
2928
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "13px", lineHeight: 1.45, overflowWrap: "anywhere" }, children: chat.title || "Untitled chat" }),
|
|
2929
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
2930
|
+
filed ? (_a2 = chat.filedLabel) != null ? _a2 : "Sent" : "Not sent yet \u2014 tap to continue",
|
|
2931
|
+
" \xB7",
|
|
2932
|
+
" ",
|
|
2933
|
+
chatAge(chat.updatedAt)
|
|
2934
|
+
] })
|
|
2935
|
+
]
|
|
2936
|
+
}
|
|
2937
|
+
),
|
|
2938
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2939
|
+
"button",
|
|
2940
|
+
{
|
|
2941
|
+
type: "button",
|
|
2942
|
+
"aria-label": `Delete chat: ${chat.title}`,
|
|
2943
|
+
onClick: () => forgetChat(chat.id),
|
|
2944
|
+
style: {
|
|
2945
|
+
flexShrink: 0,
|
|
2946
|
+
border: "none",
|
|
2947
|
+
background: "transparent",
|
|
2948
|
+
color: t.textMuted,
|
|
2949
|
+
fontSize: "16px",
|
|
2950
|
+
lineHeight: 1,
|
|
2951
|
+
padding: "4px 6px",
|
|
2952
|
+
cursor: "pointer",
|
|
2953
|
+
fontFamily: "inherit"
|
|
2954
|
+
},
|
|
2955
|
+
children: "\xD7"
|
|
2956
|
+
}
|
|
2957
|
+
)
|
|
2958
|
+
] }),
|
|
2959
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2960
|
+
"div",
|
|
2961
|
+
{
|
|
2962
|
+
"data-gg-saved-transcript": "",
|
|
2963
|
+
style: {
|
|
2964
|
+
display: "flex",
|
|
2965
|
+
flexDirection: "column",
|
|
2966
|
+
gap: "6px",
|
|
2967
|
+
borderTop: `1px solid ${t.border}`,
|
|
2968
|
+
paddingTop: "8px",
|
|
2969
|
+
fontSize: "12.5px",
|
|
2970
|
+
lineHeight: 1.5
|
|
2971
|
+
},
|
|
2972
|
+
children: chat.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { minWidth: 0, overflowWrap: "anywhere" }, children: [
|
|
2973
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { color: t.textMuted, fontWeight: 600 }, children: [
|
|
2974
|
+
m.role === "user" ? "You" : m.kind === "report" ? "Report" : "Assistant",
|
|
2975
|
+
":",
|
|
2976
|
+
" "
|
|
2977
|
+
] }),
|
|
2978
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { whiteSpace: "pre-wrap" }, children: m.content })
|
|
2979
|
+
] }, i))
|
|
2980
|
+
}
|
|
2981
|
+
)
|
|
2982
|
+
]
|
|
2983
|
+
},
|
|
2984
|
+
chat.id
|
|
2985
|
+
);
|
|
2986
|
+
})
|
|
2987
|
+
] });
|
|
2988
|
+
}
|
|
2337
2989
|
function renderKnownIssue({ title, footer }) {
|
|
2338
2990
|
if (!duplicate) return null;
|
|
2339
2991
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
@@ -2367,8 +3019,8 @@ function AssistSheet({
|
|
|
2367
3019
|
);
|
|
2368
3020
|
}
|
|
2369
3021
|
const initials2 = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
|
|
2370
|
-
var
|
|
2371
|
-
return (_b = (
|
|
3022
|
+
var _a2, _b;
|
|
3023
|
+
return (_b = (_a2 = w[0]) == null ? void 0 : _a2.toUpperCase()) != null ? _b : "";
|
|
2372
3024
|
}).join("");
|
|
2373
3025
|
const panelStyle = narrow ? {
|
|
2374
3026
|
width: "100%",
|
|
@@ -2459,7 +3111,9 @@ function AssistSheet({
|
|
|
2459
3111
|
alignItems: "center",
|
|
2460
3112
|
gap: "7px",
|
|
2461
3113
|
fontSize: "14px",
|
|
2462
|
-
fontWeight: 600
|
|
3114
|
+
fontWeight: 600,
|
|
3115
|
+
// One line even with the Chats pill beside it (#567).
|
|
3116
|
+
whiteSpace: "nowrap"
|
|
2463
3117
|
},
|
|
2464
3118
|
children: [
|
|
2465
3119
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Sparkle, { color: t.accent }),
|
|
@@ -2489,801 +3143,914 @@ function AssistSheet({
|
|
|
2489
3143
|
projectSlot ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
|
|
2490
3144
|
] })
|
|
2491
3145
|
] }),
|
|
2492
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
3146
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "6px", flexShrink: 0 }, children: [
|
|
3147
|
+
historyKey && (showChats || otherChats.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3148
|
+
"button",
|
|
3149
|
+
{
|
|
3150
|
+
type: "button",
|
|
3151
|
+
"data-gg-chats-toggle": "",
|
|
3152
|
+
disabled: busy,
|
|
3153
|
+
"aria-pressed": showChats,
|
|
3154
|
+
onClick: () => {
|
|
3155
|
+
setShowChats((v) => !v);
|
|
3156
|
+
setViewingChat(null);
|
|
3157
|
+
},
|
|
3158
|
+
style: {
|
|
3159
|
+
flexShrink: 0,
|
|
3160
|
+
border: `1px solid ${showChats ? t.accent : t.inputBorder}`,
|
|
3161
|
+
borderRadius: "999px",
|
|
3162
|
+
background: "transparent",
|
|
3163
|
+
color: showChats ? t.accent : t.textMuted,
|
|
3164
|
+
cursor: busy ? "default" : "pointer",
|
|
3165
|
+
opacity: busy ? 0.5 : 1,
|
|
3166
|
+
fontSize: "11.5px",
|
|
3167
|
+
lineHeight: 1,
|
|
3168
|
+
fontFamily: "inherit",
|
|
3169
|
+
whiteSpace: "nowrap",
|
|
3170
|
+
padding: "9px 11px"
|
|
3171
|
+
},
|
|
3172
|
+
children: showChats ? "\u2190 Chat" : `Chats \xB7 ${otherChats.length}`
|
|
3173
|
+
}
|
|
3174
|
+
),
|
|
3175
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3176
|
+
"button",
|
|
3177
|
+
{
|
|
3178
|
+
type: "button",
|
|
3179
|
+
"data-gg-write-myself": "",
|
|
3180
|
+
onClick: () => leave("write_myself", `header, ${phase}`),
|
|
3181
|
+
"aria-label": "Write it myself instead",
|
|
3182
|
+
style: {
|
|
3183
|
+
flexShrink: 0,
|
|
3184
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3185
|
+
borderRadius: "999px",
|
|
3186
|
+
background: "transparent",
|
|
3187
|
+
color: t.textMuted,
|
|
3188
|
+
cursor: "pointer",
|
|
3189
|
+
fontSize: "11.5px",
|
|
3190
|
+
lineHeight: 1,
|
|
3191
|
+
fontFamily: "inherit",
|
|
3192
|
+
whiteSpace: "nowrap",
|
|
3193
|
+
// ~32px tall either way — this is the escape hatch, not a hint.
|
|
3194
|
+
padding: "9px 11px"
|
|
3195
|
+
},
|
|
3196
|
+
children: "Write it myself"
|
|
3197
|
+
}
|
|
3198
|
+
)
|
|
3199
|
+
] })
|
|
3200
|
+
]
|
|
3201
|
+
}
|
|
3202
|
+
),
|
|
3203
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3204
|
+
"div",
|
|
3205
|
+
{
|
|
3206
|
+
ref: scrollRef,
|
|
3207
|
+
style: {
|
|
3208
|
+
flex: 1,
|
|
3209
|
+
minHeight: narrow ? "180px" : 0,
|
|
3210
|
+
overflowY: "auto",
|
|
3211
|
+
padding: "16px",
|
|
2528
3212
|
display: "flex",
|
|
2529
3213
|
flexDirection: "column"
|
|
2530
3214
|
},
|
|
2531
|
-
children:
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3215
|
+
children: [
|
|
3216
|
+
showChats && renderChatList(),
|
|
3217
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3218
|
+
"div",
|
|
3219
|
+
{
|
|
3220
|
+
style: {
|
|
3221
|
+
marginTop: "auto",
|
|
3222
|
+
display: "flex",
|
|
3223
|
+
flexDirection: "column",
|
|
3224
|
+
gap: "12px",
|
|
3225
|
+
minWidth: 0
|
|
3226
|
+
},
|
|
3227
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: showChats ? "none" : "contents" }, children: [
|
|
3228
|
+
phase === "type" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3229
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3230
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3231
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3232
|
+
"div",
|
|
3233
|
+
{
|
|
3234
|
+
style: {
|
|
3235
|
+
padding: "9px 12px",
|
|
3236
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3237
|
+
backgroundColor: t.bgSecondary,
|
|
3238
|
+
fontSize: "13px",
|
|
3239
|
+
lineHeight: 1.55,
|
|
3240
|
+
maxWidth: "88%"
|
|
3241
|
+
},
|
|
3242
|
+
children: [
|
|
3243
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 w` : "W",
|
|
3244
|
+
"hat do you want to do? Pick one and I'll take it from there."
|
|
3245
|
+
]
|
|
3246
|
+
}
|
|
3247
|
+
)
|
|
3248
|
+
] }),
|
|
3249
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2546
3250
|
"div",
|
|
2547
3251
|
{
|
|
2548
3252
|
style: {
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
lineHeight: 1.55,
|
|
2554
|
-
maxWidth: "88%"
|
|
3253
|
+
display: "flex",
|
|
3254
|
+
flexWrap: "wrap",
|
|
3255
|
+
gap: "6px",
|
|
3256
|
+
paddingLeft: "32px"
|
|
2555
3257
|
},
|
|
2556
|
-
children:
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
3258
|
+
children: tiles.map((tile) => {
|
|
3259
|
+
const rate = tile === "RATING";
|
|
3260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3261
|
+
"button",
|
|
3262
|
+
{
|
|
3263
|
+
type: "button",
|
|
3264
|
+
"data-gg-chip": "",
|
|
3265
|
+
"data-gg-tile": tile,
|
|
3266
|
+
onClick: () => pickType(tile),
|
|
3267
|
+
style: {
|
|
3268
|
+
display: "inline-flex",
|
|
3269
|
+
alignItems: "center",
|
|
3270
|
+
gap: "5px",
|
|
3271
|
+
// The rating is the only tile that isn't a report, so
|
|
3272
|
+
// it wears the star colour the dialog's hero row uses
|
|
3273
|
+
// rather than hiding among the report types.
|
|
3274
|
+
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
3275
|
+
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
3276
|
+
color: rate ? "#f59e0b" : t.textMuted,
|
|
3277
|
+
borderRadius: "999px",
|
|
3278
|
+
// 8px vertical keeps the tap target at ~32px.
|
|
3279
|
+
padding: "8px 12px",
|
|
3280
|
+
fontSize: "12px",
|
|
3281
|
+
fontWeight: rate ? 600 : 400,
|
|
3282
|
+
fontFamily: "inherit",
|
|
3283
|
+
cursor: "pointer"
|
|
3284
|
+
},
|
|
3285
|
+
children: rate ? "\u2605 Rate us" : getTypeLabel(tile)
|
|
3286
|
+
},
|
|
3287
|
+
tile
|
|
3288
|
+
);
|
|
3289
|
+
})
|
|
2560
3290
|
}
|
|
2561
3291
|
)
|
|
2562
3292
|
] }),
|
|
2563
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
2564
|
-
"div",
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
3293
|
+
phase === "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3294
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3295
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3296
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3297
|
+
"div",
|
|
3298
|
+
{
|
|
3299
|
+
style: {
|
|
3300
|
+
padding: "9px 12px",
|
|
3301
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3302
|
+
backgroundColor: t.bgSecondary,
|
|
3303
|
+
fontSize: "13px",
|
|
3304
|
+
lineHeight: 1.55,
|
|
3305
|
+
maxWidth: "88%"
|
|
3306
|
+
},
|
|
3307
|
+
children: "How bad is it?"
|
|
3308
|
+
}
|
|
3309
|
+
)
|
|
3310
|
+
] }),
|
|
3311
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3312
|
+
"div",
|
|
3313
|
+
{
|
|
3314
|
+
role: "radiogroup",
|
|
3315
|
+
"aria-label": "Severity",
|
|
3316
|
+
style: {
|
|
3317
|
+
display: "flex",
|
|
3318
|
+
flexWrap: "wrap",
|
|
3319
|
+
gap: "6px",
|
|
3320
|
+
paddingLeft: "32px"
|
|
3321
|
+
},
|
|
3322
|
+
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2575
3323
|
"button",
|
|
2576
3324
|
{
|
|
2577
3325
|
type: "button",
|
|
3326
|
+
role: "radio",
|
|
3327
|
+
"aria-checked": severity === s,
|
|
2578
3328
|
"data-gg-chip": "",
|
|
2579
|
-
"data-gg-
|
|
2580
|
-
onClick: () =>
|
|
3329
|
+
"data-gg-severity": s,
|
|
3330
|
+
onClick: () => answerSeverity(s),
|
|
2581
3331
|
style: {
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
// The rating is the only tile that isn't a report, so
|
|
2586
|
-
// it wears the star colour the dialog's hero row uses
|
|
2587
|
-
// rather than hiding among the report types.
|
|
2588
|
-
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
2589
|
-
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
2590
|
-
color: rate ? "#f59e0b" : t.textMuted,
|
|
3332
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3333
|
+
background: "transparent",
|
|
3334
|
+
color: t.textMuted,
|
|
2591
3335
|
borderRadius: "999px",
|
|
2592
|
-
//
|
|
3336
|
+
// Same as the picker and option chips — one chip size.
|
|
2593
3337
|
padding: "8px 12px",
|
|
2594
3338
|
fontSize: "12px",
|
|
2595
|
-
fontWeight: rate ? 600 : 400,
|
|
2596
3339
|
fontFamily: "inherit",
|
|
2597
3340
|
cursor: "pointer"
|
|
2598
3341
|
},
|
|
2599
|
-
children:
|
|
3342
|
+
children: SEVERITY_LABELS[s]
|
|
2600
3343
|
},
|
|
2601
|
-
|
|
2602
|
-
)
|
|
2603
|
-
})
|
|
2604
|
-
}
|
|
2605
|
-
)
|
|
2606
|
-
] }),
|
|
2607
|
-
phase === "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2608
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2609
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2610
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2611
|
-
"div",
|
|
2612
|
-
{
|
|
2613
|
-
style: {
|
|
2614
|
-
padding: "9px 12px",
|
|
2615
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2616
|
-
backgroundColor: t.bgSecondary,
|
|
2617
|
-
fontSize: "13px",
|
|
2618
|
-
lineHeight: 1.55,
|
|
2619
|
-
maxWidth: "88%"
|
|
2620
|
-
},
|
|
2621
|
-
children: "How bad is it?"
|
|
3344
|
+
s
|
|
3345
|
+
))
|
|
2622
3346
|
}
|
|
2623
3347
|
)
|
|
2624
3348
|
] }),
|
|
2625
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
2626
|
-
"div",
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
style: {
|
|
2631
|
-
display: "flex",
|
|
2632
|
-
flexWrap: "wrap",
|
|
2633
|
-
gap: "6px",
|
|
2634
|
-
paddingLeft: "32px"
|
|
2635
|
-
},
|
|
2636
|
-
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2637
|
-
"button",
|
|
3349
|
+
phase === "rating" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3350
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3351
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3352
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3353
|
+
"div",
|
|
2638
3354
|
{
|
|
2639
|
-
type: "button",
|
|
2640
|
-
role: "radio",
|
|
2641
|
-
"aria-checked": severity === s,
|
|
2642
|
-
"data-gg-chip": "",
|
|
2643
|
-
"data-gg-severity": s,
|
|
2644
|
-
onClick: () => answerSeverity(s),
|
|
2645
3355
|
style: {
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
fontSize: "12px",
|
|
2653
|
-
fontFamily: "inherit",
|
|
2654
|
-
cursor: "pointer"
|
|
3356
|
+
padding: "9px 12px",
|
|
3357
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3358
|
+
backgroundColor: t.bgSecondary,
|
|
3359
|
+
fontSize: "13px",
|
|
3360
|
+
lineHeight: 1.55,
|
|
3361
|
+
maxWidth: "88%"
|
|
2655
3362
|
},
|
|
2656
|
-
children:
|
|
2657
|
-
}
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
)
|
|
2662
|
-
] }),
|
|
2663
|
-
phase === "rating" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2664
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2665
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2666
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3363
|
+
children: "How are we doing? Tap a star \u2014 the words are optional."
|
|
3364
|
+
}
|
|
3365
|
+
)
|
|
3366
|
+
] }),
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2667
3368
|
"div",
|
|
2668
3369
|
{
|
|
2669
3370
|
style: {
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
3371
|
+
display: "flex",
|
|
3372
|
+
flexDirection: "column",
|
|
3373
|
+
gap: "10px",
|
|
3374
|
+
marginLeft: "32px",
|
|
3375
|
+
padding: "12px",
|
|
3376
|
+
borderRadius: "12px",
|
|
3377
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
3378
|
+
backgroundColor: "rgba(245,158,11,0.06)"
|
|
2676
3379
|
},
|
|
2677
|
-
children:
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
3380
|
+
children: [
|
|
3381
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: "4px" }, role: "group", "aria-label": "Rating", children: [1, 2, 3, 4, 5].map((star) => {
|
|
3382
|
+
const filled = star <= (hoveredStar || rating);
|
|
3383
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3384
|
+
"button",
|
|
3385
|
+
{
|
|
3386
|
+
type: "button",
|
|
3387
|
+
"aria-label": `${star} star${star > 1 ? "s" : ""}`,
|
|
3388
|
+
"aria-pressed": star <= rating,
|
|
3389
|
+
onClick: () => onRatingChange(star),
|
|
3390
|
+
onMouseEnter: () => setHoveredStar(star),
|
|
3391
|
+
onMouseLeave: () => setHoveredStar(0),
|
|
3392
|
+
style: {
|
|
3393
|
+
border: "none",
|
|
3394
|
+
background: "transparent",
|
|
3395
|
+
padding: 0,
|
|
3396
|
+
cursor: "pointer",
|
|
3397
|
+
lineHeight: 0
|
|
3398
|
+
},
|
|
3399
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3400
|
+
"path",
|
|
3401
|
+
{
|
|
3402
|
+
d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
|
|
3403
|
+
fill: filled ? "#f59e0b" : "transparent",
|
|
3404
|
+
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
3405
|
+
strokeWidth: "1.5",
|
|
3406
|
+
strokeLinejoin: "round"
|
|
3407
|
+
}
|
|
3408
|
+
) })
|
|
3409
|
+
},
|
|
3410
|
+
star
|
|
3411
|
+
);
|
|
3412
|
+
}) }),
|
|
3413
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3414
|
+
"textarea",
|
|
3415
|
+
{
|
|
3416
|
+
value: description,
|
|
3417
|
+
onChange: (e) => onDescriptionChange(e.target.value),
|
|
3418
|
+
rows: 3,
|
|
3419
|
+
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
3420
|
+
style: {
|
|
3421
|
+
width: "100%",
|
|
3422
|
+
padding: "10px",
|
|
3423
|
+
borderRadius: "8px",
|
|
3424
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3425
|
+
backgroundColor: t.inputBg,
|
|
3426
|
+
color: t.text,
|
|
3427
|
+
fontSize: "13px",
|
|
3428
|
+
lineHeight: 1.5,
|
|
3429
|
+
fontFamily: "inherit",
|
|
3430
|
+
resize: "vertical",
|
|
3431
|
+
outline: "none",
|
|
3432
|
+
boxSizing: "border-box"
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
),
|
|
3436
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2698
3437
|
"button",
|
|
2699
3438
|
{
|
|
2700
3439
|
type: "button",
|
|
2701
|
-
|
|
2702
|
-
"aria-pressed": star <= rating,
|
|
2703
|
-
onClick: () => onRatingChange(star),
|
|
2704
|
-
onMouseEnter: () => setHoveredStar(star),
|
|
2705
|
-
onMouseLeave: () => setHoveredStar(0),
|
|
3440
|
+
onClick: () => setPhase("type"),
|
|
2706
3441
|
style: {
|
|
3442
|
+
alignSelf: "flex-start",
|
|
2707
3443
|
border: "none",
|
|
2708
3444
|
background: "transparent",
|
|
2709
|
-
|
|
3445
|
+
color: t.textMuted,
|
|
3446
|
+
fontSize: "12px",
|
|
3447
|
+
fontFamily: "inherit",
|
|
3448
|
+
// A bare text link is ~14px tall — half a thumb.
|
|
3449
|
+
padding: "9px 0",
|
|
2710
3450
|
cursor: "pointer",
|
|
2711
|
-
|
|
3451
|
+
textDecoration: "underline"
|
|
2712
3452
|
},
|
|
2713
|
-
children:
|
|
2714
|
-
"path",
|
|
2715
|
-
{
|
|
2716
|
-
d: "M12 3l2.6 5.3 5.9.9-4.3 4.1 1 5.8L12 16.4 6.8 19.1l1-5.8L3.5 9.2l5.9-.9L12 3z",
|
|
2717
|
-
fill: filled ? "#f59e0b" : "transparent",
|
|
2718
|
-
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
2719
|
-
strokeWidth: "1.5",
|
|
2720
|
-
strokeLinejoin: "round"
|
|
2721
|
-
}
|
|
2722
|
-
) })
|
|
2723
|
-
},
|
|
2724
|
-
star
|
|
2725
|
-
);
|
|
2726
|
-
}) }),
|
|
2727
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2728
|
-
"textarea",
|
|
2729
|
-
{
|
|
2730
|
-
value: description,
|
|
2731
|
-
onChange: (e) => onDescriptionChange(e.target.value),
|
|
2732
|
-
rows: 3,
|
|
2733
|
-
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
2734
|
-
style: {
|
|
2735
|
-
width: "100%",
|
|
2736
|
-
padding: "10px",
|
|
2737
|
-
borderRadius: "8px",
|
|
2738
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2739
|
-
backgroundColor: t.inputBg,
|
|
2740
|
-
color: t.text,
|
|
2741
|
-
fontSize: "13px",
|
|
2742
|
-
lineHeight: 1.5,
|
|
2743
|
-
fontFamily: "inherit",
|
|
2744
|
-
resize: "vertical",
|
|
2745
|
-
outline: "none",
|
|
2746
|
-
boxSizing: "border-box"
|
|
3453
|
+
children: "Report something instead"
|
|
2747
3454
|
}
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
style: {
|
|
2756
|
-
alignSelf: "flex-start",
|
|
2757
|
-
border: "none",
|
|
2758
|
-
background: "transparent",
|
|
2759
|
-
color: t.textMuted,
|
|
2760
|
-
fontSize: "12px",
|
|
2761
|
-
fontFamily: "inherit",
|
|
2762
|
-
// A bare text link is ~14px tall — half a thumb.
|
|
2763
|
-
padding: "9px 0",
|
|
2764
|
-
cursor: "pointer",
|
|
2765
|
-
textDecoration: "underline"
|
|
2766
|
-
},
|
|
2767
|
-
children: "Report something instead"
|
|
2768
|
-
}
|
|
2769
|
-
)
|
|
2770
|
-
]
|
|
2771
|
-
}
|
|
2772
|
-
)
|
|
2773
|
-
] }),
|
|
2774
|
-
empty && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2775
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2776
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2777
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3455
|
+
)
|
|
3456
|
+
]
|
|
3457
|
+
}
|
|
3458
|
+
)
|
|
3459
|
+
] }),
|
|
3460
|
+
empty && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3461
|
+
resumable && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2778
3462
|
"div",
|
|
2779
3463
|
{
|
|
3464
|
+
"data-gg-resume-chat": "",
|
|
2780
3465
|
style: {
|
|
2781
|
-
|
|
2782
|
-
|
|
3466
|
+
display: "flex",
|
|
3467
|
+
flexDirection: "column",
|
|
3468
|
+
gap: "8px",
|
|
3469
|
+
padding: "10px 12px",
|
|
3470
|
+
borderRadius: "10px",
|
|
3471
|
+
border: `1px solid ${t.accent}55`,
|
|
2783
3472
|
backgroundColor: t.bgSecondary,
|
|
2784
|
-
|
|
2785
|
-
lineHeight: 1.55,
|
|
2786
|
-
maxWidth: "88%"
|
|
3473
|
+
minWidth: 0
|
|
2787
3474
|
},
|
|
2788
3475
|
children: [
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
"button",
|
|
2806
|
-
{
|
|
2807
|
-
type: "button",
|
|
2808
|
-
"data-gg-chip": "",
|
|
2809
|
-
onClick: () => {
|
|
2810
|
-
logEvent("starter_tap", s);
|
|
2811
|
-
send(s);
|
|
2812
|
-
},
|
|
2813
|
-
style: {
|
|
2814
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2815
|
-
background: "transparent",
|
|
2816
|
-
color: t.textMuted,
|
|
2817
|
-
borderRadius: "999px",
|
|
2818
|
-
padding: "6px 11px",
|
|
2819
|
-
fontSize: "12px",
|
|
2820
|
-
fontFamily: "inherit",
|
|
2821
|
-
cursor: "pointer"
|
|
2822
|
-
},
|
|
2823
|
-
children: s
|
|
2824
|
-
},
|
|
2825
|
-
s
|
|
2826
|
-
))
|
|
2827
|
-
}
|
|
2828
|
-
)
|
|
2829
|
-
] }),
|
|
2830
|
-
messages.map((m, i) => {
|
|
2831
|
-
const mine = m.role === "user";
|
|
2832
|
-
if (m.kind === "report") {
|
|
2833
|
-
const live = phase === "draft" && i === messages.length - 1;
|
|
2834
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
2835
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2836
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2837
|
-
"div",
|
|
2838
|
-
{
|
|
2839
|
-
"data-gg-draft-bubble": "",
|
|
2840
|
-
style: {
|
|
2841
|
-
maxWidth: "82%",
|
|
2842
|
-
minWidth: 0,
|
|
2843
|
-
padding: "9px 12px",
|
|
2844
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2845
|
-
fontSize: "13px",
|
|
2846
|
-
lineHeight: 1.55,
|
|
2847
|
-
backgroundColor: t.bgSecondary,
|
|
2848
|
-
color: t.text,
|
|
2849
|
-
border: live ? "none" : `1px solid ${t.accent}66`
|
|
2850
|
-
},
|
|
2851
|
-
children: live ? (
|
|
2852
|
-
// #402: "have a read" beside a countdown reads as a
|
|
2853
|
-
// contradiction. Say what is about to happen instead.
|
|
2854
|
-
autoFileLeft !== null ? "Here's your report \u2014 I'll file it unless you want to change something." : "Here's your report \u2014 have a read."
|
|
2855
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3476
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3477
|
+
"Pick up where you left off \xB7 ",
|
|
3478
|
+
chatAge(resumable.updatedAt)
|
|
3479
|
+
] }),
|
|
3480
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3481
|
+
"span",
|
|
3482
|
+
{
|
|
3483
|
+
style: {
|
|
3484
|
+
fontSize: "13px",
|
|
3485
|
+
lineHeight: 1.45,
|
|
3486
|
+
overflowWrap: "anywhere"
|
|
3487
|
+
},
|
|
3488
|
+
children: resumable.title
|
|
3489
|
+
}
|
|
3490
|
+
),
|
|
3491
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
2856
3492
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2857
|
-
"
|
|
3493
|
+
"button",
|
|
2858
3494
|
{
|
|
3495
|
+
type: "button",
|
|
3496
|
+
"data-gg-resume-continue": "",
|
|
3497
|
+
onClick: () => resumeChat(resumable),
|
|
2859
3498
|
style: {
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
3499
|
+
border: "none",
|
|
3500
|
+
borderRadius: "999px",
|
|
3501
|
+
backgroundColor: t.accent,
|
|
3502
|
+
color: t.accentText,
|
|
3503
|
+
padding: "7px 13px",
|
|
3504
|
+
fontSize: "12px",
|
|
3505
|
+
fontWeight: 600,
|
|
3506
|
+
fontFamily: "inherit",
|
|
3507
|
+
cursor: "pointer"
|
|
2867
3508
|
},
|
|
2868
|
-
children: "
|
|
3509
|
+
children: "Continue this chat"
|
|
2869
3510
|
}
|
|
2870
3511
|
),
|
|
2871
3512
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2872
|
-
"
|
|
3513
|
+
"button",
|
|
2873
3514
|
{
|
|
3515
|
+
type: "button",
|
|
3516
|
+
onClick: () => setShowChats(true),
|
|
2874
3517
|
style: {
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
3518
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3519
|
+
borderRadius: "999px",
|
|
3520
|
+
background: "transparent",
|
|
3521
|
+
color: t.textMuted,
|
|
3522
|
+
padding: "7px 13px",
|
|
3523
|
+
fontSize: "12px",
|
|
3524
|
+
fontFamily: "inherit",
|
|
3525
|
+
cursor: "pointer"
|
|
2881
3526
|
},
|
|
2882
|
-
children:
|
|
3527
|
+
children: "All chats"
|
|
2883
3528
|
}
|
|
2884
3529
|
)
|
|
2885
3530
|
] })
|
|
3531
|
+
]
|
|
3532
|
+
}
|
|
3533
|
+
),
|
|
3534
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3535
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3536
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3537
|
+
"div",
|
|
3538
|
+
{
|
|
3539
|
+
style: {
|
|
3540
|
+
padding: "9px 12px",
|
|
3541
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3542
|
+
backgroundColor: t.bgSecondary,
|
|
3543
|
+
fontSize: "13px",
|
|
3544
|
+
lineHeight: 1.55,
|
|
3545
|
+
maxWidth: "88%"
|
|
3546
|
+
},
|
|
3547
|
+
children: [
|
|
3548
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 t` : "T",
|
|
3549
|
+
"ell me what went wrong in your own words. I can already see your screenshot and what you clicked, so skip the boring parts."
|
|
3550
|
+
]
|
|
2886
3551
|
}
|
|
2887
3552
|
)
|
|
2888
|
-
] },
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
children: [
|
|
2900
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
2901
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2902
|
-
"div",
|
|
2903
|
-
{
|
|
2904
|
-
style: {
|
|
2905
|
-
maxWidth: "82%",
|
|
2906
|
-
minWidth: 0,
|
|
2907
|
-
padding: "9px 12px",
|
|
2908
|
-
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
2909
|
-
fontSize: "13px",
|
|
2910
|
-
lineHeight: 1.55,
|
|
2911
|
-
// Markdown owns the assistant's line breaks and lists.
|
|
2912
|
-
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
2913
|
-
wordBreak: "break-word",
|
|
2914
|
-
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
2915
|
-
color: mine ? t.accentText : t.text
|
|
2916
|
-
},
|
|
2917
|
-
children: mine ? m.content : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChatMarkdown, { text: m.content, theme: t })
|
|
2918
|
-
}
|
|
2919
|
-
)
|
|
2920
|
-
]
|
|
2921
|
-
},
|
|
2922
|
-
i
|
|
2923
|
-
);
|
|
2924
|
-
}),
|
|
2925
|
-
duplicate && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
2926
|
-
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2927
|
-
"div",
|
|
2928
|
-
{
|
|
2929
|
-
"data-gg-glitchgrab-offer": "",
|
|
2930
|
-
style: {
|
|
2931
|
-
display: "flex",
|
|
2932
|
-
flexDirection: "column",
|
|
2933
|
-
gap: "8px",
|
|
2934
|
-
padding: "10px",
|
|
2935
|
-
borderRadius: "8px",
|
|
2936
|
-
border: `1px solid ${t.accent}55`,
|
|
2937
|
-
backgroundColor: `${t.accent}14`,
|
|
2938
|
-
fontSize: "12px",
|
|
2939
|
-
lineHeight: 1.5
|
|
2940
|
-
},
|
|
2941
|
-
children: [
|
|
2942
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
2943
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
2944
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
2945
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3553
|
+
] }),
|
|
3554
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3555
|
+
"div",
|
|
3556
|
+
{
|
|
3557
|
+
style: {
|
|
3558
|
+
display: "flex",
|
|
3559
|
+
flexWrap: "wrap",
|
|
3560
|
+
gap: "6px",
|
|
3561
|
+
paddingLeft: "32px"
|
|
3562
|
+
},
|
|
3563
|
+
children: STARTERS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2946
3564
|
"button",
|
|
2947
3565
|
{
|
|
2948
3566
|
type: "button",
|
|
2949
|
-
"data-gg-
|
|
3567
|
+
"data-gg-chip": "",
|
|
2950
3568
|
onClick: () => {
|
|
2951
|
-
logEvent("
|
|
2952
|
-
|
|
2953
|
-
onReportGlitchgrabProblem(
|
|
2954
|
-
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
2955
|
-
);
|
|
3569
|
+
logEvent("starter_tap", s);
|
|
3570
|
+
send(s);
|
|
2956
3571
|
},
|
|
2957
3572
|
style: {
|
|
2958
|
-
|
|
3573
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3574
|
+
background: "transparent",
|
|
3575
|
+
color: t.textMuted,
|
|
2959
3576
|
borderRadius: "999px",
|
|
2960
|
-
|
|
2961
|
-
backgroundColor: t.accent,
|
|
2962
|
-
color: t.accentText,
|
|
3577
|
+
padding: "6px 11px",
|
|
2963
3578
|
fontSize: "12px",
|
|
2964
|
-
fontWeight: 700,
|
|
2965
3579
|
fontFamily: "inherit",
|
|
2966
|
-
cursor: "pointer"
|
|
2967
|
-
// Both stretch, so on a phone each wrapped line reads as
|
|
2968
|
-
// a choice rather than one button left stranded.
|
|
2969
|
-
flex: "1 1 auto"
|
|
3580
|
+
cursor: "pointer"
|
|
2970
3581
|
},
|
|
2971
|
-
children:
|
|
2972
|
-
}
|
|
2973
|
-
|
|
3582
|
+
children: s
|
|
3583
|
+
},
|
|
3584
|
+
s
|
|
3585
|
+
))
|
|
3586
|
+
}
|
|
3587
|
+
)
|
|
3588
|
+
] }),
|
|
3589
|
+
messages.map((m, i) => {
|
|
3590
|
+
const mine = m.role === "user";
|
|
3591
|
+
if (m.kind === "report") {
|
|
3592
|
+
const live = phase === "draft" && i === messages.length - 1;
|
|
3593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
3594
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2974
3595
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2975
|
-
"
|
|
3596
|
+
"div",
|
|
2976
3597
|
{
|
|
2977
|
-
|
|
2978
|
-
"data-gg-glitchgrab-offer-no": "",
|
|
2979
|
-
onClick: () => {
|
|
2980
|
-
logEvent("glitchgrab_offer_declined");
|
|
2981
|
-
send("No \u2014 it's about this app, not the reporting tool");
|
|
2982
|
-
},
|
|
3598
|
+
"data-gg-draft-bubble": "",
|
|
2983
3599
|
style: {
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
3600
|
+
maxWidth: "82%",
|
|
3601
|
+
minWidth: 0,
|
|
3602
|
+
padding: "9px 12px",
|
|
3603
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3604
|
+
fontSize: "13px",
|
|
3605
|
+
lineHeight: 1.55,
|
|
3606
|
+
backgroundColor: t.bgSecondary,
|
|
3607
|
+
color: t.text,
|
|
3608
|
+
border: live ? "none" : `1px solid ${t.accent}66`
|
|
2993
3609
|
},
|
|
2994
|
-
children:
|
|
3610
|
+
children: live ? (
|
|
3611
|
+
// #402: "have a read" beside a countdown reads as a
|
|
3612
|
+
// contradiction. Say what is about to happen instead.
|
|
3613
|
+
autoFileLeft !== null ? "Here's your report \u2014 I'll file it unless you want to change something." : "Here's your report \u2014 have a read."
|
|
3614
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3615
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3616
|
+
"span",
|
|
3617
|
+
{
|
|
3618
|
+
style: {
|
|
3619
|
+
display: "block",
|
|
3620
|
+
fontSize: "10px",
|
|
3621
|
+
fontWeight: 700,
|
|
3622
|
+
letterSpacing: ".06em",
|
|
3623
|
+
textTransform: "uppercase",
|
|
3624
|
+
color: t.accent,
|
|
3625
|
+
marginBottom: "4px"
|
|
3626
|
+
},
|
|
3627
|
+
children: "Draft so far"
|
|
3628
|
+
}
|
|
3629
|
+
),
|
|
3630
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3631
|
+
"span",
|
|
3632
|
+
{
|
|
3633
|
+
style: {
|
|
3634
|
+
display: "block",
|
|
3635
|
+
whiteSpace: "pre-wrap",
|
|
3636
|
+
wordBreak: "break-word",
|
|
3637
|
+
maxHeight: "160px",
|
|
3638
|
+
overflowY: "auto",
|
|
3639
|
+
color: t.textMuted
|
|
3640
|
+
},
|
|
3641
|
+
children: m.content
|
|
3642
|
+
}
|
|
3643
|
+
)
|
|
3644
|
+
] })
|
|
2995
3645
|
}
|
|
2996
3646
|
)
|
|
2997
|
-
] })
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3002
|
-
"div",
|
|
3003
|
-
{
|
|
3004
|
-
style: {
|
|
3005
|
-
display: "flex",
|
|
3006
|
-
// Long labels wrapped into a ragged row that always stranded
|
|
3007
|
-
// the last chip on a line of its own. Past ~24 characters
|
|
3008
|
-
// these stop being chips and become a choice list, so they
|
|
3009
|
-
// stack full width and read like one.
|
|
3010
|
-
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
3011
|
-
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
3012
|
-
flexWrap: "wrap",
|
|
3013
|
-
gap: "6px",
|
|
3014
|
-
paddingLeft: "32px"
|
|
3015
|
-
},
|
|
3016
|
-
children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3017
|
-
"button",
|
|
3647
|
+
] }, i);
|
|
3648
|
+
}
|
|
3649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3650
|
+
"div",
|
|
3018
3651
|
{
|
|
3019
|
-
type: "button",
|
|
3020
|
-
"data-gg-chip": "",
|
|
3021
|
-
"data-gg-option": "",
|
|
3022
|
-
onClick: () => {
|
|
3023
|
-
logEvent("option_tap", option);
|
|
3024
|
-
send(option, option === CONFIRM_OPTION);
|
|
3025
|
-
},
|
|
3026
3652
|
style: {
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
// Same 8px as the picker chips — one tap target size in
|
|
3032
|
-
// this sheet, not two.
|
|
3033
|
-
padding: "8px 12px",
|
|
3034
|
-
fontSize: "12px",
|
|
3035
|
-
fontFamily: "inherit",
|
|
3036
|
-
cursor: "pointer",
|
|
3037
|
-
textAlign: "left"
|
|
3653
|
+
display: "flex",
|
|
3654
|
+
gap: "8px",
|
|
3655
|
+
minWidth: 0,
|
|
3656
|
+
flexDirection: mine ? "row-reverse" : "row"
|
|
3038
3657
|
},
|
|
3039
|
-
children:
|
|
3658
|
+
children: [
|
|
3659
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
3660
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3661
|
+
"div",
|
|
3662
|
+
{
|
|
3663
|
+
style: {
|
|
3664
|
+
maxWidth: "82%",
|
|
3665
|
+
minWidth: 0,
|
|
3666
|
+
padding: "9px 12px",
|
|
3667
|
+
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
3668
|
+
fontSize: "13px",
|
|
3669
|
+
lineHeight: 1.55,
|
|
3670
|
+
// Markdown owns the assistant's line breaks and lists.
|
|
3671
|
+
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
3672
|
+
wordBreak: "break-word",
|
|
3673
|
+
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
3674
|
+
color: mine ? t.accentText : t.text
|
|
3675
|
+
},
|
|
3676
|
+
children: mine ? m.content : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChatMarkdown, { text: m.content, theme: t })
|
|
3677
|
+
}
|
|
3678
|
+
)
|
|
3679
|
+
]
|
|
3040
3680
|
},
|
|
3041
|
-
|
|
3042
|
-
)
|
|
3043
|
-
}
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3048
|
-
"span",
|
|
3681
|
+
i
|
|
3682
|
+
);
|
|
3683
|
+
}),
|
|
3684
|
+
duplicate && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
3685
|
+
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3686
|
+
"div",
|
|
3049
3687
|
{
|
|
3688
|
+
"data-gg-glitchgrab-offer": "",
|
|
3050
3689
|
style: {
|
|
3051
|
-
display: "
|
|
3052
|
-
|
|
3053
|
-
gap: "
|
|
3054
|
-
padding: "
|
|
3055
|
-
borderRadius: "
|
|
3056
|
-
|
|
3690
|
+
display: "flex",
|
|
3691
|
+
flexDirection: "column",
|
|
3692
|
+
gap: "8px",
|
|
3693
|
+
padding: "10px",
|
|
3694
|
+
borderRadius: "8px",
|
|
3695
|
+
border: `1px solid ${t.accent}55`,
|
|
3696
|
+
backgroundColor: `${t.accent}14`,
|
|
3697
|
+
fontSize: "12px",
|
|
3698
|
+
lineHeight: 1.5
|
|
3057
3699
|
},
|
|
3058
|
-
children: [
|
|
3059
|
-
"span",
|
|
3060
|
-
{
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3700
|
+
children: [
|
|
3701
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
3702
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
3703
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
3704
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3705
|
+
"button",
|
|
3706
|
+
{
|
|
3707
|
+
type: "button",
|
|
3708
|
+
"data-gg-glitchgrab-offer-send": "",
|
|
3709
|
+
onClick: () => {
|
|
3710
|
+
logEvent("glitchgrab_offer_tap");
|
|
3711
|
+
setGlitchgrabOffer(false);
|
|
3712
|
+
onReportGlitchgrabProblem(
|
|
3713
|
+
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
3714
|
+
);
|
|
3715
|
+
},
|
|
3716
|
+
style: {
|
|
3717
|
+
padding: "8px 12px",
|
|
3718
|
+
borderRadius: "999px",
|
|
3719
|
+
border: "none",
|
|
3720
|
+
backgroundColor: t.accent,
|
|
3721
|
+
color: t.accentText,
|
|
3722
|
+
fontSize: "12px",
|
|
3723
|
+
fontWeight: 700,
|
|
3724
|
+
fontFamily: "inherit",
|
|
3725
|
+
cursor: "pointer",
|
|
3726
|
+
// Both stretch, so on a phone each wrapped line reads as
|
|
3727
|
+
// a choice rather than one button left stranded.
|
|
3728
|
+
flex: "1 1 auto"
|
|
3729
|
+
},
|
|
3730
|
+
children: "Send to the Glitchgrab team"
|
|
3731
|
+
}
|
|
3732
|
+
),
|
|
3733
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3734
|
+
"button",
|
|
3735
|
+
{
|
|
3736
|
+
type: "button",
|
|
3737
|
+
"data-gg-glitchgrab-offer-no": "",
|
|
3738
|
+
onClick: () => {
|
|
3739
|
+
logEvent("glitchgrab_offer_declined");
|
|
3740
|
+
send("No \u2014 it's about this app, not the reporting tool");
|
|
3741
|
+
},
|
|
3742
|
+
style: {
|
|
3743
|
+
padding: "8px 12px",
|
|
3744
|
+
borderRadius: "999px",
|
|
3745
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3746
|
+
background: "transparent",
|
|
3747
|
+
color: t.textMuted,
|
|
3748
|
+
fontSize: "12px",
|
|
3749
|
+
fontFamily: "inherit",
|
|
3750
|
+
cursor: "pointer",
|
|
3751
|
+
flex: "1 1 auto"
|
|
3752
|
+
},
|
|
3753
|
+
children: "No, it's about this app"
|
|
3754
|
+
}
|
|
3755
|
+
)
|
|
3756
|
+
] })
|
|
3757
|
+
]
|
|
3071
3758
|
}
|
|
3072
|
-
)
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
"span",
|
|
3091
|
-
{
|
|
3092
|
-
style: {
|
|
3093
|
-
fontSize: "10px",
|
|
3094
|
-
fontWeight: 700,
|
|
3095
|
-
letterSpacing: ".06em",
|
|
3096
|
-
textTransform: "uppercase",
|
|
3097
|
-
color: t.accent
|
|
3098
|
-
},
|
|
3099
|
-
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3100
|
-
}
|
|
3101
|
-
),
|
|
3102
|
-
renderKnownIssue({
|
|
3103
|
-
title: true,
|
|
3104
|
-
footer: "Your details will be added to it instead of opening a new issue."
|
|
3105
|
-
}),
|
|
3106
|
-
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3107
|
-
// box edge is the very thing #543 is about. One line of text,
|
|
3108
|
-
// so Enter is swallowed.
|
|
3109
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3110
|
-
"textarea",
|
|
3111
|
-
{
|
|
3112
|
-
"aria-label": "Title",
|
|
3113
|
-
value: issueTitle,
|
|
3114
|
-
maxLength: 120,
|
|
3115
|
-
rows: 2,
|
|
3116
|
-
onKeyDown: (e) => {
|
|
3117
|
-
if (e.key === "Enter") e.preventDefault();
|
|
3118
|
-
},
|
|
3119
|
-
onChange: (e) => {
|
|
3120
|
-
stopAutoFile("edited the title");
|
|
3121
|
-
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3122
|
-
},
|
|
3123
|
-
style: {
|
|
3124
|
-
width: "100%",
|
|
3125
|
-
padding: "8px 10px",
|
|
3126
|
-
lineHeight: 1.45,
|
|
3127
|
-
resize: "none",
|
|
3128
|
-
borderRadius: "8px",
|
|
3129
|
-
border: `1px solid ${t.inputBorder}`,
|
|
3130
|
-
backgroundColor: t.inputBg,
|
|
3131
|
-
color: t.text,
|
|
3132
|
-
fontSize: "13px",
|
|
3133
|
-
fontWeight: 600,
|
|
3134
|
-
fontFamily: "inherit",
|
|
3135
|
-
outline: "none",
|
|
3136
|
-
boxSizing: "border-box"
|
|
3137
|
-
}
|
|
3138
|
-
}
|
|
3139
|
-
),
|
|
3140
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3141
|
-
"textarea",
|
|
3759
|
+
) }),
|
|
3760
|
+
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3761
|
+
"div",
|
|
3762
|
+
{
|
|
3763
|
+
style: {
|
|
3764
|
+
display: "flex",
|
|
3765
|
+
// Long labels wrapped into a ragged row that always stranded
|
|
3766
|
+
// the last chip on a line of its own. Past ~24 characters
|
|
3767
|
+
// these stop being chips and become a choice list, so they
|
|
3768
|
+
// stack full width and read like one.
|
|
3769
|
+
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
3770
|
+
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
3771
|
+
flexWrap: "wrap",
|
|
3772
|
+
gap: "6px",
|
|
3773
|
+
paddingLeft: "32px"
|
|
3774
|
+
},
|
|
3775
|
+
children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3776
|
+
"button",
|
|
3142
3777
|
{
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3778
|
+
type: "button",
|
|
3779
|
+
"data-gg-chip": "",
|
|
3780
|
+
"data-gg-option": "",
|
|
3781
|
+
onClick: () => {
|
|
3782
|
+
logEvent("option_tap", option);
|
|
3783
|
+
send(option, option === CONFIRM_OPTION);
|
|
3148
3784
|
},
|
|
3149
|
-
rows: 6,
|
|
3150
3785
|
style: {
|
|
3151
|
-
width: "100%",
|
|
3152
|
-
minHeight: "120px",
|
|
3153
|
-
padding: "10px",
|
|
3154
|
-
borderRadius: "8px",
|
|
3155
3786
|
border: `1px solid ${t.inputBorder}`,
|
|
3156
|
-
|
|
3157
|
-
color: t.
|
|
3158
|
-
|
|
3159
|
-
|
|
3787
|
+
background: "transparent",
|
|
3788
|
+
color: t.textMuted,
|
|
3789
|
+
borderRadius: "999px",
|
|
3790
|
+
// Same 8px as the picker chips — one tap target size in
|
|
3791
|
+
// this sheet, not two.
|
|
3792
|
+
padding: "8px 12px",
|
|
3793
|
+
fontSize: "12px",
|
|
3160
3794
|
fontFamily: "inherit",
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
}
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3795
|
+
cursor: "pointer",
|
|
3796
|
+
textAlign: "left"
|
|
3797
|
+
},
|
|
3798
|
+
children: option
|
|
3799
|
+
},
|
|
3800
|
+
option
|
|
3801
|
+
))
|
|
3802
|
+
}
|
|
3803
|
+
),
|
|
3804
|
+
busy && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, role: "status", "aria-label": "Thinking", children: [
|
|
3805
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3806
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3807
|
+
"span",
|
|
3808
|
+
{
|
|
3809
|
+
style: {
|
|
3810
|
+
display: "inline-flex",
|
|
3811
|
+
alignItems: "center",
|
|
3812
|
+
// The "still working" line must wrap on a phone, not push
|
|
3813
|
+
// the bubble past the sheet's edge.
|
|
3814
|
+
flexWrap: "wrap",
|
|
3815
|
+
minWidth: 0,
|
|
3816
|
+
gap: "4px",
|
|
3817
|
+
padding: "12px",
|
|
3818
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3819
|
+
backgroundColor: t.bgSecondary
|
|
3820
|
+
},
|
|
3821
|
+
children: [
|
|
3822
|
+
[0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3823
|
+
"span",
|
|
3824
|
+
{
|
|
3825
|
+
style: {
|
|
3826
|
+
width: "5px",
|
|
3827
|
+
height: "5px",
|
|
3828
|
+
borderRadius: "50%",
|
|
3829
|
+
backgroundColor: t.textMuted,
|
|
3830
|
+
animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
|
|
3831
|
+
}
|
|
3832
|
+
},
|
|
3833
|
+
i
|
|
3834
|
+
)),
|
|
3835
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ThinkingClock, { color: t.textMuted })
|
|
3836
|
+
]
|
|
3837
|
+
}
|
|
3838
|
+
)
|
|
3839
|
+
] }),
|
|
3840
|
+
phase === "draft" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3841
|
+
"div",
|
|
3842
|
+
{
|
|
3843
|
+
style: {
|
|
3844
|
+
border: `1px solid ${t.accent}`,
|
|
3845
|
+
borderRadius: "12px",
|
|
3846
|
+
backgroundColor: t.bgSecondary,
|
|
3847
|
+
padding: "12px",
|
|
3848
|
+
display: "flex",
|
|
3849
|
+
flexDirection: "column",
|
|
3850
|
+
gap: "10px",
|
|
3851
|
+
minWidth: 0,
|
|
3852
|
+
boxSizing: "border-box"
|
|
3853
|
+
},
|
|
3854
|
+
children: [
|
|
3855
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3169
3856
|
"span",
|
|
3170
3857
|
{
|
|
3171
3858
|
style: {
|
|
3172
|
-
fontSize: "
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3859
|
+
fontSize: "10px",
|
|
3860
|
+
fontWeight: 700,
|
|
3861
|
+
letterSpacing: ".06em",
|
|
3862
|
+
textTransform: "uppercase",
|
|
3863
|
+
color: t.accent
|
|
3176
3864
|
},
|
|
3177
|
-
children:
|
|
3178
|
-
"How bad is it?",
|
|
3179
|
-
!severity && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3180
|
-
"span",
|
|
3181
|
-
{
|
|
3182
|
-
style: {
|
|
3183
|
-
marginLeft: "6px",
|
|
3184
|
-
fontSize: "11px",
|
|
3185
|
-
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3186
|
-
},
|
|
3187
|
-
children: "\xB7 required"
|
|
3188
|
-
}
|
|
3189
|
-
)
|
|
3190
|
-
]
|
|
3865
|
+
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3191
3866
|
}
|
|
3192
3867
|
),
|
|
3868
|
+
renderKnownIssue({
|
|
3869
|
+
title: true,
|
|
3870
|
+
footer: "Your details will be added to it instead of opening a new issue."
|
|
3871
|
+
}),
|
|
3872
|
+
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3873
|
+
// box edge is the very thing #543 is about. One line of text,
|
|
3874
|
+
// so Enter is swallowed.
|
|
3193
3875
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3194
|
-
"
|
|
3876
|
+
"textarea",
|
|
3195
3877
|
{
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
cursor: "pointer"
|
|
3223
|
-
},
|
|
3224
|
-
children: SEVERITY_LABELS[s]
|
|
3225
|
-
},
|
|
3226
|
-
s
|
|
3227
|
-
);
|
|
3228
|
-
})
|
|
3878
|
+
"aria-label": "Title",
|
|
3879
|
+
value: issueTitle,
|
|
3880
|
+
maxLength: 120,
|
|
3881
|
+
rows: 2,
|
|
3882
|
+
onKeyDown: (e) => {
|
|
3883
|
+
if (e.key === "Enter") e.preventDefault();
|
|
3884
|
+
},
|
|
3885
|
+
onChange: (e) => {
|
|
3886
|
+
stopAutoFile("edited the title");
|
|
3887
|
+
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3888
|
+
},
|
|
3889
|
+
style: {
|
|
3890
|
+
width: "100%",
|
|
3891
|
+
padding: "8px 10px",
|
|
3892
|
+
lineHeight: 1.45,
|
|
3893
|
+
resize: "none",
|
|
3894
|
+
borderRadius: "8px",
|
|
3895
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3896
|
+
backgroundColor: t.inputBg,
|
|
3897
|
+
color: t.text,
|
|
3898
|
+
fontSize: "13px",
|
|
3899
|
+
fontWeight: 600,
|
|
3900
|
+
fontFamily: "inherit",
|
|
3901
|
+
outline: "none",
|
|
3902
|
+
boxSizing: "border-box"
|
|
3903
|
+
}
|
|
3229
3904
|
}
|
|
3230
|
-
)
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3905
|
+
),
|
|
3906
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3907
|
+
"textarea",
|
|
3908
|
+
{
|
|
3909
|
+
ref: draftRef,
|
|
3910
|
+
value: description,
|
|
3911
|
+
onChange: (e) => {
|
|
3912
|
+
stopAutoFile("edited the draft");
|
|
3913
|
+
onDescriptionChange(e.target.value);
|
|
3914
|
+
},
|
|
3915
|
+
rows: 6,
|
|
3916
|
+
style: {
|
|
3917
|
+
width: "100%",
|
|
3918
|
+
minHeight: "120px",
|
|
3919
|
+
padding: "10px",
|
|
3920
|
+
borderRadius: "8px",
|
|
3921
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3922
|
+
backgroundColor: t.inputBg,
|
|
3923
|
+
color: t.text,
|
|
3924
|
+
fontSize: "13px",
|
|
3925
|
+
lineHeight: 1.55,
|
|
3926
|
+
fontFamily: "inherit",
|
|
3927
|
+
resize: "vertical",
|
|
3928
|
+
outline: "none",
|
|
3929
|
+
boxSizing: "border-box"
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
),
|
|
3933
|
+
severityAsked && autoFileLeft === null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
3934
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3935
|
+
"span",
|
|
3936
|
+
{
|
|
3937
|
+
style: {
|
|
3938
|
+
fontSize: "11.5px",
|
|
3939
|
+
color: t.textMuted,
|
|
3940
|
+
display: "block",
|
|
3941
|
+
marginBottom: "6px"
|
|
3942
|
+
},
|
|
3943
|
+
children: [
|
|
3944
|
+
"How bad is it?",
|
|
3945
|
+
!severity && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3946
|
+
"span",
|
|
3947
|
+
{
|
|
3948
|
+
style: {
|
|
3949
|
+
marginLeft: "6px",
|
|
3950
|
+
fontSize: "11px",
|
|
3951
|
+
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3952
|
+
},
|
|
3953
|
+
children: "\xB7 required"
|
|
3954
|
+
}
|
|
3955
|
+
)
|
|
3956
|
+
]
|
|
3957
|
+
}
|
|
3958
|
+
),
|
|
3959
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3960
|
+
"div",
|
|
3961
|
+
{
|
|
3962
|
+
role: "radiogroup",
|
|
3963
|
+
"aria-label": "Severity",
|
|
3964
|
+
style: { display: "flex", gap: "6px" },
|
|
3965
|
+
children: SEVERITY_LEVELS.map((s) => {
|
|
3966
|
+
const on = severity === s;
|
|
3967
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3968
|
+
"button",
|
|
3969
|
+
{
|
|
3970
|
+
type: "button",
|
|
3971
|
+
onClick: () => onSeverityChange(s),
|
|
3972
|
+
role: "radio",
|
|
3973
|
+
"aria-checked": on,
|
|
3974
|
+
style: {
|
|
3975
|
+
flex: 1,
|
|
3976
|
+
minWidth: 0,
|
|
3977
|
+
padding: "8px 2px",
|
|
3978
|
+
borderRadius: "8px",
|
|
3979
|
+
border: `1px solid ${on ? t.accent : severityRefused ? "#ef4444" : t.inputBorder}`,
|
|
3980
|
+
backgroundColor: on ? t.accent : "transparent",
|
|
3981
|
+
color: on ? t.accentText : t.textMuted,
|
|
3982
|
+
fontSize: "12px",
|
|
3983
|
+
fontWeight: 600,
|
|
3984
|
+
fontFamily: "inherit",
|
|
3985
|
+
whiteSpace: "nowrap",
|
|
3986
|
+
overflow: "hidden",
|
|
3987
|
+
textOverflow: "ellipsis",
|
|
3988
|
+
cursor: "pointer"
|
|
3989
|
+
},
|
|
3990
|
+
children: SEVERITY_LABELS[s]
|
|
3991
|
+
},
|
|
3992
|
+
s
|
|
3993
|
+
);
|
|
3994
|
+
})
|
|
3995
|
+
}
|
|
3996
|
+
)
|
|
3997
|
+
] }),
|
|
3998
|
+
attachmentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3999
|
+
attachmentCount,
|
|
4000
|
+
" ",
|
|
4001
|
+
attachmentCount === 1 ? "attachment" : "attachments",
|
|
4002
|
+
" will be sent with this."
|
|
4003
|
+
] })
|
|
4004
|
+
]
|
|
4005
|
+
}
|
|
4006
|
+
),
|
|
4007
|
+
phase === "solved" && solved && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
4008
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
4009
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
4010
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4011
|
+
"div",
|
|
4012
|
+
{
|
|
4013
|
+
style: {
|
|
4014
|
+
padding: "9px 12px",
|
|
4015
|
+
borderRadius: "12px 12px 12px 4px",
|
|
4016
|
+
backgroundColor: t.bgSecondary,
|
|
4017
|
+
fontSize: "13px",
|
|
4018
|
+
lineHeight: 1.55,
|
|
4019
|
+
maxWidth: "88%",
|
|
4020
|
+
whiteSpace: "pre-wrap"
|
|
4021
|
+
},
|
|
4022
|
+
children: solved
|
|
4023
|
+
}
|
|
4024
|
+
)
|
|
4025
|
+
] }),
|
|
3244
4026
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3245
|
-
"
|
|
4027
|
+
"span",
|
|
3246
4028
|
{
|
|
3247
|
-
style: {
|
|
3248
|
-
|
|
3249
|
-
borderRadius: "12px 12px 12px 4px",
|
|
3250
|
-
backgroundColor: t.bgSecondary,
|
|
3251
|
-
fontSize: "13px",
|
|
3252
|
-
lineHeight: 1.55,
|
|
3253
|
-
maxWidth: "88%",
|
|
3254
|
-
whiteSpace: "pre-wrap"
|
|
3255
|
-
},
|
|
3256
|
-
children: solved
|
|
4029
|
+
style: { fontSize: "11.5px", color: t.textMuted, paddingLeft: "32px" },
|
|
4030
|
+
children: "Nothing was filed \u2014 you are all set."
|
|
3257
4031
|
}
|
|
3258
4032
|
)
|
|
3259
4033
|
] }),
|
|
3260
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3261
|
-
"
|
|
4034
|
+
submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4035
|
+
"div",
|
|
3262
4036
|
{
|
|
3263
|
-
style: {
|
|
3264
|
-
|
|
4037
|
+
style: {
|
|
4038
|
+
textAlign: "center",
|
|
4039
|
+
padding: "24px 0",
|
|
4040
|
+
color: t.accent,
|
|
4041
|
+
fontSize: "14px",
|
|
4042
|
+
fontWeight: 600
|
|
4043
|
+
},
|
|
4044
|
+
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3265
4045
|
}
|
|
3266
4046
|
)
|
|
3267
|
-
] })
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
style: {
|
|
3272
|
-
textAlign: "center",
|
|
3273
|
-
padding: "24px 0",
|
|
3274
|
-
color: t.accent,
|
|
3275
|
-
fontSize: "14px",
|
|
3276
|
-
fontWeight: 600
|
|
3277
|
-
},
|
|
3278
|
-
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3279
|
-
}
|
|
3280
|
-
)
|
|
3281
|
-
]
|
|
3282
|
-
}
|
|
3283
|
-
)
|
|
4047
|
+
] })
|
|
4048
|
+
}
|
|
4049
|
+
)
|
|
4050
|
+
]
|
|
3284
4051
|
}
|
|
3285
4052
|
),
|
|
3286
|
-
!submitted && phase !== "type" && phase !== "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
4053
|
+
!submitted && !showChats && phase !== "type" && phase !== "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3287
4054
|
"div",
|
|
3288
4055
|
{
|
|
3289
4056
|
style: {
|
|
@@ -3600,8 +4367,8 @@ function AssistSheet({
|
|
|
3600
4367
|
accept: canReadPdf ? ASSIST_ATTACHMENT_ACCEPT_WITH_PDF : ASSIST_ATTACHMENT_ACCEPT,
|
|
3601
4368
|
multiple: true,
|
|
3602
4369
|
onChange: (e) => {
|
|
3603
|
-
var
|
|
3604
|
-
const picked = Array.from((
|
|
4370
|
+
var _a2;
|
|
4371
|
+
const picked = Array.from((_a2 = e.target.files) != null ? _a2 : []);
|
|
3605
4372
|
if (picked.length) {
|
|
3606
4373
|
stopAutoFile("changed attachments");
|
|
3607
4374
|
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
@@ -4579,20 +5346,20 @@ function initialsOf(name) {
|
|
|
4579
5346
|
}).join("");
|
|
4580
5347
|
}
|
|
4581
5348
|
function ReporterChip({
|
|
4582
|
-
reporter,
|
|
5349
|
+
reporter: reporter2,
|
|
4583
5350
|
t
|
|
4584
5351
|
}) {
|
|
4585
5352
|
var _a;
|
|
4586
5353
|
const [avatarFailed, setAvatarFailed] = (0, import_react.useState)(false);
|
|
4587
|
-
const avatarUrl = (
|
|
5354
|
+
const avatarUrl = (reporter2 == null ? void 0 : reporter2.avatarUrl) || "";
|
|
4588
5355
|
(0, import_react.useEffect)(() => {
|
|
4589
5356
|
setAvatarFailed(false);
|
|
4590
5357
|
}, [avatarUrl]);
|
|
4591
|
-
const name = ((_a =
|
|
5358
|
+
const name = ((_a = reporter2 == null ? void 0 : reporter2.name) == null ? void 0 : _a.trim()) || "";
|
|
4592
5359
|
const isAnonymous = !name;
|
|
4593
5360
|
const initials2 = isAnonymous ? "" : initialsOf(name);
|
|
4594
5361
|
const label = isAnonymous ? "Anonymous" : name;
|
|
4595
|
-
const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name,
|
|
5362
|
+
const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name, reporter2 == null ? void 0 : reporter2.email, reporter2 == null ? void 0 : reporter2.role].filter(Boolean).join(" \xB7 ");
|
|
4596
5363
|
const showAvatarImage = !!avatarUrl && !avatarFailed;
|
|
4597
5364
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4598
5365
|
"span",
|
|
@@ -4656,7 +5423,7 @@ function ReporterChip({
|
|
|
4656
5423
|
},
|
|
4657
5424
|
children: [
|
|
4658
5425
|
label,
|
|
4659
|
-
(
|
|
5426
|
+
(reporter2 == null ? void 0 : reporter2.role) ? ` \xB7 ${reporter2.role}` : ""
|
|
4660
5427
|
]
|
|
4661
5428
|
}
|
|
4662
5429
|
)
|
|
@@ -4773,11 +5540,12 @@ function ReportDialog({
|
|
|
4773
5540
|
types,
|
|
4774
5541
|
showSeverity = true,
|
|
4775
5542
|
captureScreenshot = captureDefaultScreenshot,
|
|
4776
|
-
reporter,
|
|
5543
|
+
reporter: reporter2,
|
|
4777
5544
|
onClose,
|
|
4778
5545
|
headerSlot,
|
|
4779
5546
|
reportGlitchgrabProblem,
|
|
4780
|
-
layout = "modal"
|
|
5547
|
+
layout = "modal",
|
|
5548
|
+
chatHistoryKey: chatHistoryKey2 = null
|
|
4781
5549
|
}) {
|
|
4782
5550
|
var _a;
|
|
4783
5551
|
const sheet = layout === "sheet";
|
|
@@ -4799,6 +5567,7 @@ function ReportDialog({
|
|
|
4799
5567
|
const [aiConversationId, setAiConversationId] = (0, import_react.useState)(null);
|
|
4800
5568
|
const [issueTitle, setIssueTitle] = (0, import_react.useState)("");
|
|
4801
5569
|
const [isEnhanced, setIsEnhanced] = (0, import_react.useState)(false);
|
|
5570
|
+
const [enhanceError, setEnhanceError] = (0, import_react.useState)(null);
|
|
4802
5571
|
const [originalDescription, setOriginalDescription] = (0, import_react.useState)(
|
|
4803
5572
|
null
|
|
4804
5573
|
);
|
|
@@ -4882,15 +5651,15 @@ function ReportDialog({
|
|
|
4882
5651
|
});
|
|
4883
5652
|
};
|
|
4884
5653
|
applyInert();
|
|
4885
|
-
const
|
|
5654
|
+
const observer2 = new MutationObserver((mutations) => {
|
|
4886
5655
|
const structural = mutations.some(
|
|
4887
5656
|
(m) => m.addedNodes.length > 0 || m.removedNodes.length > 0
|
|
4888
5657
|
);
|
|
4889
5658
|
if (structural) applyInert();
|
|
4890
5659
|
});
|
|
4891
|
-
|
|
5660
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
4892
5661
|
return () => {
|
|
4893
|
-
|
|
5662
|
+
observer2.disconnect();
|
|
4894
5663
|
inerted.forEach((el) => el.removeAttribute("inert"));
|
|
4895
5664
|
};
|
|
4896
5665
|
}, [isOpen]);
|
|
@@ -5253,6 +6022,7 @@ function ReportDialog({
|
|
|
5253
6022
|
setSelfReportFrom(null);
|
|
5254
6023
|
setVoiceError(null);
|
|
5255
6024
|
setIsEnhanced(false);
|
|
6025
|
+
setEnhanceError(null);
|
|
5256
6026
|
setOriginalDescription(null);
|
|
5257
6027
|
setAssistOpen(false);
|
|
5258
6028
|
setAssistUsed(false);
|
|
@@ -5318,6 +6088,7 @@ function ReportDialog({
|
|
|
5318
6088
|
const sep = base.trim() ? " " : "";
|
|
5319
6089
|
setDescriptionFromVoice(base + sep + text.trim());
|
|
5320
6090
|
setValidationError(null);
|
|
6091
|
+
setEnhanceError(null);
|
|
5321
6092
|
setIsEnhanced(false);
|
|
5322
6093
|
setOriginalDescription(null);
|
|
5323
6094
|
}
|
|
@@ -5542,6 +6313,9 @@ function ReportDialog({
|
|
|
5542
6313
|
setAddedAsRelated(!!duplicateOf && result.issueNumber === duplicateOf && attachKind === "related");
|
|
5543
6314
|
const queued = result.status === "QUEUED" && !!result.message;
|
|
5544
6315
|
setQueuedMessage(queued ? (_c = result.message) != null ? _c : null : null);
|
|
6316
|
+
if (chatHistoryKey2 && aiConversationId) {
|
|
6317
|
+
markChatFiled(chatHistoryKey2, aiConversationId, `${getTypeLabel(reportType)} sent`);
|
|
6318
|
+
}
|
|
5545
6319
|
setSubmitted(true);
|
|
5546
6320
|
setDescription("");
|
|
5547
6321
|
setScreenshots([]);
|
|
@@ -6410,6 +7184,7 @@ function ReportDialog({
|
|
|
6410
7184
|
notePushToTalkEdit();
|
|
6411
7185
|
setDescription(e.target.value);
|
|
6412
7186
|
if (validationError) setValidationError(null);
|
|
7187
|
+
if (enhanceError) setEnhanceError(null);
|
|
6413
7188
|
if (isEnhanced) {
|
|
6414
7189
|
setIsEnhanced(false);
|
|
6415
7190
|
setOriginalDescription(null);
|
|
@@ -6531,6 +7306,7 @@ function ReportDialog({
|
|
|
6531
7306
|
var _a2;
|
|
6532
7307
|
if (!description.trim() || isEnhancing) return;
|
|
6533
7308
|
setIsEnhancing(true);
|
|
7309
|
+
setEnhanceError(null);
|
|
6534
7310
|
try {
|
|
6535
7311
|
const polished = await enhanceText2(
|
|
6536
7312
|
description,
|
|
@@ -6543,6 +7319,10 @@ function ReportDialog({
|
|
|
6543
7319
|
if (validationError)
|
|
6544
7320
|
setValidationError(null);
|
|
6545
7321
|
}
|
|
7322
|
+
} catch (err) {
|
|
7323
|
+
setEnhanceError(
|
|
7324
|
+
err instanceof Error && err.message ? err.message : "AI enhance isn't available right now \u2014 send your report as written."
|
|
7325
|
+
);
|
|
6546
7326
|
} finally {
|
|
6547
7327
|
setIsEnhancing(false);
|
|
6548
7328
|
}
|
|
@@ -6801,6 +7581,20 @@ function ReportDialog({
|
|
|
6801
7581
|
children: voiceError
|
|
6802
7582
|
}
|
|
6803
7583
|
),
|
|
7584
|
+
enhanceError && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7585
|
+
"p",
|
|
7586
|
+
{
|
|
7587
|
+
role: "alert",
|
|
7588
|
+
style: {
|
|
7589
|
+
color: "#ef4444",
|
|
7590
|
+
fontSize: "11px",
|
|
7591
|
+
lineHeight: 1.5,
|
|
7592
|
+
marginTop: "4px",
|
|
7593
|
+
marginBottom: 0
|
|
7594
|
+
},
|
|
7595
|
+
children: enhanceError
|
|
7596
|
+
}
|
|
7597
|
+
),
|
|
6804
7598
|
assistNotice && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6805
7599
|
"p",
|
|
6806
7600
|
{
|
|
@@ -7361,7 +8155,7 @@ function ReportDialog({
|
|
|
7361
8155
|
gap: "12px"
|
|
7362
8156
|
},
|
|
7363
8157
|
children: [
|
|
7364
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ReporterChip, { reporter, t }),
|
|
8158
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ReporterChip, { reporter: reporter2, t }),
|
|
7365
8159
|
reportGlitchgrabProblem ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7366
8160
|
"button",
|
|
7367
8161
|
{
|
|
@@ -7641,6 +8435,7 @@ function ReportDialog({
|
|
|
7641
8435
|
setDuplicateKind(issueNumber && kind === "related" ? "related" : "duplicate");
|
|
7642
8436
|
},
|
|
7643
8437
|
onConversationChange: setAiConversationId,
|
|
8438
|
+
historyKey: chatHistoryKey2,
|
|
7644
8439
|
onFinish: handleClose,
|
|
7645
8440
|
rating,
|
|
7646
8441
|
onRatingChange: (value) => {
|
|
@@ -7648,7 +8443,7 @@ function ReportDialog({
|
|
|
7648
8443
|
if (validationError) setValidationError(null);
|
|
7649
8444
|
},
|
|
7650
8445
|
projectSlot: headerSlot,
|
|
7651
|
-
reporterName: (_a =
|
|
8446
|
+
reporterName: (_a = reporter2 == null ? void 0 : reporter2.name) != null ? _a : null,
|
|
7652
8447
|
description,
|
|
7653
8448
|
onDescriptionChange: (value) => {
|
|
7654
8449
|
setDescription(value);
|
|
@@ -9235,6 +10030,9 @@ function GlitchgrabProviderInner({
|
|
|
9235
10030
|
onError,
|
|
9236
10031
|
onReportSent
|
|
9237
10032
|
});
|
|
10033
|
+
if (process.env.NODE_ENV !== "development") {
|
|
10034
|
+
installHydrationCapture(reportHydrationError);
|
|
10035
|
+
}
|
|
9238
10036
|
(0, import_react6.useEffect)(() => {
|
|
9239
10037
|
if (enableBreadcrumbs) {
|
|
9240
10038
|
initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
|
|
@@ -9290,7 +10088,7 @@ function GlitchgrabProviderInner({
|
|
|
9290
10088
|
return matchesIgnorePatterns(message, ignoreErrors);
|
|
9291
10089
|
};
|
|
9292
10090
|
const handleError = (event) => {
|
|
9293
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
10091
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
9294
10092
|
try {
|
|
9295
10093
|
const isOpaqueCrossOrigin = event.message === "Script error." || event.message === "Script error" || !event.error && !event.filename;
|
|
9296
10094
|
if (isOpaqueCrossOrigin) {
|
|
@@ -9305,6 +10103,7 @@ function GlitchgrabProviderInner({
|
|
|
9305
10103
|
if (event.filename && EXTENSION_ORIGIN_RE.test(event.filename) || ((_a = event.error) == null ? void 0 : _a.stack) && EXTENSION_ORIGIN_RE.test(event.error.stack)) {
|
|
9306
10104
|
return;
|
|
9307
10105
|
}
|
|
10106
|
+
if (isHandledHydrationError(event.error)) return;
|
|
9308
10107
|
incrementErrorCount();
|
|
9309
10108
|
const context = captureContext(visitedPagesRef.current);
|
|
9310
10109
|
const sig = computeSignature({
|
|
@@ -9330,6 +10129,9 @@ function GlitchgrabProviderInner({
|
|
|
9330
10129
|
filename: (_e = event.filename) != null ? _e : "",
|
|
9331
10130
|
lineno: String((_f = event.lineno) != null ? _f : ""),
|
|
9332
10131
|
colno: String((_g = event.colno) != null ? _g : ""),
|
|
10132
|
+
// The root patch could not attach (React internals moved, or a
|
|
10133
|
+
// root it does not know): still label it and send the DOM context.
|
|
10134
|
+
...isHydrationError((_h = event.error) != null ? _h : event.message) ? hydrationMetadata((_i = event.error) != null ? _i : event.message) : {},
|
|
9333
10135
|
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
9334
10136
|
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
9335
10137
|
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
@@ -9546,21 +10348,27 @@ function GlitchgrabProviderInner({
|
|
|
9546
10348
|
() => ({ userId: signedUserId != null ? signedUserId : null, signature }),
|
|
9547
10349
|
[signedUserId, signature]
|
|
9548
10350
|
);
|
|
10351
|
+
const enhanceForDialog = (0, import_react6.useCallback)(
|
|
10352
|
+
async (text, screenshot) => {
|
|
10353
|
+
const ctx = captureContext(visitedPagesRef.current);
|
|
10354
|
+
const context = {
|
|
10355
|
+
url: ctx.url,
|
|
10356
|
+
visitedPages: ctx.visitedPages.slice(-5),
|
|
10357
|
+
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
10358
|
+
};
|
|
10359
|
+
return await enhanceTextOrThrow(text, token, baseUrl, screenshot, context, identity);
|
|
10360
|
+
},
|
|
10361
|
+
[token, baseUrl, identity]
|
|
10362
|
+
);
|
|
9549
10363
|
const enhance = (0, import_react6.useCallback)(
|
|
9550
10364
|
async (text, screenshot) => {
|
|
9551
10365
|
try {
|
|
9552
|
-
|
|
9553
|
-
const context = {
|
|
9554
|
-
url: ctx.url,
|
|
9555
|
-
visitedPages: ctx.visitedPages.slice(-5),
|
|
9556
|
-
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
9557
|
-
};
|
|
9558
|
-
return await enhanceText(text, token, baseUrl, screenshot, context, identity);
|
|
10366
|
+
return await enhanceForDialog(text, screenshot);
|
|
9559
10367
|
} catch (e) {
|
|
9560
10368
|
return text;
|
|
9561
10369
|
}
|
|
9562
10370
|
},
|
|
9563
|
-
[
|
|
10371
|
+
[enhanceForDialog]
|
|
9564
10372
|
);
|
|
9565
10373
|
const assist = (0, import_react6.useCallback)(
|
|
9566
10374
|
async (params) => {
|
|
@@ -9671,7 +10479,7 @@ function GlitchgrabProviderInner({
|
|
|
9671
10479
|
} catch (e) {
|
|
9672
10480
|
}
|
|
9673
10481
|
}, [openReportDialog]);
|
|
9674
|
-
const
|
|
10482
|
+
const reporter2 = (0, import_react6.useMemo)(() => {
|
|
9675
10483
|
var _a;
|
|
9676
10484
|
if (!session) return null;
|
|
9677
10485
|
const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
|
|
@@ -9734,7 +10542,7 @@ function GlitchgrabProviderInner({
|
|
|
9734
10542
|
{
|
|
9735
10543
|
report,
|
|
9736
10544
|
sendFeedback: feedback,
|
|
9737
|
-
enhanceText: aiAssist && !aiBlockedUnsigned ?
|
|
10545
|
+
enhanceText: aiAssist && !aiBlockedUnsigned ? enhanceForDialog : void 0,
|
|
9738
10546
|
assist: aiAssist && !aiBlockedUnsigned ? assist : void 0,
|
|
9739
10547
|
findSimilarIssues: aiAssist && !aiBlockedUnsigned ? findSimilar : void 0,
|
|
9740
10548
|
readFile: aiAssist && !aiBlockedUnsigned ? readFile : void 0,
|
|
@@ -9742,7 +10550,8 @@ function GlitchgrabProviderInner({
|
|
|
9742
10550
|
transcribeAudio: aiBlockedUnsigned ? void 0 : transcribe,
|
|
9743
10551
|
types,
|
|
9744
10552
|
showSeverity,
|
|
9745
|
-
reporter,
|
|
10553
|
+
reporter: reporter2,
|
|
10554
|
+
chatHistoryKey: chatHistoryKey("sdk", token, session == null ? void 0 : session.userId),
|
|
9746
10555
|
headerSlot: projectName ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
|
|
9747
10556
|
"Reporting to ",
|
|
9748
10557
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { style: { color: "#e5e5e5" }, children: projectName })
|
|
@@ -10078,6 +10887,87 @@ function useGlitchgrabActions({
|
|
|
10078
10887
|
error
|
|
10079
10888
|
};
|
|
10080
10889
|
}
|
|
10890
|
+
async function fetchGlitchgrabReportThread({
|
|
10891
|
+
token,
|
|
10892
|
+
reportId
|
|
10893
|
+
}) {
|
|
10894
|
+
var _a, _b, _c;
|
|
10895
|
+
const res = await fetch(`${BASE_URL}/api/v1/sdk/reports/${encodeURIComponent(reportId)}`, {
|
|
10896
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
10897
|
+
});
|
|
10898
|
+
const data = await res.json().catch(() => ({}));
|
|
10899
|
+
if (!res.ok || !data.success) throw new Error((_a = data.error) != null ? _a : "Failed to fetch report");
|
|
10900
|
+
return { ...data.data, comments: (_c = (_b = data.data) == null ? void 0 : _b.comments) != null ? _c : [] };
|
|
10901
|
+
}
|
|
10902
|
+
async function postGlitchgrabReportComment({
|
|
10903
|
+
token,
|
|
10904
|
+
reportId,
|
|
10905
|
+
message,
|
|
10906
|
+
reporterName,
|
|
10907
|
+
reporterEmail
|
|
10908
|
+
}) {
|
|
10909
|
+
var _a;
|
|
10910
|
+
const res = await fetch(`${BASE_URL}/api/v1/sdk/reports/${encodeURIComponent(reportId)}/comments`, {
|
|
10911
|
+
method: "POST",
|
|
10912
|
+
headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
|
|
10913
|
+
body: JSON.stringify({ message, reporterName, reporterEmail })
|
|
10914
|
+
});
|
|
10915
|
+
const data = await res.json().catch(() => ({}));
|
|
10916
|
+
if (!res.ok || !data.success) throw new Error((_a = data.error) != null ? _a : "Failed to post comment");
|
|
10917
|
+
return data.data;
|
|
10918
|
+
}
|
|
10919
|
+
function useGlitchgrabReportThread({
|
|
10920
|
+
token,
|
|
10921
|
+
reportId,
|
|
10922
|
+
reporterName,
|
|
10923
|
+
reporterEmail
|
|
10924
|
+
}) {
|
|
10925
|
+
var _a;
|
|
10926
|
+
const [report, setReport] = (0, import_react8.useState)(null);
|
|
10927
|
+
const [isLoading, setIsLoading] = (0, import_react8.useState)(!!reportId);
|
|
10928
|
+
const [isFetching, setIsFetching] = (0, import_react8.useState)(false);
|
|
10929
|
+
const [isPosting, setIsPosting] = (0, import_react8.useState)(false);
|
|
10930
|
+
const [error, setError] = (0, import_react8.useState)(null);
|
|
10931
|
+
const refetch = (0, import_react8.useCallback)(async () => {
|
|
10932
|
+
if (!token || !reportId) {
|
|
10933
|
+
setReport(null);
|
|
10934
|
+
setIsLoading(false);
|
|
10935
|
+
return;
|
|
10936
|
+
}
|
|
10937
|
+
setIsFetching(true);
|
|
10938
|
+
setError(null);
|
|
10939
|
+
try {
|
|
10940
|
+
setReport(await fetchGlitchgrabReportThread({ token, reportId }));
|
|
10941
|
+
} catch (e) {
|
|
10942
|
+
setError(e instanceof Error ? e.message : "Network error");
|
|
10943
|
+
} finally {
|
|
10944
|
+
setIsLoading(false);
|
|
10945
|
+
setIsFetching(false);
|
|
10946
|
+
}
|
|
10947
|
+
}, [token, reportId]);
|
|
10948
|
+
(0, import_react8.useEffect)(() => {
|
|
10949
|
+
refetch();
|
|
10950
|
+
}, [refetch]);
|
|
10951
|
+
const addComment = (0, import_react8.useCallback)(
|
|
10952
|
+
async (message) => {
|
|
10953
|
+
if (!token || !reportId || !message.trim()) return false;
|
|
10954
|
+
setIsPosting(true);
|
|
10955
|
+
setError(null);
|
|
10956
|
+
try {
|
|
10957
|
+
await postGlitchgrabReportComment({ token, reportId, message: message.trim(), reporterName, reporterEmail });
|
|
10958
|
+
await refetch();
|
|
10959
|
+
return true;
|
|
10960
|
+
} catch (e) {
|
|
10961
|
+
setError(e instanceof Error ? e.message : "Failed to post comment");
|
|
10962
|
+
return false;
|
|
10963
|
+
} finally {
|
|
10964
|
+
setIsPosting(false);
|
|
10965
|
+
}
|
|
10966
|
+
},
|
|
10967
|
+
[token, reportId, reporterName, reporterEmail, refetch]
|
|
10968
|
+
);
|
|
10969
|
+
return { report, comments: (_a = report == null ? void 0 : report.comments) != null ? _a : [], isLoading, isFetching, isPosting, error, refetch, addComment };
|
|
10970
|
+
}
|
|
10081
10971
|
|
|
10082
10972
|
// src/use-feedback.ts
|
|
10083
10973
|
var import_react9 = require("react");
|
|
@@ -10159,12 +11049,14 @@ function useGlitchgrabFeedback(query) {
|
|
|
10159
11049
|
computeSignature,
|
|
10160
11050
|
enhanceText,
|
|
10161
11051
|
fetchGlitchgrabFeedback,
|
|
11052
|
+
fetchGlitchgrabReportThread,
|
|
10162
11053
|
fetchGlitchgrabReports,
|
|
10163
11054
|
getAppContext,
|
|
10164
11055
|
getBreadcrumbs,
|
|
10165
11056
|
getShortcutLabel,
|
|
10166
11057
|
initBreadcrumbs,
|
|
10167
11058
|
matchesShortcut,
|
|
11059
|
+
postGlitchgrabReportComment,
|
|
10168
11060
|
sanitizeUrl,
|
|
10169
11061
|
sendFeedback,
|
|
10170
11062
|
sendLead,
|
|
@@ -10175,6 +11067,7 @@ function useGlitchgrabFeedback(query) {
|
|
|
10175
11067
|
useGlitchgrab,
|
|
10176
11068
|
useGlitchgrabActions,
|
|
10177
11069
|
useGlitchgrabFeedback,
|
|
11070
|
+
useGlitchgrabReportThread,
|
|
10178
11071
|
useGlitchgrabReports
|
|
10179
11072
|
});
|
|
10180
11073
|
//# sourceMappingURL=index.js.map
|