glitchgrab 1.23.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -0
- package/dist/index.js +258 -278
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +258 -278
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -707,10 +707,11 @@ function ReportDialog({
|
|
|
707
707
|
const [description, setDescription] = (0, import_react.useState)("");
|
|
708
708
|
const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
|
|
709
709
|
const [submitted, setSubmitted] = (0, import_react.useState)(false);
|
|
710
|
-
const [
|
|
711
|
-
const [
|
|
710
|
+
const [screenshots, setScreenshots] = (0, import_react.useState)([]);
|
|
711
|
+
const [previewIndex, setPreviewIndex] = (0, import_react.useState)(null);
|
|
712
712
|
const fileInputRef = (0, import_react.useRef)(null);
|
|
713
713
|
const modalRef = (0, import_react.useRef)(null);
|
|
714
|
+
const previewImgRef = (0, import_react.useRef)(null);
|
|
714
715
|
const textareaRef = (0, import_react.useRef)(null);
|
|
715
716
|
const recognitionRef = (0, import_react.useRef)(null);
|
|
716
717
|
const voiceBaseRef = (0, import_react.useRef)("");
|
|
@@ -745,20 +746,21 @@ function ReportDialog({
|
|
|
745
746
|
const isDark = useIsDark();
|
|
746
747
|
const t = getTheme(isDark);
|
|
747
748
|
const handleFileUpload = (e) => {
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
749
|
+
const files = e.target.files;
|
|
750
|
+
if (!files || files.length === 0) return;
|
|
751
|
+
Array.from(files).forEach((file) => {
|
|
752
|
+
const reader = new FileReader();
|
|
753
|
+
reader.onload = () => {
|
|
754
|
+
setScreenshots((prev) => [...prev, reader.result]);
|
|
755
|
+
};
|
|
756
|
+
reader.readAsDataURL(file);
|
|
757
|
+
});
|
|
756
758
|
e.target.value = "";
|
|
757
759
|
};
|
|
758
760
|
const retakeScreenshot = async () => {
|
|
759
|
-
|
|
761
|
+
setPreviewIndex(null);
|
|
760
762
|
setIsOpen(false);
|
|
761
|
-
|
|
763
|
+
setScreenshots([]);
|
|
762
764
|
await new Promise((r) => setTimeout(r, 300));
|
|
763
765
|
try {
|
|
764
766
|
const { default: html2canvas } = await import("html2canvas-pro");
|
|
@@ -768,7 +770,7 @@ function ReportDialog({
|
|
|
768
770
|
useCORS: true,
|
|
769
771
|
allowTaint: true
|
|
770
772
|
});
|
|
771
|
-
|
|
773
|
+
setScreenshots([canvas.toDataURL("image/jpeg", 0.6)]);
|
|
772
774
|
} catch (e) {
|
|
773
775
|
}
|
|
774
776
|
setIsOpen(true);
|
|
@@ -787,7 +789,7 @@ function ReportDialog({
|
|
|
787
789
|
useCORS: true,
|
|
788
790
|
allowTaint: true
|
|
789
791
|
});
|
|
790
|
-
|
|
792
|
+
setScreenshots([canvas.toDataURL("image/jpeg", 0.6)]);
|
|
791
793
|
} catch (e) {
|
|
792
794
|
}
|
|
793
795
|
setIsOpen(true);
|
|
@@ -810,13 +812,24 @@ function ReportDialog({
|
|
|
810
812
|
if (!isOpen) return;
|
|
811
813
|
const handleEsc = (e) => {
|
|
812
814
|
if (e.key === "Escape") {
|
|
813
|
-
if (
|
|
815
|
+
if (previewIndex !== null) setPreviewIndex(null);
|
|
814
816
|
else handleClose();
|
|
815
817
|
}
|
|
816
818
|
};
|
|
817
819
|
document.addEventListener("keydown", handleEsc);
|
|
818
820
|
return () => document.removeEventListener("keydown", handleEsc);
|
|
819
|
-
}, [isOpen,
|
|
821
|
+
}, [isOpen, previewIndex]);
|
|
822
|
+
(0, import_react.useEffect)(() => {
|
|
823
|
+
if (previewIndex === null) return;
|
|
824
|
+
const handlePointerDown = (e) => {
|
|
825
|
+
var _a;
|
|
826
|
+
if (!((_a = previewImgRef.current) == null ? void 0 : _a.contains(e.target))) {
|
|
827
|
+
setPreviewIndex(null);
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
document.addEventListener("pointerdown", handlePointerDown, true);
|
|
831
|
+
return () => document.removeEventListener("pointerdown", handlePointerDown, true);
|
|
832
|
+
}, [previewIndex]);
|
|
820
833
|
(0, import_react.useEffect)(() => {
|
|
821
834
|
if (!isOpen) return;
|
|
822
835
|
const handlePaste = (e) => {
|
|
@@ -824,17 +837,18 @@ function ReportDialog({
|
|
|
824
837
|
try {
|
|
825
838
|
const items = (_a = e.clipboardData) == null ? void 0 : _a.items;
|
|
826
839
|
if (!items) return;
|
|
840
|
+
let matched = false;
|
|
827
841
|
for (let i = 0; i < items.length; i++) {
|
|
828
842
|
if (items[i].type.startsWith("image/")) {
|
|
829
843
|
const file = items[i].getAsFile();
|
|
830
844
|
if (!file) continue;
|
|
845
|
+
matched = true;
|
|
831
846
|
const reader = new FileReader();
|
|
832
|
-
reader.onload = () =>
|
|
847
|
+
reader.onload = () => setScreenshots((prev) => [...prev, reader.result]);
|
|
833
848
|
reader.readAsDataURL(file);
|
|
834
|
-
e.preventDefault();
|
|
835
|
-
break;
|
|
836
849
|
}
|
|
837
850
|
}
|
|
851
|
+
if (matched) e.preventDefault();
|
|
838
852
|
} catch (e2) {
|
|
839
853
|
}
|
|
840
854
|
};
|
|
@@ -896,8 +910,9 @@ function ReportDialog({
|
|
|
896
910
|
let stream = null;
|
|
897
911
|
try {
|
|
898
912
|
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
899
|
-
} catch (
|
|
900
|
-
|
|
913
|
+
} catch (err) {
|
|
914
|
+
const isDenied = err instanceof DOMException && (err.name === "NotAllowedError" || err.name === "PermissionDeniedError");
|
|
915
|
+
if (!SpeechRec || isDenied) {
|
|
901
916
|
setVoiceError("Microphone access denied");
|
|
902
917
|
return;
|
|
903
918
|
}
|
|
@@ -974,7 +989,8 @@ function ReportDialog({
|
|
|
974
989
|
};
|
|
975
990
|
recognition.onerror = (event) => {
|
|
976
991
|
if (event.error === "aborted" || event.error === "no-speech") return;
|
|
977
|
-
|
|
992
|
+
const isDenied = event.error === "not-allowed" || event.error === "audio-capture";
|
|
993
|
+
setVoiceError(isDenied ? "Microphone access denied" : "Speech recognition not available \u2014 try Chrome");
|
|
978
994
|
usingWebSpeechRef.current = false;
|
|
979
995
|
recognitionRef.current = null;
|
|
980
996
|
setIsListening(false);
|
|
@@ -986,35 +1002,35 @@ function ReportDialog({
|
|
|
986
1002
|
}
|
|
987
1003
|
};
|
|
988
1004
|
const handleSpaceDown = (e) => {
|
|
1005
|
+
var _a;
|
|
989
1006
|
if (e.code !== "Space") return;
|
|
990
|
-
if (
|
|
1007
|
+
if (isListening || isPushToTalkRef.current) {
|
|
991
1008
|
e.preventDefault();
|
|
992
1009
|
return;
|
|
993
1010
|
}
|
|
994
|
-
if (e.repeat || !transcribeAudio2 || isTranscribing)
|
|
995
|
-
|
|
1011
|
+
if (e.repeat || !transcribeAudio2 || isTranscribing || spaceTimerRef.current)
|
|
1012
|
+
return;
|
|
1013
|
+
const pos = (_a = e.currentTarget.selectionStart) != null ? _a : description.length;
|
|
996
1014
|
spaceTimerRef.current = setTimeout(() => {
|
|
1015
|
+
spaceTimerRef.current = null;
|
|
997
1016
|
isPushToTalkRef.current = true;
|
|
1017
|
+
setDescription(
|
|
1018
|
+
(prev) => prev[pos] === " " ? prev.slice(0, pos) + prev.slice(pos + 1) : prev
|
|
1019
|
+
);
|
|
1020
|
+
requestAnimationFrame(() => {
|
|
1021
|
+
if (textareaRef.current) {
|
|
1022
|
+
textareaRef.current.selectionStart = pos;
|
|
1023
|
+
textareaRef.current.selectionEnd = pos;
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
998
1026
|
void toggleVoice();
|
|
999
1027
|
}, 400);
|
|
1000
1028
|
};
|
|
1001
1029
|
const handleSpaceUp = (e) => {
|
|
1002
|
-
var _a;
|
|
1003
1030
|
if (e.code !== "Space") return;
|
|
1004
1031
|
if (spaceTimerRef.current) {
|
|
1005
1032
|
clearTimeout(spaceTimerRef.current);
|
|
1006
1033
|
spaceTimerRef.current = null;
|
|
1007
|
-
if (!isPushToTalkRef.current) {
|
|
1008
|
-
const ta = textareaRef.current;
|
|
1009
|
-
const pos = ta ? (_a = ta.selectionStart) != null ? _a : description.length : description.length;
|
|
1010
|
-
setDescription((prev) => prev.slice(0, pos) + " " + prev.slice(pos));
|
|
1011
|
-
requestAnimationFrame(() => {
|
|
1012
|
-
if (textareaRef.current) {
|
|
1013
|
-
textareaRef.current.selectionStart = pos + 1;
|
|
1014
|
-
textareaRef.current.selectionEnd = pos + 1;
|
|
1015
|
-
}
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
1034
|
}
|
|
1019
1035
|
if (isPushToTalkRef.current) {
|
|
1020
1036
|
isPushToTalkRef.current = false;
|
|
@@ -1032,7 +1048,7 @@ function ReportDialog({
|
|
|
1032
1048
|
}
|
|
1033
1049
|
setIsSubmitting(true);
|
|
1034
1050
|
const metadata = {};
|
|
1035
|
-
if (
|
|
1051
|
+
if (screenshots.length > 0) metadata.screenshots = JSON.stringify(screenshots);
|
|
1036
1052
|
if (showSeverity && reportType === "BUG") {
|
|
1037
1053
|
metadata.severity = severity;
|
|
1038
1054
|
}
|
|
@@ -1044,7 +1060,7 @@ function ReportDialog({
|
|
|
1044
1060
|
if (result) {
|
|
1045
1061
|
setSubmitted(true);
|
|
1046
1062
|
setDescription("");
|
|
1047
|
-
|
|
1063
|
+
setScreenshots([]);
|
|
1048
1064
|
setTimeout(() => {
|
|
1049
1065
|
setSubmitted(false);
|
|
1050
1066
|
handleClose();
|
|
@@ -1083,7 +1099,7 @@ function ReportDialog({
|
|
|
1083
1099
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
1084
1100
|
},
|
|
1085
1101
|
onClick: () => {
|
|
1086
|
-
if (
|
|
1102
|
+
if (previewIndex === null) handleClose();
|
|
1087
1103
|
},
|
|
1088
1104
|
onPointerDown: (e) => e.stopPropagation(),
|
|
1089
1105
|
onFocus: (e) => e.stopPropagation(),
|
|
@@ -1467,12 +1483,13 @@ function ReportDialog({
|
|
|
1467
1483
|
{
|
|
1468
1484
|
type: "button",
|
|
1469
1485
|
onClick: async () => {
|
|
1486
|
+
var _a;
|
|
1470
1487
|
if (!description.trim() || isEnhancing) return;
|
|
1471
1488
|
setIsEnhancing(true);
|
|
1472
1489
|
try {
|
|
1473
1490
|
const polished = await enhanceText2(
|
|
1474
1491
|
description,
|
|
1475
|
-
|
|
1492
|
+
(_a = screenshots[0]) != null ? _a : null
|
|
1476
1493
|
);
|
|
1477
1494
|
if (polished && polished !== description) {
|
|
1478
1495
|
setOriginalDescription(description);
|
|
@@ -1738,7 +1755,7 @@ function ReportDialog({
|
|
|
1738
1755
|
}
|
|
1739
1756
|
),
|
|
1740
1757
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
|
|
1741
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1758
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1742
1759
|
"span",
|
|
1743
1760
|
{
|
|
1744
1761
|
style: {
|
|
@@ -1748,83 +1765,79 @@ function ReportDialog({
|
|
|
1748
1765
|
display: "block",
|
|
1749
1766
|
fontWeight: 500
|
|
1750
1767
|
},
|
|
1751
|
-
children:
|
|
1768
|
+
children: [
|
|
1769
|
+
"Screenshots",
|
|
1770
|
+
screenshots.length > 0 ? ` (${screenshots.length})` : ""
|
|
1771
|
+
]
|
|
1752
1772
|
}
|
|
1753
1773
|
),
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
border: `1px solid ${t.border}`,
|
|
1766
|
-
maxHeight: "64px",
|
|
1767
|
-
objectFit: "cover",
|
|
1768
|
-
objectPosition: "top",
|
|
1769
|
-
cursor: "zoom-in",
|
|
1770
|
-
display: "block"
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
),
|
|
1774
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1775
|
-
"span",
|
|
1774
|
+
screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1775
|
+
"div",
|
|
1776
|
+
{
|
|
1777
|
+
style: {
|
|
1778
|
+
display: "flex",
|
|
1779
|
+
flexWrap: "wrap",
|
|
1780
|
+
gap: "8px",
|
|
1781
|
+
marginBottom: "8px"
|
|
1782
|
+
},
|
|
1783
|
+
children: screenshots.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1784
|
+
"div",
|
|
1776
1785
|
{
|
|
1777
1786
|
style: {
|
|
1778
|
-
position: "
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
background: "rgba(0,0,0,0.55)",
|
|
1782
|
-
color: "#fff",
|
|
1783
|
-
fontSize: "10px",
|
|
1784
|
-
padding: "1px 5px",
|
|
1785
|
-
borderRadius: "3px",
|
|
1786
|
-
pointerEvents: "none"
|
|
1787
|
+
position: "relative",
|
|
1788
|
+
width: "56px",
|
|
1789
|
+
height: "56px"
|
|
1787
1790
|
},
|
|
1788
|
-
children:
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1791
|
+
children: [
|
|
1792
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1793
|
+
"img",
|
|
1794
|
+
{
|
|
1795
|
+
src,
|
|
1796
|
+
alt: `Screenshot ${i + 1}`,
|
|
1797
|
+
onClick: () => setPreviewIndex(i),
|
|
1798
|
+
style: {
|
|
1799
|
+
width: "100%",
|
|
1800
|
+
height: "100%",
|
|
1801
|
+
borderRadius: "6px",
|
|
1802
|
+
border: `1px solid ${t.border}`,
|
|
1803
|
+
objectFit: "cover",
|
|
1804
|
+
objectPosition: "top",
|
|
1805
|
+
cursor: "zoom-in",
|
|
1806
|
+
display: "block"
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
),
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1811
|
+
"button",
|
|
1812
|
+
{
|
|
1813
|
+
type: "button",
|
|
1814
|
+
onClick: () => setScreenshots(
|
|
1815
|
+
(prev) => prev.filter((_, idx) => idx !== i)
|
|
1816
|
+
),
|
|
1817
|
+
"aria-label": `Remove screenshot ${i + 1}`,
|
|
1818
|
+
style: {
|
|
1819
|
+
position: "absolute",
|
|
1820
|
+
top: "-6px",
|
|
1821
|
+
right: "-6px",
|
|
1822
|
+
width: "17px",
|
|
1823
|
+
height: "17px",
|
|
1824
|
+
borderRadius: "50%",
|
|
1825
|
+
border: "none",
|
|
1826
|
+
background: "#ef4444",
|
|
1827
|
+
color: "#fff",
|
|
1828
|
+
fontSize: "11px",
|
|
1829
|
+
lineHeight: 1,
|
|
1830
|
+
padding: 0,
|
|
1831
|
+
cursor: "pointer",
|
|
1832
|
+
display: "flex",
|
|
1833
|
+
alignItems: "center",
|
|
1834
|
+
justifyContent: "center"
|
|
1835
|
+
},
|
|
1836
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1824
1837
|
"svg",
|
|
1825
1838
|
{
|
|
1826
|
-
width: "
|
|
1827
|
-
height: "
|
|
1839
|
+
width: "8",
|
|
1840
|
+
height: "8",
|
|
1828
1841
|
viewBox: "0 0 10 10",
|
|
1829
1842
|
fill: "none",
|
|
1830
1843
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -1837,171 +1850,136 @@ function ReportDialog({
|
|
|
1837
1850
|
}
|
|
1838
1851
|
)
|
|
1839
1852
|
}
|
|
1840
|
-
)
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
),
|
|
1845
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1846
|
-
"button",
|
|
1847
|
-
{
|
|
1848
|
-
type: "button",
|
|
1849
|
-
onClick: () => {
|
|
1850
|
-
var _a;
|
|
1851
|
-
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
1852
|
-
},
|
|
1853
|
-
style: {
|
|
1854
|
-
flex: 1,
|
|
1855
|
-
padding: "6px 0",
|
|
1856
|
-
borderRadius: "6px",
|
|
1857
|
-
border: `1px solid ${t.inputBorder}`,
|
|
1858
|
-
background: "transparent",
|
|
1859
|
-
color: t.textMuted,
|
|
1860
|
-
fontSize: "12px",
|
|
1861
|
-
fontWeight: 500,
|
|
1862
|
-
cursor: "pointer",
|
|
1863
|
-
fontFamily: "inherit",
|
|
1864
|
-
display: "flex",
|
|
1865
|
-
alignItems: "center",
|
|
1866
|
-
justifyContent: "center",
|
|
1867
|
-
gap: "4px"
|
|
1868
|
-
},
|
|
1869
|
-
children: [
|
|
1870
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1871
|
-
"svg",
|
|
1872
|
-
{
|
|
1873
|
-
width: "11",
|
|
1874
|
-
height: "11",
|
|
1875
|
-
viewBox: "0 0 24 24",
|
|
1876
|
-
fill: "none",
|
|
1877
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1878
|
-
"path",
|
|
1879
|
-
{
|
|
1880
|
-
d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12",
|
|
1881
|
-
stroke: "currentColor",
|
|
1882
|
-
strokeWidth: "2",
|
|
1883
|
-
strokeLinecap: "round",
|
|
1884
|
-
strokeLinejoin: "round"
|
|
1885
|
-
}
|
|
1886
|
-
)
|
|
1887
|
-
}
|
|
1888
|
-
),
|
|
1889
|
-
"Replace"
|
|
1890
|
-
]
|
|
1891
|
-
}
|
|
1892
|
-
)
|
|
1893
|
-
]
|
|
1894
|
-
}
|
|
1895
|
-
)
|
|
1896
|
-
] }) : (
|
|
1897
|
-
/* Drop zone */
|
|
1898
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1899
|
-
"div",
|
|
1900
|
-
{
|
|
1901
|
-
onClick: () => {
|
|
1902
|
-
var _a;
|
|
1903
|
-
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
1853
|
+
)
|
|
1854
|
+
}
|
|
1855
|
+
)
|
|
1856
|
+
]
|
|
1904
1857
|
},
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1858
|
+
i
|
|
1859
|
+
))
|
|
1860
|
+
}
|
|
1861
|
+
),
|
|
1862
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1863
|
+
"div",
|
|
1864
|
+
{
|
|
1865
|
+
onClick: () => {
|
|
1866
|
+
var _a;
|
|
1867
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
1868
|
+
},
|
|
1869
|
+
onDrop: (e) => {
|
|
1870
|
+
e.preventDefault();
|
|
1871
|
+
setScreenshotDragOver(false);
|
|
1872
|
+
const files = Array.from(
|
|
1873
|
+
e.dataTransfer.files
|
|
1874
|
+
).filter((f) => f.type.startsWith("image/"));
|
|
1875
|
+
files.forEach((file) => {
|
|
1912
1876
|
const reader = new FileReader();
|
|
1913
|
-
reader.onload = () =>
|
|
1877
|
+
reader.onload = () => setScreenshots((prev) => [
|
|
1878
|
+
...prev,
|
|
1879
|
+
reader.result
|
|
1880
|
+
]);
|
|
1914
1881
|
reader.readAsDataURL(file);
|
|
1915
|
-
}
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
1882
|
+
});
|
|
1883
|
+
},
|
|
1884
|
+
onDragOver: (e) => {
|
|
1885
|
+
e.preventDefault();
|
|
1886
|
+
setScreenshotDragOver(true);
|
|
1887
|
+
},
|
|
1888
|
+
onDragLeave: () => setScreenshotDragOver(false),
|
|
1889
|
+
style: {
|
|
1890
|
+
border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
|
|
1891
|
+
borderRadius: "8px",
|
|
1892
|
+
padding: screenshots.length > 0 ? "8px 12px" : "18px 12px",
|
|
1893
|
+
textAlign: "center",
|
|
1894
|
+
cursor: "pointer",
|
|
1895
|
+
background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
|
|
1896
|
+
transition: "border-color 0.15s ease, background 0.15s ease"
|
|
1897
|
+
},
|
|
1898
|
+
children: screenshots.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1899
|
+
"p",
|
|
1900
|
+
{
|
|
1901
|
+
style: {
|
|
1902
|
+
margin: 0,
|
|
1903
|
+
fontSize: "11px",
|
|
1904
|
+
fontWeight: 500,
|
|
1905
|
+
color: t.textMuted
|
|
1906
|
+
},
|
|
1907
|
+
children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
|
|
1908
|
+
}
|
|
1909
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1910
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1911
|
+
"svg",
|
|
1912
|
+
{
|
|
1913
|
+
width: "22",
|
|
1914
|
+
height: "22",
|
|
1915
|
+
viewBox: "0 0 24 24",
|
|
1916
|
+
fill: "none",
|
|
1917
|
+
style: {
|
|
1918
|
+
margin: "0 auto 6px",
|
|
1919
|
+
display: "block",
|
|
1920
|
+
opacity: 0.45
|
|
1921
|
+
},
|
|
1922
|
+
children: [
|
|
1923
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1924
|
+
"rect",
|
|
1925
|
+
{
|
|
1926
|
+
x: "3",
|
|
1927
|
+
y: "3",
|
|
1928
|
+
width: "18",
|
|
1929
|
+
height: "18",
|
|
1930
|
+
rx: "2",
|
|
1931
|
+
stroke: t.textMuted,
|
|
1932
|
+
strokeWidth: "1.5"
|
|
1933
|
+
}
|
|
1934
|
+
),
|
|
1935
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1936
|
+
"circle",
|
|
1937
|
+
{
|
|
1938
|
+
cx: "8.5",
|
|
1939
|
+
cy: "8.5",
|
|
1940
|
+
r: "1.5",
|
|
1941
|
+
stroke: t.textMuted,
|
|
1942
|
+
strokeWidth: "1.5"
|
|
1943
|
+
}
|
|
1944
|
+
),
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1946
|
+
"path",
|
|
1947
|
+
{
|
|
1948
|
+
d: "M21 15l-5-5L5 21",
|
|
1949
|
+
stroke: t.textMuted,
|
|
1950
|
+
strokeWidth: "1.5",
|
|
1951
|
+
strokeLinecap: "round",
|
|
1952
|
+
strokeLinejoin: "round"
|
|
1953
|
+
}
|
|
1954
|
+
)
|
|
1955
|
+
]
|
|
1956
|
+
}
|
|
1957
|
+
),
|
|
1958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1959
|
+
"p",
|
|
1960
|
+
{
|
|
1961
|
+
style: {
|
|
1962
|
+
margin: 0,
|
|
1963
|
+
fontSize: "12px",
|
|
1964
|
+
fontWeight: 600,
|
|
1965
|
+
color: t.text
|
|
1966
|
+
},
|
|
1967
|
+
children: screenshotDragOver ? "Drop to attach" : "Add screenshots"
|
|
1968
|
+
}
|
|
1969
|
+
),
|
|
1970
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1971
|
+
"p",
|
|
1972
|
+
{
|
|
1973
|
+
style: {
|
|
1974
|
+
margin: "3px 0 0",
|
|
1975
|
+
fontSize: "11px",
|
|
1976
|
+
color: t.textMuted
|
|
1977
|
+
},
|
|
1978
|
+
children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
|
|
1979
|
+
}
|
|
1980
|
+
)
|
|
1981
|
+
] })
|
|
1982
|
+
}
|
|
2005
1983
|
)
|
|
2006
1984
|
] }),
|
|
2007
1985
|
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
|
|
@@ -2101,11 +2079,12 @@ function ReportDialog({
|
|
|
2101
2079
|
ref: fileInputRef,
|
|
2102
2080
|
type: "file",
|
|
2103
2081
|
accept: "image/*",
|
|
2082
|
+
multiple: true,
|
|
2104
2083
|
onChange: handleFileUpload,
|
|
2105
2084
|
style: { display: "none" }
|
|
2106
2085
|
}
|
|
2107
2086
|
),
|
|
2108
|
-
|
|
2087
|
+
previewIndex !== null && screenshots[previewIndex] && (0, import_react_dom.createPortal)(
|
|
2109
2088
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
2110
2089
|
"div",
|
|
2111
2090
|
{
|
|
@@ -2123,14 +2102,15 @@ function ReportDialog({
|
|
|
2123
2102
|
},
|
|
2124
2103
|
onClick: (e) => {
|
|
2125
2104
|
e.stopPropagation();
|
|
2126
|
-
|
|
2105
|
+
setPreviewIndex(null);
|
|
2127
2106
|
},
|
|
2128
2107
|
onMouseDown: (e) => e.stopPropagation(),
|
|
2129
2108
|
children: [
|
|
2130
2109
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2131
2110
|
"img",
|
|
2132
2111
|
{
|
|
2133
|
-
|
|
2112
|
+
ref: previewImgRef,
|
|
2113
|
+
src: screenshots[previewIndex],
|
|
2134
2114
|
alt: "Screenshot preview",
|
|
2135
2115
|
onClick: (e) => e.stopPropagation(),
|
|
2136
2116
|
style: {
|
|
@@ -2150,7 +2130,7 @@ function ReportDialog({
|
|
|
2150
2130
|
color: t.textMuted,
|
|
2151
2131
|
fontSize: "12px"
|
|
2152
2132
|
},
|
|
2153
|
-
children: "Click outside to close"
|
|
2133
|
+
children: screenshots.length > 1 ? `${previewIndex + 1} / ${screenshots.length} \xB7 Click outside to close` : "Click outside to close"
|
|
2154
2134
|
}
|
|
2155
2135
|
)
|
|
2156
2136
|
]
|