"use strict"; const api = window.chjPlugin; const i18n = window.chjPluginI18n.createI18n("cs"); const t = i18n.t; const elements = Object.fromEntries(["pluginVersion", "closeButton", "levelFilter", "searchInput", "refreshButton", "autoRefresh", "status", "visibleCount", "readTime", "fileSize", "logList", "recordTemplate"].map((id) => [id, document.querySelector(`#${id}`)])); let records = []; let busy = false; function bytes(value) { const units = ["B", "KB", "MB", "GB"]; let amount = Number(value || 0); let unit = 0; while (amount >= 1024 && unit < units.length - 1) { amount /= 1024; unit += 1; } return `${amount.toLocaleString(i18n.locale(), { maximumFractionDigits: 1 })} ${units[unit]}`; } function parseLines(text) { return String(text || "").split("\n").filter(Boolean).map((line) => { try { const value = JSON.parse(line); return { timestamp: String(value.timestamp || ""), level: String(value.level || "info").toLowerCase(), message: String(value.message || ""), data: value.data ?? {} }; } catch { return { timestamp: "", level: "raw", message: line, data: null }; } }); } function render() { const level = elements.levelFilter.value; const query = elements.searchInput.value.trim().toLocaleLowerCase(i18n.locale()); const visible = records.filter((record) => { if (level !== "all" && record.level !== level) return false; return !query || `${record.message} ${JSON.stringify(record.data)}`.toLocaleLowerCase(i18n.locale()).includes(query); }); const fragment = document.createDocumentFragment(); for (const record of visible) { const node = elements.recordTemplate.content.cloneNode(true); const article = node.querySelector(".record"); article.dataset.level = record.level; node.querySelector(".level").textContent = record.level.toUpperCase(); node.querySelector("time").textContent = record.timestamp ? new Date(record.timestamp).toLocaleString(i18n.locale()) : t("bez času"); node.querySelector(".message").textContent = record.message; const data = node.querySelector(".data"); const hasData = record.data && typeof record.data === "object" && Object.keys(record.data).length; data.hidden = !hasData; data.textContent = hasData ? JSON.stringify(record.data, null, 2) : ""; fragment.append(node); } elements.logList.replaceChildren(fragment); elements.visibleCount.textContent = String(visible.length); if (!visible.length) elements.logList.textContent = records.length ? t("Filtru neodpovídá žádný záznam.") : t("Log zatím neobsahuje žádné záznamy."); } async function refresh() { if (busy) return; busy = true; elements.refreshButton.disabled = true; elements.status.textContent = t("Načítám diagnostický log…"); elements.status.classList.remove("error"); try { const result = await api.logs.read({ maxBytes: 1024 * 1024 }); records = parseLines(result.text); elements.readTime.textContent = t("Načteno {time}", { time: new Date(result.readAt).toLocaleTimeString(i18n.locale()) }); elements.fileSize.textContent = bytes(result.size); elements.status.textContent = result.truncated ? t("Zobrazen je poslední 1 MB logu.") : t("Log byl načten."); render(); } catch (error) { elements.status.textContent = error?.message || String(error); elements.status.classList.add("error"); } finally { busy = false; elements.refreshButton.disabled = false; } } elements.closeButton.addEventListener("click", () => api.close()); elements.refreshButton.addEventListener("click", refresh); elements.levelFilter.addEventListener("change", render); elements.searchInput.addEventListener("input", render); setInterval(() => { if (elements.autoRefresh.checked && !document.hidden) void refresh(); }, 5000); (async () => { try { i18n.setLanguage(await api.ui.getLanguage()); } catch {} i18n.apply(document); api.ui.onLanguageChanged((language) => { i18n.setLanguage(language); i18n.apply(document); void refresh(); }); const info = await api.getInfo(); elements.pluginVersion.textContent = `${info.name} v${info.version} · ${info.publisher}`; await refresh(); })().catch((error) => { elements.status.textContent = error?.message || String(error); elements.status.classList.add("error"); });