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.js
CHANGED
|
@@ -319,7 +319,7 @@ async function sendReport(payload, baseUrl) {
|
|
|
319
319
|
return null;
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
|
-
async function enhanceText(text, token, baseUrl) {
|
|
322
|
+
async function enhanceText(text, token, baseUrl, screenshot, context) {
|
|
323
323
|
var _a;
|
|
324
324
|
try {
|
|
325
325
|
const trimmed = text.trim();
|
|
@@ -331,7 +331,11 @@ async function enhanceText(text, token, baseUrl) {
|
|
|
331
331
|
"Content-Type": "application/json",
|
|
332
332
|
Authorization: `Bearer ${token}`
|
|
333
333
|
},
|
|
334
|
-
body: JSON.stringify({
|
|
334
|
+
body: JSON.stringify({
|
|
335
|
+
text: trimmed,
|
|
336
|
+
...screenshot ? { screenshot } : {},
|
|
337
|
+
...context ? { context } : {}
|
|
338
|
+
})
|
|
335
339
|
});
|
|
336
340
|
if (!response.ok) return text;
|
|
337
341
|
const envelope = await response.json();
|
|
@@ -343,6 +347,28 @@ async function enhanceText(text, token, baseUrl) {
|
|
|
343
347
|
return text;
|
|
344
348
|
}
|
|
345
349
|
}
|
|
350
|
+
async function transcribeAudio(blob, token, baseUrl) {
|
|
351
|
+
var _a;
|
|
352
|
+
try {
|
|
353
|
+
if (blob.size === 0) return "";
|
|
354
|
+
const url = `${baseUrl != null ? baseUrl : DEFAULT_BASE_URL}/api/v1/sdk/stt`;
|
|
355
|
+
const form = new FormData();
|
|
356
|
+
form.append("file", blob, "audio.webm");
|
|
357
|
+
const response = await fetch(url, {
|
|
358
|
+
method: "POST",
|
|
359
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
360
|
+
body: form
|
|
361
|
+
});
|
|
362
|
+
if (!response.ok) return "";
|
|
363
|
+
const envelope = await response.json();
|
|
364
|
+
if ((envelope == null ? void 0 : envelope.success) && typeof ((_a = envelope.data) == null ? void 0 : _a.transcript) === "string") {
|
|
365
|
+
return envelope.data.transcript;
|
|
366
|
+
}
|
|
367
|
+
return "";
|
|
368
|
+
} catch (e) {
|
|
369
|
+
return "";
|
|
370
|
+
}
|
|
371
|
+
}
|
|
346
372
|
|
|
347
373
|
// src/dedup.ts
|
|
348
374
|
var DEFAULT_WINDOW_MS = 5 * 60 * 1e3;
|
|
@@ -481,11 +507,17 @@ function useIsDark() {
|
|
|
481
507
|
try {
|
|
482
508
|
for (const el of [document.body, document.documentElement]) {
|
|
483
509
|
const bg = getComputedStyle(el).backgroundColor;
|
|
484
|
-
const match = bg.match(
|
|
510
|
+
const match = bg.match(
|
|
511
|
+
/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/
|
|
512
|
+
);
|
|
485
513
|
if (match) {
|
|
486
514
|
const alpha = match[4] !== void 0 ? parseFloat(match[4]) : 1;
|
|
487
515
|
if (alpha < 0.05) continue;
|
|
488
|
-
const [r, g, b] = [
|
|
516
|
+
const [r, g, b] = [
|
|
517
|
+
Number(match[1]),
|
|
518
|
+
Number(match[2]),
|
|
519
|
+
Number(match[3])
|
|
520
|
+
];
|
|
489
521
|
return (r * 299 + g * 587 + b * 114) / 1e3 < 128;
|
|
490
522
|
}
|
|
491
523
|
}
|
|
@@ -511,14 +543,26 @@ function parseColorToRgb(value) {
|
|
|
511
543
|
const hexMatch = trimmed.match(/^#([0-9a-f]{3,8})$/i);
|
|
512
544
|
if (hexMatch) {
|
|
513
545
|
let hex = hexMatch[1];
|
|
514
|
-
if (hex.length === 3)
|
|
515
|
-
|
|
546
|
+
if (hex.length === 3)
|
|
547
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
548
|
+
return [
|
|
549
|
+
parseInt(hex.slice(0, 2), 16),
|
|
550
|
+
parseInt(hex.slice(2, 4), 16),
|
|
551
|
+
parseInt(hex.slice(4, 6), 16)
|
|
552
|
+
];
|
|
516
553
|
}
|
|
517
554
|
const rgbMatch = trimmed.match(/rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/);
|
|
518
|
-
if (rgbMatch)
|
|
519
|
-
|
|
555
|
+
if (rgbMatch)
|
|
556
|
+
return [Number(rgbMatch[1]), Number(rgbMatch[2]), Number(rgbMatch[3])];
|
|
557
|
+
const hslMatch = trimmed.match(
|
|
558
|
+
/hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%/
|
|
559
|
+
);
|
|
520
560
|
if (hslMatch) {
|
|
521
|
-
const hex = hslToHex(
|
|
561
|
+
const hex = hslToHex(
|
|
562
|
+
Number(hslMatch[1]),
|
|
563
|
+
Number(hslMatch[2]),
|
|
564
|
+
Number(hslMatch[3])
|
|
565
|
+
);
|
|
522
566
|
return parseColorToRgb(hex);
|
|
523
567
|
}
|
|
524
568
|
return null;
|
|
@@ -548,9 +592,16 @@ function detectHostAccent() {
|
|
|
548
592
|
if (!raw) continue;
|
|
549
593
|
const hslSpaceMatch = raw.match(/^([\d.]+)\s+([\d.]+)%\s+([\d.]+)%$/);
|
|
550
594
|
if (hslSpaceMatch) {
|
|
551
|
-
const hex = hslToHex(
|
|
595
|
+
const hex = hslToHex(
|
|
596
|
+
Number(hslSpaceMatch[1]),
|
|
597
|
+
Number(hslSpaceMatch[2]),
|
|
598
|
+
Number(hslSpaceMatch[3])
|
|
599
|
+
);
|
|
552
600
|
const rgb2 = parseColorToRgb(hex);
|
|
553
|
-
return {
|
|
601
|
+
return {
|
|
602
|
+
accent: hex,
|
|
603
|
+
accentText: rgb2 ? getContrastText(...rgb2) : "#ffffff"
|
|
604
|
+
};
|
|
554
605
|
}
|
|
555
606
|
const rgb = parseColorToRgb(raw);
|
|
556
607
|
if (rgb) {
|
|
@@ -565,7 +616,27 @@ function detectHostAccent() {
|
|
|
565
616
|
}
|
|
566
617
|
function getTheme(dark) {
|
|
567
618
|
const hostAccent = detectHostAccent();
|
|
568
|
-
const defaults = dark ? {
|
|
619
|
+
const defaults = dark ? {
|
|
620
|
+
bg: "#1c1c1e",
|
|
621
|
+
bgSecondary: "#27272a",
|
|
622
|
+
border: "#2c2c2e",
|
|
623
|
+
text: "#fafafa",
|
|
624
|
+
textMuted: "#a1a1aa",
|
|
625
|
+
accent: "#22d3ee",
|
|
626
|
+
accentText: "#09090b",
|
|
627
|
+
inputBg: "#27272a",
|
|
628
|
+
inputBorder: "#3f3f46"
|
|
629
|
+
} : {
|
|
630
|
+
bg: "#ffffff",
|
|
631
|
+
bgSecondary: "#f4f4f5",
|
|
632
|
+
border: "#e4e4e7",
|
|
633
|
+
text: "#18181b",
|
|
634
|
+
textMuted: "#71717a",
|
|
635
|
+
accent: "#0891b2",
|
|
636
|
+
accentText: "#ffffff",
|
|
637
|
+
inputBg: "#fafafa",
|
|
638
|
+
inputBorder: "#d4d4d8"
|
|
639
|
+
};
|
|
569
640
|
if (hostAccent) {
|
|
570
641
|
defaults.accent = hostAccent.accent;
|
|
571
642
|
defaults.accentText = hostAccent.accentText;
|
|
@@ -615,10 +686,18 @@ function isLowQualityText(text) {
|
|
|
615
686
|
function ReportDialog({
|
|
616
687
|
report,
|
|
617
688
|
enhanceText: enhanceText2,
|
|
689
|
+
transcribeAudio: transcribeAudio2,
|
|
618
690
|
types,
|
|
619
691
|
showSeverity = true
|
|
620
692
|
}) {
|
|
621
693
|
const [isEnhancing, setIsEnhancing] = (0, import_react.useState)(false);
|
|
694
|
+
const [isEnhanced, setIsEnhanced] = (0, import_react.useState)(false);
|
|
695
|
+
const [originalDescription, setOriginalDescription] = (0, import_react.useState)(
|
|
696
|
+
null
|
|
697
|
+
);
|
|
698
|
+
const [isListening, setIsListening] = (0, import_react.useState)(false);
|
|
699
|
+
const [isTranscribing, setIsTranscribing] = (0, import_react.useState)(false);
|
|
700
|
+
const [voiceError, setVoiceError] = (0, import_react.useState)(null);
|
|
622
701
|
const [screenshotDragOver, setScreenshotDragOver] = (0, import_react.useState)(false);
|
|
623
702
|
const [mounted, setMounted] = (0, import_react.useState)(false);
|
|
624
703
|
(0, import_react.useEffect)(() => {
|
|
@@ -632,10 +711,22 @@ function ReportDialog({
|
|
|
632
711
|
const [previewOpen, setPreviewOpen] = (0, import_react.useState)(false);
|
|
633
712
|
const fileInputRef = (0, import_react.useRef)(null);
|
|
634
713
|
const modalRef = (0, import_react.useRef)(null);
|
|
714
|
+
const textareaRef = (0, import_react.useRef)(null);
|
|
715
|
+
const recognitionRef = (0, import_react.useRef)(null);
|
|
716
|
+
const voiceBaseRef = (0, import_react.useRef)("");
|
|
717
|
+
const usingWebSpeechRef = (0, import_react.useRef)(false);
|
|
718
|
+
const textBeforeVoiceRef = (0, import_react.useRef)("");
|
|
719
|
+
const mediaRecorderRef = (0, import_react.useRef)(null);
|
|
720
|
+
const streamRef = (0, import_react.useRef)(null);
|
|
721
|
+
const sarvamChunksRef = (0, import_react.useRef)([]);
|
|
722
|
+
const spaceTimerRef = (0, import_react.useRef)(null);
|
|
723
|
+
const isPushToTalkRef = (0, import_react.useRef)(false);
|
|
635
724
|
(0, import_react.useEffect)(() => {
|
|
636
725
|
if (!isOpen) return;
|
|
637
726
|
const dialogs = Array.from(
|
|
638
|
-
document.querySelectorAll(
|
|
727
|
+
document.querySelectorAll(
|
|
728
|
+
'[role="dialog"][data-state="open"]'
|
|
729
|
+
)
|
|
639
730
|
);
|
|
640
731
|
dialogs.forEach((d) => d.setAttribute("inert", ""));
|
|
641
732
|
return () => dialogs.forEach((d) => d.removeAttribute("inert"));
|
|
@@ -644,7 +735,13 @@ function ReportDialog({
|
|
|
644
735
|
const [reportType, setReportType] = (0, import_react.useState)("BUG");
|
|
645
736
|
const [severity, setSeverity] = (0, import_react.useState)("medium");
|
|
646
737
|
const [validationError, setValidationError] = (0, import_react.useState)(null);
|
|
647
|
-
const
|
|
738
|
+
const [placeholderIdx, setPlaceholderIdx] = (0, import_react.useState)(0);
|
|
739
|
+
const availableTypes = types != null ? types : [
|
|
740
|
+
"BUG",
|
|
741
|
+
"FEATURE_REQUEST",
|
|
742
|
+
"QUESTION",
|
|
743
|
+
"OTHER"
|
|
744
|
+
];
|
|
648
745
|
const isDark = useIsDark();
|
|
649
746
|
const t = getTheme(isDark);
|
|
650
747
|
const handleFileUpload = (e) => {
|
|
@@ -744,12 +841,187 @@ function ReportDialog({
|
|
|
744
841
|
window.addEventListener("paste", handlePaste);
|
|
745
842
|
return () => window.removeEventListener("paste", handlePaste);
|
|
746
843
|
}, [isOpen]);
|
|
844
|
+
(0, import_react.useEffect)(() => {
|
|
845
|
+
if (!isOpen || !transcribeAudio2) return;
|
|
846
|
+
const id = setInterval(() => {
|
|
847
|
+
setPlaceholderIdx((i) => (i + 1) % 2);
|
|
848
|
+
}, 3e3);
|
|
849
|
+
return () => clearInterval(id);
|
|
850
|
+
}, [isOpen, transcribeAudio2]);
|
|
851
|
+
const stopVoice = () => {
|
|
852
|
+
var _a, _b;
|
|
853
|
+
usingWebSpeechRef.current = false;
|
|
854
|
+
(_a = recognitionRef.current) == null ? void 0 : _a.stop();
|
|
855
|
+
recognitionRef.current = null;
|
|
856
|
+
sarvamChunksRef.current = [];
|
|
857
|
+
const stream = streamRef.current;
|
|
858
|
+
streamRef.current = null;
|
|
859
|
+
stream == null ? void 0 : stream.getTracks().forEach((t2) => t2.stop());
|
|
860
|
+
try {
|
|
861
|
+
(_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
|
|
862
|
+
} catch (e) {
|
|
863
|
+
}
|
|
864
|
+
mediaRecorderRef.current = null;
|
|
865
|
+
setIsListening(false);
|
|
866
|
+
setIsTranscribing(false);
|
|
867
|
+
};
|
|
868
|
+
const stopListeningAndTranscribe = () => {
|
|
869
|
+
var _a, _b;
|
|
870
|
+
usingWebSpeechRef.current = false;
|
|
871
|
+
(_a = recognitionRef.current) == null ? void 0 : _a.stop();
|
|
872
|
+
recognitionRef.current = null;
|
|
873
|
+
setIsListening(false);
|
|
874
|
+
try {
|
|
875
|
+
(_b = mediaRecorderRef.current) == null ? void 0 : _b.stop();
|
|
876
|
+
} catch (e) {
|
|
877
|
+
}
|
|
878
|
+
};
|
|
747
879
|
const handleClose = () => {
|
|
880
|
+
stopVoice();
|
|
748
881
|
setIsOpen(false);
|
|
749
882
|
setStep(1);
|
|
750
883
|
setReportType("BUG");
|
|
751
884
|
setSeverity("medium");
|
|
752
885
|
setValidationError(null);
|
|
886
|
+
setVoiceError(null);
|
|
887
|
+
setIsEnhanced(false);
|
|
888
|
+
setOriginalDescription(null);
|
|
889
|
+
};
|
|
890
|
+
const toggleVoice = async () => {
|
|
891
|
+
if (isListening) {
|
|
892
|
+
stopListeningAndTranscribe();
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const SpeechRec = typeof window !== "undefined" ? window.SpeechRecognition || window.webkitSpeechRecognition : void 0;
|
|
896
|
+
let stream = null;
|
|
897
|
+
try {
|
|
898
|
+
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
899
|
+
} catch (err) {
|
|
900
|
+
const isDenied = err instanceof DOMException && (err.name === "NotAllowedError" || err.name === "PermissionDeniedError");
|
|
901
|
+
if (!SpeechRec || isDenied) {
|
|
902
|
+
setVoiceError("Microphone access denied");
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
if (stream && transcribeAudio2) {
|
|
907
|
+
streamRef.current = stream;
|
|
908
|
+
sarvamChunksRef.current = [];
|
|
909
|
+
textBeforeVoiceRef.current = description;
|
|
910
|
+
const rec = new MediaRecorder(stream);
|
|
911
|
+
mediaRecorderRef.current = rec;
|
|
912
|
+
rec.ondataavailable = (e) => {
|
|
913
|
+
if (e.data.size > 0) sarvamChunksRef.current.push(e.data);
|
|
914
|
+
};
|
|
915
|
+
rec.onstop = async () => {
|
|
916
|
+
stream.getTracks().forEach((t2) => t2.stop());
|
|
917
|
+
if (streamRef.current === stream) streamRef.current = null;
|
|
918
|
+
mediaRecorderRef.current = null;
|
|
919
|
+
const chunks = sarvamChunksRef.current;
|
|
920
|
+
sarvamChunksRef.current = [];
|
|
921
|
+
if (!chunks.length || !transcribeAudio2) return;
|
|
922
|
+
setIsTranscribing(true);
|
|
923
|
+
try {
|
|
924
|
+
const blob = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
|
|
925
|
+
const text = await transcribeAudio2(blob);
|
|
926
|
+
if (text.trim()) {
|
|
927
|
+
const sep = textBeforeVoiceRef.current.trim() ? " " : "";
|
|
928
|
+
setDescription(textBeforeVoiceRef.current + sep + text.trim());
|
|
929
|
+
setValidationError(null);
|
|
930
|
+
setIsEnhanced(false);
|
|
931
|
+
setOriginalDescription(null);
|
|
932
|
+
}
|
|
933
|
+
} catch (e) {
|
|
934
|
+
}
|
|
935
|
+
setIsTranscribing(false);
|
|
936
|
+
};
|
|
937
|
+
rec.start();
|
|
938
|
+
}
|
|
939
|
+
if (SpeechRec) {
|
|
940
|
+
setVoiceError(null);
|
|
941
|
+
usingWebSpeechRef.current = true;
|
|
942
|
+
voiceBaseRef.current = description;
|
|
943
|
+
textBeforeVoiceRef.current = description;
|
|
944
|
+
const recognition = new SpeechRec();
|
|
945
|
+
recognition.lang = "en-IN";
|
|
946
|
+
recognition.interimResults = true;
|
|
947
|
+
recognition.continuous = true;
|
|
948
|
+
recognitionRef.current = recognition;
|
|
949
|
+
recognition.onstart = () => setIsListening(true);
|
|
950
|
+
recognition.onresult = (event) => {
|
|
951
|
+
let finalText = "";
|
|
952
|
+
let interimText = "";
|
|
953
|
+
for (let i = event.resultIndex; i < event.results.length; i++) {
|
|
954
|
+
const text = event.results[i][0].transcript;
|
|
955
|
+
if (event.results[i].isFinal) finalText += text;
|
|
956
|
+
else interimText += text;
|
|
957
|
+
}
|
|
958
|
+
if (finalText) {
|
|
959
|
+
const sep = voiceBaseRef.current.trim() ? " " : "";
|
|
960
|
+
voiceBaseRef.current += sep + finalText.trim();
|
|
961
|
+
}
|
|
962
|
+
const liveText = interimText ? voiceBaseRef.current + (voiceBaseRef.current.trim() ? " " : "") + interimText : voiceBaseRef.current;
|
|
963
|
+
setDescription(liveText);
|
|
964
|
+
setValidationError(null);
|
|
965
|
+
};
|
|
966
|
+
recognition.onend = () => {
|
|
967
|
+
if (usingWebSpeechRef.current && recognitionRef.current === recognition) {
|
|
968
|
+
try {
|
|
969
|
+
recognition.start();
|
|
970
|
+
} catch (e) {
|
|
971
|
+
}
|
|
972
|
+
} else {
|
|
973
|
+
setIsListening(false);
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
recognition.onerror = (event) => {
|
|
977
|
+
if (event.error === "aborted" || event.error === "no-speech") return;
|
|
978
|
+
const isDenied = event.error === "not-allowed" || event.error === "audio-capture";
|
|
979
|
+
setVoiceError(isDenied ? "Microphone access denied" : "Speech recognition not available \u2014 try Chrome");
|
|
980
|
+
usingWebSpeechRef.current = false;
|
|
981
|
+
recognitionRef.current = null;
|
|
982
|
+
setIsListening(false);
|
|
983
|
+
};
|
|
984
|
+
recognition.start();
|
|
985
|
+
} else if (stream) {
|
|
986
|
+
setVoiceError(null);
|
|
987
|
+
setIsListening(true);
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
const handleSpaceDown = (e) => {
|
|
991
|
+
if (e.code !== "Space") return;
|
|
992
|
+
if (spaceTimerRef.current || isListening || isPushToTalkRef.current) {
|
|
993
|
+
e.preventDefault();
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
if (e.repeat || !transcribeAudio2 || isTranscribing) return;
|
|
997
|
+
e.preventDefault();
|
|
998
|
+
spaceTimerRef.current = setTimeout(() => {
|
|
999
|
+
isPushToTalkRef.current = true;
|
|
1000
|
+
void toggleVoice();
|
|
1001
|
+
}, 400);
|
|
1002
|
+
};
|
|
1003
|
+
const handleSpaceUp = (e) => {
|
|
1004
|
+
var _a;
|
|
1005
|
+
if (e.code !== "Space") return;
|
|
1006
|
+
if (spaceTimerRef.current) {
|
|
1007
|
+
clearTimeout(spaceTimerRef.current);
|
|
1008
|
+
spaceTimerRef.current = null;
|
|
1009
|
+
if (!isPushToTalkRef.current) {
|
|
1010
|
+
const ta = textareaRef.current;
|
|
1011
|
+
const pos = ta ? (_a = ta.selectionStart) != null ? _a : description.length : description.length;
|
|
1012
|
+
setDescription((prev) => prev.slice(0, pos) + " " + prev.slice(pos));
|
|
1013
|
+
requestAnimationFrame(() => {
|
|
1014
|
+
if (textareaRef.current) {
|
|
1015
|
+
textareaRef.current.selectionStart = pos + 1;
|
|
1016
|
+
textareaRef.current.selectionEnd = pos + 1;
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
1021
|
+
if (isPushToTalkRef.current) {
|
|
1022
|
+
isPushToTalkRef.current = false;
|
|
1023
|
+
stopListeningAndTranscribe();
|
|
1024
|
+
}
|
|
753
1025
|
};
|
|
754
1026
|
const handleSubmit = async () => {
|
|
755
1027
|
try {
|
|
@@ -766,7 +1038,11 @@ function ReportDialog({
|
|
|
766
1038
|
if (showSeverity && reportType === "BUG") {
|
|
767
1039
|
metadata.severity = severity;
|
|
768
1040
|
}
|
|
769
|
-
const result = await report(
|
|
1041
|
+
const result = await report(
|
|
1042
|
+
reportType,
|
|
1043
|
+
description.trim(),
|
|
1044
|
+
Object.keys(metadata).length > 0 ? metadata : void 0
|
|
1045
|
+
);
|
|
770
1046
|
if (result) {
|
|
771
1047
|
setSubmitted(true);
|
|
772
1048
|
setDescription("");
|
|
@@ -783,6 +1059,16 @@ function ReportDialog({
|
|
|
783
1059
|
};
|
|
784
1060
|
if (!mounted) return null;
|
|
785
1061
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1062
|
+
isOpen && (0, import_react_dom.createPortal)(
|
|
1063
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
|
|
1064
|
+
@keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
|
|
1065
|
+
@keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
|
|
1066
|
+
@keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
|
|
1067
|
+
@keyframes gg-b3{0%,100%{height:4px}30%{height:14px}70%{height:5px}}
|
|
1068
|
+
@keyframes gg-b4{0%,100%{height:6px}60%{height:13px}}
|
|
1069
|
+
` }),
|
|
1070
|
+
document.body
|
|
1071
|
+
),
|
|
786
1072
|
isOpen && (0, import_react_dom.createPortal)(
|
|
787
1073
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
788
1074
|
"div",
|
|
@@ -839,36 +1125,64 @@ function ReportDialog({
|
|
|
839
1125
|
alignItems: "center"
|
|
840
1126
|
},
|
|
841
1127
|
children: [
|
|
842
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
{
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1128
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1129
|
+
"div",
|
|
1130
|
+
{
|
|
1131
|
+
style: {
|
|
1132
|
+
display: "flex",
|
|
1133
|
+
alignItems: "center",
|
|
1134
|
+
gap: "8px"
|
|
1135
|
+
},
|
|
1136
|
+
children: [
|
|
1137
|
+
step > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1138
|
+
"button",
|
|
1139
|
+
{
|
|
1140
|
+
type: "button",
|
|
1141
|
+
onClick: () => setStep((s) => s - 1),
|
|
1142
|
+
style: {
|
|
1143
|
+
background: "none",
|
|
1144
|
+
border: "none",
|
|
1145
|
+
cursor: "pointer",
|
|
1146
|
+
padding: "2px",
|
|
1147
|
+
display: "flex",
|
|
1148
|
+
alignItems: "center"
|
|
1149
|
+
},
|
|
1150
|
+
"aria-label": "Back",
|
|
1151
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1152
|
+
"svg",
|
|
1153
|
+
{
|
|
1154
|
+
width: "16",
|
|
1155
|
+
height: "16",
|
|
1156
|
+
viewBox: "0 0 16 16",
|
|
1157
|
+
fill: "none",
|
|
1158
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1159
|
+
"path",
|
|
1160
|
+
{
|
|
1161
|
+
d: "M10 3L5 8L10 13",
|
|
1162
|
+
stroke: t.textMuted,
|
|
1163
|
+
strokeWidth: "2",
|
|
1164
|
+
strokeLinecap: "round",
|
|
1165
|
+
strokeLinejoin: "round"
|
|
1166
|
+
}
|
|
1167
|
+
)
|
|
1168
|
+
}
|
|
1169
|
+
)
|
|
1170
|
+
}
|
|
1171
|
+
),
|
|
1172
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1173
|
+
"span",
|
|
1174
|
+
{
|
|
1175
|
+
style: {
|
|
1176
|
+
fontSize: "15px",
|
|
1177
|
+
fontWeight: 600,
|
|
1178
|
+
color: t.text
|
|
1179
|
+
},
|
|
1180
|
+
children: step === 1 ? "What's on your mind?" : "Tell us more"
|
|
1181
|
+
}
|
|
1182
|
+
)
|
|
1183
|
+
]
|
|
1184
|
+
}
|
|
1185
|
+
),
|
|
872
1186
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
873
1187
|
"button",
|
|
874
1188
|
{
|
|
@@ -884,27 +1198,74 @@ function ReportDialog({
|
|
|
884
1198
|
justifyContent: "center"
|
|
885
1199
|
},
|
|
886
1200
|
"aria-label": "Close",
|
|
887
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1201
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1202
|
+
"svg",
|
|
1203
|
+
{
|
|
1204
|
+
width: "16",
|
|
1205
|
+
height: "16",
|
|
1206
|
+
viewBox: "0 0 16 16",
|
|
1207
|
+
fill: "none",
|
|
1208
|
+
style: { display: "block" },
|
|
1209
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1210
|
+
"path",
|
|
1211
|
+
{
|
|
1212
|
+
d: "M4 4L12 12M12 4L4 12",
|
|
1213
|
+
stroke: t.textMuted,
|
|
1214
|
+
strokeWidth: "2",
|
|
1215
|
+
strokeLinecap: "round"
|
|
1216
|
+
}
|
|
1217
|
+
)
|
|
1218
|
+
}
|
|
1219
|
+
)
|
|
888
1220
|
}
|
|
889
1221
|
)
|
|
890
1222
|
]
|
|
891
1223
|
}
|
|
892
1224
|
),
|
|
893
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1226
|
+
"div",
|
|
1227
|
+
{
|
|
1228
|
+
style: {
|
|
1229
|
+
display: "flex",
|
|
1230
|
+
alignItems: "center",
|
|
1231
|
+
justifyContent: "center",
|
|
1232
|
+
gap: "0",
|
|
1233
|
+
marginTop: "12px"
|
|
1234
|
+
},
|
|
1235
|
+
children: [1, 2].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1236
|
+
"div",
|
|
1237
|
+
{
|
|
1238
|
+
style: { display: "flex", alignItems: "center" },
|
|
1239
|
+
children: [
|
|
1240
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1241
|
+
"div",
|
|
1242
|
+
{
|
|
1243
|
+
style: {
|
|
1244
|
+
width: "8px",
|
|
1245
|
+
height: "8px",
|
|
1246
|
+
borderRadius: "50%",
|
|
1247
|
+
backgroundColor: s <= step ? t.accent : t.inputBorder,
|
|
1248
|
+
transition: "background-color 0.2s ease"
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
),
|
|
1252
|
+
i < 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1253
|
+
"div",
|
|
1254
|
+
{
|
|
1255
|
+
style: {
|
|
1256
|
+
width: "40px",
|
|
1257
|
+
height: "2px",
|
|
1258
|
+
backgroundColor: s < step ? t.accent : t.inputBorder,
|
|
1259
|
+
transition: "background-color 0.2s ease"
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
)
|
|
1263
|
+
]
|
|
1264
|
+
},
|
|
1265
|
+
s
|
|
1266
|
+
))
|
|
1267
|
+
}
|
|
1268
|
+
)
|
|
908
1269
|
]
|
|
909
1270
|
}
|
|
910
1271
|
),
|
|
@@ -924,76 +1285,185 @@ function ReportDialog({
|
|
|
924
1285
|
]
|
|
925
1286
|
}
|
|
926
1287
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
927
|
-
step === 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
928
|
-
"
|
|
1288
|
+
step === 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1289
|
+
"div",
|
|
929
1290
|
{
|
|
930
|
-
type: "button",
|
|
931
|
-
onClick: () => {
|
|
932
|
-
setReportType(type);
|
|
933
|
-
setStep(2);
|
|
934
|
-
},
|
|
935
1291
|
style: {
|
|
936
|
-
display: "
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
gap: "8px",
|
|
940
|
-
padding: "16px 8px",
|
|
941
|
-
borderRadius: "8px",
|
|
942
|
-
border: `1px solid ${t.inputBorder}`,
|
|
943
|
-
background: t.inputBg,
|
|
944
|
-
cursor: "pointer",
|
|
945
|
-
color: t.text,
|
|
946
|
-
fontFamily: "inherit",
|
|
947
|
-
transition: "border-color 0.15s ease"
|
|
948
|
-
},
|
|
949
|
-
onMouseEnter: (e) => {
|
|
950
|
-
e.currentTarget.style.borderColor = t.accent;
|
|
951
|
-
},
|
|
952
|
-
onMouseLeave: (e) => {
|
|
953
|
-
e.currentTarget.style.borderColor = t.inputBorder;
|
|
1292
|
+
display: "grid",
|
|
1293
|
+
gridTemplateColumns: "1fr 1fr",
|
|
1294
|
+
gap: "8px"
|
|
954
1295
|
},
|
|
955
|
-
children:
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1296
|
+
children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1297
|
+
"button",
|
|
1298
|
+
{
|
|
1299
|
+
type: "button",
|
|
1300
|
+
onClick: () => {
|
|
1301
|
+
setReportType(type);
|
|
1302
|
+
setStep(2);
|
|
1303
|
+
},
|
|
1304
|
+
style: {
|
|
1305
|
+
display: "flex",
|
|
1306
|
+
flexDirection: "column",
|
|
1307
|
+
alignItems: "center",
|
|
1308
|
+
gap: "8px",
|
|
1309
|
+
padding: "16px 8px",
|
|
1310
|
+
borderRadius: "8px",
|
|
1311
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1312
|
+
background: t.inputBg,
|
|
1313
|
+
cursor: "pointer",
|
|
1314
|
+
color: t.text,
|
|
1315
|
+
fontFamily: "inherit",
|
|
1316
|
+
transition: "border-color 0.15s ease"
|
|
1317
|
+
},
|
|
1318
|
+
onMouseEnter: (e) => {
|
|
1319
|
+
e.currentTarget.style.borderColor = t.accent;
|
|
1320
|
+
},
|
|
1321
|
+
onMouseLeave: (e) => {
|
|
1322
|
+
e.currentTarget.style.borderColor = t.inputBorder;
|
|
1323
|
+
},
|
|
1324
|
+
children: [
|
|
1325
|
+
getTypeIcon(type, t.accent),
|
|
1326
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
|
|
1327
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1328
|
+
"span",
|
|
1329
|
+
{
|
|
1330
|
+
style: {
|
|
1331
|
+
fontSize: "11px",
|
|
1332
|
+
color: t.textMuted,
|
|
1333
|
+
lineHeight: "1.3"
|
|
1334
|
+
},
|
|
1335
|
+
children: getTypeSubtitle(type)
|
|
1336
|
+
}
|
|
1337
|
+
)
|
|
1338
|
+
]
|
|
1339
|
+
},
|
|
1340
|
+
type
|
|
1341
|
+
))
|
|
1342
|
+
}
|
|
1343
|
+
),
|
|
963
1344
|
step === 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
964
1345
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
|
|
965
1346
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
966
1347
|
"textarea",
|
|
967
1348
|
{
|
|
1349
|
+
ref: textareaRef,
|
|
968
1350
|
value: description,
|
|
969
1351
|
onChange: (e) => {
|
|
970
1352
|
setDescription(e.target.value);
|
|
971
1353
|
if (validationError) setValidationError(null);
|
|
1354
|
+
if (isEnhanced) {
|
|
1355
|
+
setIsEnhanced(false);
|
|
1356
|
+
setOriginalDescription(null);
|
|
1357
|
+
}
|
|
972
1358
|
},
|
|
973
|
-
placeholder: getPlaceholder(reportType),
|
|
1359
|
+
placeholder: isTranscribing ? "Transcribing your speech\u2026" : isListening ? "Listening\u2026 speak now" : getPlaceholder(reportType, placeholderIdx, !!transcribeAudio2),
|
|
974
1360
|
style: {
|
|
975
1361
|
width: "100%",
|
|
976
1362
|
minHeight: "100px",
|
|
977
|
-
padding: enhanceText2 ? "28px 12px 10px" : "10px 12px",
|
|
1363
|
+
padding: enhanceText2 ? "28px 12px 36px" : transcribeAudio2 ? "10px 12px 36px" : "10px 12px",
|
|
978
1364
|
borderRadius: "8px",
|
|
979
|
-
border: `1px solid ${t.inputBorder}`,
|
|
1365
|
+
border: `1px solid ${isTranscribing ? "#f59e0b" : isListening ? t.accent : t.inputBorder}`,
|
|
980
1366
|
fontSize: "14px",
|
|
981
1367
|
fontFamily: "inherit",
|
|
982
|
-
resize: "
|
|
1368
|
+
resize: "none",
|
|
983
1369
|
outline: "none",
|
|
984
1370
|
boxSizing: "border-box",
|
|
985
1371
|
color: t.text,
|
|
986
|
-
backgroundColor: t.inputBg
|
|
1372
|
+
backgroundColor: t.inputBg,
|
|
1373
|
+
transition: "border-color 0.2s ease"
|
|
987
1374
|
},
|
|
1375
|
+
onKeyDown: handleSpaceDown,
|
|
1376
|
+
onKeyUp: handleSpaceUp,
|
|
988
1377
|
onFocus: (e) => {
|
|
989
1378
|
e.target.style.borderColor = t.accent;
|
|
990
1379
|
},
|
|
991
1380
|
onBlur: (e) => {
|
|
992
|
-
|
|
1381
|
+
if (!isListening && !isTranscribing)
|
|
1382
|
+
e.target.style.borderColor = t.inputBorder;
|
|
993
1383
|
},
|
|
994
1384
|
autoFocus: true
|
|
995
1385
|
}
|
|
996
1386
|
),
|
|
1387
|
+
(isListening || isTranscribing) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1388
|
+
"span",
|
|
1389
|
+
{
|
|
1390
|
+
style: {
|
|
1391
|
+
position: "absolute",
|
|
1392
|
+
bottom: "10px",
|
|
1393
|
+
left: "10px",
|
|
1394
|
+
display: "inline-flex",
|
|
1395
|
+
alignItems: "center",
|
|
1396
|
+
gap: "4px",
|
|
1397
|
+
fontSize: "10px",
|
|
1398
|
+
fontWeight: 700,
|
|
1399
|
+
letterSpacing: "0.04em",
|
|
1400
|
+
color: isTranscribing ? "#f59e0b" : "#ef4444",
|
|
1401
|
+
pointerEvents: "none",
|
|
1402
|
+
zIndex: 1
|
|
1403
|
+
},
|
|
1404
|
+
children: [
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1406
|
+
"span",
|
|
1407
|
+
{
|
|
1408
|
+
style: {
|
|
1409
|
+
width: "6px",
|
|
1410
|
+
height: "6px",
|
|
1411
|
+
borderRadius: "50%",
|
|
1412
|
+
backgroundColor: "currentColor",
|
|
1413
|
+
animation: "gg-pulse 1.2s ease-in-out infinite",
|
|
1414
|
+
display: "inline-block",
|
|
1415
|
+
flexShrink: 0
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
),
|
|
1419
|
+
isTranscribing ? "Transcribing\u2026" : "REC",
|
|
1420
|
+
isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1421
|
+
"span",
|
|
1422
|
+
{
|
|
1423
|
+
style: {
|
|
1424
|
+
display: "inline-flex",
|
|
1425
|
+
alignItems: "flex-end",
|
|
1426
|
+
gap: "2px",
|
|
1427
|
+
height: "14px",
|
|
1428
|
+
marginLeft: "3px"
|
|
1429
|
+
},
|
|
1430
|
+
children: [
|
|
1431
|
+
{ anim: "gg-b1", dur: "0.6s", delay: "0s" },
|
|
1432
|
+
{
|
|
1433
|
+
anim: "gg-b2",
|
|
1434
|
+
dur: "0.5s",
|
|
1435
|
+
delay: "0.1s"
|
|
1436
|
+
},
|
|
1437
|
+
{
|
|
1438
|
+
anim: "gg-b3",
|
|
1439
|
+
dur: "0.7s",
|
|
1440
|
+
delay: "0.05s"
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
anim: "gg-b4",
|
|
1444
|
+
dur: "0.55s",
|
|
1445
|
+
delay: "0.15s"
|
|
1446
|
+
}
|
|
1447
|
+
].map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1448
|
+
"span",
|
|
1449
|
+
{
|
|
1450
|
+
style: {
|
|
1451
|
+
width: "2.5px",
|
|
1452
|
+
height: "4px",
|
|
1453
|
+
borderRadius: "1px",
|
|
1454
|
+
backgroundColor: "#ef4444",
|
|
1455
|
+
animation: `${b.anim} ${b.dur} ease-in-out ${b.delay} infinite`,
|
|
1456
|
+
display: "inline-block",
|
|
1457
|
+
alignSelf: "center"
|
|
1458
|
+
}
|
|
1459
|
+
},
|
|
1460
|
+
i
|
|
1461
|
+
))
|
|
1462
|
+
}
|
|
1463
|
+
)
|
|
1464
|
+
]
|
|
1465
|
+
}
|
|
1466
|
+
),
|
|
997
1467
|
enhanceText2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
998
1468
|
"button",
|
|
999
1469
|
{
|
|
@@ -1002,16 +1472,22 @@ function ReportDialog({
|
|
|
1002
1472
|
if (!description.trim() || isEnhancing) return;
|
|
1003
1473
|
setIsEnhancing(true);
|
|
1004
1474
|
try {
|
|
1005
|
-
const polished = await enhanceText2(
|
|
1475
|
+
const polished = await enhanceText2(
|
|
1476
|
+
description,
|
|
1477
|
+
screenshot
|
|
1478
|
+
);
|
|
1006
1479
|
if (polished && polished !== description) {
|
|
1480
|
+
setOriginalDescription(description);
|
|
1007
1481
|
setDescription(polished);
|
|
1008
|
-
|
|
1482
|
+
setIsEnhanced(true);
|
|
1483
|
+
if (validationError)
|
|
1484
|
+
setValidationError(null);
|
|
1009
1485
|
}
|
|
1010
1486
|
} finally {
|
|
1011
1487
|
setIsEnhancing(false);
|
|
1012
1488
|
}
|
|
1013
1489
|
},
|
|
1014
|
-
disabled: !description.trim() || isEnhancing,
|
|
1490
|
+
disabled: !description.trim() || isEnhancing || isEnhanced,
|
|
1015
1491
|
style: {
|
|
1016
1492
|
position: "absolute",
|
|
1017
1493
|
top: "6px",
|
|
@@ -1032,105 +1508,393 @@ function ReportDialog({
|
|
|
1032
1508
|
},
|
|
1033
1509
|
title: "Polish grammar \u2014 preserves your meaning",
|
|
1034
1510
|
children: [
|
|
1035
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1511
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1512
|
+
"svg",
|
|
1513
|
+
{
|
|
1514
|
+
width: "11",
|
|
1515
|
+
height: "11",
|
|
1516
|
+
viewBox: "0 0 24 24",
|
|
1517
|
+
fill: "none",
|
|
1518
|
+
"aria-hidden": "true",
|
|
1519
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1520
|
+
"path",
|
|
1521
|
+
{
|
|
1522
|
+
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",
|
|
1523
|
+
stroke: t.textMuted,
|
|
1524
|
+
strokeWidth: "1.5",
|
|
1525
|
+
strokeLinejoin: "round"
|
|
1526
|
+
}
|
|
1527
|
+
)
|
|
1528
|
+
}
|
|
1529
|
+
),
|
|
1036
1530
|
isEnhancing ? "Enhancing..." : "AI enhance"
|
|
1037
1531
|
]
|
|
1038
1532
|
}
|
|
1533
|
+
),
|
|
1534
|
+
transcribeAudio2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1535
|
+
"button",
|
|
1536
|
+
{
|
|
1537
|
+
type: "button",
|
|
1538
|
+
onClick: () => {
|
|
1539
|
+
void toggleVoice();
|
|
1540
|
+
},
|
|
1541
|
+
title: isListening ? "Stop recording" : "Speak your report",
|
|
1542
|
+
style: {
|
|
1543
|
+
position: "absolute",
|
|
1544
|
+
bottom: "14px",
|
|
1545
|
+
right: "7px",
|
|
1546
|
+
width: "26px",
|
|
1547
|
+
height: "26px",
|
|
1548
|
+
display: "flex",
|
|
1549
|
+
alignItems: "center",
|
|
1550
|
+
justifyContent: "center",
|
|
1551
|
+
background: "transparent",
|
|
1552
|
+
border: `1.5px solid ${isListening ? "#ef4444" : t.inputBorder}`,
|
|
1553
|
+
borderRadius: "6px",
|
|
1554
|
+
color: isListening ? "#ef4444" : t.textMuted,
|
|
1555
|
+
cursor: "pointer",
|
|
1556
|
+
zIndex: 1,
|
|
1557
|
+
padding: 0,
|
|
1558
|
+
transition: "border-color 0.2s ease, color 0.2s ease"
|
|
1559
|
+
},
|
|
1560
|
+
children: isListening ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1561
|
+
"svg",
|
|
1562
|
+
{
|
|
1563
|
+
width: "12",
|
|
1564
|
+
height: "12",
|
|
1565
|
+
viewBox: "0 0 24 24",
|
|
1566
|
+
fill: "currentColor",
|
|
1567
|
+
"aria-hidden": "true",
|
|
1568
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1569
|
+
"rect",
|
|
1570
|
+
{
|
|
1571
|
+
x: "6",
|
|
1572
|
+
y: "6",
|
|
1573
|
+
width: "12",
|
|
1574
|
+
height: "12",
|
|
1575
|
+
rx: "2"
|
|
1576
|
+
}
|
|
1577
|
+
)
|
|
1578
|
+
}
|
|
1579
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1580
|
+
"svg",
|
|
1581
|
+
{
|
|
1582
|
+
width: "13",
|
|
1583
|
+
height: "13",
|
|
1584
|
+
viewBox: "0 0 24 24",
|
|
1585
|
+
fill: "none",
|
|
1586
|
+
"aria-hidden": "true",
|
|
1587
|
+
children: [
|
|
1588
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1589
|
+
"rect",
|
|
1590
|
+
{
|
|
1591
|
+
x: "9",
|
|
1592
|
+
y: "2",
|
|
1593
|
+
width: "6",
|
|
1594
|
+
height: "12",
|
|
1595
|
+
rx: "3",
|
|
1596
|
+
stroke: "currentColor",
|
|
1597
|
+
strokeWidth: "1.8"
|
|
1598
|
+
}
|
|
1599
|
+
),
|
|
1600
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1601
|
+
"path",
|
|
1602
|
+
{
|
|
1603
|
+
d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
|
|
1604
|
+
stroke: "currentColor",
|
|
1605
|
+
strokeWidth: "1.8",
|
|
1606
|
+
strokeLinecap: "round"
|
|
1607
|
+
}
|
|
1608
|
+
)
|
|
1609
|
+
]
|
|
1610
|
+
}
|
|
1611
|
+
)
|
|
1612
|
+
}
|
|
1039
1613
|
)
|
|
1040
1614
|
] }),
|
|
1041
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1615
|
+
transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1616
|
+
"div",
|
|
1617
|
+
{
|
|
1618
|
+
style: {
|
|
1619
|
+
display: "flex",
|
|
1620
|
+
alignItems: "center",
|
|
1621
|
+
gap: "5px",
|
|
1622
|
+
marginTop: "5px",
|
|
1623
|
+
fontSize: "11px",
|
|
1624
|
+
color: t.text,
|
|
1625
|
+
opacity: 0.55,
|
|
1626
|
+
userSelect: "none"
|
|
1627
|
+
},
|
|
1628
|
+
children: [
|
|
1629
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1630
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
|
|
1631
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1632
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
|
|
1633
|
+
] }),
|
|
1634
|
+
"Hold Space to speak \u2014 we'll transcribe it"
|
|
1635
|
+
]
|
|
1636
|
+
}
|
|
1637
|
+
),
|
|
1638
|
+
isEnhanced && originalDescription !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1639
|
+
"div",
|
|
1640
|
+
{
|
|
1641
|
+
style: {
|
|
1642
|
+
display: "flex",
|
|
1643
|
+
alignItems: "center",
|
|
1644
|
+
gap: "6px",
|
|
1645
|
+
marginTop: "6px",
|
|
1646
|
+
padding: "6px 8px",
|
|
1647
|
+
borderRadius: "6px",
|
|
1648
|
+
background: isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.05)",
|
|
1649
|
+
border: `1px solid ${t.accent}40`
|
|
1650
|
+
},
|
|
1651
|
+
children: [
|
|
1045
1652
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1046
|
-
"
|
|
1653
|
+
"svg",
|
|
1654
|
+
{
|
|
1655
|
+
width: "12",
|
|
1656
|
+
height: "12",
|
|
1657
|
+
viewBox: "0 0 24 24",
|
|
1658
|
+
fill: "none",
|
|
1659
|
+
style: { flexShrink: 0 },
|
|
1660
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1661
|
+
"path",
|
|
1662
|
+
{
|
|
1663
|
+
d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
|
|
1664
|
+
stroke: t.accent,
|
|
1665
|
+
strokeWidth: "1.5",
|
|
1666
|
+
strokeLinejoin: "round"
|
|
1667
|
+
}
|
|
1668
|
+
)
|
|
1669
|
+
}
|
|
1670
|
+
),
|
|
1671
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1672
|
+
"span",
|
|
1047
1673
|
{
|
|
1048
|
-
src: screenshot,
|
|
1049
|
-
alt: "Page screenshot",
|
|
1050
|
-
onClick: () => setPreviewOpen(true),
|
|
1051
1674
|
style: {
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
objectPosition: "top",
|
|
1058
|
-
cursor: "zoom-in",
|
|
1059
|
-
display: "block"
|
|
1060
|
-
}
|
|
1675
|
+
fontSize: "11px",
|
|
1676
|
+
color: t.textMuted,
|
|
1677
|
+
flex: 1
|
|
1678
|
+
},
|
|
1679
|
+
children: "AI enhanced"
|
|
1061
1680
|
}
|
|
1062
1681
|
),
|
|
1063
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1064
|
-
position: "absolute",
|
|
1065
|
-
bottom: "5px",
|
|
1066
|
-
left: "6px",
|
|
1067
|
-
background: "rgba(0,0,0,0.55)",
|
|
1068
|
-
color: "#fff",
|
|
1069
|
-
fontSize: "10px",
|
|
1070
|
-
padding: "1px 5px",
|
|
1071
|
-
borderRadius: "3px",
|
|
1072
|
-
pointerEvents: "none"
|
|
1073
|
-
}, children: "click to preview" })
|
|
1074
|
-
] }),
|
|
1075
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", marginTop: "6px" }, children: [
|
|
1076
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1682
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1077
1683
|
"button",
|
|
1078
1684
|
{
|
|
1079
1685
|
type: "button",
|
|
1080
|
-
onClick: () =>
|
|
1686
|
+
onClick: () => {
|
|
1687
|
+
setIsEnhanced(false);
|
|
1688
|
+
setOriginalDescription(null);
|
|
1689
|
+
},
|
|
1081
1690
|
style: {
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
fontWeight: 500,
|
|
1691
|
+
padding: "2px 8px",
|
|
1692
|
+
borderRadius: "4px",
|
|
1693
|
+
border: `1px solid ${t.accent}`,
|
|
1694
|
+
background: t.accent,
|
|
1695
|
+
color: t.accentText,
|
|
1696
|
+
fontSize: "11px",
|
|
1697
|
+
fontWeight: 600,
|
|
1090
1698
|
cursor: "pointer",
|
|
1091
|
-
fontFamily: "inherit"
|
|
1092
|
-
display: "flex",
|
|
1093
|
-
alignItems: "center",
|
|
1094
|
-
justifyContent: "center",
|
|
1095
|
-
gap: "4px"
|
|
1699
|
+
fontFamily: "inherit"
|
|
1096
1700
|
},
|
|
1097
|
-
children:
|
|
1098
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "11", height: "11", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }),
|
|
1099
|
-
"Remove"
|
|
1100
|
-
]
|
|
1701
|
+
children: "Keep"
|
|
1101
1702
|
}
|
|
1102
1703
|
),
|
|
1103
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
1704
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1104
1705
|
"button",
|
|
1105
1706
|
{
|
|
1106
1707
|
type: "button",
|
|
1107
1708
|
onClick: () => {
|
|
1108
|
-
|
|
1109
|
-
|
|
1709
|
+
setDescription(originalDescription);
|
|
1710
|
+
setIsEnhanced(false);
|
|
1711
|
+
setOriginalDescription(null);
|
|
1110
1712
|
},
|
|
1111
1713
|
style: {
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
borderRadius: "6px",
|
|
1714
|
+
padding: "2px 8px",
|
|
1715
|
+
borderRadius: "4px",
|
|
1115
1716
|
border: `1px solid ${t.inputBorder}`,
|
|
1116
1717
|
background: "transparent",
|
|
1117
1718
|
color: t.textMuted,
|
|
1118
|
-
fontSize: "
|
|
1119
|
-
fontWeight:
|
|
1719
|
+
fontSize: "11px",
|
|
1720
|
+
fontWeight: 600,
|
|
1120
1721
|
cursor: "pointer",
|
|
1121
|
-
fontFamily: "inherit"
|
|
1122
|
-
display: "flex",
|
|
1123
|
-
alignItems: "center",
|
|
1124
|
-
justifyContent: "center",
|
|
1125
|
-
gap: "4px"
|
|
1722
|
+
fontFamily: "inherit"
|
|
1126
1723
|
},
|
|
1127
|
-
children:
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1724
|
+
children: "Restore"
|
|
1725
|
+
}
|
|
1726
|
+
)
|
|
1727
|
+
]
|
|
1728
|
+
}
|
|
1729
|
+
),
|
|
1730
|
+
voiceError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1731
|
+
"p",
|
|
1732
|
+
{
|
|
1733
|
+
style: {
|
|
1734
|
+
color: "#ef4444",
|
|
1735
|
+
fontSize: "11px",
|
|
1736
|
+
marginTop: "4px",
|
|
1737
|
+
marginBottom: 0
|
|
1738
|
+
},
|
|
1739
|
+
children: voiceError
|
|
1740
|
+
}
|
|
1741
|
+
),
|
|
1742
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
|
|
1743
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1744
|
+
"span",
|
|
1745
|
+
{
|
|
1746
|
+
style: {
|
|
1747
|
+
fontSize: "12px",
|
|
1748
|
+
color: t.textMuted,
|
|
1749
|
+
marginBottom: "6px",
|
|
1750
|
+
display: "block",
|
|
1751
|
+
fontWeight: 500
|
|
1752
|
+
},
|
|
1753
|
+
children: "Screenshot"
|
|
1754
|
+
}
|
|
1755
|
+
),
|
|
1756
|
+
screenshot ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
1757
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
|
|
1758
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1759
|
+
"img",
|
|
1760
|
+
{
|
|
1761
|
+
src: screenshot,
|
|
1762
|
+
alt: "Page screenshot",
|
|
1763
|
+
onClick: () => setPreviewOpen(true),
|
|
1764
|
+
style: {
|
|
1765
|
+
width: "100%",
|
|
1766
|
+
borderRadius: "6px",
|
|
1767
|
+
border: `1px solid ${t.border}`,
|
|
1768
|
+
maxHeight: "64px",
|
|
1769
|
+
objectFit: "cover",
|
|
1770
|
+
objectPosition: "top",
|
|
1771
|
+
cursor: "zoom-in",
|
|
1772
|
+
display: "block"
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
),
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1777
|
+
"span",
|
|
1778
|
+
{
|
|
1779
|
+
style: {
|
|
1780
|
+
position: "absolute",
|
|
1781
|
+
bottom: "5px",
|
|
1782
|
+
left: "6px",
|
|
1783
|
+
background: "rgba(0,0,0,0.55)",
|
|
1784
|
+
color: "#fff",
|
|
1785
|
+
fontSize: "10px",
|
|
1786
|
+
padding: "1px 5px",
|
|
1787
|
+
borderRadius: "3px",
|
|
1788
|
+
pointerEvents: "none"
|
|
1789
|
+
},
|
|
1790
|
+
children: "click to preview"
|
|
1131
1791
|
}
|
|
1132
1792
|
)
|
|
1133
|
-
] })
|
|
1793
|
+
] }),
|
|
1794
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1795
|
+
"div",
|
|
1796
|
+
{
|
|
1797
|
+
style: {
|
|
1798
|
+
display: "flex",
|
|
1799
|
+
gap: "6px",
|
|
1800
|
+
marginTop: "6px"
|
|
1801
|
+
},
|
|
1802
|
+
children: [
|
|
1803
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1804
|
+
"button",
|
|
1805
|
+
{
|
|
1806
|
+
type: "button",
|
|
1807
|
+
onClick: () => setScreenshot(null),
|
|
1808
|
+
style: {
|
|
1809
|
+
flex: 1,
|
|
1810
|
+
padding: "6px 0",
|
|
1811
|
+
borderRadius: "6px",
|
|
1812
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1813
|
+
background: "transparent",
|
|
1814
|
+
color: "#ef4444",
|
|
1815
|
+
fontSize: "12px",
|
|
1816
|
+
fontWeight: 500,
|
|
1817
|
+
cursor: "pointer",
|
|
1818
|
+
fontFamily: "inherit",
|
|
1819
|
+
display: "flex",
|
|
1820
|
+
alignItems: "center",
|
|
1821
|
+
justifyContent: "center",
|
|
1822
|
+
gap: "4px"
|
|
1823
|
+
},
|
|
1824
|
+
children: [
|
|
1825
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1826
|
+
"svg",
|
|
1827
|
+
{
|
|
1828
|
+
width: "11",
|
|
1829
|
+
height: "11",
|
|
1830
|
+
viewBox: "0 0 10 10",
|
|
1831
|
+
fill: "none",
|
|
1832
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1833
|
+
"path",
|
|
1834
|
+
{
|
|
1835
|
+
d: "M1 1L9 9M9 1L1 9",
|
|
1836
|
+
stroke: "currentColor",
|
|
1837
|
+
strokeWidth: "1.5",
|
|
1838
|
+
strokeLinecap: "round"
|
|
1839
|
+
}
|
|
1840
|
+
)
|
|
1841
|
+
}
|
|
1842
|
+
),
|
|
1843
|
+
"Remove"
|
|
1844
|
+
]
|
|
1845
|
+
}
|
|
1846
|
+
),
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1848
|
+
"button",
|
|
1849
|
+
{
|
|
1850
|
+
type: "button",
|
|
1851
|
+
onClick: () => {
|
|
1852
|
+
var _a;
|
|
1853
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
1854
|
+
},
|
|
1855
|
+
style: {
|
|
1856
|
+
flex: 1,
|
|
1857
|
+
padding: "6px 0",
|
|
1858
|
+
borderRadius: "6px",
|
|
1859
|
+
border: `1px solid ${t.inputBorder}`,
|
|
1860
|
+
background: "transparent",
|
|
1861
|
+
color: t.textMuted,
|
|
1862
|
+
fontSize: "12px",
|
|
1863
|
+
fontWeight: 500,
|
|
1864
|
+
cursor: "pointer",
|
|
1865
|
+
fontFamily: "inherit",
|
|
1866
|
+
display: "flex",
|
|
1867
|
+
alignItems: "center",
|
|
1868
|
+
justifyContent: "center",
|
|
1869
|
+
gap: "4px"
|
|
1870
|
+
},
|
|
1871
|
+
children: [
|
|
1872
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1873
|
+
"svg",
|
|
1874
|
+
{
|
|
1875
|
+
width: "11",
|
|
1876
|
+
height: "11",
|
|
1877
|
+
viewBox: "0 0 24 24",
|
|
1878
|
+
fill: "none",
|
|
1879
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1880
|
+
"path",
|
|
1881
|
+
{
|
|
1882
|
+
d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12",
|
|
1883
|
+
stroke: "currentColor",
|
|
1884
|
+
strokeWidth: "2",
|
|
1885
|
+
strokeLinecap: "round",
|
|
1886
|
+
strokeLinejoin: "round"
|
|
1887
|
+
}
|
|
1888
|
+
)
|
|
1889
|
+
}
|
|
1890
|
+
),
|
|
1891
|
+
"Replace"
|
|
1892
|
+
]
|
|
1893
|
+
}
|
|
1894
|
+
)
|
|
1895
|
+
]
|
|
1896
|
+
}
|
|
1897
|
+
)
|
|
1134
1898
|
] }) : (
|
|
1135
1899
|
/* Drop zone */
|
|
1136
1900
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -1143,7 +1907,9 @@ function ReportDialog({
|
|
|
1143
1907
|
onDrop: (e) => {
|
|
1144
1908
|
e.preventDefault();
|
|
1145
1909
|
setScreenshotDragOver(false);
|
|
1146
|
-
const file = Array.from(
|
|
1910
|
+
const file = Array.from(
|
|
1911
|
+
e.dataTransfer.files
|
|
1912
|
+
).find((f) => f.type.startsWith("image/"));
|
|
1147
1913
|
if (!file) return;
|
|
1148
1914
|
const reader = new FileReader();
|
|
1149
1915
|
reader.onload = () => setScreenshot(reader.result);
|
|
@@ -1164,20 +1930,95 @@ function ReportDialog({
|
|
|
1164
1930
|
transition: "border-color 0.15s ease, background 0.15s ease"
|
|
1165
1931
|
},
|
|
1166
1932
|
children: [
|
|
1167
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1933
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1934
|
+
"svg",
|
|
1935
|
+
{
|
|
1936
|
+
width: "22",
|
|
1937
|
+
height: "22",
|
|
1938
|
+
viewBox: "0 0 24 24",
|
|
1939
|
+
fill: "none",
|
|
1940
|
+
style: {
|
|
1941
|
+
margin: "0 auto 6px",
|
|
1942
|
+
display: "block",
|
|
1943
|
+
opacity: 0.45
|
|
1944
|
+
},
|
|
1945
|
+
children: [
|
|
1946
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1947
|
+
"rect",
|
|
1948
|
+
{
|
|
1949
|
+
x: "3",
|
|
1950
|
+
y: "3",
|
|
1951
|
+
width: "18",
|
|
1952
|
+
height: "18",
|
|
1953
|
+
rx: "2",
|
|
1954
|
+
stroke: t.textMuted,
|
|
1955
|
+
strokeWidth: "1.5"
|
|
1956
|
+
}
|
|
1957
|
+
),
|
|
1958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1959
|
+
"circle",
|
|
1960
|
+
{
|
|
1961
|
+
cx: "8.5",
|
|
1962
|
+
cy: "8.5",
|
|
1963
|
+
r: "1.5",
|
|
1964
|
+
stroke: t.textMuted,
|
|
1965
|
+
strokeWidth: "1.5"
|
|
1966
|
+
}
|
|
1967
|
+
),
|
|
1968
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1969
|
+
"path",
|
|
1970
|
+
{
|
|
1971
|
+
d: "M21 15l-5-5L5 21",
|
|
1972
|
+
stroke: t.textMuted,
|
|
1973
|
+
strokeWidth: "1.5",
|
|
1974
|
+
strokeLinecap: "round",
|
|
1975
|
+
strokeLinejoin: "round"
|
|
1976
|
+
}
|
|
1977
|
+
)
|
|
1978
|
+
]
|
|
1979
|
+
}
|
|
1980
|
+
),
|
|
1981
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1982
|
+
"p",
|
|
1983
|
+
{
|
|
1984
|
+
style: {
|
|
1985
|
+
margin: 0,
|
|
1986
|
+
fontSize: "12px",
|
|
1987
|
+
fontWeight: 600,
|
|
1988
|
+
color: t.text
|
|
1989
|
+
},
|
|
1990
|
+
children: screenshotDragOver ? "Drop to attach" : "Add a screenshot"
|
|
1991
|
+
}
|
|
1992
|
+
),
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1994
|
+
"p",
|
|
1995
|
+
{
|
|
1996
|
+
style: {
|
|
1997
|
+
margin: "3px 0 0",
|
|
1998
|
+
fontSize: "11px",
|
|
1999
|
+
color: t.textMuted
|
|
2000
|
+
},
|
|
2001
|
+
children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
|
|
2002
|
+
}
|
|
2003
|
+
)
|
|
1174
2004
|
]
|
|
1175
2005
|
}
|
|
1176
2006
|
)
|
|
1177
2007
|
)
|
|
1178
2008
|
] }),
|
|
1179
2009
|
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
|
|
1180
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2010
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2011
|
+
"span",
|
|
2012
|
+
{
|
|
2013
|
+
style: {
|
|
2014
|
+
fontSize: "12px",
|
|
2015
|
+
color: t.textMuted,
|
|
2016
|
+
marginBottom: "6px",
|
|
2017
|
+
display: "block"
|
|
2018
|
+
},
|
|
2019
|
+
children: "Severity"
|
|
2020
|
+
}
|
|
2021
|
+
),
|
|
1181
2022
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1182
2023
|
"button",
|
|
1183
2024
|
{
|
|
@@ -1202,114 +2043,34 @@ function ReportDialog({
|
|
|
1202
2043
|
s
|
|
1203
2044
|
)) })
|
|
1204
2045
|
] }),
|
|
1205
|
-
validationError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1206
|
-
|
|
1207
|
-
"button",
|
|
2046
|
+
validationError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2047
|
+
"p",
|
|
1208
2048
|
{
|
|
1209
|
-
type: "button",
|
|
1210
|
-
onClick: () => {
|
|
1211
|
-
const err = isLowQualityText(description);
|
|
1212
|
-
if (err) {
|
|
1213
|
-
setValidationError(err);
|
|
1214
|
-
return;
|
|
1215
|
-
}
|
|
1216
|
-
setValidationError(null);
|
|
1217
|
-
setStep(3);
|
|
1218
|
-
},
|
|
1219
|
-
disabled: !description.trim(),
|
|
1220
2049
|
style: {
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
borderRadius: "8px",
|
|
1225
|
-
border: "none",
|
|
1226
|
-
backgroundColor: !description.trim() ? t.bgSecondary : t.accent,
|
|
1227
|
-
color: !description.trim() ? t.textMuted : t.accentText,
|
|
1228
|
-
fontSize: "14px",
|
|
1229
|
-
fontWeight: 600,
|
|
1230
|
-
cursor: !description.trim() ? "not-allowed" : "pointer",
|
|
1231
|
-
fontFamily: "inherit",
|
|
1232
|
-
transition: "background-color 0.15s ease"
|
|
2050
|
+
color: "#ef4444",
|
|
2051
|
+
fontSize: "12px",
|
|
2052
|
+
marginTop: "6px"
|
|
1233
2053
|
},
|
|
1234
|
-
children:
|
|
2054
|
+
children: validationError
|
|
1235
2055
|
}
|
|
1236
|
-
)
|
|
1237
|
-
] }),
|
|
1238
|
-
step === 3 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1239
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", marginBottom: "12px" }, children: [
|
|
1240
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: {
|
|
1241
|
-
display: "inline-flex",
|
|
1242
|
-
alignItems: "center",
|
|
1243
|
-
gap: "4px",
|
|
1244
|
-
padding: "4px 10px",
|
|
1245
|
-
borderRadius: "12px",
|
|
1246
|
-
fontSize: "12px",
|
|
1247
|
-
fontWeight: 600,
|
|
1248
|
-
backgroundColor: t.bgSecondary,
|
|
1249
|
-
color: t.text,
|
|
1250
|
-
border: `1px solid ${t.border}`
|
|
1251
|
-
}, children: [
|
|
1252
|
-
getTypeIcon(reportType, t.accent, 12),
|
|
1253
|
-
getTypeLabel(reportType)
|
|
1254
|
-
] }),
|
|
1255
|
-
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: {
|
|
1256
|
-
display: "inline-flex",
|
|
1257
|
-
alignItems: "center",
|
|
1258
|
-
padding: "4px 10px",
|
|
1259
|
-
borderRadius: "12px",
|
|
1260
|
-
fontSize: "12px",
|
|
1261
|
-
fontWeight: 600,
|
|
1262
|
-
backgroundColor: severity === "high" ? "#fef2f2" : severity === "medium" ? "#fffbeb" : "#f0fdf4",
|
|
1263
|
-
color: severity === "high" ? "#dc2626" : severity === "medium" ? "#d97706" : "#16a34a",
|
|
1264
|
-
border: `1px solid ${severity === "high" ? "#fecaca" : severity === "medium" ? "#fde68a" : "#bbf7d0"}`,
|
|
1265
|
-
textTransform: "capitalize"
|
|
1266
|
-
}, children: severity })
|
|
1267
|
-
] }),
|
|
1268
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
1269
|
-
padding: "10px 12px",
|
|
1270
|
-
borderRadius: "8px",
|
|
1271
|
-
border: `1px solid ${t.inputBorder}`,
|
|
1272
|
-
backgroundColor: t.inputBg,
|
|
1273
|
-
fontSize: "13px",
|
|
1274
|
-
color: t.text,
|
|
1275
|
-
marginBottom: "10px",
|
|
1276
|
-
maxHeight: "80px",
|
|
1277
|
-
overflow: "hidden",
|
|
1278
|
-
lineHeight: "1.4"
|
|
1279
|
-
}, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
|
|
1280
|
-
screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: "10px", position: "relative" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1281
|
-
"img",
|
|
1282
|
-
{
|
|
1283
|
-
src: screenshot,
|
|
1284
|
-
alt: "Page screenshot",
|
|
1285
|
-
onClick: () => setPreviewOpen(true),
|
|
1286
|
-
style: {
|
|
1287
|
-
width: "100%",
|
|
1288
|
-
borderRadius: "6px",
|
|
1289
|
-
border: `1px solid ${t.border}`,
|
|
1290
|
-
maxHeight: "80px",
|
|
1291
|
-
objectFit: "cover",
|
|
1292
|
-
objectPosition: "top",
|
|
1293
|
-
cursor: "pointer"
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
) }),
|
|
2056
|
+
),
|
|
1297
2057
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1298
2058
|
"button",
|
|
1299
2059
|
{
|
|
1300
2060
|
type: "button",
|
|
1301
2061
|
onClick: handleSubmit,
|
|
1302
|
-
disabled: isSubmitting,
|
|
2062
|
+
disabled: !description.trim() || isSubmitting,
|
|
1303
2063
|
style: {
|
|
2064
|
+
marginTop: "12px",
|
|
1304
2065
|
width: "100%",
|
|
1305
2066
|
padding: "10px",
|
|
1306
2067
|
borderRadius: "8px",
|
|
1307
2068
|
border: "none",
|
|
1308
|
-
backgroundColor: isSubmitting ? t.bgSecondary : t.accent,
|
|
1309
|
-
color: isSubmitting ? t.textMuted : t.accentText,
|
|
2069
|
+
backgroundColor: !description.trim() || isSubmitting ? t.bgSecondary : t.accent,
|
|
2070
|
+
color: !description.trim() || isSubmitting ? t.textMuted : t.accentText,
|
|
1310
2071
|
fontSize: "14px",
|
|
1311
2072
|
fontWeight: 600,
|
|
1312
|
-
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
2073
|
+
cursor: !description.trim() || isSubmitting ? "not-allowed" : "pointer",
|
|
1313
2074
|
fontFamily: "inherit",
|
|
1314
2075
|
transition: "background-color 0.15s ease"
|
|
1315
2076
|
},
|
|
@@ -1425,10 +2186,11 @@ function getTypeSubtitle(type) {
|
|
|
1425
2186
|
return "General feedback";
|
|
1426
2187
|
}
|
|
1427
2188
|
}
|
|
1428
|
-
function getPlaceholder(type) {
|
|
2189
|
+
function getPlaceholder(type, idx = 0, hasVoice = false) {
|
|
2190
|
+
if (hasVoice && idx === 1) return "Hold Space to speak \u2014 we'll transcribe it";
|
|
1429
2191
|
switch (type) {
|
|
1430
2192
|
case "BUG":
|
|
1431
|
-
return "What went wrong?";
|
|
2193
|
+
return "What went wrong? Describe it or paste an error...";
|
|
1432
2194
|
case "FEATURE_REQUEST":
|
|
1433
2195
|
return "Describe the feature you'd like...";
|
|
1434
2196
|
case "QUESTION":
|
|
@@ -1438,19 +2200,58 @@ function getPlaceholder(type) {
|
|
|
1438
2200
|
}
|
|
1439
2201
|
}
|
|
1440
2202
|
function getTypeIcon(type, color, size = 24) {
|
|
1441
|
-
const props = {
|
|
2203
|
+
const props = {
|
|
2204
|
+
width: size,
|
|
2205
|
+
height: size,
|
|
2206
|
+
viewBox: "0 0 24 24",
|
|
2207
|
+
fill: "none",
|
|
2208
|
+
style: { flexShrink: 0 }
|
|
2209
|
+
};
|
|
1442
2210
|
switch (type) {
|
|
1443
2211
|
case "BUG":
|
|
1444
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2212
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2213
|
+
"path",
|
|
2214
|
+
{
|
|
2215
|
+
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",
|
|
2216
|
+
stroke: color,
|
|
2217
|
+
strokeWidth: "1.5",
|
|
2218
|
+
strokeLinecap: "round"
|
|
2219
|
+
}
|
|
2220
|
+
) });
|
|
1445
2221
|
case "FEATURE_REQUEST":
|
|
1446
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2222
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2223
|
+
"path",
|
|
2224
|
+
{
|
|
2225
|
+
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",
|
|
2226
|
+
stroke: color,
|
|
2227
|
+
strokeWidth: "1.5",
|
|
2228
|
+
strokeLinejoin: "round"
|
|
2229
|
+
}
|
|
2230
|
+
) });
|
|
1447
2231
|
case "QUESTION":
|
|
1448
2232
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
|
|
1449
2233
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
|
|
1450
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2234
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2235
|
+
"path",
|
|
2236
|
+
{
|
|
2237
|
+
d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
|
|
2238
|
+
stroke: color,
|
|
2239
|
+
strokeWidth: "1.5",
|
|
2240
|
+
strokeLinecap: "round",
|
|
2241
|
+
strokeLinejoin: "round"
|
|
2242
|
+
}
|
|
2243
|
+
)
|
|
1451
2244
|
] });
|
|
1452
2245
|
case "OTHER":
|
|
1453
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
2247
|
+
"path",
|
|
2248
|
+
{
|
|
2249
|
+
d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
|
|
2250
|
+
stroke: color,
|
|
2251
|
+
strokeWidth: "1.5",
|
|
2252
|
+
strokeLinejoin: "round"
|
|
2253
|
+
}
|
|
2254
|
+
) });
|
|
1454
2255
|
}
|
|
1455
2256
|
}
|
|
1456
2257
|
|
|
@@ -1672,15 +2473,31 @@ function GlitchgrabProviderInner({
|
|
|
1672
2473
|
[]
|
|
1673
2474
|
);
|
|
1674
2475
|
const enhance = (0, import_react2.useCallback)(
|
|
1675
|
-
async (text) => {
|
|
2476
|
+
async (text, screenshot) => {
|
|
1676
2477
|
try {
|
|
1677
|
-
|
|
2478
|
+
const ctx = captureContext(visitedPagesRef.current);
|
|
2479
|
+
const context = {
|
|
2480
|
+
url: ctx.url,
|
|
2481
|
+
visitedPages: ctx.visitedPages.slice(-5),
|
|
2482
|
+
breadcrumbs: ctx.breadcrumbs.slice(-10).map((b) => ({ type: b.type, message: b.message }))
|
|
2483
|
+
};
|
|
2484
|
+
return await enhanceText(text, token, baseUrl, screenshot, context);
|
|
1678
2485
|
} catch (e) {
|
|
1679
2486
|
return text;
|
|
1680
2487
|
}
|
|
1681
2488
|
},
|
|
1682
2489
|
[token, baseUrl]
|
|
1683
2490
|
);
|
|
2491
|
+
const transcribe = (0, import_react2.useCallback)(
|
|
2492
|
+
async (blob) => {
|
|
2493
|
+
try {
|
|
2494
|
+
return await transcribeAudio(blob, token, baseUrl);
|
|
2495
|
+
} catch (e) {
|
|
2496
|
+
return "";
|
|
2497
|
+
}
|
|
2498
|
+
},
|
|
2499
|
+
[token, baseUrl]
|
|
2500
|
+
);
|
|
1684
2501
|
const openReportDialog = (0, import_react2.useCallback)((options) => {
|
|
1685
2502
|
if (typeof window !== "undefined") {
|
|
1686
2503
|
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
@@ -1725,7 +2542,7 @@ function GlitchgrabProviderInner({
|
|
|
1725
2542
|
children
|
|
1726
2543
|
}
|
|
1727
2544
|
),
|
|
1728
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, enhanceText: enhance, types, showSeverity })
|
|
2545
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity })
|
|
1729
2546
|
]
|
|
1730
2547
|
}
|
|
1731
2548
|
);
|