glitchgrab 1.22.0 → 1.23.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.d.mts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +1097 -282
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1102 -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,185 @@ 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 (e) {
|
|
857
|
+
if (!SpeechRec) {
|
|
858
|
+
setVoiceError("Microphone access denied");
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
if (stream && transcribeAudio2) {
|
|
863
|
+
streamRef.current = stream;
|
|
864
|
+
sarvamChunksRef.current = [];
|
|
865
|
+
textBeforeVoiceRef.current = description;
|
|
866
|
+
const rec = new MediaRecorder(stream);
|
|
867
|
+
mediaRecorderRef.current = rec;
|
|
868
|
+
rec.ondataavailable = (e) => {
|
|
869
|
+
if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
|
|
870
|
+
};
|
|
871
|
+
rec.onstop = async () => {
|
|
872
|
+
stream.getTracks().forEach((t2) => t2.stop());
|
|
873
|
+
if (streamRef.current === stream) streamRef.current = null;
|
|
874
|
+
mediaRecorderRef.current = null;
|
|
875
|
+
const chunks = sarvamChunksRef.current;
|
|
876
|
+
sarvamChunksRef.current = [];
|
|
877
|
+
if (!chunks.length || !transcribeAudio2) return;
|
|
878
|
+
setIsTranscribing(true);
|
|
879
|
+
try {
|
|
880
|
+
const blob = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
|
|
881
|
+
const text = await transcribeAudio2(blob);
|
|
882
|
+
if (text.trim()) {
|
|
883
|
+
const sep = textBeforeVoiceRef.current.trim() ? " " : "";
|
|
884
|
+
setDescription(textBeforeVoiceRef.current + sep + text.trim());
|
|
885
|
+
setValidationError(null);
|
|
886
|
+
setIsEnhanced(false);
|
|
887
|
+
setOriginalDescription(null);
|
|
888
|
+
}
|
|
889
|
+
} catch (e) {
|
|
890
|
+
}
|
|
891
|
+
setIsTranscribing(false);
|
|
892
|
+
};
|
|
893
|
+
rec.start();
|
|
894
|
+
}
|
|
895
|
+
if (SpeechRec) {
|
|
896
|
+
setVoiceError(null);
|
|
897
|
+
usingWebSpeechRef.current = true;
|
|
898
|
+
voiceBaseRef.current = description;
|
|
899
|
+
textBeforeVoiceRef.current = description;
|
|
900
|
+
const recognition = new SpeechRec();
|
|
901
|
+
recognition.lang = "en-IN";
|
|
902
|
+
recognition.interimResults = true;
|
|
903
|
+
recognition.continuous = true;
|
|
904
|
+
recognitionRef.current = recognition;
|
|
905
|
+
recognition.onstart = () => setIsListening(true);
|
|
906
|
+
recognition.onresult = (event) => {
|
|
907
|
+
let finalText = "";
|
|
908
|
+
let interimText = "";
|
|
909
|
+
for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
910
|
+
const text = event.results[i][0].transcript;
|
|
911
|
+
if (event.results[i].isFinal) finalText += text;
|
|
912
|
+
else interimText += text;
|
|
913
|
+
}
|
|
914
|
+
if (finalText) {
|
|
915
|
+
const sep = voiceBaseRef.current.trim() ? " " : "";
|
|
916
|
+
voiceBaseRef.current += sep + finalText.trim();
|
|
917
|
+
}
|
|
918
|
+
const liveText = interimText ? voiceBaseRef.current + (voiceBaseRef.current.trim() ? " " : "") + interimText : voiceBaseRef.current;
|
|
919
|
+
setDescription(liveText);
|
|
920
|
+
setValidationError(null);
|
|
921
|
+
};
|
|
922
|
+
recognition.onend = () => {
|
|
923
|
+
if (usingWebSpeechRef.current && recognitionRef.current === recognition) {
|
|
924
|
+
try {
|
|
925
|
+
recognition.start();
|
|
926
|
+
} catch (e) {
|
|
927
|
+
}
|
|
928
|
+
} else {
|
|
929
|
+
setIsListening(false);
|
|
930
|
+
}
|
|
931
|
+
};
|
|
932
|
+
recognition.onerror = (event) => {
|
|
933
|
+
if (event.error === "aborted" || event.error === "no-speech") return;
|
|
934
|
+
setVoiceError("Speech recognition not available \u2014 try Chrome");
|
|
935
|
+
usingWebSpeechRef.current = false;
|
|
936
|
+
recognitionRef.current = null;
|
|
937
|
+
setIsListening(false);
|
|
938
|
+
};
|
|
939
|
+
recognition.start();
|
|
940
|
+
} else if (stream) {
|
|
941
|
+
setVoiceError(null);
|
|
942
|
+
setIsListening(true);
|
|
943
|
+
}
|
|
944
|
+
};
|
|
945
|
+
const handleSpaceDown = (e) => {
|
|
946
|
+
if (e.code !== "Space") return;
|
|
947
|
+
if (spaceTimerRef.current || isListening || isPushToTalkRef.current) {
|
|
948
|
+
e.preventDefault();
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
if (e.repeat || !transcribeAudio2 || isTranscribing) return;
|
|
952
|
+
e.preventDefault();
|
|
953
|
+
spaceTimerRef.current = setTimeout(() => {
|
|
954
|
+
isPushToTalkRef.current = true;
|
|
955
|
+
void toggleVoice();
|
|
956
|
+
}, 400);
|
|
957
|
+
};
|
|
958
|
+
const handleSpaceUp = (e) => {
|
|
959
|
+
var _a;
|
|
960
|
+
if (e.code !== "Space") return;
|
|
961
|
+
if (spaceTimerRef.current) {
|
|
962
|
+
clearTimeout(spaceTimerRef.current);
|
|
963
|
+
spaceTimerRef.current = null;
|
|
964
|
+
if (!isPushToTalkRef.current) {
|
|
965
|
+
const ta = textareaRef.current;
|
|
966
|
+
const pos = ta ? (_a = ta.selectionStart) != null ? _a : description.length : description.length;
|
|
967
|
+
setDescription((prev) => prev.slice(0, pos) + " " + prev.slice(pos));
|
|
968
|
+
requestAnimationFrame(() => {
|
|
969
|
+
if (textareaRef.current) {
|
|
970
|
+
textareaRef.current.selectionStart = pos + 1;
|
|
971
|
+
textareaRef.current.selectionEnd = pos + 1;
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
if (isPushToTalkRef.current) {
|
|
977
|
+
isPushToTalkRef.current = false;
|
|
978
|
+
stopListeningAndTranscribe();
|
|
979
|
+
}
|
|
706
980
|
};
|
|
707
981
|
const handleSubmit = async () => {
|
|
708
982
|
try {
|
|
@@ -719,7 +993,11 @@ function ReportDialog({
|
|
|
719
993
|
if (showSeverity && reportType === "BUG") {
|
|
720
994
|
metadata.severity = severity;
|
|
721
995
|
}
|
|
722
|
-
const result = await report(
|
|
996
|
+
const result = await report(
|
|
997
|
+
reportType,
|
|
998
|
+
description.trim(),
|
|
999
|
+
Object.keys(metadata).length > 0 ? metadata : void 0
|
|
1000
|
+
);
|
|
723
1001
|
if (result) {
|
|
724
1002
|
setSubmitted(true);
|
|
725
1003
|
setDescription("");
|
|
@@ -736,6 +1014,16 @@ function ReportDialog({
|
|
|
736
1014
|
};
|
|
737
1015
|
if (!mounted) return null;
|
|
738
1016
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1017
|
+
isOpen && createPortal(
|
|
1018
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
1019
|
+
@keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
|
|
1020
|
+
@keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
|
|
1021
|
+
@keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
|
|
1022
|
+
@keyframes gg-b3{0%,100%{height:4px}30%{height:14px}70%{height:5px}}
|
|
1023
|
+
@keyframes gg-b4{0%,100%{height:6px}60%{height:13px}}
|
|
1024
|
+
` }),
|
|
1025
|
+
document.body
|
|
1026
|
+
),
|
|
739
1027
|
isOpen && createPortal(
|
|
740
1028
|
/* @__PURE__ */ jsx(
|
|
741
1029
|
"div",
|
|
@@ -792,36 +1080,64 @@ function ReportDialog({
|
|
|
792
1080
|
alignItems: "center"
|
|
793
1081
|
},
|
|
794
1082
|
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
|
-
|
|
1083
|
+
/* @__PURE__ */ jsxs(
|
|
1084
|
+
"div",
|
|
1085
|
+
{
|
|
1086
|
+
style: {
|
|
1087
|
+
display: "flex",
|
|
1088
|
+
alignItems: "center",
|
|
1089
|
+
gap: "8px"
|
|
1090
|
+
},
|
|
1091
|
+
children: [
|
|
1092
|
+
step > 1 && /* @__PURE__ */ jsx(
|
|
1093
|
+
"button",
|
|
1094
|
+
{
|
|
1095
|
+
type: "button",
|
|
1096
|
+
onClick: () => setStep((s) => s - 1),
|
|
1097
|
+
style: {
|
|
1098
|
+
background: "none",
|
|
1099
|
+
border: "none",
|
|
1100
|
+
cursor: "pointer",
|
|
1101
|
+
padding: "2px",
|
|
1102
|
+
display: "flex",
|
|
1103
|
+
alignItems: "center"
|
|
1104
|
+
},
|
|
1105
|
+
"aria-label": "Back",
|
|
1106
|
+
children: /* @__PURE__ */ jsx(
|
|
1107
|
+
"svg",
|
|
1108
|
+
{
|
|
1109
|
+
width: "16",
|
|
1110
|
+
height: "16",
|
|
1111
|
+
viewBox: "0 0 16 16",
|
|
1112
|
+
fill: "none",
|
|
1113
|
+
children: /* @__PURE__ */ jsx(
|
|
1114
|
+
"path",
|
|
1115
|
+
{
|
|
1116
|
+
d: "M10 3L5 8L10 13",
|
|
1117
|
+
stroke: t.textMuted,
|
|
1118
|
+
strokeWidth: "2",
|
|
1119
|
+
strokeLinecap: "round",
|
|
1120
|
+
strokeLinejoin: "round"
|
|
1121
|
+
}
|
|
1122
|
+
)
|
|
1123
|
+
}
|
|
1124
|
+
)
|
|
1125
|
+
}
|
|
1126
|
+
),
|
|
1127
|
+
/* @__PURE__ */ jsx(
|
|
1128
|
+
"span",
|
|
1129
|
+
{
|
|
1130
|
+
style: {
|
|
1131
|
+
fontSize: "15px",
|
|
1132
|
+
fontWeight: 600,
|
|
1133
|
+
color: t.text
|
|
1134
|
+
},
|
|
1135
|
+
children: step === 1 ? "What's on your mind?" : "Tell us more"
|
|
1136
|
+
}
|
|
1137
|
+
)
|
|
1138
|
+
]
|
|
1139
|
+
}
|
|
1140
|
+
),
|
|
825
1141
|
/* @__PURE__ */ jsx(
|
|
826
1142
|
"button",
|
|
827
1143
|
{
|
|
@@ -837,27 +1153,74 @@ function ReportDialog({
|
|
|
837
1153
|
justifyContent: "center"
|
|
838
1154
|
},
|
|
839
1155
|
"aria-label": "Close",
|
|
840
|
-
children: /* @__PURE__ */ jsx(
|
|
1156
|
+
children: /* @__PURE__ */ jsx(
|
|
1157
|
+
"svg",
|
|
1158
|
+
{
|
|
1159
|
+
width: "16",
|
|
1160
|
+
height: "16",
|
|
1161
|
+
viewBox: "0 0 16 16",
|
|
1162
|
+
fill: "none",
|
|
1163
|
+
style: { display: "block" },
|
|
1164
|
+
children: /* @__PURE__ */ jsx(
|
|
1165
|
+
"path",
|
|
1166
|
+
{
|
|
1167
|
+
d: "M4 4L12 12M12 4L4 12",
|
|
1168
|
+
stroke: t.textMuted,
|
|
1169
|
+
strokeWidth: "2",
|
|
1170
|
+
strokeLinecap: "round"
|
|
1171
|
+
}
|
|
1172
|
+
)
|
|
1173
|
+
}
|
|
1174
|
+
)
|
|
841
1175
|
}
|
|
842
1176
|
)
|
|
843
1177
|
]
|
|
844
1178
|
}
|
|
845
1179
|
),
|
|
846
|
-
/* @__PURE__ */ jsx(
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1180
|
+
/* @__PURE__ */ jsx(
|
|
1181
|
+
"div",
|
|
1182
|
+
{
|
|
1183
|
+
style: {
|
|
1184
|
+
display: "flex",
|
|
1185
|
+
alignItems: "center",
|
|
1186
|
+
justifyContent: "center",
|
|
1187
|
+
gap: "0",
|
|
1188
|
+
marginTop: "12px"
|
|
1189
|
+
},
|
|
1190
|
+
children: [1, 2].map((s, i) => /* @__PURE__ */ jsxs(
|
|
1191
|
+
"div",
|
|
1192
|
+
{
|
|
1193
|
+
style: { display: "flex", alignItems: "center" },
|
|
1194
|
+
children: [
|
|
1195
|
+
/* @__PURE__ */ jsx(
|
|
1196
|
+
"div",
|
|
1197
|
+
{
|
|
1198
|
+
style: {
|
|
1199
|
+
width: "8px",
|
|
1200
|
+
height: "8px",
|
|
1201
|
+
borderRadius: "50%",
|
|
1202
|
+
backgroundColor: s <= step ? t.accent : t.inputBorder,
|
|
1203
|
+
transition: "background-color 0.2s ease"
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
),
|
|
1207
|
+
i < 1 && /* @__PURE__ */ jsx(
|
|
1208
|
+
"div",
|
|
1209
|
+
{
|
|
1210
|
+
style: {
|
|
1211
|
+
width: "40px",
|
|
1212
|
+
height: "2px",
|
|
1213
|
+
backgroundColor: s < step ? t.accent : t.inputBorder,
|
|
1214
|
+
transition: "background-color 0.2s ease"
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
)
|
|
1218
|
+
]
|
|
1219
|
+
},
|
|
1220
|
+
s
|
|
1221
|
+
))
|
|
1222
|
+
}
|
|
1223
|
+
)
|
|
861
1224
|
]
|
|
862
1225
|
}
|
|
863
1226
|
),
|
|
@@ -877,76 +1240,185 @@ function ReportDialog({
|
|
|
877
1240
|
]
|
|
878
1241
|
}
|
|
879
1242
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
880
|
-
step === 1 && /* @__PURE__ */ jsx(
|
|
881
|
-
"
|
|
1243
|
+
step === 1 && /* @__PURE__ */ jsx(
|
|
1244
|
+
"div",
|
|
882
1245
|
{
|
|
883
|
-
type: "button",
|
|
884
|
-
onClick: () => {
|
|
885
|
-
setReportType(type);
|
|
886
|
-
setStep(2);
|
|
887
|
-
},
|
|
888
1246
|
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;
|
|
1247
|
+
display: "grid",
|
|
1248
|
+
gridTemplateColumns: "1fr 1fr",
|
|
1249
|
+
gap: "8px"
|
|
904
1250
|
},
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
1251
|
+
children: availableTypes.map((type) => /* @__PURE__ */ jsxs(
|
|
1252
|
+
"button",
|
|
1253
|
+
{
|
|
1254
|
+
type: "button",
|
|
1255
|
+
onClick: () => {
|
|
1256
|
+
setReportType(type);
|
|
1257
|
+
setStep(2);
|
|
1258
|
+
},
|
|
1259
|
+
style: {
|
|
1260
|
+
display: "flex",
|
|
1261
|
+
flexDirection: "column",
|
|
1262
|
+
alignItems: "center",
|
|
1263
|
+
gap: "8px",
|
|
1264
|
+
padding: "16px 8px",
|
|
1265
|
+
borderRadius: "8px",
|
|
1266
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1267
|
+
background: t.inputBg,
|
|
1268
|
+
cursor: "pointer",
|
|
1269
|
+
color: t.text,
|
|
1270
|
+
fontFamily: "inherit",
|
|
1271
|
+
transition: "border-color 0.15s ease"
|
|
1272
|
+
},
|
|
1273
|
+
onMouseEnter: (e) => {
|
|
1274
|
+
e.currentTarget.style.borderColor = t.accent;
|
|
1275
|
+
},
|
|
1276
|
+
onMouseLeave: (e) => {
|
|
1277
|
+
e.currentTarget.style.borderColor = t.inputBorder;
|
|
1278
|
+
},
|
|
1279
|
+
children: [
|
|
1280
|
+
getTypeIcon(type, t.accent),
|
|
1281
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
|
|
1282
|
+
/* @__PURE__ */ jsx(
|
|
1283
|
+
"span",
|
|
1284
|
+
{
|
|
1285
|
+
style: {
|
|
1286
|
+
fontSize: "11px",
|
|
1287
|
+
color: t.textMuted,
|
|
1288
|
+
lineHeight: "1.3"
|
|
1289
|
+
},
|
|
1290
|
+
children: getTypeSubtitle(type)
|
|
1291
|
+
}
|
|
1292
|
+
)
|
|
1293
|
+
]
|
|
1294
|
+
},
|
|
1295
|
+
type
|
|
1296
|
+
))
|
|
1297
|
+
}
|
|
1298
|
+
),
|
|
916
1299
|
step === 2 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
917
1300
|
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
918
1301
|
/* @__PURE__ */ jsx(
|
|
919
1302
|
"textarea",
|
|
920
1303
|
{
|
|
1304
|
+
ref: textareaRef,
|
|
921
1305
|
value: description,
|
|
922
1306
|
onChange: (e) => {
|
|
923
1307
|
setDescription(e.target.value);
|
|
924
1308
|
if (validationError) setValidationError(null);
|
|
1309
|
+
if (isEnhanced) {
|
|
1310
|
+
setIsEnhanced(false);
|
|
1311
|
+
setOriginalDescription(null);
|
|
1312
|
+
}
|
|
925
1313
|
},
|
|
926
|
-
placeholder: getPlaceholder(reportType),
|
|
1314
|
+
placeholder: isTranscribing ? "Transcribing your speech\u2026" : isListening ? "Listening\u2026 speak now" : getPlaceholder(reportType, placeholderIdx, !!transcribeAudio2),
|
|
927
1315
|
style: {
|
|
928
1316
|
width: "100%",
|
|
929
1317
|
minHeight: "100px",
|
|
930
|
-
padding: enhanceText2 ? "28px 12px 10px" : "10px 12px",
|
|
1318
|
+
padding: enhanceText2 ? "28px 12px 36px" : transcribeAudio2 ? "10px 12px 36px" : "10px 12px",
|
|
931
1319
|
borderRadius: "8px",
|
|
932
|
-
border: `1px solid ${t.inputBorder}`,
|
|
1320
|
+
border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t.accent : t.inputBorder}`,
|
|
933
1321
|
fontSize: "14px",
|
|
934
1322
|
fontFamily: "inherit",
|
|
935
|
-
resize: "
|
|
1323
|
+
resize: "none",
|
|
936
1324
|
outline: "none",
|
|
937
1325
|
boxSizing: "border-box",
|
|
938
1326
|
color: t.text,
|
|
939
|
-
backgroundColor: t.inputBg
|
|
1327
|
+
backgroundColor: t.inputBg,
|
|
1328
|
+
transition: "border-color 0.2s ease"
|
|
940
1329
|
},
|
|
1330
|
+
onKeyDown: handleSpaceDown,
|
|
1331
|
+
onKeyUp: handleSpaceUp,
|
|
941
1332
|
onFocus: (e) => {
|
|
942
1333
|
e.target.style.borderColor = t.accent;
|
|
943
1334
|
},
|
|
944
1335
|
onBlur: (e) => {
|
|
945
|
-
|
|
1336
|
+
if (!isListening && !isTranscribing)
|
|
1337
|
+
e.target.style.borderColor = t.inputBorder;
|
|
946
1338
|
},
|
|
947
1339
|
autoFocus: true
|
|
948
1340
|
}
|
|
949
1341
|
),
|
|
1342
|
+
(isListening || isTranscribing) && /* @__PURE__ */ jsxs(
|
|
1343
|
+
"span",
|
|
1344
|
+
{
|
|
1345
|
+
style: {
|
|
1346
|
+
position: "absolute",
|
|
1347
|
+
bottom: "10px",
|
|
1348
|
+
left: "10px",
|
|
1349
|
+
display: "inline-flex",
|
|
1350
|
+
alignItems: "center",
|
|
1351
|
+
gap: "4px",
|
|
1352
|
+
fontSize: "10px",
|
|
1353
|
+
fontWeight: 700,
|
|
1354
|
+
letterSpacing: "0.04em",
|
|
1355
|
+
color: isTranscribing ? "#f59e0b" : "#ef4444",
|
|
1356
|
+
pointerEvents: "none",
|
|
1357
|
+
zIndex: 1
|
|
1358
|
+
},
|
|
1359
|
+
children: [
|
|
1360
|
+
/* @__PURE__ */ jsx(
|
|
1361
|
+
"span",
|
|
1362
|
+
{
|
|
1363
|
+
style: {
|
|
1364
|
+
width: "6px",
|
|
1365
|
+
height: "6px",
|
|
1366
|
+
borderRadius: "50%",
|
|
1367
|
+
backgroundColor: "currentColor",
|
|
1368
|
+
animation: "gg-pulse 1.2s ease-in-out infinite",
|
|
1369
|
+
display: "inline-block",
|
|
1370
|
+
flexShrink: 0
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
),
|
|
1374
|
+
isTranscribing ? "Transcribing\u2026" : "REC",
|
|
1375
|
+
isListening && !isTranscribing && /* @__PURE__ */ jsx(
|
|
1376
|
+
"span",
|
|
1377
|
+
{
|
|
1378
|
+
style: {
|
|
1379
|
+
display: "inline-flex",
|
|
1380
|
+
alignItems: "flex-end",
|
|
1381
|
+
gap: "2px",
|
|
1382
|
+
height: "14px",
|
|
1383
|
+
marginLeft: "3px"
|
|
1384
|
+
},
|
|
1385
|
+
children: [
|
|
1386
|
+
{ anim: "gg-b1", dur: "0.6s", delay: "0s" },
|
|
1387
|
+
{
|
|
1388
|
+
anim: "gg-b2",
|
|
1389
|
+
dur: "0.5s",
|
|
1390
|
+
delay: "0.1s"
|
|
1391
|
+
},
|
|
1392
|
+
{
|
|
1393
|
+
anim: "gg-b3",
|
|
1394
|
+
dur: "0.7s",
|
|
1395
|
+
delay: "0.05s"
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
anim: "gg-b4",
|
|
1399
|
+
dur: "0.55s",
|
|
1400
|
+
delay: "0.15s"
|
|
1401
|
+
}
|
|
1402
|
+
].map((b, i) => /* @__PURE__ */ jsx(
|
|
1403
|
+
"span",
|
|
1404
|
+
{
|
|
1405
|
+
style: {
|
|
1406
|
+
width: "2.5px",
|
|
1407
|
+
height: "4px",
|
|
1408
|
+
borderRadius: "1px",
|
|
1409
|
+
backgroundColor: "#ef4444",
|
|
1410
|
+
animation: `${b.anim} ${b.dur} ease-in-out ${b.delay} infinite`,
|
|
1411
|
+
display: "inline-block",
|
|
1412
|
+
alignSelf: "center"
|
|
1413
|
+
}
|
|
1414
|
+
},
|
|
1415
|
+
i
|
|
1416
|
+
))
|
|
1417
|
+
}
|
|
1418
|
+
)
|
|
1419
|
+
]
|
|
1420
|
+
}
|
|
1421
|
+
),
|
|
950
1422
|
enhanceText2 && /* @__PURE__ */ jsxs(
|
|
951
1423
|
"button",
|
|
952
1424
|
{
|
|
@@ -955,16 +1427,22 @@ function ReportDialog({
|
|
|
955
1427
|
if (!description.trim() || isEnhancing) return;
|
|
956
1428
|
setIsEnhancing(true);
|
|
957
1429
|
try {
|
|
958
|
-
const polished = await enhanceText2(
|
|
1430
|
+
const polished = await enhanceText2(
|
|
1431
|
+
description,
|
|
1432
|
+
screenshot
|
|
1433
|
+
);
|
|
959
1434
|
if (polished && polished !== description) {
|
|
1435
|
+
setOriginalDescription(description);
|
|
960
1436
|
setDescription(polished);
|
|
961
|
-
|
|
1437
|
+
setIsEnhanced(true);
|
|
1438
|
+
if (validationError)
|
|
1439
|
+
setValidationError(null);
|
|
962
1440
|
}
|
|
963
1441
|
} finally {
|
|
964
1442
|
setIsEnhancing(false);
|
|
965
1443
|
}
|
|
966
1444
|
},
|
|
967
|
-
disabled: !description.trim() || isEnhancing,
|
|
1445
|
+
disabled: !description.trim() || isEnhancing || isEnhanced,
|
|
968
1446
|
style: {
|
|
969
1447
|
position: "absolute",
|
|
970
1448
|
top: "6px",
|
|
@@ -985,105 +1463,393 @@ function ReportDialog({
|
|
|
985
1463
|
},
|
|
986
1464
|
title: "Polish grammar \u2014 preserves your meaning",
|
|
987
1465
|
children: [
|
|
988
|
-
/* @__PURE__ */ jsx(
|
|
1466
|
+
/* @__PURE__ */ jsx(
|
|
1467
|
+
"svg",
|
|
1468
|
+
{
|
|
1469
|
+
width: "11",
|
|
1470
|
+
height: "11",
|
|
1471
|
+
viewBox: "0 0 24 24",
|
|
1472
|
+
fill: "none",
|
|
1473
|
+
"aria-hidden": "true",
|
|
1474
|
+
children: /* @__PURE__ */ jsx(
|
|
1475
|
+
"path",
|
|
1476
|
+
{
|
|
1477
|
+
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",
|
|
1478
|
+
stroke: t.textMuted,
|
|
1479
|
+
strokeWidth: "1.5",
|
|
1480
|
+
strokeLinejoin: "round"
|
|
1481
|
+
}
|
|
1482
|
+
)
|
|
1483
|
+
}
|
|
1484
|
+
),
|
|
989
1485
|
isEnhancing ? "Enhancing..." : "AI enhance"
|
|
990
1486
|
]
|
|
991
1487
|
}
|
|
1488
|
+
),
|
|
1489
|
+
transcribeAudio2 && /* @__PURE__ */ jsx(
|
|
1490
|
+
"button",
|
|
1491
|
+
{
|
|
1492
|
+
type: "button",
|
|
1493
|
+
onClick: () => {
|
|
1494
|
+
void toggleVoice();
|
|
1495
|
+
},
|
|
1496
|
+
title: isListening ? "Stop recording" : "Speak your report",
|
|
1497
|
+
style: {
|
|
1498
|
+
position: "absolute",
|
|
1499
|
+
bottom: "14px",
|
|
1500
|
+
right: "7px",
|
|
1501
|
+
width: "26px",
|
|
1502
|
+
height: "26px",
|
|
1503
|
+
display: "flex",
|
|
1504
|
+
alignItems: "center",
|
|
1505
|
+
justifyContent: "center",
|
|
1506
|
+
background: "transparent",
|
|
1507
|
+
border: `1.5px solid ${isListening ? "#ef4444" : t.inputBorder}`,
|
|
1508
|
+
borderRadius: "6px",
|
|
1509
|
+
color: isListening ? "#ef4444" : t.textMuted,
|
|
1510
|
+
cursor: "pointer",
|
|
1511
|
+
zIndex: 1,
|
|
1512
|
+
padding: 0,
|
|
1513
|
+
transition: "border-color 0.2s ease, color 0.2s ease"
|
|
1514
|
+
},
|
|
1515
|
+
children: isListening ? /* @__PURE__ */ jsx(
|
|
1516
|
+
"svg",
|
|
1517
|
+
{
|
|
1518
|
+
width: "12",
|
|
1519
|
+
height: "12",
|
|
1520
|
+
viewBox: "0 0 24 24",
|
|
1521
|
+
fill: "currentColor",
|
|
1522
|
+
"aria-hidden": "true",
|
|
1523
|
+
children: /* @__PURE__ */ jsx(
|
|
1524
|
+
"rect",
|
|
1525
|
+
{
|
|
1526
|
+
x: "6",
|
|
1527
|
+
y: "6",
|
|
1528
|
+
width: "12",
|
|
1529
|
+
height: "12",
|
|
1530
|
+
rx: "2"
|
|
1531
|
+
}
|
|
1532
|
+
)
|
|
1533
|
+
}
|
|
1534
|
+
) : /* @__PURE__ */ jsxs(
|
|
1535
|
+
"svg",
|
|
1536
|
+
{
|
|
1537
|
+
width: "13",
|
|
1538
|
+
height: "13",
|
|
1539
|
+
viewBox: "0 0 24 24",
|
|
1540
|
+
fill: "none",
|
|
1541
|
+
"aria-hidden": "true",
|
|
1542
|
+
children: [
|
|
1543
|
+
/* @__PURE__ */ jsx(
|
|
1544
|
+
"rect",
|
|
1545
|
+
{
|
|
1546
|
+
x: "9",
|
|
1547
|
+
y: "2",
|
|
1548
|
+
width: "6",
|
|
1549
|
+
height: "12",
|
|
1550
|
+
rx: "3",
|
|
1551
|
+
stroke: "currentColor",
|
|
1552
|
+
strokeWidth: "1.8"
|
|
1553
|
+
}
|
|
1554
|
+
),
|
|
1555
|
+
/* @__PURE__ */ jsx(
|
|
1556
|
+
"path",
|
|
1557
|
+
{
|
|
1558
|
+
d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
|
|
1559
|
+
stroke: "currentColor",
|
|
1560
|
+
strokeWidth: "1.8",
|
|
1561
|
+
strokeLinecap: "round"
|
|
1562
|
+
}
|
|
1563
|
+
)
|
|
1564
|
+
]
|
|
1565
|
+
}
|
|
1566
|
+
)
|
|
1567
|
+
}
|
|
992
1568
|
)
|
|
993
1569
|
] }),
|
|
994
|
-
/* @__PURE__ */ jsxs(
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1570
|
+
transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ jsxs(
|
|
1571
|
+
"div",
|
|
1572
|
+
{
|
|
1573
|
+
style: {
|
|
1574
|
+
display: "flex",
|
|
1575
|
+
alignItems: "center",
|
|
1576
|
+
gap: "5px",
|
|
1577
|
+
marginTop: "5px",
|
|
1578
|
+
fontSize: "11px",
|
|
1579
|
+
color: t.text,
|
|
1580
|
+
opacity: 0.55,
|
|
1581
|
+
userSelect: "none"
|
|
1582
|
+
},
|
|
1583
|
+
children: [
|
|
1584
|
+
/* @__PURE__ */ jsxs("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1585
|
+
/* @__PURE__ */ jsx("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
|
|
1586
|
+
/* @__PURE__ */ jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1587
|
+
/* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
|
|
1588
|
+
] }),
|
|
1589
|
+
"Hold Space to speak \u2014 we'll transcribe it"
|
|
1590
|
+
]
|
|
1591
|
+
}
|
|
1592
|
+
),
|
|
1593
|
+
isEnhanced && originalDescription !== null && /* @__PURE__ */ jsxs(
|
|
1594
|
+
"div",
|
|
1595
|
+
{
|
|
1596
|
+
style: {
|
|
1597
|
+
display: "flex",
|
|
1598
|
+
alignItems: "center",
|
|
1599
|
+
gap: "6px",
|
|
1600
|
+
marginTop: "6px",
|
|
1601
|
+
padding: "6px 8px",
|
|
1602
|
+
borderRadius: "6px",
|
|
1603
|
+
background: isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.05)",
|
|
1604
|
+
border: `1px solid ${t.accent}40`
|
|
1605
|
+
},
|
|
1606
|
+
children: [
|
|
998
1607
|
/* @__PURE__ */ jsx(
|
|
999
|
-
"
|
|
1608
|
+
"svg",
|
|
1609
|
+
{
|
|
1610
|
+
width: "12",
|
|
1611
|
+
height: "12",
|
|
1612
|
+
viewBox: "0 0 24 24",
|
|
1613
|
+
fill: "none",
|
|
1614
|
+
style: { flexShrink: 0 },
|
|
1615
|
+
children: /* @__PURE__ */ jsx(
|
|
1616
|
+
"path",
|
|
1617
|
+
{
|
|
1618
|
+
d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
|
|
1619
|
+
stroke: t.accent,
|
|
1620
|
+
strokeWidth: "1.5",
|
|
1621
|
+
strokeLinejoin: "round"
|
|
1622
|
+
}
|
|
1623
|
+
)
|
|
1624
|
+
}
|
|
1625
|
+
),
|
|
1626
|
+
/* @__PURE__ */ jsx(
|
|
1627
|
+
"span",
|
|
1000
1628
|
{
|
|
1001
|
-
src: screenshot,
|
|
1002
|
-
alt: "Page screenshot",
|
|
1003
|
-
onClick: () => setPreviewOpen(true),
|
|
1004
1629
|
style: {
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
objectPosition: "top",
|
|
1011
|
-
cursor: "zoom-in",
|
|
1012
|
-
display: "block"
|
|
1013
|
-
}
|
|
1630
|
+
fontSize: "11px",
|
|
1631
|
+
color: t.textMuted,
|
|
1632
|
+
flex: 1
|
|
1633
|
+
},
|
|
1634
|
+
children: "AI enhanced"
|
|
1014
1635
|
}
|
|
1015
1636
|
),
|
|
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(
|
|
1637
|
+
/* @__PURE__ */ jsx(
|
|
1030
1638
|
"button",
|
|
1031
1639
|
{
|
|
1032
1640
|
type: "button",
|
|
1033
|
-
onClick: () =>
|
|
1641
|
+
onClick: () => {
|
|
1642
|
+
setIsEnhanced(false);
|
|
1643
|
+
setOriginalDescription(null);
|
|
1644
|
+
},
|
|
1034
1645
|
style: {
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
fontWeight: 500,
|
|
1646
|
+
padding: "2px 8px",
|
|
1647
|
+
borderRadius: "4px",
|
|
1648
|
+
border: `1px solid ${t.accent}`,
|
|
1649
|
+
background: t.accent,
|
|
1650
|
+
color: t.accentText,
|
|
1651
|
+
fontSize: "11px",
|
|
1652
|
+
fontWeight: 600,
|
|
1043
1653
|
cursor: "pointer",
|
|
1044
|
-
fontFamily: "inherit"
|
|
1045
|
-
display: "flex",
|
|
1046
|
-
alignItems: "center",
|
|
1047
|
-
justifyContent: "center",
|
|
1048
|
-
gap: "4px"
|
|
1654
|
+
fontFamily: "inherit"
|
|
1049
1655
|
},
|
|
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
|
-
]
|
|
1656
|
+
children: "Keep"
|
|
1054
1657
|
}
|
|
1055
1658
|
),
|
|
1056
|
-
/* @__PURE__ */
|
|
1659
|
+
/* @__PURE__ */ jsx(
|
|
1057
1660
|
"button",
|
|
1058
1661
|
{
|
|
1059
1662
|
type: "button",
|
|
1060
1663
|
onClick: () => {
|
|
1061
|
-
|
|
1062
|
-
|
|
1664
|
+
setDescription(originalDescription);
|
|
1665
|
+
setIsEnhanced(false);
|
|
1666
|
+
setOriginalDescription(null);
|
|
1063
1667
|
},
|
|
1064
1668
|
style: {
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
borderRadius: "6px",
|
|
1669
|
+
padding: "2px 8px",
|
|
1670
|
+
borderRadius: "4px",
|
|
1068
1671
|
border: `1px solid ${t.inputBorder}`,
|
|
1069
1672
|
background: "transparent",
|
|
1070
1673
|
color: t.textMuted,
|
|
1071
|
-
fontSize: "
|
|
1072
|
-
fontWeight:
|
|
1674
|
+
fontSize: "11px",
|
|
1675
|
+
fontWeight: 600,
|
|
1073
1676
|
cursor: "pointer",
|
|
1074
|
-
fontFamily: "inherit"
|
|
1075
|
-
display: "flex",
|
|
1076
|
-
alignItems: "center",
|
|
1077
|
-
justifyContent: "center",
|
|
1078
|
-
gap: "4px"
|
|
1677
|
+
fontFamily: "inherit"
|
|
1079
1678
|
},
|
|
1080
|
-
children:
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1679
|
+
children: "Restore"
|
|
1680
|
+
}
|
|
1681
|
+
)
|
|
1682
|
+
]
|
|
1683
|
+
}
|
|
1684
|
+
),
|
|
1685
|
+
voiceError && /* @__PURE__ */ jsx(
|
|
1686
|
+
"p",
|
|
1687
|
+
{
|
|
1688
|
+
style: {
|
|
1689
|
+
color: "#ef4444",
|
|
1690
|
+
fontSize: "11px",
|
|
1691
|
+
marginTop: "4px",
|
|
1692
|
+
marginBottom: 0
|
|
1693
|
+
},
|
|
1694
|
+
children: voiceError
|
|
1695
|
+
}
|
|
1696
|
+
),
|
|
1697
|
+
/* @__PURE__ */ jsxs("div", { style: { marginTop: "10px" }, children: [
|
|
1698
|
+
/* @__PURE__ */ jsx(
|
|
1699
|
+
"span",
|
|
1700
|
+
{
|
|
1701
|
+
style: {
|
|
1702
|
+
fontSize: "12px",
|
|
1703
|
+
color: t.textMuted,
|
|
1704
|
+
marginBottom: "6px",
|
|
1705
|
+
display: "block",
|
|
1706
|
+
fontWeight: 500
|
|
1707
|
+
},
|
|
1708
|
+
children: "Screenshot"
|
|
1709
|
+
}
|
|
1710
|
+
),
|
|
1711
|
+
screenshot ? /* @__PURE__ */ jsxs("div", { children: [
|
|
1712
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
|
|
1713
|
+
/* @__PURE__ */ jsx(
|
|
1714
|
+
"img",
|
|
1715
|
+
{
|
|
1716
|
+
src: screenshot,
|
|
1717
|
+
alt: "Page screenshot",
|
|
1718
|
+
onClick: () => setPreviewOpen(true),
|
|
1719
|
+
style: {
|
|
1720
|
+
width: "100%",
|
|
1721
|
+
borderRadius: "6px",
|
|
1722
|
+
border: `1px solid ${t.border}`,
|
|
1723
|
+
maxHeight: "64px",
|
|
1724
|
+
objectFit: "cover",
|
|
1725
|
+
objectPosition: "top",
|
|
1726
|
+
cursor: "zoom-in",
|
|
1727
|
+
display: "block"
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
),
|
|
1731
|
+
/* @__PURE__ */ jsx(
|
|
1732
|
+
"span",
|
|
1733
|
+
{
|
|
1734
|
+
style: {
|
|
1735
|
+
position: "absolute",
|
|
1736
|
+
bottom: "5px",
|
|
1737
|
+
left: "6px",
|
|
1738
|
+
background: "rgba(0,0,0,0.55)",
|
|
1739
|
+
color: "#fff",
|
|
1740
|
+
fontSize: "10px",
|
|
1741
|
+
padding: "1px 5px",
|
|
1742
|
+
borderRadius: "3px",
|
|
1743
|
+
pointerEvents: "none"
|
|
1744
|
+
},
|
|
1745
|
+
children: "click to preview"
|
|
1084
1746
|
}
|
|
1085
1747
|
)
|
|
1086
|
-
] })
|
|
1748
|
+
] }),
|
|
1749
|
+
/* @__PURE__ */ jsxs(
|
|
1750
|
+
"div",
|
|
1751
|
+
{
|
|
1752
|
+
style: {
|
|
1753
|
+
display: "flex",
|
|
1754
|
+
gap: "6px",
|
|
1755
|
+
marginTop: "6px"
|
|
1756
|
+
},
|
|
1757
|
+
children: [
|
|
1758
|
+
/* @__PURE__ */ jsxs(
|
|
1759
|
+
"button",
|
|
1760
|
+
{
|
|
1761
|
+
type: "button",
|
|
1762
|
+
onClick: () => setScreenshot(null),
|
|
1763
|
+
style: {
|
|
1764
|
+
flex: 1,
|
|
1765
|
+
padding: "6px 0",
|
|
1766
|
+
borderRadius: "6px",
|
|
1767
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1768
|
+
background: "transparent",
|
|
1769
|
+
color: "#ef4444",
|
|
1770
|
+
fontSize: "12px",
|
|
1771
|
+
fontWeight: 500,
|
|
1772
|
+
cursor: "pointer",
|
|
1773
|
+
fontFamily: "inherit",
|
|
1774
|
+
display: "flex",
|
|
1775
|
+
alignItems: "center",
|
|
1776
|
+
justifyContent: "center",
|
|
1777
|
+
gap: "4px"
|
|
1778
|
+
},
|
|
1779
|
+
children: [
|
|
1780
|
+
/* @__PURE__ */ jsx(
|
|
1781
|
+
"svg",
|
|
1782
|
+
{
|
|
1783
|
+
width: "11",
|
|
1784
|
+
height: "11",
|
|
1785
|
+
viewBox: "0 0 10 10",
|
|
1786
|
+
fill: "none",
|
|
1787
|
+
children: /* @__PURE__ */ jsx(
|
|
1788
|
+
"path",
|
|
1789
|
+
{
|
|
1790
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
1791
|
+
stroke: "currentColor",
|
|
1792
|
+
strokeWidth: "1.5",
|
|
1793
|
+
strokeLinecap: "round"
|
|
1794
|
+
}
|
|
1795
|
+
)
|
|
1796
|
+
}
|
|
1797
|
+
),
|
|
1798
|
+
"Remove"
|
|
1799
|
+
]
|
|
1800
|
+
}
|
|
1801
|
+
),
|
|
1802
|
+
/* @__PURE__ */ jsxs(
|
|
1803
|
+
"button",
|
|
1804
|
+
{
|
|
1805
|
+
type: "button",
|
|
1806
|
+
onClick: () => {
|
|
1807
|
+
var _a;
|
|
1808
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
1809
|
+
},
|
|
1810
|
+
style: {
|
|
1811
|
+
flex: 1,
|
|
1812
|
+
padding: "6px 0",
|
|
1813
|
+
borderRadius: "6px",
|
|
1814
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1815
|
+
background: "transparent",
|
|
1816
|
+
color: t.textMuted,
|
|
1817
|
+
fontSize: "12px",
|
|
1818
|
+
fontWeight: 500,
|
|
1819
|
+
cursor: "pointer",
|
|
1820
|
+
fontFamily: "inherit",
|
|
1821
|
+
display: "flex",
|
|
1822
|
+
alignItems: "center",
|
|
1823
|
+
justifyContent: "center",
|
|
1824
|
+
gap: "4px"
|
|
1825
|
+
},
|
|
1826
|
+
children: [
|
|
1827
|
+
/* @__PURE__ */ jsx(
|
|
1828
|
+
"svg",
|
|
1829
|
+
{
|
|
1830
|
+
width: "11",
|
|
1831
|
+
height: "11",
|
|
1832
|
+
viewBox: "0 0 24 24",
|
|
1833
|
+
fill: "none",
|
|
1834
|
+
children: /* @__PURE__ */ jsx(
|
|
1835
|
+
"path",
|
|
1836
|
+
{
|
|
1837
|
+
d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12",
|
|
1838
|
+
stroke: "currentColor",
|
|
1839
|
+
strokeWidth: "2",
|
|
1840
|
+
strokeLinecap: "round",
|
|
1841
|
+
strokeLinejoin: "round"
|
|
1842
|
+
}
|
|
1843
|
+
)
|
|
1844
|
+
}
|
|
1845
|
+
),
|
|
1846
|
+
"Replace"
|
|
1847
|
+
]
|
|
1848
|
+
}
|
|
1849
|
+
)
|
|
1850
|
+
]
|
|
1851
|
+
}
|
|
1852
|
+
)
|
|
1087
1853
|
] }) : (
|
|
1088
1854
|
/* Drop zone */
|
|
1089
1855
|
/* @__PURE__ */ jsxs(
|
|
@@ -1096,7 +1862,9 @@ function ReportDialog({
|
|
|
1096
1862
|
onDrop: (e) => {
|
|
1097
1863
|
e.preventDefault();
|
|
1098
1864
|
setScreenshotDragOver(false);
|
|
1099
|
-
const file = Array.from(
|
|
1865
|
+
const file = Array.from(
|
|
1866
|
+
e.dataTransfer.files
|
|
1867
|
+
).find((f) => f.type.startsWith("image/"));
|
|
1100
1868
|
if (!file) return;
|
|
1101
1869
|
const reader = new FileReader();
|
|
1102
1870
|
reader.onload = () => setScreenshot(reader.result);
|
|
@@ -1117,20 +1885,95 @@ function ReportDialog({
|
|
|
1117
1885
|
transition: "border-color 0.15s ease, background 0.15s ease"
|
|
1118
1886
|
},
|
|
1119
1887
|
children: [
|
|
1120
|
-
/* @__PURE__ */ jsxs(
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1888
|
+
/* @__PURE__ */ jsxs(
|
|
1889
|
+
"svg",
|
|
1890
|
+
{
|
|
1891
|
+
width: "22",
|
|
1892
|
+
height: "22",
|
|
1893
|
+
viewBox: "0 0 24 24",
|
|
1894
|
+
fill: "none",
|
|
1895
|
+
style: {
|
|
1896
|
+
margin: "0 auto 6px",
|
|
1897
|
+
display: "block",
|
|
1898
|
+
opacity: 0.45
|
|
1899
|
+
},
|
|
1900
|
+
children: [
|
|
1901
|
+
/* @__PURE__ */ jsx(
|
|
1902
|
+
"rect",
|
|
1903
|
+
{
|
|
1904
|
+
x: "3",
|
|
1905
|
+
y: "3",
|
|
1906
|
+
width: "18",
|
|
1907
|
+
height: "18",
|
|
1908
|
+
rx: "2",
|
|
1909
|
+
stroke: t.textMuted,
|
|
1910
|
+
strokeWidth: "1.5"
|
|
1911
|
+
}
|
|
1912
|
+
),
|
|
1913
|
+
/* @__PURE__ */ jsx(
|
|
1914
|
+
"circle",
|
|
1915
|
+
{
|
|
1916
|
+
cx: "8.5",
|
|
1917
|
+
cy: "8.5",
|
|
1918
|
+
r: "1.5",
|
|
1919
|
+
stroke: t.textMuted,
|
|
1920
|
+
strokeWidth: "1.5"
|
|
1921
|
+
}
|
|
1922
|
+
),
|
|
1923
|
+
/* @__PURE__ */ jsx(
|
|
1924
|
+
"path",
|
|
1925
|
+
{
|
|
1926
|
+
d: "M21 15l-5-5L5 21",
|
|
1927
|
+
stroke: t.textMuted,
|
|
1928
|
+
strokeWidth: "1.5",
|
|
1929
|
+
strokeLinecap: "round",
|
|
1930
|
+
strokeLinejoin: "round"
|
|
1931
|
+
}
|
|
1932
|
+
)
|
|
1933
|
+
]
|
|
1934
|
+
}
|
|
1935
|
+
),
|
|
1936
|
+
/* @__PURE__ */ jsx(
|
|
1937
|
+
"p",
|
|
1938
|
+
{
|
|
1939
|
+
style: {
|
|
1940
|
+
margin: 0,
|
|
1941
|
+
fontSize: "12px",
|
|
1942
|
+
fontWeight: 600,
|
|
1943
|
+
color: t.text
|
|
1944
|
+
},
|
|
1945
|
+
children: screenshotDragOver ? "Drop to attach" : "Add a screenshot"
|
|
1946
|
+
}
|
|
1947
|
+
),
|
|
1948
|
+
/* @__PURE__ */ jsx(
|
|
1949
|
+
"p",
|
|
1950
|
+
{
|
|
1951
|
+
style: {
|
|
1952
|
+
margin: "3px 0 0",
|
|
1953
|
+
fontSize: "11px",
|
|
1954
|
+
color: t.textMuted
|
|
1955
|
+
},
|
|
1956
|
+
children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
|
|
1957
|
+
}
|
|
1958
|
+
)
|
|
1127
1959
|
]
|
|
1128
1960
|
}
|
|
1129
1961
|
)
|
|
1130
1962
|
)
|
|
1131
1963
|
] }),
|
|
1132
1964
|
showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs("div", { style: { marginTop: "10px" }, children: [
|
|
1133
|
-
/* @__PURE__ */ jsx(
|
|
1965
|
+
/* @__PURE__ */ jsx(
|
|
1966
|
+
"span",
|
|
1967
|
+
{
|
|
1968
|
+
style: {
|
|
1969
|
+
fontSize: "12px",
|
|
1970
|
+
color: t.textMuted,
|
|
1971
|
+
marginBottom: "6px",
|
|
1972
|
+
display: "block"
|
|
1973
|
+
},
|
|
1974
|
+
children: "Severity"
|
|
1975
|
+
}
|
|
1976
|
+
),
|
|
1134
1977
|
/* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ jsx(
|
|
1135
1978
|
"button",
|
|
1136
1979
|
{
|
|
@@ -1155,114 +1998,34 @@ function ReportDialog({
|
|
|
1155
1998
|
s
|
|
1156
1999
|
)) })
|
|
1157
2000
|
] }),
|
|
1158
|
-
validationError && /* @__PURE__ */ jsx(
|
|
1159
|
-
|
|
1160
|
-
"button",
|
|
2001
|
+
validationError && /* @__PURE__ */ jsx(
|
|
2002
|
+
"p",
|
|
1161
2003
|
{
|
|
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
2004
|
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"
|
|
2005
|
+
color: "#ef4444",
|
|
2006
|
+
fontSize: "12px",
|
|
2007
|
+
marginTop: "6px"
|
|
1186
2008
|
},
|
|
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
|
-
}
|
|
2009
|
+
children: validationError
|
|
1248
2010
|
}
|
|
1249
|
-
)
|
|
2011
|
+
),
|
|
1250
2012
|
/* @__PURE__ */ jsx(
|
|
1251
2013
|
"button",
|
|
1252
2014
|
{
|
|
1253
2015
|
type: "button",
|
|
1254
2016
|
onClick: handleSubmit,
|
|
1255
|
-
disabled: isSubmitting,
|
|
2017
|
+
disabled: !description.trim() || isSubmitting,
|
|
1256
2018
|
style: {
|
|
2019
|
+
marginTop: "12px",
|
|
1257
2020
|
width: "100%",
|
|
1258
2021
|
padding: "10px",
|
|
1259
2022
|
borderRadius: "8px",
|
|
1260
2023
|
border: "none",
|
|
1261
|
-
backgroundColor: isSubmitting ? t.bgSecondary : t.accent,
|
|
1262
|
-
color: isSubmitting ? t.textMuted : t.accentText,
|
|
2024
|
+
backgroundColor: !description.trim() || isSubmitting ? t.bgSecondary : t.accent,
|
|
2025
|
+
color: !description.trim() || isSubmitting ? t.textMuted : t.accentText,
|
|
1263
2026
|
fontSize: "14px",
|
|
1264
2027
|
fontWeight: 600,
|
|
1265
|
-
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
2028
|
+
cursor: !description.trim() || isSubmitting ? "not-allowed" : "pointer",
|
|
1266
2029
|
fontFamily: "inherit",
|
|
1267
2030
|
transition: "background-color 0.15s ease"
|
|
1268
2031
|
},
|
|
@@ -1378,10 +2141,11 @@ function getTypeSubtitle(type) {
|
|
|
1378
2141
|
return "General feedback";
|
|
1379
2142
|
}
|
|
1380
2143
|
}
|
|
1381
|
-
function getPlaceholder(type) {
|
|
2144
|
+
function getPlaceholder(type, idx = 0, hasVoice = false) {
|
|
2145
|
+
if (hasVoice && idx === 1) return "Hold Space to speak \u2014 we'll transcribe it";
|
|
1382
2146
|
switch (type) {
|
|
1383
2147
|
case "BUG":
|
|
1384
|
-
return "What went wrong?";
|
|
2148
|
+
return "What went wrong? Describe it or paste an error...";
|
|
1385
2149
|
case "FEATURE_REQUEST":
|
|
1386
2150
|
return "Describe the feature you'd like...";
|
|
1387
2151
|
case "QUESTION":
|
|
@@ -1391,19 +2155,58 @@ function getPlaceholder(type) {
|
|
|
1391
2155
|
}
|
|
1392
2156
|
}
|
|
1393
2157
|
function getTypeIcon(type, color, size = 24) {
|
|
1394
|
-
const props = {
|
|
2158
|
+
const props = {
|
|
2159
|
+
width: size,
|
|
2160
|
+
height: size,
|
|
2161
|
+
viewBox: "0 0 24 24",
|
|
2162
|
+
fill: "none",
|
|
2163
|
+
style: { flexShrink: 0 }
|
|
2164
|
+
};
|
|
1395
2165
|
switch (type) {
|
|
1396
2166
|
case "BUG":
|
|
1397
|
-
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2167
|
+
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2168
|
+
"path",
|
|
2169
|
+
{
|
|
2170
|
+
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",
|
|
2171
|
+
stroke: color,
|
|
2172
|
+
strokeWidth: "1.5",
|
|
2173
|
+
strokeLinecap: "round"
|
|
2174
|
+
}
|
|
2175
|
+
) });
|
|
1398
2176
|
case "FEATURE_REQUEST":
|
|
1399
|
-
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2177
|
+
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2178
|
+
"path",
|
|
2179
|
+
{
|
|
2180
|
+
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",
|
|
2181
|
+
stroke: color,
|
|
2182
|
+
strokeWidth: "1.5",
|
|
2183
|
+
strokeLinejoin: "round"
|
|
2184
|
+
}
|
|
2185
|
+
) });
|
|
1400
2186
|
case "QUESTION":
|
|
1401
2187
|
return /* @__PURE__ */ jsxs("svg", { ...props, children: [
|
|
1402
2188
|
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
|
|
1403
|
-
/* @__PURE__ */ jsx(
|
|
2189
|
+
/* @__PURE__ */ jsx(
|
|
2190
|
+
"path",
|
|
2191
|
+
{
|
|
2192
|
+
d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
|
|
2193
|
+
stroke: color,
|
|
2194
|
+
strokeWidth: "1.5",
|
|
2195
|
+
strokeLinecap: "round",
|
|
2196
|
+
strokeLinejoin: "round"
|
|
2197
|
+
}
|
|
2198
|
+
)
|
|
1404
2199
|
] });
|
|
1405
2200
|
case "OTHER":
|
|
1406
|
-
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2201
|
+
return /* @__PURE__ */ jsx("svg", { ...props, children: /* @__PURE__ */ jsx(
|
|
2202
|
+
"path",
|
|
2203
|
+
{
|
|
2204
|
+
d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
|
|
2205
|
+
stroke: color,
|
|
2206
|
+
strokeWidth: "1.5",
|
|
2207
|
+
strokeLinejoin: "round"
|
|
2208
|
+
}
|
|
2209
|
+
) });
|
|
1407
2210
|
}
|
|
1408
2211
|
}
|
|
1409
2212
|
|
|
@@ -1625,15 +2428,31 @@ function GlitchgrabProviderInner({
|
|
|
1625
2428
|
[]
|
|
1626
2429
|
);
|
|
1627
2430
|
const enhance = useCallback(
|
|
1628
|
-
async (text) => {
|
|
2431
|
+
async (text, screenshot) => {
|
|
1629
2432
|
try {
|
|
1630
|
-
|
|
2433
|
+
const ctx = captureContext(visitedPagesRef.current);
|
|
2434
|
+
const context = {
|
|
2435
|
+
url: ctx.url,
|
|
2436
|
+
visitedPages: ctx.visitedPages.slice(-5),
|
|
2437
|
+
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
2438
|
+
};
|
|
2439
|
+
return await enhanceText(text, token, baseUrl, screenshot, context);
|
|
1631
2440
|
} catch (e) {
|
|
1632
2441
|
return text;
|
|
1633
2442
|
}
|
|
1634
2443
|
},
|
|
1635
2444
|
[token, baseUrl]
|
|
1636
2445
|
);
|
|
2446
|
+
const transcribe = useCallback(
|
|
2447
|
+
async (blob) => {
|
|
2448
|
+
try {
|
|
2449
|
+
return await transcribeAudio(blob, token, baseUrl);
|
|
2450
|
+
} catch (e) {
|
|
2451
|
+
return "";
|
|
2452
|
+
}
|
|
2453
|
+
},
|
|
2454
|
+
[token, baseUrl]
|
|
2455
|
+
);
|
|
1637
2456
|
const openReportDialog = useCallback((options) => {
|
|
1638
2457
|
if (typeof window !== "undefined") {
|
|
1639
2458
|
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
@@ -1678,7 +2497,7 @@ function GlitchgrabProviderInner({
|
|
|
1678
2497
|
children
|
|
1679
2498
|
}
|
|
1680
2499
|
),
|
|
1681
|
-
/* @__PURE__ */ jsx2(ReportDialog, { report, enhanceText: enhance, types, showSeverity })
|
|
2500
|
+
/* @__PURE__ */ jsx2(ReportDialog, { report, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity })
|
|
1682
2501
|
]
|
|
1683
2502
|
}
|
|
1684
2503
|
);
|