glitchgrab 1.58.1 → 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 +32 -0
- package/dist/index.d.mts +21 -3
- package/dist/index.d.ts +21 -3
- package/dist/index.js +2205 -1281
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2204 -1281
- package/dist/index.mjs.map +1 -1
- package/dist/server.d.mts +41 -3
- package/dist/server.d.ts +41 -3
- package/dist/server.js +49 -15
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +47 -15
- package/dist/server.mjs.map +1 -1
- package/dist/{types-DfVtKZcp.d.mts → types-BpTLWJ1y.d.mts} +8 -0
- package/dist/{types-DfVtKZcp.d.ts → types-BpTLWJ1y.d.ts} +8 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
32
32
|
var index_exports = {};
|
|
33
33
|
__export(index_exports, {
|
|
34
34
|
BookDemoButton: () => BookDemoButton,
|
|
35
|
+
BookingDialog: () => BookingDialog,
|
|
35
36
|
FeedbackButton: () => FeedbackButton,
|
|
36
37
|
GLITCHGRAB_SHORTCUT: () => GLITCHGRAB_SHORTCUT2,
|
|
37
38
|
GLITCHGRAB_SHORTCUT_MAC: () => GLITCHGRAB_SHORTCUT_MAC2,
|
|
@@ -238,7 +239,7 @@ function argsToString(args) {
|
|
|
238
239
|
function previewJson(value, max) {
|
|
239
240
|
let out = "";
|
|
240
241
|
const path = /* @__PURE__ */ new WeakSet();
|
|
241
|
-
const
|
|
242
|
+
const write2 = (input, inArray) => {
|
|
242
243
|
if (out.length > max) return;
|
|
243
244
|
let v = input;
|
|
244
245
|
if (v !== null && typeof v === "object" && typeof v.toJSON === "function") {
|
|
@@ -275,7 +276,7 @@ function previewJson(value, max) {
|
|
|
275
276
|
out += "[";
|
|
276
277
|
for (let i = 0; i < obj.length && out.length <= max; i++) {
|
|
277
278
|
if (i > 0) out += ",";
|
|
278
|
-
|
|
279
|
+
write2(obj[i], true);
|
|
279
280
|
}
|
|
280
281
|
out += "]";
|
|
281
282
|
} else {
|
|
@@ -288,13 +289,13 @@ function previewJson(value, max) {
|
|
|
288
289
|
if (child === void 0 || typeof child === "function" || typeof child === "symbol") continue;
|
|
289
290
|
out += `${first ? "" : ","}${JSON.stringify(key)}:`;
|
|
290
291
|
first = false;
|
|
291
|
-
|
|
292
|
+
write2(child, false);
|
|
292
293
|
}
|
|
293
294
|
out += "}";
|
|
294
295
|
}
|
|
295
296
|
path.delete(obj);
|
|
296
297
|
};
|
|
297
|
-
|
|
298
|
+
write2(value, false);
|
|
298
299
|
return out;
|
|
299
300
|
}
|
|
300
301
|
async function readErrorBody(response, url) {
|
|
@@ -647,6 +648,9 @@ function contextMetadata(context) {
|
|
|
647
648
|
var DEFAULT_BASE_URL = "https://glitchgrab.dev";
|
|
648
649
|
var MAX_RETRIES = 3;
|
|
649
650
|
var RETRY_BASE_MS = 500;
|
|
651
|
+
function reportAttemptTimeoutMs(bodyLength) {
|
|
652
|
+
return 1e4 + Math.ceil(bodyLength / 1e5) * 1e3;
|
|
653
|
+
}
|
|
650
654
|
async function sendReport(payload, baseUrl) {
|
|
651
655
|
var _a;
|
|
652
656
|
try {
|
|
@@ -657,13 +661,18 @@ async function sendReport(payload, baseUrl) {
|
|
|
657
661
|
Authorization: `Bearer ${payload.token}`
|
|
658
662
|
};
|
|
659
663
|
const useKeepalive = body.length < 6e4;
|
|
664
|
+
const timeoutMs = reportAttemptTimeoutMs(body.length);
|
|
660
665
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
666
|
+
const isLast = attempt === MAX_RETRIES - 1;
|
|
667
|
+
const controller = !isLast && typeof AbortController === "function" ? new AbortController() : null;
|
|
668
|
+
const timer = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
661
669
|
try {
|
|
662
670
|
const response = await fetch(url, {
|
|
663
671
|
method: "POST",
|
|
664
672
|
headers,
|
|
665
673
|
body,
|
|
666
|
-
...useKeepalive ? { keepalive: true } : {}
|
|
674
|
+
...useKeepalive ? { keepalive: true } : {},
|
|
675
|
+
...controller ? { signal: controller.signal } : {}
|
|
667
676
|
});
|
|
668
677
|
if (response.ok) {
|
|
669
678
|
const envelope = await response.json();
|
|
@@ -673,6 +682,8 @@ async function sendReport(payload, baseUrl) {
|
|
|
673
682
|
return null;
|
|
674
683
|
}
|
|
675
684
|
} catch (e) {
|
|
685
|
+
} finally {
|
|
686
|
+
if (timer) clearTimeout(timer);
|
|
676
687
|
}
|
|
677
688
|
if (attempt < MAX_RETRIES - 1) {
|
|
678
689
|
await new Promise(
|
|
@@ -789,7 +800,7 @@ async function enhanceText(text, token, baseUrl, screenshot, context, identity)
|
|
|
789
800
|
return text;
|
|
790
801
|
}
|
|
791
802
|
}
|
|
792
|
-
async function findSimilarIssues(description, token, baseUrl, identity) {
|
|
803
|
+
async function findSimilarIssues(description, token, baseUrl, identity, files) {
|
|
793
804
|
var _a;
|
|
794
805
|
try {
|
|
795
806
|
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/reports/similar`;
|
|
@@ -799,7 +810,11 @@ async function findSimilarIssues(description, token, baseUrl, identity) {
|
|
|
799
810
|
"Content-Type": "application/json",
|
|
800
811
|
Authorization: `Bearer ${token}`
|
|
801
812
|
},
|
|
802
|
-
body: JSON.stringify({
|
|
813
|
+
body: JSON.stringify({
|
|
814
|
+
text: description,
|
|
815
|
+
...(files == null ? void 0 : files.length) ? { files } : {},
|
|
816
|
+
...signedFields(identity)
|
|
817
|
+
})
|
|
803
818
|
});
|
|
804
819
|
const envelope = await response.json().catch(() => null);
|
|
805
820
|
if (!response.ok || !(envelope == null ? void 0 : envelope.success)) return null;
|
|
@@ -809,6 +824,25 @@ async function findSimilarIssues(description, token, baseUrl, identity) {
|
|
|
809
824
|
return null;
|
|
810
825
|
}
|
|
811
826
|
}
|
|
827
|
+
async function readAttachment(file, token, baseUrl, identity) {
|
|
828
|
+
var _a;
|
|
829
|
+
try {
|
|
830
|
+
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/read-file`;
|
|
831
|
+
const response = await fetch(url, {
|
|
832
|
+
method: "POST",
|
|
833
|
+
headers: {
|
|
834
|
+
"Content-Type": "application/json",
|
|
835
|
+
Authorization: `Bearer ${token}`
|
|
836
|
+
},
|
|
837
|
+
body: JSON.stringify({ name: file.name, data: file.dataUrl, ...signedFields(identity) })
|
|
838
|
+
});
|
|
839
|
+
const envelope = await response.json().catch(() => null);
|
|
840
|
+
if (!response.ok || !(envelope == null ? void 0 : envelope.success) || !((_a = envelope.data) == null ? void 0 : _a.enabled)) return null;
|
|
841
|
+
return typeof envelope.data.text === "string" ? envelope.data.text : null;
|
|
842
|
+
} catch (e) {
|
|
843
|
+
return null;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
812
846
|
async function assistTurn(params, token, baseUrl) {
|
|
813
847
|
const offline = assistOffline();
|
|
814
848
|
try {
|
|
@@ -922,6 +956,292 @@ function clearDedupCache() {
|
|
|
922
956
|
seen.clear();
|
|
923
957
|
}
|
|
924
958
|
|
|
959
|
+
// src/hydration.ts
|
|
960
|
+
var HYDRATION_CODE_RE = /Minified React error #(418|419|422|423|425)\b/;
|
|
961
|
+
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;
|
|
962
|
+
var BAILOUT_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
|
|
963
|
+
var DOM_SNIPPET_MAX = 3e3;
|
|
964
|
+
var STACK_FRAMES_MAX = 40;
|
|
965
|
+
function messageOf(error) {
|
|
966
|
+
if (error && typeof error === "object" && typeof error.message === "string") {
|
|
967
|
+
return error.message;
|
|
968
|
+
}
|
|
969
|
+
return typeof error === "string" ? error : "";
|
|
970
|
+
}
|
|
971
|
+
function hydrationCode(message) {
|
|
972
|
+
if (!message) return null;
|
|
973
|
+
const m = HYDRATION_CODE_RE.exec(message);
|
|
974
|
+
if (m) return m[1];
|
|
975
|
+
return HYDRATION_DEV_RE.test(message) ? "dev" : null;
|
|
976
|
+
}
|
|
977
|
+
function isHydrationError(error) {
|
|
978
|
+
if (hydrationCode(messageOf(error))) return true;
|
|
979
|
+
const cause = error && typeof error === "object" ? error.cause : void 0;
|
|
980
|
+
return cause !== void 0 && cause !== error && hydrationCode(messageOf(cause)) !== null;
|
|
981
|
+
}
|
|
982
|
+
function isBailout(error) {
|
|
983
|
+
const e = error;
|
|
984
|
+
if (!e || typeof e !== "object") return false;
|
|
985
|
+
if (e.digest === BAILOUT_DIGEST) return true;
|
|
986
|
+
const c = e.cause;
|
|
987
|
+
return !!c && typeof c === "object" && c.digest === BAILOUT_DIGEST;
|
|
988
|
+
}
|
|
989
|
+
function componentStackNames(stack) {
|
|
990
|
+
if (!stack) return [];
|
|
991
|
+
const names = [];
|
|
992
|
+
for (const raw of stack.split("\n")) {
|
|
993
|
+
const line = raw.trim();
|
|
994
|
+
if (!line) continue;
|
|
995
|
+
let name = "";
|
|
996
|
+
if (line.startsWith("at ")) {
|
|
997
|
+
name = line.slice(3).split(" (")[0].trim();
|
|
998
|
+
} else if (line.includes("@")) {
|
|
999
|
+
name = line.slice(0, line.indexOf("@")).trim();
|
|
1000
|
+
} else {
|
|
1001
|
+
name = line;
|
|
1002
|
+
}
|
|
1003
|
+
if (name) names.push(name);
|
|
1004
|
+
if (names.length >= STACK_FRAMES_MAX) break;
|
|
1005
|
+
}
|
|
1006
|
+
return names;
|
|
1007
|
+
}
|
|
1008
|
+
function componentStackKey(stack) {
|
|
1009
|
+
return componentStackNames(stack).join(">");
|
|
1010
|
+
}
|
|
1011
|
+
var observer = null;
|
|
1012
|
+
var observerStarted = false;
|
|
1013
|
+
var observerStopAt = 0;
|
|
1014
|
+
var OBSERVE_MS = 3e4;
|
|
1015
|
+
function startObserver() {
|
|
1016
|
+
if (observerStarted || typeof MutationObserver === "undefined" || typeof document === "undefined") {
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
observerStarted = true;
|
|
1020
|
+
try {
|
|
1021
|
+
observer = new MutationObserver(() => {
|
|
1022
|
+
if (Date.now() > observerStopAt) stopObserver();
|
|
1023
|
+
});
|
|
1024
|
+
observer.observe(document, { childList: true, subtree: true });
|
|
1025
|
+
observerStopAt = Date.now() + OBSERVE_MS;
|
|
1026
|
+
setTimeout(stopObserver, OBSERVE_MS);
|
|
1027
|
+
} catch (e) {
|
|
1028
|
+
observer = null;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function stopObserver() {
|
|
1032
|
+
try {
|
|
1033
|
+
observer == null ? void 0 : observer.disconnect();
|
|
1034
|
+
} catch (e) {
|
|
1035
|
+
}
|
|
1036
|
+
observer = null;
|
|
1037
|
+
}
|
|
1038
|
+
function describeNode(node) {
|
|
1039
|
+
if (!node) return "";
|
|
1040
|
+
if (node.nodeType === 9) return "#document";
|
|
1041
|
+
const el = node;
|
|
1042
|
+
if (!el.tagName) return node.nodeName;
|
|
1043
|
+
const id = el.id ? `#${el.id}` : "";
|
|
1044
|
+
const cls = typeof el.className === "string" && el.className.trim() ? "." + el.className.trim().split(/\s+/).slice(0, 3).join(".") : "";
|
|
1045
|
+
return `${el.tagName.toLowerCase()}${id}${cls}`;
|
|
1046
|
+
}
|
|
1047
|
+
function pathOf(node) {
|
|
1048
|
+
const parts = [];
|
|
1049
|
+
let cur = node;
|
|
1050
|
+
while (cur && parts.length < 6) {
|
|
1051
|
+
parts.unshift(describeNode(cur));
|
|
1052
|
+
if (cur.nodeType === 9) break;
|
|
1053
|
+
cur = cur.parentNode;
|
|
1054
|
+
}
|
|
1055
|
+
return parts.join(" > ");
|
|
1056
|
+
}
|
|
1057
|
+
var NON_CONTENT_TAGS = /* @__PURE__ */ new Set(["SCRIPT", "STYLE", "LINK", "META", "NOSCRIPT", "TEMPLATE", "TITLE", "HEAD"]);
|
|
1058
|
+
function isInHead(node) {
|
|
1059
|
+
for (let cur = node; cur; cur = cur.parentNode) {
|
|
1060
|
+
if (cur.nodeName === "HEAD") return true;
|
|
1061
|
+
if (cur.nodeName === "BODY") return false;
|
|
1062
|
+
}
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
var GSTIN_RE = /\b\d{2}[A-Z]{5}\d{4}[A-Z][A-Z0-9]Z[A-Z0-9]\b/g;
|
|
1066
|
+
var PAN_RE = /\b[A-Z]{5}\d{4}[A-Z]\b/g;
|
|
1067
|
+
function scrubHtml(html) {
|
|
1068
|
+
return redactString(
|
|
1069
|
+
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)))
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
function takeRemovedServerHtml() {
|
|
1073
|
+
var _a, _b;
|
|
1074
|
+
if (!observer) return { html: "", where: "" };
|
|
1075
|
+
try {
|
|
1076
|
+
const records = observer.takeRecords();
|
|
1077
|
+
let html = "";
|
|
1078
|
+
let where = "";
|
|
1079
|
+
for (const rec of records) {
|
|
1080
|
+
if (rec.type !== "childList" || rec.removedNodes.length === 0) continue;
|
|
1081
|
+
if (isInHead(rec.target)) continue;
|
|
1082
|
+
if (!where) where = pathOf(rec.target);
|
|
1083
|
+
for (const node of Array.from(rec.removedNodes)) {
|
|
1084
|
+
if (node.nodeType === 1 && NON_CONTENT_TAGS.has(node.tagName)) continue;
|
|
1085
|
+
if (node.nodeType === 3 && !((_a = node.textContent) != null ? _a : "").trim()) continue;
|
|
1086
|
+
const piece = node.nodeType === 1 ? node.outerHTML : node.nodeType === 3 ? `#text "${(_b = node.textContent) != null ? _b : ""}"` : "";
|
|
1087
|
+
if (!piece) continue;
|
|
1088
|
+
html += (html ? "\n" : "") + piece;
|
|
1089
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1090
|
+
}
|
|
1091
|
+
if (html.length >= DOM_SNIPPET_MAX) break;
|
|
1092
|
+
}
|
|
1093
|
+
const scrubbed = scrubHtml(html);
|
|
1094
|
+
return {
|
|
1095
|
+
html: scrubbed.length > DOM_SNIPPET_MAX ? `${scrubbed.slice(0, DOM_SNIPPET_MAX)}\u2026[truncated]` : scrubbed,
|
|
1096
|
+
where
|
|
1097
|
+
};
|
|
1098
|
+
} catch (e) {
|
|
1099
|
+
return { html: "", where: "" };
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
function detectForeignNodes(doc = document) {
|
|
1103
|
+
var _a;
|
|
1104
|
+
const found = [];
|
|
1105
|
+
try {
|
|
1106
|
+
const html = doc.documentElement;
|
|
1107
|
+
if ((html == null ? void 0 : html.classList.contains("translated-ltr")) || (html == null ? void 0 : html.classList.contains("translated-rtl"))) {
|
|
1108
|
+
found.push("Google Translate is active (html.translated-*)");
|
|
1109
|
+
}
|
|
1110
|
+
const fonts = doc.getElementsByTagName("font").length;
|
|
1111
|
+
if (fonts > 0) found.push(`<font> \xD7 ${fonts} (Google Translate or a translation extension)`);
|
|
1112
|
+
const detectors = doc.querySelectorAll("a[x-apple-data-detectors]").length;
|
|
1113
|
+
if (detectors > 0) {
|
|
1114
|
+
found.push(`<a x-apple-data-detectors> \xD7 ${detectors} (iOS format detection turned text into links)`);
|
|
1115
|
+
}
|
|
1116
|
+
if (doc.querySelector("[data-gr-ext-installed],[data-new-gr-c-s-check-loaded],grammarly-desktop-integration")) {
|
|
1117
|
+
found.push("Grammarly extension attributes");
|
|
1118
|
+
}
|
|
1119
|
+
if (doc.querySelector("[data-lt-installed]")) found.push("LanguageTool extension attributes");
|
|
1120
|
+
if ((_a = doc.body) == null ? void 0 : _a.hasAttribute("cz-shortcut-listen")) found.push("ColorZilla extension attribute on <body>");
|
|
1121
|
+
const custom = /* @__PURE__ */ new Set();
|
|
1122
|
+
for (const parent of [html, doc.body]) {
|
|
1123
|
+
if (!parent) continue;
|
|
1124
|
+
for (const child of Array.from(parent.children)) {
|
|
1125
|
+
const tag = child.tagName.toLowerCase();
|
|
1126
|
+
if (tag.includes("-")) custom.add(tag);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
if (custom.size > 0) {
|
|
1130
|
+
found.push(`custom elements at top level: ${Array.from(custom).slice(0, 5).join(", ")} (often an extension)`);
|
|
1131
|
+
}
|
|
1132
|
+
} catch (e) {
|
|
1133
|
+
}
|
|
1134
|
+
return found;
|
|
1135
|
+
}
|
|
1136
|
+
function hydrationTiming() {
|
|
1137
|
+
var _a, _b, _c, _d;
|
|
1138
|
+
try {
|
|
1139
|
+
if (typeof performance === "undefined") return "";
|
|
1140
|
+
const at2 = Math.round(performance.now());
|
|
1141
|
+
const parts = [`error at ${at2}ms after navigation start`];
|
|
1142
|
+
const nav = (_b = (_a = performance.getEntriesByType) == null ? void 0 : _a.call(performance, "navigation")) == null ? void 0 : _b[0];
|
|
1143
|
+
if (nav == null ? void 0 : nav.domContentLoadedEventEnd) {
|
|
1144
|
+
parts.push(`DOMContentLoaded ${Math.round(nav.domContentLoadedEventEnd)}ms`);
|
|
1145
|
+
}
|
|
1146
|
+
const fetches = ((_d = (_c = performance.getEntriesByType) == null ? void 0 : _c.call(performance, "resource")) != null ? _d : []).filter((e) => {
|
|
1147
|
+
const t = e.initiatorType;
|
|
1148
|
+
return t === "fetch" || t === "xmlhttprequest";
|
|
1149
|
+
}).sort((a, b) => a.responseEnd - b.responseEnd).slice(0, 8).map((e) => {
|
|
1150
|
+
let path = e.name;
|
|
1151
|
+
try {
|
|
1152
|
+
const u = new URL(e.name);
|
|
1153
|
+
path = u.origin === window.location.origin ? u.pathname : `${u.host}${u.pathname}`;
|
|
1154
|
+
} catch (e2) {
|
|
1155
|
+
}
|
|
1156
|
+
return `${path} ${Math.round(e.responseEnd)}ms`;
|
|
1157
|
+
});
|
|
1158
|
+
if (fetches.length > 0) parts.push(`fetches finished before it: ${fetches.join(", ")}`);
|
|
1159
|
+
else parts.push("no fetch had finished yet");
|
|
1160
|
+
return parts.join("; ");
|
|
1161
|
+
} catch (e) {
|
|
1162
|
+
return "";
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
function hydrationMetadata(error, extra) {
|
|
1166
|
+
var _a, _b, _c;
|
|
1167
|
+
const code = (_a = hydrationCode(messageOf(error))) != null ? _a : hydrationCode(messageOf(error == null ? void 0 : error.cause));
|
|
1168
|
+
const meta = { errorKind: "hydration" };
|
|
1169
|
+
if (code) meta.hydrationCode = code;
|
|
1170
|
+
const cause = error == null ? void 0 : error.cause;
|
|
1171
|
+
if (cause && cause !== error && messageOf(cause)) {
|
|
1172
|
+
meta.hydrationCause = messageOf(cause).slice(0, 500);
|
|
1173
|
+
}
|
|
1174
|
+
if ((_b = extra == null ? void 0 : extra.removed) == null ? void 0 : _b.html) meta.hydrationServerHtml = extra.removed.html;
|
|
1175
|
+
if ((_c = extra == null ? void 0 : extra.removed) == null ? void 0 : _c.where) meta.hydrationReplacedIn = extra.removed.where;
|
|
1176
|
+
const foreign = detectForeignNodes();
|
|
1177
|
+
if (foreign.length > 0) meta.hydrationForeignNodes = foreign.join("\n");
|
|
1178
|
+
const timing = hydrationTiming();
|
|
1179
|
+
if (timing) meta.hydrationTiming = timing;
|
|
1180
|
+
return meta;
|
|
1181
|
+
}
|
|
1182
|
+
var handled = /* @__PURE__ */ new WeakSet();
|
|
1183
|
+
function isHandledHydrationError(error) {
|
|
1184
|
+
return !!error && typeof error === "object" && handled.has(error);
|
|
1185
|
+
}
|
|
1186
|
+
function markHandled(error) {
|
|
1187
|
+
if (error && typeof error === "object") {
|
|
1188
|
+
handled.add(error);
|
|
1189
|
+
const cause = error.cause;
|
|
1190
|
+
if (cause && typeof cause === "object") handled.add(cause);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
var reporter = null;
|
|
1194
|
+
var PATCHED = "__glitchgrabHydrationPatched";
|
|
1195
|
+
function findFiberRoot(container) {
|
|
1196
|
+
if (!container || typeof container !== "object") return null;
|
|
1197
|
+
try {
|
|
1198
|
+
const key = Object.keys(container).find((k) => k.startsWith("__reactContainer$"));
|
|
1199
|
+
if (!key) return null;
|
|
1200
|
+
const hostRoot = container[key];
|
|
1201
|
+
const root = hostRoot == null ? void 0 : hostRoot.stateNode;
|
|
1202
|
+
return root && typeof root === "object" ? root : null;
|
|
1203
|
+
} catch (e) {
|
|
1204
|
+
return null;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
function patchRoot(root) {
|
|
1208
|
+
if (root[PATCHED]) return true;
|
|
1209
|
+
const original = root.onRecoverableError;
|
|
1210
|
+
if (typeof original !== "function") return false;
|
|
1211
|
+
root.onRecoverableError = function glitchgrabOnRecoverableError(error, info) {
|
|
1212
|
+
var _a;
|
|
1213
|
+
try {
|
|
1214
|
+
if (reporter && isHydrationError(error) && !isBailout(error)) {
|
|
1215
|
+
const removed = takeRemovedServerHtml();
|
|
1216
|
+
markHandled(error);
|
|
1217
|
+
reporter(error, (_a = info == null ? void 0 : info.componentStack) != null ? _a : "", hydrationMetadata(error, { removed }));
|
|
1218
|
+
}
|
|
1219
|
+
} catch (e) {
|
|
1220
|
+
}
|
|
1221
|
+
return original.call(this, error, info);
|
|
1222
|
+
};
|
|
1223
|
+
root[PATCHED] = true;
|
|
1224
|
+
return true;
|
|
1225
|
+
}
|
|
1226
|
+
function patchKnownRoots() {
|
|
1227
|
+
if (typeof document === "undefined") return false;
|
|
1228
|
+
let patched = false;
|
|
1229
|
+
for (const container of [document, document.getElementById("__next"), document.getElementById("root")]) {
|
|
1230
|
+
const root = findFiberRoot(container);
|
|
1231
|
+
if (root && patchRoot(root)) patched = true;
|
|
1232
|
+
}
|
|
1233
|
+
return patched;
|
|
1234
|
+
}
|
|
1235
|
+
function installHydrationCapture(report) {
|
|
1236
|
+
try {
|
|
1237
|
+
if (typeof window === "undefined") return;
|
|
1238
|
+
reporter = report;
|
|
1239
|
+
startObserver();
|
|
1240
|
+
patchKnownRoots();
|
|
1241
|
+
} catch (e) {
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
|
|
925
1245
|
// src/capture.ts
|
|
926
1246
|
var config = null;
|
|
927
1247
|
function registerCaptureConfig(next) {
|
|
@@ -941,7 +1261,7 @@ function sessionMetadata(session) {
|
|
|
941
1261
|
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {}
|
|
942
1262
|
};
|
|
943
1263
|
}
|
|
944
|
-
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError") {
|
|
1264
|
+
function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureError", dedupKey) {
|
|
945
1265
|
var _a, _b, _c;
|
|
946
1266
|
const err = error instanceof Error ? error : void 0;
|
|
947
1267
|
const errorMessage = err ? err.message : String(error);
|
|
@@ -953,7 +1273,7 @@ function buildCapturedErrorPayload(error, options, cfg, capturedBy = "captureErr
|
|
|
953
1273
|
const sig = computeSignature({
|
|
954
1274
|
errorMessage,
|
|
955
1275
|
pageUrl: context.url,
|
|
956
|
-
errorStack: err == null ? void 0 : err.stack,
|
|
1276
|
+
errorStack: dedupKey ? `at ${dedupKey}` : err == null ? void 0 : err.stack,
|
|
957
1277
|
digest
|
|
958
1278
|
});
|
|
959
1279
|
if (shouldSkipDuplicate(sig)) return null;
|
|
@@ -993,6 +1313,25 @@ function captureError(error, options) {
|
|
|
993
1313
|
} catch (e) {
|
|
994
1314
|
}
|
|
995
1315
|
}
|
|
1316
|
+
function reportHydrationError(error, componentStack, metadata) {
|
|
1317
|
+
try {
|
|
1318
|
+
const cfg = config;
|
|
1319
|
+
if (!(cfg == null ? void 0 : cfg.token)) return;
|
|
1320
|
+
const payload = buildCapturedErrorPayload(
|
|
1321
|
+
error,
|
|
1322
|
+
{ componentStack: componentStack || void 0, metadata },
|
|
1323
|
+
cfg,
|
|
1324
|
+
"onRecoverableError",
|
|
1325
|
+
componentStackKey(componentStack) || void 0
|
|
1326
|
+
);
|
|
1327
|
+
if (!payload) return;
|
|
1328
|
+
void sendReport(payload, cfg.baseUrl).then((result) => {
|
|
1329
|
+
if (result && cfg.onReportSent) cfg.onReportSent(result);
|
|
1330
|
+
});
|
|
1331
|
+
if (cfg.onError && error instanceof Error) cfg.onError(error);
|
|
1332
|
+
} catch (e) {
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
996
1335
|
|
|
997
1336
|
// src/error-boundary.tsx
|
|
998
1337
|
var GlitchgrabErrorBoundary = class extends React.Component {
|
|
@@ -1410,6 +1749,9 @@ var MAX_ASSIST_IMAGE_CHARS = 35e5;
|
|
|
1410
1749
|
var MAX_ASSIST_FILES = 3;
|
|
1411
1750
|
var MAX_ASSIST_FILE_CHARS = 3e5;
|
|
1412
1751
|
var MAX_ASSIST_FILE_CHARS_EACH = 2e5;
|
|
1752
|
+
var MAX_SIMILAR_FILE_CHARS = 2e4;
|
|
1753
|
+
var MAX_SIMILAR_FILES_TOTAL_CHARS = 4e4;
|
|
1754
|
+
var MAX_READABLE_PDF_BYTES = 3 * 1024 * 1024;
|
|
1413
1755
|
var TEXT_ATTACHMENT_EXTENSIONS = [
|
|
1414
1756
|
".html",
|
|
1415
1757
|
".htm",
|
|
@@ -1440,6 +1782,10 @@ var ATTACHMENT_ACCEPT = [
|
|
|
1440
1782
|
...BINARY_ATTACHMENT_EXTENSIONS
|
|
1441
1783
|
].join(",");
|
|
1442
1784
|
var ASSIST_ATTACHMENT_ACCEPT = ["image/*", ...TEXT_ATTACHMENT_EXTENSIONS].join(",");
|
|
1785
|
+
var ASSIST_ATTACHMENT_ACCEPT_WITH_PDF = [ASSIST_ATTACHMENT_ACCEPT, ".pdf"].join(",");
|
|
1786
|
+
function isPdfFile(name) {
|
|
1787
|
+
return name.toLowerCase().endsWith(".pdf");
|
|
1788
|
+
}
|
|
1443
1789
|
function isAssistReadableFile(name) {
|
|
1444
1790
|
const lower = name.toLowerCase();
|
|
1445
1791
|
return TEXT_ATTACHMENT_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
@@ -1460,6 +1806,27 @@ function decodeTextDataUrl(dataUrl) {
|
|
|
1460
1806
|
return null;
|
|
1461
1807
|
}
|
|
1462
1808
|
}
|
|
1809
|
+
function heldFileKey(file) {
|
|
1810
|
+
return `${file.name}:${file.size}`;
|
|
1811
|
+
}
|
|
1812
|
+
function heldFileText(file) {
|
|
1813
|
+
if (isPdfFile(file.name)) return typeof file.text === "string" && file.text.trim() ? file.text : null;
|
|
1814
|
+
if (!isAssistReadableFile(file.name)) return null;
|
|
1815
|
+
const text = decodeTextDataUrl(file.dataUrl);
|
|
1816
|
+
return text && text.trim() ? text : null;
|
|
1817
|
+
}
|
|
1818
|
+
function filesForSimilar(files, each, total) {
|
|
1819
|
+
const picked = [];
|
|
1820
|
+
let used = 0;
|
|
1821
|
+
for (let i = files.length - 1; i >= 0 && used < total; i--) {
|
|
1822
|
+
const text = heldFileText(files[i]);
|
|
1823
|
+
if (!text) continue;
|
|
1824
|
+
const content = text.slice(0, Math.min(each, total - used));
|
|
1825
|
+
picked.unshift({ name: files[i].name, content });
|
|
1826
|
+
used += content.length;
|
|
1827
|
+
}
|
|
1828
|
+
return picked;
|
|
1829
|
+
}
|
|
1463
1830
|
function getTypeLabel(type) {
|
|
1464
1831
|
switch (type) {
|
|
1465
1832
|
case "RATING":
|
|
@@ -1886,6 +2253,79 @@ function renderBlocks(lines, theme, key) {
|
|
|
1886
2253
|
function ChatMarkdown({ text, theme }) {
|
|
1887
2254
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: STACK, children: renderBlocks(text.replace(/\r\n?/g, "\n").split("\n"), theme, "md") });
|
|
1888
2255
|
}
|
|
2256
|
+
var MAX_SAVED_CHATS = 20;
|
|
2257
|
+
var SAVED_CHAT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
2258
|
+
var TITLE_CHARS = 80;
|
|
2259
|
+
var PREFIX = "glitchgrab:ai-chats:";
|
|
2260
|
+
function chatHistoryKey(...parts) {
|
|
2261
|
+
const input = parts.map((p) => p != null ? p : "").join("\0");
|
|
2262
|
+
let hash = 2166136261;
|
|
2263
|
+
for (let i = 0; i < input.length; i++) {
|
|
2264
|
+
hash ^= input.charCodeAt(i);
|
|
2265
|
+
hash = Math.imul(hash, 16777619);
|
|
2266
|
+
}
|
|
2267
|
+
return (hash >>> 0).toString(36);
|
|
2268
|
+
}
|
|
2269
|
+
function chatTitle(messages) {
|
|
2270
|
+
var _a, _b;
|
|
2271
|
+
const first = (_b = (_a = messages.find((m) => m.role === "user")) == null ? void 0 : _a.content.trim()) != null ? _b : "";
|
|
2272
|
+
const line = first.replace(/\s+/g, " ");
|
|
2273
|
+
return line.length > TITLE_CHARS ? `${line.slice(0, TITLE_CHARS - 1)}\u2026` : line;
|
|
2274
|
+
}
|
|
2275
|
+
function storage() {
|
|
2276
|
+
try {
|
|
2277
|
+
return typeof window !== "undefined" && window.localStorage ? window.localStorage : null;
|
|
2278
|
+
} catch (e) {
|
|
2279
|
+
return null;
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
function isSavedChat(value) {
|
|
2283
|
+
if (!value || typeof value !== "object") return false;
|
|
2284
|
+
const c = value;
|
|
2285
|
+
return typeof c.id === "string" && typeof c.title === "string" && typeof c.updatedAt === "number" && (c.status === "open" || c.status === "filed") && Array.isArray(c.messages);
|
|
2286
|
+
}
|
|
2287
|
+
function loadChats(key, now = Date.now()) {
|
|
2288
|
+
const store = storage();
|
|
2289
|
+
if (!store) return [];
|
|
2290
|
+
try {
|
|
2291
|
+
const raw = store.getItem(PREFIX + key);
|
|
2292
|
+
if (!raw) return [];
|
|
2293
|
+
const parsed = JSON.parse(raw);
|
|
2294
|
+
if (!Array.isArray(parsed)) return [];
|
|
2295
|
+
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);
|
|
2296
|
+
} catch (e) {
|
|
2297
|
+
return [];
|
|
2298
|
+
}
|
|
2299
|
+
}
|
|
2300
|
+
function write(key, chats) {
|
|
2301
|
+
const store = storage();
|
|
2302
|
+
if (!store) return;
|
|
2303
|
+
try {
|
|
2304
|
+
if (chats.length === 0) store.removeItem(PREFIX + key);
|
|
2305
|
+
else store.setItem(PREFIX + key, JSON.stringify(chats));
|
|
2306
|
+
} catch (e) {
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
function saveChat(key, chat, now = Date.now()) {
|
|
2310
|
+
const rest = loadChats(key, now).filter((c) => c.id !== chat.id);
|
|
2311
|
+
const next = [chat, ...rest].slice(0, MAX_SAVED_CHATS);
|
|
2312
|
+
write(key, next);
|
|
2313
|
+
return next;
|
|
2314
|
+
}
|
|
2315
|
+
function markChatFiled(key, conversationId, label, now = Date.now()) {
|
|
2316
|
+
const chats = loadChats(key, now);
|
|
2317
|
+
const hit = chats.find((c) => c.conversationId === conversationId);
|
|
2318
|
+
if (!hit || hit.status === "filed") return;
|
|
2319
|
+
write(
|
|
2320
|
+
key,
|
|
2321
|
+
chats.map((c) => c === hit ? { ...c, status: "filed", filedLabel: label, updatedAt: now } : c)
|
|
2322
|
+
);
|
|
2323
|
+
}
|
|
2324
|
+
function removeChat(key, id, now = Date.now()) {
|
|
2325
|
+
const next = loadChats(key, now).filter((c) => c.id !== id);
|
|
2326
|
+
write(key, next);
|
|
2327
|
+
return next;
|
|
2328
|
+
}
|
|
1889
2329
|
function pickAssistImages(all) {
|
|
1890
2330
|
const picked = [];
|
|
1891
2331
|
let total = 0;
|
|
@@ -1903,9 +2343,8 @@ function pickAssistFiles(files) {
|
|
|
1903
2343
|
let total = 0;
|
|
1904
2344
|
for (let i = files.length - 1; i >= 0 && picked.length < MAX_ASSIST_FILES; i--) {
|
|
1905
2345
|
const attached = files[i];
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
if (!text || !text.trim()) continue;
|
|
2346
|
+
const text = heldFileText(attached);
|
|
2347
|
+
if (!text) continue;
|
|
1909
2348
|
const content = text.slice(0, MAX_ASSIST_FILE_CHARS_EACH);
|
|
1910
2349
|
if (total + content.length > MAX_ASSIST_FILE_CHARS) continue;
|
|
1911
2350
|
picked.unshift({ index: i, file: { name: attached.name, content } });
|
|
@@ -1913,6 +2352,18 @@ function pickAssistFiles(files) {
|
|
|
1913
2352
|
}
|
|
1914
2353
|
return picked;
|
|
1915
2354
|
}
|
|
2355
|
+
function newChatId() {
|
|
2356
|
+
return `local-${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`;
|
|
2357
|
+
}
|
|
2358
|
+
function chatAge(at2, now = Date.now()) {
|
|
2359
|
+
const min = Math.round((now - at2) / 6e4);
|
|
2360
|
+
if (min < 1) return "just now";
|
|
2361
|
+
if (min < 60) return `${min} min ago`;
|
|
2362
|
+
const hours = Math.round(min / 60);
|
|
2363
|
+
if (hours < 24) return `${hours} h ago`;
|
|
2364
|
+
if (hours < 48) return "yesterday";
|
|
2365
|
+
return new Date(at2).toLocaleDateString(void 0, { day: "numeric", month: "short" });
|
|
2366
|
+
}
|
|
1916
2367
|
var STARTERS = [
|
|
1917
2368
|
"Something on this page is broken",
|
|
1918
2369
|
"It did the wrong thing",
|
|
@@ -1995,6 +2446,33 @@ function Avatar({
|
|
|
1995
2446
|
}
|
|
1996
2447
|
);
|
|
1997
2448
|
}
|
|
2449
|
+
var THINKING_SLOW_SECONDS = 20;
|
|
2450
|
+
function ThinkingClock({ color }) {
|
|
2451
|
+
const [seconds, setSeconds] = (0, import_react3.useState)(0);
|
|
2452
|
+
(0, import_react3.useEffect)(() => {
|
|
2453
|
+
const started = Date.now();
|
|
2454
|
+
const id = setInterval(() => setSeconds(Math.floor((Date.now() - started) / 1e3)), 1e3);
|
|
2455
|
+
return () => clearInterval(id);
|
|
2456
|
+
}, []);
|
|
2457
|
+
return (
|
|
2458
|
+
// Hidden from screen readers: the bubble already says "Thinking", and a
|
|
2459
|
+
// number changing every second would be read out every second.
|
|
2460
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2461
|
+
"span",
|
|
2462
|
+
{
|
|
2463
|
+
"data-gg-thinking-clock": "",
|
|
2464
|
+
"aria-hidden": "true",
|
|
2465
|
+
style: { marginLeft: "6px", fontSize: "12px", color, fontVariantNumeric: "tabular-nums" },
|
|
2466
|
+
children: [
|
|
2467
|
+
"Thinking\u2026 ",
|
|
2468
|
+
seconds,
|
|
2469
|
+
"s",
|
|
2470
|
+
seconds >= THINKING_SLOW_SECONDS ? " \xB7 taking longer than usual, still working" : ""
|
|
2471
|
+
]
|
|
2472
|
+
}
|
|
2473
|
+
)
|
|
2474
|
+
);
|
|
2475
|
+
}
|
|
1998
2476
|
function AssistSheet({
|
|
1999
2477
|
assist,
|
|
2000
2478
|
theme: t,
|
|
@@ -2002,6 +2480,7 @@ function AssistSheet({
|
|
|
2002
2480
|
pageShot = null,
|
|
2003
2481
|
onAddFiles,
|
|
2004
2482
|
files = NO_FILES,
|
|
2483
|
+
canReadPdf = false,
|
|
2005
2484
|
onRemoveFile,
|
|
2006
2485
|
onRemoveImage,
|
|
2007
2486
|
attachmentCount,
|
|
@@ -2029,17 +2508,27 @@ function AssistSheet({
|
|
|
2029
2508
|
isSubmitting,
|
|
2030
2509
|
submitted,
|
|
2031
2510
|
onSend,
|
|
2511
|
+
similarSlot,
|
|
2512
|
+
submittedText,
|
|
2032
2513
|
onDegrade,
|
|
2033
2514
|
onClose,
|
|
2034
2515
|
onFinish,
|
|
2035
|
-
onReportGlitchgrabProblem
|
|
2516
|
+
onReportGlitchgrabProblem,
|
|
2517
|
+
historyKey = null
|
|
2036
2518
|
}) {
|
|
2519
|
+
var _a;
|
|
2037
2520
|
const narrow = useIsNarrow();
|
|
2038
2521
|
const severityAsked = showSeverity && currentTile === "BUG";
|
|
2039
2522
|
const [messages, setMessages] = (0, import_react3.useState)([]);
|
|
2040
2523
|
const [input, setInput] = (0, import_react3.useState)("");
|
|
2041
2524
|
const [busy, setBusy] = (0, import_react3.useState)(false);
|
|
2042
2525
|
const [conversationId, setConversationId] = (0, import_react3.useState)(null);
|
|
2526
|
+
const chatIdRef = (0, import_react3.useRef)(newChatId());
|
|
2527
|
+
const [savedChats, setSavedChats] = (0, import_react3.useState)(
|
|
2528
|
+
() => historyKey ? loadChats(historyKey) : []
|
|
2529
|
+
);
|
|
2530
|
+
const [showChats, setShowChats] = (0, import_react3.useState)(false);
|
|
2531
|
+
const [viewingChat, setViewingChat] = (0, import_react3.useState)(null);
|
|
2043
2532
|
const [hoveredStar, setHoveredStar] = (0, import_react3.useState)(0);
|
|
2044
2533
|
const [options, setOptions] = (0, import_react3.useState)([]);
|
|
2045
2534
|
const [duplicate, setDuplicate] = (0, import_react3.useState)(null);
|
|
@@ -2052,6 +2541,7 @@ function AssistSheet({
|
|
|
2052
2541
|
const [autoFileLeft, setAutoFileLeft] = (0, import_react3.useState)(null);
|
|
2053
2542
|
const scrollRef = (0, import_react3.useRef)(null);
|
|
2054
2543
|
const draftRef = (0, import_react3.useRef)(null);
|
|
2544
|
+
const composerRef = (0, import_react3.useRef)(null);
|
|
2055
2545
|
const seededRef = (0, import_react3.useRef)(false);
|
|
2056
2546
|
const seedPendingRef = (0, import_react3.useRef)(false);
|
|
2057
2547
|
const eventsRef = (0, import_react3.useRef)([]);
|
|
@@ -2090,9 +2580,15 @@ function AssistSheet({
|
|
|
2090
2580
|
if (el) el.scrollTop = el.scrollHeight;
|
|
2091
2581
|
}, [messages, busy, phase]);
|
|
2092
2582
|
(0, import_react3.useEffect)(() => {
|
|
2093
|
-
var
|
|
2094
|
-
if (phase === "draft") (
|
|
2583
|
+
var _a2;
|
|
2584
|
+
if (phase === "draft") (_a2 = draftRef.current) == null ? void 0 : _a2.focus();
|
|
2095
2585
|
}, [phase]);
|
|
2586
|
+
(0, import_react3.useEffect)(() => {
|
|
2587
|
+
const el = composerRef.current;
|
|
2588
|
+
if (!el) return;
|
|
2589
|
+
el.style.height = "auto";
|
|
2590
|
+
el.style.height = `${el.scrollHeight + 2}px`;
|
|
2591
|
+
}, [input]);
|
|
2096
2592
|
(0, import_react3.useEffect)(() => {
|
|
2097
2593
|
if (autoFileLeft === null) return;
|
|
2098
2594
|
if (isSubmitting || submitted || phase !== "draft") {
|
|
@@ -2117,7 +2613,8 @@ function AssistSheet({
|
|
|
2117
2613
|
onDegrade(message, retryable);
|
|
2118
2614
|
}
|
|
2119
2615
|
async function runTurn(history2, autoFile = false) {
|
|
2120
|
-
var
|
|
2616
|
+
var _a2, _b, _c;
|
|
2617
|
+
const turnChat = chatIdRef.current;
|
|
2121
2618
|
setBusy(true);
|
|
2122
2619
|
setAutoFileLeft(null);
|
|
2123
2620
|
let result;
|
|
@@ -2154,6 +2651,7 @@ function AssistSheet({
|
|
|
2154
2651
|
} finally {
|
|
2155
2652
|
setBusy(false);
|
|
2156
2653
|
}
|
|
2654
|
+
if (chatIdRef.current !== turnChat) return;
|
|
2157
2655
|
if (result.degraded) {
|
|
2158
2656
|
degradeKeepingEvents(events, result.degraded, result.retryable === true);
|
|
2159
2657
|
return;
|
|
@@ -2164,7 +2662,7 @@ function AssistSheet({
|
|
|
2164
2662
|
}
|
|
2165
2663
|
const attach = result.duplicate ? { ...result.duplicate, kind: "duplicate" } : result.related ? { ...result.related, kind: "related" } : null;
|
|
2166
2664
|
setDuplicate(attach);
|
|
2167
|
-
onDuplicateChange == null ? void 0 : onDuplicateChange((
|
|
2665
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange((_a2 = attach == null ? void 0 : attach.number) != null ? _a2 : null, attach == null ? void 0 : attach.kind);
|
|
2168
2666
|
setGlitchgrabOffer(!!result.aboutGlitchgrab && !!onReportGlitchgrabProblem && !!result.question);
|
|
2169
2667
|
if (result.solved) {
|
|
2170
2668
|
setSolved(result.solved);
|
|
@@ -2218,9 +2716,9 @@ function AssistSheet({
|
|
|
2218
2716
|
}
|
|
2219
2717
|
}
|
|
2220
2718
|
function sendTyped(text) {
|
|
2221
|
-
var
|
|
2719
|
+
var _a2;
|
|
2222
2720
|
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
|
2223
|
-
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((
|
|
2721
|
+
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((_a2 = lastAssistant == null ? void 0 : lastAssistant.content) != null ? _a2 : "");
|
|
2224
2722
|
send(text, checkingBack && isAffirmativeReply(text));
|
|
2225
2723
|
}
|
|
2226
2724
|
function send(text, autoFile = false) {
|
|
@@ -2262,7 +2760,215 @@ function AssistSheet({
|
|
|
2262
2760
|
flushEvents();
|
|
2263
2761
|
onSend();
|
|
2264
2762
|
}
|
|
2763
|
+
(0, import_react3.useEffect)(() => {
|
|
2764
|
+
if (!historyKey || !messages.some((m) => m.role === "user")) return;
|
|
2765
|
+
const done = submitted || phase === "solved";
|
|
2766
|
+
const kept = submitted || phase === "draft" ? withCurrentDraft(messages) : messages;
|
|
2767
|
+
setSavedChats(
|
|
2768
|
+
saveChat(historyKey, {
|
|
2769
|
+
id: chatIdRef.current,
|
|
2770
|
+
conversationId,
|
|
2771
|
+
title: chatTitle(kept),
|
|
2772
|
+
tile: currentTile,
|
|
2773
|
+
messages: kept,
|
|
2774
|
+
...issueTitle ? { issueTitle } : {},
|
|
2775
|
+
status: done ? "filed" : "open",
|
|
2776
|
+
...done ? {
|
|
2777
|
+
filedLabel: submitted ? submittedText != null ? submittedText : `${reportTypeLabel} sent` : "Answered \u2014 nothing was filed"
|
|
2778
|
+
} : {},
|
|
2779
|
+
updatedAt: Date.now()
|
|
2780
|
+
})
|
|
2781
|
+
);
|
|
2782
|
+
}, [
|
|
2783
|
+
historyKey,
|
|
2784
|
+
messages,
|
|
2785
|
+
conversationId,
|
|
2786
|
+
submitted,
|
|
2787
|
+
phase === "solved",
|
|
2788
|
+
issueTitle,
|
|
2789
|
+
phase === "draft" ? description : null
|
|
2790
|
+
]);
|
|
2791
|
+
function resumeChat(chat) {
|
|
2792
|
+
var _a2;
|
|
2793
|
+
flushEvents();
|
|
2794
|
+
chatIdRef.current = chat.id;
|
|
2795
|
+
setMessages(chat.messages);
|
|
2796
|
+
setConversationId(chat.conversationId);
|
|
2797
|
+
onConversationChange == null ? void 0 : onConversationChange(chat.conversationId);
|
|
2798
|
+
setOptions([]);
|
|
2799
|
+
setDuplicate(null);
|
|
2800
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2801
|
+
setGlitchgrabOffer(false);
|
|
2802
|
+
setAutoFileLeft(null);
|
|
2803
|
+
setInput("");
|
|
2804
|
+
if (chat.tile !== currentTile && tiles.includes(chat.tile)) {
|
|
2805
|
+
onPickType(chat.tile);
|
|
2806
|
+
}
|
|
2807
|
+
const last = chat.messages[chat.messages.length - 1];
|
|
2808
|
+
if ((last == null ? void 0 : last.kind) === "report") {
|
|
2809
|
+
onDescriptionChange(last.content);
|
|
2810
|
+
onIssueTitleChange((_a2 = chat.issueTitle) != null ? _a2 : "");
|
|
2811
|
+
aiDraftRef.current = last.content;
|
|
2812
|
+
setPhase("draft");
|
|
2813
|
+
} else {
|
|
2814
|
+
setPhase("chat");
|
|
2815
|
+
}
|
|
2816
|
+
setShowChats(false);
|
|
2817
|
+
setViewingChat(null);
|
|
2818
|
+
}
|
|
2819
|
+
function startNewChat() {
|
|
2820
|
+
flushEvents();
|
|
2821
|
+
chatIdRef.current = newChatId();
|
|
2822
|
+
setMessages([]);
|
|
2823
|
+
setConversationId(null);
|
|
2824
|
+
onConversationChange == null ? void 0 : onConversationChange(null);
|
|
2825
|
+
setOptions([]);
|
|
2826
|
+
setDuplicate(null);
|
|
2827
|
+
onDuplicateChange == null ? void 0 : onDuplicateChange(null);
|
|
2828
|
+
setGlitchgrabOffer(false);
|
|
2829
|
+
setAutoFileLeft(null);
|
|
2830
|
+
setInput("");
|
|
2831
|
+
onDescriptionChange("");
|
|
2832
|
+
onIssueTitleChange("");
|
|
2833
|
+
aiDraftRef.current = null;
|
|
2834
|
+
setPhase("chat");
|
|
2835
|
+
setShowChats(false);
|
|
2836
|
+
setViewingChat(null);
|
|
2837
|
+
}
|
|
2838
|
+
function forgetChat(id) {
|
|
2839
|
+
if (!historyKey) return;
|
|
2840
|
+
setSavedChats(removeChat(historyKey, id));
|
|
2841
|
+
if (viewingChat === id) setViewingChat(null);
|
|
2842
|
+
}
|
|
2843
|
+
const otherChats = savedChats.filter((c) => c.id !== chatIdRef.current);
|
|
2844
|
+
const resumable = (_a = otherChats.find((c) => c.status === "open" && c.messages.length > 0)) != null ? _a : null;
|
|
2265
2845
|
const empty = phase === "chat" && messages.length === 0 && !busy;
|
|
2846
|
+
function renderChatList() {
|
|
2847
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { "data-gg-chat-list": "", style: { display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
2849
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: "Your chats" }),
|
|
2850
|
+
messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2851
|
+
"button",
|
|
2852
|
+
{
|
|
2853
|
+
type: "button",
|
|
2854
|
+
"data-gg-new-chat": "",
|
|
2855
|
+
onClick: startNewChat,
|
|
2856
|
+
style: {
|
|
2857
|
+
border: `1px solid ${t.inputBorder}`,
|
|
2858
|
+
borderRadius: "999px",
|
|
2859
|
+
background: "transparent",
|
|
2860
|
+
color: t.text,
|
|
2861
|
+
padding: "7px 12px",
|
|
2862
|
+
fontSize: "12px",
|
|
2863
|
+
fontFamily: "inherit",
|
|
2864
|
+
cursor: "pointer"
|
|
2865
|
+
},
|
|
2866
|
+
children: "+ New chat"
|
|
2867
|
+
}
|
|
2868
|
+
)
|
|
2869
|
+
] }),
|
|
2870
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "11.5px", color: t.textMuted, lineHeight: 1.5 }, children: "Kept in this browser only, for 30 days." }),
|
|
2871
|
+
otherChats.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "12.5px", color: t.textMuted, padding: "12px 0" }, children: "No other chats yet." }),
|
|
2872
|
+
otherChats.map((chat) => {
|
|
2873
|
+
var _a2;
|
|
2874
|
+
const filed = chat.status === "filed";
|
|
2875
|
+
const open = viewingChat === chat.id;
|
|
2876
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2877
|
+
"div",
|
|
2878
|
+
{
|
|
2879
|
+
"data-gg-saved-chat": chat.status,
|
|
2880
|
+
style: {
|
|
2881
|
+
border: `1px solid ${t.border}`,
|
|
2882
|
+
borderRadius: "10px",
|
|
2883
|
+
padding: "10px 12px",
|
|
2884
|
+
display: "flex",
|
|
2885
|
+
flexDirection: "column",
|
|
2886
|
+
gap: "6px",
|
|
2887
|
+
minWidth: 0
|
|
2888
|
+
},
|
|
2889
|
+
children: [
|
|
2890
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-start", minWidth: 0 }, children: [
|
|
2891
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2892
|
+
"button",
|
|
2893
|
+
{
|
|
2894
|
+
type: "button",
|
|
2895
|
+
onClick: () => filed ? setViewingChat(open ? null : chat.id) : resumeChat(chat),
|
|
2896
|
+
style: {
|
|
2897
|
+
flex: 1,
|
|
2898
|
+
minWidth: 0,
|
|
2899
|
+
textAlign: "left",
|
|
2900
|
+
border: "none",
|
|
2901
|
+
background: "transparent",
|
|
2902
|
+
color: t.text,
|
|
2903
|
+
padding: 0,
|
|
2904
|
+
fontFamily: "inherit",
|
|
2905
|
+
cursor: "pointer",
|
|
2906
|
+
display: "flex",
|
|
2907
|
+
flexDirection: "column",
|
|
2908
|
+
gap: "4px"
|
|
2909
|
+
},
|
|
2910
|
+
children: [
|
|
2911
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { fontSize: "13px", lineHeight: 1.45, overflowWrap: "anywhere" }, children: chat.title || "Untitled chat" }),
|
|
2912
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
2913
|
+
filed ? (_a2 = chat.filedLabel) != null ? _a2 : "Sent" : "Not sent yet \u2014 tap to continue",
|
|
2914
|
+
" \xB7",
|
|
2915
|
+
" ",
|
|
2916
|
+
chatAge(chat.updatedAt)
|
|
2917
|
+
] })
|
|
2918
|
+
]
|
|
2919
|
+
}
|
|
2920
|
+
),
|
|
2921
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2922
|
+
"button",
|
|
2923
|
+
{
|
|
2924
|
+
type: "button",
|
|
2925
|
+
"aria-label": `Delete chat: ${chat.title}`,
|
|
2926
|
+
onClick: () => forgetChat(chat.id),
|
|
2927
|
+
style: {
|
|
2928
|
+
flexShrink: 0,
|
|
2929
|
+
border: "none",
|
|
2930
|
+
background: "transparent",
|
|
2931
|
+
color: t.textMuted,
|
|
2932
|
+
fontSize: "16px",
|
|
2933
|
+
lineHeight: 1,
|
|
2934
|
+
padding: "4px 6px",
|
|
2935
|
+
cursor: "pointer",
|
|
2936
|
+
fontFamily: "inherit"
|
|
2937
|
+
},
|
|
2938
|
+
children: "\xD7"
|
|
2939
|
+
}
|
|
2940
|
+
)
|
|
2941
|
+
] }),
|
|
2942
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2943
|
+
"div",
|
|
2944
|
+
{
|
|
2945
|
+
"data-gg-saved-transcript": "",
|
|
2946
|
+
style: {
|
|
2947
|
+
display: "flex",
|
|
2948
|
+
flexDirection: "column",
|
|
2949
|
+
gap: "6px",
|
|
2950
|
+
borderTop: `1px solid ${t.border}`,
|
|
2951
|
+
paddingTop: "8px",
|
|
2952
|
+
fontSize: "12.5px",
|
|
2953
|
+
lineHeight: 1.5
|
|
2954
|
+
},
|
|
2955
|
+
children: chat.messages.map((m, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { minWidth: 0, overflowWrap: "anywhere" }, children: [
|
|
2956
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { color: t.textMuted, fontWeight: 600 }, children: [
|
|
2957
|
+
m.role === "user" ? "You" : m.kind === "report" ? "Report" : "Assistant",
|
|
2958
|
+
":",
|
|
2959
|
+
" "
|
|
2960
|
+
] }),
|
|
2961
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { whiteSpace: "pre-wrap" }, children: m.content })
|
|
2962
|
+
] }, i))
|
|
2963
|
+
}
|
|
2964
|
+
)
|
|
2965
|
+
]
|
|
2966
|
+
},
|
|
2967
|
+
chat.id
|
|
2968
|
+
);
|
|
2969
|
+
})
|
|
2970
|
+
] });
|
|
2971
|
+
}
|
|
2266
2972
|
function renderKnownIssue({ title, footer }) {
|
|
2267
2973
|
if (!duplicate) return null;
|
|
2268
2974
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
@@ -2296,8 +3002,8 @@ function AssistSheet({
|
|
|
2296
3002
|
);
|
|
2297
3003
|
}
|
|
2298
3004
|
const initials2 = (reporterName != null ? reporterName : "").split(/\s+/).filter(Boolean).slice(0, 2).map((w) => {
|
|
2299
|
-
var
|
|
2300
|
-
return (_b = (
|
|
3005
|
+
var _a2, _b;
|
|
3006
|
+
return (_b = (_a2 = w[0]) == null ? void 0 : _a2.toUpperCase()) != null ? _b : "";
|
|
2301
3007
|
}).join("");
|
|
2302
3008
|
const panelStyle = narrow ? {
|
|
2303
3009
|
width: "100%",
|
|
@@ -2319,6 +3025,7 @@ function AssistSheet({
|
|
|
2319
3025
|
@keyframes gg-sheet-up{from{transform:translateY(24px);opacity:0}to{transform:translateY(0);opacity:1}}
|
|
2320
3026
|
@keyframes gg-sheet-fade{from{opacity:0}to{opacity:1}}
|
|
2321
3027
|
@keyframes gg-autofile{from{transform:scaleX(0)}to{transform:scaleX(1)}}
|
|
3028
|
+
@keyframes gg-spin{to{transform:rotate(360deg)}}
|
|
2322
3029
|
@keyframes gg-dot{0%,80%,100%{transform:translateY(0);opacity:.4}40%{transform:translateY(-3px);opacity:1}}
|
|
2323
3030
|
[data-gg-sheet-send]:focus-visible,[data-gg-chip]:focus-visible,[data-gg-assist-remove]:focus-visible,[data-gg-stop-auto-file]:focus-visible{outline:2px solid currentColor;outline-offset:2px}
|
|
2324
3031
|
` }),
|
|
@@ -2387,7 +3094,9 @@ function AssistSheet({
|
|
|
2387
3094
|
alignItems: "center",
|
|
2388
3095
|
gap: "7px",
|
|
2389
3096
|
fontSize: "14px",
|
|
2390
|
-
fontWeight: 600
|
|
3097
|
+
fontWeight: 600,
|
|
3098
|
+
// One line even with the Chats pill beside it (#567).
|
|
3099
|
+
whiteSpace: "nowrap"
|
|
2391
3100
|
},
|
|
2392
3101
|
children: [
|
|
2393
3102
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Sparkle, { color: t.accent }),
|
|
@@ -2417,34 +3126,64 @@ function AssistSheet({
|
|
|
2417
3126
|
projectSlot ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
|
|
2418
3127
|
] })
|
|
2419
3128
|
] }),
|
|
2420
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
3129
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "6px", flexShrink: 0 }, children: [
|
|
3130
|
+
historyKey && (showChats || otherChats.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3131
|
+
"button",
|
|
3132
|
+
{
|
|
3133
|
+
type: "button",
|
|
3134
|
+
"data-gg-chats-toggle": "",
|
|
3135
|
+
disabled: busy,
|
|
3136
|
+
"aria-pressed": showChats,
|
|
3137
|
+
onClick: () => {
|
|
3138
|
+
setShowChats((v) => !v);
|
|
3139
|
+
setViewingChat(null);
|
|
3140
|
+
},
|
|
3141
|
+
style: {
|
|
3142
|
+
flexShrink: 0,
|
|
3143
|
+
border: `1px solid ${showChats ? t.accent : t.inputBorder}`,
|
|
3144
|
+
borderRadius: "999px",
|
|
3145
|
+
background: "transparent",
|
|
3146
|
+
color: showChats ? t.accent : t.textMuted,
|
|
3147
|
+
cursor: busy ? "default" : "pointer",
|
|
3148
|
+
opacity: busy ? 0.5 : 1,
|
|
3149
|
+
fontSize: "11.5px",
|
|
3150
|
+
lineHeight: 1,
|
|
3151
|
+
fontFamily: "inherit",
|
|
3152
|
+
whiteSpace: "nowrap",
|
|
3153
|
+
padding: "9px 11px"
|
|
3154
|
+
},
|
|
3155
|
+
children: showChats ? "\u2190 Chat" : `Chats \xB7 ${otherChats.length}`
|
|
3156
|
+
}
|
|
3157
|
+
),
|
|
3158
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3159
|
+
"button",
|
|
3160
|
+
{
|
|
3161
|
+
type: "button",
|
|
3162
|
+
"data-gg-write-myself": "",
|
|
3163
|
+
onClick: () => leave("write_myself", `header, ${phase}`),
|
|
3164
|
+
"aria-label": "Write it myself instead",
|
|
3165
|
+
style: {
|
|
3166
|
+
flexShrink: 0,
|
|
3167
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3168
|
+
borderRadius: "999px",
|
|
3169
|
+
background: "transparent",
|
|
3170
|
+
color: t.textMuted,
|
|
3171
|
+
cursor: "pointer",
|
|
3172
|
+
fontSize: "11.5px",
|
|
3173
|
+
lineHeight: 1,
|
|
3174
|
+
fontFamily: "inherit",
|
|
3175
|
+
whiteSpace: "nowrap",
|
|
3176
|
+
// ~32px tall either way — this is the escape hatch, not a hint.
|
|
3177
|
+
padding: "9px 11px"
|
|
3178
|
+
},
|
|
3179
|
+
children: "Write it myself"
|
|
3180
|
+
}
|
|
3181
|
+
)
|
|
3182
|
+
] })
|
|
2444
3183
|
]
|
|
2445
3184
|
}
|
|
2446
3185
|
),
|
|
2447
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
3186
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2448
3187
|
"div",
|
|
2449
3188
|
{
|
|
2450
3189
|
ref: scrollRef,
|
|
@@ -2456,765 +3195,845 @@ function AssistSheet({
|
|
|
2456
3195
|
display: "flex",
|
|
2457
3196
|
flexDirection: "column"
|
|
2458
3197
|
},
|
|
2459
|
-
children:
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3198
|
+
children: [
|
|
3199
|
+
showChats && renderChatList(),
|
|
3200
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3201
|
+
"div",
|
|
3202
|
+
{
|
|
3203
|
+
style: {
|
|
3204
|
+
marginTop: "auto",
|
|
3205
|
+
display: "flex",
|
|
3206
|
+
flexDirection: "column",
|
|
3207
|
+
gap: "12px",
|
|
3208
|
+
minWidth: 0
|
|
3209
|
+
},
|
|
3210
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: showChats ? "none" : "contents" }, children: [
|
|
3211
|
+
phase === "type" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3212
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3213
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3214
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3215
|
+
"div",
|
|
3216
|
+
{
|
|
3217
|
+
style: {
|
|
3218
|
+
padding: "9px 12px",
|
|
3219
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3220
|
+
backgroundColor: t.bgSecondary,
|
|
3221
|
+
fontSize: "13px",
|
|
3222
|
+
lineHeight: 1.55,
|
|
3223
|
+
maxWidth: "88%"
|
|
3224
|
+
},
|
|
3225
|
+
children: [
|
|
3226
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 w` : "W",
|
|
3227
|
+
"hat do you want to do? Pick one and I'll take it from there."
|
|
3228
|
+
]
|
|
3229
|
+
}
|
|
3230
|
+
)
|
|
3231
|
+
] }),
|
|
3232
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2474
3233
|
"div",
|
|
2475
3234
|
{
|
|
2476
3235
|
style: {
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
lineHeight: 1.55,
|
|
2482
|
-
maxWidth: "88%"
|
|
3236
|
+
display: "flex",
|
|
3237
|
+
flexWrap: "wrap",
|
|
3238
|
+
gap: "6px",
|
|
3239
|
+
paddingLeft: "32px"
|
|
2483
3240
|
},
|
|
2484
|
-
children:
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
3241
|
+
children: tiles.map((tile) => {
|
|
3242
|
+
const rate = tile === "RATING";
|
|
3243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3244
|
+
"button",
|
|
3245
|
+
{
|
|
3246
|
+
type: "button",
|
|
3247
|
+
"data-gg-chip": "",
|
|
3248
|
+
"data-gg-tile": tile,
|
|
3249
|
+
onClick: () => pickType(tile),
|
|
3250
|
+
style: {
|
|
3251
|
+
display: "inline-flex",
|
|
3252
|
+
alignItems: "center",
|
|
3253
|
+
gap: "5px",
|
|
3254
|
+
// The rating is the only tile that isn't a report, so
|
|
3255
|
+
// it wears the star colour the dialog's hero row uses
|
|
3256
|
+
// rather than hiding among the report types.
|
|
3257
|
+
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
3258
|
+
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
3259
|
+
color: rate ? "#f59e0b" : t.textMuted,
|
|
3260
|
+
borderRadius: "999px",
|
|
3261
|
+
// 8px vertical keeps the tap target at ~32px.
|
|
3262
|
+
padding: "8px 12px",
|
|
3263
|
+
fontSize: "12px",
|
|
3264
|
+
fontWeight: rate ? 600 : 400,
|
|
3265
|
+
fontFamily: "inherit",
|
|
3266
|
+
cursor: "pointer"
|
|
3267
|
+
},
|
|
3268
|
+
children: rate ? "\u2605 Rate us" : getTypeLabel(tile)
|
|
3269
|
+
},
|
|
3270
|
+
tile
|
|
3271
|
+
);
|
|
3272
|
+
})
|
|
2488
3273
|
}
|
|
2489
3274
|
)
|
|
2490
3275
|
] }),
|
|
2491
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
2492
|
-
"div",
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
3276
|
+
phase === "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3277
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3278
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3279
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3280
|
+
"div",
|
|
3281
|
+
{
|
|
3282
|
+
style: {
|
|
3283
|
+
padding: "9px 12px",
|
|
3284
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3285
|
+
backgroundColor: t.bgSecondary,
|
|
3286
|
+
fontSize: "13px",
|
|
3287
|
+
lineHeight: 1.55,
|
|
3288
|
+
maxWidth: "88%"
|
|
3289
|
+
},
|
|
3290
|
+
children: "How bad is it?"
|
|
3291
|
+
}
|
|
3292
|
+
)
|
|
3293
|
+
] }),
|
|
3294
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3295
|
+
"div",
|
|
3296
|
+
{
|
|
3297
|
+
role: "radiogroup",
|
|
3298
|
+
"aria-label": "Severity",
|
|
3299
|
+
style: {
|
|
3300
|
+
display: "flex",
|
|
3301
|
+
flexWrap: "wrap",
|
|
3302
|
+
gap: "6px",
|
|
3303
|
+
paddingLeft: "32px"
|
|
3304
|
+
},
|
|
3305
|
+
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2503
3306
|
"button",
|
|
2504
3307
|
{
|
|
2505
3308
|
type: "button",
|
|
3309
|
+
role: "radio",
|
|
3310
|
+
"aria-checked": severity === s,
|
|
2506
3311
|
"data-gg-chip": "",
|
|
2507
|
-
"data-gg-
|
|
2508
|
-
onClick: () =>
|
|
3312
|
+
"data-gg-severity": s,
|
|
3313
|
+
onClick: () => answerSeverity(s),
|
|
2509
3314
|
style: {
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
// The rating is the only tile that isn't a report, so
|
|
2514
|
-
// it wears the star colour the dialog's hero row uses
|
|
2515
|
-
// rather than hiding among the report types.
|
|
2516
|
-
border: `1px solid ${rate ? "rgba(245,158,11,0.5)" : t.inputBorder}`,
|
|
2517
|
-
background: rate ? "rgba(245,158,11,0.08)" : "transparent",
|
|
2518
|
-
color: rate ? "#f59e0b" : t.textMuted,
|
|
3315
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3316
|
+
background: "transparent",
|
|
3317
|
+
color: t.textMuted,
|
|
2519
3318
|
borderRadius: "999px",
|
|
2520
|
-
//
|
|
3319
|
+
// Same as the picker and option chips — one chip size.
|
|
2521
3320
|
padding: "8px 12px",
|
|
2522
3321
|
fontSize: "12px",
|
|
2523
|
-
fontWeight: rate ? 600 : 400,
|
|
2524
3322
|
fontFamily: "inherit",
|
|
2525
3323
|
cursor: "pointer"
|
|
2526
3324
|
},
|
|
2527
|
-
children:
|
|
3325
|
+
children: SEVERITY_LABELS[s]
|
|
2528
3326
|
},
|
|
2529
|
-
|
|
2530
|
-
)
|
|
2531
|
-
})
|
|
2532
|
-
}
|
|
2533
|
-
)
|
|
2534
|
-
] }),
|
|
2535
|
-
phase === "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2536
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2537
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2538
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2539
|
-
"div",
|
|
2540
|
-
{
|
|
2541
|
-
style: {
|
|
2542
|
-
padding: "9px 12px",
|
|
2543
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2544
|
-
backgroundColor: t.bgSecondary,
|
|
2545
|
-
fontSize: "13px",
|
|
2546
|
-
lineHeight: 1.55,
|
|
2547
|
-
maxWidth: "88%"
|
|
2548
|
-
},
|
|
2549
|
-
children: "How bad is it?"
|
|
3327
|
+
s
|
|
3328
|
+
))
|
|
2550
3329
|
}
|
|
2551
3330
|
)
|
|
2552
3331
|
] }),
|
|
2553
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
2554
|
-
"div",
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
style: {
|
|
2559
|
-
display: "flex",
|
|
2560
|
-
flexWrap: "wrap",
|
|
2561
|
-
gap: "6px",
|
|
2562
|
-
paddingLeft: "32px"
|
|
2563
|
-
},
|
|
2564
|
-
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2565
|
-
"button",
|
|
3332
|
+
phase === "rating" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3333
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3334
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3335
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3336
|
+
"div",
|
|
2566
3337
|
{
|
|
2567
|
-
type: "button",
|
|
2568
|
-
role: "radio",
|
|
2569
|
-
"aria-checked": severity === s,
|
|
2570
|
-
"data-gg-chip": "",
|
|
2571
|
-
"data-gg-severity": s,
|
|
2572
|
-
onClick: () => answerSeverity(s),
|
|
2573
3338
|
style: {
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
fontSize: "12px",
|
|
2581
|
-
fontFamily: "inherit",
|
|
2582
|
-
cursor: "pointer"
|
|
3339
|
+
padding: "9px 12px",
|
|
3340
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3341
|
+
backgroundColor: t.bgSecondary,
|
|
3342
|
+
fontSize: "13px",
|
|
3343
|
+
lineHeight: 1.55,
|
|
3344
|
+
maxWidth: "88%"
|
|
2583
3345
|
},
|
|
2584
|
-
children:
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
)
|
|
2590
|
-
] }),
|
|
2591
|
-
phase === "rating" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2592
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2593
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2594
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3346
|
+
children: "How are we doing? Tap a star \u2014 the words are optional."
|
|
3347
|
+
}
|
|
3348
|
+
)
|
|
3349
|
+
] }),
|
|
3350
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2595
3351
|
"div",
|
|
2596
3352
|
{
|
|
2597
3353
|
style: {
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
3354
|
+
display: "flex",
|
|
3355
|
+
flexDirection: "column",
|
|
3356
|
+
gap: "10px",
|
|
3357
|
+
marginLeft: "32px",
|
|
3358
|
+
padding: "12px",
|
|
3359
|
+
borderRadius: "12px",
|
|
3360
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
3361
|
+
backgroundColor: "rgba(245,158,11,0.06)"
|
|
2604
3362
|
},
|
|
2605
|
-
children:
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
3363
|
+
children: [
|
|
3364
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: "4px" }, role: "group", "aria-label": "Rating", children: [1, 2, 3, 4, 5].map((star) => {
|
|
3365
|
+
const filled = star <= (hoveredStar || rating);
|
|
3366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3367
|
+
"button",
|
|
3368
|
+
{
|
|
3369
|
+
type: "button",
|
|
3370
|
+
"aria-label": `${star} star${star > 1 ? "s" : ""}`,
|
|
3371
|
+
"aria-pressed": star <= rating,
|
|
3372
|
+
onClick: () => onRatingChange(star),
|
|
3373
|
+
onMouseEnter: () => setHoveredStar(star),
|
|
3374
|
+
onMouseLeave: () => setHoveredStar(0),
|
|
3375
|
+
style: {
|
|
3376
|
+
border: "none",
|
|
3377
|
+
background: "transparent",
|
|
3378
|
+
padding: 0,
|
|
3379
|
+
cursor: "pointer",
|
|
3380
|
+
lineHeight: 0
|
|
3381
|
+
},
|
|
3382
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "30", height: "30", viewBox: "0 0 24 24", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3383
|
+
"path",
|
|
3384
|
+
{
|
|
3385
|
+
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",
|
|
3386
|
+
fill: filled ? "#f59e0b" : "transparent",
|
|
3387
|
+
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
3388
|
+
strokeWidth: "1.5",
|
|
3389
|
+
strokeLinejoin: "round"
|
|
3390
|
+
}
|
|
3391
|
+
) })
|
|
3392
|
+
},
|
|
3393
|
+
star
|
|
3394
|
+
);
|
|
3395
|
+
}) }),
|
|
3396
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3397
|
+
"textarea",
|
|
3398
|
+
{
|
|
3399
|
+
value: description,
|
|
3400
|
+
onChange: (e) => onDescriptionChange(e.target.value),
|
|
3401
|
+
rows: 3,
|
|
3402
|
+
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
3403
|
+
style: {
|
|
3404
|
+
width: "100%",
|
|
3405
|
+
padding: "10px",
|
|
3406
|
+
borderRadius: "8px",
|
|
3407
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3408
|
+
backgroundColor: t.inputBg,
|
|
3409
|
+
color: t.text,
|
|
3410
|
+
fontSize: "13px",
|
|
3411
|
+
lineHeight: 1.5,
|
|
3412
|
+
fontFamily: "inherit",
|
|
3413
|
+
resize: "vertical",
|
|
3414
|
+
outline: "none",
|
|
3415
|
+
boxSizing: "border-box"
|
|
3416
|
+
}
|
|
3417
|
+
}
|
|
3418
|
+
),
|
|
3419
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2626
3420
|
"button",
|
|
2627
3421
|
{
|
|
2628
3422
|
type: "button",
|
|
2629
|
-
|
|
2630
|
-
"aria-pressed": star <= rating,
|
|
2631
|
-
onClick: () => onRatingChange(star),
|
|
2632
|
-
onMouseEnter: () => setHoveredStar(star),
|
|
2633
|
-
onMouseLeave: () => setHoveredStar(0),
|
|
3423
|
+
onClick: () => setPhase("type"),
|
|
2634
3424
|
style: {
|
|
3425
|
+
alignSelf: "flex-start",
|
|
2635
3426
|
border: "none",
|
|
2636
3427
|
background: "transparent",
|
|
2637
|
-
|
|
3428
|
+
color: t.textMuted,
|
|
3429
|
+
fontSize: "12px",
|
|
3430
|
+
fontFamily: "inherit",
|
|
3431
|
+
// A bare text link is ~14px tall — half a thumb.
|
|
3432
|
+
padding: "9px 0",
|
|
2638
3433
|
cursor: "pointer",
|
|
2639
|
-
|
|
3434
|
+
textDecoration: "underline"
|
|
2640
3435
|
},
|
|
2641
|
-
children:
|
|
2642
|
-
"path",
|
|
2643
|
-
{
|
|
2644
|
-
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",
|
|
2645
|
-
fill: filled ? "#f59e0b" : "transparent",
|
|
2646
|
-
stroke: filled ? "#f59e0b" : t.inputBorder,
|
|
2647
|
-
strokeWidth: "1.5",
|
|
2648
|
-
strokeLinejoin: "round"
|
|
2649
|
-
}
|
|
2650
|
-
) })
|
|
2651
|
-
},
|
|
2652
|
-
star
|
|
2653
|
-
);
|
|
2654
|
-
}) }),
|
|
2655
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2656
|
-
"textarea",
|
|
2657
|
-
{
|
|
2658
|
-
value: description,
|
|
2659
|
-
onChange: (e) => onDescriptionChange(e.target.value),
|
|
2660
|
-
rows: 3,
|
|
2661
|
-
placeholder: "What made it good \u2014 or what let you down? (optional)",
|
|
2662
|
-
style: {
|
|
2663
|
-
width: "100%",
|
|
2664
|
-
padding: "10px",
|
|
2665
|
-
borderRadius: "8px",
|
|
2666
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2667
|
-
backgroundColor: t.inputBg,
|
|
2668
|
-
color: t.text,
|
|
2669
|
-
fontSize: "13px",
|
|
2670
|
-
lineHeight: 1.5,
|
|
2671
|
-
fontFamily: "inherit",
|
|
2672
|
-
resize: "vertical",
|
|
2673
|
-
outline: "none",
|
|
2674
|
-
boxSizing: "border-box"
|
|
3436
|
+
children: "Report something instead"
|
|
2675
3437
|
}
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
style: {
|
|
2684
|
-
alignSelf: "flex-start",
|
|
2685
|
-
border: "none",
|
|
2686
|
-
background: "transparent",
|
|
2687
|
-
color: t.textMuted,
|
|
2688
|
-
fontSize: "12px",
|
|
2689
|
-
fontFamily: "inherit",
|
|
2690
|
-
// A bare text link is ~14px tall — half a thumb.
|
|
2691
|
-
padding: "9px 0",
|
|
2692
|
-
cursor: "pointer",
|
|
2693
|
-
textDecoration: "underline"
|
|
2694
|
-
},
|
|
2695
|
-
children: "Report something instead"
|
|
2696
|
-
}
|
|
2697
|
-
)
|
|
2698
|
-
]
|
|
2699
|
-
}
|
|
2700
|
-
)
|
|
2701
|
-
] }),
|
|
2702
|
-
empty && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2703
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2704
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2705
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3438
|
+
)
|
|
3439
|
+
]
|
|
3440
|
+
}
|
|
3441
|
+
)
|
|
3442
|
+
] }),
|
|
3443
|
+
empty && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3444
|
+
resumable && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2706
3445
|
"div",
|
|
2707
3446
|
{
|
|
3447
|
+
"data-gg-resume-chat": "",
|
|
2708
3448
|
style: {
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
3449
|
+
display: "flex",
|
|
3450
|
+
flexDirection: "column",
|
|
3451
|
+
gap: "8px",
|
|
3452
|
+
padding: "10px 12px",
|
|
3453
|
+
borderRadius: "10px",
|
|
3454
|
+
border: `1px solid ${t.accent}55`,
|
|
3455
|
+
backgroundColor: t.bgSecondary,
|
|
3456
|
+
minWidth: 0
|
|
2715
3457
|
},
|
|
2716
3458
|
children: [
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
"button",
|
|
2734
|
-
{
|
|
2735
|
-
type: "button",
|
|
2736
|
-
"data-gg-chip": "",
|
|
2737
|
-
onClick: () => {
|
|
2738
|
-
logEvent("starter_tap", s);
|
|
2739
|
-
send(s);
|
|
2740
|
-
},
|
|
2741
|
-
style: {
|
|
2742
|
-
border: `1px solid ${t.inputBorder}`,
|
|
2743
|
-
background: "transparent",
|
|
2744
|
-
color: t.textMuted,
|
|
2745
|
-
borderRadius: "999px",
|
|
2746
|
-
padding: "6px 11px",
|
|
2747
|
-
fontSize: "12px",
|
|
2748
|
-
fontFamily: "inherit",
|
|
2749
|
-
cursor: "pointer"
|
|
2750
|
-
},
|
|
2751
|
-
children: s
|
|
2752
|
-
},
|
|
2753
|
-
s
|
|
2754
|
-
))
|
|
2755
|
-
}
|
|
2756
|
-
)
|
|
2757
|
-
] }),
|
|
2758
|
-
messages.map((m, i) => {
|
|
2759
|
-
const mine = m.role === "user";
|
|
2760
|
-
if (m.kind === "report") {
|
|
2761
|
-
const live = phase === "draft" && i === messages.length - 1;
|
|
2762
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
2763
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2764
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2765
|
-
"div",
|
|
2766
|
-
{
|
|
2767
|
-
"data-gg-draft-bubble": "",
|
|
2768
|
-
style: {
|
|
2769
|
-
maxWidth: "82%",
|
|
2770
|
-
minWidth: 0,
|
|
2771
|
-
padding: "9px 12px",
|
|
2772
|
-
borderRadius: "12px 12px 12px 4px",
|
|
2773
|
-
fontSize: "13px",
|
|
2774
|
-
lineHeight: 1.55,
|
|
2775
|
-
backgroundColor: t.bgSecondary,
|
|
2776
|
-
color: t.text,
|
|
2777
|
-
border: live ? "none" : `1px solid ${t.accent}66`
|
|
2778
|
-
},
|
|
2779
|
-
children: live ? (
|
|
2780
|
-
// #402: "have a read" beside a countdown reads as a
|
|
2781
|
-
// contradiction. Say what is about to happen instead.
|
|
2782
|
-
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."
|
|
2783
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3459
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3460
|
+
"Pick up where you left off \xB7 ",
|
|
3461
|
+
chatAge(resumable.updatedAt)
|
|
3462
|
+
] }),
|
|
3463
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3464
|
+
"span",
|
|
3465
|
+
{
|
|
3466
|
+
style: {
|
|
3467
|
+
fontSize: "13px",
|
|
3468
|
+
lineHeight: 1.45,
|
|
3469
|
+
overflowWrap: "anywhere"
|
|
3470
|
+
},
|
|
3471
|
+
children: resumable.title
|
|
3472
|
+
}
|
|
3473
|
+
),
|
|
3474
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap" }, children: [
|
|
2784
3475
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2785
|
-
"
|
|
3476
|
+
"button",
|
|
2786
3477
|
{
|
|
3478
|
+
type: "button",
|
|
3479
|
+
"data-gg-resume-continue": "",
|
|
3480
|
+
onClick: () => resumeChat(resumable),
|
|
2787
3481
|
style: {
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
3482
|
+
border: "none",
|
|
3483
|
+
borderRadius: "999px",
|
|
3484
|
+
backgroundColor: t.accent,
|
|
3485
|
+
color: t.accentText,
|
|
3486
|
+
padding: "7px 13px",
|
|
3487
|
+
fontSize: "12px",
|
|
3488
|
+
fontWeight: 600,
|
|
3489
|
+
fontFamily: "inherit",
|
|
3490
|
+
cursor: "pointer"
|
|
2795
3491
|
},
|
|
2796
|
-
children: "
|
|
3492
|
+
children: "Continue this chat"
|
|
2797
3493
|
}
|
|
2798
3494
|
),
|
|
2799
3495
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2800
|
-
"
|
|
3496
|
+
"button",
|
|
2801
3497
|
{
|
|
3498
|
+
type: "button",
|
|
3499
|
+
onClick: () => setShowChats(true),
|
|
2802
3500
|
style: {
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
3501
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3502
|
+
borderRadius: "999px",
|
|
3503
|
+
background: "transparent",
|
|
3504
|
+
color: t.textMuted,
|
|
3505
|
+
padding: "7px 13px",
|
|
3506
|
+
fontSize: "12px",
|
|
3507
|
+
fontFamily: "inherit",
|
|
3508
|
+
cursor: "pointer"
|
|
2809
3509
|
},
|
|
2810
|
-
children:
|
|
3510
|
+
children: "All chats"
|
|
2811
3511
|
}
|
|
2812
3512
|
)
|
|
2813
3513
|
] })
|
|
3514
|
+
]
|
|
3515
|
+
}
|
|
3516
|
+
),
|
|
3517
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3518
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3519
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3520
|
+
"div",
|
|
3521
|
+
{
|
|
3522
|
+
style: {
|
|
3523
|
+
padding: "9px 12px",
|
|
3524
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3525
|
+
backgroundColor: t.bgSecondary,
|
|
3526
|
+
fontSize: "13px",
|
|
3527
|
+
lineHeight: 1.55,
|
|
3528
|
+
maxWidth: "88%"
|
|
3529
|
+
},
|
|
3530
|
+
children: [
|
|
3531
|
+
reporterName ? `Hi ${reporterName.split(" ")[0]} \u2014 t` : "T",
|
|
3532
|
+
"ell me what went wrong in your own words. I can already see your screenshot and what you clicked, so skip the boring parts."
|
|
3533
|
+
]
|
|
2814
3534
|
}
|
|
2815
3535
|
)
|
|
2816
|
-
] },
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
children: [
|
|
2828
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
2829
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2830
|
-
"div",
|
|
2831
|
-
{
|
|
2832
|
-
style: {
|
|
2833
|
-
maxWidth: "82%",
|
|
2834
|
-
minWidth: 0,
|
|
2835
|
-
padding: "9px 12px",
|
|
2836
|
-
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
2837
|
-
fontSize: "13px",
|
|
2838
|
-
lineHeight: 1.55,
|
|
2839
|
-
// Markdown owns the assistant's line breaks and lists.
|
|
2840
|
-
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
2841
|
-
wordBreak: "break-word",
|
|
2842
|
-
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
2843
|
-
color: mine ? t.accentText : t.text
|
|
2844
|
-
},
|
|
2845
|
-
children: mine ? m.content : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChatMarkdown, { text: m.content, theme: t })
|
|
2846
|
-
}
|
|
2847
|
-
)
|
|
2848
|
-
]
|
|
2849
|
-
},
|
|
2850
|
-
i
|
|
2851
|
-
);
|
|
2852
|
-
}),
|
|
2853
|
-
duplicate && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
2854
|
-
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2855
|
-
"div",
|
|
2856
|
-
{
|
|
2857
|
-
"data-gg-glitchgrab-offer": "",
|
|
2858
|
-
style: {
|
|
2859
|
-
display: "flex",
|
|
2860
|
-
flexDirection: "column",
|
|
2861
|
-
gap: "8px",
|
|
2862
|
-
padding: "10px",
|
|
2863
|
-
borderRadius: "8px",
|
|
2864
|
-
border: `1px solid ${t.accent}55`,
|
|
2865
|
-
backgroundColor: `${t.accent}14`,
|
|
2866
|
-
fontSize: "12px",
|
|
2867
|
-
lineHeight: 1.5
|
|
2868
|
-
},
|
|
2869
|
-
children: [
|
|
2870
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
2871
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
2872
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
2873
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3536
|
+
] }),
|
|
3537
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3538
|
+
"div",
|
|
3539
|
+
{
|
|
3540
|
+
style: {
|
|
3541
|
+
display: "flex",
|
|
3542
|
+
flexWrap: "wrap",
|
|
3543
|
+
gap: "6px",
|
|
3544
|
+
paddingLeft: "32px"
|
|
3545
|
+
},
|
|
3546
|
+
children: STARTERS.map((s) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2874
3547
|
"button",
|
|
2875
3548
|
{
|
|
2876
3549
|
type: "button",
|
|
2877
|
-
"data-gg-
|
|
3550
|
+
"data-gg-chip": "",
|
|
2878
3551
|
onClick: () => {
|
|
2879
|
-
logEvent("
|
|
2880
|
-
|
|
2881
|
-
onReportGlitchgrabProblem(
|
|
2882
|
-
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
2883
|
-
);
|
|
3552
|
+
logEvent("starter_tap", s);
|
|
3553
|
+
send(s);
|
|
2884
3554
|
},
|
|
2885
3555
|
style: {
|
|
2886
|
-
|
|
3556
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3557
|
+
background: "transparent",
|
|
3558
|
+
color: t.textMuted,
|
|
2887
3559
|
borderRadius: "999px",
|
|
2888
|
-
|
|
2889
|
-
backgroundColor: t.accent,
|
|
2890
|
-
color: t.accentText,
|
|
3560
|
+
padding: "6px 11px",
|
|
2891
3561
|
fontSize: "12px",
|
|
2892
|
-
fontWeight: 700,
|
|
2893
3562
|
fontFamily: "inherit",
|
|
2894
|
-
cursor: "pointer"
|
|
2895
|
-
// Both stretch, so on a phone each wrapped line reads as
|
|
2896
|
-
// a choice rather than one button left stranded.
|
|
2897
|
-
flex: "1 1 auto"
|
|
3563
|
+
cursor: "pointer"
|
|
2898
3564
|
},
|
|
2899
|
-
children:
|
|
2900
|
-
}
|
|
2901
|
-
|
|
3565
|
+
children: s
|
|
3566
|
+
},
|
|
3567
|
+
s
|
|
3568
|
+
))
|
|
3569
|
+
}
|
|
3570
|
+
)
|
|
3571
|
+
] }),
|
|
3572
|
+
messages.map((m, i) => {
|
|
3573
|
+
const mine = m.role === "user";
|
|
3574
|
+
if (m.kind === "report") {
|
|
3575
|
+
const live = phase === "draft" && i === messages.length - 1;
|
|
3576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, children: [
|
|
3577
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
2902
3578
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2903
|
-
"
|
|
3579
|
+
"div",
|
|
2904
3580
|
{
|
|
2905
|
-
|
|
2906
|
-
"data-gg-glitchgrab-offer-no": "",
|
|
2907
|
-
onClick: () => {
|
|
2908
|
-
logEvent("glitchgrab_offer_declined");
|
|
2909
|
-
send("No \u2014 it's about this app, not the reporting tool");
|
|
2910
|
-
},
|
|
3581
|
+
"data-gg-draft-bubble": "",
|
|
2911
3582
|
style: {
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
3583
|
+
maxWidth: "82%",
|
|
3584
|
+
minWidth: 0,
|
|
3585
|
+
padding: "9px 12px",
|
|
3586
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3587
|
+
fontSize: "13px",
|
|
3588
|
+
lineHeight: 1.55,
|
|
3589
|
+
backgroundColor: t.bgSecondary,
|
|
3590
|
+
color: t.text,
|
|
3591
|
+
border: live ? "none" : `1px solid ${t.accent}66`
|
|
2921
3592
|
},
|
|
2922
|
-
children:
|
|
3593
|
+
children: live ? (
|
|
3594
|
+
// #402: "have a read" beside a countdown reads as a
|
|
3595
|
+
// contradiction. Say what is about to happen instead.
|
|
3596
|
+
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."
|
|
3597
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3598
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3599
|
+
"span",
|
|
3600
|
+
{
|
|
3601
|
+
style: {
|
|
3602
|
+
display: "block",
|
|
3603
|
+
fontSize: "10px",
|
|
3604
|
+
fontWeight: 700,
|
|
3605
|
+
letterSpacing: ".06em",
|
|
3606
|
+
textTransform: "uppercase",
|
|
3607
|
+
color: t.accent,
|
|
3608
|
+
marginBottom: "4px"
|
|
3609
|
+
},
|
|
3610
|
+
children: "Draft so far"
|
|
3611
|
+
}
|
|
3612
|
+
),
|
|
3613
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3614
|
+
"span",
|
|
3615
|
+
{
|
|
3616
|
+
style: {
|
|
3617
|
+
display: "block",
|
|
3618
|
+
whiteSpace: "pre-wrap",
|
|
3619
|
+
wordBreak: "break-word",
|
|
3620
|
+
maxHeight: "160px",
|
|
3621
|
+
overflowY: "auto",
|
|
3622
|
+
color: t.textMuted
|
|
3623
|
+
},
|
|
3624
|
+
children: m.content
|
|
3625
|
+
}
|
|
3626
|
+
)
|
|
3627
|
+
] })
|
|
2923
3628
|
}
|
|
2924
3629
|
)
|
|
2925
|
-
] })
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2930
|
-
"div",
|
|
2931
|
-
{
|
|
2932
|
-
style: {
|
|
2933
|
-
display: "flex",
|
|
2934
|
-
// Long labels wrapped into a ragged row that always stranded
|
|
2935
|
-
// the last chip on a line of its own. Past ~24 characters
|
|
2936
|
-
// these stop being chips and become a choice list, so they
|
|
2937
|
-
// stack full width and read like one.
|
|
2938
|
-
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
2939
|
-
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
2940
|
-
flexWrap: "wrap",
|
|
2941
|
-
gap: "6px",
|
|
2942
|
-
paddingLeft: "32px"
|
|
2943
|
-
},
|
|
2944
|
-
children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2945
|
-
"button",
|
|
3630
|
+
] }, i);
|
|
3631
|
+
}
|
|
3632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3633
|
+
"div",
|
|
2946
3634
|
{
|
|
2947
|
-
type: "button",
|
|
2948
|
-
"data-gg-chip": "",
|
|
2949
|
-
"data-gg-option": "",
|
|
2950
|
-
onClick: () => {
|
|
2951
|
-
logEvent("option_tap", option);
|
|
2952
|
-
send(option, option === CONFIRM_OPTION);
|
|
2953
|
-
},
|
|
2954
3635
|
style: {
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
// Same 8px as the picker chips — one tap target size in
|
|
2960
|
-
// this sheet, not two.
|
|
2961
|
-
padding: "8px 12px",
|
|
2962
|
-
fontSize: "12px",
|
|
2963
|
-
fontFamily: "inherit",
|
|
2964
|
-
cursor: "pointer",
|
|
2965
|
-
textAlign: "left"
|
|
3636
|
+
display: "flex",
|
|
3637
|
+
gap: "8px",
|
|
3638
|
+
minWidth: 0,
|
|
3639
|
+
flexDirection: mine ? "row-reverse" : "row"
|
|
2966
3640
|
},
|
|
2967
|
-
children:
|
|
3641
|
+
children: [
|
|
3642
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: m.role, theme: t, initials: initials2 }),
|
|
3643
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3644
|
+
"div",
|
|
3645
|
+
{
|
|
3646
|
+
style: {
|
|
3647
|
+
maxWidth: "82%",
|
|
3648
|
+
minWidth: 0,
|
|
3649
|
+
padding: "9px 12px",
|
|
3650
|
+
borderRadius: mine ? "12px 12px 4px 12px" : "12px 12px 12px 4px",
|
|
3651
|
+
fontSize: "13px",
|
|
3652
|
+
lineHeight: 1.55,
|
|
3653
|
+
// Markdown owns the assistant's line breaks and lists.
|
|
3654
|
+
whiteSpace: mine ? "pre-wrap" : "normal",
|
|
3655
|
+
wordBreak: "break-word",
|
|
3656
|
+
backgroundColor: mine ? t.accent : t.bgSecondary,
|
|
3657
|
+
color: mine ? t.accentText : t.text
|
|
3658
|
+
},
|
|
3659
|
+
children: mine ? m.content : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ChatMarkdown, { text: m.content, theme: t })
|
|
3660
|
+
}
|
|
3661
|
+
)
|
|
3662
|
+
]
|
|
2968
3663
|
},
|
|
2969
|
-
|
|
2970
|
-
)
|
|
2971
|
-
}
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2976
|
-
"span",
|
|
3664
|
+
i
|
|
3665
|
+
);
|
|
3666
|
+
}),
|
|
3667
|
+
duplicate && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: renderKnownIssue({ title: false }) }),
|
|
3668
|
+
glitchgrabOffer && onReportGlitchgrabProblem && !busy && phase === "chat" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { paddingLeft: "32px", minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3669
|
+
"div",
|
|
2977
3670
|
{
|
|
3671
|
+
"data-gg-glitchgrab-offer": "",
|
|
2978
3672
|
style: {
|
|
2979
|
-
display: "
|
|
2980
|
-
|
|
2981
|
-
gap: "
|
|
2982
|
-
padding: "
|
|
2983
|
-
borderRadius: "
|
|
2984
|
-
|
|
3673
|
+
display: "flex",
|
|
3674
|
+
flexDirection: "column",
|
|
3675
|
+
gap: "8px",
|
|
3676
|
+
padding: "10px",
|
|
3677
|
+
borderRadius: "8px",
|
|
3678
|
+
border: `1px solid ${t.accent}55`,
|
|
3679
|
+
backgroundColor: `${t.accent}14`,
|
|
3680
|
+
fontSize: "12px",
|
|
3681
|
+
lineHeight: 1.5
|
|
2985
3682
|
},
|
|
2986
|
-
children: [
|
|
2987
|
-
"span",
|
|
2988
|
-
{
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
3683
|
+
children: [
|
|
3684
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.text, fontWeight: 600 }, children: "This is about Glitchgrab, not this app" }),
|
|
3685
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: t.textMuted }, children: "It goes to the team that builds this reporter, with your chat attached." }),
|
|
3686
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexWrap: "wrap", gap: "6px" }, children: [
|
|
3687
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3688
|
+
"button",
|
|
3689
|
+
{
|
|
3690
|
+
type: "button",
|
|
3691
|
+
"data-gg-glitchgrab-offer-send": "",
|
|
3692
|
+
onClick: () => {
|
|
3693
|
+
logEvent("glitchgrab_offer_tap");
|
|
3694
|
+
setGlitchgrabOffer(false);
|
|
3695
|
+
onReportGlitchgrabProblem(
|
|
3696
|
+
messages.filter((m) => m.role === "user").map((m) => m.content.trim()).filter(Boolean).join("\n\n")
|
|
3697
|
+
);
|
|
3698
|
+
},
|
|
3699
|
+
style: {
|
|
3700
|
+
padding: "8px 12px",
|
|
3701
|
+
borderRadius: "999px",
|
|
3702
|
+
border: "none",
|
|
3703
|
+
backgroundColor: t.accent,
|
|
3704
|
+
color: t.accentText,
|
|
3705
|
+
fontSize: "12px",
|
|
3706
|
+
fontWeight: 700,
|
|
3707
|
+
fontFamily: "inherit",
|
|
3708
|
+
cursor: "pointer",
|
|
3709
|
+
// Both stretch, so on a phone each wrapped line reads as
|
|
3710
|
+
// a choice rather than one button left stranded.
|
|
3711
|
+
flex: "1 1 auto"
|
|
3712
|
+
},
|
|
3713
|
+
children: "Send to the Glitchgrab team"
|
|
3714
|
+
}
|
|
3715
|
+
),
|
|
3716
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3717
|
+
"button",
|
|
3718
|
+
{
|
|
3719
|
+
type: "button",
|
|
3720
|
+
"data-gg-glitchgrab-offer-no": "",
|
|
3721
|
+
onClick: () => {
|
|
3722
|
+
logEvent("glitchgrab_offer_declined");
|
|
3723
|
+
send("No \u2014 it's about this app, not the reporting tool");
|
|
3724
|
+
},
|
|
3725
|
+
style: {
|
|
3726
|
+
padding: "8px 12px",
|
|
3727
|
+
borderRadius: "999px",
|
|
3728
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3729
|
+
background: "transparent",
|
|
3730
|
+
color: t.textMuted,
|
|
3731
|
+
fontSize: "12px",
|
|
3732
|
+
fontFamily: "inherit",
|
|
3733
|
+
cursor: "pointer",
|
|
3734
|
+
flex: "1 1 auto"
|
|
3735
|
+
},
|
|
3736
|
+
children: "No, it's about this app"
|
|
3737
|
+
}
|
|
3738
|
+
)
|
|
3739
|
+
] })
|
|
3740
|
+
]
|
|
2999
3741
|
}
|
|
3000
|
-
)
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
"span",
|
|
3019
|
-
{
|
|
3020
|
-
style: {
|
|
3021
|
-
fontSize: "10px",
|
|
3022
|
-
fontWeight: 700,
|
|
3023
|
-
letterSpacing: ".06em",
|
|
3024
|
-
textTransform: "uppercase",
|
|
3025
|
-
color: t.accent
|
|
3026
|
-
},
|
|
3027
|
-
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3028
|
-
}
|
|
3029
|
-
),
|
|
3030
|
-
renderKnownIssue({
|
|
3031
|
-
title: true,
|
|
3032
|
-
footer: "Your details will be added to it instead of opening a new issue."
|
|
3033
|
-
}),
|
|
3034
|
-
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3035
|
-
// box edge is the very thing #543 is about. One line of text,
|
|
3036
|
-
// so Enter is swallowed.
|
|
3037
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3038
|
-
"textarea",
|
|
3742
|
+
) }),
|
|
3743
|
+
options.length > 0 && !busy && phase === "chat" && !glitchgrabOffer && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3744
|
+
"div",
|
|
3745
|
+
{
|
|
3746
|
+
style: {
|
|
3747
|
+
display: "flex",
|
|
3748
|
+
// Long labels wrapped into a ragged row that always stranded
|
|
3749
|
+
// the last chip on a line of its own. Past ~24 characters
|
|
3750
|
+
// these stop being chips and become a choice list, so they
|
|
3751
|
+
// stack full width and read like one.
|
|
3752
|
+
flexDirection: options.some((o) => o.length > 24) ? "column" : "row",
|
|
3753
|
+
alignItems: options.some((o) => o.length > 24) ? "stretch" : "flex-start",
|
|
3754
|
+
flexWrap: "wrap",
|
|
3755
|
+
gap: "6px",
|
|
3756
|
+
paddingLeft: "32px"
|
|
3757
|
+
},
|
|
3758
|
+
children: options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3759
|
+
"button",
|
|
3039
3760
|
{
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
},
|
|
3047
|
-
onChange: (e) => {
|
|
3048
|
-
stopAutoFile("edited the title");
|
|
3049
|
-
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3761
|
+
type: "button",
|
|
3762
|
+
"data-gg-chip": "",
|
|
3763
|
+
"data-gg-option": "",
|
|
3764
|
+
onClick: () => {
|
|
3765
|
+
logEvent("option_tap", option);
|
|
3766
|
+
send(option, option === CONFIRM_OPTION);
|
|
3050
3767
|
},
|
|
3051
3768
|
style: {
|
|
3052
|
-
width: "100%",
|
|
3053
|
-
padding: "8px 10px",
|
|
3054
|
-
lineHeight: 1.45,
|
|
3055
|
-
resize: "none",
|
|
3056
|
-
borderRadius: "8px",
|
|
3057
3769
|
border: `1px solid ${t.inputBorder}`,
|
|
3058
|
-
|
|
3059
|
-
color: t.
|
|
3060
|
-
|
|
3061
|
-
|
|
3770
|
+
background: "transparent",
|
|
3771
|
+
color: t.textMuted,
|
|
3772
|
+
borderRadius: "999px",
|
|
3773
|
+
// Same 8px as the picker chips — one tap target size in
|
|
3774
|
+
// this sheet, not two.
|
|
3775
|
+
padding: "8px 12px",
|
|
3776
|
+
fontSize: "12px",
|
|
3062
3777
|
fontFamily: "inherit",
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
}
|
|
3066
|
-
}
|
|
3067
|
-
),
|
|
3068
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3069
|
-
"textarea",
|
|
3070
|
-
{
|
|
3071
|
-
ref: draftRef,
|
|
3072
|
-
value: description,
|
|
3073
|
-
onChange: (e) => {
|
|
3074
|
-
stopAutoFile("edited the draft");
|
|
3075
|
-
onDescriptionChange(e.target.value);
|
|
3778
|
+
cursor: "pointer",
|
|
3779
|
+
textAlign: "left"
|
|
3076
3780
|
},
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3781
|
+
children: option
|
|
3782
|
+
},
|
|
3783
|
+
option
|
|
3784
|
+
))
|
|
3785
|
+
}
|
|
3786
|
+
),
|
|
3787
|
+
busy && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", minWidth: 0 }, role: "status", "aria-label": "Thinking", children: [
|
|
3788
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3789
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3790
|
+
"span",
|
|
3791
|
+
{
|
|
3792
|
+
style: {
|
|
3793
|
+
display: "inline-flex",
|
|
3794
|
+
alignItems: "center",
|
|
3795
|
+
// The "still working" line must wrap on a phone, not push
|
|
3796
|
+
// the bubble past the sheet's edge.
|
|
3797
|
+
flexWrap: "wrap",
|
|
3798
|
+
minWidth: 0,
|
|
3799
|
+
gap: "4px",
|
|
3800
|
+
padding: "12px",
|
|
3801
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3802
|
+
backgroundColor: t.bgSecondary
|
|
3803
|
+
},
|
|
3804
|
+
children: [
|
|
3805
|
+
[0, 1, 2].map((i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3806
|
+
"span",
|
|
3807
|
+
{
|
|
3808
|
+
style: {
|
|
3809
|
+
width: "5px",
|
|
3810
|
+
height: "5px",
|
|
3811
|
+
borderRadius: "50%",
|
|
3812
|
+
backgroundColor: t.textMuted,
|
|
3813
|
+
animation: `gg-dot 1.1s ease-in-out ${i * 0.15}s infinite`
|
|
3814
|
+
}
|
|
3815
|
+
},
|
|
3816
|
+
i
|
|
3817
|
+
)),
|
|
3818
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ThinkingClock, { color: t.textMuted })
|
|
3819
|
+
]
|
|
3820
|
+
}
|
|
3821
|
+
)
|
|
3822
|
+
] }),
|
|
3823
|
+
phase === "draft" && !submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3824
|
+
"div",
|
|
3825
|
+
{
|
|
3826
|
+
style: {
|
|
3827
|
+
border: `1px solid ${t.accent}`,
|
|
3828
|
+
borderRadius: "12px",
|
|
3829
|
+
backgroundColor: t.bgSecondary,
|
|
3830
|
+
padding: "12px",
|
|
3831
|
+
display: "flex",
|
|
3832
|
+
flexDirection: "column",
|
|
3833
|
+
gap: "10px",
|
|
3834
|
+
minWidth: 0,
|
|
3835
|
+
boxSizing: "border-box"
|
|
3836
|
+
},
|
|
3837
|
+
children: [
|
|
3838
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3097
3839
|
"span",
|
|
3098
3840
|
{
|
|
3099
|
-
style: {
|
|
3100
|
-
fontSize: "
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3841
|
+
style: {
|
|
3842
|
+
fontSize: "10px",
|
|
3843
|
+
fontWeight: 700,
|
|
3844
|
+
letterSpacing: ".06em",
|
|
3845
|
+
textTransform: "uppercase",
|
|
3846
|
+
color: t.accent
|
|
3847
|
+
},
|
|
3848
|
+
children: duplicate ? `What we'll add to #${duplicate.number}${duplicate.kind === "related" ? " as a related request" : ""} \xB7 edit anything` : "Your report \xB7 edit anything"
|
|
3849
|
+
}
|
|
3850
|
+
),
|
|
3851
|
+
renderKnownIssue({
|
|
3852
|
+
title: true,
|
|
3853
|
+
footer: "Your details will be added to it instead of opening a new issue."
|
|
3854
|
+
}),
|
|
3855
|
+
!duplicate && issueTitle && // Wraps rather than scrolls sideways: a title cut off at the
|
|
3856
|
+
// box edge is the very thing #543 is about. One line of text,
|
|
3857
|
+
// so Enter is swallowed.
|
|
3858
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3859
|
+
"textarea",
|
|
3860
|
+
{
|
|
3861
|
+
"aria-label": "Title",
|
|
3862
|
+
value: issueTitle,
|
|
3863
|
+
maxLength: 120,
|
|
3864
|
+
rows: 2,
|
|
3865
|
+
onKeyDown: (e) => {
|
|
3866
|
+
if (e.key === "Enter") e.preventDefault();
|
|
3104
3867
|
},
|
|
3105
|
-
|
|
3106
|
-
"
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3868
|
+
onChange: (e) => {
|
|
3869
|
+
stopAutoFile("edited the title");
|
|
3870
|
+
onIssueTitleChange(e.target.value.replace(/[\r\n]+/g, " "));
|
|
3871
|
+
},
|
|
3872
|
+
style: {
|
|
3873
|
+
width: "100%",
|
|
3874
|
+
padding: "8px 10px",
|
|
3875
|
+
lineHeight: 1.45,
|
|
3876
|
+
resize: "none",
|
|
3877
|
+
borderRadius: "8px",
|
|
3878
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3879
|
+
backgroundColor: t.inputBg,
|
|
3880
|
+
color: t.text,
|
|
3881
|
+
fontSize: "13px",
|
|
3882
|
+
fontWeight: 600,
|
|
3883
|
+
fontFamily: "inherit",
|
|
3884
|
+
outline: "none",
|
|
3885
|
+
boxSizing: "border-box"
|
|
3886
|
+
}
|
|
3119
3887
|
}
|
|
3120
3888
|
),
|
|
3121
3889
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3122
|
-
"
|
|
3890
|
+
"textarea",
|
|
3123
3891
|
{
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
fontFamily: "inherit",
|
|
3147
|
-
whiteSpace: "nowrap",
|
|
3148
|
-
overflow: "hidden",
|
|
3149
|
-
textOverflow: "ellipsis",
|
|
3150
|
-
cursor: "pointer"
|
|
3151
|
-
},
|
|
3152
|
-
children: SEVERITY_LABELS[s]
|
|
3153
|
-
},
|
|
3154
|
-
s
|
|
3155
|
-
);
|
|
3156
|
-
})
|
|
3892
|
+
ref: draftRef,
|
|
3893
|
+
value: description,
|
|
3894
|
+
onChange: (e) => {
|
|
3895
|
+
stopAutoFile("edited the draft");
|
|
3896
|
+
onDescriptionChange(e.target.value);
|
|
3897
|
+
},
|
|
3898
|
+
rows: 6,
|
|
3899
|
+
style: {
|
|
3900
|
+
width: "100%",
|
|
3901
|
+
minHeight: "120px",
|
|
3902
|
+
padding: "10px",
|
|
3903
|
+
borderRadius: "8px",
|
|
3904
|
+
border: `1px solid ${t.inputBorder}`,
|
|
3905
|
+
backgroundColor: t.inputBg,
|
|
3906
|
+
color: t.text,
|
|
3907
|
+
fontSize: "13px",
|
|
3908
|
+
lineHeight: 1.55,
|
|
3909
|
+
fontFamily: "inherit",
|
|
3910
|
+
resize: "vertical",
|
|
3911
|
+
outline: "none",
|
|
3912
|
+
boxSizing: "border-box"
|
|
3913
|
+
}
|
|
3157
3914
|
}
|
|
3158
|
-
)
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3915
|
+
),
|
|
3916
|
+
severityAsked && autoFileLeft === null && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
3917
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3918
|
+
"span",
|
|
3919
|
+
{
|
|
3920
|
+
style: {
|
|
3921
|
+
fontSize: "11.5px",
|
|
3922
|
+
color: t.textMuted,
|
|
3923
|
+
display: "block",
|
|
3924
|
+
marginBottom: "6px"
|
|
3925
|
+
},
|
|
3926
|
+
children: [
|
|
3927
|
+
"How bad is it?",
|
|
3928
|
+
!severity && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3929
|
+
"span",
|
|
3930
|
+
{
|
|
3931
|
+
style: {
|
|
3932
|
+
marginLeft: "6px",
|
|
3933
|
+
fontSize: "11px",
|
|
3934
|
+
color: severityRefused ? "#ef4444" : t.textMuted
|
|
3935
|
+
},
|
|
3936
|
+
children: "\xB7 required"
|
|
3937
|
+
}
|
|
3938
|
+
)
|
|
3939
|
+
]
|
|
3940
|
+
}
|
|
3941
|
+
),
|
|
3942
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3943
|
+
"div",
|
|
3944
|
+
{
|
|
3945
|
+
role: "radiogroup",
|
|
3946
|
+
"aria-label": "Severity",
|
|
3947
|
+
style: { display: "flex", gap: "6px" },
|
|
3948
|
+
children: SEVERITY_LEVELS.map((s) => {
|
|
3949
|
+
const on = severity === s;
|
|
3950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3951
|
+
"button",
|
|
3952
|
+
{
|
|
3953
|
+
type: "button",
|
|
3954
|
+
onClick: () => onSeverityChange(s),
|
|
3955
|
+
role: "radio",
|
|
3956
|
+
"aria-checked": on,
|
|
3957
|
+
style: {
|
|
3958
|
+
flex: 1,
|
|
3959
|
+
minWidth: 0,
|
|
3960
|
+
padding: "8px 2px",
|
|
3961
|
+
borderRadius: "8px",
|
|
3962
|
+
border: `1px solid ${on ? t.accent : severityRefused ? "#ef4444" : t.inputBorder}`,
|
|
3963
|
+
backgroundColor: on ? t.accent : "transparent",
|
|
3964
|
+
color: on ? t.accentText : t.textMuted,
|
|
3965
|
+
fontSize: "12px",
|
|
3966
|
+
fontWeight: 600,
|
|
3967
|
+
fontFamily: "inherit",
|
|
3968
|
+
whiteSpace: "nowrap",
|
|
3969
|
+
overflow: "hidden",
|
|
3970
|
+
textOverflow: "ellipsis",
|
|
3971
|
+
cursor: "pointer"
|
|
3972
|
+
},
|
|
3973
|
+
children: SEVERITY_LABELS[s]
|
|
3974
|
+
},
|
|
3975
|
+
s
|
|
3976
|
+
);
|
|
3977
|
+
})
|
|
3978
|
+
}
|
|
3979
|
+
)
|
|
3980
|
+
] }),
|
|
3981
|
+
attachmentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: [
|
|
3982
|
+
attachmentCount,
|
|
3983
|
+
" ",
|
|
3984
|
+
attachmentCount === 1 ? "attachment" : "attachments",
|
|
3985
|
+
" will be sent with this."
|
|
3986
|
+
] })
|
|
3987
|
+
]
|
|
3988
|
+
}
|
|
3989
|
+
),
|
|
3990
|
+
phase === "solved" && solved && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
3991
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
3992
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Avatar, { who: "assistant", theme: t }),
|
|
3993
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3994
|
+
"div",
|
|
3995
|
+
{
|
|
3996
|
+
style: {
|
|
3997
|
+
padding: "9px 12px",
|
|
3998
|
+
borderRadius: "12px 12px 12px 4px",
|
|
3999
|
+
backgroundColor: t.bgSecondary,
|
|
4000
|
+
fontSize: "13px",
|
|
4001
|
+
lineHeight: 1.55,
|
|
4002
|
+
maxWidth: "88%",
|
|
4003
|
+
whiteSpace: "pre-wrap"
|
|
4004
|
+
},
|
|
4005
|
+
children: solved
|
|
4006
|
+
}
|
|
4007
|
+
)
|
|
4008
|
+
] }),
|
|
3172
4009
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3173
|
-
"
|
|
4010
|
+
"span",
|
|
3174
4011
|
{
|
|
3175
|
-
style: {
|
|
3176
|
-
|
|
3177
|
-
borderRadius: "12px 12px 12px 4px",
|
|
3178
|
-
backgroundColor: t.bgSecondary,
|
|
3179
|
-
fontSize: "13px",
|
|
3180
|
-
lineHeight: 1.55,
|
|
3181
|
-
maxWidth: "88%",
|
|
3182
|
-
whiteSpace: "pre-wrap"
|
|
3183
|
-
},
|
|
3184
|
-
children: solved
|
|
4012
|
+
style: { fontSize: "11.5px", color: t.textMuted, paddingLeft: "32px" },
|
|
4013
|
+
children: "Nothing was filed \u2014 you are all set."
|
|
3185
4014
|
}
|
|
3186
4015
|
)
|
|
3187
4016
|
] }),
|
|
3188
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3189
|
-
"
|
|
4017
|
+
submitted && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4018
|
+
"div",
|
|
3190
4019
|
{
|
|
3191
|
-
style: {
|
|
3192
|
-
|
|
4020
|
+
style: {
|
|
4021
|
+
textAlign: "center",
|
|
4022
|
+
padding: "24px 0",
|
|
4023
|
+
color: t.accent,
|
|
4024
|
+
fontSize: "14px",
|
|
4025
|
+
fontWeight: 600
|
|
4026
|
+
},
|
|
4027
|
+
children: submittedText != null ? submittedText : `${reportTypeLabel} sent. Thank you!`
|
|
3193
4028
|
}
|
|
3194
4029
|
)
|
|
3195
|
-
] })
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
style: {
|
|
3200
|
-
textAlign: "center",
|
|
3201
|
-
padding: "24px 0",
|
|
3202
|
-
color: t.accent,
|
|
3203
|
-
fontSize: "14px",
|
|
3204
|
-
fontWeight: 600
|
|
3205
|
-
},
|
|
3206
|
-
children: [
|
|
3207
|
-
reportTypeLabel,
|
|
3208
|
-
" sent. Thank you!"
|
|
3209
|
-
]
|
|
3210
|
-
}
|
|
3211
|
-
)
|
|
3212
|
-
]
|
|
3213
|
-
}
|
|
3214
|
-
)
|
|
4030
|
+
] })
|
|
4031
|
+
}
|
|
4032
|
+
)
|
|
4033
|
+
]
|
|
3215
4034
|
}
|
|
3216
4035
|
),
|
|
3217
|
-
!submitted && phase !== "type" && phase !== "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
4036
|
+
!submitted && !showChats && phase !== "type" && phase !== "severity" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3218
4037
|
"div",
|
|
3219
4038
|
{
|
|
3220
4039
|
style: {
|
|
@@ -3272,342 +4091,363 @@ function AssistSheet({
|
|
|
3272
4091
|
// instead of remounting, and a draft is something you can
|
|
3273
4092
|
// still reply to (#360), not a form that replaced the chat.
|
|
3274
4093
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
4094
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: similarSlot ? "none" : "contents" }, children: [
|
|
4095
|
+
(screenshots.length > 0 || files.length > 0 || onAddFiles) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
4096
|
+
"div",
|
|
4097
|
+
{
|
|
4098
|
+
style: {
|
|
4099
|
+
display: "flex",
|
|
4100
|
+
gap: "8px",
|
|
4101
|
+
alignItems: "center",
|
|
4102
|
+
flexWrap: "wrap",
|
|
4103
|
+
marginBottom: "8px"
|
|
4104
|
+
},
|
|
4105
|
+
children: [
|
|
4106
|
+
screenshots.map((shot, i) => {
|
|
4107
|
+
const read = readShots.has(shot);
|
|
4108
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
4109
|
+
"div",
|
|
4110
|
+
{
|
|
4111
|
+
style: {
|
|
4112
|
+
position: "relative",
|
|
4113
|
+
width: "40px",
|
|
4114
|
+
height: "40px",
|
|
4115
|
+
flexShrink: 0
|
|
4116
|
+
},
|
|
4117
|
+
children: [
|
|
4118
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4119
|
+
"img",
|
|
4120
|
+
{
|
|
4121
|
+
src: shot,
|
|
4122
|
+
alt: read ? "Attached image the assistant reads" : "Attached image",
|
|
4123
|
+
"data-gg-assist-thumb": "",
|
|
4124
|
+
style: {
|
|
4125
|
+
display: "block",
|
|
4126
|
+
width: "100%",
|
|
4127
|
+
height: "100%",
|
|
4128
|
+
objectFit: "cover",
|
|
4129
|
+
borderRadius: "8px",
|
|
4130
|
+
border: `1px solid ${read ? t.accent : t.inputBorder}`,
|
|
4131
|
+
opacity: read ? 1 : 0.45,
|
|
4132
|
+
boxSizing: "border-box"
|
|
4133
|
+
}
|
|
3313
4134
|
}
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
}
|
|
3370
|
-
|
|
4135
|
+
),
|
|
4136
|
+
onRemoveImage && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4137
|
+
"button",
|
|
4138
|
+
{
|
|
4139
|
+
type: "button",
|
|
4140
|
+
"data-gg-assist-remove": "",
|
|
4141
|
+
"aria-label": `Remove image ${i + 1}`,
|
|
4142
|
+
title: "Remove this image",
|
|
4143
|
+
onClick: () => {
|
|
4144
|
+
stopAutoFile("changed attachments");
|
|
4145
|
+
logEvent(
|
|
4146
|
+
"image_removed",
|
|
4147
|
+
pageShot && shot === pageShot ? "page capture" : "attached"
|
|
4148
|
+
);
|
|
4149
|
+
onRemoveImage(i);
|
|
4150
|
+
},
|
|
4151
|
+
style: {
|
|
4152
|
+
position: "absolute",
|
|
4153
|
+
top: "-13px",
|
|
4154
|
+
right: "-13px",
|
|
4155
|
+
width: "32px",
|
|
4156
|
+
height: "32px",
|
|
4157
|
+
border: "none",
|
|
4158
|
+
background: "transparent",
|
|
4159
|
+
padding: 0,
|
|
4160
|
+
cursor: "pointer",
|
|
4161
|
+
display: "flex",
|
|
4162
|
+
alignItems: "center",
|
|
4163
|
+
justifyContent: "center",
|
|
4164
|
+
borderRadius: "50%"
|
|
4165
|
+
},
|
|
4166
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4167
|
+
"span",
|
|
4168
|
+
{
|
|
4169
|
+
"aria-hidden": "true",
|
|
4170
|
+
style: {
|
|
4171
|
+
width: "20px",
|
|
4172
|
+
height: "20px",
|
|
4173
|
+
boxSizing: "border-box",
|
|
4174
|
+
borderRadius: "50%",
|
|
4175
|
+
border: `2px solid ${t.bg}`,
|
|
4176
|
+
background: "#ef4444",
|
|
4177
|
+
color: "#fff",
|
|
4178
|
+
display: "flex",
|
|
4179
|
+
alignItems: "center",
|
|
4180
|
+
justifyContent: "center"
|
|
4181
|
+
},
|
|
4182
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4183
|
+
"path",
|
|
4184
|
+
{
|
|
4185
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
4186
|
+
stroke: "currentColor",
|
|
4187
|
+
strokeWidth: "1.6",
|
|
4188
|
+
strokeLinecap: "round"
|
|
4189
|
+
}
|
|
4190
|
+
) })
|
|
4191
|
+
}
|
|
4192
|
+
)
|
|
4193
|
+
}
|
|
4194
|
+
)
|
|
4195
|
+
]
|
|
4196
|
+
},
|
|
4197
|
+
`${i}-${shot.slice(-16)}`
|
|
4198
|
+
);
|
|
4199
|
+
}),
|
|
4200
|
+
files.map((file, i) => {
|
|
4201
|
+
const read = readFiles.has(i);
|
|
4202
|
+
const pdf = isPdfFile(file.name);
|
|
4203
|
+
const why = read ? "the assistant reads this file" : pdf && file.reading ? "reading the text in this PDF\u2026" : pdf && file.text !== void 0 ? file.text === null ? file.tooLarge ? "attached to the report \u2014 too large for the assistant to read (over 3 MB)" : "attached to the report \u2014 couldn't read this PDF" : file.text.trim() ? "attached, but more than one message can carry, so the assistant is not reading it" : "attached to the report \u2014 this PDF has no text to read (a scan?)" : isAssistReadableFile(file.name) ? "attached, but more than one message can carry, so the assistant is not reading it" : "attached to the report \u2014 the assistant can't read this kind of file";
|
|
4204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
4205
|
+
"div",
|
|
4206
|
+
{
|
|
4207
|
+
"data-gg-assist-file": "",
|
|
4208
|
+
"data-gg-assist-file-read": read ? "" : void 0,
|
|
4209
|
+
"data-gg-assist-file-reading": pdf && file.reading ? "" : void 0,
|
|
4210
|
+
title: `${file.name} \u2014 ${why}`,
|
|
4211
|
+
style: {
|
|
4212
|
+
position: "relative",
|
|
4213
|
+
height: "40px",
|
|
4214
|
+
maxWidth: "170px",
|
|
4215
|
+
display: "flex",
|
|
4216
|
+
alignItems: "center",
|
|
4217
|
+
gap: "6px",
|
|
4218
|
+
padding: "0 10px",
|
|
4219
|
+
borderRadius: "8px",
|
|
4220
|
+
border: `1px solid ${read ? t.accent : t.inputBorder}`,
|
|
4221
|
+
opacity: read || pdf && file.reading ? 1 : 0.55,
|
|
4222
|
+
boxSizing: "border-box",
|
|
4223
|
+
flexShrink: 0
|
|
4224
|
+
},
|
|
4225
|
+
children: [
|
|
4226
|
+
pdf && file.reading ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4227
|
+
"span",
|
|
4228
|
+
{
|
|
4229
|
+
role: "status",
|
|
4230
|
+
"aria-label": "Reading this PDF",
|
|
4231
|
+
style: {
|
|
4232
|
+
width: "12px",
|
|
4233
|
+
height: "12px",
|
|
4234
|
+
flexShrink: 0,
|
|
4235
|
+
borderRadius: "50%",
|
|
4236
|
+
border: `1.5px solid ${t.inputBorder}`,
|
|
4237
|
+
borderTopColor: t.accent,
|
|
4238
|
+
boxSizing: "border-box",
|
|
4239
|
+
animation: "gg-spin .8s linear infinite"
|
|
3371
4240
|
}
|
|
3372
|
-
|
|
3373
|
-
}
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
4241
|
+
}
|
|
4242
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", style: { flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4243
|
+
"path",
|
|
4244
|
+
{
|
|
4245
|
+
d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z M14 2v6h6",
|
|
4246
|
+
stroke: t.textMuted,
|
|
4247
|
+
strokeWidth: "1.5",
|
|
4248
|
+
strokeLinecap: "round",
|
|
4249
|
+
strokeLinejoin: "round"
|
|
4250
|
+
}
|
|
4251
|
+
) }),
|
|
4252
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4253
|
+
"span",
|
|
4254
|
+
{
|
|
4255
|
+
style: {
|
|
4256
|
+
fontSize: "11.5px",
|
|
4257
|
+
color: t.text,
|
|
4258
|
+
overflow: "hidden",
|
|
4259
|
+
textOverflow: "ellipsis",
|
|
4260
|
+
whiteSpace: "nowrap"
|
|
4261
|
+
},
|
|
4262
|
+
children: file.name
|
|
4263
|
+
}
|
|
4264
|
+
),
|
|
4265
|
+
onRemoveFile && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4266
|
+
"button",
|
|
4267
|
+
{
|
|
4268
|
+
type: "button",
|
|
4269
|
+
"data-gg-assist-remove-file": "",
|
|
4270
|
+
"aria-label": `Remove file ${file.name}`,
|
|
4271
|
+
title: "Remove this file",
|
|
4272
|
+
onClick: () => {
|
|
4273
|
+
stopAutoFile("changed attachments");
|
|
4274
|
+
logEvent("file_removed", read ? "read" : "not read");
|
|
4275
|
+
onRemoveFile(i);
|
|
4276
|
+
},
|
|
4277
|
+
style: {
|
|
4278
|
+
position: "absolute",
|
|
4279
|
+
top: "-13px",
|
|
4280
|
+
right: "-13px",
|
|
4281
|
+
width: "32px",
|
|
4282
|
+
height: "32px",
|
|
4283
|
+
border: "none",
|
|
4284
|
+
background: "transparent",
|
|
4285
|
+
padding: 0,
|
|
4286
|
+
cursor: "pointer",
|
|
4287
|
+
display: "flex",
|
|
4288
|
+
alignItems: "center",
|
|
4289
|
+
justifyContent: "center",
|
|
4290
|
+
borderRadius: "50%"
|
|
4291
|
+
},
|
|
4292
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4293
|
+
"span",
|
|
4294
|
+
{
|
|
4295
|
+
"aria-hidden": "true",
|
|
4296
|
+
style: {
|
|
4297
|
+
width: "20px",
|
|
4298
|
+
height: "20px",
|
|
4299
|
+
boxSizing: "border-box",
|
|
4300
|
+
borderRadius: "50%",
|
|
4301
|
+
border: `2px solid ${t.bg}`,
|
|
4302
|
+
background: "#ef4444",
|
|
4303
|
+
color: "#fff",
|
|
4304
|
+
display: "flex",
|
|
4305
|
+
alignItems: "center",
|
|
4306
|
+
justifyContent: "center"
|
|
4307
|
+
},
|
|
4308
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4309
|
+
"path",
|
|
4310
|
+
{
|
|
4311
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
4312
|
+
stroke: "currentColor",
|
|
4313
|
+
strokeWidth: "1.6",
|
|
4314
|
+
strokeLinecap: "round"
|
|
4315
|
+
}
|
|
4316
|
+
) })
|
|
4317
|
+
}
|
|
4318
|
+
)
|
|
4319
|
+
}
|
|
4320
|
+
)
|
|
4321
|
+
]
|
|
4322
|
+
},
|
|
4323
|
+
`file-${i}-${file.name}`
|
|
4324
|
+
);
|
|
4325
|
+
}),
|
|
4326
|
+
onAddFiles && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
4327
|
+
"label",
|
|
3385
4328
|
{
|
|
3386
|
-
"data-gg-assist-
|
|
3387
|
-
"
|
|
3388
|
-
title: `${file.name} \u2014 ${why}`,
|
|
4329
|
+
"data-gg-assist-attach": "",
|
|
4330
|
+
title: "Attach an image or a file (html, json, log\u2026) \u2014 or paste one",
|
|
3389
4331
|
style: {
|
|
3390
|
-
|
|
4332
|
+
width: "40px",
|
|
3391
4333
|
height: "40px",
|
|
3392
|
-
maxWidth: "170px",
|
|
3393
|
-
display: "flex",
|
|
3394
|
-
alignItems: "center",
|
|
3395
|
-
gap: "6px",
|
|
3396
|
-
padding: "0 10px",
|
|
3397
4334
|
borderRadius: "8px",
|
|
3398
|
-
border: `1px
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
),
|
|
3427
|
-
onRemoveFile && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3428
|
-
"button",
|
|
3429
|
-
{
|
|
3430
|
-
type: "button",
|
|
3431
|
-
"data-gg-assist-remove-file": "",
|
|
3432
|
-
"aria-label": `Remove file ${file.name}`,
|
|
3433
|
-
title: "Remove this file",
|
|
3434
|
-
onClick: () => {
|
|
3435
|
-
stopAutoFile("changed attachments");
|
|
3436
|
-
logEvent("file_removed", read ? "read" : "not read");
|
|
3437
|
-
onRemoveFile(i);
|
|
3438
|
-
},
|
|
3439
|
-
style: {
|
|
3440
|
-
position: "absolute",
|
|
3441
|
-
top: "-13px",
|
|
3442
|
-
right: "-13px",
|
|
3443
|
-
width: "32px",
|
|
3444
|
-
height: "32px",
|
|
3445
|
-
border: "none",
|
|
3446
|
-
background: "transparent",
|
|
3447
|
-
padding: 0,
|
|
3448
|
-
cursor: "pointer",
|
|
3449
|
-
display: "flex",
|
|
3450
|
-
alignItems: "center",
|
|
3451
|
-
justifyContent: "center",
|
|
3452
|
-
borderRadius: "50%"
|
|
3453
|
-
},
|
|
3454
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3455
|
-
"span",
|
|
3456
|
-
{
|
|
3457
|
-
"aria-hidden": "true",
|
|
3458
|
-
style: {
|
|
3459
|
-
width: "20px",
|
|
3460
|
-
height: "20px",
|
|
3461
|
-
boxSizing: "border-box",
|
|
3462
|
-
borderRadius: "50%",
|
|
3463
|
-
border: `2px solid ${t.bg}`,
|
|
3464
|
-
background: "#ef4444",
|
|
3465
|
-
color: "#fff",
|
|
3466
|
-
display: "flex",
|
|
3467
|
-
alignItems: "center",
|
|
3468
|
-
justifyContent: "center"
|
|
3469
|
-
},
|
|
3470
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "8", height: "8", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3471
|
-
"path",
|
|
3472
|
-
{
|
|
3473
|
-
d: "M1 1L9 9M9 1L1 9",
|
|
3474
|
-
stroke: "currentColor",
|
|
3475
|
-
strokeWidth: "1.6",
|
|
3476
|
-
strokeLinecap: "round"
|
|
3477
|
-
}
|
|
3478
|
-
) })
|
|
3479
|
-
}
|
|
3480
|
-
)
|
|
3481
|
-
}
|
|
3482
|
-
)
|
|
3483
|
-
]
|
|
3484
|
-
},
|
|
3485
|
-
`file-${i}-${file.name}`
|
|
3486
|
-
);
|
|
3487
|
-
}),
|
|
3488
|
-
onAddFiles && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
3489
|
-
"label",
|
|
3490
|
-
{
|
|
3491
|
-
"data-gg-assist-attach": "",
|
|
3492
|
-
title: "Attach an image or a file (html, json, log\u2026) \u2014 or paste one",
|
|
3493
|
-
style: {
|
|
3494
|
-
width: "40px",
|
|
3495
|
-
height: "40px",
|
|
3496
|
-
borderRadius: "8px",
|
|
3497
|
-
border: `1px dashed ${t.inputBorder}`,
|
|
3498
|
-
display: "inline-flex",
|
|
3499
|
-
alignItems: "center",
|
|
3500
|
-
justifyContent: "center",
|
|
3501
|
-
color: t.textMuted,
|
|
3502
|
-
fontSize: "18px",
|
|
3503
|
-
cursor: "pointer",
|
|
3504
|
-
flexShrink: 0
|
|
3505
|
-
},
|
|
3506
|
-
children: [
|
|
3507
|
-
"+",
|
|
3508
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3509
|
-
"input",
|
|
3510
|
-
{
|
|
3511
|
-
type: "file",
|
|
3512
|
-
accept: ASSIST_ATTACHMENT_ACCEPT,
|
|
3513
|
-
multiple: true,
|
|
3514
|
-
onChange: (e) => {
|
|
3515
|
-
var _a;
|
|
3516
|
-
const picked = Array.from((_a = e.target.files) != null ? _a : []);
|
|
3517
|
-
if (picked.length) {
|
|
3518
|
-
stopAutoFile("changed attachments");
|
|
3519
|
-
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
3520
|
-
if (images) logEvent("image_added", String(images));
|
|
3521
|
-
if (picked.length > images) {
|
|
3522
|
-
logEvent("file_added", String(picked.length - images));
|
|
4335
|
+
border: `1px dashed ${t.inputBorder}`,
|
|
4336
|
+
display: "inline-flex",
|
|
4337
|
+
alignItems: "center",
|
|
4338
|
+
justifyContent: "center",
|
|
4339
|
+
color: t.textMuted,
|
|
4340
|
+
fontSize: "18px",
|
|
4341
|
+
cursor: "pointer",
|
|
4342
|
+
flexShrink: 0
|
|
4343
|
+
},
|
|
4344
|
+
children: [
|
|
4345
|
+
"+",
|
|
4346
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4347
|
+
"input",
|
|
4348
|
+
{
|
|
4349
|
+
type: "file",
|
|
4350
|
+
accept: canReadPdf ? ASSIST_ATTACHMENT_ACCEPT_WITH_PDF : ASSIST_ATTACHMENT_ACCEPT,
|
|
4351
|
+
multiple: true,
|
|
4352
|
+
onChange: (e) => {
|
|
4353
|
+
var _a2;
|
|
4354
|
+
const picked = Array.from((_a2 = e.target.files) != null ? _a2 : []);
|
|
4355
|
+
if (picked.length) {
|
|
4356
|
+
stopAutoFile("changed attachments");
|
|
4357
|
+
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
4358
|
+
if (images) logEvent("image_added", String(images));
|
|
4359
|
+
if (picked.length > images) {
|
|
4360
|
+
logEvent("file_added", String(picked.length - images));
|
|
4361
|
+
}
|
|
4362
|
+
onAddFiles(picked);
|
|
3523
4363
|
}
|
|
3524
|
-
|
|
3525
|
-
}
|
|
3526
|
-
|
|
3527
|
-
}
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
}
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
] })
|
|
3540
|
-
]
|
|
3541
|
-
}
|
|
3542
|
-
),
|
|
3543
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
|
|
3544
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
3545
|
-
"textarea",
|
|
3546
|
-
{
|
|
3547
|
-
value: input,
|
|
3548
|
-
onChange: (e) => {
|
|
3549
|
-
stopAutoFile("typing a change");
|
|
3550
|
-
setInput(e.target.value);
|
|
3551
|
-
},
|
|
3552
|
-
onKeyDown: (e) => {
|
|
3553
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
3554
|
-
e.preventDefault();
|
|
3555
|
-
sendTyped(input);
|
|
3556
|
-
}
|
|
3557
|
-
},
|
|
3558
|
-
placeholder: phase === "draft" ? "Anything to change? Tell me here\u2026" : "Type your answer\u2026",
|
|
3559
|
-
rows: 1,
|
|
3560
|
-
disabled: busy,
|
|
3561
|
-
autoFocus: true,
|
|
3562
|
-
style: {
|
|
3563
|
-
flex: 1,
|
|
3564
|
-
minHeight: "42px",
|
|
3565
|
-
maxHeight: "120px",
|
|
3566
|
-
padding: "11px 12px",
|
|
3567
|
-
borderRadius: "10px",
|
|
3568
|
-
border: `1px solid ${t.inputBorder}`,
|
|
3569
|
-
backgroundColor: t.inputBg,
|
|
3570
|
-
color: t.text,
|
|
3571
|
-
fontSize: "13px",
|
|
3572
|
-
lineHeight: 1.4,
|
|
3573
|
-
fontFamily: "inherit",
|
|
3574
|
-
resize: "none",
|
|
3575
|
-
outline: "none",
|
|
3576
|
-
boxSizing: "border-box"
|
|
3577
|
-
}
|
|
4364
|
+
e.target.value = "";
|
|
4365
|
+
},
|
|
4366
|
+
style: { display: "none" }
|
|
4367
|
+
}
|
|
4368
|
+
)
|
|
4369
|
+
]
|
|
4370
|
+
}
|
|
4371
|
+
),
|
|
4372
|
+
readShots.size < screenshots.length && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { color: t.textMuted, fontSize: "11px" }, children: [
|
|
4373
|
+
readShots.size,
|
|
4374
|
+
" of ",
|
|
4375
|
+
screenshots.length,
|
|
4376
|
+
" read"
|
|
4377
|
+
] })
|
|
4378
|
+
]
|
|
3578
4379
|
}
|
|
3579
4380
|
),
|
|
3580
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
4381
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "8px", alignItems: "flex-end" }, children: [
|
|
4382
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4383
|
+
"textarea",
|
|
4384
|
+
{
|
|
4385
|
+
ref: composerRef,
|
|
4386
|
+
value: input,
|
|
4387
|
+
onChange: (e) => {
|
|
4388
|
+
stopAutoFile("typing a change");
|
|
4389
|
+
setInput(e.target.value);
|
|
4390
|
+
},
|
|
4391
|
+
onKeyDown: (e) => {
|
|
4392
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
4393
|
+
e.preventDefault();
|
|
4394
|
+
sendTyped(input);
|
|
4395
|
+
}
|
|
4396
|
+
},
|
|
4397
|
+
placeholder: phase === "draft" ? "Anything to change? Tell me here\u2026" : "Type your answer\u2026",
|
|
4398
|
+
rows: 3,
|
|
4399
|
+
disabled: busy,
|
|
4400
|
+
autoFocus: true,
|
|
4401
|
+
style: {
|
|
4402
|
+
flex: 1,
|
|
4403
|
+
minHeight: "72px",
|
|
4404
|
+
maxHeight: "220px",
|
|
4405
|
+
padding: "11px 12px",
|
|
4406
|
+
borderRadius: "10px",
|
|
4407
|
+
border: `1px solid ${t.inputBorder}`,
|
|
4408
|
+
backgroundColor: t.inputBg,
|
|
4409
|
+
color: t.text,
|
|
4410
|
+
fontSize: "13px",
|
|
4411
|
+
lineHeight: 1.4,
|
|
4412
|
+
fontFamily: "inherit",
|
|
4413
|
+
resize: "none",
|
|
4414
|
+
outline: "none",
|
|
4415
|
+
boxSizing: "border-box"
|
|
3607
4416
|
}
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
4417
|
+
}
|
|
4418
|
+
),
|
|
4419
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4420
|
+
"button",
|
|
4421
|
+
{
|
|
4422
|
+
type: "button",
|
|
4423
|
+
"data-gg-sheet-send": "",
|
|
4424
|
+
onClick: () => sendTyped(input),
|
|
4425
|
+
disabled: busy || !input.trim(),
|
|
4426
|
+
"aria-label": "Send message",
|
|
4427
|
+
"data-gg-send-message": "",
|
|
4428
|
+
style: {
|
|
4429
|
+
flexShrink: 0,
|
|
4430
|
+
width: "42px",
|
|
4431
|
+
height: "42px",
|
|
4432
|
+
borderRadius: "10px",
|
|
4433
|
+
border: "none",
|
|
4434
|
+
display: "inline-flex",
|
|
4435
|
+
alignItems: "center",
|
|
4436
|
+
justifyContent: "center",
|
|
4437
|
+
backgroundColor: busy || !input.trim() ? t.bgSecondary : t.accent,
|
|
4438
|
+
color: busy || !input.trim() ? t.textMuted : t.accentText,
|
|
4439
|
+
cursor: busy || !input.trim() ? "default" : "pointer"
|
|
4440
|
+
},
|
|
4441
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "17", height: "17", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
4442
|
+
"path",
|
|
4443
|
+
{
|
|
4444
|
+
d: "M3 20.5L21.5 12 3 3.5V10l12 2-12 2v6.5z",
|
|
4445
|
+
fill: "currentColor"
|
|
4446
|
+
}
|
|
4447
|
+
) })
|
|
4448
|
+
}
|
|
4449
|
+
)
|
|
4450
|
+
] })
|
|
3611
4451
|
] }),
|
|
3612
4452
|
phase === "draft" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
3613
4453
|
validationError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -3621,7 +4461,7 @@ function AssistSheet({
|
|
|
3621
4461
|
children: validationError
|
|
3622
4462
|
}
|
|
3623
4463
|
),
|
|
3624
|
-
autoFileLeft !== null ? (
|
|
4464
|
+
similarSlot ? similarSlot : autoFileLeft !== null ? (
|
|
3625
4465
|
// #402: "Yes, that's it" was the confirmation. The draft
|
|
3626
4466
|
// files itself unless they stop it — the bar shows how
|
|
3627
4467
|
// long is left, the button sends now, the × on its right
|
|
@@ -4489,20 +5329,20 @@ function initialsOf(name) {
|
|
|
4489
5329
|
}).join("");
|
|
4490
5330
|
}
|
|
4491
5331
|
function ReporterChip({
|
|
4492
|
-
reporter,
|
|
5332
|
+
reporter: reporter2,
|
|
4493
5333
|
t
|
|
4494
5334
|
}) {
|
|
4495
5335
|
var _a;
|
|
4496
5336
|
const [avatarFailed, setAvatarFailed] = (0, import_react.useState)(false);
|
|
4497
|
-
const avatarUrl = (
|
|
5337
|
+
const avatarUrl = (reporter2 == null ? void 0 : reporter2.avatarUrl) || "";
|
|
4498
5338
|
(0, import_react.useEffect)(() => {
|
|
4499
5339
|
setAvatarFailed(false);
|
|
4500
5340
|
}, [avatarUrl]);
|
|
4501
|
-
const name = ((_a =
|
|
5341
|
+
const name = ((_a = reporter2 == null ? void 0 : reporter2.name) == null ? void 0 : _a.trim()) || "";
|
|
4502
5342
|
const isAnonymous = !name;
|
|
4503
5343
|
const initials2 = isAnonymous ? "" : initialsOf(name);
|
|
4504
5344
|
const label = isAnonymous ? "Anonymous" : name;
|
|
4505
|
-
const title = isAnonymous ? "No reporter identity was passed to Glitchgrab \u2014 this report won't be attributed to anyone" : [name,
|
|
5345
|
+
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 ");
|
|
4506
5346
|
const showAvatarImage = !!avatarUrl && !avatarFailed;
|
|
4507
5347
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
4508
5348
|
"span",
|
|
@@ -4566,7 +5406,7 @@ function ReporterChip({
|
|
|
4566
5406
|
},
|
|
4567
5407
|
children: [
|
|
4568
5408
|
label,
|
|
4569
|
-
(
|
|
5409
|
+
(reporter2 == null ? void 0 : reporter2.role) ? ` \xB7 ${reporter2.role}` : ""
|
|
4570
5410
|
]
|
|
4571
5411
|
}
|
|
4572
5412
|
)
|
|
@@ -4677,16 +5517,18 @@ function ReportDialog({
|
|
|
4677
5517
|
enhanceText: enhanceText2,
|
|
4678
5518
|
assist,
|
|
4679
5519
|
findSimilarIssues: findSimilarIssues2,
|
|
5520
|
+
readFile,
|
|
4680
5521
|
assistContext = null,
|
|
4681
5522
|
transcribeAudio: transcribeAudio2,
|
|
4682
5523
|
types,
|
|
4683
5524
|
showSeverity = true,
|
|
4684
5525
|
captureScreenshot = captureDefaultScreenshot,
|
|
4685
|
-
reporter,
|
|
5526
|
+
reporter: reporter2,
|
|
4686
5527
|
onClose,
|
|
4687
5528
|
headerSlot,
|
|
4688
5529
|
reportGlitchgrabProblem,
|
|
4689
|
-
layout = "modal"
|
|
5530
|
+
layout = "modal",
|
|
5531
|
+
chatHistoryKey: chatHistoryKey2 = null
|
|
4690
5532
|
}) {
|
|
4691
5533
|
var _a;
|
|
4692
5534
|
const sheet = layout === "sheet";
|
|
@@ -4730,6 +5572,15 @@ function ReportDialog({
|
|
|
4730
5572
|
const pendingShotRef = (0, import_react.useRef)(null);
|
|
4731
5573
|
const openGenRef = (0, import_react.useRef)(0);
|
|
4732
5574
|
const [attachments, setAttachments] = (0, import_react.useState)([]);
|
|
5575
|
+
const [pdfTexts, setPdfTexts] = (0, import_react.useState)({});
|
|
5576
|
+
const heldFiles = (0, import_react.useMemo)(
|
|
5577
|
+
() => attachments.map((a) => {
|
|
5578
|
+
const read = pdfTexts[heldFileKey(a)];
|
|
5579
|
+
if (!read) return a;
|
|
5580
|
+
return "reading" in read ? { ...a, reading: true } : { ...a, text: read.text, ...read.tooLarge ? { tooLarge: true } : {} };
|
|
5581
|
+
}),
|
|
5582
|
+
[attachments, pdfTexts]
|
|
5583
|
+
);
|
|
4733
5584
|
const [previewIndex, setPreviewIndex] = (0, import_react.useState)(null);
|
|
4734
5585
|
const [annotatingIndex, setAnnotatingIndex] = (0, import_react.useState)(null);
|
|
4735
5586
|
const [previewZoomed, setPreviewZoomed] = (0, import_react.useState)(false);
|
|
@@ -4782,15 +5633,15 @@ function ReportDialog({
|
|
|
4782
5633
|
});
|
|
4783
5634
|
};
|
|
4784
5635
|
applyInert();
|
|
4785
|
-
const
|
|
5636
|
+
const observer2 = new MutationObserver((mutations) => {
|
|
4786
5637
|
const structural = mutations.some(
|
|
4787
5638
|
(m) => m.addedNodes.length > 0 || m.removedNodes.length > 0
|
|
4788
5639
|
);
|
|
4789
5640
|
if (structural) applyInert();
|
|
4790
5641
|
});
|
|
4791
|
-
|
|
5642
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
4792
5643
|
return () => {
|
|
4793
|
-
|
|
5644
|
+
observer2.disconnect();
|
|
4794
5645
|
inerted.forEach((el) => el.removeAttribute("inert"));
|
|
4795
5646
|
};
|
|
4796
5647
|
}, [isOpen]);
|
|
@@ -4890,10 +5741,16 @@ function ReportDialog({
|
|
|
4890
5741
|
files.filter((file) => !file.type.startsWith("image/")).forEach((file) => {
|
|
4891
5742
|
const reader = new FileReader();
|
|
4892
5743
|
reader.onload = () => {
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
]);
|
|
5744
|
+
const dataUrl = reader.result;
|
|
5745
|
+
setAttachments((prev) => [...prev, { name: file.name, size: file.size, dataUrl }]);
|
|
5746
|
+
const key = heldFileKey(file);
|
|
5747
|
+
if (!readFile || !isPdfFile(file.name) || pdfTexts[key]) return;
|
|
5748
|
+
if (file.size > MAX_READABLE_PDF_BYTES) {
|
|
5749
|
+
setPdfTexts((prev) => ({ ...prev, [key]: { text: null, tooLarge: true } }));
|
|
5750
|
+
return;
|
|
5751
|
+
}
|
|
5752
|
+
setPdfTexts((prev) => ({ ...prev, [key]: { reading: true } }));
|
|
5753
|
+
void Promise.resolve().then(() => readFile({ name: file.name, dataUrl })).catch(() => null).then((text) => setPdfTexts((prev) => ({ ...prev, [key]: { text } })));
|
|
4897
5754
|
};
|
|
4898
5755
|
reader.readAsDataURL(file);
|
|
4899
5756
|
});
|
|
@@ -5329,6 +6186,10 @@ function ReportDialog({
|
|
|
5329
6186
|
stopListeningAndTranscribe();
|
|
5330
6187
|
}
|
|
5331
6188
|
};
|
|
6189
|
+
(0, import_react.useEffect)(() => {
|
|
6190
|
+
setSimilarIssues(null);
|
|
6191
|
+
setPickedSimilar(null);
|
|
6192
|
+
}, [description]);
|
|
5332
6193
|
const handleSubmit = async (opts) => {
|
|
5333
6194
|
var _a2, _b, _c;
|
|
5334
6195
|
try {
|
|
@@ -5369,11 +6230,17 @@ function ReportDialog({
|
|
|
5369
6230
|
}
|
|
5370
6231
|
const duplicateOf = (_a2 = opts == null ? void 0 : opts.duplicateOf) != null ? _a2 : duplicateIssueNumber;
|
|
5371
6232
|
const attachKind = (opts == null ? void 0 : opts.duplicateOf) ? (_b = opts.kind) != null ? _b : "duplicate" : duplicateKind;
|
|
5372
|
-
if (findSimilarIssues2 && !(opts == null ? void 0 : opts.skipSimilar) && !duplicateOf
|
|
6233
|
+
if (findSimilarIssues2 && !(opts == null ? void 0 : opts.skipSimilar) && !duplicateOf) {
|
|
6234
|
+
const similarFiles = filesForSimilar(
|
|
6235
|
+
heldFiles,
|
|
6236
|
+
MAX_SIMILAR_FILE_CHARS,
|
|
6237
|
+
MAX_SIMILAR_FILES_TOTAL_CHARS
|
|
6238
|
+
);
|
|
5373
6239
|
setIsSubmitting(true);
|
|
5374
6240
|
setCheckingSimilar(true);
|
|
5375
6241
|
const matches = await Promise.race([
|
|
5376
|
-
|
|
6242
|
+
// A PDF still being read is left out rather than waited for.
|
|
6243
|
+
(similarFiles.length ? findSimilarIssues2(description.trim(), similarFiles) : findSimilarIssues2(description.trim())).catch(() => null),
|
|
5377
6244
|
new Promise((resolve) => setTimeout(() => resolve(null), SIMILAR_WAIT_MS))
|
|
5378
6245
|
]);
|
|
5379
6246
|
setCheckingSimilar(false);
|
|
@@ -5405,6 +6272,8 @@ function ReportDialog({
|
|
|
5405
6272
|
if (duplicateOf) {
|
|
5406
6273
|
metadata.duplicateIssueNumber = String(duplicateOf);
|
|
5407
6274
|
if (attachKind === "related") metadata.duplicateKind = "related";
|
|
6275
|
+
} else if (opts == null ? void 0 : opts.possiblyRelated) {
|
|
6276
|
+
metadata.possiblyRelatedIssue = String(opts.possiblyRelated);
|
|
5408
6277
|
}
|
|
5409
6278
|
if (aiConversationId) {
|
|
5410
6279
|
metadata.aiConversationId = aiConversationId;
|
|
@@ -5418,14 +6287,20 @@ function ReportDialog({
|
|
|
5418
6287
|
Object.keys(metadata).length > 0 ? metadata : void 0
|
|
5419
6288
|
);
|
|
5420
6289
|
if (result) {
|
|
5421
|
-
setAddedToIssue(
|
|
6290
|
+
setAddedToIssue(
|
|
6291
|
+
duplicateOf && result.issueNumber === duplicateOf ? duplicateOf : result.status === "DUPLICATE" && result.issueNumber ? result.issueNumber : null
|
|
6292
|
+
);
|
|
5422
6293
|
setAddedAsRelated(!!duplicateOf && result.issueNumber === duplicateOf && attachKind === "related");
|
|
5423
6294
|
const queued = result.status === "QUEUED" && !!result.message;
|
|
5424
6295
|
setQueuedMessage(queued ? (_c = result.message) != null ? _c : null : null);
|
|
6296
|
+
if (chatHistoryKey2 && aiConversationId) {
|
|
6297
|
+
markChatFiled(chatHistoryKey2, aiConversationId, `${getTypeLabel(reportType)} sent`);
|
|
6298
|
+
}
|
|
5425
6299
|
setSubmitted(true);
|
|
5426
6300
|
setDescription("");
|
|
5427
6301
|
setScreenshots([]);
|
|
5428
6302
|
setAttachments([]);
|
|
6303
|
+
setPdfTexts({});
|
|
5429
6304
|
setAiConversationId(null);
|
|
5430
6305
|
setIssueTitle("");
|
|
5431
6306
|
setDuplicateIssueNumber(null);
|
|
@@ -5446,6 +6321,220 @@ function ReportDialog({
|
|
|
5446
6321
|
setAttachingTo(null);
|
|
5447
6322
|
}
|
|
5448
6323
|
};
|
|
6324
|
+
const similarCard = similarIssues ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6325
|
+
"div",
|
|
6326
|
+
{
|
|
6327
|
+
"data-gg-similar": "",
|
|
6328
|
+
style: {
|
|
6329
|
+
marginTop: "12px",
|
|
6330
|
+
display: "flex",
|
|
6331
|
+
flexDirection: "column",
|
|
6332
|
+
gap: "10px",
|
|
6333
|
+
padding: "12px",
|
|
6334
|
+
borderRadius: "10px",
|
|
6335
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
6336
|
+
backgroundColor: "rgba(245,158,11,0.08)"
|
|
6337
|
+
},
|
|
6338
|
+
children: [
|
|
6339
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
|
|
6340
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: t.text, fontWeight: 600, fontSize: "13px" }, children: "Our team may already have this, or something close" }),
|
|
6341
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: t.textMuted, fontSize: "12px", lineHeight: 1.5 }, children: similarIssues.length > 1 ? "Pick the one that matches. Same problem, or a different request for the same feature \u2014 it's added to that issue, so the team has it in one place." : "Same problem, or a different request for the same feature? Pick it \u2014 it's added to that issue, so the team has it in one place." })
|
|
6342
|
+
] }),
|
|
6343
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6344
|
+
"div",
|
|
6345
|
+
{
|
|
6346
|
+
role: "radiogroup",
|
|
6347
|
+
"aria-label": "Existing issues",
|
|
6348
|
+
style: { display: "flex", flexDirection: "column", gap: "6px" },
|
|
6349
|
+
children: similarIssues.map((issue) => {
|
|
6350
|
+
const picked = pickedSimilar === issue.number;
|
|
6351
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6352
|
+
"button",
|
|
6353
|
+
{
|
|
6354
|
+
type: "button",
|
|
6355
|
+
role: "radio",
|
|
6356
|
+
"aria-checked": picked,
|
|
6357
|
+
disabled: isSubmitting,
|
|
6358
|
+
onClick: () => setPickedSimilar(issue.number),
|
|
6359
|
+
style: {
|
|
6360
|
+
display: "flex",
|
|
6361
|
+
alignItems: "flex-start",
|
|
6362
|
+
gap: "10px",
|
|
6363
|
+
width: "100%",
|
|
6364
|
+
minHeight: "44px",
|
|
6365
|
+
padding: "9px 10px",
|
|
6366
|
+
borderRadius: "8px",
|
|
6367
|
+
border: `1px solid ${picked ? t.accent : t.border}`,
|
|
6368
|
+
boxShadow: picked ? `0 0 0 1px ${t.accent}` : "none",
|
|
6369
|
+
backgroundColor: t.bg,
|
|
6370
|
+
color: t.text,
|
|
6371
|
+
textAlign: "left",
|
|
6372
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
6373
|
+
fontFamily: "inherit"
|
|
6374
|
+
},
|
|
6375
|
+
children: [
|
|
6376
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6377
|
+
"span",
|
|
6378
|
+
{
|
|
6379
|
+
"aria-hidden": "true",
|
|
6380
|
+
style: {
|
|
6381
|
+
flexShrink: 0,
|
|
6382
|
+
marginTop: "2px",
|
|
6383
|
+
width: "14px",
|
|
6384
|
+
height: "14px",
|
|
6385
|
+
boxSizing: "border-box",
|
|
6386
|
+
borderRadius: "50%",
|
|
6387
|
+
border: `2px solid ${picked ? t.accent : t.textMuted}`,
|
|
6388
|
+
backgroundColor: picked ? t.accent : "transparent",
|
|
6389
|
+
boxShadow: picked ? `inset 0 0 0 2px ${t.bg}` : "none"
|
|
6390
|
+
}
|
|
6391
|
+
}
|
|
6392
|
+
),
|
|
6393
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6394
|
+
"span",
|
|
6395
|
+
{
|
|
6396
|
+
style: {
|
|
6397
|
+
display: "flex",
|
|
6398
|
+
flexDirection: "column",
|
|
6399
|
+
gap: "3px",
|
|
6400
|
+
minWidth: 0
|
|
6401
|
+
},
|
|
6402
|
+
children: [
|
|
6403
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6404
|
+
"span",
|
|
6405
|
+
{
|
|
6406
|
+
title: issue.title,
|
|
6407
|
+
style: {
|
|
6408
|
+
fontSize: "12.5px",
|
|
6409
|
+
lineHeight: 1.45,
|
|
6410
|
+
wordBreak: "break-word",
|
|
6411
|
+
overflow: "hidden",
|
|
6412
|
+
display: "-webkit-box",
|
|
6413
|
+
WebkitLineClamp: 3,
|
|
6414
|
+
WebkitBoxOrient: "vertical"
|
|
6415
|
+
},
|
|
6416
|
+
children: [
|
|
6417
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { color: t.textMuted, fontWeight: 600 }, children: [
|
|
6418
|
+
"#",
|
|
6419
|
+
issue.number
|
|
6420
|
+
] }),
|
|
6421
|
+
" ",
|
|
6422
|
+
issue.title
|
|
6423
|
+
]
|
|
6424
|
+
}
|
|
6425
|
+
),
|
|
6426
|
+
issue.status && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: issue.status })
|
|
6427
|
+
]
|
|
6428
|
+
}
|
|
6429
|
+
)
|
|
6430
|
+
]
|
|
6431
|
+
},
|
|
6432
|
+
issue.number
|
|
6433
|
+
);
|
|
6434
|
+
})
|
|
6435
|
+
}
|
|
6436
|
+
),
|
|
6437
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6438
|
+
"button",
|
|
6439
|
+
{
|
|
6440
|
+
type: "button",
|
|
6441
|
+
disabled: isSubmitting || !pickedSimilar,
|
|
6442
|
+
onClick: () => {
|
|
6443
|
+
if (!pickedSimilar) return;
|
|
6444
|
+
setAttachingTo(pickedSimilar);
|
|
6445
|
+
setDuplicateIssueNumber(pickedSimilar);
|
|
6446
|
+
setDuplicateKind("duplicate");
|
|
6447
|
+
void handleSubmit({ duplicateOf: pickedSimilar, kind: "duplicate" });
|
|
6448
|
+
},
|
|
6449
|
+
style: {
|
|
6450
|
+
width: "100%",
|
|
6451
|
+
minHeight: "40px",
|
|
6452
|
+
padding: "10px",
|
|
6453
|
+
borderRadius: "8px",
|
|
6454
|
+
border: "none",
|
|
6455
|
+
backgroundColor: isSubmitting || !pickedSimilar ? t.bgSecondary : t.accent,
|
|
6456
|
+
color: isSubmitting || !pickedSimilar ? t.textMuted : t.accentText,
|
|
6457
|
+
fontSize: "14px",
|
|
6458
|
+
fontWeight: 600,
|
|
6459
|
+
cursor: isSubmitting || !pickedSimilar ? "not-allowed" : "pointer",
|
|
6460
|
+
fontFamily: "inherit"
|
|
6461
|
+
},
|
|
6462
|
+
children: typeof attachingTo === "number" && duplicateKind !== "related" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
6463
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ButtonSpinner, {}),
|
|
6464
|
+
"Adding to #",
|
|
6465
|
+
attachingTo,
|
|
6466
|
+
"\u2026"
|
|
6467
|
+
] }) : pickedSimilar ? `Add to #${pickedSimilar}` : "Pick the matching issue"
|
|
6468
|
+
}
|
|
6469
|
+
),
|
|
6470
|
+
pickedSimilar && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6471
|
+
"button",
|
|
6472
|
+
{
|
|
6473
|
+
type: "button",
|
|
6474
|
+
disabled: isSubmitting,
|
|
6475
|
+
onClick: () => {
|
|
6476
|
+
setAttachingTo(pickedSimilar);
|
|
6477
|
+
setDuplicateIssueNumber(pickedSimilar);
|
|
6478
|
+
setDuplicateKind("related");
|
|
6479
|
+
void handleSubmit({ duplicateOf: pickedSimilar, kind: "related" });
|
|
6480
|
+
},
|
|
6481
|
+
style: {
|
|
6482
|
+
width: "100%",
|
|
6483
|
+
minHeight: "40px",
|
|
6484
|
+
marginTop: "-4px",
|
|
6485
|
+
padding: "9px 10px",
|
|
6486
|
+
borderRadius: "8px",
|
|
6487
|
+
border: "1px solid rgba(245,158,11,0.4)",
|
|
6488
|
+
backgroundColor: "transparent",
|
|
6489
|
+
color: isSubmitting ? t.textMuted : t.text,
|
|
6490
|
+
fontSize: "13px",
|
|
6491
|
+
fontWeight: 600,
|
|
6492
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
6493
|
+
fontFamily: "inherit"
|
|
6494
|
+
},
|
|
6495
|
+
children: typeof attachingTo === "number" && duplicateKind === "related" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
6496
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ButtonSpinner, {}),
|
|
6497
|
+
"Adding to #",
|
|
6498
|
+
attachingTo,
|
|
6499
|
+
"\u2026"
|
|
6500
|
+
] }) : `Related request \u2014 add to #${pickedSimilar}`
|
|
6501
|
+
}
|
|
6502
|
+
),
|
|
6503
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
6504
|
+
"button",
|
|
6505
|
+
{
|
|
6506
|
+
type: "button",
|
|
6507
|
+
disabled: isSubmitting,
|
|
6508
|
+
onClick: () => {
|
|
6509
|
+
var _a2;
|
|
6510
|
+
setAttachingTo("new");
|
|
6511
|
+
void handleSubmit({ skipSimilar: true, possiblyRelated: (_a2 = similarIssues[0]) == null ? void 0 : _a2.number });
|
|
6512
|
+
},
|
|
6513
|
+
style: {
|
|
6514
|
+
width: "100%",
|
|
6515
|
+
minHeight: "40px",
|
|
6516
|
+
marginTop: "-4px",
|
|
6517
|
+
padding: "8px",
|
|
6518
|
+
borderRadius: "8px",
|
|
6519
|
+
border: "none",
|
|
6520
|
+
backgroundColor: "transparent",
|
|
6521
|
+
color: isSubmitting ? t.textMuted : t.text,
|
|
6522
|
+
fontSize: "13px",
|
|
6523
|
+
fontWeight: 500,
|
|
6524
|
+
textDecoration: "underline",
|
|
6525
|
+
textUnderlineOffset: "3px",
|
|
6526
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
6527
|
+
fontFamily: "inherit"
|
|
6528
|
+
},
|
|
6529
|
+
children: attachingTo === "new" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
6530
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ButtonSpinner, {}),
|
|
6531
|
+
"Sending as new\u2026"
|
|
6532
|
+
] }) : "No, mine is different \u2014 send as new"
|
|
6533
|
+
}
|
|
6534
|
+
)
|
|
6535
|
+
]
|
|
6536
|
+
}
|
|
6537
|
+
) : null;
|
|
5449
6538
|
if (!mounted) return null;
|
|
5450
6539
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
5451
6540
|
isOpen && (0, import_react_dom.createPortal)(
|
|
@@ -6984,224 +8073,7 @@ function ReportDialog({
|
|
|
6984
8073
|
children: validationError
|
|
6985
8074
|
}
|
|
6986
8075
|
),
|
|
6987
|
-
|
|
6988
|
-
// Same visual language as the assistant's "Our team is
|
|
6989
|
-
// already on this" card, so both routes to a duplicate
|
|
6990
|
-
// read as one feature.
|
|
6991
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
6992
|
-
"div",
|
|
6993
|
-
{
|
|
6994
|
-
"data-gg-similar": "",
|
|
6995
|
-
style: {
|
|
6996
|
-
marginTop: "12px",
|
|
6997
|
-
display: "flex",
|
|
6998
|
-
flexDirection: "column",
|
|
6999
|
-
gap: "10px",
|
|
7000
|
-
padding: "12px",
|
|
7001
|
-
borderRadius: "10px",
|
|
7002
|
-
border: "1px solid rgba(245,158,11,0.4)",
|
|
7003
|
-
backgroundColor: "rgba(245,158,11,0.08)"
|
|
7004
|
-
},
|
|
7005
|
-
children: [
|
|
7006
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "2px" }, children: [
|
|
7007
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: t.text, fontWeight: 600, fontSize: "13px" }, children: "Our team may already have this, or something close" }),
|
|
7008
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: t.textMuted, fontSize: "12px", lineHeight: 1.5 }, children: similarIssues.length > 1 ? "Pick the one that matches. Same problem, or a different request for the same feature \u2014 it's added to that issue, so the team has it in one place." : "Same problem, or a different request for the same feature? Pick it \u2014 it's added to that issue, so the team has it in one place." })
|
|
7009
|
-
] }),
|
|
7010
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7011
|
-
"div",
|
|
7012
|
-
{
|
|
7013
|
-
role: "radiogroup",
|
|
7014
|
-
"aria-label": "Existing issues",
|
|
7015
|
-
style: { display: "flex", flexDirection: "column", gap: "6px" },
|
|
7016
|
-
children: similarIssues.map((issue) => {
|
|
7017
|
-
const picked = pickedSimilar === issue.number;
|
|
7018
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
7019
|
-
"button",
|
|
7020
|
-
{
|
|
7021
|
-
type: "button",
|
|
7022
|
-
role: "radio",
|
|
7023
|
-
"aria-checked": picked,
|
|
7024
|
-
disabled: isSubmitting,
|
|
7025
|
-
onClick: () => setPickedSimilar(issue.number),
|
|
7026
|
-
style: {
|
|
7027
|
-
display: "flex",
|
|
7028
|
-
alignItems: "flex-start",
|
|
7029
|
-
gap: "10px",
|
|
7030
|
-
width: "100%",
|
|
7031
|
-
minHeight: "44px",
|
|
7032
|
-
padding: "9px 10px",
|
|
7033
|
-
borderRadius: "8px",
|
|
7034
|
-
border: `1px solid ${picked ? t.accent : t.border}`,
|
|
7035
|
-
boxShadow: picked ? `0 0 0 1px ${t.accent}` : "none",
|
|
7036
|
-
backgroundColor: t.bg,
|
|
7037
|
-
color: t.text,
|
|
7038
|
-
textAlign: "left",
|
|
7039
|
-
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
7040
|
-
fontFamily: "inherit"
|
|
7041
|
-
},
|
|
7042
|
-
children: [
|
|
7043
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7044
|
-
"span",
|
|
7045
|
-
{
|
|
7046
|
-
"aria-hidden": "true",
|
|
7047
|
-
style: {
|
|
7048
|
-
flexShrink: 0,
|
|
7049
|
-
marginTop: "2px",
|
|
7050
|
-
width: "14px",
|
|
7051
|
-
height: "14px",
|
|
7052
|
-
boxSizing: "border-box",
|
|
7053
|
-
borderRadius: "50%",
|
|
7054
|
-
border: `2px solid ${picked ? t.accent : t.textMuted}`,
|
|
7055
|
-
backgroundColor: picked ? t.accent : "transparent",
|
|
7056
|
-
boxShadow: picked ? `inset 0 0 0 2px ${t.bg}` : "none"
|
|
7057
|
-
}
|
|
7058
|
-
}
|
|
7059
|
-
),
|
|
7060
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
7061
|
-
"span",
|
|
7062
|
-
{
|
|
7063
|
-
style: {
|
|
7064
|
-
display: "flex",
|
|
7065
|
-
flexDirection: "column",
|
|
7066
|
-
gap: "3px",
|
|
7067
|
-
minWidth: 0
|
|
7068
|
-
},
|
|
7069
|
-
children: [
|
|
7070
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
7071
|
-
"span",
|
|
7072
|
-
{
|
|
7073
|
-
title: issue.title,
|
|
7074
|
-
style: {
|
|
7075
|
-
fontSize: "12.5px",
|
|
7076
|
-
lineHeight: 1.45,
|
|
7077
|
-
wordBreak: "break-word",
|
|
7078
|
-
overflow: "hidden",
|
|
7079
|
-
display: "-webkit-box",
|
|
7080
|
-
WebkitLineClamp: 3,
|
|
7081
|
-
WebkitBoxOrient: "vertical"
|
|
7082
|
-
},
|
|
7083
|
-
children: [
|
|
7084
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { color: t.textMuted, fontWeight: 600 }, children: [
|
|
7085
|
-
"#",
|
|
7086
|
-
issue.number
|
|
7087
|
-
] }),
|
|
7088
|
-
" ",
|
|
7089
|
-
issue.title
|
|
7090
|
-
]
|
|
7091
|
-
}
|
|
7092
|
-
),
|
|
7093
|
-
issue.status && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { fontSize: "11.5px", color: t.textMuted }, children: issue.status })
|
|
7094
|
-
]
|
|
7095
|
-
}
|
|
7096
|
-
)
|
|
7097
|
-
]
|
|
7098
|
-
},
|
|
7099
|
-
issue.number
|
|
7100
|
-
);
|
|
7101
|
-
})
|
|
7102
|
-
}
|
|
7103
|
-
),
|
|
7104
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7105
|
-
"button",
|
|
7106
|
-
{
|
|
7107
|
-
type: "button",
|
|
7108
|
-
disabled: isSubmitting || !pickedSimilar,
|
|
7109
|
-
onClick: () => {
|
|
7110
|
-
if (!pickedSimilar) return;
|
|
7111
|
-
setAttachingTo(pickedSimilar);
|
|
7112
|
-
setDuplicateIssueNumber(pickedSimilar);
|
|
7113
|
-
setDuplicateKind("duplicate");
|
|
7114
|
-
void handleSubmit({ duplicateOf: pickedSimilar, kind: "duplicate" });
|
|
7115
|
-
},
|
|
7116
|
-
style: {
|
|
7117
|
-
width: "100%",
|
|
7118
|
-
minHeight: "40px",
|
|
7119
|
-
padding: "10px",
|
|
7120
|
-
borderRadius: "8px",
|
|
7121
|
-
border: "none",
|
|
7122
|
-
backgroundColor: isSubmitting || !pickedSimilar ? t.bgSecondary : t.accent,
|
|
7123
|
-
color: isSubmitting || !pickedSimilar ? t.textMuted : t.accentText,
|
|
7124
|
-
fontSize: "14px",
|
|
7125
|
-
fontWeight: 600,
|
|
7126
|
-
cursor: isSubmitting || !pickedSimilar ? "not-allowed" : "pointer",
|
|
7127
|
-
fontFamily: "inherit"
|
|
7128
|
-
},
|
|
7129
|
-
children: typeof attachingTo === "number" && duplicateKind !== "related" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
7130
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ButtonSpinner, {}),
|
|
7131
|
-
"Adding to #",
|
|
7132
|
-
attachingTo,
|
|
7133
|
-
"\u2026"
|
|
7134
|
-
] }) : pickedSimilar ? `Add to #${pickedSimilar}` : "Pick the matching issue"
|
|
7135
|
-
}
|
|
7136
|
-
),
|
|
7137
|
-
pickedSimilar && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7138
|
-
"button",
|
|
7139
|
-
{
|
|
7140
|
-
type: "button",
|
|
7141
|
-
disabled: isSubmitting,
|
|
7142
|
-
onClick: () => {
|
|
7143
|
-
setAttachingTo(pickedSimilar);
|
|
7144
|
-
setDuplicateIssueNumber(pickedSimilar);
|
|
7145
|
-
setDuplicateKind("related");
|
|
7146
|
-
void handleSubmit({ duplicateOf: pickedSimilar, kind: "related" });
|
|
7147
|
-
},
|
|
7148
|
-
style: {
|
|
7149
|
-
width: "100%",
|
|
7150
|
-
minHeight: "40px",
|
|
7151
|
-
marginTop: "-4px",
|
|
7152
|
-
padding: "9px 10px",
|
|
7153
|
-
borderRadius: "8px",
|
|
7154
|
-
border: "1px solid rgba(245,158,11,0.4)",
|
|
7155
|
-
backgroundColor: "transparent",
|
|
7156
|
-
color: isSubmitting ? t.textMuted : t.text,
|
|
7157
|
-
fontSize: "13px",
|
|
7158
|
-
fontWeight: 600,
|
|
7159
|
-
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
7160
|
-
fontFamily: "inherit"
|
|
7161
|
-
},
|
|
7162
|
-
children: typeof attachingTo === "number" && duplicateKind === "related" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
7163
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ButtonSpinner, {}),
|
|
7164
|
-
"Adding to #",
|
|
7165
|
-
attachingTo,
|
|
7166
|
-
"\u2026"
|
|
7167
|
-
] }) : `Related request \u2014 add to #${pickedSimilar}`
|
|
7168
|
-
}
|
|
7169
|
-
),
|
|
7170
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7171
|
-
"button",
|
|
7172
|
-
{
|
|
7173
|
-
type: "button",
|
|
7174
|
-
disabled: isSubmitting,
|
|
7175
|
-
onClick: () => {
|
|
7176
|
-
setAttachingTo("new");
|
|
7177
|
-
void handleSubmit({ skipSimilar: true });
|
|
7178
|
-
},
|
|
7179
|
-
style: {
|
|
7180
|
-
width: "100%",
|
|
7181
|
-
minHeight: "40px",
|
|
7182
|
-
marginTop: "-4px",
|
|
7183
|
-
padding: "8px",
|
|
7184
|
-
borderRadius: "8px",
|
|
7185
|
-
border: "none",
|
|
7186
|
-
backgroundColor: "transparent",
|
|
7187
|
-
color: isSubmitting ? t.textMuted : t.text,
|
|
7188
|
-
fontSize: "13px",
|
|
7189
|
-
fontWeight: 500,
|
|
7190
|
-
textDecoration: "underline",
|
|
7191
|
-
textUnderlineOffset: "3px",
|
|
7192
|
-
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
7193
|
-
fontFamily: "inherit"
|
|
7194
|
-
},
|
|
7195
|
-
children: attachingTo === "new" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
7196
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ButtonSpinner, {}),
|
|
7197
|
-
"Sending as new\u2026"
|
|
7198
|
-
] }) : "No, mine is different \u2014 send as new"
|
|
7199
|
-
}
|
|
7200
|
-
)
|
|
7201
|
-
]
|
|
7202
|
-
}
|
|
7203
|
-
)
|
|
7204
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
8076
|
+
similarCard != null ? similarCard : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7205
8077
|
"button",
|
|
7206
8078
|
{
|
|
7207
8079
|
type: "button",
|
|
@@ -7243,7 +8115,7 @@ function ReportDialog({
|
|
|
7243
8115
|
gap: "12px"
|
|
7244
8116
|
},
|
|
7245
8117
|
children: [
|
|
7246
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ReporterChip, { reporter, t }),
|
|
8118
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ReporterChip, { reporter: reporter2, t }),
|
|
7247
8119
|
reportGlitchgrabProblem ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
7248
8120
|
"button",
|
|
7249
8121
|
{
|
|
@@ -7500,7 +8372,8 @@ function ReportDialog({
|
|
|
7500
8372
|
pageShot,
|
|
7501
8373
|
onAddFiles: addFiles,
|
|
7502
8374
|
onRemoveImage: (index) => setScreenshots((prev) => prev.filter((_, i) => i !== index)),
|
|
7503
|
-
files:
|
|
8375
|
+
files: heldFiles,
|
|
8376
|
+
canReadPdf: !!readFile,
|
|
7504
8377
|
onRemoveFile: (index) => setAttachments((prev) => prev.filter((_, i) => i !== index)),
|
|
7505
8378
|
attachmentCount: screenshots.length + attachments.length,
|
|
7506
8379
|
context: { ...assistContext != null ? assistContext : {}, reportType },
|
|
@@ -7514,10 +8387,15 @@ function ReportDialog({
|
|
|
7514
8387
|
setStep(2);
|
|
7515
8388
|
},
|
|
7516
8389
|
onDuplicateChange: (issueNumber, kind) => {
|
|
8390
|
+
if (issueNumber) {
|
|
8391
|
+
setSimilarIssues(null);
|
|
8392
|
+
setPickedSimilar(null);
|
|
8393
|
+
}
|
|
7517
8394
|
setDuplicateIssueNumber(issueNumber);
|
|
7518
8395
|
setDuplicateKind(issueNumber && kind === "related" ? "related" : "duplicate");
|
|
7519
8396
|
},
|
|
7520
8397
|
onConversationChange: setAiConversationId,
|
|
8398
|
+
historyKey: chatHistoryKey2,
|
|
7521
8399
|
onFinish: handleClose,
|
|
7522
8400
|
rating,
|
|
7523
8401
|
onRatingChange: (value) => {
|
|
@@ -7525,7 +8403,7 @@ function ReportDialog({
|
|
|
7525
8403
|
if (validationError) setValidationError(null);
|
|
7526
8404
|
},
|
|
7527
8405
|
projectSlot: headerSlot,
|
|
7528
|
-
reporterName: (_a =
|
|
8406
|
+
reporterName: (_a = reporter2 == null ? void 0 : reporter2.name) != null ? _a : null,
|
|
7529
8407
|
description,
|
|
7530
8408
|
onDescriptionChange: (value) => {
|
|
7531
8409
|
setDescription(value);
|
|
@@ -7543,7 +8421,9 @@ function ReportDialog({
|
|
|
7543
8421
|
severityRefused: needsSeverity,
|
|
7544
8422
|
isSubmitting,
|
|
7545
8423
|
submitted,
|
|
7546
|
-
onSend: () => void handleSubmit(
|
|
8424
|
+
onSend: () => void handleSubmit(),
|
|
8425
|
+
similarSlot: similarCard,
|
|
8426
|
+
submittedText: addedToIssue ? `Added to #${addedToIssue}${addedAsRelated ? " as a related request" : ""}. Thank you!` : null,
|
|
7547
8427
|
onReportGlitchgrabProblem: reportGlitchgrabProblem ? (prefill) => {
|
|
7548
8428
|
setSelfReportPrefill(prefill != null ? prefill : "");
|
|
7549
8429
|
setSelfReportFrom("assist");
|
|
@@ -7837,7 +8717,9 @@ function BookingDialog({
|
|
|
7837
8717
|
token,
|
|
7838
8718
|
baseUrl,
|
|
7839
8719
|
open,
|
|
7840
|
-
onClose
|
|
8720
|
+
onClose,
|
|
8721
|
+
preview = false,
|
|
8722
|
+
availabilityUrl
|
|
7841
8723
|
}) {
|
|
7842
8724
|
var _a, _b, _c, _d, _e;
|
|
7843
8725
|
const wide = useMediaQuery(WIDE_QUERY, true);
|
|
@@ -7871,10 +8753,12 @@ function BookingDialog({
|
|
|
7871
8753
|
const [meetUrl, setMeetUrl] = (0, import_react5.useState)(null);
|
|
7872
8754
|
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
7873
8755
|
const [error, setError] = (0, import_react5.useState)(null);
|
|
7874
|
-
const
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
8756
|
+
const [previewEnded, setPreviewEnded] = (0, import_react5.useState)(false);
|
|
8757
|
+
const headers = (0, import_react5.useMemo)(() => {
|
|
8758
|
+
const out = { "Content-Type": "application/json" };
|
|
8759
|
+
if (token) out.Authorization = `Bearer ${token}`;
|
|
8760
|
+
return out;
|
|
8761
|
+
}, [token]);
|
|
7878
8762
|
const loadMonth = (0, import_react5.useCallback)(
|
|
7879
8763
|
async (target) => {
|
|
7880
8764
|
var _a2, _b2, _c2;
|
|
@@ -7886,8 +8770,9 @@ function BookingDialog({
|
|
|
7886
8770
|
return;
|
|
7887
8771
|
}
|
|
7888
8772
|
try {
|
|
8773
|
+
const source = availabilityUrl != null ? availabilityUrl : `${baseUrl}/api/v1/sdk/booking/availability`;
|
|
7889
8774
|
const res = await fetch(
|
|
7890
|
-
`${
|
|
8775
|
+
`${source}${source.includes("?") ? "&" : "?"}from=${encodeURIComponent(new Date(from).toISOString())}&to=${encodeURIComponent(new Date(to).toISOString())}${preview ? "&preview=1" : ""}`,
|
|
7891
8776
|
{ headers }
|
|
7892
8777
|
);
|
|
7893
8778
|
const json = await res.json();
|
|
@@ -7916,7 +8801,7 @@ function BookingDialog({
|
|
|
7916
8801
|
setPageLoaded(true);
|
|
7917
8802
|
}
|
|
7918
8803
|
},
|
|
7919
|
-
[baseUrl, headers]
|
|
8804
|
+
[baseUrl, headers, availabilityUrl, preview]
|
|
7920
8805
|
);
|
|
7921
8806
|
(0, import_react5.useEffect)(() => {
|
|
7922
8807
|
if (!open) return;
|
|
@@ -7930,6 +8815,7 @@ function BookingDialog({
|
|
|
7930
8815
|
setCode("");
|
|
7931
8816
|
setBookingId(null);
|
|
7932
8817
|
setError(null);
|
|
8818
|
+
setPreviewEnded(false);
|
|
7933
8819
|
setAvatarFailed(false);
|
|
7934
8820
|
setPageLoaded(false);
|
|
7935
8821
|
setAsked(false);
|
|
@@ -7968,6 +8854,10 @@ function BookingDialog({
|
|
|
7968
8854
|
async function startBooking() {
|
|
7969
8855
|
var _a2, _b2;
|
|
7970
8856
|
if (!selected) return;
|
|
8857
|
+
if (preview) {
|
|
8858
|
+
setPreviewEnded(true);
|
|
8859
|
+
return;
|
|
8860
|
+
}
|
|
7971
8861
|
setBusy(true);
|
|
7972
8862
|
setError(null);
|
|
7973
8863
|
try {
|
|
@@ -8161,6 +9051,22 @@ function BookingDialog({
|
|
|
8161
9051
|
) : null,
|
|
8162
9052
|
page.hostName && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 14, fontWeight: 500, ...muted }, children: page.hostName })
|
|
8163
9053
|
] }),
|
|
9054
|
+
preview && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
9055
|
+
"div",
|
|
9056
|
+
{
|
|
9057
|
+
style: {
|
|
9058
|
+
alignSelf: "flex-start",
|
|
9059
|
+
padding: "3px 9px",
|
|
9060
|
+
borderRadius: 999,
|
|
9061
|
+
border: `1px dashed ${t.border}`,
|
|
9062
|
+
fontSize: 11.5,
|
|
9063
|
+
fontWeight: 600,
|
|
9064
|
+
letterSpacing: "0.02em",
|
|
9065
|
+
color: t.muted
|
|
9066
|
+
},
|
|
9067
|
+
children: "Preview \u2014 nothing is booked"
|
|
9068
|
+
}
|
|
9069
|
+
),
|
|
8164
9070
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 20, fontWeight: 600, lineHeight: 1.25, paddingRight: 32, overflowWrap: "anywhere" }, children: page.title }),
|
|
8165
9071
|
page.description && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 13, lineHeight: 1.5, overflowWrap: "anywhere", ...muted }, children: page.description }),
|
|
8166
9072
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 10, marginTop: 4, fontSize: 14 }, children: [
|
|
@@ -8598,6 +9504,7 @@ function BookingDialog({
|
|
|
8598
9504
|
},
|
|
8599
9505
|
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { maxWidth: 440, display: "flex", flexDirection: "column", gap: 14 }, children: [
|
|
8600
9506
|
error && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { color: t.danger, fontSize: 13, lineHeight: 1.5 }, children: error }),
|
|
9507
|
+
previewEnded && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 13, lineHeight: 1.5, ...muted }, children: "End of the preview \u2014 a prospect would be booked here. Nothing was booked and no code was sent." }),
|
|
8601
9508
|
step === "details" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
8602
9509
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Field, { t, label: "Your name", value: name, onChange: setName, autoComplete: "name" }),
|
|
8603
9510
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Field, { t, label: "Email", value: email, onChange: setEmail, type: "email", autoComplete: "email" }),
|
|
@@ -9083,6 +9990,9 @@ function GlitchgrabProviderInner({
|
|
|
9083
9990
|
onError,
|
|
9084
9991
|
onReportSent
|
|
9085
9992
|
});
|
|
9993
|
+
if (process.env.NODE_ENV !== "development") {
|
|
9994
|
+
installHydrationCapture(reportHydrationError);
|
|
9995
|
+
}
|
|
9086
9996
|
(0, import_react6.useEffect)(() => {
|
|
9087
9997
|
if (enableBreadcrumbs) {
|
|
9088
9998
|
initBreadcrumbs(maxBreadcrumbs2, { responseBodyOrigins: responseBodyOrigins2 });
|
|
@@ -9138,7 +10048,7 @@ function GlitchgrabProviderInner({
|
|
|
9138
10048
|
return matchesIgnorePatterns(message, ignoreErrors);
|
|
9139
10049
|
};
|
|
9140
10050
|
const handleError = (event) => {
|
|
9141
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
10051
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i;
|
|
9142
10052
|
try {
|
|
9143
10053
|
const isOpaqueCrossOrigin = event.message === "Script error." || event.message === "Script error" || !event.error && !event.filename;
|
|
9144
10054
|
if (isOpaqueCrossOrigin) {
|
|
@@ -9153,6 +10063,7 @@ function GlitchgrabProviderInner({
|
|
|
9153
10063
|
if (event.filename && EXTENSION_ORIGIN_RE.test(event.filename) || ((_a = event.error) == null ? void 0 : _a.stack) && EXTENSION_ORIGIN_RE.test(event.error.stack)) {
|
|
9154
10064
|
return;
|
|
9155
10065
|
}
|
|
10066
|
+
if (isHandledHydrationError(event.error)) return;
|
|
9156
10067
|
incrementErrorCount();
|
|
9157
10068
|
const context = captureContext(visitedPagesRef.current);
|
|
9158
10069
|
const sig = computeSignature({
|
|
@@ -9178,6 +10089,9 @@ function GlitchgrabProviderInner({
|
|
|
9178
10089
|
filename: (_e = event.filename) != null ? _e : "",
|
|
9179
10090
|
lineno: String((_f = event.lineno) != null ? _f : ""),
|
|
9180
10091
|
colno: String((_g = event.colno) != null ? _g : ""),
|
|
10092
|
+
// The root patch could not attach (React internals moved, or a
|
|
10093
|
+
// root it does not know): still label it and send the DOM context.
|
|
10094
|
+
...isHydrationError((_h = event.error) != null ? _h : event.message) ? hydrationMetadata((_i = event.error) != null ? _i : event.message) : {},
|
|
9181
10095
|
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
9182
10096
|
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
9183
10097
|
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
@@ -9438,7 +10352,11 @@ function GlitchgrabProviderInner({
|
|
|
9438
10352
|
[token, baseUrl, session]
|
|
9439
10353
|
);
|
|
9440
10354
|
const findSimilar = (0, import_react6.useCallback)(
|
|
9441
|
-
(description) => findSimilarIssues(description, token, baseUrl, identity),
|
|
10355
|
+
(description, files) => findSimilarIssues(description, token, baseUrl, identity, files),
|
|
10356
|
+
[token, baseUrl, identity]
|
|
10357
|
+
);
|
|
10358
|
+
const readFile = (0, import_react6.useCallback)(
|
|
10359
|
+
(file) => readAttachment(file, token, baseUrl, identity),
|
|
9442
10360
|
[token, baseUrl, identity]
|
|
9443
10361
|
);
|
|
9444
10362
|
const transcribe = (0, import_react6.useCallback)(
|
|
@@ -9469,8 +10387,9 @@ function GlitchgrabProviderInner({
|
|
|
9469
10387
|
const [glitchgrabReport, setGlitchgrabReport] = (0, import_react6.useState)(false);
|
|
9470
10388
|
const [signedUsers, setSignedUsers] = (0, import_react6.useState)("OFF");
|
|
9471
10389
|
const aiBlockedUnsigned = signedUsers === "ENFORCE" && !signature;
|
|
9472
|
-
const [
|
|
9473
|
-
const openBookingDialog = (0, import_react6.useCallback)(() =>
|
|
10390
|
+
const [booking, setBooking] = (0, import_react6.useState)("closed");
|
|
10391
|
+
const openBookingDialog = (0, import_react6.useCallback)(() => setBooking("live"), []);
|
|
10392
|
+
const openBookingPreview = (0, import_react6.useCallback)(() => setBooking("preview"), []);
|
|
9474
10393
|
(0, import_react6.useEffect)(() => {
|
|
9475
10394
|
let cancelled = false;
|
|
9476
10395
|
fetch(`${baseUrl}/api/v1/sdk/project`, {
|
|
@@ -9514,7 +10433,7 @@ function GlitchgrabProviderInner({
|
|
|
9514
10433
|
} catch (e) {
|
|
9515
10434
|
}
|
|
9516
10435
|
}, [openReportDialog]);
|
|
9517
|
-
const
|
|
10436
|
+
const reporter2 = (0, import_react6.useMemo)(() => {
|
|
9518
10437
|
var _a;
|
|
9519
10438
|
if (!session) return null;
|
|
9520
10439
|
const avatar = (_a = session.avatarUrl) != null ? _a : session.image;
|
|
@@ -9545,6 +10464,7 @@ function GlitchgrabProviderInner({
|
|
|
9545
10464
|
addBreadcrumb: addBreadcrumb2,
|
|
9546
10465
|
openReportDialog,
|
|
9547
10466
|
openBookingDialog,
|
|
10467
|
+
openBookingPreview,
|
|
9548
10468
|
enhanceText: enhance,
|
|
9549
10469
|
shortcutLabel
|
|
9550
10470
|
},
|
|
@@ -9566,8 +10486,9 @@ function GlitchgrabProviderInner({
|
|
|
9566
10486
|
{
|
|
9567
10487
|
token,
|
|
9568
10488
|
baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
|
|
9569
|
-
open:
|
|
9570
|
-
|
|
10489
|
+
open: booking !== "closed",
|
|
10490
|
+
preview: booking === "preview",
|
|
10491
|
+
onClose: () => setBooking("closed")
|
|
9571
10492
|
}
|
|
9572
10493
|
),
|
|
9573
10494
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -9578,11 +10499,13 @@ function GlitchgrabProviderInner({
|
|
|
9578
10499
|
enhanceText: aiAssist && !aiBlockedUnsigned ? enhance : void 0,
|
|
9579
10500
|
assist: aiAssist && !aiBlockedUnsigned ? assist : void 0,
|
|
9580
10501
|
findSimilarIssues: aiAssist && !aiBlockedUnsigned ? findSimilar : void 0,
|
|
10502
|
+
readFile: aiAssist && !aiBlockedUnsigned ? readFile : void 0,
|
|
9581
10503
|
reportGlitchgrabProblem: glitchgrabReport ? reportGlitchgrabProblem : void 0,
|
|
9582
10504
|
transcribeAudio: aiBlockedUnsigned ? void 0 : transcribe,
|
|
9583
10505
|
types,
|
|
9584
10506
|
showSeverity,
|
|
9585
|
-
reporter,
|
|
10507
|
+
reporter: reporter2,
|
|
10508
|
+
chatHistoryKey: chatHistoryKey("sdk", token, session == null ? void 0 : session.userId),
|
|
9586
10509
|
headerSlot: projectName ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { fontSize: 11, color: "#9aa0a6" }, children: [
|
|
9587
10510
|
"Reporting to ",
|
|
9588
10511
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("strong", { style: { color: "#e5e5e5" }, children: projectName })
|
|
@@ -9982,6 +10905,7 @@ function useGlitchgrabFeedback(query) {
|
|
|
9982
10905
|
// Annotate the CommonJS export names for ESM import in node:
|
|
9983
10906
|
0 && (module.exports = {
|
|
9984
10907
|
BookDemoButton,
|
|
10908
|
+
BookingDialog,
|
|
9985
10909
|
FeedbackButton,
|
|
9986
10910
|
GLITCHGRAB_SHORTCUT,
|
|
9987
10911
|
GLITCHGRAB_SHORTCUT_MAC,
|