import { useState, useEffect, useRef, useSyncExternalStore } from "react"; import { useTranslation } from "react-i18next"; import { ScrollText, Trash2, Copy, Check, MessageSquarePlus } from "lucide-react"; import { getLogs, clearLogs, subscribe, type LogLevel } from "../../services/logService"; import FeedbackDialog from "./FeedbackDialog"; import FeedbackConsentDialog from "./FeedbackConsentDialog"; type Filter = "all" | LogLevel; const FEEDBACK_CONSENT_KEY = "feedbackConsentAccepted"; export default function LogViewerCard() { const { t } = useTranslation(); const [filter, setFilter] = useState("all"); const [copied, setCopied] = useState(false); const [consentOpen, setConsentOpen] = useState(false); const [feedbackOpen, setFeedbackOpen] = useState(false); const listRef = useRef(null); const openFeedback = () => { const accepted = localStorage.getItem(FEEDBACK_CONSENT_KEY) === "true"; if (accepted) { setFeedbackOpen(true); } else { setConsentOpen(true); } }; const acceptConsent = () => { localStorage.setItem(FEEDBACK_CONSENT_KEY, "true"); setConsentOpen(false); setFeedbackOpen(true); }; const logs = useSyncExternalStore(subscribe, getLogs, getLogs); const filtered = filter === "all" ? logs : logs.filter((l) => l.level === filter); useEffect(() => { if (listRef.current) { listRef.current.scrollTop = listRef.current.scrollHeight; } }, [filtered.length]); const handleCopy = async () => { const text = filtered .map((l) => { const time = new Date(l.timestamp).toLocaleTimeString(); return `[${time}] [${l.level.toUpperCase()}] ${l.message}`; }) .join("\n"); await navigator.clipboard.writeText(text); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const levelColor: Record = { info: "text-[var(--muted-foreground)]", warn: "text-amber-500", error: "text-[var(--negative)]", }; const filters: { value: Filter; label: string }[] = [ { value: "all", label: t("settings.logs.filterAll") }, { value: "error", label: "Error" }, { value: "warn", label: "Warn" }, { value: "info", label: "Info" }, ]; return (

{t("settings.logs.title")}

{filters.map((f) => ( ))}
{filtered.length === 0 ? (

{t("settings.logs.empty")}

) : ( filtered.map((entry, i) => (
{new Date(entry.timestamp).toLocaleTimeString()} {entry.level} {entry.message}
)) )}
{consentOpen && ( setConsentOpen(false)} /> )} {feedbackOpen && setFeedbackOpen(false)} />}
); }