glitchgrab 1.47.0 → 1.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +271 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +271 -59
- package/dist/index.mjs.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,37 @@ import {
|
|
|
14
14
|
// src/error-boundary.tsx
|
|
15
15
|
import * as React from "react";
|
|
16
16
|
|
|
17
|
+
// ../report-ui/dist/assist-response.mjs
|
|
18
|
+
var ASSIST_OFFLINE_MESSAGE = "The assistant is unavailable \u2014 write your report below and send it as normal.";
|
|
19
|
+
function assistOffline() {
|
|
20
|
+
return { conversationId: null, question: null, report: null, degraded: ASSIST_OFFLINE_MESSAGE };
|
|
21
|
+
}
|
|
22
|
+
function toAssistTurnResult(ok, body) {
|
|
23
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
24
|
+
const envelope = body != null ? body : null;
|
|
25
|
+
if (!ok || !(envelope == null ? void 0 : envelope.success)) {
|
|
26
|
+
return {
|
|
27
|
+
...assistOffline(),
|
|
28
|
+
// The server words why (cap, rate limit, switched off). An hourly limit
|
|
29
|
+
// keeps the assistant button for this report.
|
|
30
|
+
degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : ASSIST_OFFLINE_MESSAGE,
|
|
31
|
+
retryable: (envelope == null ? void 0 : envelope.retryable) === true
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const d = (_b = envelope.data) != null ? _b : {};
|
|
35
|
+
return {
|
|
36
|
+
conversationId: (_c = d.conversationId) != null ? _c : null,
|
|
37
|
+
question: (_d = d.question) != null ? _d : null,
|
|
38
|
+
options: Array.isArray(d.options) ? d.options.filter((o) => typeof o === "string") : [],
|
|
39
|
+
report: (_e = d.report) != null ? _e : null,
|
|
40
|
+
duplicate: (_f = d.duplicate) != null ? _f : null,
|
|
41
|
+
related: (_g = d.related) != null ? _g : null,
|
|
42
|
+
solved: (_h = d.solved) != null ? _h : null,
|
|
43
|
+
aboutGlitchgrab: d.aboutGlitchgrab === true,
|
|
44
|
+
degraded: null
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
17
48
|
// src/redact.ts
|
|
18
49
|
var SENSITIVE_KEY_RE = /(pass|pwd|secret|token|auth|session|cookie|credential|apikey|api_key|access_key|private|signature|otp|pin|cvv|card|ssn|aadhaar|pan)/i;
|
|
19
50
|
var EMAIL_RE = /[\w.+-]+@[\w-]+\.[\w.-]+/g;
|
|
@@ -688,13 +719,7 @@ async function findSimilarIssues(description, token, baseUrl, identity) {
|
|
|
688
719
|
}
|
|
689
720
|
}
|
|
690
721
|
async function assistTurn(params, token, baseUrl) {
|
|
691
|
-
|
|
692
|
-
const offline = {
|
|
693
|
-
conversationId: null,
|
|
694
|
-
question: null,
|
|
695
|
-
report: null,
|
|
696
|
-
degraded: "The assistant is unavailable \u2014 write your report below and send it as normal."
|
|
697
|
-
};
|
|
722
|
+
const offline = assistOffline();
|
|
698
723
|
try {
|
|
699
724
|
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/ai/report-chat`;
|
|
700
725
|
const response = await fetch(url, {
|
|
@@ -705,28 +730,7 @@ async function assistTurn(params, token, baseUrl) {
|
|
|
705
730
|
},
|
|
706
731
|
body: JSON.stringify(params)
|
|
707
732
|
});
|
|
708
|
-
|
|
709
|
-
if (!response.ok || !(envelope == null ? void 0 : envelope.success)) {
|
|
710
|
-
return {
|
|
711
|
-
conversationId: null,
|
|
712
|
-
question: null,
|
|
713
|
-
report: null,
|
|
714
|
-
degraded: (_a = envelope == null ? void 0 : envelope.error) != null ? _a : offline.degraded,
|
|
715
|
-
// An hourly limit, not a cap: the dialog keeps the assistant button.
|
|
716
|
-
retryable: (envelope == null ? void 0 : envelope.retryable) === true
|
|
717
|
-
};
|
|
718
|
-
}
|
|
719
|
-
return {
|
|
720
|
-
conversationId: (_c = (_b = envelope.data) == null ? void 0 : _b.conversationId) != null ? _c : null,
|
|
721
|
-
question: (_e = (_d = envelope.data) == null ? void 0 : _d.question) != null ? _e : null,
|
|
722
|
-
options: (_g = (_f = envelope.data) == null ? void 0 : _f.options) != null ? _g : [],
|
|
723
|
-
report: (_i = (_h = envelope.data) == null ? void 0 : _h.report) != null ? _i : null,
|
|
724
|
-
duplicate: (_k = (_j = envelope.data) == null ? void 0 : _j.duplicate) != null ? _k : null,
|
|
725
|
-
related: (_m = (_l = envelope.data) == null ? void 0 : _l.related) != null ? _m : null,
|
|
726
|
-
solved: (_o = (_n = envelope.data) == null ? void 0 : _n.solved) != null ? _o : null,
|
|
727
|
-
aboutGlitchgrab: ((_p = envelope.data) == null ? void 0 : _p.aboutGlitchgrab) === true,
|
|
728
|
-
degraded: null
|
|
729
|
-
};
|
|
733
|
+
return toAssistTurnResult(response.ok, await response.json().catch(() => null));
|
|
730
734
|
} catch (e) {
|
|
731
735
|
return offline;
|
|
732
736
|
}
|
|
@@ -1421,6 +1425,17 @@ var STARTERS = [
|
|
|
1421
1425
|
"It did the wrong thing",
|
|
1422
1426
|
"I wish it could\u2026"
|
|
1423
1427
|
];
|
|
1428
|
+
var CONFIRM_OPTION = "Yes, that's it";
|
|
1429
|
+
function isCheckBackQuestion(text) {
|
|
1430
|
+
const t2 = text.trim();
|
|
1431
|
+
return /^so,? you['’]?re saying\b/i.test(t2) || /\b(is that right|is that correct|did i get (that|it) right|have i got (that|it) right)\s*\??\s*$/i.test(t2);
|
|
1432
|
+
}
|
|
1433
|
+
function isAffirmativeReply(text) {
|
|
1434
|
+
return /^(y|ya|yah|yes|yess|yeah|yep|yup|ok|okay|sure|correct|right|exactly|confirm(ed)?|that['’]?s (it|right|correct)|yes,? that['’]?s (it|right)|haan|han|ha|ho|hmm yes|👍)[\s.!👍]*$/i.test(
|
|
1435
|
+
text.trim()
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
var AUTO_FILE_SECONDS = 4;
|
|
1424
1439
|
var NARROW_QUERY = "(max-width: 640px)";
|
|
1425
1440
|
function useIsNarrow() {
|
|
1426
1441
|
const [narrow, setNarrow] = useState2(false);
|
|
@@ -1535,12 +1550,15 @@ function AssistSheet({
|
|
|
1535
1550
|
const [duplicate, setDuplicate] = useState2(null);
|
|
1536
1551
|
const [glitchgrabOffer, setGlitchgrabOffer] = useState2(false);
|
|
1537
1552
|
const [solved, setSolved] = useState2(null);
|
|
1553
|
+
const needsSeverity = (tile) => showSeverity && tile === "BUG" && !severity;
|
|
1538
1554
|
const [phase, setPhase] = useState2(
|
|
1539
|
-
!typePicked ? "type" : currentTile === "RATING" ? "rating" : "chat"
|
|
1555
|
+
() => !typePicked ? "type" : currentTile === "RATING" ? "rating" : needsSeverity(currentTile) ? "severity" : "chat"
|
|
1540
1556
|
);
|
|
1557
|
+
const [autoFileLeft, setAutoFileLeft] = useState2(null);
|
|
1541
1558
|
const scrollRef = useRef2(null);
|
|
1542
1559
|
const draftRef = useRef2(null);
|
|
1543
1560
|
const seededRef = useRef2(false);
|
|
1561
|
+
const seedPendingRef = useRef2(false);
|
|
1544
1562
|
const eventsRef = useRef2([]);
|
|
1545
1563
|
const aiDraftRef = useRef2(null);
|
|
1546
1564
|
function logEvent(type, detail) {
|
|
@@ -1580,14 +1598,33 @@ function AssistSheet({
|
|
|
1580
1598
|
var _a;
|
|
1581
1599
|
if (phase === "draft") (_a = draftRef.current) == null ? void 0 : _a.focus();
|
|
1582
1600
|
}, [phase]);
|
|
1601
|
+
useEffect2(() => {
|
|
1602
|
+
if (autoFileLeft === null) return;
|
|
1603
|
+
if (isSubmitting || submitted || phase !== "draft") {
|
|
1604
|
+
setAutoFileLeft(null);
|
|
1605
|
+
return;
|
|
1606
|
+
}
|
|
1607
|
+
if (autoFileLeft <= 0) {
|
|
1608
|
+
sendDraft(true);
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
const id = setTimeout(() => setAutoFileLeft((n) => n === null ? null : n - 1), 1e3);
|
|
1612
|
+
return () => clearTimeout(id);
|
|
1613
|
+
}, [autoFileLeft, isSubmitting, submitted, phase]);
|
|
1614
|
+
function stopAutoFile(reason) {
|
|
1615
|
+
if (autoFileLeft === null) return;
|
|
1616
|
+
setAutoFileLeft(null);
|
|
1617
|
+
logEvent("auto_file_stopped", reason);
|
|
1618
|
+
}
|
|
1583
1619
|
function degradeKeepingEvents(events, message, retryable) {
|
|
1584
1620
|
if (events) eventsRef.current = [...events, ...eventsRef.current];
|
|
1585
1621
|
flushEvents();
|
|
1586
1622
|
onDegrade(message, retryable);
|
|
1587
1623
|
}
|
|
1588
|
-
async function runTurn(history2) {
|
|
1624
|
+
async function runTurn(history2, autoFile = false) {
|
|
1589
1625
|
var _a, _b;
|
|
1590
1626
|
setBusy(true);
|
|
1627
|
+
setAutoFileLeft(null);
|
|
1591
1628
|
let result;
|
|
1592
1629
|
const events = takeEvents();
|
|
1593
1630
|
try {
|
|
@@ -1647,6 +1684,9 @@ function AssistSheet({
|
|
|
1647
1684
|
setMessages([...history2, { role: "assistant", content: result.report, kind: "report" }]);
|
|
1648
1685
|
setOptions([]);
|
|
1649
1686
|
setPhase("draft");
|
|
1687
|
+
if (autoFile && !attach && !(severityAsked && !severity)) {
|
|
1688
|
+
setAutoFileLeft(AUTO_FILE_SECONDS);
|
|
1689
|
+
}
|
|
1650
1690
|
return;
|
|
1651
1691
|
}
|
|
1652
1692
|
if (result.question) {
|
|
@@ -1660,13 +1700,34 @@ function AssistSheet({
|
|
|
1660
1700
|
if (seededRef.current) return;
|
|
1661
1701
|
seededRef.current = true;
|
|
1662
1702
|
if (!typePicked || currentTile === "RATING") return;
|
|
1703
|
+
if (phase === "severity") {
|
|
1704
|
+
seedPendingRef.current = true;
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
seedFromDescription();
|
|
1708
|
+
}, []);
|
|
1709
|
+
function seedFromDescription() {
|
|
1663
1710
|
const seed = description.trim();
|
|
1664
1711
|
if (!seed) return;
|
|
1665
1712
|
const history2 = [{ role: "user", content: seed }];
|
|
1666
1713
|
setMessages(history2);
|
|
1667
1714
|
void runTurn(history2);
|
|
1668
|
-
}
|
|
1669
|
-
function
|
|
1715
|
+
}
|
|
1716
|
+
function answerSeverity(value) {
|
|
1717
|
+
onSeverityChange(value);
|
|
1718
|
+
setPhase("chat");
|
|
1719
|
+
if (seedPendingRef.current) {
|
|
1720
|
+
seedPendingRef.current = false;
|
|
1721
|
+
seedFromDescription();
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
function sendTyped(text) {
|
|
1725
|
+
var _a;
|
|
1726
|
+
const lastAssistant = [...messages].reverse().find((m) => m.role === "assistant");
|
|
1727
|
+
const checkingBack = options.includes(CONFIRM_OPTION) || (lastAssistant == null ? void 0 : lastAssistant.kind) !== "report" && isCheckBackQuestion((_a = lastAssistant == null ? void 0 : lastAssistant.content) != null ? _a : "");
|
|
1728
|
+
send(text, checkingBack && isAffirmativeReply(text));
|
|
1729
|
+
}
|
|
1730
|
+
function send(text, autoFile = false) {
|
|
1670
1731
|
const value = text.trim();
|
|
1671
1732
|
if (!value || busy) return;
|
|
1672
1733
|
setOptions([]);
|
|
@@ -1681,11 +1742,11 @@ function AssistSheet({
|
|
|
1681
1742
|
const history2 = [...base, { role: "user", content: value }];
|
|
1682
1743
|
setMessages(history2);
|
|
1683
1744
|
setInput("");
|
|
1684
|
-
void runTurn(history2);
|
|
1745
|
+
void runTurn(history2, autoFile);
|
|
1685
1746
|
}
|
|
1686
1747
|
function pickType(tile) {
|
|
1687
1748
|
onPickType(tile);
|
|
1688
|
-
setPhase(tile === "RATING" ? "rating" : "chat");
|
|
1749
|
+
setPhase(tile === "RATING" ? "rating" : needsSeverity(tile) ? "severity" : "chat");
|
|
1689
1750
|
}
|
|
1690
1751
|
function withCurrentDraft(history2) {
|
|
1691
1752
|
const current = description.trim();
|
|
@@ -1698,9 +1759,10 @@ function AssistSheet({
|
|
|
1698
1759
|
}
|
|
1699
1760
|
return next;
|
|
1700
1761
|
}
|
|
1701
|
-
function sendDraft() {
|
|
1762
|
+
function sendDraft(auto = false) {
|
|
1763
|
+
setAutoFileLeft(null);
|
|
1702
1764
|
const edited = aiDraftRef.current !== null && description.trim() !== aiDraftRef.current.trim();
|
|
1703
|
-
logEvent("draft_sent", edited ? "edited" : "as drafted");
|
|
1765
|
+
logEvent("draft_sent", auto ? "auto-filed" : edited ? "edited" : "as drafted");
|
|
1704
1766
|
flushEvents();
|
|
1705
1767
|
onSend();
|
|
1706
1768
|
}
|
|
@@ -1760,6 +1822,7 @@ function AssistSheet({
|
|
|
1760
1822
|
@keyframes gg-sheet-in{from{transform:translateX(24px);opacity:0}to{transform:translateX(0);opacity:1}}
|
|
1761
1823
|
@keyframes gg-sheet-up{from{transform:translateY(24px);opacity:0}to{transform:translateY(0);opacity:1}}
|
|
1762
1824
|
@keyframes gg-sheet-fade{from{opacity:0}to{opacity:1}}
|
|
1825
|
+
@keyframes gg-autofile{from{transform:scaleX(0)}to{transform:scaleX(1)}}
|
|
1763
1826
|
@keyframes gg-dot{0%,80%,100%{transform:translateY(0);opacity:.4}40%{transform:translateY(-3px);opacity:1}}
|
|
1764
1827
|
[data-gg-sheet-send]:focus-visible,[data-gg-chip]:focus-visible,[data-gg-assist-remove]:focus-visible{outline:2px solid currentColor;outline-offset:2px}
|
|
1765
1828
|
` }),
|
|
@@ -1854,6 +1917,7 @@ function AssistSheet({
|
|
|
1854
1917
|
),
|
|
1855
1918
|
/* @__PURE__ */ jsxs2("div", { style: { fontSize: "11.5px", color: t2.textMuted, marginTop: "3px" }, children: [
|
|
1856
1919
|
phase === "type" ? null : reportTypeLabel,
|
|
1920
|
+
phase !== "type" && severityAsked && severity ? ` \xB7 ${SEVERITY_LABELS[severity]}` : null,
|
|
1857
1921
|
projectSlot ? /* @__PURE__ */ jsx2("span", { style: { marginLeft: "6px" }, children: projectSlot }) : null
|
|
1858
1922
|
] })
|
|
1859
1923
|
] }),
|
|
@@ -1972,6 +2036,62 @@ function AssistSheet({
|
|
|
1972
2036
|
}
|
|
1973
2037
|
)
|
|
1974
2038
|
] }),
|
|
2039
|
+
phase === "severity" && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
2040
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
2041
|
+
/* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
|
|
2042
|
+
/* @__PURE__ */ jsx2(
|
|
2043
|
+
"div",
|
|
2044
|
+
{
|
|
2045
|
+
style: {
|
|
2046
|
+
padding: "9px 12px",
|
|
2047
|
+
borderRadius: "12px 12px 12px 4px",
|
|
2048
|
+
backgroundColor: t2.bgSecondary,
|
|
2049
|
+
fontSize: "13px",
|
|
2050
|
+
lineHeight: 1.55,
|
|
2051
|
+
maxWidth: "88%"
|
|
2052
|
+
},
|
|
2053
|
+
children: "How bad is it?"
|
|
2054
|
+
}
|
|
2055
|
+
)
|
|
2056
|
+
] }),
|
|
2057
|
+
/* @__PURE__ */ jsx2(
|
|
2058
|
+
"div",
|
|
2059
|
+
{
|
|
2060
|
+
role: "radiogroup",
|
|
2061
|
+
"aria-label": "Severity",
|
|
2062
|
+
style: {
|
|
2063
|
+
display: "flex",
|
|
2064
|
+
flexWrap: "wrap",
|
|
2065
|
+
gap: "6px",
|
|
2066
|
+
paddingLeft: "32px"
|
|
2067
|
+
},
|
|
2068
|
+
children: SEVERITY_LEVELS.map((s) => /* @__PURE__ */ jsx2(
|
|
2069
|
+
"button",
|
|
2070
|
+
{
|
|
2071
|
+
type: "button",
|
|
2072
|
+
role: "radio",
|
|
2073
|
+
"aria-checked": severity === s,
|
|
2074
|
+
"data-gg-chip": "",
|
|
2075
|
+
"data-gg-severity": s,
|
|
2076
|
+
onClick: () => answerSeverity(s),
|
|
2077
|
+
style: {
|
|
2078
|
+
border: `1px solid ${t2.inputBorder}`,
|
|
2079
|
+
background: "transparent",
|
|
2080
|
+
color: t2.textMuted,
|
|
2081
|
+
borderRadius: "999px",
|
|
2082
|
+
// Same as the picker and option chips — one chip size.
|
|
2083
|
+
padding: "8px 12px",
|
|
2084
|
+
fontSize: "12px",
|
|
2085
|
+
fontFamily: "inherit",
|
|
2086
|
+
cursor: "pointer"
|
|
2087
|
+
},
|
|
2088
|
+
children: SEVERITY_LABELS[s]
|
|
2089
|
+
},
|
|
2090
|
+
s
|
|
2091
|
+
))
|
|
2092
|
+
}
|
|
2093
|
+
)
|
|
2094
|
+
] }),
|
|
1975
2095
|
phase === "rating" && !submitted && /* @__PURE__ */ jsxs2("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
|
|
1976
2096
|
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px" }, children: [
|
|
1977
2097
|
/* @__PURE__ */ jsx2(Avatar, { who: "assistant", theme: t2 }),
|
|
@@ -2160,7 +2280,11 @@ function AssistSheet({
|
|
|
2160
2280
|
color: t2.text,
|
|
2161
2281
|
border: live ? "none" : `1px solid ${t2.accent}66`
|
|
2162
2282
|
},
|
|
2163
|
-
children: live ?
|
|
2283
|
+
children: live ? (
|
|
2284
|
+
// #402: "have a read" beside a countdown reads as a
|
|
2285
|
+
// contradiction. Say what is about to happen instead.
|
|
2286
|
+
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."
|
|
2287
|
+
) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2164
2288
|
/* @__PURE__ */ jsx2(
|
|
2165
2289
|
"span",
|
|
2166
2290
|
{
|
|
@@ -2327,7 +2451,7 @@ function AssistSheet({
|
|
|
2327
2451
|
"data-gg-option": "",
|
|
2328
2452
|
onClick: () => {
|
|
2329
2453
|
logEvent("option_tap", option);
|
|
2330
|
-
send(option);
|
|
2454
|
+
send(option, option === CONFIRM_OPTION);
|
|
2331
2455
|
},
|
|
2332
2456
|
style: {
|
|
2333
2457
|
border: `1px solid ${t2.inputBorder}`,
|
|
@@ -2414,7 +2538,10 @@ function AssistSheet({
|
|
|
2414
2538
|
{
|
|
2415
2539
|
ref: draftRef,
|
|
2416
2540
|
value: description,
|
|
2417
|
-
onChange: (e) =>
|
|
2541
|
+
onChange: (e) => {
|
|
2542
|
+
stopAutoFile("edited the draft");
|
|
2543
|
+
onDescriptionChange(e.target.value);
|
|
2544
|
+
},
|
|
2418
2545
|
rows: 6,
|
|
2419
2546
|
style: {
|
|
2420
2547
|
width: "100%",
|
|
@@ -2433,7 +2560,7 @@ function AssistSheet({
|
|
|
2433
2560
|
}
|
|
2434
2561
|
}
|
|
2435
2562
|
),
|
|
2436
|
-
severityAsked && /* @__PURE__ */ jsxs2("div", { children: [
|
|
2563
|
+
severityAsked && autoFileLeft === null && /* @__PURE__ */ jsxs2("div", { children: [
|
|
2437
2564
|
/* @__PURE__ */ jsxs2(
|
|
2438
2565
|
"span",
|
|
2439
2566
|
{
|
|
@@ -2555,7 +2682,7 @@ function AssistSheet({
|
|
|
2555
2682
|
)
|
|
2556
2683
|
}
|
|
2557
2684
|
),
|
|
2558
|
-
!submitted && phase !== "type" && /* @__PURE__ */ jsxs2(
|
|
2685
|
+
!submitted && phase !== "type" && phase !== "severity" && /* @__PURE__ */ jsxs2(
|
|
2559
2686
|
"div",
|
|
2560
2687
|
{
|
|
2561
2688
|
style: {
|
|
@@ -2662,6 +2789,7 @@ function AssistSheet({
|
|
|
2662
2789
|
"aria-label": `Remove image ${i + 1}`,
|
|
2663
2790
|
title: "Remove this image",
|
|
2664
2791
|
onClick: () => {
|
|
2792
|
+
stopAutoFile("changed attachments");
|
|
2665
2793
|
logEvent(
|
|
2666
2794
|
"image_removed",
|
|
2667
2795
|
pageShot && shot === pageShot ? "page capture" : "attached"
|
|
@@ -2772,6 +2900,7 @@ function AssistSheet({
|
|
|
2772
2900
|
"aria-label": `Remove file ${file.name}`,
|
|
2773
2901
|
title: "Remove this file",
|
|
2774
2902
|
onClick: () => {
|
|
2903
|
+
stopAutoFile("changed attachments");
|
|
2775
2904
|
logEvent("file_removed", read ? "read" : "not read");
|
|
2776
2905
|
onRemoveFile(i);
|
|
2777
2906
|
},
|
|
@@ -2854,6 +2983,7 @@ function AssistSheet({
|
|
|
2854
2983
|
var _a;
|
|
2855
2984
|
const picked = Array.from((_a = e.target.files) != null ? _a : []);
|
|
2856
2985
|
if (picked.length) {
|
|
2986
|
+
stopAutoFile("changed attachments");
|
|
2857
2987
|
const images = picked.filter((f) => f.type.startsWith("image/")).length;
|
|
2858
2988
|
if (images) logEvent("image_added", String(images));
|
|
2859
2989
|
if (picked.length > images) {
|
|
@@ -2883,11 +3013,14 @@ function AssistSheet({
|
|
|
2883
3013
|
"textarea",
|
|
2884
3014
|
{
|
|
2885
3015
|
value: input,
|
|
2886
|
-
onChange: (e) =>
|
|
3016
|
+
onChange: (e) => {
|
|
3017
|
+
stopAutoFile("typing a change");
|
|
3018
|
+
setInput(e.target.value);
|
|
3019
|
+
},
|
|
2887
3020
|
onKeyDown: (e) => {
|
|
2888
3021
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
2889
3022
|
e.preventDefault();
|
|
2890
|
-
|
|
3023
|
+
sendTyped(input);
|
|
2891
3024
|
}
|
|
2892
3025
|
},
|
|
2893
3026
|
placeholder: phase === "draft" ? "Anything to change? Tell me here\u2026" : "Type your answer\u2026",
|
|
@@ -2917,7 +3050,7 @@ function AssistSheet({
|
|
|
2917
3050
|
{
|
|
2918
3051
|
type: "button",
|
|
2919
3052
|
"data-gg-sheet-send": "",
|
|
2920
|
-
onClick: () =>
|
|
3053
|
+
onClick: () => sendTyped(input),
|
|
2921
3054
|
disabled: busy || !input.trim(),
|
|
2922
3055
|
"aria-label": "Send message",
|
|
2923
3056
|
"data-gg-send-message": "",
|
|
@@ -2956,12 +3089,87 @@ function AssistSheet({
|
|
|
2956
3089
|
children: validationError
|
|
2957
3090
|
}
|
|
2958
3091
|
),
|
|
2959
|
-
|
|
3092
|
+
autoFileLeft !== null ? (
|
|
3093
|
+
// #402: "Yes, that's it" was the confirmation. The draft
|
|
3094
|
+
// files itself unless they stop it — the bar shows how
|
|
3095
|
+
// long is left, the button sends now.
|
|
3096
|
+
/* @__PURE__ */ jsxs2("div", { style: { display: "flex", gap: "8px", marginTop: "8px" }, children: [
|
|
3097
|
+
/* @__PURE__ */ jsxs2(
|
|
3098
|
+
"button",
|
|
3099
|
+
{
|
|
3100
|
+
type: "button",
|
|
3101
|
+
"data-gg-sheet-send": "",
|
|
3102
|
+
"data-gg-auto-file": "",
|
|
3103
|
+
onClick: () => sendDraft(),
|
|
3104
|
+
style: {
|
|
3105
|
+
flex: 1,
|
|
3106
|
+
minWidth: 0,
|
|
3107
|
+
position: "relative",
|
|
3108
|
+
overflow: "hidden",
|
|
3109
|
+
padding: "12px",
|
|
3110
|
+
borderRadius: "10px",
|
|
3111
|
+
border: "none",
|
|
3112
|
+
backgroundColor: t2.accent,
|
|
3113
|
+
color: t2.accentText,
|
|
3114
|
+
fontSize: "14px",
|
|
3115
|
+
fontWeight: 700,
|
|
3116
|
+
fontFamily: "inherit",
|
|
3117
|
+
cursor: "pointer"
|
|
3118
|
+
},
|
|
3119
|
+
children: [
|
|
3120
|
+
/* @__PURE__ */ jsx2(
|
|
3121
|
+
"span",
|
|
3122
|
+
{
|
|
3123
|
+
"aria-hidden": "true",
|
|
3124
|
+
style: {
|
|
3125
|
+
position: "absolute",
|
|
3126
|
+
inset: 0,
|
|
3127
|
+
backgroundColor: "rgba(255,255,255,0.22)",
|
|
3128
|
+
transformOrigin: "left",
|
|
3129
|
+
animation: `gg-autofile ${AUTO_FILE_SECONDS}s linear forwards`
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
),
|
|
3133
|
+
/* @__PURE__ */ jsxs2("span", { style: { position: "relative" }, children: [
|
|
3134
|
+
"Filing in ",
|
|
3135
|
+
autoFileLeft,
|
|
3136
|
+
"s\u2026"
|
|
3137
|
+
] })
|
|
3138
|
+
]
|
|
3139
|
+
}
|
|
3140
|
+
),
|
|
3141
|
+
/* @__PURE__ */ jsx2(
|
|
3142
|
+
"button",
|
|
3143
|
+
{
|
|
3144
|
+
type: "button",
|
|
3145
|
+
"data-gg-edit-first": "",
|
|
3146
|
+
onClick: () => {
|
|
3147
|
+
var _a;
|
|
3148
|
+
stopAutoFile("edit first");
|
|
3149
|
+
(_a = draftRef.current) == null ? void 0 : _a.focus();
|
|
3150
|
+
},
|
|
3151
|
+
style: {
|
|
3152
|
+
flexShrink: 0,
|
|
3153
|
+
padding: "12px 14px",
|
|
3154
|
+
borderRadius: "10px",
|
|
3155
|
+
border: `1px solid ${t2.inputBorder}`,
|
|
3156
|
+
background: "transparent",
|
|
3157
|
+
color: t2.text,
|
|
3158
|
+
fontSize: "13px",
|
|
3159
|
+
fontWeight: 600,
|
|
3160
|
+
fontFamily: "inherit",
|
|
3161
|
+
cursor: "pointer"
|
|
3162
|
+
},
|
|
3163
|
+
children: "Edit first"
|
|
3164
|
+
}
|
|
3165
|
+
)
|
|
3166
|
+
] })
|
|
3167
|
+
) : /* @__PURE__ */ jsx2(
|
|
2960
3168
|
"button",
|
|
2961
3169
|
{
|
|
2962
3170
|
type: "button",
|
|
2963
3171
|
"data-gg-sheet-send": "",
|
|
2964
|
-
onClick: sendDraft,
|
|
3172
|
+
onClick: () => sendDraft(),
|
|
2965
3173
|
disabled: isSubmitting || !description.trim(),
|
|
2966
3174
|
style: {
|
|
2967
3175
|
width: "100%",
|
|
@@ -3937,9 +4145,11 @@ function ReportDialog({
|
|
|
3937
4145
|
reporter,
|
|
3938
4146
|
onClose,
|
|
3939
4147
|
headerSlot,
|
|
3940
|
-
reportGlitchgrabProblem
|
|
4148
|
+
reportGlitchgrabProblem,
|
|
4149
|
+
layout = "modal"
|
|
3941
4150
|
}) {
|
|
3942
4151
|
var _a;
|
|
4152
|
+
const sheet = layout === "sheet";
|
|
3943
4153
|
const [isEnhancing, setIsEnhancing] = useState4(false);
|
|
3944
4154
|
const [assistOpen, setAssistOpen] = useState4(false);
|
|
3945
4155
|
const [assistNotice, setAssistNotice] = useState4(null);
|
|
@@ -4747,8 +4957,8 @@ function ReportDialog({
|
|
|
4747
4957
|
// dialog's state IS the report, and unmounting would drop the
|
|
4748
4958
|
// screenshots, attachments and step the reporter is on.
|
|
4749
4959
|
display: sheetUp ? "none" : "flex",
|
|
4750
|
-
alignItems: "center",
|
|
4751
|
-
justifyContent: "center",
|
|
4960
|
+
alignItems: sheet ? "stretch" : "center",
|
|
4961
|
+
justifyContent: sheet ? "flex-end" : "center",
|
|
4752
4962
|
backgroundColor: "rgba(0,0,0,0.5)",
|
|
4753
4963
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
4754
4964
|
},
|
|
@@ -4768,14 +4978,15 @@ function ReportDialog({
|
|
|
4768
4978
|
style: {
|
|
4769
4979
|
position: "relative",
|
|
4770
4980
|
zIndex: 2147483647,
|
|
4771
|
-
width: "420px",
|
|
4772
|
-
maxWidth: "calc(100% - 32px)",
|
|
4773
|
-
maxHeight: "calc(100dvh - 32px)",
|
|
4981
|
+
width: sheet ? "440px" : "420px",
|
|
4982
|
+
maxWidth: sheet ? "100%" : "calc(100% - 32px)",
|
|
4983
|
+
maxHeight: sheet ? "100dvh" : "calc(100dvh - 32px)",
|
|
4984
|
+
...sheet ? { height: "100dvh", borderLeft: `1px solid ${t2.inputBorder}` } : {},
|
|
4774
4985
|
display: "flex",
|
|
4775
4986
|
flexDirection: "column",
|
|
4776
4987
|
backgroundColor: t2.bg,
|
|
4777
|
-
borderRadius: "12px",
|
|
4778
|
-
boxShadow: "0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)",
|
|
4988
|
+
borderRadius: sheet ? 0 : "12px",
|
|
4989
|
+
boxShadow: sheet ? "0 20px 60px rgba(0, 0, 0, 0.35)" : "0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)",
|
|
4779
4990
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
4780
4991
|
overflow: "hidden",
|
|
4781
4992
|
color: t2.text,
|
|
@@ -4809,7 +5020,7 @@ function ReportDialog({
|
|
|
4809
5020
|
gap: "8px"
|
|
4810
5021
|
},
|
|
4811
5022
|
children: [
|
|
4812
|
-
step > 1 && /* @__PURE__ */ jsx4(
|
|
5023
|
+
step > 1 && availableTypes.length > 1 && /* @__PURE__ */ jsx4(
|
|
4813
5024
|
"button",
|
|
4814
5025
|
{
|
|
4815
5026
|
type: "button",
|
|
@@ -4927,7 +5138,7 @@ function ReportDialog({
|
|
|
4927
5138
|
]
|
|
4928
5139
|
}
|
|
4929
5140
|
),
|
|
4930
|
-
/* @__PURE__ */ jsx4(
|
|
5141
|
+
availableTypes.length > 1 && /* @__PURE__ */ jsx4(
|
|
4931
5142
|
"div",
|
|
4932
5143
|
{
|
|
4933
5144
|
style: {
|
|
@@ -5203,6 +5414,7 @@ function ReportDialog({
|
|
|
5203
5414
|
"button",
|
|
5204
5415
|
{
|
|
5205
5416
|
type: "button",
|
|
5417
|
+
disabled: availableTypes.length === 1,
|
|
5206
5418
|
onClick: () => setStep(1),
|
|
5207
5419
|
style: {
|
|
5208
5420
|
display: "inline-flex",
|
|
@@ -5217,12 +5429,12 @@ function ReportDialog({
|
|
|
5217
5429
|
fontSize: "11px",
|
|
5218
5430
|
fontWeight: 600,
|
|
5219
5431
|
fontFamily: "inherit",
|
|
5220
|
-
cursor: "pointer"
|
|
5432
|
+
cursor: availableTypes.length === 1 ? "default" : "pointer"
|
|
5221
5433
|
},
|
|
5222
5434
|
children: [
|
|
5223
5435
|
getTypeIcon(reportType, isRating ? "#f59e0b" : t2.accent, 13),
|
|
5224
5436
|
getTypeLabel(reportType),
|
|
5225
|
-
/* @__PURE__ */ jsx4("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
|
|
5437
|
+
availableTypes.length > 1 && /* @__PURE__ */ jsx4("span", { style: { color: t2.textMuted, fontWeight: 400 }, children: "\xB7 change" })
|
|
5226
5438
|
]
|
|
5227
5439
|
}
|
|
5228
5440
|
),
|