glitchgrab 1.22.0 → 1.23.1
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.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +1099 -282
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1104 -283
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -272,7 +272,7 @@ async function sendReport(payload, baseUrl) {
|
|
|
272
272
|
return null;
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
|
-
async function enhanceText(text, token, baseUrl) {
|
|
275
|
+
async function enhanceText(text, token, baseUrl, screenshot, context) {
|
|
276
276
|
var _a;
|
|
277
277
|
try {
|
|
278
278
|
const trimmed = text.trim();
|
|
@@ -284,7 +284,11 @@ async function enhanceText(text, token, baseUrl) {
|
|
|
284
284
|
"Content-Type": "application/json",
|
|
285
285
|
Authorization: `Bearer ${token}`
|
|
286
286
|
},
|
|
287
|
-
body: JSON.stringify({
|
|
287
|
+
body: JSON.stringify({
|
|
288
|
+
text: trimmed,
|
|
289
|
+
...screenshot ? { screenshot } : {},
|
|
290
|
+
...context ? { context } : {}
|
|
291
|
+
})
|
|
288
292
|
});
|
|
289
293
|
if (!response.ok) return text;
|
|
290
294
|
const envelope = await response.json();
|
|
@@ -296,6 +300,28 @@ async function enhanceText(text, token, baseUrl) {
|
|
|
296
300
|
return text;
|
|
297
301
|
}
|
|
298
302
|
}
|
|
303
|
+
async function transcribeAudio(blob, token, baseUrl) {
|
|
304
|
+
var _a;
|
|
305
|
+
try {
|
|
306
|
+
if (blob.size === 0) return "";
|
|
307
|
+
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/sdk/stt`;
|
|
308
|
+
const form = new FormData();
|
|
309
|
+
form.append("file", blob, "audio.webm");
|
|
310
|
+
const response = await fetch(url, {
|
|
311
|
+
method: "POST",
|
|
312
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
313
|
+
body: form
|
|
314
|
+
});
|
|
315
|
+
if (!response.ok) return "";
|
|
316
|
+
const envelope = await response.json();
|
|
317
|
+
if ((envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.transcript) === "string") {
|
|
318
|
+
return envelope.data.transcript;
|
|
319
|
+
}
|
|
320
|
+
return "";
|
|
321
|
+
} catch (e) {
|
|
322
|
+
return "";
|
|
323
|
+
}
|
|
324
|
+
}
|
|
299
325
|
|
|
300
326
|
// src/dedup.ts
|
|
301
327
|
var DEFAULT_WINDOW_MS = 5 * 60 * 1e3;
|
|
@@ -426,7 +452,11 @@ var GlitchgrabErrorBoundary = class extends React.Component {
|
|
|
426
452
|
};
|
|
427
453
|
|
|
428
454
|
// src/report-dialog.tsx
|
|
429
|
-
import {
|
|
455
|
+
import {
|
|
456
|
+
useState,
|
|
457
|
+
useRef,
|
|
458
|
+
useEffect
|
|
459
|
+
} from "react";
|
|
430
460
|
import { createPortal } from "react-dom";
|
|
431
461
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
432
462
|
function useIsDark() {
|
|
@@ -434,11 +464,17 @@ function useIsDark() {
|
|
|
434
464
|
try {
|
|
435
465
|
for (const el of [document.body, document.documentElement]) {
|
|
436
466
|
const bg = getComputedStyle(el).backgroundColor;
|
|
437
|
-
const match = bg.match(
|
|
467
|
+
const match = bg.match(
|
|
468
|
+
/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/
|
|
469
|
+
);
|
|
438
470
|
if (match) {
|
|
439
471
|
const alpha = match[4] !== void 0 ? parseFloat(match[4]) : 1;
|
|
440
472
|
if (alpha < 0.05) continue;
|
|
441
|
-
const [r, g, b] = [
|
|
473
|
+
const [r, g, b] = [
|
|
474
|
+
Number(match[1]),
|
|
475
|
+
Number(match[2]),
|
|
476
|
+
Number(match[3])
|
|
477
|
+
];
|
|
442
478
|
return (r * 299 + g * 587 + b * 114) / 1e3 < 128;
|
|
443
479
|
}
|
|
444
480
|
}
|
|
@@ -464,14 +500,26 @@ function parseColorToRgb(value) {
|
|
|
464
500
|
const hexMatch = trimmed.match(/^#([0-9a-f]{3,8})$/i);
|
|
465
501
|
if (hexMatch) {
|
|
466
502
|
let hex = hexMatch[1];
|
|
467
|
-
if (hex.length === 3)
|
|
468
|
-
|
|
503
|
+
if (hex.length === 3)
|
|
504
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
505
|
+
return [
|
|
506
|
+
parseInt(hex.slice(0, 2), 16),
|
|
507
|
+
parseInt(hex.slice(2, 4), 16),
|
|
508
|
+
parseInt(hex.slice(4, 6), 16)
|
|
509
|
+
];
|
|
469
510
|
}
|
|
470
511
|
const rgbMatch = trimmed.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
|
|
471
|
-
if (rgbMatch)
|
|
472
|
-
|
|
512
|
+
if (rgbMatch)
|
|
513
|
+
return [Number(rgbMatch[1]), Number(rgbMatch[2]), Number(rgbMatch[3])];
|
|
514
|
+
const hslMatch = trimmed.match(
|
|
515
|
+
/hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%/
|
|
516
|
+
);
|
|
473
517
|
if (hslMatch) {
|
|
474
|
-
const hex = hslToHex(
|
|
518
|
+
const hex = hslToHex(
|
|
519
|
+
Number(hslMatch[1]),
|
|
520
|
+
Number(hslMatch[2]),
|
|
521
|
+
Number(hslMatch[3])
|
|
522
|
+
);
|
|
475
523
|
return parseColorToRgb(hex);
|
|
476
524
|
}
|
|
477
525
|
return null;
|
|
@@ -501,9 +549,16 @@ function detectHostAccent() {
|
|
|
501
549
|
if (!raw) continue;
|
|
502
550
|
const hslSpaceMatch = raw.match(/^([\d.]+)\s+([\d.]+)%\s+([\d.]+)%$/);
|
|
503
551
|
if (hslSpaceMatch) {
|
|
504
|
-
const hex = hslToHex(
|
|
552
|
+
const hex = hslToHex(
|
|
553
|
+
Number(hslSpaceMatch[1]),
|
|
554
|
+
Number(hslSpaceMatch[2]),
|
|
555
|
+
Number(hslSpaceMatch[3])
|
|
556
|
+
);
|
|
505
557
|
const rgb2 = parseColorToRgb(hex);
|
|
506
|
-
return {
|
|
558
|
+
return {
|
|
559
|
+
accent: hex,
|
|
560
|
+
accentText: rgb2 ? getContrastText(...rgb2) : "#ffffff"
|
|
561
|
+
};
|
|
507
562
|
}
|
|
508
563
|
const rgb = parseColorToRgb(raw);
|
|
509
564
|
if (rgb) {
|
|
@@ -518,7 +573,27 @@ function detectHostAccent() {
|
|
|
518
573
|
}
|
|
519
574
|
function getTheme(dark) {
|
|
520
575
|
const hostAccent = detectHostAccent();
|
|
521
|
-
const defaults = dark ? {
|
|
576
|
+
const defaults = dark ? {
|
|
577
|
+
bg: "#1c1c1e",
|
|
578
|
+
bgSecondary: "#27272a",
|
|
579
|
+
border: "#2c2c2e",
|
|
580
|
+
text: "#fafafa",
|
|
581
|
+
textMuted: "#a1a1aa",
|
|
582
|
+
accent: "#22d3ee",
|
|
583
|
+
accentText: "#09090b",
|
|
584
|
+
inputBg: "#27272a",
|
|
585
|
+
inputBorder: "#3f3f46"
|
|
586
|
+
} : {
|
|
587
|
+
bg: "#ffffff",
|
|
588
|
+
bgSecondary: "#f4f4f5",
|
|
589
|
+
border: "#e4e4e7",
|
|
590
|
+
text: "#18181b",
|
|
591
|
+
textMuted: "#71717a",
|
|
592
|
+
accent: "#0891b2",
|
|
593
|
+
accentText: "#ffffff",
|
|
594
|
+
inputBg: "#fafafa",
|
|
595
|
+
inputBorder: "#d4d4d8"
|
|
596
|
+
};
|
|
522
597
|
if (hostAccent) {
|
|
523
598
|
defaults.accent = hostAccent.accent;
|
|
524
599
|
defaults.accentText = hostAccent.accentText;
|
|
@@ -568,10 +643,18 @@ function isLowQualityText(text) {
|
|
|
568
643
|
function ReportDialog({
|
|
569
644
|
report,
|
|
570
645
|
enhanceText: enhanceText2,
|
|
646
|
+
transcribeAudio: transcribeAudio2,
|
|
571
647
|
types,
|
|
572
648
|
showSeverity = true
|
|
573
649
|
}) {
|
|
574
650
|
const [isEnhancing, setIsEnhancing] = useState(false);
|
|
651
|
+
const [isEnhanced, setIsEnhanced] = useState(false);
|
|
652
|
+
const [originalDescription, setOriginalDescription] = useState(
|
|
653
|
+
null
|
|
654
|
+
);
|
|
655
|
+
const [isListening, setIsListening] = useState(false);
|
|
656
|
+
const [isTranscribing, setIsTranscribing] = useState(false);
|
|
657
|
+
const [voiceError, setVoiceError] = useState(null);
|
|
575
658
|
const [screenshotDragOver, setScreenshotDragOver] = useState(false);
|
|
576
659
|
const [mounted, setMounted] = useState(false);
|
|
577
660
|
useEffect(() => {
|
|
@@ -585,10 +668,22 @@ function ReportDialog({
|
|
|
585
668
|
const [previewOpen, setPreviewOpen] = useState(false);
|
|
586
669
|
const fileInputRef = useRef(null);
|
|
587
670
|
const modalRef = useRef(null);
|
|
671
|
+
const textareaRef = useRef(null);
|
|
672
|
+
const recognitionRef = useRef(null);
|
|
673
|
+
const voiceBaseRef = useRef("");
|
|
674
|
+
const usingWebSpeechRef = useRef(false);
|
|
675
|
+
const textBeforeVoiceRef = useRef("");
|
|
676
|
+
const mediaRecorderRef = useRef(null);
|
|
677
|
+
const streamRef = useRef(null);
|
|
678
|
+
const sarvamChunksRef = useRef([]);
|
|
679
|
+
const spaceTimerRef = useRef(null);
|
|
680
|
+
const isPushToTalkRef = useRef(false);
|
|
588
681
|
useEffect(() => {
|
|
589
682
|
if (!isOpen) return;
|
|
590
683
|
const dialogs = Array.from(
|
|
591
|
-
document.querySelectorAll(
|
|
684
|
+
document.querySelectorAll(
|
|
685
|
+
'[role="dialog"][data-state="open"]'
|
|
686
|
+
)
|
|
592
687
|
);
|
|
593
688
|
dialogs.forEach((d) => d.setAttribute("inert", ""));
|
|
594
689
|
return () => dialogs.forEach((d) => d.removeAttribute("inert"));
|
|
@@ -597,7 +692,13 @@ function ReportDialog({
|
|
|
597
692
|
const [reportType, setReportType] = useState("BUG");
|
|
598
693
|
const [severity, setSeverity] = useState("medium");
|
|
599
694
|
const [validationError, setValidationError] = useState(null);
|
|
600
|
-
const
|
|
695
|
+
const [placeholderIdx, setPlaceholderIdx] = useState(0);
|
|
696
|
+
const availableTypes = types != null ? types : [
|
|
697
|
+
"BUG",
|
|
698
|
+
"FEATURE_REQUEST",
|
|
699
|
+
"QUESTION",
|
|
700
|
+
"OTHER"
|
|
701
|
+
];
|
|
601
702
|
const isDark = useIsDark();
|
|
602
703
|
const t = getTheme(isDark);
|
|
603
704
|
const handleFileUpload = (e) => {
|
|
@@ -697,12 +798,187 @@ function ReportDialog({
|
|
|
697
798
|
window.addEventListener("paste", handlePaste);
|
|
698
799
|
return () => window.removeEventListener("paste", handlePaste);
|
|
699
800
|
}, [isOpen]);
|
|
801
|
+
useEffect(() => {
|
|
802
|
+
if (!isOpen || !transcribeAudio2) return;
|
|
803
|
+
const id = setInterval(() => {
|
|
804
|
+
setPlaceholderIdx((i) => (i + 1) % 2);
|
|
805
|
+
}, 3e3);
|
|
806
|
+
return () => clearInterval(id);
|
|
807
|
+
}, [isOpen, transcribeAudio2]);
|
|
808
|
+
const stopVoice = () => {
|
|
809
|
+
var _a, _b;
|
|
810
|
+
usingWebSpeechRef.current = false;
|
|
811
|
+
(_a = recognitionRef.current) == null ? void 0 : _a.stop();
|
|
812
|
+
recognitionRef.current = null;
|
|
813
|
+
sarvamChunksRef.current = [];
|
|
814
|
+
const stream = streamRef.current;
|
|
815
|
+
streamRef.current = null;
|
|
816
|
+
stream == null ? void 0 : stream.getTracks().forEach((t2) => t2.stop());
|
|
817
|
+
try {
|
|
818
|
+
(_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
|
|
819
|
+
} catch (e) {
|
|
820
|
+
}
|
|
821
|
+
mediaRecorderRef.current = null;
|
|
822
|
+
setIsListening(false);
|
|
823
|
+
setIsTranscribing(false);
|
|
824
|
+
};
|
|
825
|
+
const stopListeningAndTranscribe = () => {
|
|
826
|
+
var _a, _b;
|
|
827
|
+
usingWebSpeechRef.current = false;
|
|
828
|
+
(_a = recognitionRef.current) == null ? void 0 : _a.stop();
|
|
829
|
+
recognitionRef.current = null;
|
|
830
|
+
setIsListening(false);
|
|
831
|
+
try {
|
|
832
|
+
(_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
|
|
833
|
+
} catch (e) {
|
|
834
|
+
}
|
|
835
|
+
};
|
|
700
836
|
const handleClose = () => {
|
|
837
|
+
stopVoice();
|
|
701
838
|
setIsOpen(false);
|
|
702
839
|
setStep(1);
|
|
703
840
|
setReportType("BUG");
|
|
704
841
|
setSeverity("medium");
|
|
705
842
|
setValidationError(null);
|
|
843
|
+
setVoiceError(null);
|
|
844
|
+
setIsEnhanced(false);
|
|
845
|
+
setOriginalDescription(null);
|
|
846
|
+
};
|
|
847
|
+
const toggleVoice = async () => {
|
|
848
|
+
if (isListening) {
|
|
849
|
+
stopListeningAndTranscribe();
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
const SpeechRec = typeof window !== "undefined" ? window.SpeechRecognition || window.webkitSpeechRecognition : void 0;
|
|
853
|
+
let stream = null;
|
|
854
|
+
try {
|
|
855
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
856
|
+
} catch (err) {
|
|
857
|
+
const isDenied = err instanceof DOMException && (err.name === "NotAllowedError" || err.name === "PermissionDeniedError");
|
|
858
|
+
if (!SpeechRec || isDenied) {
|
|
859
|
+
setVoiceError("Microphone access denied");
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
if (stream && transcribeAudio2) {
|
|
864
|
+
streamRef.current = stream;
|
|
865
|
+
sarvamChunksRef.current = [];
|
|
866
|
+
textBeforeVoiceRef.current = description;
|
|
867
|
+
const rec = new MediaRecorder(stream);
|
|
868
|
+
mediaRecorderRef.current = rec;
|
|
869
|
+
rec.ondataavailable = (e) => {
|
|
870
|
+
if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
|
|
871
|
+
};
|
|
872
|
+
rec.onstop = async () => {
|
|
873
|
+
stream.getTracks().forEach((t2) => t2.stop());
|
|
874
|
+
if (streamRef.current === stream) streamRef.current = null;
|
|
875
|
+
mediaRecorderRef.current = null;
|
|
876
|
+
const chunks = sarvamChunksRef.current;
|
|
877
|
+
sarvamChunksRef.current = [];
|
|
878
|
+
if (!chunks.length || !transcribeAudio2) return;
|
|
879
|
+
setIsTranscribing(true);
|
|
880
|
+
try {
|
|
881
|
+
const blob = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
|
|
882
|
+
const text = await transcribeAudio2(blob);
|
|
883
|
+
if (text.trim()) {
|
|
884
|
+
const sep = textBeforeVoiceRef.current.trim() ? " " : "";
|
|
885
|
+
setDescription(textBeforeVoiceRef.current + sep + text.trim());
|
|
886
|
+
setValidationError(null);
|
|
887
|
+
setIsEnhanced(false);
|
|
888
|
+
setOriginalDescription(null);
|
|
889
|
+
}
|
|
890
|
+
} catch (e) {
|
|
891
|
+
}
|
|
892
|
+
setIsTranscribing(false);
|
|
893
|
+
};
|
|
894
|
+
rec.start();
|
|
895
|
+
}
|
|
896
|
+
if (SpeechRec) {
|
|
897
|
+
setVoiceError(null);
|
|
898
|
+
usingWebSpeechRef.current = true;
|
|
899
|
+
voiceBaseRef.current = description;
|
|
900
|
+
textBeforeVoiceRef.current = description;
|
|
901
|
+
const recognition = new SpeechRec();
|
|
902
|
+
recognition.lang = "en-IN";
|
|
903
|
+
recognition.interimResults = true;
|
|
904
|
+
recognition.continuous = true;
|
|
905
|
+
recognitionRef.current = recognition;
|
|
906
|
+
recognition.onstart = () => setIsListening(true);
|
|
907
|
+
recognition.onresult = (event) => {
|
|
908
|
+
let finalText = "";
|
|
909
|
+
let interimText = "";
|
|
910
|
+
for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
911
|
+
const text = event.results[i][0].transcript;
|
|
912
|
+
if (event.results[i].isFinal) finalText += text;
|
|
913
|
+
else interimText += text;
|
|
914
|
+
}
|
|
915
|
+
if (finalText) {
|
|
916
|
+
const sep = voiceBaseRef.current.trim() ? " " : "";
|
|
917
|
+
voiceBaseRef.current += sep + finalText.trim();
|
|
918
|
+
}
|
|
919
|
+
const liveText = interimText ? voiceBaseRef.current + (voiceBaseRef.current.trim() ? " " : "") + interimText : voiceBaseRef.current;
|
|
920
|
+
setDescription(liveText);
|
|
921
|
+
setValidationError(null);
|
|
922
|
+
};
|
|
923
|
+
recognition.onend = () => {
|
|
924
|
+
if (usingWebSpeechRef.current && recognitionRef.current === recognition) {
|
|
925
|
+
try {
|
|
926
|
+
recognition.start();
|
|
927
|
+
} catch (e) {
|
|
928
|
+
}
|
|
929
|
+
} else {
|
|
930
|
+
setIsListening(false);
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
recognition.onerror = (event) => {
|
|
934
|
+
if (event.error === "aborted" || event.error === "no-speech") return;
|
|
935
|
+
const isDenied = event.error === "not-allowed" || event.error === "audio-capture";
|
|
936
|
+
setVoiceError(isDenied ? "Microphone access denied" : "Speech recognition not available \u2014 try Chrome");
|
|
937
|
+
usingWebSpeechRef.current = false;
|
|
938
|
+
recognitionRef.current = null;
|
|
939
|
+
setIsListening(false);
|
|
940
|
+
};
|
|
941
|
+
recognition.start();
|
|
942
|
+
} else if (stream) {
|
|
943
|
+
setVoiceError(null);
|
|
944
|
+
setIsListening(true);
|
|
945
|
+
}
|
|
946
|
+
};
|
|
947
|
+
const handleSpaceDown = (e) => {
|
|
948
|
+
if (e.code !== "Space") return;
|
|
949
|
+
if (spaceTimerRef.current || isListening || isPushToTalkRef.current) {
|
|
950
|
+
e.preventDefault();
|
|
951
|
+
return;
|
|
952
|
+
}
|
|
953
|
+
if (e.repeat || !transcribeAudio2 || isTranscribing) return;
|
|
954
|
+
e.preventDefault();
|
|
955
|
+
spaceTimerRef.current = setTimeout(() => {
|
|
956
|
+
isPushToTalkRef.current = true;
|
|
957
|
+
void toggleVoice();
|
|
958
|
+
}, 400);
|
|
959
|
+
};
|
|
960
|
+
const handleSpaceUp = (e) => {
|
|
961
|
+
var _a;
|
|
962
|
+
if (e.code !== "Space") return;
|
|
963
|
+
if (spaceTimerRef.current) {
|
|
964
|
+
clearTimeout(spaceTimerRef.current);
|
|
965
|
+
spaceTimerRef.current = null;
|
|
966
|
+
if (!isPushToTalkRef.current) {
|
|
967
|
+
const ta = textareaRef.current;
|
|
968
|
+
const pos = ta ? (_a = ta.selectionStart) != null ? _a : description.length : description.length;
|
|
969
|
+
setDescription((prev) => prev.slice(0, pos) + " " + prev.slice(pos));
|
|
970
|
+
requestAnimationFrame(() => {
|
|
971
|
+
if (textareaRef.current) {
|
|
972
|
+
textareaRef.current.selectionStart = pos + 1;
|
|
973
|
+
textareaRef.current.selectionEnd = pos + 1;
|
|
974
|
+
}
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
if (isPushToTalkRef.current) {
|
|
979
|
+
isPushToTalkRef.current = false;
|
|
980
|
+
stopListeningAndTranscribe();
|
|
981
|
+
}
|
|
706
982
|
};
|
|
707
983
|
const handleSubmit = async () => {
|
|
708
984
|
try {
|
|
@@ -719,7 +995,11 @@ function ReportDialog({
|
|
|
719
995
|
if (showSeverity && reportType === "BUG") {
|
|
720
996
|
metadata.severity = severity;
|
|
721
997
|
}
|
|
722
|
-
const result = await report(
|
|
998
|
+
const result = await report(
|
|
999
|
+
reportType,
|
|
1000
|
+
description.trim(),
|
|
1001
|
+
Object.keys(metadata).length > 0 ? metadata : void 0
|
|
1002
|
+
);
|
|
723
1003
|
if (result) {
|
|
724
1004
|
setSubmitted(true);
|
|
725
1005
|
setDescription("");
|
|
@@ -736,6 +1016,16 @@ function ReportDialog({
|
|
|
736
1016
|
};
|
|
737
1017
|
if (!mounted) return null;
|
|
738
1018
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1019
|
+
isOpen && createPortal(
|
|
1020
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
1021
|
+
@keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
|
|
1022
|
+
@keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
|
|
1023
|
+
@keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
|
|
1024
|
+
@keyframes gg-b3{0%,100%{height:4px}30%{height:14px}70%{height:5px}}
|
|
1025
|
+
@keyframes gg-b4{0%,100%{height:6px}60%{height:13px}}
|
|
1026
|
+
` }),
|
|
1027
|
+
document.body
|
|
1028
|
+
),
|
|
739
1029
|
isOpen && createPortal(
|
|
740
1030
|
/* @__PURE__ */ jsx(
|
|
741
1031
|
"div",
|
|
@@ -792,36 +1082,64 @@ function ReportDialog({
|
|
|
792
1082
|
alignItems: "center"
|
|
793
1083
|
},
|
|
794
1084
|
children: [
|
|
795
|
-
/* @__PURE__ */ jsxs(
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
{
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1085
|
+
/* @__PURE__ */ jsxs(
|
|
1086
|
+
"div",
|
|
1087
|
+
{
|
|
1088
|
+
style: {
|
|
1089
|
+
display: "flex",
|
|
1090
|
+
alignItems: "center",
|
|
1091
|
+
gap: "8px"
|
|
1092
|
+
},
|
|
1093
|
+
children: [
|
|
1094
|
+
step > 1 && /* @__PURE__ */ jsx(
|
|
1095
|
+
"button",
|
|
1096
|
+
{
|
|
1097
|
+
type: "button",
|
|
1098
|
+
onClick: () => setStep((s) => s - 1),
|
|
1099
|
+
style: {
|
|
1100
|
+
background: "none",
|
|
1101
|
+
border: "none",
|
|
1102
|
+
cursor: "pointer",
|
|
1103
|
+
padding: "2px",
|
|
1104
|
+
display: "flex",
|
|
1105
|
+
alignItems: "center"
|
|
1106
|
+
},
|
|
1107
|
+
"aria-label": "Back",
|
|
1108
|
+
children: /* @__PURE__ */ jsx(
|
|
1109
|
+
"svg",
|
|
1110
|
+
{
|
|
1111
|
+
width: "16",
|
|
1112
|
+
height: "16",
|
|
1113
|
+
viewBox: "0 0 16 16",
|
|
1114
|
+
fill: "none",
|
|
1115
|
+
children: /* @__PURE__ */ jsx(
|
|
1116
|
+
"path",
|
|
1117
|
+
{
|
|
1118
|
+
d: "M10 3L5 8L10 13",
|
|
1119
|
+
stroke: t.textMuted,
|
|
1120
|
+
strokeWidth: "2",
|
|
1121
|
+
strokeLinecap: "round",
|
|
1122
|
+
strokeLinejoin: "round"
|
|
1123
|
+
}
|
|
1124
|
+
)
|
|
1125
|
+
}
|
|
1126
|
+
)
|
|
1127
|
+
}
|
|
1128
|
+
),
|
|
1129
|
+
/* @__PURE__ */ jsx(
|
|
1130
|
+
"span",
|
|
1131
|
+
{
|
|
1132
|
+
style: {
|
|
1133
|
+
fontSize: "15px",
|
|
1134
|
+
fontWeight: 600,
|
|
1135
|
+
color: t.text
|
|
1136
|
+
},
|
|
1137
|
+
children: step === 1 ? "What's on your mind?" : "Tell us more"
|
|
1138
|
+
}
|
|
1139
|
+
)
|
|
1140
|
+
]
|
|
1141
|
+
}
|
|
1142
|
+
),
|
|
825
1143
|
/* @__PURE__ */ jsx(
|
|
826
1144
|
"button",
|
|
827
1145
|
{
|
|
@@ -837,27 +1155,74 @@ function ReportDialog({
|
|
|
837
1155
|
justifyContent: "center"
|
|
838
1156
|
},
|
|
839
1157
|
"aria-label": "Close",
|
|
840
|
-
children: /* @__PURE__ */ jsx(
|
|
1158
|
+
children: /* @__PURE__ */ jsx(
|
|
1159
|
+
"svg",
|
|
1160
|
+
{
|
|
1161
|
+
width: "16",
|
|
1162
|
+
height: "16",
|
|
1163
|
+
viewBox: "0 0 16 16",
|
|
1164
|
+
fill: "none",
|
|
1165
|
+
style: { display: "block" },
|
|
1166
|
+
children: /* @__PURE__ */ jsx(
|
|
1167
|
+
"path",
|
|
1168
|
+
{
|
|
1169
|
+
d: "M4 4L12 12M12 4L4 12",
|
|
1170
|
+
stroke: t.textMuted,
|
|
1171
|
+
strokeWidth: "2",
|
|
1172
|
+
strokeLinecap: "round"
|
|
1173
|
+
}
|
|
1174
|
+
)
|
|
1175
|
+
}
|
|
1176
|
+
)
|
|
841
1177
|
}
|
|
842
1178
|
)
|
|
843
1179
|
]
|
|
844
1180
|
}
|
|
845
1181
|
),
|
|
846
|
-
/* @__PURE__ */ jsx(
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1182
|
+
/* @__PURE__ */ jsx(
|
|
1183
|
+
"div",
|
|
1184
|
+
{
|
|
1185
|
+
style: {
|
|
1186
|
+
display: "flex",
|
|
1187
|
+
alignItems: "center",
|
|
1188
|
+
justifyContent: "center",
|
|
1189
|
+
gap: "0",
|
|
1190
|
+
marginTop: "12px"
|
|
1191
|
+
},
|
|
1192
|
+
children: [1, 2].map((s, i) => /* @__PURE__ */ jsxs(
|
|
1193
|
+
"div",
|
|
1194
|
+
{
|
|
1195
|
+
style: { display: "flex", alignItems: "center" },
|
|
1196
|
+
children: [
|
|
1197
|
+
/* @__PURE__ */ jsx(
|
|
1198
|
+
"div",
|
|
1199
|
+
{
|
|
1200
|
+
style: {
|
|
1201
|
+
width: "8px",
|
|
1202
|
+
height: "8px",
|
|
1203
|
+
borderRadius: "50%",
|
|
1204
|
+
backgroundColor: s <= step ? t.accent : t.inputBorder,
|
|
1205
|
+
transition: "background-color 0.2s ease"
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
),
|
|
1209
|
+
i < 1 && /* @__PURE__ */ jsx(
|
|
1210
|
+
"div",
|
|
1211
|
+
{
|
|
1212
|
+
style: {
|
|
1213
|
+
width: "40px",
|
|
1214
|
+
height: "2px",
|
|
1215
|
+
backgroundColor: s < step ? t.accent : t.inputBorder,
|
|
1216
|
+
transition: "background-color 0.2s ease"
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
)
|
|
1220
|
+
]
|
|
1221
|
+
},
|
|
1222
|
+
s
|
|
1223
|
+
))
|
|
1224
|
+
}
|
|
1225
|
+
)
|
|
861
1226
|
]
|
|
862
1227
|
}
|
|
863
1228
|
),
|
|
@@ -877,76 +1242,185 @@ function ReportDialog({
|
|
|
877
1242
|
]
|
|
878
1243
|
}
|
|
879
1244
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
880
|
-
step === 1 && /* @__PURE__ */ jsx(
|
|
881
|
-
"
|
|
1245
|
+
step === 1 && /* @__PURE__ */ jsx(
|
|
1246
|
+
"div",
|
|
882
1247
|
{
|
|
883
|
-
type: "button",
|
|
884
|
-
onClick: () => {
|
|
885
|
-
setReportType(type);
|
|
886
|
-
setStep(2);
|
|
887
|
-
},
|
|
888
1248
|
style: {
|
|
889
|
-
display: "
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
gap: "8px",
|
|
893
|
-
padding: "16px 8px",
|
|
894
|
-
borderRadius: "8px",
|
|
895
|
-
border: `1px solid ${t.inputBorder}`,
|
|
896
|
-
background: t.inputBg,
|
|
897
|
-
cursor: "pointer",
|
|
898
|
-
color: t.text,
|
|
899
|
-
fontFamily: "inherit",
|
|
900
|
-
transition: "border-color 0.15s ease"
|
|
901
|
-
},
|
|
902
|
-
onMouseEnter: (e) => {
|
|
903
|
-
e.currentTarget.style.borderColor = t.accent;
|
|
1249
|
+
display: "grid",
|
|
1250
|
+
gridTemplateColumns: "1fr 1fr",
|
|
1251
|
+
gap: "8px"
|
|
904
1252
|
},
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1253
|
+
children: availableTypes.map((type) => /* @__PURE__ */ jsxs(
|
|
1254
|
+
"button",
|
|
1255
|
+
{
|
|
1256
|
+
type: "button",
|
|
1257
|
+
onClick: () => {
|
|
1258
|
+
setReportType(type);
|
|
1259
|
+
setStep(2);
|
|
1260
|
+
},
|
|
1261
|
+
style: {
|
|
1262
|
+
display: "flex",
|
|
1263
|
+
flexDirection: "column",
|
|
1264
|
+
alignItems: "center",
|
|
1265
|
+
gap: "8px",
|
|
1266
|
+
padding: "16px 8px",
|
|
1267
|
+
borderRadius: "8px",
|
|
1268
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1269
|
+
background: t.inputBg,
|
|
1270
|
+
cursor: "pointer",
|
|
1271
|
+
color: t.text,
|
|
1272
|
+
fontFamily: "inherit",
|
|
1273
|
+
transition: "border-color 0.15s ease"
|
|
1274
|
+
},
|
|
1275
|
+
onMouseEnter: (e) => {
|
|
1276
|
+
e.currentTarget.style.borderColor = t.accent;
|
|
1277
|
+
},
|
|
1278
|
+
onMouseLeave: (e) => {
|
|
1279
|
+
e.currentTarget.style.borderColor = t.inputBorder;
|
|
1280
|
+
},
|
|
1281
|
+
children: [
|
|
1282
|
+
getTypeIcon(type, t.accent),
|
|
1283
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
|
|
1284
|
+
/* @__PURE__ */ jsx(
|
|
1285
|
+
"span",
|
|
1286
|
+
{
|
|
1287
|
+
style: {
|
|
1288
|
+
fontSize: "11px",
|
|
1289
|
+
color: t.textMuted,
|
|
1290
|
+
lineHeight: "1.3"
|
|
1291
|
+
},
|
|
1292
|
+
children: getTypeSubtitle(type)
|
|
1293
|
+
}
|
|
1294
|
+
)
|
|
1295
|
+
]
|
|
1296
|
+
},
|
|
1297
|
+
type
|
|
1298
|
+
))
|
|
1299
|
+
}
|
|
1300
|
+
),
|
|
916
1301
|
step === 2 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
917
1302
|
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
918
1303
|
/* @__PURE__ */ jsx(
|
|
919
1304
|
"textarea",
|
|
920
1305
|
{
|
|
1306
|
+
ref: textareaRef,
|
|
921
1307
|
value: description,
|
|
922
1308
|
onChange: (e) => {
|
|
923
1309
|
setDescription(e.target.value);
|
|
924
1310
|
if (validationError) setValidationError(null);
|
|
1311
|
+
if (isEnhanced) {
|
|
1312
|
+
setIsEnhanced(false);
|
|
1313
|
+
setOriginalDescription(null);
|
|
1314
|
+
}
|
|
925
1315
|
},
|
|
926
|
-
placeholder: getPlaceholder(reportType),
|
|
1316
|
+
placeholder: isTranscribing ? "Transcribing your speech\u2026" : isListening ? "Listening\u2026 speak now" : getPlaceholder(reportType, placeholderIdx, !!transcribeAudio2),
|
|
927
1317
|
style: {
|
|
928
1318
|
width: "100%",
|
|
929
1319
|
minHeight: "100px",
|
|
930
|
-
padding: enhanceText2 ? "28px 12px 10px" : "10px 12px",
|
|
1320
|
+
padding: enhanceText2 ? "28px 12px 36px" : transcribeAudio2 ? "10px 12px 36px" : "10px 12px",
|
|
931
1321
|
borderRadius: "8px",
|
|
932
|
-
border: `1px solid ${t.inputBorder}`,
|
|
1322
|
+
border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t.accent : t.inputBorder}`,
|
|
933
1323
|
fontSize: "14px",
|
|
934
1324
|
fontFamily: "inherit",
|
|
935
|
-
resize: "
|
|
1325
|
+
resize: "none",
|
|
936
1326
|
outline: "none",
|
|
937
1327
|
boxSizing: "border-box",
|
|
938
1328
|
color: t.text,
|
|
939
|
-
backgroundColor: t.inputBg
|
|
1329
|
+
backgroundColor: t.inputBg,
|
|
1330
|
+
transition: "border-color 0.2s ease"
|
|
940
1331
|
},
|
|
1332
|
+
onKeyDown: handleSpaceDown,
|
|
1333
|
+
onKeyUp: handleSpaceUp,
|
|
941
1334
|
onFocus: (e) => {
|
|
942
1335
|
e.target.style.borderColor = t.accent;
|
|
943
1336
|
},
|
|
944
1337
|
onBlur: (e) => {
|
|
945
|
-
|
|
1338
|
+
if (!isListening && !isTranscribing)
|
|
1339
|
+
e.target.style.borderColor = t.inputBorder;
|
|
946
1340
|
},
|
|
947
1341
|
autoFocus: true
|
|
948
1342
|
}
|
|
949
1343
|
),
|
|
1344
|
+
(isListening || isTranscribing) && /* @__PURE__ */ jsxs(
|
|
1345
|
+
"span",
|
|
1346
|
+
{
|
|
1347
|
+
style: {
|
|
1348
|
+
position: "absolute",
|
|
1349
|
+
bottom: "10px",
|
|
1350
|
+
left: "10px",
|
|
1351
|
+
display: "inline-flex",
|
|
1352
|
+
alignItems: "center",
|
|
1353
|
+
gap: "4px",
|
|
1354
|
+
fontSize: "10px",
|
|
1355
|
+
fontWeight: 700,
|
|
1356
|
+
letterSpacing: "0.04em",
|
|
1357
|
+
color: isTranscribing ? "#f59e0b" : "#ef4444",
|
|
1358
|
+
pointerEvents: "none",
|
|
1359
|
+
zIndex: 1
|
|
1360
|
+
},
|
|
1361
|
+
children: [
|
|
1362
|
+
/* @__PURE__ */ jsx(
|
|
1363
|
+
"span",
|
|
1364
|
+
{
|
|
1365
|
+
style: {
|
|
1366
|
+
width: "6px",
|
|
1367
|
+
height: "6px",
|
|
1368
|
+
borderRadius: "50%",
|
|
1369
|
+
backgroundColor: "currentColor",
|
|
1370
|
+
animation: "gg-pulse 1.2s ease-in-out infinite",
|
|
1371
|
+
display: "inline-block",
|
|
1372
|
+
flexShrink: 0
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
),
|
|
1376
|
+
isTranscribing ? "Transcribing\u2026" : "REC",
|
|
1377
|
+
isListening && !isTranscribing && /* @__PURE__ */ jsx(
|
|
1378
|
+
"span",
|
|
1379
|
+
{
|
|
1380
|
+
style: {
|
|
1381
|
+
display: "inline-flex",
|
|
1382
|
+
alignItems: "flex-end",
|
|
1383
|
+
gap: "2px",
|
|
1384
|
+
height: "14px",
|
|
1385
|
+
marginLeft: "3px"
|
|
1386
|
+
},
|
|
1387
|
+
children: [
|
|
1388
|
+
{ anim: "gg-b1", dur: "0.6s", delay: "0s" },
|
|
1389
|
+
{
|
|
1390
|
+
anim: "gg-b2",
|
|
1391
|
+
dur: "0.5s",
|
|
1392
|
+
delay: "0.1s"
|
|
1393
|
+
},
|
|
1394
|
+
{
|
|
1395
|
+
anim: "gg-b3",
|
|
1396
|
+
dur: "0.7s",
|
|
1397
|
+
delay: "0.05s"
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
anim: "gg-b4",
|
|
1401
|
+
dur: "0.55s",
|
|
1402
|
+
delay: "0.15s"
|
|
1403
|
+
}
|
|
1404
|
+
].map((b, i) => /* @__PURE__ */ jsx(
|
|
1405
|
+
"span",
|
|
1406
|
+
{
|
|
1407
|
+
style: {
|
|
1408
|
+
width: "2.5px",
|
|
1409
|
+
height: "4px",
|
|
1410
|
+
borderRadius: "1px",
|
|
1411
|
+
backgroundColor: "#ef4444",
|
|
1412
|
+
animation: `${b.anim} ${b.dur} ease-in-out ${b.delay} infinite`,
|
|
1413
|
+
display: "inline-block",
|
|
1414
|
+
alignSelf: "center"
|
|
1415
|
+
}
|
|
1416
|
+
},
|
|
1417
|
+
i
|
|
1418
|
+
))
|
|
1419
|
+
}
|
|
1420
|
+
)
|
|
1421
|
+
]
|
|
1422
|
+
}
|
|
1423
|
+
),
|
|
950
1424
|
enhanceText2 && /* @__PURE__ */ jsxs(
|
|
951
1425
|
"button",
|
|
952
1426
|
{
|
|
@@ -955,16 +1429,22 @@ function ReportDialog({
|
|
|
955
1429
|
if (!description.trim() || isEnhancing) return;
|
|
956
1430
|
setIsEnhancing(true);
|
|
957
1431
|
try {
|
|
958
|
-
const polished = await enhanceText2(
|
|
1432
|
+
const polished = await enhanceText2(
|
|
1433
|
+
description,
|
|
1434
|
+
screenshot
|
|
1435
|
+
);
|
|
959
1436
|
if (polished && polished !== description) {
|
|
1437
|
+
setOriginalDescription(description);
|
|
960
1438
|
setDescription(polished);
|
|
961
|
-
|
|
1439
|
+
setIsEnhanced(true);
|
|
1440
|
+
if (validationError)
|
|
1441
|
+
setValidationError(null);
|
|
962
1442
|
}
|
|
963
1443
|
} finally {
|
|
964
1444
|
setIsEnhancing(false);
|
|
965
1445
|
}
|
|
966
1446
|
},
|
|
967
|
-
disabled: !description.trim() || isEnhancing,
|
|
1447
|
+
disabled: !description.trim() || isEnhancing || isEnhanced,
|
|
968
1448
|
style: {
|
|
969
1449
|
position: "absolute",
|
|
970
1450
|
top: "6px",
|
|
@@ -985,105 +1465,393 @@ function ReportDialog({
|
|
|
985
1465
|
},
|
|
986
1466
|
title: "Polish grammar \u2014 preserves your meaning",
|
|
987
1467
|
children: [
|
|
988
|
-
/* @__PURE__ */ jsx(
|
|
1468
|
+
/* @__PURE__ */ jsx(
|
|
1469
|
+
"svg",
|
|
1470
|
+
{
|
|
1471
|
+
width: "11",
|
|
1472
|
+
height: "11",
|
|
1473
|
+
viewBox: "0 0 24 24",
|
|
1474
|
+
fill: "none",
|
|
1475
|
+
"aria-hidden": "true",
|
|
1476
|
+
children: /* @__PURE__ */ jsx(
|
|
1477
|
+
"path",
|
|
1478
|
+
{
|
|
1479
|
+
d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 15l.75 2.25L22 18l-2.25.75L19 21l-.75-2.25L16 18l2.25-.75L19 15z",
|
|
1480
|
+
stroke: t.textMuted,
|
|
1481
|
+
strokeWidth: "1.5",
|
|
1482
|
+
strokeLinejoin: "round"
|
|
1483
|
+
}
|
|
1484
|
+
)
|
|
1485
|
+
}
|
|
1486
|
+
),
|
|
989
1487
|
isEnhancing ? "Enhancing..." : "AI enhance"
|
|
990
1488
|
]
|
|
991
1489
|
}
|
|
1490
|
+
),
|
|
1491
|
+
transcribeAudio2 && /* @__PURE__ */ jsx(
|
|
1492
|
+
"button",
|
|
1493
|
+
{
|
|
1494
|
+
type: "button",
|
|
1495
|
+
onClick: () => {
|
|
1496
|
+
void toggleVoice();
|
|
1497
|
+
},
|
|
1498
|
+
title: isListening ? "Stop recording" : "Speak your report",
|
|
1499
|
+
style: {
|
|
1500
|
+
position: "absolute",
|
|
1501
|
+
bottom: "14px",
|
|
1502
|
+
right: "7px",
|
|
1503
|
+
width: "26px",
|
|
1504
|
+
height: "26px",
|
|
1505
|
+
display: "flex",
|
|
1506
|
+
alignItems: "center",
|
|
1507
|
+
justifyContent: "center",
|
|
1508
|
+
background: "transparent",
|
|
1509
|
+
border: `1.5px solid ${isListening ? "#ef4444" : t.inputBorder}`,
|
|
1510
|
+
borderRadius: "6px",
|
|
1511
|
+
color: isListening ? "#ef4444" : t.textMuted,
|
|
1512
|
+
cursor: "pointer",
|
|
1513
|
+
zIndex: 1,
|
|
1514
|
+
padding: 0,
|
|
1515
|
+
transition: "border-color 0.2s ease, color 0.2s ease"
|
|
1516
|
+
},
|
|
1517
|
+
children: isListening ? /* @__PURE__ */ jsx(
|
|
1518
|
+
"svg",
|
|
1519
|
+
{
|
|
1520
|
+
width: "12",
|
|
1521
|
+
height: "12",
|
|
1522
|
+
viewBox: "0 0 24 24",
|
|
1523
|
+
fill: "currentColor",
|
|
1524
|
+
"aria-hidden": "true",
|
|
1525
|
+
children: /* @__PURE__ */ jsx(
|
|
1526
|
+
"rect",
|
|
1527
|
+
{
|
|
1528
|
+
x: "6",
|
|
1529
|
+
y: "6",
|
|
1530
|
+
width: "12",
|
|
1531
|
+
height: "12",
|
|
1532
|
+
rx: "2"
|
|
1533
|
+
}
|
|
1534
|
+
)
|
|
1535
|
+
}
|
|
1536
|
+
) : /* @__PURE__ */ jsxs(
|
|
1537
|
+
"svg",
|
|
1538
|
+
{
|
|
1539
|
+
width: "13",
|
|
1540
|
+
height: "13",
|
|
1541
|
+
viewBox: "0 0 24 24",
|
|
1542
|
+
fill: "none",
|
|
1543
|
+
"aria-hidden": "true",
|
|
1544
|
+
children: [
|
|
1545
|
+
/* @__PURE__ */ jsx(
|
|
1546
|
+
"rect",
|
|
1547
|
+
{
|
|
1548
|
+
x: "9",
|
|
1549
|
+
y: "2",
|
|
1550
|
+
width: "6",
|
|
1551
|
+
height: "12",
|
|
1552
|
+
rx: "3",
|
|
1553
|
+
stroke: "currentColor",
|
|
1554
|
+
strokeWidth: "1.8"
|
|
1555
|
+
}
|
|
1556
|
+
),
|
|
1557
|
+
/* @__PURE__ */ jsx(
|
|
1558
|
+
"path",
|
|
1559
|
+
{
|
|
1560
|
+
d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
|
|
1561
|
+
stroke: "currentColor",
|
|
1562
|
+
strokeWidth: "1.8",
|
|
1563
|
+
strokeLinecap: "round"
|
|
1564
|
+
}
|
|
1565
|
+
)
|
|
1566
|
+
]
|
|
1567
|
+
}
|
|
1568
|
+
)
|
|
1569
|
+
}
|
|
992
1570
|
)
|
|
993
1571
|
] }),
|
|
994
|
-
/* @__PURE__ */ jsxs(
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1572
|
+
transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ jsxs(
|
|
1573
|
+
"div",
|
|
1574
|
+
{
|
|
1575
|
+
style: {
|
|
1576
|
+
display: "flex",
|
|
1577
|
+
alignItems: "center",
|
|
1578
|
+
gap: "5px",
|
|
1579
|
+
marginTop: "5px",
|
|
1580
|
+
fontSize: "11px",
|
|
1581
|
+
color: t.text,
|
|
1582
|
+
opacity: 0.55,
|
|
1583
|
+
userSelect: "none"
|
|
1584
|
+
},
|
|
1585
|
+
children: [
|
|
1586
|
+
/* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1587
|
+
/* @__PURE__ */ jsx("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
|
|
1588
|
+
/* @__PURE__ */ jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1589
|
+
/* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
|
|
1590
|
+
] }),
|
|
1591
|
+
"Hold Space to speak \u2014 we'll transcribe it"
|
|
1592
|
+
]
|
|
1593
|
+
}
|
|
1594
|
+
),
|
|
1595
|
+
isEnhanced && originalDescription !== null && /* @__PURE__ */ jsxs(
|
|
1596
|
+
"div",
|
|
1597
|
+
{
|
|
1598
|
+
style: {
|
|
1599
|
+
display: "flex",
|
|
1600
|
+
alignItems: "center",
|
|
1601
|
+
gap: "6px",
|
|
1602
|
+
marginTop: "6px",
|
|
1603
|
+
padding: "6px 8px",
|
|
1604
|
+
borderRadius: "6px",
|
|
1605
|
+
background: isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.05)",
|
|
1606
|
+
border: `1px solid ${t.accent}40`
|
|
1607
|
+
},
|
|
1608
|
+
children: [
|
|
998
1609
|
/* @__PURE__ */ jsx(
|
|
999
|
-
"
|
|
1610
|
+
"svg",
|
|
1611
|
+
{
|
|
1612
|
+
width: "12",
|
|
1613
|
+
height: "12",
|
|
1614
|
+
viewBox: "0 0 24 24",
|
|
1615
|
+
fill: "none",
|
|
1616
|
+
style: { flexShrink: 0 },
|
|
1617
|
+
children: /* @__PURE__ */ jsx(
|
|
1618
|
+
"path",
|
|
1619
|
+
{
|
|
1620
|
+
d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
|
|
1621
|
+
stroke: t.accent,
|
|
1622
|
+
strokeWidth: "1.5",
|
|
1623
|
+
strokeLinejoin: "round"
|
|
1624
|
+
}
|
|
1625
|
+
)
|
|
1626
|
+
}
|
|
1627
|
+
),
|
|
1628
|
+
/* @__PURE__ */ jsx(
|
|
1629
|
+
"span",
|
|
1000
1630
|
{
|
|
1001
|
-
src: screenshot,
|
|
1002
|
-
alt: "Page screenshot",
|
|
1003
|
-
onClick: () => setPreviewOpen(true),
|
|
1004
1631
|
style: {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
objectPosition: "top",
|
|
1011
|
-
cursor: "zoom-in",
|
|
1012
|
-
display: "block"
|
|
1013
|
-
}
|
|
1632
|
+
fontSize: "11px",
|
|
1633
|
+
color: t.textMuted,
|
|
1634
|
+
flex: 1
|
|
1635
|
+
},
|
|
1636
|
+
children: "AI enhanced"
|
|
1014
1637
|
}
|
|
1015
1638
|
),
|
|
1016
|
-
/* @__PURE__ */ jsx(
|
|
1017
|
-
position: "absolute",
|
|
1018
|
-
bottom: "5px",
|
|
1019
|
-
left: "6px",
|
|
1020
|
-
background: "rgba(0,0,0,0.55)",
|
|
1021
|
-
color: "#fff",
|
|
1022
|
-
fontSize: "10px",
|
|
1023
|
-
padding: "1px 5px",
|
|
1024
|
-
borderRadius: "3px",
|
|
1025
|
-
pointerEvents: "none"
|
|
1026
|
-
}, children: "click to preview" })
|
|
1027
|
-
] }),
|
|
1028
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px", marginTop: "6px" }, children: [
|
|
1029
|
-
/* @__PURE__ */ jsxs(
|
|
1639
|
+
/* @__PURE__ */ jsx(
|
|
1030
1640
|
"button",
|
|
1031
1641
|
{
|
|
1032
1642
|
type: "button",
|
|
1033
|
-
onClick: () =>
|
|
1643
|
+
onClick: () => {
|
|
1644
|
+
setIsEnhanced(false);
|
|
1645
|
+
setOriginalDescription(null);
|
|
1646
|
+
},
|
|
1034
1647
|
style: {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
fontWeight: 500,
|
|
1648
|
+
padding: "2px 8px",
|
|
1649
|
+
borderRadius: "4px",
|
|
1650
|
+
border: `1px solid ${t.accent}`,
|
|
1651
|
+
background: t.accent,
|
|
1652
|
+
color: t.accentText,
|
|
1653
|
+
fontSize: "11px",
|
|
1654
|
+
fontWeight: 600,
|
|
1043
1655
|
cursor: "pointer",
|
|
1044
|
-
fontFamily: "inherit"
|
|
1045
|
-
display: "flex",
|
|
1046
|
-
alignItems: "center",
|
|
1047
|
-
justifyContent: "center",
|
|
1048
|
-
gap: "4px"
|
|
1656
|
+
fontFamily: "inherit"
|
|
1049
1657
|
},
|
|
1050
|
-
children:
|
|
1051
|
-
/* @__PURE__ */ jsx("svg", { width: "11", height: "11", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M1 1L9 9M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }),
|
|
1052
|
-
"Remove"
|
|
1053
|
-
]
|
|
1658
|
+
children: "Keep"
|
|
1054
1659
|
}
|
|
1055
1660
|
),
|
|
1056
|
-
/* @__PURE__ */
|
|
1661
|
+
/* @__PURE__ */ jsx(
|
|
1057
1662
|
"button",
|
|
1058
1663
|
{
|
|
1059
1664
|
type: "button",
|
|
1060
1665
|
onClick: () => {
|
|
1061
|
-
|
|
1062
|
-
|
|
1666
|
+
setDescription(originalDescription);
|
|
1667
|
+
setIsEnhanced(false);
|
|
1668
|
+
setOriginalDescription(null);
|
|
1063
1669
|
},
|
|
1064
1670
|
style: {
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
borderRadius: "6px",
|
|
1671
|
+
padding: "2px 8px",
|
|
1672
|
+
borderRadius: "4px",
|
|
1068
1673
|
border: `1px solid ${t.inputBorder}`,
|
|
1069
1674
|
background: "transparent",
|
|
1070
1675
|
color: t.textMuted,
|
|
1071
|
-
fontSize: "
|
|
1072
|
-
fontWeight:
|
|
1676
|
+
fontSize: "11px",
|
|
1677
|
+
fontWeight: 600,
|
|
1073
1678
|
cursor: "pointer",
|
|
1074
|
-
fontFamily: "inherit"
|
|
1075
|
-
display: "flex",
|
|
1076
|
-
alignItems: "center",
|
|
1077
|
-
justifyContent: "center",
|
|
1078
|
-
gap: "4px"
|
|
1679
|
+
fontFamily: "inherit"
|
|
1079
1680
|
},
|
|
1080
|
-
children:
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1681
|
+
children: "Restore"
|
|
1682
|
+
}
|
|
1683
|
+
)
|
|
1684
|
+
]
|
|
1685
|
+
}
|
|
1686
|
+
),
|
|
1687
|
+
voiceError && /* @__PURE__ */ jsx(
|
|
1688
|
+
"p",
|
|
1689
|
+
{
|
|
1690
|
+
style: {
|
|
1691
|
+
color: "#ef4444",
|
|
1692
|
+
fontSize: "11px",
|
|
1693
|
+
marginTop: "4px",
|
|
1694
|
+
marginBottom: 0
|
|
1695
|
+
},
|
|
1696
|
+
children: voiceError
|
|
1697
|
+
}
|
|
1698
|
+
),
|
|
1699
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: "10px" }, children: [
|
|
1700
|
+
/* @__PURE__ */ jsx(
|
|
1701
|
+
"span",
|
|
1702
|
+
{
|
|
1703
|
+
style: {
|
|
1704
|
+
fontSize: "12px",
|
|
1705
|
+
color: t.textMuted,
|
|
1706
|
+
marginBottom: "6px",
|
|
1707
|
+
display: "block",
|
|
1708
|
+
fontWeight: 500
|
|
1709
|
+
},
|
|
1710
|
+
children: "Screenshot"
|
|
1711
|
+
}
|
|
1712
|
+
),
|
|
1713
|
+
screenshot ? /* @__PURE__ */ jsxs("div", { children: [
|
|
1714
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
1715
|
+
/* @__PURE__ */ jsx(
|
|
1716
|
+
"img",
|
|
1717
|
+
{
|
|
1718
|
+
src: screenshot,
|
|
1719
|
+
alt: "Page screenshot",
|
|
1720
|
+
onClick: () => setPreviewOpen(true),
|
|
1721
|
+
style: {
|
|
1722
|
+
width: "100%",
|
|
1723
|
+
borderRadius: "6px",
|
|
1724
|
+
border: `1px solid ${t.border}`,
|
|
1725
|
+
maxHeight: "64px",
|
|
1726
|
+
objectFit: "cover",
|
|
1727
|
+
objectPosition: "top",
|
|
1728
|
+
cursor: "zoom-in",
|
|
1729
|
+
display: "block"
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
),
|
|
1733
|
+
/* @__PURE__ */ jsx(
|
|
1734
|
+
"span",
|
|
1735
|
+
{
|
|
1736
|
+
style: {
|
|
1737
|
+
position: "absolute",
|
|
1738
|
+
bottom: "5px",
|
|
1739
|
+
left: "6px",
|
|
1740
|
+
background: "rgba(0,0,0,0.55)",
|
|
1741
|
+
color: "#fff",
|
|
1742
|
+
fontSize: "10px",
|
|
1743
|
+
padding: "1px 5px",
|
|
1744
|
+
borderRadius: "3px",
|
|
1745
|
+
pointerEvents: "none"
|
|
1746
|
+
},
|
|
1747
|
+
children: "click to preview"
|
|
1084
1748
|
}
|
|
1085
1749
|
)
|
|
1086
|
-
] })
|
|
1750
|
+
] }),
|
|
1751
|
+
/* @__PURE__ */ jsxs(
|
|
1752
|
+
"div",
|
|
1753
|
+
{
|
|
1754
|
+
style: {
|
|
1755
|
+
display: "flex",
|
|
1756
|
+
gap: "6px",
|
|
1757
|
+
marginTop: "6px"
|
|
1758
|
+
},
|
|
1759
|
+
children: [
|
|
1760
|
+
/* @__PURE__ */ jsxs(
|
|
1761
|
+
"button",
|
|
1762
|
+
{
|
|
1763
|
+
type: "button",
|
|
1764
|
+
onClick: () => setScreenshot(null),
|
|
1765
|
+
style: {
|
|
1766
|
+
flex: 1,
|
|
1767
|
+
padding: "6px 0",
|
|
1768
|
+
borderRadius: "6px",
|
|
1769
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1770
|
+
background: "transparent",
|
|
1771
|
+
color: "#ef4444",
|
|
1772
|
+
fontSize: "12px",
|
|
1773
|
+
fontWeight: 500,
|
|
1774
|
+
cursor: "pointer",
|
|
1775
|
+
fontFamily: "inherit",
|
|
1776
|
+
display: "flex",
|
|
1777
|
+
alignItems: "center",
|
|
1778
|
+
justifyContent: "center",
|
|
1779
|
+
gap: "4px"
|
|
1780
|
+
},
|
|
1781
|
+
children: [
|
|
1782
|
+
/* @__PURE__ */ jsx(
|
|
1783
|
+
"svg",
|
|
1784
|
+
{
|
|
1785
|
+
width: "11",
|
|
1786
|
+
height: "11",
|
|
1787
|
+
viewBox: "0 0 10 10",
|
|
1788
|
+
fill: "none",
|
|
1789
|
+
children: /* @__PURE__ */ jsx(
|
|
1790
|
+
"path",
|
|
1791
|
+
{
|
|
1792
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
1793
|
+
stroke: "currentColor",
|
|
1794
|
+
strokeWidth: "1.5",
|
|
1795
|
+
strokeLinecap: "round"
|
|
1796
|
+
}
|
|
1797
|
+
)
|
|
1798
|
+
}
|
|
1799
|
+
),
|
|
1800
|
+
"Remove"
|
|
1801
|
+
]
|
|
1802
|
+
}
|
|
1803
|
+
),
|
|
1804
|
+
/* @__PURE__ */ jsxs(
|
|
1805
|
+
"button",
|
|
1806
|
+
{
|
|
1807
|
+
type: "button",
|
|
1808
|
+
onClick: () => {
|
|
1809
|
+
var _a;
|
|
1810
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
1811
|
+
},
|
|
1812
|
+
style: {
|
|
1813
|
+
flex: 1,
|
|
1814
|
+
padding: "6px 0",
|
|
1815
|
+
borderRadius: "6px",
|
|
1816
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1817
|
+
background: "transparent",
|
|
1818
|
+
color: t.textMuted,
|
|
1819
|
+
fontSize: "12px",
|
|
1820
|
+
fontWeight: 500,
|
|
1821
|
+
cursor: "pointer",
|
|
1822
|
+
fontFamily: "inherit",
|
|
1823
|
+
display: "flex",
|
|
1824
|
+
alignItems: "center",
|
|
1825
|
+
justifyContent: "center",
|
|
1826
|
+
gap: "4px"
|
|
1827
|
+
},
|
|
1828
|
+
children: [
|
|
1829
|
+
/* @__PURE__ */ jsx(
|
|
1830
|
+
"svg",
|
|
1831
|
+
{
|
|
1832
|
+
width: "11",
|
|
1833
|
+
height: "11",
|
|
1834
|
+
viewBox: "0 0 24 24",
|
|
1835
|
+
fill: "none",
|
|
1836
|
+
children: /* @__PURE__ */ jsx(
|
|
1837
|
+
"path",
|
|
1838
|
+
{
|
|
1839
|
+
d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12",
|
|
1840
|
+
stroke: "currentColor",
|
|
1841
|
+
strokeWidth: "2",
|
|
1842
|
+
strokeLinecap: "round",
|
|
1843
|
+
strokeLinejoin: "round"
|
|
1844
|
+
}
|
|
1845
|
+
)
|
|
1846
|
+
}
|
|
1847
|
+
),
|
|
1848
|
+
"Replace"
|
|
1849
|
+
]
|
|
1850
|
+
}
|
|
1851
|
+
)
|
|
1852
|
+
]
|
|
1853
|
+
}
|
|
1854
|
+
)
|
|
1087
1855
|
] }) : (
|
|
1088
1856
|
/* Drop zone */
|
|
1089
1857
|
/* @__PURE__ */ jsxs(
|
|
@@ -1096,7 +1864,9 @@ function ReportDialog({
|
|
|
1096
1864
|
onDrop: (e) => {
|
|
1097
1865
|
e.preventDefault();
|
|
1098
1866
|
setScreenshotDragOver(false);
|
|
1099
|
-
const file = Array.from(
|
|
1867
|
+
const file = Array.from(
|
|
1868
|
+
e.dataTransfer.files
|
|
1869
|
+
).find((f) => f.type.startsWith("image/"));
|
|
1100
1870
|
if (!file) return;
|
|
1101
1871
|
const reader = new FileReader();
|
|
1102
1872
|
reader.onload = () => setScreenshot(reader.result);
|
|
@@ -1117,20 +1887,95 @@ function ReportDialog({
|
|
|
1117
1887
|
transition: "border-color 0.15s ease, background 0.15s ease"
|
|
1118
1888
|
},
|
|
1119
1889
|
children: [
|
|
1120
|
-
/* @__PURE__ */ jsxs(
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1890
|
+
/* @__PURE__ */ jsxs(
|
|
1891
|
+
"svg",
|
|
1892
|
+
{
|
|
1893
|
+
width: "22",
|
|
1894
|
+
height: "22",
|
|
1895
|
+
viewBox: "0 0 24 24",
|
|
1896
|
+
fill: "none",
|
|
1897
|
+
style: {
|
|
1898
|
+
margin: "0 auto 6px",
|
|
1899
|
+
display: "block",
|
|
1900
|
+
opacity: 0.45
|
|
1901
|
+
},
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ jsx(
|
|
1904
|
+
"rect",
|
|
1905
|
+
{
|
|
1906
|
+
x: "3",
|
|
1907
|
+
y: "3",
|
|
1908
|
+
width: "18",
|
|
1909
|
+
height: "18",
|
|
1910
|
+
rx: "2",
|
|
1911
|
+
stroke: t.textMuted,
|
|
1912
|
+
strokeWidth: "1.5"
|
|
1913
|
+
}
|
|
1914
|
+
),
|
|
1915
|
+
/* @__PURE__ */ jsx(
|
|
1916
|
+
"circle",
|
|
1917
|
+
{
|
|
1918
|
+
cx: "8.5",
|
|
1919
|
+
cy: "8.5",
|
|
1920
|
+
r: "1.5",
|
|
1921
|
+
stroke: t.textMuted,
|
|
1922
|
+
strokeWidth: "1.5"
|
|
1923
|
+
}
|
|
1924
|
+
),
|
|
1925
|
+
/* @__PURE__ */ jsx(
|
|
1926
|
+
"path",
|
|
1927
|
+
{
|
|
1928
|
+
d: "M21 15l-5-5L5 21",
|
|
1929
|
+
stroke: t.textMuted,
|
|
1930
|
+
strokeWidth: "1.5",
|
|
1931
|
+
strokeLinecap: "round",
|
|
1932
|
+
strokeLinejoin: "round"
|
|
1933
|
+
}
|
|
1934
|
+
)
|
|
1935
|
+
]
|
|
1936
|
+
}
|
|
1937
|
+
),
|
|
1938
|
+
/* @__PURE__ */ jsx(
|
|
1939
|
+
"p",
|
|
1940
|
+
{
|
|
1941
|
+
style: {
|
|
1942
|
+
margin: 0,
|
|
1943
|
+
fontSize: "12px",
|
|
1944
|
+
fontWeight: 600,
|
|
1945
|
+
color: t.text
|
|
1946
|
+
},
|
|
1947
|
+
children: screenshotDragOver ? "Drop to attach" : "Add a screenshot"
|
|
1948
|
+
}
|
|
1949
|
+
),
|
|
1950
|
+
/* @__PURE__ */ jsx(
|
|
1951
|
+
"p",
|
|
1952
|
+
{
|
|
1953
|
+
style: {
|
|
1954
|
+
margin: "3px 0 0",
|
|
1955
|
+
fontSize: "11px",
|
|
1956
|
+
color: t.textMuted
|
|
1957
|
+
},
|
|
1958
|
+
children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
|
|
1959
|
+
}
|
|
1960
|
+
)
|
|
1127
1961
|
]
|
|
1128
1962
|
}
|
|
1129
1963
|
)
|
|
1130
1964
|
)
|
|
1131
1965
|
] }),
|
|
1132
1966
|
showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs("div", { style: { marginTop: "10px" }, children: [
|
|
1133
|
-
/* @__PURE__ */ jsx(
|
|
1967
|
+
/* @__PURE__ */ jsx(
|
|
1968
|
+
"span",
|
|
1969
|
+
{
|
|
1970
|
+
style: {
|
|
1971
|
+
fontSize: "12px",
|
|
1972
|
+
color: t.textMuted,
|
|
1973
|
+
marginBottom: "6px",
|
|
1974
|
+
display: "block"
|
|
1975
|
+
},
|
|
1976
|
+
children: "Severity"
|
|
1977
|
+
}
|
|
1978
|
+
),
|
|
1134
1979
|
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ jsx(
|
|
1135
1980
|
"button",
|
|
1136
1981
|
{
|
|
@@ -1155,114 +2000,34 @@ function ReportDialog({
|
|
|
1155
2000
|
s
|
|
1156
2001
|
)) })
|
|
1157
2002
|
] }),
|
|
1158
|
-
validationError && /* @__PURE__ */ jsx(
|
|
1159
|
-
|
|
1160
|
-
"button",
|
|
2003
|
+
validationError && /* @__PURE__ */ jsx(
|
|
2004
|
+
"p",
|
|
1161
2005
|
{
|
|
1162
|
-
type: "button",
|
|
1163
|
-
onClick: () => {
|
|
1164
|
-
const err = isLowQualityText(description);
|
|
1165
|
-
if (err) {
|
|
1166
|
-
setValidationError(err);
|
|
1167
|
-
return;
|
|
1168
|
-
}
|
|
1169
|
-
setValidationError(null);
|
|
1170
|
-
setStep(3);
|
|
1171
|
-
},
|
|
1172
|
-
disabled: !description.trim(),
|
|
1173
2006
|
style: {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
borderRadius: "8px",
|
|
1178
|
-
border: "none",
|
|
1179
|
-
backgroundColor: !description.trim() ? t.bgSecondary : t.accent,
|
|
1180
|
-
color: !description.trim() ? t.textMuted : t.accentText,
|
|
1181
|
-
fontSize: "14px",
|
|
1182
|
-
fontWeight: 600,
|
|
1183
|
-
cursor: !description.trim() ? "not-allowed" : "pointer",
|
|
1184
|
-
fontFamily: "inherit",
|
|
1185
|
-
transition: "background-color 0.15s ease"
|
|
2007
|
+
color: "#ef4444",
|
|
2008
|
+
fontSize: "12px",
|
|
2009
|
+
marginTop: "6px"
|
|
1186
2010
|
},
|
|
1187
|
-
children:
|
|
1188
|
-
}
|
|
1189
|
-
)
|
|
1190
|
-
] }),
|
|
1191
|
-
step === 3 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1192
|
-
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", marginBottom: "12px" }, children: [
|
|
1193
|
-
/* @__PURE__ */ jsxs("span", { style: {
|
|
1194
|
-
display: "inline-flex",
|
|
1195
|
-
alignItems: "center",
|
|
1196
|
-
gap: "4px",
|
|
1197
|
-
padding: "4px 10px",
|
|
1198
|
-
borderRadius: "12px",
|
|
1199
|
-
fontSize: "12px",
|
|
1200
|
-
fontWeight: 600,
|
|
1201
|
-
backgroundColor: t.bgSecondary,
|
|
1202
|
-
color: t.text,
|
|
1203
|
-
border: `1px solid ${t.border}`
|
|
1204
|
-
}, children: [
|
|
1205
|
-
getTypeIcon(reportType, t.accent, 12),
|
|
1206
|
-
getTypeLabel(reportType)
|
|
1207
|
-
] }),
|
|
1208
|
-
showSeverity && reportType === "BUG" && /* @__PURE__ */ jsx("span", { style: {
|
|
1209
|
-
display: "inline-flex",
|
|
1210
|
-
alignItems: "center",
|
|
1211
|
-
padding: "4px 10px",
|
|
1212
|
-
borderRadius: "12px",
|
|
1213
|
-
fontSize: "12px",
|
|
1214
|
-
fontWeight: 600,
|
|
1215
|
-
backgroundColor: severity === "high" ? "#fef2f2" : severity === "medium" ? "#fffbeb" : "#f0fdf4",
|
|
1216
|
-
color: severity === "high" ? "#dc2626" : severity === "medium" ? "#d97706" : "#16a34a",
|
|
1217
|
-
border: `1px solid ${severity === "high" ? "#fecaca" : severity === "medium" ? "#fde68a" : "#bbf7d0"}`,
|
|
1218
|
-
textTransform: "capitalize"
|
|
1219
|
-
}, children: severity })
|
|
1220
|
-
] }),
|
|
1221
|
-
/* @__PURE__ */ jsx("div", { style: {
|
|
1222
|
-
padding: "10px 12px",
|
|
1223
|
-
borderRadius: "8px",
|
|
1224
|
-
border: `1px solid ${t.inputBorder}`,
|
|
1225
|
-
backgroundColor: t.inputBg,
|
|
1226
|
-
fontSize: "13px",
|
|
1227
|
-
color: t.text,
|
|
1228
|
-
marginBottom: "10px",
|
|
1229
|
-
maxHeight: "80px",
|
|
1230
|
-
overflow: "hidden",
|
|
1231
|
-
lineHeight: "1.4"
|
|
1232
|
-
}, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
|
|
1233
|
-
screenshot && /* @__PURE__ */ jsx("div", { style: { marginBottom: "10px", position: "relative" }, children: /* @__PURE__ */ jsx(
|
|
1234
|
-
"img",
|
|
1235
|
-
{
|
|
1236
|
-
src: screenshot,
|
|
1237
|
-
alt: "Page screenshot",
|
|
1238
|
-
onClick: () => setPreviewOpen(true),
|
|
1239
|
-
style: {
|
|
1240
|
-
width: "100%",
|
|
1241
|
-
borderRadius: "6px",
|
|
1242
|
-
border: `1px solid ${t.border}`,
|
|
1243
|
-
maxHeight: "80px",
|
|
1244
|
-
objectFit: "cover",
|
|
1245
|
-
objectPosition: "top",
|
|
1246
|
-
cursor: "pointer"
|
|
1247
|
-
}
|
|
2011
|
+
children: validationError
|
|
1248
2012
|
}
|
|
1249
|
-
)
|
|
2013
|
+
),
|
|
1250
2014
|
/* @__PURE__ */ jsx(
|
|
1251
2015
|
"button",
|
|
1252
2016
|
{
|
|
1253
2017
|
type: "button",
|
|
1254
2018
|
onClick: handleSubmit,
|
|
1255
|
-
disabled: isSubmitting,
|
|
2019
|
+
disabled: !description.trim() || isSubmitting,
|
|
1256
2020
|
style: {
|
|
2021
|
+
marginTop: "12px",
|
|
1257
2022
|
width: "100%",
|
|
1258
2023
|
padding: "10px",
|
|
1259
2024
|
borderRadius: "8px",
|
|
1260
2025
|
border: "none",
|
|
1261
|
-
backgroundColor: isSubmitting ? t.bgSecondary : t.accent,
|
|
1262
|
-
color: isSubmitting ? t.textMuted : t.accentText,
|
|
2026
|
+
backgroundColor: !description.trim() || isSubmitting ? t.bgSecondary : t.accent,
|
|
2027
|
+
color: !description.trim() || isSubmitting ? t.textMuted : t.accentText,
|
|
1263
2028
|
fontSize: "14px",
|
|
1264
2029
|
fontWeight: 600,
|
|
1265
|
-
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
2030
|
+
cursor: !description.trim() || isSubmitting ? "not-allowed" : "pointer",
|
|
1266
2031
|
fontFamily: "inherit",
|
|
1267
2032
|
transition: "background-color 0.15s ease"
|
|
1268
2033
|
},
|
|
@@ -1378,10 +2143,11 @@ function getTypeSubtitle(type) {
|
|
|
1378
2143
|
return "General feedback";
|
|
1379
2144
|
}
|
|
1380
2145
|
}
|
|
1381
|
-
function getPlaceholder(type) {
|
|
2146
|
+
function getPlaceholder(type, idx = 0, hasVoice = false) {
|
|
2147
|
+
if (hasVoice && idx === 1) return "Hold Space to speak \u2014 we'll transcribe it";
|
|
1382
2148
|
switch (type) {
|
|
1383
2149
|
case "BUG":
|
|
1384
|
-
return "What went wrong?";
|
|
2150
|
+
return "What went wrong? Describe it or paste an error...";
|
|
1385
2151
|
case "FEATURE_REQUEST":
|
|
1386
2152
|
return "Describe the feature you'd like...";
|
|
1387
2153
|
case "QUESTION":
|
|
@@ -1391,19 +2157,58 @@ function getPlaceholder(type) {
|
|
|
1391
2157
|
}
|
|
1392
2158
|
}
|
|
1393
2159
|
function getTypeIcon(type, color, size = 24) {
|
|
1394
|
-
const props = {
|
|
2160
|
+
const props = {
|
|
2161
|
+
width: size,
|
|
2162
|
+
height: size,
|
|
2163
|
+
viewBox: "0 0 24 24",
|
|
2164
|
+
fill: "none",
|
|
2165
|
+
style: { flexShrink: 0 }
|
|
2166
|
+
};
|
|
1395
2167
|
switch (type) {
|
|
1396
2168
|
case "BUG":
|
|
1397
|
-
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2169
|
+
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2170
|
+
"path",
|
|
2171
|
+
{
|
|
2172
|
+
d: "M8 2L6.5 3.5M16 2L17.5 3.5M3 9H7M17 9H21M12 2a5 5 0 015 5v4a5 5 0 01-10 0V7a5 5 0 015-5zM7 16l-2 3M17 16l2 3",
|
|
2173
|
+
stroke: color,
|
|
2174
|
+
strokeWidth: "1.5",
|
|
2175
|
+
strokeLinecap: "round"
|
|
2176
|
+
}
|
|
2177
|
+
) });
|
|
1398
2178
|
case "FEATURE_REQUEST":
|
|
1399
|
-
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2179
|
+
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2180
|
+
"path",
|
|
2181
|
+
{
|
|
2182
|
+
d: "M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2z",
|
|
2183
|
+
stroke: color,
|
|
2184
|
+
strokeWidth: "1.5",
|
|
2185
|
+
strokeLinejoin: "round"
|
|
2186
|
+
}
|
|
2187
|
+
) });
|
|
1400
2188
|
case "QUESTION":
|
|
1401
2189
|
return /* @__PURE__ */ jsxs("svg", { ...props, children: [
|
|
1402
2190
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
|
|
1403
|
-
/* @__PURE__ */ jsx(
|
|
2191
|
+
/* @__PURE__ */ jsx(
|
|
2192
|
+
"path",
|
|
2193
|
+
{
|
|
2194
|
+
d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
|
|
2195
|
+
stroke: color,
|
|
2196
|
+
strokeWidth: "1.5",
|
|
2197
|
+
strokeLinecap: "round",
|
|
2198
|
+
strokeLinejoin: "round"
|
|
2199
|
+
}
|
|
2200
|
+
)
|
|
1404
2201
|
] });
|
|
1405
2202
|
case "OTHER":
|
|
1406
|
-
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2203
|
+
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2204
|
+
"path",
|
|
2205
|
+
{
|
|
2206
|
+
d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
|
|
2207
|
+
stroke: color,
|
|
2208
|
+
strokeWidth: "1.5",
|
|
2209
|
+
strokeLinejoin: "round"
|
|
2210
|
+
}
|
|
2211
|
+
) });
|
|
1407
2212
|
}
|
|
1408
2213
|
}
|
|
1409
2214
|
|
|
@@ -1625,15 +2430,31 @@ function GlitchgrabProviderInner({
|
|
|
1625
2430
|
[]
|
|
1626
2431
|
);
|
|
1627
2432
|
const enhance = useCallback(
|
|
1628
|
-
async (text) => {
|
|
2433
|
+
async (text, screenshot) => {
|
|
1629
2434
|
try {
|
|
1630
|
-
|
|
2435
|
+
const ctx = captureContext(visitedPagesRef.current);
|
|
2436
|
+
const context = {
|
|
2437
|
+
url: ctx.url,
|
|
2438
|
+
visitedPages: ctx.visitedPages.slice(-5),
|
|
2439
|
+
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
2440
|
+
};
|
|
2441
|
+
return await enhanceText(text, token, baseUrl, screenshot, context);
|
|
1631
2442
|
} catch (e) {
|
|
1632
2443
|
return text;
|
|
1633
2444
|
}
|
|
1634
2445
|
},
|
|
1635
2446
|
[token, baseUrl]
|
|
1636
2447
|
);
|
|
2448
|
+
const transcribe = useCallback(
|
|
2449
|
+
async (blob) => {
|
|
2450
|
+
try {
|
|
2451
|
+
return await transcribeAudio(blob, token, baseUrl);
|
|
2452
|
+
} catch (e) {
|
|
2453
|
+
return "";
|
|
2454
|
+
}
|
|
2455
|
+
},
|
|
2456
|
+
[token, baseUrl]
|
|
2457
|
+
);
|
|
1637
2458
|
const openReportDialog = useCallback((options) => {
|
|
1638
2459
|
if (typeof window !== "undefined") {
|
|
1639
2460
|
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
@@ -1678,7 +2499,7 @@ function GlitchgrabProviderInner({
|
|
|
1678
2499
|
children
|
|
1679
2500
|
}
|
|
1680
2501
|
),
|
|
1681
|
-
/* @__PURE__ */ jsx2(ReportDialog, { report, enhanceText: enhance, types, showSeverity })
|
|
2502
|
+
/* @__PURE__ */ jsx2(ReportDialog, { report, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity })
|
|
1682
2503
|
]
|
|
1683
2504
|
}
|
|
1684
2505
|
);
|