glitchgrab 1.58.2 → 1.58.3
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 +4 -0
- package/dist/index.js +1453 -690
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1453 -690
- 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.mjs
CHANGED
|
@@ -178,7 +178,7 @@ function argsToString(args) {
|
|
|
178
178
|
function previewJson(value, max) {
|
|
179
179
|
let out = "";
|
|
180
180
|
const path = /* @__PURE__ */ new WeakSet();
|
|
181
|
-
const
|
|
181
|
+
const write2 = (input, inArray) => {
|
|
182
182
|
if (out.length > max) return;
|
|
183
183
|
let v = input;
|
|
184
184
|
if (v !== null && typeof v === "object" && typeof v.toJSON === "function") {
|
|
@@ -215,7 +215,7 @@ function previewJson(value, max) {
|
|
|
215
215
|
out += "[";
|
|
216
216
|
for (let i = 0; i < obj.length && out.length <= max; i++) {
|
|
217
217
|
if (i > 0) out += ",";
|
|
218
|
-
|
|
218
|
+
write2(obj[i], true);
|
|
219
219
|
}
|
|
220
220
|
out += "]";
|
|
221
221
|
} else {
|
|
@@ -228,13 +228,13 @@ function previewJson(value, max) {
|
|
|
228
228
|
if (child === void 0 || typeof child === "function" || typeof child === "symbol") continue;
|
|
229
229
|
out += `${first ? "" : ","}${JSON.stringify(key)}:`;
|
|
230
230
|
first = false;
|
|
231
|
-
|
|
231
|
+
write2(child, false);
|
|
232
232
|
}
|
|
233
233
|
out += "}";
|
|
234
234
|
}
|
|
235
235
|
path.delete(obj);
|
|
236
236
|
};
|
|
237
|
-
|
|
237
|
+
write2(value, false);
|
|
238
238
|
return out;
|
|
239
239
|
}
|
|
240
240
|
async function readErrorBody(response, url) {
|
|
@@ -895,6 +895,292 @@ function clearDedupCache() {
|
|
|
895
895
|
seen.clear();
|
|
896
896
|
}
|
|
897
897
|
|
|
898
|
+
// src/hydration.ts
|
|
899
|
+
var HYDRATION_CODE_RE = /Minified React error #(418|419|422|423|425)\b/;
|
|
900
|
+
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;
|
|
901
|
+
var BAILOUT_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
|
902
|
+
var DOM_SNIPPET_MAX = 3e3;
|
|
903
|
+
var STACK_FRAMES_MAX = 40;
|
|
904
|
+
function messageOf(error) {
|
|
905
|
+
if (error && typeof error === "object" && typeof error.message === "string") {
|
|
906
|
+
return error.message;
|
|
907
|
+
}
|
|
908
|
+
return typeof error === "string" ? error : "";
|
|
909
|
+
}
|
|
910
|
+
function hydrationCode(message) {
|
|
911
|
+
if (!message) return null;
|
|
912
|
+
const m = HYDRATION_CODE_RE.exec(message);
|
|
913
|
+
if (m) return m[1];
|
|
914
|
+
return HYDRATION_DEV_RE.test(message) ? "dev" : null;
|
|
915
|
+
}
|
|
916
|
+
function isHydrationError(error) {
|
|
917
|
+
if (hydrationCode(messageOf(error))) return true;
|
|
918
|
+
const cause = error && typeof error === "object" ? error.cause : void 0;
|
|
919
|
+
return cause !== void 0 && cause !== error && hydrationCode(messageOf(cause)) !== null;
|
|
920
|
+
}
|
|
921
|
+
function isBailout(error) {
|
|
922
|
+
const e = error;
|
|
923
|
+
if (!e || typeof e !== "object") return false;
|
|
924
|
+
if (e.digest === BAILOUT_DIGEST) return true;
|
|
925
|
+
const c = e.cause;
|
|
926
|
+
return !!c && typeof c === "object" && c.digest === BAILOUT_DIGEST;
|
|
927
|
+
}
|
|
928
|
+
function componentStackNames(stack) {
|
|
929
|
+
if (!stack) return [];
|
|
930
|
+
const names = [];
|
|
931
|
+
for (const raw of stack.split("\n")) {
|
|
932
|
+
const line = raw.trim();
|
|
933
|
+
if (!line) continue;
|
|
934
|
+
let name = "";
|
|
935
|
+
if (line.startsWith("at ")) {
|
|
936
|
+
name = line.slice(3).split(" (")[0].trim();
|
|
937
|
+
} else if (line.includes("@")) {
|
|
938
|
+
name = line.slice(0, line.indexOf("@")).trim();
|
|
939
|
+
} else {
|
|
940
|
+
name = line;
|
|
941
|
+
}
|
|
942
|
+
if (name) names.push(name);
|
|
943
|
+
if (names.length >= STACK_FRAMES_MAX) break;
|
|
944
|
+
}
|
|
945
|
+
return names;
|
|
946
|
+
}
|
|
947
|
+
function componentStackKey(stack) {
|
|
948
|
+
return componentStackNames(stack).join(">");
|
|
949
|
+
}
|
|
950
|
+
var observer = null;
|
|
951
|
+
var observerStarted = false;
|
|
952
|
+
var observerStopAt = 0;
|
|
953
|
+
var OBSERVE_MS = 3e4;
|
|
954
|
+
function startObserver() {
|
|
955
|
+
if (observerStarted || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
956
|
+
return;
|
|
957
|
+
}
|
|
958
|
+
observerStarted = true;
|
|
959
|
+
try {
|
|
960
|
+
observer = new MutationObserver(() => {
|
|
961
|
+
if (Date.now() > observerStopAt) stopObserver();
|
|
962
|
+
});
|
|
963
|
+
observer.observe(document, { childList: true, subtree: true });
|
|
964
|
+
observerStopAt = Date.now() + OBSERVE_MS;
|
|
965
|
+
setTimeout(stopObserver, OBSERVE_MS);
|
|
966
|
+
} catch (e) {
|
|
967
|
+
observer = null;
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
function stopObserver() {
|
|
971
|
+
try {
|
|
972
|
+
observer == null ? void 0 : observer.disconnect();
|
|
973
|
+
} catch (e) {
|
|
974
|
+
}
|
|
975
|
+
observer = null;
|
|
976
|
+
}
|
|
977
|
+
function describeNode(node) {
|
|
978
|
+
if (!node) return "";
|
|
979
|
+
if (node.nodeType === 9) return "#document";
|
|
980
|
+
const el = node;
|
|
981
|
+
if (!el.tagName) return node.nodeName;
|
|
982
|
+
const id = el.id ? `#${el.id}` : "";
|
|
983
|
+
const cls = typeof el.className === "string" && el.className.trim() ? "." + el.className.trim().split(/\s+/).slice(0, 3).join(".") : "";
|
|
984
|
+
return `${el.tagName.toLowerCase()}${id}${cls}`;
|
|
985
|
+
}
|
|
986
|
+
function pathOf(node) {
|
|
987
|
+
const parts = [];
|
|
988
|
+
let cur = node;
|
|
989
|
+
while (cur && parts.length < 6) {
|
|
990
|
+
parts.unshift(describeNode(cur));
|
|
991
|
+
if (cur.nodeType === 9) break;
|
|
992
|
+
cur = cur.parentNode;
|
|
993
|
+
}
|
|
994
|
+
return parts.join(" > ");
|
|
995
|
+
}
|
|
996
|
+
var NON_CONTENT_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "LINK", "META", "NOSCRIPT", "TEMPLATE", "TITLE", "HEAD"]);
|
|
997
|
+
function isInHead(node) {
|
|
998
|
+
for (let cur = node; cur; cur = cur.parentNode) {
|
|
999
|
+
if (cur.nodeName === "HEAD") return true;
|
|
1000
|
+
if (cur.nodeName === "BODY") return false;
|
|
1001
|
+
}
|
|
1002
|
+
return false;
|
|
1003
|
+
}
|
|
1004
|
+
var GSTIN_RE = /\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z0-9]Z[A-Z0-9]\b/g;
|
|
1005
|
+
var PAN_RE = /\b[A-Z]{5}\d{4}[A-Z]\b/g;
|
|
1006
|
+
function scrubHtml(html) {
|
|
1007
|
+
return redactString(
|
|
1008
|
+
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)))
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
function takeRemovedServerHtml() {
|
|
1012
|
+
var _a, _b;
|
|
1013
|
+
if (!observer) return { html: "", where: "" };
|
|
1014
|
+
try {
|
|
1015
|
+
const records = observer.takeRecords();
|
|
1016
|
+
let html = "";
|
|
1017
|
+
let where = "";
|
|
1018
|
+
for (const rec of records) {
|
|
1019
|
+
if (rec.type !== "childList" || rec.removedNodes.length === 0) continue;
|
|
1020
|
+
if (isInHead(rec.target)) continue;
|
|
1021
|
+
if (!where) where = pathOf(rec.target);
|
|
1022
|
+
for (const node of Array.from(rec.removedNodes)) {
|
|
1023
|
+
if (node.nodeType === 1 && NON_CONTENT_TAGS.has(node.tagName)) continue;
|
|
1024
|
+
if (node.nodeType === 3 && !((_a = node.textContent) != null ? _a : "").trim()) continue;
|
|
1025
|
+
const piece = node.nodeType === 1 ? node.outerHTML : node.nodeType === 3 ? `#text "${(_b = node.textContent) != null ? _b : ""}"` : "";
|
|
1026
|
+
if (!piece) continue;
|
|
1027
|
+
html += (html ? "\n" : "") + piece;
|
|
1028
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1029
|
+
}
|
|
1030
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1031
|
+
}
|
|
1032
|
+
const scrubbed = scrubHtml(html);
|
|
1033
|
+
return {
|
|
1034
|
+
html: scrubbed.length > DOM_SNIPPET_MAX ? `${scrubbed.slice(0, DOM_SNIPPET_MAX)}\u2026[truncated]` : scrubbed,
|
|
1035
|
+
where
|
|
1036
|
+
};
|
|
1037
|
+
} catch (e) {
|
|
1038
|
+
return { html: "", where: "" };
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
function detectForeignNodes(doc = document) {
|
|
1042
|
+
var _a;
|
|
1043
|
+
const found = [];
|
|
1044
|
+
try {
|
|
1045
|
+
const html = doc.documentElement;
|
|
1046
|
+
if ((html == null ? void 0 : html.classList.contains("translated-ltr")) || (html == null ? void 0 : html.classList.contains("translated-rtl"))) {
|
|
1047
|
+
found.push("Google Translate is active (html.translated-*)");
|
|
1048
|
+
}
|
|
1049
|
+
const fonts = doc.getElementsByTagName("font").length;
|
|
1050
|
+
if (fonts > 0) found.push(`<font> \xD7 ${fonts} (Google Translate or a translation extension)`);
|
|
1051
|
+
const detectors = doc.querySelectorAll("a[x-apple-data-detectors]").length;
|
|
1052
|
+
if (detectors > 0) {
|
|
1053
|
+
found.push(`<a x-apple-data-detectors> \xD7 ${detectors} (iOS format detection turned text into links)`);
|
|
1054
|
+
}
|
|
1055
|
+
if (doc.querySelector("[data-gr-ext-installed],[data-new-gr-c-s-check-loaded],grammarly-desktop-integration")) {
|
|
1056
|
+
found.push("Grammarly extension attributes");
|
|
1057
|
+
}
|
|
1058
|
+
if (doc.querySelector("[data-lt-installed]")) found.push("LanguageTool extension attributes");
|
|
1059
|
+
if ((_a = doc.body) == null ? void 0 : _a.hasAttribute("cz-shortcut-listen")) found.push("ColorZilla extension attribute on <body>");
|
|
1060
|
+
const custom = /* @__PURE__ */ new Set();
|
|
1061
|
+
for (const parent of [html, doc.body]) {
|
|
1062
|
+
if (!parent) continue;
|
|
1063
|
+
for (const child of Array.from(parent.children)) {
|
|
1064
|
+
const tag = child.tagName.toLowerCase();
|
|
1065
|
+
if (tag.includes("-")) custom.add(tag);
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
if (custom.size > 0) {
|
|
1069
|
+
found.push(`custom elements at top level: ${Array.from(custom).slice(0, 5).join(", ")} (often an extension)`);
|
|
1070
|
+
}
|
|
1071
|
+
} catch (e) {
|
|
1072
|
+
}
|
|
1073
|
+
return found;
|
|
1074
|
+
}
|
|
1075
|
+
function hydrationTiming() {
|
|
1076
|
+
var _a, _b, _c, _d;
|
|
1077
|
+
try {
|
|
1078
|
+
if (typeof performance === "undefined") return "";
|
|
1079
|
+
const at2 = Math.round(performance.now());
|
|
1080
|
+
const parts = [`error at ${at2}ms after navigation start`];
|
|
1081
|
+
const nav = (_b = (_a = performance.getEntriesByType) == null ? void 0 : _a.call(performance, "navigation")) == null ? void 0 : _b[0];
|
|
1082
|
+
if (nav == null ? void 0 : nav.domContentLoadedEventEnd) {
|
|
1083
|
+
parts.push(`DOMContentLoaded ${Math.round(nav.domContentLoadedEventEnd)}ms`);
|
|
1084
|
+
}
|
|
1085
|
+
const fetches = ((_d = (_c = performance.getEntriesByType) == null ? void 0 : _c.call(performance, "resource")) != null ? _d : []).filter((e) => {
|
|
1086
|
+
const t = e.initiatorType;
|
|
1087
|
+
return t === "fetch" || t === "xmlhttprequest";
|
|
1088
|
+
}).sort((a, b) => a.responseEnd - b.responseEnd).slice(0, 8).map((e) => {
|
|
1089
|
+
let path = e.name;
|
|
1090
|
+
try {
|
|
1091
|
+
const u = new URL(e.name);
|
|
1092
|
+
path = u.origin === window.location.origin ? u.pathname : `${u.host}${u.pathname}`;
|
|
1093
|
+
} catch (e2) {
|
|
1094
|
+
}
|
|
1095
|
+
return `${path} ${Math.round(e.responseEnd)}ms`;
|
|
1096
|
+
});
|
|
1097
|
+
if (fetches.length > 0) parts.push(`fetches finished before it: ${fetches.join(", ")}`);
|
|
1098
|
+
else parts.push("no fetch had finished yet");
|
|
1099
|
+
return parts.join("; ");
|
|
1100
|
+
} catch (e) {
|
|
1101
|
+
return "";
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
function hydrationMetadata(error, extra) {
|
|
1105
|
+
var _a, _b, _c;
|
|
1106
|
+
const code = (_a = hydrationCode(messageOf(error))) != null ? _a : hydrationCode(messageOf(error == null ? void 0 : error.cause));
|
|
1107
|
+
const meta = { errorKind: "hydration" };
|
|
1108
|
+
if (code) meta.hydrationCode = code;
|
|
1109
|
+
const cause = error == null ? void 0 : error.cause;
|
|
1110
|
+
if (cause && cause !== error && messageOf(cause)) {
|
|
1111
|
+
meta.hydrationCause = messageOf(cause).slice(0, 500);
|
|
1112
|
+
}
|
|
1113
|
+
if ((_b = extra == null ? void 0 : extra.removed) == null ? void 0 : _b.html) meta.hydrationServerHtml = extra.removed.html;
|
|
1114
|
+
if ((_c = extra == null ? void 0 : extra.removed) == null ? void 0 : _c.where) meta.hydrationReplacedIn = extra.removed.where;
|
|
1115
|
+
const foreign = detectForeignNodes();
|
|
1116
|
+
if (foreign.length > 0) meta.hydrationForeignNodes = foreign.join("\n");
|
|
1117
|
+
const timing = hydrationTiming();
|
|
1118
|
+
if (timing) meta.hydrationTiming = timing;
|
|
1119
|
+
return meta;
|
|
1120
|
+
}
|
|
1121
|
+
var handled = /* @__PURE__ */ new WeakSet();
|
|
1122
|
+
function isHandledHydrationError(error) {
|
|
1123
|
+
return !!error && typeof error === "object" && handled.has(error);
|
|
1124
|
+
}
|
|
1125
|
+
function markHandled(error) {
|
|
1126
|
+
if (error && typeof error === "object") {
|
|
1127
|
+
handled.add(error);
|
|
1128
|
+
const cause = error.cause;
|
|
1129
|
+
if (cause && typeof cause === "object") handled.add(cause);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
var reporter = null;
|
|
1133
|
+
var PATCHED = "__glitchgrabHydrationPatched";
|
|
1134
|
+
function findFiberRoot(container) {
|
|
1135
|
+
if (!container || typeof container !== "object") return null;
|
|
1136
|
+
try {
|
|
1137
|
+
const key = Object.keys(container).find((k) => k.startsWith("__reactContainer$"));
|
|
1138
|
+
if (!key) return null;
|
|
1139
|
+
const hostRoot = container[key];
|
|
1140
|
+
const root = hostRoot == null ? void 0 : hostRoot.stateNode;
|
|
1141
|
+
return root && typeof root === "object" ? root : null;
|
|
1142
|
+
} catch (e) {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
function patchRoot(root) {
|
|
1147
|
+
if (root[PATCHED]) return true;
|
|
1148
|
+
const original = root.onRecoverableError;
|
|
1149
|
+
if (typeof original !== "function") return false;
|
|
1150
|
+
root.onRecoverableError = function glitchgrabOnRecoverableError(error, info) {
|
|
1151
|
+
var _a;
|
|
1152
|
+
try {
|
|
1153
|
+
if (reporter && isHydrationError(error) && !isBailout(error)) {
|
|
1154
|
+
const removed = takeRemovedServerHtml();
|
|
1155
|
+
markHandled(error);
|
|
1156
|
+
reporter(error, (_a = info == null ? void 0 : info.componentStack) != null ? _a : "", hydrationMetadata(error, { removed }));
|
|
1157
|
+
}
|
|
1158
|
+
} catch (e) {
|
|
1159
|
+
}
|
|
1160
|
+
return original.call(this, error, info);
|
|
1161
|
+
};
|
|
1162
|
+
root[PATCHED] = true;
|
|
1163
|
+
return true;
|
|
1164
|
+
}
|
|
1165
|
+
function patchKnownRoots() {
|
|
1166
|
+
if (typeof document === "undefined") return false;
|
|
1167
|
+
let patched = false;
|
|
1168
|
+
for (const container of [document, document.getElementById("__next"), document.getElementById("root")]) {
|
|
1169
|
+
const root = findFiberRoot(container);
|
|
1170
|
+
if (root && patchRoot(root)) patched = true;
|
|
1171
|
+
}
|
|
1172
|
+
return patched;
|
|
1173
|
+
}
|
|
1174
|
+
function installHydrationCapture(report) {
|
|
1175
|
+
try {
|
|
1176
|
+
if (typeof window === "undefined") return;
|
|
1177
|
+
reporter = report;
|
|
1178
|
+
startObserver();
|
|
1179
|
+
patchKnownRoots();
|
|
1180
|
+
} catch (e) {
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
898
1184
|
// src/capture.ts
|
|
899
1185
|
var config = null;
|
|
900
1186
|
function registerCaptureConfig(next) {
|
|
@@ -914,7 +1200,7 @@ function sessionMetadata(session) {
|
|
|
914
1200
|
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {}
|
|
915
1201
|
};
|
|
916
1202
|
}
|
|
917
|
-
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError") {
|
|
1203
|
+
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError", dedupKey) {
|
|
918
1204
|
var _a, _b, _c;
|
|
919
1205
|
const err = error instanceof Error ? error : void 0;
|
|
920
1206
|
const errorMessage = err ? err.message : String(error);
|
|
@@ -926,7 +1212,7 @@ function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureErr
|
|
|
926
1212
|
const sig = computeSignature({
|
|
927
1213
|
errorMessage,
|
|
928
1214
|
pageUrl: context.url,
|
|
929
|
-
errorStack: err == null ? void 0 : err.stack,
|
|
1215
|
+
errorStack: dedupKey ? `at ${dedupKey}` : err == null ? void 0 : err.stack,
|
|
930
1216
|
digest
|
|
931
1217
|
});
|
|
932
1218
|
if (shouldSkipDuplicate(sig)) return null;
|
|
@@ -966,6 +1252,25 @@ function captureError(error, options) {
|
|
|
966
1252
|
} catch (e) {
|
|
967
1253
|
}
|
|
968
1254
|
}
|
|
1255
|
+
function reportHydrationError(error, componentStack, metadata) {
|
|
1256
|
+
try {
|
|
1257
|
+
const cfg = config;
|
|
1258
|
+
if (!(cfg == null ? void 0 : cfg.token)) return;
|
|
1259
|
+
const payload = buildCapturedErrorPayload(
|
|
1260
|
+
error,
|
|
1261
|
+
{ componentStack: componentStack || void 0, metadata },
|
|
1262
|
+
cfg,
|
|
1263
|
+
"onRecoverableError",
|
|
1264
|
+
componentStackKey(componentStack) || void 0
|
|
1265
|
+
);
|
|
1266
|
+
if (!payload) return;
|
|
1267
|
+
void sendReport(payload, cfg.baseUrl).then((result) => {
|
|
1268
|
+
if (result && cfg.onReportSent) cfg.onReportSent(result);
|
|
1269
|
+
});
|
|
1270
|
+
if (cfg.onError && error instanceof Error) cfg.onError(error);
|
|
1271
|
+
} catch (e) {
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
969
1274
|
|
|
970
1275
|
// src/error-boundary.tsx
|
|
971
1276
|
var GlitchgrabErrorBoundary = class extends React.Component {
|
|
@@ -1892,6 +2197,79 @@ function renderBlocks(lines, theme, key) {
|
|
|
1892
2197
|
function ChatMarkdown({ text, theme }) {
|
|
1893
2198
|
return /* @__PURE__ */ jsx2("div", { style: STACK, children: renderBlocks(text.replace(/\r\n?/g, "\n").split("\n"), theme, "md") });
|
|
1894
2199
|
}
|
|
2200
|
+
var MAX_SAVED_CHATS = 20;
|
|
2201
|
+
var SAVED_CHAT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
2202
|
+
var TITLE_CHARS = 80;
|
|
2203
|
+
var PREFIX = "glitchgrab:ai-chats:";
|
|
2204
|
+
function chatHistoryKey(...parts) {
|
|
2205
|
+
const input = parts.map((p) => p != null ? p : "").join("\0");
|
|
2206
|
+
let hash = 2166136261;
|
|
2207
|
+
for (let i = 0; i < input.length; i++) {
|
|
2208
|
+
hash ^= input.charCodeAt(i);
|
|
2209
|
+
hash = Math.imul(hash, 16777619);
|
|
2210
|
+
}
|
|
2211
|
+
return (hash >>> 0).toString(36);
|
|
2212
|
+
}
|
|
2213
|
+
function chatTitle(messages) {
|
|
2214
|
+
var _a, _b;
|
|
2215
|
+
const first = (_b = (_a = messages.find((m) => m.role === "user")) == null ? void 0 : _a.content.trim()) != null ? _b : "";
|
|
2216
|
+
const line = first.replace(/\s+/g, " ");
|
|
2217
|
+
return line.length > TITLE_CHARS ? `${line.slice(0, TITLE_CHARS - 1)}\u2026` : line;
|
|
2218
|
+
}
|
|
2219
|
+
function storage() {
|
|
2220
|
+
try {
|
|
2221
|
+
return typeof window !== "undefined" && window.localStorage ? window.localStorage : null;
|
|
2222
|
+
} catch (e) {
|
|
2223
|
+
return null;
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
function isSavedChat(value) {
|
|
2227
|
+
if (!value || typeof value !== "object") return false;
|
|
2228
|
+
const c = value;
|
|
2229
|
+
return typeof c.id === "string" && typeof c.title === "string" && typeof c.updatedAt === "number" && (c.status === "open" || c.status === "filed") && Array.isArray(c.messages);
|
|
2230
|
+
}
|
|
2231
|
+
function loadChats(key, now = Date.now()) {
|
|
2232
|
+
const store = storage();
|
|
2233
|
+
if (!store) return [];
|
|
2234
|
+
try {
|
|
2235
|
+
const raw = store.getItem(PREFIX + key);
|
|
2236
|
+
if (!raw) return [];
|
|
2237
|
+
const parsed = JSON.parse(raw);
|
|
2238
|
+
if (!Array.isArray(parsed)) return [];
|
|
2239
|
+
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);
|
|
2240
|
+
} catch (e) {
|
|
2241
|
+
return [];
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
function write(key, chats) {
|
|
2245
|
+
const store = storage();
|
|
2246
|
+
if (!store) return;
|
|
2247
|
+
try {
|
|
2248
|
+
if (chats.length === 0) store.removeItem(PREFIX + key);
|
|
2249
|
+
else store.setItem(PREFIX + key, JSON.stringify(chats));
|
|
2250
|
+
} catch (e) {
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
function saveChat(key, chat, now = Date.now()) {
|
|
2254
|
+
const rest = loadChats(key, now).filter((c) => c.id !== chat.id);
|
|
2255
|
+
const next = [chat, ...rest].slice(0, MAX_SAVED_CHATS);
|
|
2256
|
+
write(key, next);
|
|
2257
|
+
return next;
|
|
2258
|
+
}
|
|
2259
|
+
function markChatFiled(key, conversationId, label, now = Date.now()) {
|
|
2260
|
+
const chats = loadChats(key, now);
|
|
2261
|
+
const hit = chats.find((c) => c.conversationId === conversationId);
|
|
2262
|
+
if (!hit || hit.status === "filed") return;
|
|
2263
|
+
write(
|
|
2264
|
+
key,
|
|
2265
|
+
chats.map((c) => c === hit ? { ...c, status: "filed", filedLabel: label, updatedAt: now } : c)
|
|
2266
|
+
);
|
|
2267
|
+
}
|
|
2268
|
+
function removeChat(key, id, now = Date.now()) {
|
|
2269
|
+
const next = loadChats(key, now).filter((c) => c.id !== id);
|
|
2270
|
+
write(key, next);
|
|
2271
|
+
return next;
|
|
2272
|
+
}
|
|
1895
2273
|
function pickAssistImages(all) {
|
|
1896
2274
|
const picked = [];
|
|
1897
2275
|
let total = 0;
|
|
@@ -1918,6 +2296,18 @@ function pickAssistFiles(files) {
|
|
|
1918
2296
|
}
|
|
1919
2297
|
return picked;
|
|
1920
2298
|
}
|
|
2299
|
+
function newChatId() {
|
|
2300
|
+
return `local-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
|
2301
|
+
}
|
|
2302
|
+
function chatAge(at2, now = Date.now()) {
|
|
2303
|
+
const min = Math.round((now - at2) / 6e4);
|
|
2304
|
+
if (min < 1) return "just now";
|
|
2305
|
+
if (min < 60) return `${min} min ago`;
|
|
2306
|
+
const hours = Math.round(min / 60);
|
|
2307
|
+
if (hours < 24) return `${hours} h ago`;
|
|
2308
|
+
if (hours < 48) return "yesterday";
|
|
2309
|
+
return new Date(at2).toLocaleDateString(void 0, { day: "numeric", month: "short" });
|
|
2310
|
+
}
|
|
1921
2311
|
var STARTERS = [
|
|
1922
2312
|
"Something on this page is broken",
|
|
1923
2313
|
"It did the wrong thing",
|
|
@@ -2000,6 +2390,33 @@ function Avatar({
|
|
|
2000
2390
|
}
|
|
2001
2391
|
);
|
|
2002
2392
|
}
|
|
2393
|
+
var THINKING_SLOW_SECONDS = 20;
|
|
2394
|
+
function ThinkingClock({ color }) {
|
|
2395
|
+
const [seconds, setSeconds] = useState2(0);
|
|
2396
|
+
useEffect2(() => {
|
|
2397
|
+
const started = Date.now();
|
|
2398
|
+
const id = setInterval(() => setSeconds(Math.floor((Date.now() - started) / 1e3)), 1e3);
|
|
2399
|
+
return () => clearInterval(id);
|
|
2400
|
+
}, []);
|
|
2401
|
+
return (
|
|
2402
|
+
// Hidden from screen readers: the bubble already says "Thinking", and a
|
|
2403
|
+
// number changing every second would be read out every second.
|
|
2404
|
+
/* @__PURE__ */ jsxs3(
|
|
2405
|
+
"span",
|
|
2406
|
+
{
|
|
2407
|
+
"data-gg-thinking-clock": "",
|
|
2408
|
+
"aria-hidden": "true",
|
|
2409
|
+
style: { marginLeft: "6px", fontSize: "12px", color, fontVariantNumeric: "tabular-nums" },
|
|
2410
|
+
children: [
|
|
2411
|
+
"Thinking\u2026 ",
|
|
2412
|
+
seconds,
|
|
2413
|
+
"s",
|
|
2414
|
+
seconds >= THINKING_SLOW_SECONDS ? " \xB7 taking longer than usual, still working" : ""
|
|
2415
|
+
]
|
|
2416
|
+
}
|
|
2417
|
+
)
|
|
2418
|
+
);
|
|
2419
|
+
}
|
|
2003
2420
|
function AssistSheet({
|
|
2004
2421
|
assist,
|
|
2005
2422
|
theme: t,
|
|
@@ -2040,14 +2457,22 @@ function AssistSheet({
|
|
|
2040
2457
|
onDegrade,
|
|
2041
2458
|
onClose,
|
|
2042
2459
|
onFinish,
|
|
2043
|
-
onReportGlitchgrabProblem
|
|
2460
|
+
onReportGlitchgrabProblem,
|
|
2461
|
+
historyKey = null
|
|
2044
2462
|
}) {
|
|
2463
|
+
var _a;
|
|
2045
2464
|
const narrow = useIsNarrow();
|
|
2046
2465
|
const severityAsked = showSeverity && currentTile === "BUG";
|
|
2047
2466
|
const [messages, setMessages] = useState2([]);
|
|
2048
2467
|
const [input, setInput] = useState2("");
|
|
2049
2468
|
const [busy, setBusy] = useState2(false);
|
|
2050
2469
|
const [conversationId, setConversationId] = useState2(null);
|
|
2470
|
+
const chatIdRef = useRef2(newChatId());
|
|
2471
|
+
const [savedChats, setSavedChats] = useState2(
|
|
2472
|
+
() => historyKey ? loadChats(historyKey) : []
|
|
2473
|
+
);
|
|
2474
|
+
const [showChats, setShowChats] = useState2(false);
|
|
2475
|
+
const [viewingChat, setViewingChat] = useState2(null);
|
|
2051
2476
|
const [hoveredStar, setHoveredStar] = useState2(0);
|
|
2052
2477
|
const [options, setOptions] = useState2([]);
|
|
2053
2478
|
const [duplicate, setDuplicate] = useState2(null);
|
|
@@ -2099,8 +2524,8 @@ function AssistSheet({
|
|
|
2099
2524
|
if (el) el.scrollTop = el.scrollHeight;
|
|
2100
2525
|
}, [messages, busy, phase]);
|
|
2101
2526
|
useEffect2(() => {
|
|
2102
|
-
var
|
|
2103
|
-
if (phase === "draft") (
|
|
2527
|
+
var _a2;
|
|
2528
|
+
if (phase === "draft") (_a2 = draftRef.current) == null ? void 0 : _a2.focus();
|
|
2104
2529
|
}, [phase]);
|
|
2105
2530
|
useEffect2(() => {
|
|
2106
2531
|
const el = composerRef.current;
|
|
@@ -2132,7 +2557,8 @@ function AssistSheet({
|
|
|
2132
2557
|
onDegrade(message, retryable);
|
|
2133
2558
|
}
|
|
2134
2559
|
async function runTurn(history2, autoFile = false) {
|
|
2135
|
-
var
|
|
2560
|
+
var _a2, _b, _c;
|
|
2561
|
+
const turnChat = chatIdRef.current;
|
|
2136
2562
|
setBusy(true);
|
|
2137
2563
|
setAutoFileLeft(null);
|
|
2138
2564
|
let result;
|
|
@@ -2169,6 +2595,7 @@ function AssistSheet({
|
|
|
2169
2595
|
} finally {
|
|
2170
2596
|
setBusy(false);
|
|
2171
2597
|
}
|
|
2598
|
+
if (chatIdRef.current !== turnChat) return;
|
|
2172
2599
|
if (result.degraded) {
|
|
2173
2600
|
degradeKeepingEvents(events, result.degraded, result.retryable === true);
|
|
2174
2601
|
return;
|
|
@@ -2179,7 +2606,7 @@ function AssistSheet({
|
|
|
2179
2606
|
}
|
|
2180
2607
|
const attach = result.duplicate ? { ...result.duplicate, kind: "duplicate" } : result.related ? { ...result.related, kind: "related" } : null;
|
|
2181
2608
|
setDuplicate(attach);
|
|
2182
|
-
onDuplicateChange == null ? void 0 : onDuplicateChange((
|
|
2609
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange((_a2 = attach == null ? void 0 : attach.number) != null ? _a2 : null, attach == null ? void 0 : attach.kind);
|
|
2183
2610
|
setGlitchgrabOffer(!!result.aboutGlitchgrab && !!onReportGlitchgrabProblem && !!result.question);
|
|
2184
2611
|
if (result.solved) {
|
|
2185
2612
|
setSolved(result.solved);
|
|
@@ -2233,9 +2660,9 @@ function AssistSheet({
|
|
|
2233
2660
|
}
|
|
2234
2661
|
}
|
|
2235
2662
|
function sendTyped(text) {
|
|
2236
|
-
var
|
|
2663
|
+
var _a2;
|
|
2237
2664
|
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
|
2238
|
-
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((
|
|
2665
|
+
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((_a2 = lastAssistant == null ? void 0 : lastAssistant.content) != null ? _a2 : "");
|
|
2239
2666
|
send(text, checkingBack && isAffirmativeReply(text));
|
|
2240
2667
|
}
|
|
2241
2668
|
function send(text, autoFile = false) {
|
|
@@ -2277,7 +2704,215 @@ function AssistSheet({
|
|
|
2277
2704
|
flushEvents();
|
|
2278
2705
|
onSend();
|
|
2279
2706
|
}
|
|
2707
|
+
useEffect2(() => {
|
|
2708
|
+
if (!historyKey || !messages.some((m) => m.role === "user")) return;
|
|
2709
|
+
const done = submitted || phase === "solved";
|
|
2710
|
+
const kept = submitted || phase === "draft" ? withCurrentDraft(messages) : messages;
|
|
2711
|
+
setSavedChats(
|
|
2712
|
+
saveChat(historyKey, {
|
|
2713
|
+
id: chatIdRef.current,
|
|
2714
|
+
conversationId,
|
|
2715
|
+
title: chatTitle(kept),
|
|
2716
|
+
tile: currentTile,
|
|
2717
|
+
messages: kept,
|
|
2718
|
+
...issueTitle ? { issueTitle } : {},
|
|
2719
|
+
status: done ? "filed" : "open",
|
|
2720
|
+
...done ? {
|
|
2721
|
+
filedLabel: submitted ? submittedText != null ? submittedText : `${reportTypeLabel} sent` : "Answered \u2014 nothing was filed"
|
|
2722
|
+
} : {},
|
|
2723
|
+
updatedAt: Date.now()
|
|
2724
|
+
})
|
|
2725
|
+
);
|
|
2726
|
+
}, [
|
|
2727
|
+
historyKey,
|
|
2728
|
+
messages,
|
|
2729
|
+
conversationId,
|
|
2730
|
+
submitted,
|
|
2731
|
+
phase === "solved",
|
|
2732
|
+
issueTitle,
|
|
2733
|
+
phase === "draft" ? description : null
|
|
2734
|
+
]);
|
|
2735
|
+
function resumeChat(chat) {
|
|
2736
|
+
var _a2;
|
|
2737
|
+
flushEvents();
|
|
2738
|
+
chatIdRef.current = chat.id;
|
|
2739
|
+
setMessages(chat.messages);
|
|
2740
|
+
setConversationId(chat.conversationId);
|
|
2741
|
+
onConversationChange == null ? void 0 : onConversationChange(chat.conversationId);
|
|
2742
|
+
setOptions([]);
|
|
2743
|
+
setDuplicate(null);
|
|
2744
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2745
|
+
setGlitchgrabOffer(false);
|
|
2746
|
+
setAutoFileLeft(null);
|
|
2747
|
+
setInput("");
|
|
2748
|
+
if (chat.tile !== currentTile && tiles.includes(chat.tile)) {
|
|
2749
|
+
onPickType(chat.tile);
|
|
2750
|
+
}
|
|
2751
|
+
const last = chat.messages[chat.messages.length - 1];
|
|
2752
|
+
if ((last == null ? void 0 : last.kind) === "report") {
|
|
2753
|
+
onDescriptionChange(last.content);
|
|
2754
|
+
onIssueTitleChange((_a2 = chat.issueTitle) != null ? _a2 : "");
|
|
2755
|
+
aiDraftRef.current = last.content;
|
|
2756
|
+
setPhase("draft");
|
|
2757
|
+
} else {
|
|
2758
|
+
setPhase("chat");
|
|
2759
|
+
}
|
|
2760
|
+
setShowChats(false);
|
|
2761
|
+
setViewingChat(null);
|
|
2762
|
+
}
|
|
2763
|
+
function startNewChat() {
|
|
2764
|
+
flushEvents();
|
|
2765
|
+
chatIdRef.current = newChatId();
|
|
2766
|
+
setMessages([]);
|
|
2767
|
+
setConversationId(null);
|
|
2768
|
+
onConversationChange == null ? void 0 : onConversationChange(null);
|
|
2769
|
+
setOptions([]);
|
|
2770
|
+
setDuplicate(null);
|
|
2771
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2772
|
+
setGlitchgrabOffer(false);
|
|
2773
|
+
setAutoFileLeft(null);
|
|
2774
|
+
setInput("");
|
|
2775
|
+
onDescriptionChange("");
|
|
2776
|
+
onIssueTitleChange("");
|
|
2777
|
+
aiDraftRef.current = null;
|
|
2778
|
+
setPhase("chat");
|
|
2779
|
+
setShowChats(false);
|
|
2780
|
+
setViewingChat(null);
|
|
2781
|
+
}
|
|
2782
|
+
function forgetChat(id) {
|
|
2783
|
+
if (!historyKey) return;
|
|
2784
|
+
setSavedChats(removeChat(historyKey, id));
|
|
2785
|
+
if (viewingChat === id) setViewingChat(null);
|
|
2786
|
+
}
|
|
2787
|
+
const otherChats = savedChats.filter((c) => c.id !== chatIdRef.current);
|
|
2788
|
+
const resumable = (_a = otherChats.find((c) => c.status === "open" && c.messages.length > 0)) != null ? _a : null;
|
|
2280
2789
|
const empty = phase === "chat" && messages.length === 0 && !busy;
|
|
2790
|
+
function renderChatList() {
|
|
2791
|
+
return /* @__PURE__ */ jsxs3("div", { "data-gg-chat-list": "", style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
2792
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
2793
|
+
/* @__PURE__ */ jsx3("span", { style: { fontSize: "13px", fontWeight: 600 }, children: "Your chats" }),
|
|
2794
|
+
messages.length > 0 && /* @__PURE__ */ jsx3(
|
|
2795
|
+
"button",
|
|
2796
|
+
{
|
|
2797
|
+
type: "button",
|
|
2798
|
+
"data-gg-new-chat": "",
|
|
2799
|
+
onClick: startNewChat,
|
|
2800
|
+
style: {
|
|
2801
|
+
border: `1px solid ${t.inputBorder}`,
|
|
2802
|
+
borderRadius: "999px",
|
|
2803
|
+
background: "transparent",
|
|
2804
|
+
color: t.text,
|
|
2805
|
+
padding: "7px 12px",
|
|
2806
|
+
fontSize: "12px",
|
|
2807
|
+
fontFamily: "inherit",
|
|
2808
|
+
cursor: "pointer"
|
|
2809
|
+
},
|
|
2810
|
+
children: "+ New chat"
|
|
2811
|
+
}
|
|
2812
|
+
)
|
|
2813
|
+
] }),
|
|
2814
|
+
/* @__PURE__ */ jsx3("span", { style: { fontSize: "11.5px", color: t.textMuted, lineHeight: 1.5 }, children: "Kept in this browser only, for 30 days." }),
|
|
2815
|
+
otherChats.length === 0 && /* @__PURE__ */ jsx3("span", { style: { fontSize: "12.5px", color: t.textMuted, padding: "12px 0" }, children: "No other chats yet." }),
|
|
2816
|
+
otherChats.map((chat) => {
|
|
2817
|
+
var _a2;
|
|
2818
|
+
const filed = chat.status === "filed";
|
|
2819
|
+
const open = viewingChat === chat.id;
|
|
2820
|
+
return /* @__PURE__ */ jsxs3(
|
|
2821
|
+
"div",
|
|
2822
|
+
{
|
|
2823
|
+
"data-gg-saved-chat": chat.status,
|
|
2824
|
+
style: {
|
|
2825
|
+
border: `1px solid ${t.border}`,
|
|
2826
|
+
borderRadius: "10px",
|
|
2827
|
+
padding: "10px 12px",
|
|
2828
|
+
display: "flex",
|
|
2829
|
+
flexDirection: "column",
|
|
2830
|
+
gap: "6px",
|
|
2831
|
+
minWidth: 0
|
|
2832
|
+
},
|
|
2833
|
+
children: [
|
|
2834
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", alignItems: "flex-start", minWidth: 0 }, children: [
|
|
2835
|
+
/* @__PURE__ */ jsxs3(
|
|
2836
|
+
"button",
|
|
2837
|
+
{
|
|
2838
|
+
type: "button",
|
|
2839
|
+
onClick: () => filed ? setViewingChat(open ? null : chat.id) : resumeChat(chat),
|
|
2840
|
+
style: {
|
|
2841
|
+
flex: 1,
|
|
2842
|
+
minWidth: 0,
|
|
2843
|
+
textAlign: "left",
|
|
2844
|
+
border: "none",
|
|
2845
|
+
background: "transparent",
|
|
2846
|
+
color: t.text,
|
|
2847
|
+
padding: 0,
|
|
2848
|
+
fontFamily: "inherit",
|
|
2849
|
+
cursor: "pointer",
|
|
2850
|
+
display: "flex",
|
|
2851
|
+
flexDirection: "column",
|
|
2852
|
+
gap: "4px"
|
|
2853
|
+
},
|
|
2854
|
+
children: [
|
|
2855
|
+
/* @__PURE__ */ jsx3("span", { style: { fontSize: "13px", lineHeight: 1.45, overflowWrap: "anywhere" }, children: chat.title || "Untitled chat" }),
|
|
2856
|
+
/* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
2857
|
+
filed ? (_a2 = chat.filedLabel) != null ? _a2 : "Sent" : "Not sent yet \u2014 tap to continue",
|
|
2858
|
+
" \xB7",
|
|
2859
|
+
" ",
|
|
2860
|
+
chatAge(chat.updatedAt)
|
|
2861
|
+
] })
|
|
2862
|
+
]
|
|
2863
|
+
}
|
|
2864
|
+
),
|
|
2865
|
+
/* @__PURE__ */ jsx3(
|
|
2866
|
+
"button",
|
|
2867
|
+
{
|
|
2868
|
+
type: "button",
|
|
2869
|
+
"aria-label": `Delete chat: ${chat.title}`,
|
|
2870
|
+
onClick: () => forgetChat(chat.id),
|
|
2871
|
+
style: {
|
|
2872
|
+
flexShrink: 0,
|
|
2873
|
+
border: "none",
|
|
2874
|
+
background: "transparent",
|
|
2875
|
+
color: t.textMuted,
|
|
2876
|
+
fontSize: "16px",
|
|
2877
|
+
lineHeight: 1,
|
|
2878
|
+
padding: "4px 6px",
|
|
2879
|
+
cursor: "pointer",
|
|
2880
|
+
fontFamily: "inherit"
|
|
2881
|
+
},
|
|
2882
|
+
children: "\xD7"
|
|
2883
|
+
}
|
|
2884
|
+
)
|
|
2885
|
+
] }),
|
|
2886
|
+
open && /* @__PURE__ */ jsx3(
|
|
2887
|
+
"div",
|
|
2888
|
+
{
|
|
2889
|
+
"data-gg-saved-transcript": "",
|
|
2890
|
+
style: {
|
|
2891
|
+
display: "flex",
|
|
2892
|
+
flexDirection: "column",
|
|
2893
|
+
gap: "6px",
|
|
2894
|
+
borderTop: `1px solid ${t.border}`,
|
|
2895
|
+
paddingTop: "8px",
|
|
2896
|
+
fontSize: "12.5px",
|
|
2897
|
+
lineHeight: 1.5
|
|
2898
|
+
},
|
|
2899
|
+
children: chat.messages.map((m, i) => /* @__PURE__ */ jsxs3("div", { style: { minWidth: 0, overflowWrap: "anywhere" }, children: [
|
|
2900
|
+
/* @__PURE__ */ jsxs3("span", { style: { color: t.textMuted, fontWeight: 600 }, children: [
|
|
2901
|
+
m.role === "user" ? "You" : m.kind === "report" ? "Report" : "Assistant",
|
|
2902
|
+
":",
|
|
2903
|
+
" "
|
|
2904
|
+
] }),
|
|
2905
|
+
/* @__PURE__ */ jsx3("span", { style: { whiteSpace: "pre-wrap" }, children: m.content })
|
|
2906
|
+
] }, i))
|
|
2907
|
+
}
|
|
2908
|
+
)
|
|
2909
|
+
]
|
|
2910
|
+
},
|
|
2911
|
+
chat.id
|
|
2912
|
+
);
|
|
2913
|
+
})
|
|
2914
|
+
] });
|
|
2915
|
+
}
|
|
2281
2916
|
function renderKnownIssue({ title, footer }) {
|
|
2282
2917
|
if (!duplicate) return null;
|
|
2283
2918
|
return /* @__PURE__ */ jsxs3(
|
|
@@ -2311,8 +2946,8 @@ function AssistSheet({
|
|
|
2311
2946
|
);
|
|
2312
2947
|
}
|
|
2313
2948
|
const initials2 = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
|
|
2314
|
-
var
|
|
2315
|
-
return (_b = (
|
|
2949
|
+
var _a2, _b;
|
|
2950
|
+
return (_b = (_a2 = w[0]) == null ? void 0 : _a2.toUpperCase()) != null ? _b : "";
|
|
2316
2951
|
}).join("");
|
|
2317
2952
|
const panelStyle = narrow ? {
|
|
2318
2953
|
width: "100%",
|
|
@@ -2403,7 +3038,9 @@ function AssistSheet({
|
|
|
2403
3038
|
alignItems: "center",
|
|
2404
3039
|
gap: "7px",
|
|
2405
3040
|
fontSize: "14px",
|
|
2406
|
-
fontWeight: 600
|
|
3041
|
+
fontWeight: 600,
|
|
3042
|
+
// One line even with the Chats pill beside it (#567).
|
|
3043
|
+
whiteSpace: "nowrap"
|
|
2407
3044
|
},
|
|
2408
3045
|
children: [
|
|
2409
3046
|
/* @__PURE__ */ jsx3(Sparkle, { color: t.accent }),
|
|
@@ -2433,34 +3070,64 @@ function AssistSheet({
|
|
|
2433
3070
|
projectSlot ? /* @__PURE__ */ jsx3("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
|
|
2434
3071
|
] })
|
|
2435
3072
|
] }),
|
|
2436
|
-
/* @__PURE__ */
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
3073
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "6px", flexShrink: 0 }, children: [
|
|
3074
|
+
historyKey && (showChats || otherChats.length > 0) && /* @__PURE__ */ jsx3(
|
|
3075
|
+
"button",
|
|
3076
|
+
{
|
|
3077
|
+
type: "button",
|
|
3078
|
+
"data-gg-chats-toggle": "",
|
|
3079
|
+
disabled: busy,
|
|
3080
|
+
"aria-pressed": showChats,
|
|
3081
|
+
onClick: () => {
|
|
3082
|
+
setShowChats((v) => !v);
|
|
3083
|
+
setViewingChat(null);
|
|
3084
|
+
},
|
|
3085
|
+
style: {
|
|
3086
|
+
flexShrink: 0,
|
|
3087
|
+
border: `1px solid ${showChats ? t.accent : t.inputBorder}`,
|
|
3088
|
+
borderRadius: "999px",
|
|
3089
|
+
background: "transparent",
|
|
3090
|
+
color: showChats ? t.accent : t.textMuted,
|
|
3091
|
+
cursor: busy ? "default" : "pointer",
|
|
3092
|
+
opacity: busy ? 0.5 : 1,
|
|
3093
|
+
fontSize: "11.5px",
|
|
3094
|
+
lineHeight: 1,
|
|
3095
|
+
fontFamily: "inherit",
|
|
3096
|
+
whiteSpace: "nowrap",
|
|
3097
|
+
padding: "9px 11px"
|
|
3098
|
+
},
|
|
3099
|
+
children: showChats ? "\u2190 Chat" : `Chats \xB7 ${otherChats.length}`
|
|
3100
|
+
}
|
|
3101
|
+
),
|
|
3102
|
+
/* @__PURE__ */ jsx3(
|
|
3103
|
+
"button",
|
|
3104
|
+
{
|
|
3105
|
+
type: "button",
|
|
3106
|
+
"data-gg-write-myself": "",
|
|
3107
|
+
onClick: () => leave("write_myself", `header, ${phase}`),
|
|
3108
|
+
"aria-label": "Write it myself instead",
|
|
3109
|
+
style: {
|
|
3110
|
+
flexShrink: 0,
|
|
3111
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3112
|
+
borderRadius: "999px",
|
|
3113
|
+
background: "transparent",
|
|
3114
|
+
color: t.textMuted,
|
|
3115
|
+
cursor: "pointer",
|
|
3116
|
+
fontSize: "11.5px",
|
|
3117
|
+
lineHeight: 1,
|
|
3118
|
+
fontFamily: "inherit",
|
|
3119
|
+
whiteSpace: "nowrap",
|
|
3120
|
+
// ~32px tall either way — this is the escape hatch, not a hint.
|
|
3121
|
+
padding: "9px 11px"
|
|
3122
|
+
},
|
|
3123
|
+
children: "Write it myself"
|
|
3124
|
+
}
|
|
3125
|
+
)
|
|
3126
|
+
] })
|
|
2460
3127
|
]
|
|
2461
3128
|
}
|
|
2462
3129
|
),
|
|
2463
|
-
/* @__PURE__ */
|
|
3130
|
+
/* @__PURE__ */ jsxs3(
|
|
2464
3131
|
"div",
|
|
2465
3132
|
{
|
|
2466
3133
|
ref: scrollRef,
|
|
@@ -2472,762 +3139,845 @@ function AssistSheet({
|
|
|
2472
3139
|
display: "flex",
|
|
2473
3140
|
flexDirection: "column"
|
|
2474
3141
|
},
|
|
2475
|
-
children:
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
/* @__PURE__ */ jsxs3(
|
|
3142
|
+
children: [
|
|
3143
|
+
showChats && renderChatList(),
|
|
3144
|
+
/* @__PURE__ */ jsx3(
|
|
3145
|
+
"div",
|
|
3146
|
+
{
|
|
3147
|
+
style: {
|
|
3148
|
+
marginTop: "auto",
|
|
3149
|
+
display: "flex",
|
|
3150
|
+
flexDirection: "column",
|
|
3151
|
+
gap: "12px",
|
|
3152
|
+
minWidth: 0
|
|
3153
|
+
},
|
|
3154
|
+
children: /* @__PURE__ */ jsxs3("div", { style: { display: showChats ? "none" : "contents" }, children: [
|
|
3155
|
+
phase === "type" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3156
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3157
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3158
|
+
/* @__PURE__ */ jsxs3(
|
|
3159
|
+
"div",
|
|
3160
|
+
{
|
|
3161
|
+
style: {
|
|
3162
|
+
padding: "9px 12px",
|
|
3163
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3164
|
+
backgroundColor: t.bgSecondary,
|
|
3165
|
+
fontSize: "13px",
|
|
3166
|
+
lineHeight: 1.55,
|
|
3167
|
+
maxWidth: "88%"
|
|
3168
|
+
},
|
|
3169
|
+
children: [
|
|
3170
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 w` : "W",
|
|
3171
|
+
"hat do you want to do? Pick one and I'll take it from there."
|
|
3172
|
+
]
|
|
3173
|
+
}
|
|
3174
|
+
)
|
|
3175
|
+
] }),
|
|
3176
|
+
/* @__PURE__ */ jsx3(
|
|
2490
3177
|
"div",
|
|
2491
3178
|
{
|
|
2492
3179
|
style: {
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
lineHeight: 1.55,
|
|
2498
|
-
maxWidth: "88%"
|
|
3180
|
+
display: "flex",
|
|
3181
|
+
flexWrap: "wrap",
|
|
3182
|
+
gap: "6px",
|
|
3183
|
+
paddingLeft: "32px"
|
|
2499
3184
|
},
|
|
2500
|
-
children:
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
3185
|
+
children: tiles.map((tile) => {
|
|
3186
|
+
const rate = tile === "RATING";
|
|
3187
|
+
return /* @__PURE__ */ jsx3(
|
|
3188
|
+
"button",
|
|
3189
|
+
{
|
|
3190
|
+
type: "button",
|
|
3191
|
+
"data-gg-chip": "",
|
|
3192
|
+
"data-gg-tile": tile,
|
|
3193
|
+
onClick: () => pickType(tile),
|
|
3194
|
+
style: {
|
|
3195
|
+
display: "inline-flex",
|
|
3196
|
+
alignItems: "center",
|
|
3197
|
+
gap: "5px",
|
|
3198
|
+
// The rating is the only tile that isn't a report, so
|
|
3199
|
+
// it wears the star colour the dialog's hero row uses
|
|
3200
|
+
// rather than hiding among the report types.
|
|
3201
|
+
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
3202
|
+
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
3203
|
+
color: rate ? "#f59e0b" : t.textMuted,
|
|
3204
|
+
borderRadius: "999px",
|
|
3205
|
+
// 8px vertical keeps the tap target at ~32px.
|
|
3206
|
+
padding: "8px 12px",
|
|
3207
|
+
fontSize: "12px",
|
|
3208
|
+
fontWeight: rate ? 600 : 400,
|
|
3209
|
+
fontFamily: "inherit",
|
|
3210
|
+
cursor: "pointer"
|
|
3211
|
+
},
|
|
3212
|
+
children: rate ? "\u2605 Rate us" : getTypeLabel(tile)
|
|
3213
|
+
},
|
|
3214
|
+
tile
|
|
3215
|
+
);
|
|
3216
|
+
})
|
|
2504
3217
|
}
|
|
2505
3218
|
)
|
|
2506
3219
|
] }),
|
|
2507
|
-
/* @__PURE__ */
|
|
2508
|
-
"div",
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
3220
|
+
phase === "severity" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3221
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3222
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3223
|
+
/* @__PURE__ */ jsx3(
|
|
3224
|
+
"div",
|
|
3225
|
+
{
|
|
3226
|
+
style: {
|
|
3227
|
+
padding: "9px 12px",
|
|
3228
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3229
|
+
backgroundColor: t.bgSecondary,
|
|
3230
|
+
fontSize: "13px",
|
|
3231
|
+
lineHeight: 1.55,
|
|
3232
|
+
maxWidth: "88%"
|
|
3233
|
+
},
|
|
3234
|
+
children: "How bad is it?"
|
|
3235
|
+
}
|
|
3236
|
+
)
|
|
3237
|
+
] }),
|
|
3238
|
+
/* @__PURE__ */ jsx3(
|
|
3239
|
+
"div",
|
|
3240
|
+
{
|
|
3241
|
+
role: "radiogroup",
|
|
3242
|
+
"aria-label": "Severity",
|
|
3243
|
+
style: {
|
|
3244
|
+
display: "flex",
|
|
3245
|
+
flexWrap: "wrap",
|
|
3246
|
+
gap: "6px",
|
|
3247
|
+
paddingLeft: "32px"
|
|
3248
|
+
},
|
|
3249
|
+
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ jsx3(
|
|
2519
3250
|
"button",
|
|
2520
3251
|
{
|
|
2521
3252
|
type: "button",
|
|
3253
|
+
role: "radio",
|
|
3254
|
+
"aria-checked": severity === s,
|
|
2522
3255
|
"data-gg-chip": "",
|
|
2523
|
-
"data-gg-
|
|
2524
|
-
onClick: () =>
|
|
3256
|
+
"data-gg-severity": s,
|
|
3257
|
+
onClick: () => answerSeverity(s),
|
|
2525
3258
|
style: {
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
// The rating is the only tile that isn't a report, so
|
|
2530
|
-
// it wears the star colour the dialog's hero row uses
|
|
2531
|
-
// rather than hiding among the report types.
|
|
2532
|
-
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
2533
|
-
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
2534
|
-
color: rate ? "#f59e0b" : t.textMuted,
|
|
3259
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3260
|
+
background: "transparent",
|
|
3261
|
+
color: t.textMuted,
|
|
2535
3262
|
borderRadius: "999px",
|
|
2536
|
-
//
|
|
3263
|
+
// Same as the picker and option chips — one chip size.
|
|
2537
3264
|
padding: "8px 12px",
|
|
2538
3265
|
fontSize: "12px",
|
|
2539
|
-
fontWeight: rate ? 600 : 400,
|
|
2540
3266
|
fontFamily: "inherit",
|
|
2541
3267
|
cursor: "pointer"
|
|
2542
3268
|
},
|
|
2543
|
-
children:
|
|
3269
|
+
children: SEVERITY_LABELS[s]
|
|
2544
3270
|
},
|
|
2545
|
-
|
|
2546
|
-
)
|
|
2547
|
-
})
|
|
2548
|
-
}
|
|
2549
|
-
)
|
|
2550
|
-
] }),
|
|
2551
|
-
phase === "severity" && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2552
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2553
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2554
|
-
/* @__PURE__ */ jsx3(
|
|
2555
|
-
"div",
|
|
2556
|
-
{
|
|
2557
|
-
style: {
|
|
2558
|
-
padding: "9px 12px",
|
|
2559
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2560
|
-
backgroundColor: t.bgSecondary,
|
|
2561
|
-
fontSize: "13px",
|
|
2562
|
-
lineHeight: 1.55,
|
|
2563
|
-
maxWidth: "88%"
|
|
2564
|
-
},
|
|
2565
|
-
children: "How bad is it?"
|
|
3271
|
+
s
|
|
3272
|
+
))
|
|
2566
3273
|
}
|
|
2567
3274
|
)
|
|
2568
3275
|
] }),
|
|
2569
|
-
/* @__PURE__ */
|
|
2570
|
-
"div",
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
style: {
|
|
2575
|
-
display: "flex",
|
|
2576
|
-
flexWrap: "wrap",
|
|
2577
|
-
gap: "6px",
|
|
2578
|
-
paddingLeft: "32px"
|
|
2579
|
-
},
|
|
2580
|
-
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ jsx3(
|
|
2581
|
-
"button",
|
|
3276
|
+
phase === "rating" && !submitted && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3277
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3278
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3279
|
+
/* @__PURE__ */ jsx3(
|
|
3280
|
+
"div",
|
|
2582
3281
|
{
|
|
2583
|
-
type: "button",
|
|
2584
|
-
role: "radio",
|
|
2585
|
-
"aria-checked": severity === s,
|
|
2586
|
-
"data-gg-chip": "",
|
|
2587
|
-
"data-gg-severity": s,
|
|
2588
|
-
onClick: () => answerSeverity(s),
|
|
2589
3282
|
style: {
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
fontSize: "12px",
|
|
2597
|
-
fontFamily: "inherit",
|
|
2598
|
-
cursor: "pointer"
|
|
3283
|
+
padding: "9px 12px",
|
|
3284
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3285
|
+
backgroundColor: t.bgSecondary,
|
|
3286
|
+
fontSize: "13px",
|
|
3287
|
+
lineHeight: 1.55,
|
|
3288
|
+
maxWidth: "88%"
|
|
2599
3289
|
},
|
|
2600
|
-
children:
|
|
2601
|
-
}
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
)
|
|
2606
|
-
] }),
|
|
2607
|
-
phase === "rating" && !submitted && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2608
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2609
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2610
|
-
/* @__PURE__ */ jsx3(
|
|
3290
|
+
children: "How are we doing? Tap a star \u2014 the words are optional."
|
|
3291
|
+
}
|
|
3292
|
+
)
|
|
3293
|
+
] }),
|
|
3294
|
+
/* @__PURE__ */ jsxs3(
|
|
2611
3295
|
"div",
|
|
2612
3296
|
{
|
|
2613
3297
|
style: {
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
3298
|
+
display: "flex",
|
|
3299
|
+
flexDirection: "column",
|
|
3300
|
+
gap: "10px",
|
|
3301
|
+
marginLeft: "32px",
|
|
3302
|
+
padding: "12px",
|
|
3303
|
+
borderRadius: "12px",
|
|
3304
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
3305
|
+
backgroundColor: "rgba(245,158,11,0.06)"
|
|
2620
3306
|
},
|
|
2621
|
-
children:
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
3307
|
+
children: [
|
|
3308
|
+
/* @__PURE__ */ jsx3("div", { style: { display: "flex", gap: "4px" }, role: "group", "aria-label": "Rating", children: [1, 2, 3, 4, 5].map((star) => {
|
|
3309
|
+
const filled = star <= (hoveredStar || rating);
|
|
3310
|
+
return /* @__PURE__ */ jsx3(
|
|
3311
|
+
"button",
|
|
3312
|
+
{
|
|
3313
|
+
type: "button",
|
|
3314
|
+
"aria-label": `${star} star${star > 1 ? "s" : ""}`,
|
|
3315
|
+
"aria-pressed": star <= rating,
|
|
3316
|
+
onClick: () => onRatingChange(star),
|
|
3317
|
+
onMouseEnter: () => setHoveredStar(star),
|
|
3318
|
+
onMouseLeave: () => setHoveredStar(0),
|
|
3319
|
+
style: {
|
|
3320
|
+
border: "none",
|
|
3321
|
+
background: "transparent",
|
|
3322
|
+
padding: 0,
|
|
3323
|
+
cursor: "pointer",
|
|
3324
|
+
lineHeight: 0
|
|
3325
|
+
},
|
|
3326
|
+
children: /* @__PURE__ */ jsx3("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx3(
|
|
3327
|
+
"path",
|
|
3328
|
+
{
|
|
3329
|
+
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",
|
|
3330
|
+
fill: filled ? "#f59e0b" : "transparent",
|
|
3331
|
+
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
3332
|
+
strokeWidth: "1.5",
|
|
3333
|
+
strokeLinejoin: "round"
|
|
3334
|
+
}
|
|
3335
|
+
) })
|
|
3336
|
+
},
|
|
3337
|
+
star
|
|
3338
|
+
);
|
|
3339
|
+
}) }),
|
|
3340
|
+
/* @__PURE__ */ jsx3(
|
|
3341
|
+
"textarea",
|
|
3342
|
+
{
|
|
3343
|
+
value: description,
|
|
3344
|
+
onChange: (e) => onDescriptionChange(e.target.value),
|
|
3345
|
+
rows: 3,
|
|
3346
|
+
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
3347
|
+
style: {
|
|
3348
|
+
width: "100%",
|
|
3349
|
+
padding: "10px",
|
|
3350
|
+
borderRadius: "8px",
|
|
3351
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3352
|
+
backgroundColor: t.inputBg,
|
|
3353
|
+
color: t.text,
|
|
3354
|
+
fontSize: "13px",
|
|
3355
|
+
lineHeight: 1.5,
|
|
3356
|
+
fontFamily: "inherit",
|
|
3357
|
+
resize: "vertical",
|
|
3358
|
+
outline: "none",
|
|
3359
|
+
boxSizing: "border-box"
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
),
|
|
3363
|
+
/* @__PURE__ */ jsx3(
|
|
2642
3364
|
"button",
|
|
2643
3365
|
{
|
|
2644
3366
|
type: "button",
|
|
2645
|
-
|
|
2646
|
-
"aria-pressed": star <= rating,
|
|
2647
|
-
onClick: () => onRatingChange(star),
|
|
2648
|
-
onMouseEnter: () => setHoveredStar(star),
|
|
2649
|
-
onMouseLeave: () => setHoveredStar(0),
|
|
3367
|
+
onClick: () => setPhase("type"),
|
|
2650
3368
|
style: {
|
|
3369
|
+
alignSelf: "flex-start",
|
|
2651
3370
|
border: "none",
|
|
2652
3371
|
background: "transparent",
|
|
2653
|
-
|
|
3372
|
+
color: t.textMuted,
|
|
3373
|
+
fontSize: "12px",
|
|
3374
|
+
fontFamily: "inherit",
|
|
3375
|
+
// A bare text link is ~14px tall — half a thumb.
|
|
3376
|
+
padding: "9px 0",
|
|
2654
3377
|
cursor: "pointer",
|
|
2655
|
-
|
|
3378
|
+
textDecoration: "underline"
|
|
2656
3379
|
},
|
|
2657
|
-
children:
|
|
2658
|
-
"path",
|
|
2659
|
-
{
|
|
2660
|
-
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",
|
|
2661
|
-
fill: filled ? "#f59e0b" : "transparent",
|
|
2662
|
-
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
2663
|
-
strokeWidth: "1.5",
|
|
2664
|
-
strokeLinejoin: "round"
|
|
2665
|
-
}
|
|
2666
|
-
) })
|
|
2667
|
-
},
|
|
2668
|
-
star
|
|
2669
|
-
);
|
|
2670
|
-
}) }),
|
|
2671
|
-
/* @__PURE__ */ jsx3(
|
|
2672
|
-
"textarea",
|
|
2673
|
-
{
|
|
2674
|
-
value: description,
|
|
2675
|
-
onChange: (e) => onDescriptionChange(e.target.value),
|
|
2676
|
-
rows: 3,
|
|
2677
|
-
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
2678
|
-
style: {
|
|
2679
|
-
width: "100%",
|
|
2680
|
-
padding: "10px",
|
|
2681
|
-
borderRadius: "8px",
|
|
2682
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2683
|
-
backgroundColor: t.inputBg,
|
|
2684
|
-
color: t.text,
|
|
2685
|
-
fontSize: "13px",
|
|
2686
|
-
lineHeight: 1.5,
|
|
2687
|
-
fontFamily: "inherit",
|
|
2688
|
-
resize: "vertical",
|
|
2689
|
-
outline: "none",
|
|
2690
|
-
boxSizing: "border-box"
|
|
3380
|
+
children: "Report something instead"
|
|
2691
3381
|
}
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
3382
|
+
)
|
|
3383
|
+
]
|
|
3384
|
+
}
|
|
3385
|
+
)
|
|
3386
|
+
] }),
|
|
3387
|
+
empty && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3388
|
+
resumable && /* @__PURE__ */ jsxs3(
|
|
3389
|
+
"div",
|
|
3390
|
+
{
|
|
3391
|
+
"data-gg-resume-chat": "",
|
|
3392
|
+
style: {
|
|
3393
|
+
display: "flex",
|
|
3394
|
+
flexDirection: "column",
|
|
3395
|
+
gap: "8px",
|
|
3396
|
+
padding: "10px 12px",
|
|
3397
|
+
borderRadius: "10px",
|
|
3398
|
+
border: `1px solid ${t.accent}55`,
|
|
3399
|
+
backgroundColor: t.bgSecondary,
|
|
3400
|
+
minWidth: 0
|
|
3401
|
+
},
|
|
3402
|
+
children: [
|
|
3403
|
+
/* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3404
|
+
"Pick up where you left off \xB7 ",
|
|
3405
|
+
chatAge(resumable.updatedAt)
|
|
3406
|
+
] }),
|
|
3407
|
+
/* @__PURE__ */ jsx3(
|
|
3408
|
+
"span",
|
|
3409
|
+
{
|
|
3410
|
+
style: {
|
|
3411
|
+
fontSize: "13px",
|
|
3412
|
+
lineHeight: 1.45,
|
|
3413
|
+
overflowWrap: "anywhere"
|
|
3414
|
+
},
|
|
3415
|
+
children: resumable.title
|
|
3416
|
+
}
|
|
3417
|
+
),
|
|
3418
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
3419
|
+
/* @__PURE__ */ jsx3(
|
|
3420
|
+
"button",
|
|
3421
|
+
{
|
|
3422
|
+
type: "button",
|
|
3423
|
+
"data-gg-resume-continue": "",
|
|
3424
|
+
onClick: () => resumeChat(resumable),
|
|
3425
|
+
style: {
|
|
3426
|
+
border: "none",
|
|
3427
|
+
borderRadius: "999px",
|
|
3428
|
+
backgroundColor: t.accent,
|
|
3429
|
+
color: t.accentText,
|
|
3430
|
+
padding: "7px 13px",
|
|
3431
|
+
fontSize: "12px",
|
|
3432
|
+
fontWeight: 600,
|
|
3433
|
+
fontFamily: "inherit",
|
|
3434
|
+
cursor: "pointer"
|
|
3435
|
+
},
|
|
3436
|
+
children: "Continue this chat"
|
|
3437
|
+
}
|
|
3438
|
+
),
|
|
3439
|
+
/* @__PURE__ */ jsx3(
|
|
3440
|
+
"button",
|
|
3441
|
+
{
|
|
3442
|
+
type: "button",
|
|
3443
|
+
onClick: () => setShowChats(true),
|
|
3444
|
+
style: {
|
|
3445
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3446
|
+
borderRadius: "999px",
|
|
3447
|
+
background: "transparent",
|
|
3448
|
+
color: t.textMuted,
|
|
3449
|
+
padding: "7px 13px",
|
|
3450
|
+
fontSize: "12px",
|
|
3451
|
+
fontFamily: "inherit",
|
|
3452
|
+
cursor: "pointer"
|
|
3453
|
+
},
|
|
3454
|
+
children: "All chats"
|
|
3455
|
+
}
|
|
3456
|
+
)
|
|
3457
|
+
] })
|
|
3458
|
+
]
|
|
3459
|
+
}
|
|
3460
|
+
),
|
|
3461
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3462
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3463
|
+
/* @__PURE__ */ jsxs3(
|
|
3464
|
+
"div",
|
|
3465
|
+
{
|
|
3466
|
+
style: {
|
|
3467
|
+
padding: "9px 12px",
|
|
3468
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3469
|
+
backgroundColor: t.bgSecondary,
|
|
3470
|
+
fontSize: "13px",
|
|
3471
|
+
lineHeight: 1.55,
|
|
3472
|
+
maxWidth: "88%"
|
|
3473
|
+
},
|
|
3474
|
+
children: [
|
|
3475
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 t` : "T",
|
|
3476
|
+
"ell me what went wrong in your own words. I can already see your screenshot and what you clicked, so skip the boring parts."
|
|
3477
|
+
]
|
|
3478
|
+
}
|
|
3479
|
+
)
|
|
3480
|
+
] }),
|
|
3481
|
+
/* @__PURE__ */ jsx3(
|
|
3482
|
+
"div",
|
|
3483
|
+
{
|
|
3484
|
+
style: {
|
|
3485
|
+
display: "flex",
|
|
3486
|
+
flexWrap: "wrap",
|
|
3487
|
+
gap: "6px",
|
|
3488
|
+
paddingLeft: "32px"
|
|
3489
|
+
},
|
|
3490
|
+
children: STARTERS.map((s) => /* @__PURE__ */ jsx3(
|
|
2695
3491
|
"button",
|
|
2696
3492
|
{
|
|
2697
3493
|
type: "button",
|
|
2698
|
-
|
|
3494
|
+
"data-gg-chip": "",
|
|
3495
|
+
onClick: () => {
|
|
3496
|
+
logEvent("starter_tap", s);
|
|
3497
|
+
send(s);
|
|
3498
|
+
},
|
|
2699
3499
|
style: {
|
|
2700
|
-
|
|
2701
|
-
border: "none",
|
|
3500
|
+
border: `1px solid ${t.inputBorder}`,
|
|
2702
3501
|
background: "transparent",
|
|
2703
3502
|
color: t.textMuted,
|
|
3503
|
+
borderRadius: "999px",
|
|
3504
|
+
padding: "6px 11px",
|
|
2704
3505
|
fontSize: "12px",
|
|
2705
3506
|
fontFamily: "inherit",
|
|
2706
|
-
|
|
2707
|
-
padding: "9px 0",
|
|
2708
|
-
cursor: "pointer",
|
|
2709
|
-
textDecoration: "underline"
|
|
3507
|
+
cursor: "pointer"
|
|
2710
3508
|
},
|
|
2711
|
-
children:
|
|
3509
|
+
children: s
|
|
3510
|
+
},
|
|
3511
|
+
s
|
|
3512
|
+
))
|
|
3513
|
+
}
|
|
3514
|
+
)
|
|
3515
|
+
] }),
|
|
3516
|
+
messages.map((m, i) => {
|
|
3517
|
+
const mine = m.role === "user";
|
|
3518
|
+
if (m.kind === "report") {
|
|
3519
|
+
const live = phase === "draft" && i === messages.length - 1;
|
|
3520
|
+
return /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
3521
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3522
|
+
/* @__PURE__ */ jsx3(
|
|
3523
|
+
"div",
|
|
3524
|
+
{
|
|
3525
|
+
"data-gg-draft-bubble": "",
|
|
3526
|
+
style: {
|
|
3527
|
+
maxWidth: "82%",
|
|
3528
|
+
minWidth: 0,
|
|
3529
|
+
padding: "9px 12px",
|
|
3530
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3531
|
+
fontSize: "13px",
|
|
3532
|
+
lineHeight: 1.55,
|
|
3533
|
+
backgroundColor: t.bgSecondary,
|
|
3534
|
+
color: t.text,
|
|
3535
|
+
border: live ? "none" : `1px solid ${t.accent}66`
|
|
3536
|
+
},
|
|
3537
|
+
children: live ? (
|
|
3538
|
+
// #402: "have a read" beside a countdown reads as a
|
|
3539
|
+
// contradiction. Say what is about to happen instead.
|
|
3540
|
+
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."
|
|
3541
|
+
) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
3542
|
+
/* @__PURE__ */ jsx3(
|
|
3543
|
+
"span",
|
|
3544
|
+
{
|
|
3545
|
+
style: {
|
|
3546
|
+
display: "block",
|
|
3547
|
+
fontSize: "10px",
|
|
3548
|
+
fontWeight: 700,
|
|
3549
|
+
letterSpacing: ".06em",
|
|
3550
|
+
textTransform: "uppercase",
|
|
3551
|
+
color: t.accent,
|
|
3552
|
+
marginBottom: "4px"
|
|
3553
|
+
},
|
|
3554
|
+
children: "Draft so far"
|
|
3555
|
+
}
|
|
3556
|
+
),
|
|
3557
|
+
/* @__PURE__ */ jsx3(
|
|
3558
|
+
"span",
|
|
3559
|
+
{
|
|
3560
|
+
style: {
|
|
3561
|
+
display: "block",
|
|
3562
|
+
whiteSpace: "pre-wrap",
|
|
3563
|
+
wordBreak: "break-word",
|
|
3564
|
+
maxHeight: "160px",
|
|
3565
|
+
overflowY: "auto",
|
|
3566
|
+
color: t.textMuted
|
|
3567
|
+
},
|
|
3568
|
+
children: m.content
|
|
3569
|
+
}
|
|
3570
|
+
)
|
|
3571
|
+
] })
|
|
2712
3572
|
}
|
|
2713
3573
|
)
|
|
2714
|
-
]
|
|
3574
|
+
] }, i);
|
|
2715
3575
|
}
|
|
2716
|
-
|
|
2717
|
-
] }),
|
|
2718
|
-
empty && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2719
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2720
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2721
|
-
/* @__PURE__ */ jsxs3(
|
|
3576
|
+
return /* @__PURE__ */ jsxs3(
|
|
2722
3577
|
"div",
|
|
2723
3578
|
{
|
|
2724
3579
|
style: {
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
lineHeight: 1.55,
|
|
2730
|
-
maxWidth: "88%"
|
|
3580
|
+
display: "flex",
|
|
3581
|
+
gap: "8px",
|
|
3582
|
+
minWidth: 0,
|
|
3583
|
+
flexDirection: mine ? "row-reverse" : "row"
|
|
2731
3584
|
},
|
|
2732
3585
|
children: [
|
|
2733
|
-
|
|
2734
|
-
|
|
3586
|
+
/* @__PURE__ */ jsx3(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
3587
|
+
/* @__PURE__ */ jsx3(
|
|
3588
|
+
"div",
|
|
3589
|
+
{
|
|
3590
|
+
style: {
|
|
3591
|
+
maxWidth: "82%",
|
|
3592
|
+
minWidth: 0,
|
|
3593
|
+
padding: "9px 12px",
|
|
3594
|
+
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
3595
|
+
fontSize: "13px",
|
|
3596
|
+
lineHeight: 1.55,
|
|
3597
|
+
// Markdown owns the assistant's line breaks and lists.
|
|
3598
|
+
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
3599
|
+
wordBreak: "break-word",
|
|
3600
|
+
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
3601
|
+
color: mine ? t.accentText : t.text
|
|
3602
|
+
},
|
|
3603
|
+
children: mine ? m.content : /* @__PURE__ */ jsx3(ChatMarkdown, { text: m.content, theme: t })
|
|
3604
|
+
}
|
|
3605
|
+
)
|
|
2735
3606
|
]
|
|
2736
|
-
}
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
3607
|
+
},
|
|
3608
|
+
i
|
|
3609
|
+
);
|
|
3610
|
+
}),
|
|
3611
|
+
duplicate && !busy && phase === "chat" && /* @__PURE__ */ jsx3("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
3612
|
+
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ jsx3("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ jsxs3(
|
|
2740
3613
|
"div",
|
|
2741
3614
|
{
|
|
3615
|
+
"data-gg-glitchgrab-offer": "",
|
|
2742
3616
|
style: {
|
|
2743
3617
|
display: "flex",
|
|
3618
|
+
flexDirection: "column",
|
|
3619
|
+
gap: "8px",
|
|
3620
|
+
padding: "10px",
|
|
3621
|
+
borderRadius: "8px",
|
|
3622
|
+
border: `1px solid ${t.accent}55`,
|
|
3623
|
+
backgroundColor: `${t.accent}14`,
|
|
3624
|
+
fontSize: "12px",
|
|
3625
|
+
lineHeight: 1.5
|
|
3626
|
+
},
|
|
3627
|
+
children: [
|
|
3628
|
+
/* @__PURE__ */ jsx3("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
3629
|
+
/* @__PURE__ */ jsx3("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
3630
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
3631
|
+
/* @__PURE__ */ jsx3(
|
|
3632
|
+
"button",
|
|
3633
|
+
{
|
|
3634
|
+
type: "button",
|
|
3635
|
+
"data-gg-glitchgrab-offer-send": "",
|
|
3636
|
+
onClick: () => {
|
|
3637
|
+
logEvent("glitchgrab_offer_tap");
|
|
3638
|
+
setGlitchgrabOffer(false);
|
|
3639
|
+
onReportGlitchgrabProblem(
|
|
3640
|
+
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
3641
|
+
);
|
|
3642
|
+
},
|
|
3643
|
+
style: {
|
|
3644
|
+
padding: "8px 12px",
|
|
3645
|
+
borderRadius: "999px",
|
|
3646
|
+
border: "none",
|
|
3647
|
+
backgroundColor: t.accent,
|
|
3648
|
+
color: t.accentText,
|
|
3649
|
+
fontSize: "12px",
|
|
3650
|
+
fontWeight: 700,
|
|
3651
|
+
fontFamily: "inherit",
|
|
3652
|
+
cursor: "pointer",
|
|
3653
|
+
// Both stretch, so on a phone each wrapped line reads as
|
|
3654
|
+
// a choice rather than one button left stranded.
|
|
3655
|
+
flex: "1 1 auto"
|
|
3656
|
+
},
|
|
3657
|
+
children: "Send to the Glitchgrab team"
|
|
3658
|
+
}
|
|
3659
|
+
),
|
|
3660
|
+
/* @__PURE__ */ jsx3(
|
|
3661
|
+
"button",
|
|
3662
|
+
{
|
|
3663
|
+
type: "button",
|
|
3664
|
+
"data-gg-glitchgrab-offer-no": "",
|
|
3665
|
+
onClick: () => {
|
|
3666
|
+
logEvent("glitchgrab_offer_declined");
|
|
3667
|
+
send("No \u2014 it's about this app, not the reporting tool");
|
|
3668
|
+
},
|
|
3669
|
+
style: {
|
|
3670
|
+
padding: "8px 12px",
|
|
3671
|
+
borderRadius: "999px",
|
|
3672
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3673
|
+
background: "transparent",
|
|
3674
|
+
color: t.textMuted,
|
|
3675
|
+
fontSize: "12px",
|
|
3676
|
+
fontFamily: "inherit",
|
|
3677
|
+
cursor: "pointer",
|
|
3678
|
+
flex: "1 1 auto"
|
|
3679
|
+
},
|
|
3680
|
+
children: "No, it's about this app"
|
|
3681
|
+
}
|
|
3682
|
+
)
|
|
3683
|
+
] })
|
|
3684
|
+
]
|
|
3685
|
+
}
|
|
3686
|
+
) }),
|
|
3687
|
+
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ jsx3(
|
|
3688
|
+
"div",
|
|
3689
|
+
{
|
|
3690
|
+
style: {
|
|
3691
|
+
display: "flex",
|
|
3692
|
+
// Long labels wrapped into a ragged row that always stranded
|
|
3693
|
+
// the last chip on a line of its own. Past ~24 characters
|
|
3694
|
+
// these stop being chips and become a choice list, so they
|
|
3695
|
+
// stack full width and read like one.
|
|
3696
|
+
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
3697
|
+
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
2744
3698
|
flexWrap: "wrap",
|
|
2745
3699
|
gap: "6px",
|
|
2746
3700
|
paddingLeft: "32px"
|
|
2747
3701
|
},
|
|
2748
|
-
children:
|
|
3702
|
+
children: options.map((option) => /* @__PURE__ */ jsx3(
|
|
2749
3703
|
"button",
|
|
2750
3704
|
{
|
|
2751
3705
|
type: "button",
|
|
2752
3706
|
"data-gg-chip": "",
|
|
3707
|
+
"data-gg-option": "",
|
|
2753
3708
|
onClick: () => {
|
|
2754
|
-
logEvent("
|
|
2755
|
-
send(
|
|
3709
|
+
logEvent("option_tap", option);
|
|
3710
|
+
send(option, option === CONFIRM_OPTION);
|
|
2756
3711
|
},
|
|
2757
3712
|
style: {
|
|
2758
3713
|
border: `1px solid ${t.inputBorder}`,
|
|
2759
3714
|
background: "transparent",
|
|
2760
3715
|
color: t.textMuted,
|
|
2761
3716
|
borderRadius: "999px",
|
|
2762
|
-
|
|
3717
|
+
// Same 8px as the picker chips — one tap target size in
|
|
3718
|
+
// this sheet, not two.
|
|
3719
|
+
padding: "8px 12px",
|
|
2763
3720
|
fontSize: "12px",
|
|
2764
3721
|
fontFamily: "inherit",
|
|
2765
|
-
cursor: "pointer"
|
|
3722
|
+
cursor: "pointer",
|
|
3723
|
+
textAlign: "left"
|
|
2766
3724
|
},
|
|
2767
|
-
children:
|
|
3725
|
+
children: option
|
|
2768
3726
|
},
|
|
2769
|
-
|
|
3727
|
+
option
|
|
2770
3728
|
))
|
|
2771
3729
|
}
|
|
2772
|
-
)
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
marginBottom: "4px"
|
|
2811
|
-
},
|
|
2812
|
-
children: "Draft so far"
|
|
2813
|
-
}
|
|
2814
|
-
),
|
|
2815
|
-
/* @__PURE__ */ jsx3(
|
|
2816
|
-
"span",
|
|
2817
|
-
{
|
|
2818
|
-
style: {
|
|
2819
|
-
display: "block",
|
|
2820
|
-
whiteSpace: "pre-wrap",
|
|
2821
|
-
wordBreak: "break-word",
|
|
2822
|
-
maxHeight: "160px",
|
|
2823
|
-
overflowY: "auto",
|
|
2824
|
-
color: t.textMuted
|
|
2825
|
-
},
|
|
2826
|
-
children: m.content
|
|
2827
|
-
}
|
|
2828
|
-
)
|
|
2829
|
-
] })
|
|
2830
|
-
}
|
|
2831
|
-
)
|
|
2832
|
-
] }, i);
|
|
2833
|
-
}
|
|
2834
|
-
return /* @__PURE__ */ jsxs3(
|
|
3730
|
+
),
|
|
3731
|
+
busy && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, role: "status", "aria-label": "Thinking", children: [
|
|
3732
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3733
|
+
/* @__PURE__ */ jsxs3(
|
|
3734
|
+
"span",
|
|
3735
|
+
{
|
|
3736
|
+
style: {
|
|
3737
|
+
display: "inline-flex",
|
|
3738
|
+
alignItems: "center",
|
|
3739
|
+
// The "still working" line must wrap on a phone, not push
|
|
3740
|
+
// the bubble past the sheet's edge.
|
|
3741
|
+
flexWrap: "wrap",
|
|
3742
|
+
minWidth: 0,
|
|
3743
|
+
gap: "4px",
|
|
3744
|
+
padding: "12px",
|
|
3745
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3746
|
+
backgroundColor: t.bgSecondary
|
|
3747
|
+
},
|
|
3748
|
+
children: [
|
|
3749
|
+
[0, 1, 2].map((i) => /* @__PURE__ */ jsx3(
|
|
3750
|
+
"span",
|
|
3751
|
+
{
|
|
3752
|
+
style: {
|
|
3753
|
+
width: "5px",
|
|
3754
|
+
height: "5px",
|
|
3755
|
+
borderRadius: "50%",
|
|
3756
|
+
backgroundColor: t.textMuted,
|
|
3757
|
+
animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
|
|
3758
|
+
}
|
|
3759
|
+
},
|
|
3760
|
+
i
|
|
3761
|
+
)),
|
|
3762
|
+
/* @__PURE__ */ jsx3(ThinkingClock, { color: t.textMuted })
|
|
3763
|
+
]
|
|
3764
|
+
}
|
|
3765
|
+
)
|
|
3766
|
+
] }),
|
|
3767
|
+
phase === "draft" && !submitted && /* @__PURE__ */ jsxs3(
|
|
2835
3768
|
"div",
|
|
2836
3769
|
{
|
|
2837
3770
|
style: {
|
|
3771
|
+
border: `1px solid ${t.accent}`,
|
|
3772
|
+
borderRadius: "12px",
|
|
3773
|
+
backgroundColor: t.bgSecondary,
|
|
3774
|
+
padding: "12px",
|
|
2838
3775
|
display: "flex",
|
|
2839
|
-
|
|
3776
|
+
flexDirection: "column",
|
|
3777
|
+
gap: "10px",
|
|
2840
3778
|
minWidth: 0,
|
|
2841
|
-
|
|
3779
|
+
boxSizing: "border-box"
|
|
2842
3780
|
},
|
|
2843
3781
|
children: [
|
|
2844
|
-
/* @__PURE__ */ jsx3(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
2845
3782
|
/* @__PURE__ */ jsx3(
|
|
2846
|
-
"
|
|
3783
|
+
"span",
|
|
2847
3784
|
{
|
|
2848
3785
|
style: {
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
lineHeight: 1.55,
|
|
2855
|
-
// Markdown owns the assistant's line breaks and lists.
|
|
2856
|
-
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
2857
|
-
wordBreak: "break-word",
|
|
2858
|
-
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
2859
|
-
color: mine ? t.accentText : t.text
|
|
3786
|
+
fontSize: "10px",
|
|
3787
|
+
fontWeight: 700,
|
|
3788
|
+
letterSpacing: ".06em",
|
|
3789
|
+
textTransform: "uppercase",
|
|
3790
|
+
color: t.accent
|
|
2860
3791
|
},
|
|
2861
|
-
children:
|
|
3792
|
+
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
2862
3793
|
}
|
|
2863
|
-
)
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
"div",
|
|
2872
|
-
{
|
|
2873
|
-
"data-gg-glitchgrab-offer": "",
|
|
2874
|
-
style: {
|
|
2875
|
-
display: "flex",
|
|
2876
|
-
flexDirection: "column",
|
|
2877
|
-
gap: "8px",
|
|
2878
|
-
padding: "10px",
|
|
2879
|
-
borderRadius: "8px",
|
|
2880
|
-
border: `1px solid ${t.accent}55`,
|
|
2881
|
-
backgroundColor: `${t.accent}14`,
|
|
2882
|
-
fontSize: "12px",
|
|
2883
|
-
lineHeight: 1.5
|
|
2884
|
-
},
|
|
2885
|
-
children: [
|
|
2886
|
-
/* @__PURE__ */ jsx3("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
2887
|
-
/* @__PURE__ */ jsx3("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
2888
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
3794
|
+
),
|
|
3795
|
+
renderKnownIssue({
|
|
3796
|
+
title: true,
|
|
3797
|
+
footer: "Your details will be added to it instead of opening a new issue."
|
|
3798
|
+
}),
|
|
3799
|
+
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3800
|
+
// box edge is the very thing #543 is about. One line of text,
|
|
3801
|
+
// so Enter is swallowed.
|
|
2889
3802
|
/* @__PURE__ */ jsx3(
|
|
2890
|
-
"
|
|
3803
|
+
"textarea",
|
|
2891
3804
|
{
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
3805
|
+
"aria-label": "Title",
|
|
3806
|
+
value: issueTitle,
|
|
3807
|
+
maxLength: 120,
|
|
3808
|
+
rows: 2,
|
|
3809
|
+
onKeyDown: (e) => {
|
|
3810
|
+
if (e.key === "Enter") e.preventDefault();
|
|
3811
|
+
},
|
|
3812
|
+
onChange: (e) => {
|
|
3813
|
+
stopAutoFile("edited the title");
|
|
3814
|
+
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
2900
3815
|
},
|
|
2901
3816
|
style: {
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
3817
|
+
width: "100%",
|
|
3818
|
+
padding: "8px 10px",
|
|
3819
|
+
lineHeight: 1.45,
|
|
3820
|
+
resize: "none",
|
|
3821
|
+
borderRadius: "8px",
|
|
3822
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3823
|
+
backgroundColor: t.inputBg,
|
|
3824
|
+
color: t.text,
|
|
3825
|
+
fontSize: "13px",
|
|
3826
|
+
fontWeight: 600,
|
|
2909
3827
|
fontFamily: "inherit",
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
flex: "1 1 auto"
|
|
2914
|
-
},
|
|
2915
|
-
children: "Send to the Glitchgrab team"
|
|
3828
|
+
outline: "none",
|
|
3829
|
+
boxSizing: "border-box"
|
|
3830
|
+
}
|
|
2916
3831
|
}
|
|
2917
3832
|
),
|
|
2918
3833
|
/* @__PURE__ */ jsx3(
|
|
2919
|
-
"
|
|
3834
|
+
"textarea",
|
|
2920
3835
|
{
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
3836
|
+
ref: draftRef,
|
|
3837
|
+
value: description,
|
|
3838
|
+
onChange: (e) => {
|
|
3839
|
+
stopAutoFile("edited the draft");
|
|
3840
|
+
onDescriptionChange(e.target.value);
|
|
2926
3841
|
},
|
|
3842
|
+
rows: 6,
|
|
2927
3843
|
style: {
|
|
2928
|
-
|
|
2929
|
-
|
|
3844
|
+
width: "100%",
|
|
3845
|
+
minHeight: "120px",
|
|
3846
|
+
padding: "10px",
|
|
3847
|
+
borderRadius: "8px",
|
|
2930
3848
|
border: `1px solid ${t.inputBorder}`,
|
|
2931
|
-
|
|
2932
|
-
color: t.
|
|
2933
|
-
fontSize: "
|
|
3849
|
+
backgroundColor: t.inputBg,
|
|
3850
|
+
color: t.text,
|
|
3851
|
+
fontSize: "13px",
|
|
3852
|
+
lineHeight: 1.55,
|
|
2934
3853
|
fontFamily: "inherit",
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
}
|
|
2940
|
-
)
|
|
2941
|
-
] })
|
|
2942
|
-
]
|
|
2943
|
-
}
|
|
2944
|
-
) }),
|
|
2945
|
-
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ jsx3(
|
|
2946
|
-
"div",
|
|
2947
|
-
{
|
|
2948
|
-
style: {
|
|
2949
|
-
display: "flex",
|
|
2950
|
-
// Long labels wrapped into a ragged row that always stranded
|
|
2951
|
-
// the last chip on a line of its own. Past ~24 characters
|
|
2952
|
-
// these stop being chips and become a choice list, so they
|
|
2953
|
-
// stack full width and read like one.
|
|
2954
|
-
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
2955
|
-
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
2956
|
-
flexWrap: "wrap",
|
|
2957
|
-
gap: "6px",
|
|
2958
|
-
paddingLeft: "32px"
|
|
2959
|
-
},
|
|
2960
|
-
children: options.map((option) => /* @__PURE__ */ jsx3(
|
|
2961
|
-
"button",
|
|
2962
|
-
{
|
|
2963
|
-
type: "button",
|
|
2964
|
-
"data-gg-chip": "",
|
|
2965
|
-
"data-gg-option": "",
|
|
2966
|
-
onClick: () => {
|
|
2967
|
-
logEvent("option_tap", option);
|
|
2968
|
-
send(option, option === CONFIRM_OPTION);
|
|
2969
|
-
},
|
|
2970
|
-
style: {
|
|
2971
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2972
|
-
background: "transparent",
|
|
2973
|
-
color: t.textMuted,
|
|
2974
|
-
borderRadius: "999px",
|
|
2975
|
-
// Same 8px as the picker chips — one tap target size in
|
|
2976
|
-
// this sheet, not two.
|
|
2977
|
-
padding: "8px 12px",
|
|
2978
|
-
fontSize: "12px",
|
|
2979
|
-
fontFamily: "inherit",
|
|
2980
|
-
cursor: "pointer",
|
|
2981
|
-
textAlign: "left"
|
|
2982
|
-
},
|
|
2983
|
-
children: option
|
|
2984
|
-
},
|
|
2985
|
-
option
|
|
2986
|
-
))
|
|
2987
|
-
}
|
|
2988
|
-
),
|
|
2989
|
-
busy && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, role: "status", "aria-label": "Thinking", children: [
|
|
2990
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
2991
|
-
/* @__PURE__ */ jsx3(
|
|
2992
|
-
"span",
|
|
2993
|
-
{
|
|
2994
|
-
style: {
|
|
2995
|
-
display: "inline-flex",
|
|
2996
|
-
alignItems: "center",
|
|
2997
|
-
gap: "4px",
|
|
2998
|
-
padding: "12px",
|
|
2999
|
-
borderRadius: "12px 12px 12px 4px",
|
|
3000
|
-
backgroundColor: t.bgSecondary
|
|
3001
|
-
},
|
|
3002
|
-
children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx3(
|
|
3003
|
-
"span",
|
|
3004
|
-
{
|
|
3005
|
-
style: {
|
|
3006
|
-
width: "5px",
|
|
3007
|
-
height: "5px",
|
|
3008
|
-
borderRadius: "50%",
|
|
3009
|
-
backgroundColor: t.textMuted,
|
|
3010
|
-
animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
|
|
3854
|
+
resize: "vertical",
|
|
3855
|
+
outline: "none",
|
|
3856
|
+
boxSizing: "border-box"
|
|
3857
|
+
}
|
|
3011
3858
|
}
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3859
|
+
),
|
|
3860
|
+
severityAsked && autoFileLeft === null && /* @__PURE__ */ jsxs3("div", { children: [
|
|
3861
|
+
/* @__PURE__ */ jsxs3(
|
|
3862
|
+
"span",
|
|
3863
|
+
{
|
|
3864
|
+
style: {
|
|
3865
|
+
fontSize: "11.5px",
|
|
3866
|
+
color: t.textMuted,
|
|
3867
|
+
display: "block",
|
|
3868
|
+
marginBottom: "6px"
|
|
3869
|
+
},
|
|
3870
|
+
children: [
|
|
3871
|
+
"How bad is it?",
|
|
3872
|
+
!severity && /* @__PURE__ */ jsx3(
|
|
3873
|
+
"span",
|
|
3874
|
+
{
|
|
3875
|
+
style: {
|
|
3876
|
+
marginLeft: "6px",
|
|
3877
|
+
fontSize: "11px",
|
|
3878
|
+
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3879
|
+
},
|
|
3880
|
+
children: "\xB7 required"
|
|
3881
|
+
}
|
|
3882
|
+
)
|
|
3883
|
+
]
|
|
3884
|
+
}
|
|
3885
|
+
),
|
|
3886
|
+
/* @__PURE__ */ jsx3(
|
|
3887
|
+
"div",
|
|
3888
|
+
{
|
|
3889
|
+
role: "radiogroup",
|
|
3890
|
+
"aria-label": "Severity",
|
|
3891
|
+
style: { display: "flex", gap: "6px" },
|
|
3892
|
+
children: SEVERITY_LEVELS.map((s) => {
|
|
3893
|
+
const on = severity === s;
|
|
3894
|
+
return /* @__PURE__ */ jsx3(
|
|
3895
|
+
"button",
|
|
3896
|
+
{
|
|
3897
|
+
type: "button",
|
|
3898
|
+
onClick: () => onSeverityChange(s),
|
|
3899
|
+
role: "radio",
|
|
3900
|
+
"aria-checked": on,
|
|
3901
|
+
style: {
|
|
3902
|
+
flex: 1,
|
|
3903
|
+
minWidth: 0,
|
|
3904
|
+
padding: "8px 2px",
|
|
3905
|
+
borderRadius: "8px",
|
|
3906
|
+
border: `1px solid ${on ? t.accent : severityRefused ? "#ef4444" : t.inputBorder}`,
|
|
3907
|
+
backgroundColor: on ? t.accent : "transparent",
|
|
3908
|
+
color: on ? t.accentText : t.textMuted,
|
|
3909
|
+
fontSize: "12px",
|
|
3910
|
+
fontWeight: 600,
|
|
3911
|
+
fontFamily: "inherit",
|
|
3912
|
+
whiteSpace: "nowrap",
|
|
3913
|
+
overflow: "hidden",
|
|
3914
|
+
textOverflow: "ellipsis",
|
|
3915
|
+
cursor: "pointer"
|
|
3916
|
+
},
|
|
3917
|
+
children: SEVERITY_LABELS[s]
|
|
3918
|
+
},
|
|
3919
|
+
s
|
|
3920
|
+
);
|
|
3921
|
+
})
|
|
3922
|
+
}
|
|
3923
|
+
)
|
|
3924
|
+
] }),
|
|
3925
|
+
attachmentCount > 0 && /* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3926
|
+
attachmentCount,
|
|
3927
|
+
" ",
|
|
3928
|
+
attachmentCount === 1 ? "attachment" : "attachments",
|
|
3929
|
+
" will be sent with this."
|
|
3930
|
+
] })
|
|
3931
|
+
]
|
|
3015
3932
|
}
|
|
3016
|
-
)
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
{
|
|
3021
|
-
style: {
|
|
3022
|
-
border: `1px solid ${t.accent}`,
|
|
3023
|
-
borderRadius: "12px",
|
|
3024
|
-
backgroundColor: t.bgSecondary,
|
|
3025
|
-
padding: "12px",
|
|
3026
|
-
display: "flex",
|
|
3027
|
-
flexDirection: "column",
|
|
3028
|
-
gap: "10px",
|
|
3029
|
-
minWidth: 0,
|
|
3030
|
-
boxSizing: "border-box"
|
|
3031
|
-
},
|
|
3032
|
-
children: [
|
|
3033
|
-
/* @__PURE__ */ jsx3(
|
|
3034
|
-
"span",
|
|
3035
|
-
{
|
|
3036
|
-
style: {
|
|
3037
|
-
fontSize: "10px",
|
|
3038
|
-
fontWeight: 700,
|
|
3039
|
-
letterSpacing: ".06em",
|
|
3040
|
-
textTransform: "uppercase",
|
|
3041
|
-
color: t.accent
|
|
3042
|
-
},
|
|
3043
|
-
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3044
|
-
}
|
|
3045
|
-
),
|
|
3046
|
-
renderKnownIssue({
|
|
3047
|
-
title: true,
|
|
3048
|
-
footer: "Your details will be added to it instead of opening a new issue."
|
|
3049
|
-
}),
|
|
3050
|
-
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3051
|
-
// box edge is the very thing #543 is about. One line of text,
|
|
3052
|
-
// so Enter is swallowed.
|
|
3053
|
-
/* @__PURE__ */ jsx3(
|
|
3054
|
-
"textarea",
|
|
3055
|
-
{
|
|
3056
|
-
"aria-label": "Title",
|
|
3057
|
-
value: issueTitle,
|
|
3058
|
-
maxLength: 120,
|
|
3059
|
-
rows: 2,
|
|
3060
|
-
onKeyDown: (e) => {
|
|
3061
|
-
if (e.key === "Enter") e.preventDefault();
|
|
3062
|
-
},
|
|
3063
|
-
onChange: (e) => {
|
|
3064
|
-
stopAutoFile("edited the title");
|
|
3065
|
-
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3066
|
-
},
|
|
3067
|
-
style: {
|
|
3068
|
-
width: "100%",
|
|
3069
|
-
padding: "8px 10px",
|
|
3070
|
-
lineHeight: 1.45,
|
|
3071
|
-
resize: "none",
|
|
3072
|
-
borderRadius: "8px",
|
|
3073
|
-
border: `1px solid ${t.inputBorder}`,
|
|
3074
|
-
backgroundColor: t.inputBg,
|
|
3075
|
-
color: t.text,
|
|
3076
|
-
fontSize: "13px",
|
|
3077
|
-
fontWeight: 600,
|
|
3078
|
-
fontFamily: "inherit",
|
|
3079
|
-
outline: "none",
|
|
3080
|
-
boxSizing: "border-box"
|
|
3081
|
-
}
|
|
3082
|
-
}
|
|
3083
|
-
),
|
|
3933
|
+
),
|
|
3934
|
+
phase === "solved" && solved && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3935
|
+
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3936
|
+
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3084
3937
|
/* @__PURE__ */ jsx3(
|
|
3085
|
-
"
|
|
3938
|
+
"div",
|
|
3086
3939
|
{
|
|
3087
|
-
ref: draftRef,
|
|
3088
|
-
value: description,
|
|
3089
|
-
onChange: (e) => {
|
|
3090
|
-
stopAutoFile("edited the draft");
|
|
3091
|
-
onDescriptionChange(e.target.value);
|
|
3092
|
-
},
|
|
3093
|
-
rows: 6,
|
|
3094
3940
|
style: {
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
borderRadius: "8px",
|
|
3099
|
-
border: `1px solid ${t.inputBorder}`,
|
|
3100
|
-
backgroundColor: t.inputBg,
|
|
3101
|
-
color: t.text,
|
|
3941
|
+
padding: "9px 12px",
|
|
3942
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3943
|
+
backgroundColor: t.bgSecondary,
|
|
3102
3944
|
fontSize: "13px",
|
|
3103
3945
|
lineHeight: 1.55,
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
}
|
|
3946
|
+
maxWidth: "88%",
|
|
3947
|
+
whiteSpace: "pre-wrap"
|
|
3948
|
+
},
|
|
3949
|
+
children: solved
|
|
3109
3950
|
}
|
|
3110
|
-
)
|
|
3111
|
-
|
|
3112
|
-
/* @__PURE__ */ jsxs3(
|
|
3113
|
-
"span",
|
|
3114
|
-
{
|
|
3115
|
-
style: {
|
|
3116
|
-
fontSize: "11.5px",
|
|
3117
|
-
color: t.textMuted,
|
|
3118
|
-
display: "block",
|
|
3119
|
-
marginBottom: "6px"
|
|
3120
|
-
},
|
|
3121
|
-
children: [
|
|
3122
|
-
"How bad is it?",
|
|
3123
|
-
!severity && /* @__PURE__ */ jsx3(
|
|
3124
|
-
"span",
|
|
3125
|
-
{
|
|
3126
|
-
style: {
|
|
3127
|
-
marginLeft: "6px",
|
|
3128
|
-
fontSize: "11px",
|
|
3129
|
-
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3130
|
-
},
|
|
3131
|
-
children: "\xB7 required"
|
|
3132
|
-
}
|
|
3133
|
-
)
|
|
3134
|
-
]
|
|
3135
|
-
}
|
|
3136
|
-
),
|
|
3137
|
-
/* @__PURE__ */ jsx3(
|
|
3138
|
-
"div",
|
|
3139
|
-
{
|
|
3140
|
-
role: "radiogroup",
|
|
3141
|
-
"aria-label": "Severity",
|
|
3142
|
-
style: { display: "flex", gap: "6px" },
|
|
3143
|
-
children: SEVERITY_LEVELS.map((s) => {
|
|
3144
|
-
const on = severity === s;
|
|
3145
|
-
return /* @__PURE__ */ jsx3(
|
|
3146
|
-
"button",
|
|
3147
|
-
{
|
|
3148
|
-
type: "button",
|
|
3149
|
-
onClick: () => onSeverityChange(s),
|
|
3150
|
-
role: "radio",
|
|
3151
|
-
"aria-checked": on,
|
|
3152
|
-
style: {
|
|
3153
|
-
flex: 1,
|
|
3154
|
-
minWidth: 0,
|
|
3155
|
-
padding: "8px 2px",
|
|
3156
|
-
borderRadius: "8px",
|
|
3157
|
-
border: `1px solid ${on ? t.accent : severityRefused ? "#ef4444" : t.inputBorder}`,
|
|
3158
|
-
backgroundColor: on ? t.accent : "transparent",
|
|
3159
|
-
color: on ? t.accentText : t.textMuted,
|
|
3160
|
-
fontSize: "12px",
|
|
3161
|
-
fontWeight: 600,
|
|
3162
|
-
fontFamily: "inherit",
|
|
3163
|
-
whiteSpace: "nowrap",
|
|
3164
|
-
overflow: "hidden",
|
|
3165
|
-
textOverflow: "ellipsis",
|
|
3166
|
-
cursor: "pointer"
|
|
3167
|
-
},
|
|
3168
|
-
children: SEVERITY_LABELS[s]
|
|
3169
|
-
},
|
|
3170
|
-
s
|
|
3171
|
-
);
|
|
3172
|
-
})
|
|
3173
|
-
}
|
|
3174
|
-
)
|
|
3175
|
-
] }),
|
|
3176
|
-
attachmentCount > 0 && /* @__PURE__ */ jsxs3("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3177
|
-
attachmentCount,
|
|
3178
|
-
" ",
|
|
3179
|
-
attachmentCount === 1 ? "attachment" : "attachments",
|
|
3180
|
-
" will be sent with this."
|
|
3181
|
-
] })
|
|
3182
|
-
]
|
|
3183
|
-
}
|
|
3184
|
-
),
|
|
3185
|
-
phase === "solved" && solved && /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3186
|
-
/* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3187
|
-
/* @__PURE__ */ jsx3(Avatar, { who: "assistant", theme: t }),
|
|
3951
|
+
)
|
|
3952
|
+
] }),
|
|
3188
3953
|
/* @__PURE__ */ jsx3(
|
|
3189
|
-
"
|
|
3954
|
+
"span",
|
|
3190
3955
|
{
|
|
3191
|
-
style: {
|
|
3192
|
-
|
|
3193
|
-
borderRadius: "12px 12px 12px 4px",
|
|
3194
|
-
backgroundColor: t.bgSecondary,
|
|
3195
|
-
fontSize: "13px",
|
|
3196
|
-
lineHeight: 1.55,
|
|
3197
|
-
maxWidth: "88%",
|
|
3198
|
-
whiteSpace: "pre-wrap"
|
|
3199
|
-
},
|
|
3200
|
-
children: solved
|
|
3956
|
+
style: { fontSize: "11.5px", color: t.textMuted, paddingLeft: "32px" },
|
|
3957
|
+
children: "Nothing was filed \u2014 you are all set."
|
|
3201
3958
|
}
|
|
3202
3959
|
)
|
|
3203
3960
|
] }),
|
|
3204
|
-
/* @__PURE__ */ jsx3(
|
|
3205
|
-
"
|
|
3961
|
+
submitted && /* @__PURE__ */ jsx3(
|
|
3962
|
+
"div",
|
|
3206
3963
|
{
|
|
3207
|
-
style: {
|
|
3208
|
-
|
|
3964
|
+
style: {
|
|
3965
|
+
textAlign: "center",
|
|
3966
|
+
padding: "24px 0",
|
|
3967
|
+
color: t.accent,
|
|
3968
|
+
fontSize: "14px",
|
|
3969
|
+
fontWeight: 600
|
|
3970
|
+
},
|
|
3971
|
+
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3209
3972
|
}
|
|
3210
3973
|
)
|
|
3211
|
-
] })
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
style: {
|
|
3216
|
-
textAlign: "center",
|
|
3217
|
-
padding: "24px 0",
|
|
3218
|
-
color: t.accent,
|
|
3219
|
-
fontSize: "14px",
|
|
3220
|
-
fontWeight: 600
|
|
3221
|
-
},
|
|
3222
|
-
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3223
|
-
}
|
|
3224
|
-
)
|
|
3225
|
-
]
|
|
3226
|
-
}
|
|
3227
|
-
)
|
|
3974
|
+
] })
|
|
3975
|
+
}
|
|
3976
|
+
)
|
|
3977
|
+
]
|
|
3228
3978
|
}
|
|
3229
3979
|
),
|
|
3230
|
-
!submitted && phase !== "type" && phase !== "severity" && /* @__PURE__ */ jsxs3(
|
|
3980
|
+
!submitted && !showChats && phase !== "type" && phase !== "severity" && /* @__PURE__ */ jsxs3(
|
|
3231
3981
|
"div",
|
|
3232
3982
|
{
|
|
3233
3983
|
style: {
|
|
@@ -3544,8 +4294,8 @@ function AssistSheet({
|
|
|
3544
4294
|
accept: canReadPdf ? ASSIST_ATTACHMENT_ACCEPT_WITH_PDF : ASSIST_ATTACHMENT_ACCEPT,
|
|
3545
4295
|
multiple: true,
|
|
3546
4296
|
onChange: (e) => {
|
|
3547
|
-
var
|
|
3548
|
-
const picked = Array.from((
|
|
4297
|
+
var _a2;
|
|
4298
|
+
const picked = Array.from((_a2 = e.target.files) != null ? _a2 : []);
|
|
3549
4299
|
if (picked.length) {
|
|
3550
4300
|
stopAutoFile("changed attachments");
|
|
3551
4301
|
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
@@ -4523,20 +5273,20 @@ function initialsOf(name) {
|
|
|
4523
5273
|
}).join("");
|
|
4524
5274
|
}
|
|
4525
5275
|
function ReporterChip({
|
|
4526
|
-
reporter,
|
|
5276
|
+
reporter: reporter2,
|
|
4527
5277
|
t
|
|
4528
5278
|
}) {
|
|
4529
5279
|
var _a;
|
|
4530
5280
|
const [avatarFailed, setAvatarFailed] = useState4(false);
|
|
4531
|
-
const avatarUrl = (
|
|
5281
|
+
const avatarUrl = (reporter2 == null ? void 0 : reporter2.avatarUrl) || "";
|
|
4532
5282
|
useEffect4(() => {
|
|
4533
5283
|
setAvatarFailed(false);
|
|
4534
5284
|
}, [avatarUrl]);
|
|
4535
|
-
const name = ((_a =
|
|
5285
|
+
const name = ((_a = reporter2 == null ? void 0 : reporter2.name) == null ? void 0 : _a.trim()) || "";
|
|
4536
5286
|
const isAnonymous = !name;
|
|
4537
5287
|
const initials2 = isAnonymous ? "" : initialsOf(name);
|
|
4538
5288
|
const label = isAnonymous ? "Anonymous" : name;
|
|
4539
|
-
const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name,
|
|
5289
|
+
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 ");
|
|
4540
5290
|
const showAvatarImage = !!avatarUrl && !avatarFailed;
|
|
4541
5291
|
return /* @__PURE__ */ jsxs5(
|
|
4542
5292
|
"span",
|
|
@@ -4600,7 +5350,7 @@ function ReporterChip({
|
|
|
4600
5350
|
},
|
|
4601
5351
|
children: [
|
|
4602
5352
|
label,
|
|
4603
|
-
(
|
|
5353
|
+
(reporter2 == null ? void 0 : reporter2.role) ? ` \xB7 ${reporter2.role}` : ""
|
|
4604
5354
|
]
|
|
4605
5355
|
}
|
|
4606
5356
|
)
|
|
@@ -4717,11 +5467,12 @@ function ReportDialog({
|
|
|
4717
5467
|
types,
|
|
4718
5468
|
showSeverity = true,
|
|
4719
5469
|
captureScreenshot = captureDefaultScreenshot,
|
|
4720
|
-
reporter,
|
|
5470
|
+
reporter: reporter2,
|
|
4721
5471
|
onClose,
|
|
4722
5472
|
headerSlot,
|
|
4723
5473
|
reportGlitchgrabProblem,
|
|
4724
|
-
layout = "modal"
|
|
5474
|
+
layout = "modal",
|
|
5475
|
+
chatHistoryKey: chatHistoryKey2 = null
|
|
4725
5476
|
}) {
|
|
4726
5477
|
var _a;
|
|
4727
5478
|
const sheet = layout === "sheet";
|
|
@@ -4826,15 +5577,15 @@ function ReportDialog({
|
|
|
4826
5577
|
});
|
|
4827
5578
|
};
|
|
4828
5579
|
applyInert();
|
|
4829
|
-
const
|
|
5580
|
+
const observer2 = new MutationObserver((mutations) => {
|
|
4830
5581
|
const structural = mutations.some(
|
|
4831
5582
|
(m) => m.addedNodes.length > 0 || m.removedNodes.length > 0
|
|
4832
5583
|
);
|
|
4833
5584
|
if (structural) applyInert();
|
|
4834
5585
|
});
|
|
4835
|
-
|
|
5586
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
4836
5587
|
return () => {
|
|
4837
|
-
|
|
5588
|
+
observer2.disconnect();
|
|
4838
5589
|
inerted.forEach((el) => el.removeAttribute("inert"));
|
|
4839
5590
|
};
|
|
4840
5591
|
}, [isOpen]);
|
|
@@ -5486,6 +6237,9 @@ function ReportDialog({
|
|
|
5486
6237
|
setAddedAsRelated(!!duplicateOf && result.issueNumber === duplicateOf && attachKind === "related");
|
|
5487
6238
|
const queued = result.status === "QUEUED" && !!result.message;
|
|
5488
6239
|
setQueuedMessage(queued ? (_c = result.message) != null ? _c : null : null);
|
|
6240
|
+
if (chatHistoryKey2 && aiConversationId) {
|
|
6241
|
+
markChatFiled(chatHistoryKey2, aiConversationId, `${getTypeLabel(reportType)} sent`);
|
|
6242
|
+
}
|
|
5489
6243
|
setSubmitted(true);
|
|
5490
6244
|
setDescription("");
|
|
5491
6245
|
setScreenshots([]);
|
|
@@ -7305,7 +8059,7 @@ function ReportDialog({
|
|
|
7305
8059
|
gap: "12px"
|
|
7306
8060
|
},
|
|
7307
8061
|
children: [
|
|
7308
|
-
/* @__PURE__ */ jsx5(ReporterChip, { reporter, t }),
|
|
8062
|
+
/* @__PURE__ */ jsx5(ReporterChip, { reporter: reporter2, t }),
|
|
7309
8063
|
reportGlitchgrabProblem ? /* @__PURE__ */ jsx5(
|
|
7310
8064
|
"button",
|
|
7311
8065
|
{
|
|
@@ -7585,6 +8339,7 @@ function ReportDialog({
|
|
|
7585
8339
|
setDuplicateKind(issueNumber && kind === "related" ? "related" : "duplicate");
|
|
7586
8340
|
},
|
|
7587
8341
|
onConversationChange: setAiConversationId,
|
|
8342
|
+
historyKey: chatHistoryKey2,
|
|
7588
8343
|
onFinish: handleClose,
|
|
7589
8344
|
rating,
|
|
7590
8345
|
onRatingChange: (value) => {
|
|
@@ -7592,7 +8347,7 @@ function ReportDialog({
|
|
|
7592
8347
|
if (validationError) setValidationError(null);
|
|
7593
8348
|
},
|
|
7594
8349
|
projectSlot: headerSlot,
|
|
7595
|
-
reporterName: (_a =
|
|
8350
|
+
reporterName: (_a = reporter2 == null ? void 0 : reporter2.name) != null ? _a : null,
|
|
7596
8351
|
description,
|
|
7597
8352
|
onDescriptionChange: (value) => {
|
|
7598
8353
|
setDescription(value);
|
|
@@ -9179,6 +9934,9 @@ function GlitchgrabProviderInner({
|
|
|
9179
9934
|
onError,
|
|
9180
9935
|
onReportSent
|
|
9181
9936
|
});
|
|
9937
|
+
if (process.env.NODE_ENV !== "development") {
|
|
9938
|
+
installHydrationCapture(reportHydrationError);
|
|
9939
|
+
}
|
|
9182
9940
|
useEffect6(() => {
|
|
9183
9941
|
if (enableBreadcrumbs) {
|
|
9184
9942
|
initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
|
|
@@ -9234,7 +9992,7 @@ function GlitchgrabProviderInner({
|
|
|
9234
9992
|
return matchesIgnorePatterns(message, ignoreErrors);
|
|
9235
9993
|
};
|
|
9236
9994
|
const handleError = (event) => {
|
|
9237
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
9995
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
9238
9996
|
try {
|
|
9239
9997
|
const isOpaqueCrossOrigin = event.message === "Script error." || event.message === "Script error" || !event.error && !event.filename;
|
|
9240
9998
|
if (isOpaqueCrossOrigin) {
|
|
@@ -9249,6 +10007,7 @@ function GlitchgrabProviderInner({
|
|
|
9249
10007
|
if (event.filename && EXTENSION_ORIGIN_RE.test(event.filename) || ((_a = event.error) == null ? void 0 : _a.stack) && EXTENSION_ORIGIN_RE.test(event.error.stack)) {
|
|
9250
10008
|
return;
|
|
9251
10009
|
}
|
|
10010
|
+
if (isHandledHydrationError(event.error)) return;
|
|
9252
10011
|
incrementErrorCount();
|
|
9253
10012
|
const context = captureContext(visitedPagesRef.current);
|
|
9254
10013
|
const sig = computeSignature({
|
|
@@ -9274,6 +10033,9 @@ function GlitchgrabProviderInner({
|
|
|
9274
10033
|
filename: (_e = event.filename) != null ? _e : "",
|
|
9275
10034
|
lineno: String((_f = event.lineno) != null ? _f : ""),
|
|
9276
10035
|
colno: String((_g = event.colno) != null ? _g : ""),
|
|
10036
|
+
// The root patch could not attach (React internals moved, or a
|
|
10037
|
+
// root it does not know): still label it and send the DOM context.
|
|
10038
|
+
...isHydrationError((_h = event.error) != null ? _h : event.message) ? hydrationMetadata((_i = event.error) != null ? _i : event.message) : {},
|
|
9277
10039
|
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
9278
10040
|
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
9279
10041
|
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
@@ -9615,7 +10377,7 @@ function GlitchgrabProviderInner({
|
|
|
9615
10377
|
} catch (e) {
|
|
9616
10378
|
}
|
|
9617
10379
|
}, [openReportDialog]);
|
|
9618
|
-
const
|
|
10380
|
+
const reporter2 = useMemo4(() => {
|
|
9619
10381
|
var _a;
|
|
9620
10382
|
if (!session) return null;
|
|
9621
10383
|
const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
|
|
@@ -9686,7 +10448,8 @@ function GlitchgrabProviderInner({
|
|
|
9686
10448
|
transcribeAudio: aiBlockedUnsigned ? void 0 : transcribe,
|
|
9687
10449
|
types,
|
|
9688
10450
|
showSeverity,
|
|
9689
|
-
reporter,
|
|
10451
|
+
reporter: reporter2,
|
|
10452
|
+
chatHistoryKey: chatHistoryKey("sdk", token, session == null ? void 0 : session.userId),
|
|
9690
10453
|
headerSlot: projectName ? /* @__PURE__ */ jsxs7("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
|
|
9691
10454
|
"Reporting to ",
|
|
9692
10455
|
/* @__PURE__ */ jsx7("strong", { style: { color: "#e5e5e5" }, children: projectName })
|